Skip to content

Email notification for Expired Personal Access Token

Aishwarya Subramanian requested to merge additional-pat-expiry-notification into master

What does this MR do?

Adds a cron job that runs at 2 am daily and checks for Personal Access Tokens that have expired on the current day.

Sends out an email notification to the user indicating that their Personal Access Tokens have expired. Also, links the Manage Token page to assist the user to take an action.

Mentions #214721 (closed)

Omnibus changes

omnibus-gitlab!4465 (merged)

Feature flag

Name: expired_pat_email_notification

Disabled by default.

Screenshots

Email preview:

Screen_Shot_2020-07-29_at_2.53.32_PM

Database changes

Migration

== 20200729151021 AddAfterExpiryNotificationDeliveredToPersonalAccessTokens: migrating
-- add_column(:personal_access_tokens, :after_expiry_notification_delivered, :boolean, {:null=>false, :default=>false})
   -> 0.0035s
== 20200729151021 AddAfterExpiryNotificationDeliveredToPersonalAccessTokens: migrated (0.0036s)

Rollback

== 20200729151021 AddAfterExpiryNotificationDeliveredToPersonalAccessTokens: reverting
-- remove_column(:personal_access_tokens, :after_expiry_notification_delivered, :boolean, {:null=>false, :default=>false})
   -> 0.0039s
== 20200729151021 AddAfterExpiryNotificationDeliveredToPersonalAccessTokens: reverted (0.0070s)

Query

SELECT
    "users".*
FROM
    "users"
WHERE (EXISTS (
        SELECT
            1
        FROM
            "personal_access_tokens"
        WHERE (personal_access_tokens.user_id = users.id)
        AND "personal_access_tokens"."impersonation" = FALSE
        AND (revoked = FALSE
            AND expires_at = CURRENT_DATE
            AND after_expiry_notification_delivered = FALSE)))

After index:

Link to execution plan:

https://explain.depesz.com/s/La7N

Execution Time:

Time: 300.623 ms
  - planning: 1.081 ms
  - execution: 299.542 ms
    - I/O read: 243.414 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 702 (~5.50 MiB) from the buffer pool
  - reads: 8800 (~68.80 MiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

Before index:

Link to execution plan:

https://explain.depesz.com/s/O8lv

Execution Time:

Time: 445.142 ms
  - planning: 0.826 ms
  - execution: 444.316 ms
    - I/O read: 357.225 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 193 (~1.50 MiB) from the buffer pool
  - reads: 11746 (~91.80 MiB) from the OS file cache, including disk I/O
  - dirtied: 151 (~1.20 MiB)
  - writes: 0

Local testing

  1. Create a new Personal Access Token that expires today (<gdk link>/profile/personal_access_tokens)
  2. Optionally configure the expiry email to be sent immediately (Change deliver_later to deliver_now in the notification service)
  3. Head over to rails console:
    • Execute the job: PersonalAccessTokens::ExpiredNotificationWorker.new.perform
    • Check for a new email Your personal access token has expired in <gdk link>/rails/letter_opener

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • [-] Label as security and @ mention @gitlab-com/gl-security/appsec
  • [-] The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • [-] Security reports checked/validated by a reviewer from the AppSec team
Edited by Mayra Cabrera

Merge request reports