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
if Gitlab::IncomingEmail.enabled? && author # rubocop:disable Lint/UnreachableCode
Gitlab::IncomingEmail.reply_address(
"#{path_with_namespace}+#{author.authentication_token}")
end
author.ensure_incoming_email_token!
Gitlab::IncomingEmail.reply_address(
"#{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,24 +8,29 @@
.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"
= text_field_tag "token", current_user.private_token, class: "form-control"
- else
%span You don`t have one yet. Click generate to fix it.
%p.cgray
- if current_user.private_token
= label_tag "token", "Private token", class: "label-light"
= text_field_tag "token", current_user.private_token, class: "form-control"
- 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!
.prepend-top-default
- if current_user.private_token
= f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default"
- else
= f.submit 'Generate', class: "btn btn-default"
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
= 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)