3b47774a9a
* chore(server): auth IoC 19 - setupStrategiesFactory * chore(server): auth typescript cleanup
126 lines
4.0 KiB
TypeScript
126 lines
4.0 KiB
TypeScript
import { ForbiddenError } from '@/modules/shared/errors'
|
|
import { isNullOrUndefined, isScope, Roles } from '@speckle/shared'
|
|
import {
|
|
getAppFactory,
|
|
getAllPublicAppsFactory,
|
|
getAllAppsCreatedByUserFactory,
|
|
getAllAppsAuthorizedByUserFactory,
|
|
createAppFactory,
|
|
updateAppFactory,
|
|
deleteAppFactory,
|
|
revokeExistingAppCredentialsForUserFactory
|
|
} from '@/modules/auth/repositories/apps'
|
|
import { db } from '@/db/knex'
|
|
import { Resolvers } from '@/modules/core/graph/generated/graphql'
|
|
|
|
const getApp = getAppFactory({ db })
|
|
const getAllPublicApps = getAllPublicAppsFactory({ db })
|
|
const getAllAppsCreatedByUser = getAllAppsCreatedByUserFactory({ db })
|
|
const getAllAppsAuthorizedByUser = getAllAppsAuthorizedByUserFactory({ db })
|
|
const createApp = createAppFactory({ db })
|
|
const updateApp = updateAppFactory({ db })
|
|
const deleteApp = deleteAppFactory({ db })
|
|
const revokeExistingAppCredentialsForUser = revokeExistingAppCredentialsForUserFactory({
|
|
db
|
|
})
|
|
|
|
export = {
|
|
Query: {
|
|
async app(_parent, args) {
|
|
const app = await getApp({ id: args.id })
|
|
return app
|
|
},
|
|
|
|
async apps() {
|
|
return await getAllPublicApps()
|
|
}
|
|
},
|
|
|
|
ServerApp: {
|
|
secret(parent, _args, context) {
|
|
if (
|
|
context.auth &&
|
|
parent.author &&
|
|
parent.author.id &&
|
|
parent.author.id === context.userId
|
|
)
|
|
return parent.secret
|
|
|
|
return 'App secrets are only revealed to their author 😉'
|
|
},
|
|
async scopes(parent, _args, context) {
|
|
if ('scopes' in parent && parent.scopes?.length) return parent.scopes
|
|
return await context.loaders.apps.getAppScopes.load(parent.id)
|
|
}
|
|
},
|
|
|
|
User: {
|
|
async authorizedApps(_parent, _args, context) {
|
|
const res = await getAllAppsAuthorizedByUser({ userId: context.userId! })
|
|
return res
|
|
},
|
|
async createdApps(_parent, _args, context) {
|
|
return await getAllAppsCreatedByUser({ userId: context.userId! })
|
|
}
|
|
},
|
|
Mutation: {
|
|
async appCreate(_parent, args, context) {
|
|
const { id } = await createApp({
|
|
...args.app,
|
|
authorId: context.userId!,
|
|
public: isNullOrUndefined(args.app.public) ? undefined : args.app.public,
|
|
scopes: args.app.scopes.filter(isScope)
|
|
})
|
|
return id
|
|
},
|
|
|
|
async appUpdate(_parent, args, context) {
|
|
const app = await getApp({ id: args.app.id })
|
|
if (!app) {
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
}
|
|
|
|
// only admins can update the default apps, generated by the server
|
|
if (!app?.author && context.role !== Roles.Server.Admin)
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
|
|
// only the author or an admin can update a 3rd party app
|
|
if (app?.author?.id !== context.userId && context.role !== Roles.Server.Admin)
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
|
|
await updateApp({
|
|
app: {
|
|
...args.app,
|
|
public: isNullOrUndefined(args.app.public) ? undefined : args.app.public,
|
|
scopes: args.app.scopes.filter(isScope)
|
|
}
|
|
})
|
|
return true
|
|
},
|
|
|
|
async appDelete(_parent, args, context) {
|
|
const app = await getApp({ id: args.appId })
|
|
if (!app) {
|
|
//Possibly ould have been an UserInputError, but
|
|
//we do not want to leak the existence of any app
|
|
//the user may not own or have access to.
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
}
|
|
|
|
if (!app.author && context.role !== Roles.Server.Admin)
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
if (app.author?.id !== context.userId && context.role !== Roles.Server.Admin)
|
|
throw new ForbiddenError('You are not authorized to edit this app.')
|
|
|
|
return (await deleteApp({ id: args.appId })) === 1
|
|
},
|
|
|
|
async appRevokeAccess(_parent, args, context) {
|
|
return !!(await revokeExistingAppCredentialsForUser({
|
|
appId: args.appId,
|
|
userId: context.userId!
|
|
}))
|
|
}
|
|
}
|
|
} as Resolvers
|