Commit 9d514213 authored by Douwe Maan's avatar Douwe Maan Committed by tiagonbotelho

Use separate email-friendly token for incoming email and let incoming

email token be reset
parent 09f4af04
...@@ -26,7 +26,15 @@ class ProfilesController < Profiles::ApplicationController ...@@ -26,7 +26,15 @@ class ProfilesController < Profiles::ApplicationController
def reset_private_token def reset_private_token
if current_user.reset_authentication_token! if current_user.reset_authentication_token!
flash[:notice] = "Token was successfully updated" flash[:notice] = "Private token was successfully updated"
end
redirect_to profile_account_path
end
def reset_incoming_email_token
if current_user.reset_incoming_email_token!
flash[:notice] = "Incoming email token was successfully updated"
end end
redirect_to profile_account_path redirect_to profile_account_path
......
...@@ -4,17 +4,21 @@ module TokenAuthenticatable ...@@ -4,17 +4,21 @@ module TokenAuthenticatable
private private
def write_new_token(token_field) def write_new_token(token_field)
new_token = generate_token(token_field) new_token = generate_available_token(token_field)
write_attribute(token_field, new_token) write_attribute(token_field, new_token)
end end
def generate_token(token_field) def generate_available_token(token_field)
loop do loop do
token = Devise.friendly_token token = generate_token(token_field)
break token unless self.class.unscoped.find_by(token_field => token) break token unless self.class.unscoped.find_by(token_field => token)
end end
end end
def generate_token(token_field)
Devise.friendly_token
end
class_methods do class_methods do
def authentication_token_fields def authentication_token_fields
@token_fields || [] @token_fields || []
......
...@@ -624,13 +624,12 @@ class Project < ActiveRecord::Base ...@@ -624,13 +624,12 @@ class Project < ActiveRecord::Base
end end
def new_issue_address(author) def new_issue_address(author)
# This feature is disabled for the time being. return unless Gitlab::IncomingEmail.enabled? && author
return nil
if Gitlab::IncomingEmail.enabled? && author # rubocop:disable Lint/UnreachableCode author.ensure_incoming_email_token!
Gitlab::IncomingEmail.reply_address(
"#{path_with_namespace}+#{author.authentication_token}") Gitlab::IncomingEmail.reply_address(
end "#{path_with_namespace}+#{author.incoming_email_token}")
end end
def build_commit_note(commit) def build_commit_note(commit)
......
...@@ -13,6 +13,7 @@ class User < ActiveRecord::Base ...@@ -13,6 +13,7 @@ class User < ActiveRecord::Base
DEFAULT_NOTIFICATION_LEVEL = :participating DEFAULT_NOTIFICATION_LEVEL = :participating
add_authentication_token_field :authentication_token add_authentication_token_field :authentication_token
add_authentication_token_field :incoming_email_token
default_value_for :admin, false default_value_for :admin, false
default_value_for(:external) { current_application_settings.user_default_external } default_value_for(:external) { current_application_settings.user_default_external }
...@@ -119,7 +120,7 @@ class User < ActiveRecord::Base ...@@ -119,7 +120,7 @@ class User < ActiveRecord::Base
before_validation :set_public_email, if: ->(user) { user.public_email_changed? } before_validation :set_public_email, if: ->(user) { user.public_email_changed? }
after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? } after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? }
before_save :ensure_authentication_token before_save :ensure_authentication_token, :ensure_incoming_email_token
before_save :ensure_external_user_rights before_save :ensure_external_user_rights
after_save :ensure_namespace_correct after_save :ensure_namespace_correct
after_initialize :set_projects_limit after_initialize :set_projects_limit
...@@ -946,4 +947,13 @@ class User < ActiveRecord::Base ...@@ -946,4 +947,13 @@ class User < ActiveRecord::Base
signup_domain =~ regexp signup_domain =~ regexp
end end
end end
def generate_token(token_field)
if token_field == :incoming_email_token
# Needs to be all lowercase and alphanumeric because it's gonna be used in an email address.
SecureRandom.hex
else
super
end
end
end end
...@@ -8,24 +8,29 @@ ...@@ -8,24 +8,29 @@
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0 %h4.prepend-top-0
Private Token Private Tokens
%p %p
Your private token is used to access application resources without authentication. Your private token is used to access the API and Atom feeds without
username/password authentication.
%p
Your incoming email token is used to create new issues by email, and is
included in your project-specific email addresses.
.col-lg-9 .col-lg-9
= form_for @user, url: reset_private_token_profile_path, method: :put, html: { class: "private-token" } do |f| %p.cgray
%p.cgray - if current_user.private_token
- if current_user.private_token = label_tag "token", "Private token", class: "label-light"
= label_tag "token", "Private token", class: "label-light" = text_field_tag "token", current_user.private_token, class: "form-control"
= text_field_tag "token", current_user.private_token, class: "form-control" - else
- else %span You don`t have one yet. Click generate to fix it.
%span You don`t have one yet. Click generate to fix it.
%p.help-block %p.help-block
It can be used for atom feeds or the API. Keep it secret! Keep this token secret, anyone with access to it can interact with the GitLab API as if they were you.
.prepend-top-default .prepend-top-default
- if current_user.private_token - if current_user.private_token
= f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default" = link_to 'Reset private token', reset_private_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default"
- else - else
= f.submit 'Generate', class: "btn btn-default" = f.submit 'Generate', class: "btn btn-default"
= link_to 'Reset incoming email token', reset_incoming_email_token_profile_path, method: :put, data: { confirm: "Are you sure?" }, class: "btn btn-default"
%hr %hr
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
...@@ -4,6 +4,7 @@ resource :profile, only: [:show, :update] do ...@@ -4,6 +4,7 @@ resource :profile, only: [:show, :update] do
get :applications, to: 'oauth/applications#index' get :applications, to: 'oauth/applications#index'
put :reset_private_token put :reset_private_token
put :reset_incoming_email_token
put :update_username put :update_username
end end
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddIncomingEmailTokenToUsers < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def change
add_column :users, :incoming_email_token, :string
add_concurrent_index :users, :incoming_email_token
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161103171205) do ActiveRecord::Schema.define(version: 20160819232256) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -1176,6 +1176,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do ...@@ -1176,6 +1176,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do
t.boolean "ldap_email", default: false, null: false t.boolean "ldap_email", default: false, null: false
t.boolean "external", default: false t.boolean "external", default: false
t.string "organization" t.string "organization"
t.string "incoming_email_token"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
...@@ -1185,6 +1186,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do ...@@ -1185,6 +1186,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do
add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", 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", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"} add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"}
add_index "users", ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree
add_index "users", ["name"], name: "index_users_on_name", using: :btree add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"} add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
......
...@@ -5,16 +5,16 @@ module Gitlab ...@@ -5,16 +5,16 @@ module Gitlab
module Email module Email
module Handler module Handler
class CreateIssueHandler < BaseHandler class CreateIssueHandler < BaseHandler
attr_reader :project_path, :authentication_token attr_reader :project_path, :incoming_email_token
def initialize(mail, mail_key) def initialize(mail, mail_key)
super(mail, mail_key) super(mail, mail_key)
@project_path, @authentication_token = @project_path, @incoming_email_token =
mail_key && mail_key.split('+', 2) mail_key && mail_key.split('+', 2)
end end
def can_handle? def can_handle?
!authentication_token.nil? !incoming_email_token.nil?
end end
def execute def execute
...@@ -29,7 +29,7 @@ module Gitlab ...@@ -29,7 +29,7 @@ module Gitlab
end end
def author def author
@author ||= User.find_by(authentication_token: authentication_token) @author ||= User.find_by(incoming_email_token: incoming_email_token)
end end
def project def project
......
...@@ -18,7 +18,7 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do ...@@ -18,7 +18,7 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do
create( create(
:user, :user,
email: 'jake@adventuretime.ooo', email: 'jake@adventuretime.ooo',
authentication_token: 'auth_token' incoming_email_token: 'auth_token'
) )
end end
...@@ -60,8 +60,8 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do ...@@ -60,8 +60,8 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do
end end
end end
context "when we can't find the authentication_token" do context "when we can't find the incoming_email_token" do
let(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") } let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") }
it "raises an UserNotFoundError" do it "raises an UserNotFoundError" do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError) expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
......
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