From 08e941f8af6786c92fa7f490381bed3c7db77b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Jedlicska?= <57442769+gjedlicska@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:33:16 +0200 Subject: [PATCH] Poor man's SSO (#2641) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implemented workspace general page * Added notifications to user input * Allowed non-admins to view but not edit * Added redirect to homeroute * Fixed validation * Squashed commit of the following: commit 7bf14ab8af0f76b4c9d0aa87fc08085af7c34959 Author: Chuck Driesler Date: Tue Aug 6 19:40:50 2024 +0200 mob next [ci-skip] [ci skip] [skip ci] lastFile:packages/server/modules/workspacesCore/migrations/20240806160740_workspace_domains.ts commit 8aa3fb0cb052c10eeeb83bf9874ae0d1c065e480 Author: Alessandro Magionami Date: Tue Aug 6 18:54:15 2024 +0200 mob next [ci-skip] [ci skip] [skip ci] lastFile:packages/server/modules/core/domain/userEmails/operations.ts commit 66dfd0cf6c15a789c8f96a65a3168323e83a7b9e Author: Chuck Driesler Date: Tue Aug 6 18:30:22 2024 +0200 mob next [ci-skip] [ci skip] [skip ci] lastFile:packages/server/modules/workspacesCore/domain/types.ts Co-authored-by: Alessandro Magionami * Move General to workspaces folder * feat(workspaces): inputs on security section * feat(workspaces): add domain to workspace mutation * chore(workspaces): add blocked domains list * fix(workspaces): modals with buttons * feat(workspaceDomains): delete domain * fix(workspaces): use mutation * fix(workspaces): present user verified domains as options * Moved sidebar menu to a composable * Added coming soon tag back * feat(workspaces): create domains resolver for workspace * chore(workspaces): fix tests * chore(workspaces): fix types * chore(workspaces): fix linter * fix(workspaces): do some delete I think * chore(workspaces): add domainBasedMembershipProtectionEnabled field to workspace * chore(workspaces): improve validation for email domain * fix(workspace): query and do the thing * chore(workspaces): add graphql schema for domainBasedMembershipProtection * chore(workspaces): lint and test failures * fix(workspaces): test issues w new field * feat(workspaces): add discoverability flag * chore(workspaces): they made me do it * feat(workspaces): enable toggling domain protection * feat(workspaces): add discoverability toggle to workspace settings * feat(workspace): auto enable discoverability on first domain registration * feat(workspace): discoverability toggle fixes * fix(eventBus): fix tests * feat(workspaces): user discoverable workspaces (#2620) * feat(workspaces): it works just trust me * fix(workspaces): don't worry about it * fix(workspaces); happy path success * fix(workspaces): almost there * fix(workspaces): successful tests! * fix(workspaces): we have DISCOVERED (#2621) * Fixed linting issue * Updated query * Updated validation rules * Updated validation rules * Fix unsaved file with type export * Addressed PR comments * Updated cache * Updated item classes, add fragment back * Gergo/web 1574 join workspaces via discovery (#2623) * chore(useremails): add find verified emails by user function * chore(workspace): table helper for workspace domains * chore(workspace): get workspace with domains function * chore(workspace): test get workspace with domains function * feat(workspace): restrict workspace membership when updating workspace role * chore(workspaces): fix types * feat(workspaces): WIP join * feat(workspaces): join button makes u join * chore(useremails): fix type for find verified emails function * feat(workspaces): join * feat(workspace): prevent inviting user without email matching domain * chore(workspaces): fix linter * fix(workspaces): invoke join (gergo wrote this) * fuck * fix(workspaces): properly get discoverable workspaces * fix(workspaces): test --------- Co-authored-by: Gergő Jedlicska Co-authored-by: Chuck Driesler * fix(workspaces): some query stuff * fix(workspaces): mutate cache instead of refetch * fix(workspaces): more adjustments to gql query and fragment structure * fix(workspaces): queries, style, structure * fix(workspaces): match discoverability with current styles * chore(workspaces): lint lint lint * fix(workspaces): got it twisted * chore(workspaces): fix test * fix(workspaces): route to joined workspace on join --------- Co-authored-by: Mike Tasset Co-authored-by: Chuck Driesler Co-authored-by: Alessandro Magionami --- .../dui3/lib/common/generated/gql/graphql.ts | 17 +- .../form/select/WorkspaceDomains.vue | 42 ++ .../frontend-2/components/invite/Banner.vue | 15 +- .../components/projects/Dashboard.vue | 9 +- .../components/projects/DashboardHeader.vue | 5 +- .../settings/workspaces/Security.vue | 224 +++++++++ .../workspaces/security/DomainAddDialog.vue | 161 ++++++ .../security/DomainRemoveDialog.vue | 112 +++++ .../components/workspace/invite/Banners.vue | 19 +- .../invite/DiscoverableWorkspaceBanner.vue | 92 ++++ .../lib/common/generated/gql/gql.ts | 61 ++- .../lib/common/generated/gql/graphql.ts | 143 +++++- .../lib/dashboard/graphql/mutations.ts | 11 + .../lib/dashboard/graphql/queries.ts | 4 +- .../lib/projects/graphql/queries.ts | 5 +- .../lib/settings/composables/menu.ts | 10 +- .../lib/settings/graphql/mutations.ts | 31 ++ .../lib/settings/graphql/queries.ts | 11 + packages/frontend-2/pages/index.vue | 8 +- .../typedefs/workspaces.graphql | 55 ++ .../core/domain/userEmails/operations.ts | 9 + .../modules/core/graph/generated/graphql.ts | 91 ++++ .../modules/core/repositories/userEmails.ts | 9 + .../graph/generated/graphql.ts | 57 +++ .../modules/shared/services/eventBus.ts | 2 +- .../modules/shared/test/unit/eventBus.spec.ts | 14 +- .../modules/workspaces/domain/operations.ts | 25 +- .../modules/workspaces/errors/workspace.ts | 36 ++ .../graph/dataloaders/workspaces.ts | 23 +- .../workspaces/graph/mocks/workspaces.ts | 21 +- .../workspaces/graph/resolvers/workspaces.ts | 95 +++- .../workspaces/helpers/blockedDomains.ts | 130 +++++ .../server/modules/workspaces/helpers/db.ts | 14 +- packages/server/modules/workspaces/index.ts | 4 + .../workspaces/repositories/workspaces.ts | 84 +++- .../modules/workspaces/services/invites.ts | 30 +- .../modules/workspaces/services/join.ts | 55 ++ .../modules/workspaces/services/management.ts | 138 ++++- .../modules/workspaces/services/retrieval.ts | 31 ++ .../workspaces/tests/helpers/creation.ts | 44 +- .../tests/integration/invites.graph.spec.ts | 177 +++++-- .../tests/integration/repositories.spec.ts | 368 +++++++++++++- .../integration/workspaces.graph.spec.ts | 17 +- .../tests/unit/services/join.spec.ts | 138 +++++ .../tests/unit/services/management.spec.ts | 474 +++++++++++++++++- .../modules/workspacesCore/domain/events.ts | 5 +- .../modules/workspacesCore/domain/types.ts | 13 + .../graph/resolvers/workspacesCore.ts | 15 + .../20240806160740_workspace_domains.ts | 20 + ..._column_domainBasedMembershipProtection.ts | 13 + ...0808091944_add_workspace_discovery_flag.ts | 13 + .../server/test/graphql/generated/graphql.ts | 63 +++ packages/server/test/graphql/workspaces.ts | 12 + workspace.code-workspace | 2 +- 54 files changed, 3142 insertions(+), 135 deletions(-) create mode 100644 packages/frontend-2/components/form/select/WorkspaceDomains.vue create mode 100644 packages/frontend-2/components/settings/workspaces/Security.vue create mode 100644 packages/frontend-2/components/settings/workspaces/security/DomainAddDialog.vue create mode 100644 packages/frontend-2/components/settings/workspaces/security/DomainRemoveDialog.vue create mode 100644 packages/frontend-2/components/workspace/invite/DiscoverableWorkspaceBanner.vue create mode 100644 packages/frontend-2/lib/dashboard/graphql/mutations.ts create mode 100644 packages/server/modules/workspaces/helpers/blockedDomains.ts create mode 100644 packages/server/modules/workspaces/services/join.ts create mode 100644 packages/server/modules/workspaces/tests/unit/services/join.spec.ts create mode 100644 packages/server/modules/workspacesCore/migrations/20240806160740_workspace_domains.ts create mode 100644 packages/server/modules/workspacesCore/migrations/20240807174901_add_column_domainBasedMembershipProtection.ts create mode 100644 packages/server/modules/workspacesCore/migrations/20240808091944_add_workspace_discovery_flag.ts diff --git a/packages/dui3/lib/common/generated/gql/graphql.ts b/packages/dui3/lib/common/generated/gql/graphql.ts index d0e6d09da..3cb87ca38 100644 --- a/packages/dui3/lib/common/generated/gql/graphql.ts +++ b/packages/dui3/lib/common/generated/gql/graphql.ts @@ -29,6 +29,7 @@ export type ActiveUserMutations = { finishOnboarding: Scalars['Boolean']['output']; /** Edit a user's profile */ update: User; + workspaceMutations?: Maybe; }; @@ -56,6 +57,11 @@ export type ActivityCollection = { totalCount: Scalars['Int']['output']; }; +export type AddDomainToWorkspaceInput = { + domain: Scalars['String']['input']; + workspaceId: Scalars['ID']['input']; +}; + export type AdminInviteList = { __typename?: 'AdminInviteList'; cursor?: Maybe; @@ -843,6 +849,13 @@ export type DiscoverableStreamsSortingInput = { type: DiscoverableStreamsSortType; }; +export type DiscoverableWorkspace = { + __typename?: 'DiscoverableWorkspace'; + description?: Maybe; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; +}; + export type EditCommentInput = { commentId: Scalars['String']['input']; content: CommentContentInput; @@ -3365,6 +3378,8 @@ export type User = { /** Returns the apps you have created. */ createdApps?: Maybe>; createdAt?: Maybe; + /** Get discoverable workspaces with verified domains that match the active user's */ + discoverableWorkspaces: Array; /** Only returned if API user is the user being requested or an admin */ email?: Maybe; emails: Array; @@ -4030,4 +4045,4 @@ export type AcccountTestQueryQueryVariables = Exact<{ [key: string]: never; }>; export type AcccountTestQueryQuery = { __typename?: 'Query', serverInfo: { __typename?: 'ServerInfo', version?: string | null, name: string, company?: string | null } }; -export const AcccountTestQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AcccountTestQuery"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"company"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const AcccountTestQueryDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "AcccountTestQuery" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "serverInfo" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "version" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "company" } }] } }] } }] } as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/frontend-2/components/form/select/WorkspaceDomains.vue b/packages/frontend-2/components/form/select/WorkspaceDomains.vue new file mode 100644 index 000000000..27c1ef246 --- /dev/null +++ b/packages/frontend-2/components/form/select/WorkspaceDomains.vue @@ -0,0 +1,42 @@ + + + diff --git a/packages/frontend-2/components/invite/Banner.vue b/packages/frontend-2/components/invite/Banner.vue index d6edc8341..8d5122c76 100644 --- a/packages/frontend-2/components/invite/Banner.vue +++ b/packages/frontend-2/components/invite/Banner.vue @@ -1,7 +1,12 @@