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
:- Maps a GitLab User to a Slack User ID (the
chat_id
is the Slack User ID like"UF8CHANLW"
and not a foreign key to anything). - The Slack User ID is sent during a slash command so we can use
ChatName
to identify a GitLab user from a request from Slack. - The strange model name, I think, was born out of earlier work to add Mattermost functionality (open source Slack clone, Mattermost is bundled with Omnibus) when the
ChatTeam
model was added in gitlab-foss!8746 (merged) (issue gitlab-foss#23964 (closed)).
- Maps a GitLab User to a Slack User ID (the
-
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 theintegrations
table). - It's used to look up a Gitlab integration through its
team_id
property andalias
property.- The
team_id
property is not a foreign key (and has nothing to do withChatTeam
) 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.
- The
- Should not be confused with
-
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.
- Request comes to
slack/trigger
API endpoint with params containing theteam_id
(ID in Slack of the workspace) anduser_id
(ID in Slack of the user). All params are passed toSlashCommands::GlobalSlackHandler
. - In
SlashCommands::GlobalSlackHandler
, the associatedIntegrations::GitlabSlackApplication
is found and the integration and params are passed toChatNames::FindUserService
. - In
ChatNames::FindUserService
, the associatedChatName
is found by theteam_id
,user_id
and integration. - 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 replacesSlackIntegration
. -
Integrations::Slack::User
would replaceChatName
.
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.