Skip to content

Identify users in Slack without a project or integration

This issue has been promoted to an epic &9418 (closed). See that

About

Our backend modelling currently requires a project with a GitLab for Slack integration to be present in order to use features in the GitLab for Slack app. This includes the ability for users to link their Slack user to their GitLab user to let us identify their Slack activity in requests that are sent to GitLab. This is leading to a number of pain points and feature limitations.

We should remove the project and project integration-oriented approach.

We should be able to identify who a user is in GitLab from their Slack activity without expecting them to choose a project. At the point where project settings make sense (for example, notifications) then someone can create a project integration then.

Admins should be able to install the GitLab for Slack app without needing to create a project integration first.

See more at the new epic &9418 (closed), or click to see the old issue description

🤓 Clarifications upfront

Talking about Slack integrations is made difficult because there are multiple Slack integrations. The integrations are planned to be merged into one.

Integration name Model Purpose Will continue in future?
GitLab for Slack app integration Integrations::GitlabSlackApplication The only integration that works with the GitLab for Slack app. Its features are currently limited to only slash commands (/gitlab <project> show issue 1).
Slack notifications integration Integrations::Slack Supports notifications of GitLab events appearing in Slack channels
Slack Slash Commands integration Integrations::SlackSlashCommands Enables slash commands for self-managed

As only one integration works with the GitLab for Slack app, and this is the only integration that we will have in future &7536, this issue will ignore the other two integrations and use these terms:

  • GitLab for Slack app = the Slack app that exists in the Slack marketplace.
  • GitLab for Slack app integration = The integration backed by the model Integrations::GitlabSlackApplication. This is the only integration that correlates with the GitLab for Slack app. We'll ignore the other two.

😓 Limitations (technical-talk)

The current modelling of our Slack feature has some downsides:

  • It requires there to be a GitLab integration associated with the Slack app.
  • Each time a user creates an integration for the same Slack workspace, we save information about that Slack workspace in separate records.

The modelling is diagrammed below, but in a nutshell:

  • SlackIntegration (er, confusingly, not an integration model, but the model currently representing a Slack workspace - detailed more deeply below) must have an associated integration.
  • ChatName (confusingly named, but correlates a Slack User ID to a GitLab User ID to allow us to identify a GitLab User from a Slack User ID during slash commands) must have an associated integration.

😓 Limitations (product-talk)

The limitations are that we're currently very "GitLab Slack integration"-oriented and have what feel like artificial limitations on the product:

  • Slack admins can only install the Slack app into their workspace by creating an integration in GitLab for a project at the same time. This is why our "landing page" is currently a page that asks you to choose a project.
  • Slash commands only work for projects that have the Slack integration enabled, and not others.
  • In order to use slash commands for more than one project, a Slack admin needs to set up a second project with the integration. The Slack users then also need to link their Slack and GitLab accounts a second time in order to use slash commands for that second project. This experience is a bit weird and unnecessary since we already know their Slack User ID and GitLab User ID from the first time they did this. The links appear as separate records to the user, see https://gitlab.com/gitlab-org/gitlab/uploads/cea3f287e707aa0384a032bc2a51226d/image.png.

Continuing on to future features, we would see link unfurling working with the same limitations as slash commands:

  • Link unfurling would only work for projects that have the Slack integration enabled, and not others. This limitation is not what we want #339906 (comment 905390162).

🔮 What would removing these limitations mean to the product?

We would no longer enforce a GitLab integration to be created in order to use much of the Slack functionality we offer. For example, these things could happen without needing an integration to be created at all:

  • Admins could install the Slack app into their workspace (without needing to create an integration in GitLab at the same time - or visiting our landing page).
  • Link unfurls could work for all public things on the GitLab instance.
  • We could treat slash commands the same as link unfurls if we wanted to, and work for all public things on the GitLab instance.
  • Slack users would need to only link their GitLab accounts once (per Slack workspace) when GitLab needs to identify them, instead of repeatedly per integration (because the integration would not be required).
  • Slash commands that don't take a project would be able to prompt the user to identify themselves without needing a project to be specified #377548 (comment 1168905857).

