e6e65a2f7d
* feat(workspaces): add workspace sso feature flag * feat(workspaceSso): wip validate sso * feat(workspaces): validate and add sso provider to the workspace with user sso sessions * feat(workspaces): validate and add sso provider to the workspace with user sso sessions * WIP * fix(sso): restructure to handle all branches at end of flow * fix(sso): add and validate emails used for sso * fix(sso): park progress * chore(workspaces): review sso login/valdate * fix(sso): adjust validate url * chore(sso): auth header puzzle * fix(sso): happy-path config * chore(gql): gqlgen * fix(sso): almost almost * fix(sso): auth endpoint * a lil more terse * fix(sso): light at the end of the tunnel * fix(sso): improve catch block error messages * fix(sso): session lifespan => validUntil * fix(sso): I think we've got it * feat(sso): limited workspace values for public sso login * fix(sso): use factory functions * fix(sso): til decrypt is single-use * fix(sso): correct usage of access codes * fix(sso): use finalize middleware in all routes * chore(sso): cheeky tweak * fix(sso): move some types around * fix(sso): stencil final shape I'm sleepy * fix(sso): more factories more factories * fix(sso): on to final boss of factories * fix(sso): needs a haircut but she works * fix(sso): init rest w function, not side-effects * fix(sso): /authn => /sso * chore(sso): errors * chore(sso): test test test * chore(sso): test all the corners * feat(sso): list workspace sso memberships * chore(sso): tests, expose in rest * fix(sso): expose search via gql --------- Co-authored-by: Gergő Jedlicska <gergo@jedlicska.com> Co-authored-by: Mike Tasset <mike.tasset@gmail.com>
81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
import { UserEmail } from '@/modules/core/domain/userEmails/types'
|
|
import {
|
|
WorkspaceDomainsInvalidState,
|
|
WorkspaceInvalidUpdateError
|
|
} from '@/modules/workspaces/errors/workspace'
|
|
import {
|
|
LimitedWorkspace,
|
|
Workspace,
|
|
WorkspaceDefaultProjectRole,
|
|
WorkspaceDomain
|
|
} from '@/modules/workspacesCore/domain/types'
|
|
import { Roles, WorkspaceRoles } from '@speckle/shared'
|
|
import { pick } from 'lodash'
|
|
|
|
export const userEmailsCompliantWithWorkspaceDomains = ({
|
|
userEmails,
|
|
workspaceDomains
|
|
}: {
|
|
userEmails: UserEmail[]
|
|
workspaceDomains: WorkspaceDomain[]
|
|
}): boolean =>
|
|
anyEmailCompliantWithWorkspaceDomains({
|
|
emails: userEmails.filter((e) => e.verified).map((e) => e.email),
|
|
workspaceDomains
|
|
})
|
|
|
|
export const anyEmailCompliantWithWorkspaceDomains = ({
|
|
emails,
|
|
workspaceDomains
|
|
}: {
|
|
emails: string[]
|
|
workspaceDomains: WorkspaceDomain[]
|
|
}): boolean => {
|
|
const validWorkspaceDomains = workspaceDomains.filter((domain) => domain.verified)
|
|
|
|
// we must have min 1 domain to validate compliance
|
|
if (!validWorkspaceDomains.length) throw new WorkspaceDomainsInvalidState()
|
|
|
|
for (const email of emails) {
|
|
if (validWorkspaceDomains.some((domain) => email.endsWith(domain.domain)))
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Given an optional string value, assert it is a valid default project role and return it.
|
|
*/
|
|
export const parseDefaultProjectRole = (
|
|
role?: string | null
|
|
): WorkspaceDefaultProjectRole | null => {
|
|
if (!role) return null
|
|
|
|
const isValidRole = (role: string): role is WorkspaceDefaultProjectRole => {
|
|
const validRoles: string[] = [Roles.Stream.Reviewer, Roles.Stream.Contributor]
|
|
return validRoles.includes(role)
|
|
}
|
|
|
|
if (!isValidRole(role)) {
|
|
throw new WorkspaceInvalidUpdateError('Provided default project role is invalid')
|
|
}
|
|
|
|
return role
|
|
}
|
|
|
|
export const isWorkspaceRole = (role: string): role is WorkspaceRoles => {
|
|
const validRoles: string[] = Object.values(Roles.Workspace)
|
|
return validRoles.includes(role)
|
|
}
|
|
|
|
export const toLimitedWorkspace = (workspace: Workspace): LimitedWorkspace => {
|
|
return pick(workspace, [
|
|
'id',
|
|
'slug',
|
|
'name',
|
|
'description',
|
|
'logo',
|
|
'defaultLogoIndex'
|
|
])
|
|
}
|