summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-11-13 20:35:47 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2016-11-16 13:42:35 +0100
commitc60437786bfe43344b4a5eb040437f73f37c6396 (patch)
treefe90ee0dd9e556369e7f53ce4a03e2751b486682
parentc5169b5d447ab6c73bbe542c071a4054c5969165 (diff)
downloadgitlab-ce-c60437786bfe43344b4a5eb040437f73f37c6396.tar.gz
Create relation between chat user and GitLab user and allow to authorize them [ci skip]
-rw-r--r--app/controllers/profiles/chat_names_controller.rb64
-rw-r--r--app/models/chat_name.rb12
-rw-r--r--app/models/user.rb1
-rw-r--r--app/services/chat_names/find_user_service.rb15
-rw-r--r--app/services/chat_names/request_service.rb32
-rw-r--r--app/views/layouts/nav/_profile.html.haml4
-rw-r--r--app/views/profiles/chat_names/index.html.haml49
-rw-r--r--app/views/profiles/chat_names/new.html.haml15
-rw-r--r--config/routes/profile.rb6
-rw-r--r--db/migrate/20161113184239_create_user_chat_names_table.rb20
-rw-r--r--db/schema.rb16
-rw-r--r--lib/gitlab/chat_name_token.rb45
12 files changed, 278 insertions, 1 deletions
diff --git a/app/controllers/profiles/chat_names_controller.rb b/app/controllers/profiles/chat_names_controller.rb
new file mode 100644
index 00000000000..8c5b83adaf4
--- /dev/null
+++ b/app/controllers/profiles/chat_names_controller.rb
@@ -0,0 +1,64 @@
+class Profiles::ChatNamesController < Profiles::ApplicationController
+ before_action :chat_names
+ before_action :chat_name_token, only: [:new]
+ before_action :chat_name_params, only: [:new, :create, :deny]
+
+ def index
+ end
+
+ def new
+ end
+
+ def create
+ new_chat_name = current_user.chat_names.new(chat_name_params)
+
+ if new_chat_name.save
+ flash[:notice] = "Authorized chat nickname #{new_chat_name.chat_name}"
+ else
+ flash[:alert] = "Could not authorize chat nickname. Try again!"
+ end
+
+ delete_chat_name_token
+ redirect_to profile_chat_names_path
+ end
+
+ def deny
+ delete_chat_name_token
+
+ flash[:alert] = "Denied authorization of chat nickname #{chat_name_params[:user_name]}"
+
+ redirect_to profile_chat_names_path
+ end
+
+ def destroy
+ @chat_name = chat_names.find(params[:id])
+
+ if @chat_name.destroy
+ flash[:notice] = "Delete chat nickname: #{@chat_name.chat_name}!"
+ else
+ flash[:alert] = "Could not delete chat nickname #{@chat_name.chat_name}."
+ end
+
+ redirect_to profile_chat_names_path
+ end
+
+ private
+
+ def delete_chat_name_token
+ chat_name_token.delete
+ end
+
+ def chat_name_params
+ @chat_name_params ||= chat_name_token.get || render_404
+ end
+
+ def chat_name_token
+ return render_404 unless params[:token] || render_404
+
+ @chat_name_token ||= Gitlab::ChatNameToken.new(params[:token])
+ end
+
+ def chat_names
+ @chat_names ||= current_user.chat_names
+ end
+end
diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb
new file mode 100644
index 00000000000..f321db75eeb
--- /dev/null
+++ b/app/models/chat_name.rb
@@ -0,0 +1,12 @@
+class ChatName < ActiveRecord::Base
+ belongs_to :service
+ belongs_to :user
+
+ validates :user, presence: true
+ validates :service, presence: true
+ validates :team_id, presence: true
+ validates :chat_id, presence: true
+
+ validates :user_id, uniqueness: { scope: [:service_id] }
+ validates :chat_id, uniqueness: { scope: [:service_id, :team_id] }
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 3813df6684e..10fe69818b6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -56,6 +56,7 @@ class User < ActiveRecord::Base
has_many :personal_access_tokens, dependent: :destroy
has_many :identities, dependent: :destroy, autosave: true
has_many :u2f_registrations, dependent: :destroy
+ has_many :chat_names, dependent: :destroy
# Groups
has_many :members, dependent: :destroy
diff --git a/app/services/chat_names/find_user_service.rb b/app/services/chat_names/find_user_service.rb
new file mode 100644
index 00000000000..6b7f75430a8
--- /dev/null
+++ b/app/services/chat_names/find_user_service.rb
@@ -0,0 +1,15 @@
+module ChatNames
+ class FindUserService
+ def initialize(chat_names, params)
+ @chat_names = chat_names
+ @params = params
+ end
+
+ def execute
+ @chat_names.find_by(
+ team_id: @params[:team_id],
+ chat_id: @params[:user_id]
+ )
+ end
+ end
+end
diff --git a/app/services/chat_names/request_service.rb b/app/services/chat_names/request_service.rb
new file mode 100644
index 00000000000..c67b93f932f
--- /dev/null
+++ b/app/services/chat_names/request_service.rb
@@ -0,0 +1,32 @@
+module ChatNames
+ class RequestService
+ include Gitlab::Routing.url_helpers
+
+ def initialize(service, params)
+ @service = service
+ @params = params
+ end
+
+ def execute
+ token = chat_name_token.store!(chat_name_params)
+
+ new_profile_chat_name_url(token: token) if token
+ end
+
+ private
+
+ def chat_name_token
+ Gitlab::ChatNameToken.new
+ end
+
+ def chat_name_params
+ {
+ service_id: @service.id,
+ team_id: @params[:team_id],
+ team_domain: @params[:team_domain],
+ chat_id: @params[:user_id],
+ chat_name: @params[:user_name]
+ }
+ end
+ end
+end
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index 6d514f669db..e06301bda14 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -17,6 +17,10 @@
= link_to applications_profile_path, title: 'Applications' do
%span
Applications
+ = nav_link(controller: :chat_names) do
+ = link_to profile_chat_names_path, title: 'Chat' do
+ %span
+ Chat
= nav_link(controller: :personal_access_tokens) do
= link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
%span
diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
new file mode 100644
index 00000000000..f90ac4c6a03
--- /dev/null
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -0,0 +1,49 @@
+- page_title "Chat"
+= render 'profiles/head'
+
+.row.prepend-top-default
+ .col-lg-3.profile-settings-sidebar
+ %h4.prepend-top-0
+ = page_title
+ %p
+ You can see your Chat integrations.
+
+ .col-lg-9
+ %h5 Active chat names (#{@chat_names.length})
+
+ - if @chat_names.present?
+ .table-responsive
+ %table.table.chat-names
+ %thead
+ %tr
+ %th Project
+ %th Service
+ %th Team domain
+ %th Nickname
+ %th Created
+ %th
+ %tbody
+ - @chat_names.each do |chat_name|
+ - service = chat_name.service
+ - project = service.project
+ %tr
+ %td
+ %strong
+ - if can?(current_user, :read_project, project)
+ = link_to project.name_with_namespace, project_path(project)
+ - else
+ .light N/A
+ %td
+ %strong
+ - if can?(current_user, :admin_project, project)
+ = link_to service.title, edit_namespace_project_service_path(project.namespace, project, service)
+ - else
+ = chat_name.service.title
+ %td= chat_name.team_domain
+ %td= chat_name.chat_name
+ %td= chat_name.created_at
+ %td= link_to "Remove", profile_chat_name_path(chat_name), method: :delete, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this nickname?" }
+
+ - else
+ .settings-message.text-center
+ You don't have any active chat names.
diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml
new file mode 100644
index 00000000000..0b9ee8c71ad
--- /dev/null
+++ b/app/views/profiles/chat_names/new.html.haml
@@ -0,0 +1,15 @@
+%h3.page-title Authorization required
+%main{:role => "main"}
+ %p.h4
+ Authorize the chat user
+ %strong.text-info= @chat_name_params[:chat_name]
+ to use your account?
+
+ %hr/
+ .actions
+ = form_tag profile_chat_names_path, method: :post do
+ = hidden_field_tag :token, @chat_name_token.token
+ = submit_tag "Authorize", class: "btn btn-success wide pull-left"
+ = form_tag deny_profile_chat_names_path, method: :delete do
+ = hidden_field_tag :token, @chat_name_token.token
+ = submit_tag "Deny", class: "btn btn-danger prepend-left-10"
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
index 52b9a565db8..6b91485da9e 100644
--- a/config/routes/profile.rb
+++ b/config/routes/profile.rb
@@ -23,6 +23,12 @@ resource :profile, only: [:show, :update] do
resource :preferences, only: [:show, :update]
resources :keys, only: [:index, :show, :new, :create, :destroy]
resources :emails, only: [:index, :create, :destroy]
+ resources :chat_names, only: [:index, :new, :create, :destroy] do
+ collection do
+ delete :deny
+ end
+ end
+
resource :avatar, only: [:destroy]
resources :personal_access_tokens, only: [:index, :create] do
diff --git a/db/migrate/20161113184239_create_user_chat_names_table.rb b/db/migrate/20161113184239_create_user_chat_names_table.rb
new file mode 100644
index 00000000000..f9ab2adf2a9
--- /dev/null
+++ b/db/migrate/20161113184239_create_user_chat_names_table.rb
@@ -0,0 +1,20 @@
+class CreateUserChatNamesTable < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :chat_names do |t|
+ t.integer "user_id", null: false
+ t.integer "service_id", null: false
+ t.string "team_id"
+ t.string "team_domain"
+ t.string "chat_id"
+ t.string "chat_name"
+ t.timestamps
+ end
+
+ add_index :chat_names, [:user_id, :service_id], unique: true
+ add_index :chat_names, [:service_id, :team_id, :chat_id], unique: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 62c325a52d7..5f25f0a305f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20161106185620) do
+ActiveRecord::Schema.define(version: 20161113184239) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -149,6 +149,20 @@ ActiveRecord::Schema.define(version: 20161106185620) do
t.text "message_html"
end
+ create_table "chat_names", force: :cascade do |t|
+ t.integer "user_id", null: false
+ t.integer "service_id", null: false
+ t.string "team_id"
+ t.string "team_domain"
+ t.string "chat_id"
+ t.string "chat_name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ add_index "chat_names", ["service_id", "team_id", "user_id"], name: "index_chat_names_on_service_id_and_team_id_and_user_id", unique: true, using: :btree
+ add_index "chat_names", ["user_id", "service_id"], name: "index_chat_names_on_user_id_and_service_id", unique: true, using: :btree
+
create_table "ci_application_settings", force: :cascade do |t|
t.boolean "all_broken_builds"
t.boolean "add_pusher"
diff --git a/lib/gitlab/chat_name_token.rb b/lib/gitlab/chat_name_token.rb
new file mode 100644
index 00000000000..c8349839219
--- /dev/null
+++ b/lib/gitlab/chat_name_token.rb
@@ -0,0 +1,45 @@
+require 'json'
+
+module Gitlab
+ class ChatNameToken
+ attr_reader :token
+
+ TOKEN_LENGTH = 50
+ EXPIRY_TIME = 1800
+
+ def initialize(token = new_token)
+ @token = token
+ end
+
+ def get
+ Gitlab::Redis.with do |redis|
+ data = redis.get(redis_key)
+ JSON.parse(data, symbolize_names: true) if data
+ end
+ end
+
+ def store!(params)
+ Gitlab::Redis.with do |redis|
+ params = params.to_json
+ redis.set(redis_key, params, ex: EXPIRY_TIME)
+ token
+ end
+ end
+
+ def delete
+ Gitlab::Redis.with do |redis|
+ redis.del(redis_key)
+ end
+ end
+
+ private
+
+ def new_token
+ Devise.friendly_token(TOKEN_LENGTH)
+ end
+
+ def redis_key
+ "gitlab:chat_names:#{token}"
+ end
+ end
+end