-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Add GitLab auth #5594
[RFC] Add GitLab auth #5594
Conversation
fa3dbd8
to
ac9f74c
Compare
- TODO: add userId to MattermostAuth, query best auth for team
6736ac2
to
298dc22
Compare
@@ -30,7 +30,15 @@ const useMenu = <T extends HTMLElement = HTMLButtonElement>( | |||
if (originCoords) { | |||
;(originRef as any).current = {getBoundingClientRect: () => originCoords} as RectElement | |||
} | |||
const {portal, closePortal, togglePortal, portalStatus, setPortalStatus, openPortal} = usePortal({ | |||
const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes here are only to return terminatePortal
so it may be used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review pass one: will make some small fixups
@@ -8,7 +8,8 @@ export default class DemoUser { | |||
createdAt = new Date().toJSON() | |||
email: string | |||
featureFlags = { | |||
jira: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume it is ok to remove this flag of yesteryear...
packages/server/graphql/intranetSchema/mutations/runScheduledJobs.ts
Outdated
Show resolved
Hide resolved
packages/server/postgres/migrations/1634351004998_addMattermostAuth.ts
Outdated
Show resolved
Hide resolved
👀 **Watch the demo & overview 👇 ** Specific requests from reviewers:
|
15ca521
to
450baf3
Compare
Great work @jordanh! Regarding the database schema, I'd avoid having separate columns for things that are related only to a particular provider type. For example, when the provider type is different than OAuth we'll have all OAuth columns empty. It'd be better to keep provider data in a separate JSONB column. This way we can deserialize data into a proper type when querying and no matter what provider type we add, we won't need to change the DB schema. And we avoid having provider-specific columns in a generic table. Then, the table would look like
Depending on what differences are in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I second Bartosz's suggestion and made some minor suggestions
'Content-Type': 'application/json' | ||
} | ||
|
||
const uri = `${this.provider.serverBaseUri}/oauth/token?${stringify(queryParams)}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does most of the services have OAuth token request URI like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will almost certainly need to be parameterized
try { | ||
const r = await getRethink() | ||
await flushSocketConnections() | ||
await storePersistedQueries() | ||
await r.getPoolMaster().drain() | ||
|
||
const pg = getPg() | ||
await upsertGlobalIntegrationProvidersFromEnv() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be delay between inserting the rows and app starting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pool is drained, so these row(s) will be updated before the app starts
} | ||
|
||
const data = {userId: viewerId, teamId} | ||
publish(SubscriptionChannel.TEAM, teamId, 'AddIntegrationProvider', data, subOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the subscription level should be depend on the scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. If/when we update the Org view to manage integration providers, this logic will need to be added here (and the subscriptions return types will need to be updated)
description: "The provider's unique identifier", | ||
resolve: ({id}) => IntegrationProviderId.join(id) | ||
}, | ||
type: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have cases where we expect to have more than one token type per integration provider?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's certainly possible! For Mattermost we could support Oauth2, PATs, and Webhooks if we wanted to as Mattermost supports each of these modes
"oauthClientSecret" VARCHAR(2600), | ||
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, | ||
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, | ||
UNIQUE("scopeGlobal", "type"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
"expiresAt" TIMESTAMP WITH TIME ZONE, | ||
"oauthRefreshToken" VARCHAR(2600), | ||
"oauthScopes" VARCHAR(100)[], | ||
"attributes" JSONB, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems rather vague, if we follow Bartosz's recommendation we don't need that. Is this meant to store integration specific settings like your last github search?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree with you and @BartoszJarocki, let's move these oauth*
vars to the attributes
column.
If an implementer wanted to, we could use attributes
to store things like your last github search, although, personally I think these should likely belong on their own table. I mostly intended these abstracts to only handle auth. The fact we conflate auth and state is a bit hacky IMO.
// this table has a composite primary key (userId, teamId), | ||
// which cannot use the index with a WHERE IN or JOIN on VALUES | ||
// so if we want to query multiple userIds/teamIds, just call this multiple times | ||
// if we want to query multiple userIds/teamIds, just call this multiple times |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is out of scope of this RFC, but you removed the answer to 'why?' from the comment, which is the important bit. If I would look at this in a month I wouldn't know why we wouldn't just implement it for multiple userId, teamId pairs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment was originally written by @mattkrick. He tells me this is no longer true (or perhaps was never true) when we spoke sync about this
CREATE INDEX IF NOT EXISTS "idx_IntegrationProvider_orgId" ON "IntegrationProvider"("orgId"); | ||
CREATE INDEX IF NOT EXISTS "idx_IntegrationProvider_teamId" ON "IntegrationProvider"("teamId"); | ||
CREATE TABLE IF NOT EXISTS "IntegrationToken" ( | ||
"teamId" VARCHAR(100) NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts on whether or not we should have the IntegrationToken per User, Team, Provider (1, current solution) or just User, Provider and then a separate relation TeamMemberIntegration (2).
- Pro
- easy, it's what we have now
- no joins
Con - updates to the token need to be propagated to all rows
- Pro
- it would simplify refreshing a token and similar operations on the token itself, because it would not require to update multiple rows.
- integration specific settings could be stored on TeamMemberIntegration and thus could also be stored without having a token
Con - additional join for retrieving the token
- the key User,IntegrationProvider might not work. While I think it is unlikely that someone wants to have access to Jira with 2 different accounts in 1 team, the likelyhood increases when it's spread over multiple teams. This is probably still not a use case, only wanted to mention it.
Before, when we did an "import someImage 'static/some.png'", file-loader would give us a path relative to the root like 'dist/[hash].png'. Now, we'll: - Use the CDN if it's configured - Serve up the assets via `static/` otherwise Also: - makeMattermostAttachments fixed to server assets from CDN
Also: - Fixed bugs in (Add|Update)IntegrationProvier mutations where we were returning the wrong error type (and sometimes the incorrect error variable!) - Added comments and TODOs to enhance AddIntegrationProvider when an oauth token is specified to work like AddIntegrationToken and, - validate that new tokens are functional by loading the appropriate ServerManager and running a method that tests that ServerManager's connection
Closing in favor of #5805 |
No description provided.