summaryrefslogtreecommitdiff
path: root/db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb
blob: 305c12e31f8c3fbe10872142b352ce9bf1e4127a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.

class MigrateUserAuthenticationTokenToPersonalAccessToken < ActiveRecord::Migration[4.2]
  include Gitlab::Database::MigrationHelpers

  # Set this constant to true if this migration requires downtime.
  DOWNTIME = false

  # disable_ddl_transaction!

  TOKEN_NAME = 'Private Token'.freeze

  def up
    execute <<~SQL
      INSERT INTO personal_access_tokens (user_id, token, name, created_at, updated_at, scopes)
      SELECT id, authentication_token, '#{TOKEN_NAME}', NOW(), NOW(), '#{%w[api].to_yaml}'
      FROM users
      WHERE authentication_token IS NOT NULL
      AND admin = FALSE
      AND NOT EXISTS (
        SELECT true
        FROM personal_access_tokens
        WHERE user_id = users.id
        AND token = users.authentication_token
      )
    SQL

    # Admins also need the `sudo` scope
    execute <<~SQL
      INSERT INTO personal_access_tokens (user_id, token, name, created_at, updated_at, scopes)
      SELECT id, authentication_token, '#{TOKEN_NAME}', NOW(), NOW(), '#{%w[api sudo].to_yaml}'
      FROM users
      WHERE authentication_token IS NOT NULL
      AND admin = TRUE
      AND NOT EXISTS (
        SELECT true
        FROM personal_access_tokens
        WHERE user_id = users.id
        AND token = users.authentication_token
      )
    SQL
  end

  def down
    if Gitlab::Database.postgresql?
      execute <<~SQL
        UPDATE users
        SET authentication_token = pats.token
        FROM (
          SELECT user_id, token
          FROM personal_access_tokens
          WHERE name = '#{TOKEN_NAME}'
        ) AS pats
        WHERE id = pats.user_id
      SQL
    else
      execute <<~SQL
        UPDATE users
        INNER JOIN personal_access_tokens AS pats
        ON users.id = pats.user_id
        SET authentication_token = pats.token
        WHERE pats.name = '#{TOKEN_NAME}'
      SQL
    end

    execute <<~SQL
      DELETE FROM personal_access_tokens
      WHERE name = '#{TOKEN_NAME}'
      AND EXISTS (
        SELECT true
        FROM users
        WHERE id = personal_access_tokens.user_id
        AND authentication_token = personal_access_tokens.token
      )
    SQL
  end
end