Commit 54d32f56 authored by Sytse Sijbrandij's avatar Sytse Sijbrandij

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq

parents 3a3471cc 69e8b0e9
......@@ -18,8 +18,9 @@ v 7.6.0
-
-
- In the docker directory is a container template based on the Omnibus packages.
- Update Sidekiq to version 2.17.8
-
-
- Atom feed for user activity
v 7.5.2
- Don't log Sidekiq arguments by default
......
......@@ -112,7 +112,7 @@ gem "acts-as-taggable-on"
# Background jobs
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq', '2.17.0'
gem 'sidekiq', '2.17.8'
# HTTP requests
gem "httparty"
......
......@@ -78,7 +78,7 @@ GEM
coffee-script-source (1.6.3)
colored (1.2)
colorize (0.5.8)
connection_pool (1.2.0)
connection_pool (2.1.0)
coveralls (0.7.0)
multi_json (~> 1.3)
rest-client
......@@ -402,7 +402,7 @@ GEM
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.1.2)
redis (3.0.6)
redis (3.1.0)
redis-actionpack (4.0.0)
actionpack (~> 4)
redis-rack (~> 1.5.0)
......@@ -410,8 +410,8 @@ GEM
redis-activesupport (4.0.0)
activesupport (~> 4)
redis-store (~> 1.1.0)
redis-namespace (1.4.1)
redis (~> 3.0.4)
redis-namespace (1.5.1)
redis (~> 3.0, >= 3.0.4)
redis-rack (1.5.0)
rack (~> 1.5)
redis-store (~> 1.1.0)
......@@ -470,12 +470,12 @@ GEM
sexp_processor (4.4.0)
shoulda-matchers (2.1.0)
activesupport (>= 3.0.0)
sidekiq (2.17.0)
celluloid (>= 0.15.2)
connection_pool (>= 1.0.0)
sidekiq (2.17.8)
celluloid (= 0.15.2)
connection_pool (~> 2.0)
json
redis (>= 3.0.4)
redis-namespace (>= 1.3.1)
redis (~> 3.1)
redis-namespace (~> 1.3)
simple_oauth (0.1.9)
simplecov (0.9.0)
docile (~> 1.1.0)
......@@ -684,7 +684,7 @@ DEPENDENCIES
semantic-ui-sass (~> 0.16.1.0)
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.0)
sidekiq (= 2.17.8)
simplecov
sinatra
six
......
......@@ -42,10 +42,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def handle_omniauth
if current_user
# Change a logged-in user's authentication method:
current_user.extern_uid = oauth['uid']
current_user.provider = oauth['provider']
current_user.save
# Add new authentication method
current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider'])
redirect_to profile_path
else
@user = Gitlab::OAuth::User.new(oauth)
......@@ -67,8 +65,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
end
end
rescue StandardError
flash[:notice] = "There's no such user!"
rescue ForbiddenAction => e
flash[:notice] = e.message
redirect_to new_user_session_path
end
......
......@@ -26,6 +26,7 @@ class Projects::HooksController < Projects::ApplicationController
def test
if !@project.empty_repo?
status = TestHookService.new.execute(hook, current_user)
if status
flash[:notice] = 'Hook successfully executed.'
else
......
......@@ -20,9 +20,14 @@ class UsersController < ApplicationController
# Get user activity feed for projects common for both users
@events = @user.recent_events.
where(project_id: authorized_projects_ids).limit(20)
where(project_id: authorized_projects_ids).limit(30)
@title = @user.name
respond_to do |format|
format.html
format.atom { render layout: false }
end
end
def determine_layout
......
......@@ -145,4 +145,26 @@ module EventsHelper
rescue
"--broken encoding"
end
def event_to_atom(xml, event)
if event.proper?
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
event_summary = event_feed_summary(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link href: event_link
xml.title truncate(event_title, length: 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? }
end
end
end
end
......@@ -113,4 +113,19 @@ module IssuesHelper
'issue-box-open'
end
end
def issue_to_atom(xml, issue)
xml.entry do
xml.id project_issue_url(issue.project, issue)
xml.link href: project_issue_url(issue.project, issue)
xml.title truncate(issue.title, length: 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end
end
......@@ -16,4 +16,8 @@ module OauthHelper
[:twitter, :github, :google_oauth2].include?(name.to_sym)
end
end
def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
end
end
module ProfileHelper
def oauth_active_class(provider)
if current_user.provider == provider.to_s
if current_user.identities.exists?(provider: provider.to_s)
'active'
end
end
......@@ -10,10 +10,10 @@ module ProfileHelper
end
def show_profile_social_tab?
enabled_social_providers.any? && !current_user.ldap_user?
enabled_social_providers.any?
end
def show_profile_remove_tab?
gitlab_config.signup_enabled && !current_user.ldap_user?
gitlab_config.signup_enabled
end
end
......@@ -26,6 +26,14 @@ class Notify < ActionMailer::Base
delay_for(2.seconds)
end
def test_email(recepient_email, subject, body)
mail(to: recepient_email,
subject: subject,
body: body.html_safe,
content_type: 'text/html'
)
end
private
# The default email address to send emails from
......
......@@ -32,7 +32,10 @@ class WebHook < ActiveRecord::Base
def execute(data)
parsed_url = URI.parse(url)
if parsed_url.userinfo.blank?
WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }, verify: false)
WebHook.post(url,
body: data.to_json,
headers: { "Content-Type" => "application/json" },
verify: false)
else
post_url = url.gsub("#{parsed_url.userinfo}@", "")
auth = {
......@@ -45,6 +48,9 @@ class WebHook < ActiveRecord::Base
verify: false,
basic_auth: auth)
end
rescue SocketError, Errno::ECONNREFUSED => e
logger.error("WebHook Error => #{e}")
false
end
def async_execute(data)
......
class Identity < ActiveRecord::Base
belongs_to :user
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
end
\ No newline at end of file
......@@ -79,6 +79,7 @@ class User < ActiveRecord::Base
# Profile
has_many :keys, dependent: :destroy
has_many :emails, dependent: :destroy
has_many :identities, dependent: :destroy
# Groups
has_many :members, dependent: :destroy
......@@ -113,7 +114,6 @@ class User < ActiveRecord::Base
validates :name, presence: true
validates :email, presence: true, email: {strict_mode: true}, uniqueness: true
validates :bio, length: { maximum: 255 }, allow_blank: true
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
validates :username, presence: true, uniqueness: { case_sensitive: false },
exclusion: { in: Gitlab::Blacklist.path },
......@@ -178,7 +178,6 @@ class User < ActiveRecord::Base
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
scope :ldap, -> { where('provider LIKE ?', 'ldap%') }
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
#
......@@ -407,7 +406,11 @@ class User < ActiveRecord::Base
end
def ldap_user?
extern_uid && provider.start_with?('ldap')
identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"])
end
def ldap_identity
@ldap_identity ||= identities.find_by(["provider LIKE ?", "ldap%"])
end
def accessible_deploy_keys
......
......@@ -107,7 +107,7 @@ class NotificationService
# Notify new user with email after creation
def new_user(user, token = nil)
# Don't email omniauth created users
mailer.new_user_email(user.id, token) unless user.extern_uid?
mailer.new_user_email(user.id, token) unless user.identities.any?
end
# Notify users on new note in system
......
......@@ -2,8 +2,5 @@ class TestHookService
def execute(hook, current_user)
data = GitPushService.new.sample_data(hook.project, current_user)
hook.execute(data)
true
rescue SocketError
false
end
end
......@@ -95,7 +95,7 @@
%li
%span.light LDAP uid:
%strong
= @user.extern_uid
= @user.ldap_identity.extern_uid
- if @user.created_by
%li
......
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "#{current_user.name} issues"
xml.link :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
xml.link :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
xml.id issues_dashboard_url(:private_token => current_user.private_token)
xml.link href: issues_dashboard_url(:atom, private_token: current_user.private_token), rel: "self", type: "application/atom+xml"
xml.link href: issues_dashboard_url(private_token: current_user.private_token), rel: "alternate", type: "text/html"
xml.id issues_dashboard_url(private_token: current_user.private_token)
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue|
xml.entry do
xml.id project_issue_url(issue.project, issue)
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
issue_to_atom(xml, issue)
end
end
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}"
xml.link :href => dashboard_url(:atom), :rel => "self", :type => "application/atom+xml"
xml.link :href => dashboard_url, :rel => "alternate", :type => "text/html"
xml.link href: dashboard_url(:atom), rel: "self", type: "application/atom+xml"
xml.link href: dashboard_url, rel: "alternate", type: "text/html"
xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
if event.proper?
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
event_summary = event_feed_summary(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary(:type => "xhtml") { |x| x << event_summary unless event_summary.nil? }
end
end
event_to_atom(xml, event)
end
end
- providers = (enabled_oauth_providers - [:ldap])
- providers = additional_providers
- if providers.present?
.bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp;
......
......@@ -7,18 +7,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue|
xml.entry do
xml.id project_issue_url(issue.project, issue)
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
issue_to_atom(xml, issue)
end
end
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Group feed - #{@group.name}"
xml.link :href => group_path(@group, :atom), :rel => "self", :type => "application/atom+xml"
xml.link :href => group_path(@group), :rel => "alternate", :type => "text/html"
xml.link href: group_path(@group, :atom), rel: "self", type: "application/atom+xml"
xml.link href: group_path(@group), rel: "alternate", type: "text/html"
xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
if event.proper?
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary event_title
end
end
event_to_atom(xml, event)
end
end
......@@ -7,17 +7,6 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
@issues.each do |issue|
xml.entry do
xml.id project_issue_url(@project, issue)
xml.link :href => project_issue_url(@project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
issue_to_atom(xml, issue)
end
end
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.title "Activity feed for #{@user.name}"
xml.link href: user_url(@user, :atom), rel: "self", type: "application/atom+xml"
xml.link href: user_url(@user), rel: "alternate", type: "text/html"
xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
end
end
......@@ -18,7 +18,15 @@
%h4 Groups:
= render 'groups', groups: @groups
%hr
%h4 User Activity:
%h4
User Activity:
- if current_user
%span.rss-icon.pull-right
= link_to user_path(@user, :atom, { private_token: current_user.private_token }) do
%strong
%i.fa.fa-rss
= render @events
.col-md-4
= render 'profile', user: @user
......
......@@ -137,7 +137,8 @@ Gitlab::Application.routes.draw do
end
end
match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }, via: :get
match "/u/:username" => "users#show", as: :user,
constraints: {username: /(?:[^.]|\.(?!atom$))+/, format: /atom/}, via: :get
#
# Dashboard Area
......
class AddIdentityTable < ActiveRecord::Migration
def up
create_table :identities do |t|
t.string :extern_uid
t.string :provider
t.references :user
end
add_index :identities, :user_id
User.where("provider IS NOT NULL").find_each do |user|
execute "INSERT INTO identities(provider, extern_uid, user_id) VALUES('#{user.provider}', '#{user.extern_uid}', '#{user.id}')"
end
remove_column :users, :extern_uid
remove_column :users, :provider
end
def down
add_column :users, :extern_uid, :string
add_column :users, :provider, :string
User.where("id IN(SELECT user_id FROM identities)").find_each do |user|
identity = user.identities.last
user.extern_uid = identity.extern_uid
user.provider = identity.provider
user.save
end
drop_table :identities
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141121133009) do
ActiveRecord::Schema.define(version: 20141121161704) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -74,6 +74,14 @@ ActiveRecord::Schema.define(version: 20141121133009) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "identities", force: true do |t|
t.string "extern_uid"
t.string "provider"
t.integer "user_id"
end
add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
create_table "issues", force: true do |t|
t.string "title"
t.integer "assignee_id"
......@@ -350,8 +358,6 @@ ActiveRecord::Schema.define(version: 20141121133009) do
t.string "bio"
t.integer "failed_attempts", default: 0
t.datetime "locked_at"
t.string "extern_uid"
t.string "provider"
t.string "username"
t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false
......@@ -360,6 +366,7 @@ ActiveRecord::Schema.define(version: 20141121133009) do
t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at"
t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar"
t.string "confirmation_token"
t.datetime "confirmed_at"
......@@ -367,7 +374,6 @@ ActiveRecord::Schema.define(version: 20141121133009) do
t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......@@ -375,7 +381,6 @@ ActiveRecord::Schema.define(version: 20141121133009) do
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree
......
# Rake tasks for developers
## Setup db with developer seeds:
## Setup db with developer seeds
Note that if your db user does not have advanced privileges you must create the db manually before running this command.
......@@ -8,6 +8,10 @@ Note that if your db user does not have advanced privileges you must create the
bundle exec rake setup
```
The `setup` task is a alias for `gitlab:setup`.
This tasks calls `db:setup` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and fianlly it calls `db:seed_fu` to seed the database.
Note: `db:setup` calls `db:seed` but this does nothing.
## Run tests
This runs all test suites present in GitLab.
......
......@@ -50,12 +50,12 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab
### Memory
- 512MB is the absolute minimum but we do not recommend this amount of memory.
You will need to configure minimum 1.5GB of swap space.
With 1.5GB of swap space you must configure only one unicorn worker.
With one unicorn worker only git over ssh access will work because the git over HTTP access requires two running workers (one worker to receive the user request and one worker for the authorization check).
If you use SSD storage and configure 1.5GB of swap space you can use two Unicorn workers, this will allow HTTP access but it will still be slow.
Consider installing GitLab on Ubuntu as installation on CentOS could be unsuccessful with this amount of memory.
- 512MB is the absolute minimum but we strongly **advise against** this amount of memory.
You will need to configure a minimum of 1.5GB of swap space to make the Omnibus package reconfigure run succeed.
If you use a magnetic (non-SSD) swap drive we recommend to configure only one Unicorn worker.
With one Unicorn worker only git over ssh access will work because the git over HTTP access requires two running workers (one worker to receive the user request and one worker for the authorization check).
If you use a SSD drive you can use two Unicorn workers, this will allow HTTP access although it will be slow.
Consider installing GitLab on Ubuntu instead of CentOS because sometimes CentOS gives errors during installation and usage with this amount of memory.
- 1GB RAM + 1GB swap supports up to 100 users
- **2GB RAM** is the **recommended** memory size and supports up to 500 users
- 4GB RAM supports up to 2,000 users
......
......@@ -9,3 +9,20 @@ If correctly setup, emails that require an action will be marked in Gmail.
To get this functioning, you need to be registered with Google.
[See how to register with google in this document.](https://developers.google.com/gmail/markup/registering-with-google)
To aid the registering with google, GitLab offers a rake task that will send an email to google whitelisting email address from your GitLab server.
To check what would be sent to the google email address, run the rake task:
```bash
bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production
```
**This will not send the email but give you the output of how the mail will look.**
Copy the output of the rake task to [google email markup tester](https://www.google.com/webmasters/markup-tester/u/0/) and press "Validate".
If you receive "No errors detected" message from the tester you can send the email using:
```bash
bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production SEND=true
``
......@@ -170,7 +170,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end
step "I am not an ldap user" do
current_user.update_attributes(extern_uid: nil, provider: '')
current_user.identities.delete
current_user.ldap_user?.should be_false
end
......
......@@ -14,10 +14,14 @@ module API
expose :bio, :skype, :linkedin, :twitter, :website_url
end
class Identity < Grape::Entity
expose :provider, :extern_uid
end
class UserFull < User
expose :email
expose :theme_id, :color_scheme_id, :extern_uid, :provider, \
:projects_limit
expose :theme_id, :color_scheme_id, :projects_limit
expose :identities, using: Entities::Identity
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
end
......
......@@ -59,10 +59,16 @@ module API
post do
authenticated_as_admin!
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :can_create_group, :admin]
user = User.build_user(attrs)
admin = attrs.delete(:admin)
user.admin = admin unless admin.nil?
identity_attrs = attributes_for_keys [:provider, :extern_uid]
if identity_attrs.any?
user.identities.build(identity_attrs)
end
if user.save
present user, with: Entities::UserFull
else
......@@ -89,8 +95,6 @@ module API
# twitter - Twitter account
# website_url - Website url
# projects_limit - Limit projects each user can create
# extern_uid - External authentication provider UID
# provider - External provider
# bio - Bio
# admin - User is admin - true or false (default)
# can_create_group - User can create groups - true or false
......@@ -99,7 +103,7 @@ module API
put ":id" do
authenticated_as_admin!
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :can_create_group, :admin]
user = User.find(params[:id])
not_found!('User') unless user
......
......@@ -8,7 +8,7 @@ module Gitlab
attr_reader :adapter, :provider, :user
def self.open(user, &block)
Gitlab::LDAP::Adapter.open(user.provider) do |adapter|
Gitlab::LDAP::Adapter.open(user.ldap_identity.provider) do |adapter|
block.call(self.new(user, adapter))
end
end
......@@ -28,13 +28,13 @@ module Gitlab
def initialize(user, adapter=nil)
@adapter = adapter
@user = user
@provider = user.provider
@provider = user.ldap_identity.provider
end
def allowed?
if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
if Gitlab::LDAP::Person.find_by_dn(user.ldap_identity.extern_uid, adapter)
return true unless ldap_config.active_directory
!Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
!Gitlab::LDAP::Person.disabled_via_active_directory?(user.ldap_identity.extern_uid, adapter)
else
false
end
......
......@@ -12,9 +12,10 @@ module Gitlab
class << self
def find_by_uid_and_provider(uid, provider)
# LDAP distinguished name is case-insensitive
::User.
identity = ::Identity.
where(provider: [provider, :ldap]).
where('lower(extern_uid) = ?', uid.downcase).last
identity && identity.user
end
end
......@@ -34,15 +35,13 @@ module Gitlab
end
def find_by_email
model.find_by(email: auth_hash.email)
::User.find_by(email: auth_hash.email)
end
def update_user_attributes
gl_user.attributes = {
extern_uid: auth_hash.uid,
provider: auth_hash.provider,
email: auth_hash.email
}
gl_user.email = auth_hash.email
gl_user.identities.build(provider: auth_hash.provider, extern_uid: auth_hash.uid)
gl_user
end
def changed?
......
......@@ -5,6 +5,8 @@
#
module Gitlab
module OAuth
class ForbiddenAction < StandardError; end
class User
attr_accessor :auth_hash, :gl_user
......@@ -70,24 +72,24 @@ module Gitlab
end
def find_by_uid_and_provider
model.where(provider: auth_hash.provider, extern_uid: auth_hash.uid).last
identity = Identity.find_by(provider: auth_hash.provider, extern_uid: auth_hash.uid)
identity && identity.user
end
def build_new_user
model.new(user_attributes).tap do |user|
user.skip_confirmation!
end
user = ::User.new(user_attributes)
user.skip_confirmation!
user.identities.new(extern_uid: auth_hash.uid, provider: auth_hash.provider)
user
end
def user_attributes
{
extern_uid: auth_hash.uid,
provider: auth_hash.provider,
name: auth_hash.name,
username: auth_hash.username,
email: auth_hash.email,
password: auth_hash.password,
password_confirmation: auth_hash.password,
password_confirmation: auth_hash.password
}
end
......@@ -95,12 +97,8 @@ module Gitlab
Gitlab::AppLogger
end
def model
::User
end
def raise_unauthorized_to_create
raise StandardError.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
def unauthorized_to_create
raise ForbiddenAction.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
end
end
end
......
require "#{Rails.root}/app/helpers/emails_helper"
require 'action_view/helpers'
extend ActionView::Helpers
include ActionView::Context
include EmailsHelper
namespace :gitlab do
desc "Email google whitelisting email with example email for actions in inbox"
task mail_google_schema_whitelisting: :environment do
subject = "Rails | Implemented feature"
url = "#{Gitlab.config.gitlab.url}/base/rails-project/issues/#{rand(1..100)}#note_#{rand(10..1000)}"
schema = email_action(url)
body = email_template(schema, url)
mail = Notify.test_email("schema.whitelisting+sample@gmail.com", subject, body.html_safe)
if send_now
mail.deliver
else
puts "WOULD SEND:"
end
puts mail
end
def email_template(schema, url)
"<html lang='en'>
<head>
<meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
<title>
GitLab
</title>
</meta>
</head>
<style>
img {
max-width: 100%;
height: auto;
}
p.details {
font-style:italic;
color:#777
}
.footer p {
font-size:small;
color:#777
}
</style>
<body>
<div class='content'>
<div>
<p>I like it :+1: </p>
</div>
</div>
<div class='footer' style='margin-top: 10px;'>
<p>
<br>
You're receiving this notification because you are a member of the Base / Rails Project project team.
<a href=\"#{url}\">View it on GitLab</a>
#{schema}
</p>
</div>
</body>
</html>"
end
def send_now
if ENV['SEND'] == "true"
true
else
false
end
end
end
......@@ -18,15 +18,24 @@ FactoryGirl.define do
password "12345678"
password_confirmation { password }
confirmed_at { Time.now }
confirmation_token { nil }
confirmation_token { nil }
trait :admin do
admin true
end
trait :ldap do
provider 'ldapmain'
extern_uid 'my-ldap-id'
factory :omniauth_user do
ignore do
extern_uid '123456'
provider 'ldapmain'
end
after(:create) do |user, evaluator|
user.identities << create(:identity,
provider: evaluator.provider,
extern_uid: evaluator.extern_uid
)
end
end
factory :admin, traits: [:admin]
......@@ -182,4 +191,9 @@ FactoryGirl.define do
deploy_key
project
end
factory :identity do
provider 'ldapmain'
extern_uid 'my-ldap-id'
end
end
require 'spec_helper'
describe "User Feed", feature: true do
describe "GET /" do
let!(:user) { create(:user) }
context "user atom feed via private token" do
it "should render user atom feed" do
visit user_path(user, :atom, private_token: user.private_token)
body.should have_selector("feed title")
end
end
context 'feed content' do
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project, author: user, description: '') }
let(:note) { create(:note, noteable: issue, author: user, note: 'Bug confirmed', project: project) }
before do
project.team << [user, :master]
issue_event(issue, user)
note_event(note, user)
visit user_path(user, :atom, private_token: user.private_token)
end
it "should have issue opened event" do
body.should have_content("#{user.name} opened issue ##{issue.iid}")
end
it "should have issue comment event" do
body.should have_content("#{user.name} commented on issue ##{issue.iid}")
end
end
end
def issue_event(issue, user)
EventCreateService.new.open_issue(issue, user)
end
def note_event(note, user)
EventCreateService.new.leave_note(note, user)
end
end
require "spec_helper"
describe OauthHelper do
describe "additional_providers" do
it 'returns all enabled providers' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github] }
helper.additional_providers.should include(*[:twitter, :github])
end
it 'does not return ldap provider' do
allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] }
helper.additional_providers.should include(:twitter)
end
it 'returns empty array' do
allow(helper).to receive(:enabled_oauth_providers) { [] }
helper.additional_providers.should == []
end
end
end
\ No newline at end of file
......@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::LDAP::Access do
let(:access) { Gitlab::LDAP::Access.new user }
let(:user) { create(:user, :ldap) }
let(:user) { create(:omniauth_user) }
describe :allowed? do
subject { access.allowed? }
......
......@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::LDAP::Authentication do
let(:klass) { Gitlab::LDAP::Authentication }
let(:user) { create(:user, :ldap, extern_uid: dn) }
let(:user) { create(:omniauth_user, extern_uid: dn) }
let(:dn) { 'uid=john,ou=people,dc=example,dc=com' }
let(:login) { 'john' }
let(:password) { 'password' }
......
......@@ -15,18 +15,18 @@ describe Gitlab::LDAP::User do
describe :find_or_create do
it "finds the user if already existing" do
existing_user = create(:user, extern_uid: 'my-uid', provider: 'ldapmain')
existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
expect{ gl_user.save }.to_not change{ User.count }
end
it "connects to existing non-ldap user if the email matches" do
existing_user = create(:user, email: 'john@example.com')
existing_user = create(:omniauth_user, email: 'john@example.com', provider: "twitter")
expect{ gl_user.save }.to_not change{ User.count }
existing_user.reload
expect(existing_user.extern_uid).to eql 'my-uid'
expect(existing_user.provider).to eql 'ldapmain'
expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
end
it "creates a new user if not found" do
......
......@@ -15,7 +15,7 @@ describe Gitlab::OAuth::User do
end
describe :persisted? do
let!(:existing_user) { create(:user, extern_uid: 'my-uid', provider: 'my-provider') }
let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
it "finds an existing user based on uid and provider (facebook)" do
auth = double(info: double(name: 'John'), uid: 'my-uid', provider: 'my-provider')
......@@ -39,8 +39,9 @@ describe Gitlab::OAuth::User do
oauth_user.save
expect(gl_user).to be_valid
expect(gl_user.extern_uid).to eql uid
expect(gl_user.provider).to eql 'twitter'
identity = gl_user.identities.first
expect(identity.extern_uid).to eql uid
expect(identity.provider).to eql 'twitter'
end
end
......
......@@ -62,6 +62,7 @@ describe User do
it { should have_many(:assigned_issues).dependent(:destroy) }
it { should have_many(:merge_requests).dependent(:destroy) }
it { should have_many(:assigned_merge_requests).dependent(:destroy) }
it { should have_many(:identities).dependent(:destroy) }
end
describe "Mass assignment" do
......@@ -361,24 +362,29 @@ describe User do
end
describe :ldap_user? do
let(:user) { build(:user, :ldap) }
it "is true if provider name starts with ldap" do
user.provider = 'ldapmain'
user = create(:omniauth_user, provider: 'ldapmain')
expect( user.ldap_user? ).to be_true
end
it "is false for other providers" do
user.provider = 'other-provider'
user = create(:omniauth_user, provider: 'other-provider')
expect( user.ldap_user? ).to be_false
end
it "is false if no extern_uid is provided" do
user.extern_uid = nil
user = create(:omniauth_user, extern_uid: nil)
expect( user.ldap_user? ).to be_false
end
end
describe :ldap_identity do
it "returns ldap identity" do
user = create :omniauth_user
user.ldap_identity.provider.should_not be_empty
end
end
describe '#full_website_url' do
let(:user) { create(:user) }
......
......@@ -33,7 +33,7 @@ describe API::API, api: true do
response.status.should == 200
json_response.should be_an Array
json_response.first.keys.should include 'email'
json_response.first.keys.should include 'extern_uid'
json_response.first.keys.should include 'identities'
json_response.first.keys.should include 'can_create_project'
end
end
......
require 'spec_helper'
require 'rake'
describe 'gitlab:mail_google_schema_whitelisting rake task' do
before :all do
Rake.application.rake_require "tasks/gitlab/task_helpers"
Rake.application.rake_require "tasks/gitlab/mail_google_schema_whitelisting"
# empty task as env is already loaded
Rake::Task.define_task :environment
end
describe 'call' do
before do
# avoid writing task output to spec progress
$stdout.stub :write
end
let :run_rake_task do
Rake::Task["gitlab:mail_google_schema_whitelisting"].reenable
Rake.application.invoke_task "gitlab:mail_google_schema_whitelisting"
end
it 'should run the task without errors' do
expect { run_rake_task }.to_not raise_error
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment