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

email token be reset
This commit is contained in:
Douwe Maan 2016-08-19 18:33:46 -05:00 committed by tiagonbotelho
parent 09f4af04c6
commit 9d51421346
12 changed files with 79 additions and 34 deletions

View File

@ -26,7 +26,15 @@ class ProfilesController < Profiles::ApplicationController
def reset_private_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
redirect_to profile_account_path

View File

@ -4,17 +4,21 @@ module TokenAuthenticatable
private
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)
end
def generate_token(token_field)
def generate_available_token(token_field)
loop do
token = Devise.friendly_token
token = generate_token(token_field)
break token unless self.class.unscoped.find_by(token_field => token)
end
end
def generate_token(token_field)
Devise.friendly_token
end
class_methods do
def authentication_token_fields
@token_fields || []

View File

@ -624,13 +624,12 @@ class Project < ActiveRecord::Base
end
def new_issue_address(author)
# This feature is disabled for the time being.
return nil
return unless Gitlab::IncomingEmail.enabled? && author
author.ensure_incoming_email_token!
if Gitlab::IncomingEmail.enabled? && author # rubocop:disable Lint/UnreachableCode
Gitlab::IncomingEmail.reply_address(
"#{path_with_namespace}+#{author.authentication_token}")
end
"#{path_with_namespace}+#{author.incoming_email_token}")
end
def build_commit_note(commit)

View File

@ -13,6 +13,7 @@ class User < ActiveRecord::Base
DEFAULT_NOTIFICATION_LEVEL = :participating
add_authentication_token_field :authentication_token
add_authentication_token_field :incoming_email_token
default_value_for :admin, false
default_value_for(:external) { current_application_settings.user_default_external }
@ -119,7 +120,7 @@ class User < ActiveRecord::Base
before_validation :set_public_email, if: ->(user) { user.public_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
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
@ -946,4 +947,13 @@ class User < ActiveRecord::Base
signup_domain =~ regexp
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

View File

@ -8,11 +8,14 @@
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Private Token
Private Tokens
%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
= form_for @user, url: reset_private_token_profile_path, method: :put, html: { class: "private-token" } do |f|
%p.cgray
- if current_user.private_token
= label_tag "token", "Private token", class: "label-light"
@ -20,12 +23,14 @@
- else
%span You don`t have one yet. Click generate to fix it.
%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
- 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
= 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
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar

View File

@ -4,6 +4,7 @@ resource :profile, only: [:show, :update] do
get :applications, to: 'oauth/applications#index'
put :reset_private_token
put :reset_incoming_email_token
put :update_username
end

View File

@ -0,0 +1,16 @@
# 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

View File

@ -11,7 +11,7 @@
#
# 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
enable_extension "plpgsql"
@ -1176,6 +1176,7 @@ ActiveRecord::Schema.define(version: 20161103171205) do
t.boolean "ldap_email", default: false, null: false
t.boolean "external", default: false
t.string "organization"
t.string "incoming_email_token"
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
@ -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", ["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", ["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_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

View File

@ -5,16 +5,16 @@ module Gitlab
module Email
module Handler
class CreateIssueHandler < BaseHandler
attr_reader :project_path, :authentication_token
attr_reader :project_path, :incoming_email_token
def initialize(mail, mail_key)
super(mail, mail_key)
@project_path, @authentication_token =
@project_path, @incoming_email_token =
mail_key && mail_key.split('+', 2)
end
def can_handle?
!authentication_token.nil?
!incoming_email_token.nil?
end
def execute
@ -29,7 +29,7 @@ module Gitlab
end
def author
@author ||= User.find_by(authentication_token: authentication_token)
@author ||= User.find_by(incoming_email_token: incoming_email_token)
end
def project

View File

@ -18,7 +18,7 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do
create(
:user,
email: 'jake@adventuretime.ooo',
authentication_token: 'auth_token'
incoming_email_token: 'auth_token'
)
end
@ -60,8 +60,8 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do
end
end
context "when we can't find the authentication_token" do
let(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") }
context "when we can't find the incoming_email_token" do
let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") }
it "raises an UserNotFoundError" do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)