diff options
author | Jason Hollingsworth <jhworth.developer@gmail.com> | 2014-02-08 21:08:49 -0600 |
---|---|---|
committer | Jason Hollingsworth <jhworth.developer@gmail.com> | 2014-02-13 22:59:39 -0600 |
commit | 29cfd33d949d21d67f3892473c24d4f0a127dfe6 (patch) | |
tree | e9ed4a10e06f7eba224150a643cb87507fc2ddc7 /app | |
parent | d41e404e09c79394ff1938eee01b56345edc6ed9 (diff) | |
download | gitlab-ce-29cfd33d949d21d67f3892473c24d4f0a127dfe6.tar.gz |
Add email aliases for users
Emails are used to associate commits with users. The emails
are not verified and don't have to be valid email addresses. They
are assigned on a first come, first serve basis.
Notifications are sent when an email is added.
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/profiles/emails_controller.rb | 26 | ||||
-rw-r--r-- | app/helpers/commits_helper.rb | 15 | ||||
-rw-r--r-- | app/mailers/emails/profile.rb | 6 | ||||
-rw-r--r-- | app/models/email.rb | 33 | ||||
-rw-r--r-- | app/models/user.rb | 13 | ||||
-rw-r--r-- | app/observers/email_observer.rb | 5 | ||||
-rw-r--r-- | app/services/git_push_service.rb | 4 | ||||
-rw-r--r-- | app/services/notification_service.rb | 7 | ||||
-rw-r--r-- | app/views/layouts/nav/_profile.html.haml | 4 | ||||
-rw-r--r-- | app/views/notify/new_email_email.html.haml | 10 | ||||
-rw-r--r-- | app/views/notify/new_email_email.text.erb | 7 | ||||
-rw-r--r-- | app/views/profiles/emails/index.html.haml | 29 |
12 files changed, 149 insertions, 10 deletions
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb new file mode 100644 index 00000000000..9996b67a8a4 --- /dev/null +++ b/app/controllers/profiles/emails_controller.rb @@ -0,0 +1,26 @@ +class Profiles::EmailsController < ApplicationController + layout "profile" + + def index + @primary = current_user.email + @emails = current_user.emails + end + + def create + @email = current_user.emails.new(params[:email]) + + flash[:alert] = @email.errors.full_messages.first unless @email.save + + redirect_to profile_emails_url + end + + def destroy + @email = current_user.emails.find(params[:id]) + @email.destroy + + respond_to do |format| + format.html { redirect_to profile_emails_url } + format.js { render nothing: true } + end + end +end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 663369e4584..5e5f3f77a21 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -122,17 +122,18 @@ module CommitsHelper def commit_person_link(commit, options = {}) source_name = commit.send "#{options[:source]}_name".to_sym source_email = commit.send "#{options[:source]}_email".to_sym + + user = User.find_for_commit(source_email, source_name) + person_name = user.nil? ? source_name : user.name + person_email = user.nil? ? source_email : user.email + text = if options[:avatar] - avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") - %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>} + avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") + %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>} else - source_name + person_name end - # Prefer email match over name match - user = User.where(email: source_email).first - user ||= User.where(name: source_name).first - options = { class: "commit-#{options[:source]}-link has_tooltip", data: { :'original-title' => sanitize(source_email) } diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb index bcd44f9476c..c91660a02b5 100644 --- a/app/mailers/emails/profile.rb +++ b/app/mailers/emails/profile.rb @@ -6,6 +6,12 @@ module Emails mail(to: @user.email, subject: subject("Account was created for you")) end + def new_email_email(email_id) + @email = Email.find(email_id) + @user = @email.user + mail(to: @user.email, subject: subject("Email was added to your account")) + end + def new_ssh_key_email(key_id) @key = Key.find(key_id) @user = @key.user diff --git a/app/models/email.rb b/app/models/email.rb new file mode 100644 index 00000000000..22e71e4f107 --- /dev/null +++ b/app/models/email.rb @@ -0,0 +1,33 @@ +# == Schema Information +# +# Table name: emails +# +# id :integer not null, primary key +# user_id :integer not null +# email :string not null +# created_at :datetime not null +class Email < ActiveRecord::Base + attr_accessible :email, :user_id + + # + # Relations + # + belongs_to :user + + # + # Validations + # + validates :user_id, presence: true + validates :email, presence: true, email: { strict_mode: true }, uniqueness: true + validate :unique_email, if: ->(email) { email.email_changed? } + + before_validation :cleanup_email + + def cleanup_email + self.email = self.email.downcase.strip + end + + def unique_email + self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email) + end +end
\ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 10f21d23506..dd59f67ea3d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -78,6 +78,7 @@ class User < ActiveRecord::Base # Profile has_many :keys, dependent: :destroy + has_many :emails, dependent: :destroy # Groups has_many :users_groups, dependent: :destroy @@ -116,6 +117,7 @@ class User < ActiveRecord::Base validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :avatar_type, if: ->(user) { user.avatar_changed? } + validate :unique_email, if: ->(user) { user.email_changed? } validates :avatar, file_size: { maximum: 100.kilobytes.to_i } before_validation :generate_password, on: :create @@ -183,6 +185,13 @@ class User < ActiveRecord::Base where(conditions).first end end + + def find_for_commit(email, name) + # Prefer email match over name match + User.where(email: email).first || + User.joins(:emails).where(emails: { email: email }).first || + User.where(name: name).first + end def filter filter_name case filter_name @@ -250,6 +259,10 @@ class User < ActiveRecord::Base end end + def unique_email + self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email) + end + # Groups user has access to def authorized_groups @authorized_groups ||= begin diff --git a/app/observers/email_observer.rb b/app/observers/email_observer.rb new file mode 100644 index 00000000000..026ad8b1d9a --- /dev/null +++ b/app/observers/email_observer.rb @@ -0,0 +1,5 @@ +class EmailObserver < BaseObserver + def after_create(email) + notification.new_email(email) + end +end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index e54f88e42de..fcc03c3e4b8 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -188,8 +188,6 @@ class GitPushService end def commit_user commit - User.where(email: commit.author_email).first || - User.where(name: commit.author_name).first || - user + User.find_for_commit(commit.author_email, commit.author_name) || user end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 7c02777e914..9d7bb9639ac 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -17,6 +17,13 @@ class NotificationService end end + # Always notify user about email added to profile + def new_email(email) + if email.user + mailer.new_email_email(email.id) + end + end + # When create an issue we should send next emails: # # * issue assignee if their notification level is not Disabled diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index d44cb975ea5..35d0d417502 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -4,6 +4,10 @@ %i.icon-home = nav_link(controller: :accounts) do = link_to "Account", profile_account_path + = nav_link(controller: :emails) do + = link_to profile_emails_path do + Emails + %span.count= current_user.emails.count + 1 - unless current_user.ldap_user? = nav_link(controller: :passwords) do = link_to "Password", edit_profile_password_path diff --git a/app/views/notify/new_email_email.html.haml b/app/views/notify/new_email_email.html.haml new file mode 100644 index 00000000000..4a0448a573c --- /dev/null +++ b/app/views/notify/new_email_email.html.haml @@ -0,0 +1,10 @@ +%p + Hi #{@user.name}! +%p + A new email was added to your account: +%p + email: + %code= @email.email +%p + If this email was added in error, you can remove it here: + = link_to "Emails", profile_emails_url diff --git a/app/views/notify/new_email_email.text.erb b/app/views/notify/new_email_email.text.erb new file mode 100644 index 00000000000..51cba99ad0d --- /dev/null +++ b/app/views/notify/new_email_email.text.erb @@ -0,0 +1,7 @@ +Hi <%= @user.name %>! + +A new email was added to your account: + +email.................. <%= @email.email %> + +If this email was added in error, you can remove it here: <%= profile_emails_url %> diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml new file mode 100644 index 00000000000..dc45ab2de79 --- /dev/null +++ b/app/views/profiles/emails/index.html.haml @@ -0,0 +1,29 @@ +%h3.page-title + My Email Addresses +%p.light + Your + %b Primary Email + will be used for account notifications, avatar detection and web based operations, such as edits and merges. All email addresses will be used to identify your commits. + +.ui-box + .title + Emails (#{@emails.count + 1}) + %ul.well-list#emails-table + %li + %strong= @primary + %span.label.label-success Primary Email + - @emails.each do |email| + %li + %strong= email.email + %span.cgray + added #{time_ago_with_tooltip(email.created_at)} + = link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-small btn-remove pull-right' + +%h3.page-title Add Email Address += form_for 'email', url: profile_emails_path, html: { class: 'form-horizontal' } do |f| + .form-group + = f.label :email, class: 'control-label' + .col-sm-10 + = f.text_field :email, class: 'form-control' + .form-actions + = f.submit 'Add', class: 'btn btn-create'
\ No newline at end of file |