The GitLab integration would be required only when it was needed to add selective functionality:

  • To know that we should unfurl private/confidential things for a project/group #339906 (comment 905390162).
  • To notify GitLab events in Slack channels (to say which group/project events should go to which channels).

Current modelling deep dive (technical)

The current modelling:

erDiagram
  ChatName ||--|| Integrations_GitlabSlackApplication : "belongs to"          
  ChatName ||--o{ User : "belongs to"          
  SlackIntegration ||--|| Integrations_GitlabSlackApplication : "belongs to"  
  Integrations_GitlabSlackApplication ||--|| Project : "belongs to"

  ChatName {
      string team_id
      string chat_id
  }

  SlackIntegration {
      string team_id
      string team_name
      string alias
  }
Expand to read notes on what these models are and what their properties represent
  • ChatName:
  • SlackIntegration:
    • Should not be confused with Integrations::Slack or any of our three slack integrations 🙃; its purpose is the equivalent of data fields tables (a place to store extra data outside of the integrations table).
    • It's used to look up a Gitlab integration through its team_id property and alias property.
      • The team_id property is not a foreign key (and has nothing to do with ChatTeam) but is a string ID of a Mattermost Team, or Slack Workspace sent during a slash command (e.g. "T02192311").
      • alias is the associated integration's project's full path.
  • ChatTeam doesn't appear to play a role in Slack and I think is Mattermost-only.
Expand to read how this modelling is used to identify a GitLab \`User\` from a Slack request.
  1. Request comes to slack/trigger API endpoint with params containing the team_id (ID in Slack of the workspace) and user_id (ID in Slack of the user). All params are passed to SlashCommands::GlobalSlackHandler.
  2. In SlashCommands::GlobalSlackHandler, the associated Integrations::GitlabSlackApplication is found and the integration and params are passed to ChatNames::FindUserService.
  3. In ChatNames::FindUserService, the associated ChatName is found by the team_id , user_id and integration.
  4. The associated GitLab user can then be found from ChatName.

Proposed re-modelling (technical)

We would create two new models, neither of which would require an associated integration:

  • Integrations::Slack::Workspace would replaces SlackIntegration.
  • Integrations::Slack::User would replace ChatName.

We would migrate all Slack users from ChatName to Integrations::Slack::User (leaving Mattermost ChatName records), and migrate team_id and team_name and bot data from SlackIntegration to Integrations::Slack::Workspace. The SlackIntegration#alias property would be migrated to the integration's encrypted properties.

This would be the modelling:

erDiagram
  Integrations_Slack_Workspace
  Integrations_Slack_User }o--|| User : "belongs to"
  Integrations_Slack_Workspace ||--o{ Integrations_Slack_User : "has many"          

  Integrations_Slack_User {
      integer workspace_id
      string slack_id
      integer user_id
  }

  Integrations_Slack_Workspace {
      string slack_id
      string token
  }

When a project/group integration needs to be created, they would be associated in this way:

erDiagram
  Integrations_Slack_User }o--|| User : "belongs to"
  Integrations_Slack_Workspace ||--o{ Integrations_Slack_User : "has many"
  Integrations_GitlabSlackApplication ||--|| Project : "belongs to"
  Integrations_Slack_Workspace ||--o{ Integrations_GitlabSlackApplication : "has many"

  Integrations_Slack_User {
      integer workspace_id
      string slack_id
      integer user_id
  }

  Integrations_Slack_Workspace {
      string slack_id
      string token
  }

The downside is that we would need to migrate a slack_workspace_id FK into the integrations table.

TODO Implementation

Migration

TODO details. One issue per step.

Slack app landing page

TODO details. We would still want people to install the Slack app through GitLab, for us to gain a bot token for the workspace. We wouldn't need them to choose a project first.

Edited by Luke Duncalfe