auth IoC 1 - initializeDefaultAppsFactory
This commit is contained in:
Родитель
9992a9bd1d
Коммит
68376b91c1
|
@ -4,6 +4,8 @@ import {
|
||||||
getServerOrigin,
|
getServerOrigin,
|
||||||
getFeatureFlags
|
getFeatureFlags
|
||||||
} from '@/modules/shared/helpers/envHelper'
|
} from '@/modules/shared/helpers/envHelper'
|
||||||
|
import { ServerScope } from '@speckle/shared'
|
||||||
|
import { Merge } from 'type-fest'
|
||||||
|
|
||||||
export enum DefaultAppIds {
|
export enum DefaultAppIds {
|
||||||
Web = 'spklwebapp',
|
Web = 'spklwebapp',
|
||||||
|
@ -150,3 +152,10 @@ export function getDefaultApps() {
|
||||||
export function getDefaultApp({ id }: { id: string }) {
|
export function getDefaultApp({ id }: { id: string }) {
|
||||||
return defaultApps.find((app) => app.id === id) || null
|
return defaultApps.find((app) => app.id === id) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DefaultApp = (typeof defaultApps)[number]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some workflows need 'all' unwrapped into the actual scopes
|
||||||
|
*/
|
||||||
|
export type DefaultAppWithUnwrappedScopes = Merge<DefaultApp, { scopes: ServerScope[] }>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { DefaultAppWithUnwrappedScopes } from '@/modules/auth/defaultApps'
|
||||||
|
import { FullServerApp } from '@/modules/auth/domain/types'
|
||||||
|
import { ScopeRecord } from '@/modules/auth/helpers/types'
|
||||||
|
|
||||||
|
export type GetApp = (params: { id: string }) => Promise<FullServerApp | null>
|
||||||
|
|
||||||
|
export type GetAllScopes = () => Promise<ScopeRecord[]>
|
||||||
|
|
||||||
|
export type RegisterDefaultApp = (app: DefaultAppWithUnwrappedScopes) => Promise<void>
|
||||||
|
|
||||||
|
export type UpdateDefaultApp = (
|
||||||
|
app: DefaultAppWithUnwrappedScopes,
|
||||||
|
existingApp: FullServerApp
|
||||||
|
) => Promise<void>
|
||||||
|
|
||||||
|
export type InitializeDefaultApps = () => Promise<void>
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { ScopeRecord } from '@/modules/auth/helpers/types'
|
||||||
|
import { ServerAppRecord, UserRecord } from '@/modules/core/helpers/types'
|
||||||
|
|
||||||
|
export type FullServerApp = ServerAppRecord & {
|
||||||
|
scopes: ScopeRecord[]
|
||||||
|
author: Pick<UserRecord, 'id' | 'name' | 'avatar'>
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||||
const {
|
const {
|
||||||
getApp,
|
|
||||||
getAllPublicApps,
|
getAllPublicApps,
|
||||||
getAllAppsCreatedByUser,
|
getAllAppsCreatedByUser,
|
||||||
getAllAppsAuthorizedByUser,
|
getAllAppsAuthorizedByUser,
|
||||||
|
@ -10,6 +9,10 @@ const {
|
||||||
revokeExistingAppCredentialsForUser
|
revokeExistingAppCredentialsForUser
|
||||||
} = require('../../services/apps')
|
} = require('../../services/apps')
|
||||||
const { Roles } = require('@speckle/shared')
|
const { Roles } = require('@speckle/shared')
|
||||||
|
const { getAppFactory } = require('@/modules/auth/repositories/apps')
|
||||||
|
const { db } = require('@/db/knex')
|
||||||
|
|
||||||
|
const getApp = getAppFactory({ db })
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Query: {
|
Query: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { MaybeAsync } from '@speckle/shared'
|
import { MaybeAsync, ServerScope } from '@speckle/shared'
|
||||||
import type { Express, RequestHandler } from 'express'
|
import type { Express, RequestHandler } from 'express'
|
||||||
import type { Session, SessionData } from 'express-session'
|
import type { Session, SessionData } from 'express-session'
|
||||||
import type { TokenSet, UserinfoResponse } from 'openid-client'
|
import type { TokenSet, UserinfoResponse } from 'openid-client'
|
||||||
|
@ -51,9 +51,26 @@ export type AuthRequestData = {
|
||||||
authRedirectPath?: string
|
authRedirectPath?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ScopeRecord = {
|
||||||
|
name: ServerScope
|
||||||
|
description: string
|
||||||
|
public: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export type ServerAppsScopesRecord = {
|
export type ServerAppsScopesRecord = {
|
||||||
appId: string
|
appId: string
|
||||||
scopeName: string
|
scopeName: ServerScope
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserServerAppTokenRecord = {
|
||||||
|
userId: string
|
||||||
|
appId: string
|
||||||
|
tokenId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TokenScopeRecord = {
|
||||||
|
tokenId: string
|
||||||
|
scopeName: ServerScope
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AuthStrategyMetadata = {
|
export type AuthStrategyMetadata = {
|
||||||
|
|
|
@ -2,6 +2,20 @@
|
||||||
const { registerOrUpdateScopeFactory } = require('@/modules/shared/repositories/scopes')
|
const { registerOrUpdateScopeFactory } = require('@/modules/shared/repositories/scopes')
|
||||||
const { moduleLogger } = require('@/logging/logging')
|
const { moduleLogger } = require('@/logging/logging')
|
||||||
const db = require('@/db/knex')
|
const db = require('@/db/knex')
|
||||||
|
const { initializeDefaultAppsFactory } = require('@/modules/auth/services/serverApps')
|
||||||
|
const {
|
||||||
|
getAllScopesFactory,
|
||||||
|
getAppFactory,
|
||||||
|
updateDefaultAppFactory,
|
||||||
|
registerDefaultAppFactory
|
||||||
|
} = require('@/modules/auth/repositories/apps')
|
||||||
|
|
||||||
|
const initializeDefaultApps = initializeDefaultAppsFactory({
|
||||||
|
getAllScopes: getAllScopesFactory({ db }),
|
||||||
|
getApp: getAppFactory({ db }),
|
||||||
|
updateDefaultApp: updateDefaultAppFactory({ db }),
|
||||||
|
registerDefaultApp: registerDefaultAppFactory({ db })
|
||||||
|
})
|
||||||
|
|
||||||
exports.init = async (app) => {
|
exports.init = async (app) => {
|
||||||
moduleLogger.info('🔑 Init auth module')
|
moduleLogger.info('🔑 Init auth module')
|
||||||
|
@ -23,5 +37,5 @@ exports.init = async (app) => {
|
||||||
exports.finalize = async () => {
|
exports.finalize = async () => {
|
||||||
// Note: we're registering the default apps last as we want to ensure that all
|
// Note: we're registering the default apps last as we want to ensure that all
|
||||||
// scopes have been registered by any other modules.
|
// scopes have been registered by any other modules.
|
||||||
await require('./manageDefaultApps')()
|
await initializeDefaultApps()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
'use strict'
|
|
||||||
const knex = require('@/db/knex')
|
|
||||||
const Scopes = () => knex('scopes')
|
|
||||||
const Apps = () => knex('server_apps')
|
|
||||||
const AppScopes = () => knex('server_apps_scopes')
|
|
||||||
|
|
||||||
const { getApp } = require('@/modules/auth/services/apps')
|
|
||||||
const { difference } = require('lodash')
|
|
||||||
const { moduleLogger } = require('@/logging/logging')
|
|
||||||
const { getDefaultApps } = require('@/modules/auth/defaultApps')
|
|
||||||
|
|
||||||
let allScopes = []
|
|
||||||
|
|
||||||
module.exports = async () => {
|
|
||||||
allScopes = await Scopes().select('*')
|
|
||||||
|
|
||||||
// Note: shallow cloning of app objs so as to not interfere with the original objects.
|
|
||||||
await Promise.all(getDefaultApps().map((app) => registerOrUpdateApp({ ...app })))
|
|
||||||
}
|
|
||||||
|
|
||||||
async function registerOrUpdateApp(app) {
|
|
||||||
if (app.scopes && app.scopes === 'all') {
|
|
||||||
// let scopes = await Scopes( ).select( '*' )
|
|
||||||
// logger.debug( allScopes.length )
|
|
||||||
app.scopes = allScopes.map((s) => s.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingApp = await getApp({ id: app.id })
|
|
||||||
if (existingApp) {
|
|
||||||
updateDefaultApp(app, existingApp)
|
|
||||||
} else {
|
|
||||||
await registerDefaultApp(app)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function registerDefaultApp(app) {
|
|
||||||
const scopes = app.scopes.map((s) => ({ appId: app.id, scopeName: s }))
|
|
||||||
delete app.scopes
|
|
||||||
await Apps().insert(app)
|
|
||||||
await AppScopes().insert(scopes)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateDefaultApp(app, existingApp) {
|
|
||||||
const existingAppScopes = existingApp.scopes.map((s) => s.name)
|
|
||||||
|
|
||||||
const newScopes = difference(app.scopes, existingAppScopes)
|
|
||||||
const removedScopes = difference(existingAppScopes, app.scopes)
|
|
||||||
|
|
||||||
let affectedTokenIds = []
|
|
||||||
|
|
||||||
if (newScopes.length || removedScopes.length) {
|
|
||||||
moduleLogger.info(`🔑 Updating default app ${app.name}`)
|
|
||||||
affectedTokenIds = await knex('user_server_app_tokens')
|
|
||||||
.where({ appId: app.id })
|
|
||||||
.pluck('tokenId')
|
|
||||||
}
|
|
||||||
|
|
||||||
// the internal code block makes sure if an error occurred, the trx gets rolled back
|
|
||||||
await knex.transaction(async (trx) => {
|
|
||||||
// add new scopes to the app
|
|
||||||
if (newScopes.length)
|
|
||||||
await AppScopes()
|
|
||||||
.insert(newScopes.map((s) => ({ appId: app.id, scopeName: s })))
|
|
||||||
.transacting(trx)
|
|
||||||
|
|
||||||
// remove scopes from the app
|
|
||||||
if (removedScopes.length)
|
|
||||||
await AppScopes()
|
|
||||||
.where({ appId: app.id })
|
|
||||||
.whereIn('scopeName', removedScopes)
|
|
||||||
.delete()
|
|
||||||
.transacting(trx)
|
|
||||||
|
|
||||||
//update user tokens with scope changes
|
|
||||||
if (affectedTokenIds.length)
|
|
||||||
await Promise.all(
|
|
||||||
affectedTokenIds.map(async (tokenId) => {
|
|
||||||
if (newScopes.length)
|
|
||||||
await knex('token_scopes')
|
|
||||||
.insert(newScopes.map((s) => ({ tokenId, scopeName: s })))
|
|
||||||
.transacting(trx)
|
|
||||||
|
|
||||||
if (removedScopes.length)
|
|
||||||
await knex('token_scopes')
|
|
||||||
.where({ tokenId })
|
|
||||||
.whereIn('scopeName', removedScopes)
|
|
||||||
.delete()
|
|
||||||
.transacting(trx)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
delete app.scopes
|
|
||||||
// not writing the redirect url to the DB anymore
|
|
||||||
// it will be patched on an application level from the default app definitions
|
|
||||||
delete app.redirectUrl
|
|
||||||
await Apps().where({ id: app.id }).update(app).transacting(trx)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is exported to be able to test the retention of permissions
|
|
||||||
module.exports.updateDefaultApp = updateDefaultApp
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
import { moduleLogger } from '@/logging/logging'
|
||||||
|
import { getDefaultApp } from '@/modules/auth/defaultApps'
|
||||||
|
import {
|
||||||
|
GetAllScopes,
|
||||||
|
GetApp,
|
||||||
|
RegisterDefaultApp,
|
||||||
|
UpdateDefaultApp
|
||||||
|
} from '@/modules/auth/domain/operations'
|
||||||
|
import {
|
||||||
|
ScopeRecord,
|
||||||
|
ServerAppsScopesRecord,
|
||||||
|
TokenScopeRecord,
|
||||||
|
UserServerAppTokenRecord
|
||||||
|
} from '@/modules/auth/helpers/types'
|
||||||
|
import {
|
||||||
|
Scopes,
|
||||||
|
ServerApps,
|
||||||
|
ServerAppsScopes,
|
||||||
|
TokenScopes,
|
||||||
|
Users,
|
||||||
|
UserServerAppTokens
|
||||||
|
} from '@/modules/core/dbSchema'
|
||||||
|
import { ServerAppRecord, UserRecord } from '@/modules/core/helpers/types'
|
||||||
|
import { Knex } from 'knex'
|
||||||
|
import { difference, omit } from 'lodash'
|
||||||
|
|
||||||
|
const tables = {
|
||||||
|
serverApps: (db: Knex) => db<ServerAppRecord>(ServerApps.name),
|
||||||
|
scopes: (db: Knex) => db<ScopeRecord>(Scopes.name),
|
||||||
|
serverAppsScopes: (db: Knex) => db<ServerAppsScopesRecord>(ServerAppsScopes.name),
|
||||||
|
users: (db: Knex) => db<UserRecord>(Users.name),
|
||||||
|
userServerAppTokens: (db: Knex) =>
|
||||||
|
db<UserServerAppTokenRecord>(UserServerAppTokens.name),
|
||||||
|
tokenScopes: (db: Knex) => db<TokenScopeRecord>(TokenScopes.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getAppRedirectUrl = (app: ServerAppRecord) => {
|
||||||
|
const defaultApp = getDefaultApp({ id: app.id })
|
||||||
|
return defaultApp ? defaultApp.redirectUrl : app.redirectUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAppFactory =
|
||||||
|
(deps: { db: Knex }): GetApp =>
|
||||||
|
async (params) => {
|
||||||
|
const { id } = params
|
||||||
|
|
||||||
|
const allScopes = await getAllScopesFactory(deps)()
|
||||||
|
|
||||||
|
const app = await tables.serverApps(deps.db).select('*').where({ id }).first()
|
||||||
|
if (!app) return null
|
||||||
|
|
||||||
|
const appScopeNames = (
|
||||||
|
await tables.serverAppsScopes(deps.db).select('scopeName').where({ appId: id })
|
||||||
|
).map((s) => s.scopeName)
|
||||||
|
|
||||||
|
const appScopes = allScopes.filter(
|
||||||
|
(scope) => appScopeNames.indexOf(scope.name) !== -1
|
||||||
|
)
|
||||||
|
const appAuthor = await tables
|
||||||
|
.users(deps.db)
|
||||||
|
.select('id', 'name', 'avatar')
|
||||||
|
.where({ id: app.authorId })
|
||||||
|
.first()
|
||||||
|
|
||||||
|
return {
|
||||||
|
...app,
|
||||||
|
scopes: appScopes,
|
||||||
|
author: appAuthor!,
|
||||||
|
redirectUrl: getAppRedirectUrl(app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAllScopesFactory =
|
||||||
|
(deps: { db: Knex }): GetAllScopes =>
|
||||||
|
async () => {
|
||||||
|
return tables.scopes(deps.db).select('*')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const registerDefaultAppFactory =
|
||||||
|
(deps: { db: Knex }): RegisterDefaultApp =>
|
||||||
|
async (app) => {
|
||||||
|
const scopes = app.scopes.map((s) => ({ appId: app.id, scopeName: s }))
|
||||||
|
|
||||||
|
await tables.serverApps(deps.db).insert(omit(app, 'scopes'))
|
||||||
|
await tables.serverAppsScopes(deps.db).insert(scopes)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateDefaultAppFactory =
|
||||||
|
(deps: { db: Knex }): UpdateDefaultApp =>
|
||||||
|
async (app, existingApp) => {
|
||||||
|
const { db: knex } = deps
|
||||||
|
|
||||||
|
const existingAppScopes = existingApp.scopes.map((s) => s.name)
|
||||||
|
|
||||||
|
const newScopes = difference(app.scopes, existingAppScopes)
|
||||||
|
const removedScopes = difference(existingAppScopes, app.scopes)
|
||||||
|
|
||||||
|
let affectedTokenIds: string[] = []
|
||||||
|
|
||||||
|
if (newScopes.length || removedScopes.length) {
|
||||||
|
moduleLogger.info(`🔑 Updating default app ${app.name}`)
|
||||||
|
affectedTokenIds = await tables
|
||||||
|
.userServerAppTokens(knex)
|
||||||
|
.where({ appId: app.id })
|
||||||
|
.pluck('tokenId')
|
||||||
|
}
|
||||||
|
|
||||||
|
// the internal code block makes sure if an error occurred, the trx gets rolled back
|
||||||
|
await knex.transaction(async (trx) => {
|
||||||
|
// add new scopes to the app
|
||||||
|
if (newScopes.length)
|
||||||
|
await tables
|
||||||
|
.serverAppsScopes(knex)
|
||||||
|
.insert(newScopes.map((s) => ({ appId: app.id, scopeName: s })))
|
||||||
|
.transacting(trx)
|
||||||
|
|
||||||
|
// remove scopes from the app
|
||||||
|
if (removedScopes.length)
|
||||||
|
await tables
|
||||||
|
.serverAppsScopes(knex)
|
||||||
|
.where({ appId: app.id })
|
||||||
|
.whereIn('scopeName', removedScopes)
|
||||||
|
.delete()
|
||||||
|
.transacting(trx)
|
||||||
|
|
||||||
|
//update user tokens with scope changes
|
||||||
|
if (affectedTokenIds.length)
|
||||||
|
await Promise.all(
|
||||||
|
affectedTokenIds.map(async (tokenId) => {
|
||||||
|
if (newScopes.length)
|
||||||
|
await tables
|
||||||
|
.tokenScopes(knex)
|
||||||
|
.insert(newScopes.map((s) => ({ tokenId, scopeName: s })))
|
||||||
|
.transacting(trx)
|
||||||
|
|
||||||
|
if (removedScopes.length)
|
||||||
|
await tables
|
||||||
|
.tokenScopes(knex)
|
||||||
|
.where({ tokenId })
|
||||||
|
.whereIn('scopeName', removedScopes)
|
||||||
|
.delete()
|
||||||
|
.transacting(trx)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// not writing the redirect url to the DB anymore
|
||||||
|
// it will be patched on an application level from the default app definitions
|
||||||
|
await tables
|
||||||
|
.serverApps(knex)
|
||||||
|
.where({ id: app.id })
|
||||||
|
.update(omit(app, ['scopes', 'redirectUrl']))
|
||||||
|
.transacting(trx)
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
const cors = require('cors')
|
const cors = require('cors')
|
||||||
const {
|
const {
|
||||||
getApp,
|
|
||||||
createAuthorizationCode,
|
createAuthorizationCode,
|
||||||
createAppTokenFromAccessCode,
|
createAppTokenFromAccessCode,
|
||||||
refreshAppToken
|
refreshAppToken
|
||||||
|
@ -12,6 +11,8 @@ const { validateScopes } = require(`@/modules/shared`)
|
||||||
const { InvalidAccessCodeRequestError } = require('@/modules/auth/errors')
|
const { InvalidAccessCodeRequestError } = require('@/modules/auth/errors')
|
||||||
const { Scopes } = require('@speckle/shared')
|
const { Scopes } = require('@speckle/shared')
|
||||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||||
|
const { getAppFactory } = require('@/modules/auth/repositories/apps')
|
||||||
|
const { db } = require('@/db/knex')
|
||||||
|
|
||||||
// TODO: Secure these endpoints!
|
// TODO: Secure these endpoints!
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
|
@ -21,6 +22,7 @@ module.exports = (app) => {
|
||||||
*/
|
*/
|
||||||
app.get('/auth/accesscode', async (req, res) => {
|
app.get('/auth/accesscode', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
const getApp = getAppFactory({ db })
|
||||||
const preventRedirect = !!req.query.preventRedirect
|
const preventRedirect = !!req.query.preventRedirect
|
||||||
const appId = req.query.appId
|
const appId = req.query.appId
|
||||||
const app = await getApp({ id: appId })
|
const app = await getApp({ id: appId })
|
||||||
|
|
|
@ -6,11 +6,10 @@ const knex = require(`@/db/knex`)
|
||||||
const { createBareToken, createAppToken } = require(`@/modules/core/services/tokens`)
|
const { createBareToken, createAppToken } = require(`@/modules/core/services/tokens`)
|
||||||
const { logger } = require('@/logging/logging')
|
const { logger } = require('@/logging/logging')
|
||||||
const { getDefaultApp } = require('@/modules/auth/defaultApps')
|
const { getDefaultApp } = require('@/modules/auth/defaultApps')
|
||||||
const Users = () => knex('users')
|
const { getAppFactory } = require('@/modules/auth/repositories/apps')
|
||||||
const ApiTokens = () => knex('api_tokens')
|
const ApiTokens = () => knex('api_tokens')
|
||||||
const ServerApps = () => knex('server_apps')
|
const ServerApps = () => knex('server_apps')
|
||||||
const ServerAppsScopes = () => knex('server_apps_scopes')
|
const ServerAppsScopes = () => knex('server_apps_scopes')
|
||||||
const Scopes = () => knex('scopes')
|
|
||||||
|
|
||||||
const AuthorizationCodes = () => knex('authorization_codes')
|
const AuthorizationCodes = () => knex('authorization_codes')
|
||||||
const RefreshTokens = () => knex('refresh_tokens')
|
const RefreshTokens = () => knex('refresh_tokens')
|
||||||
|
@ -22,25 +21,6 @@ const addDefaultAppOverrides = (app) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async getApp({ id }) {
|
|
||||||
const allScopes = await Scopes().select('*')
|
|
||||||
|
|
||||||
const app = await ServerApps().select('*').where({ id }).first()
|
|
||||||
if (!app) return null
|
|
||||||
|
|
||||||
const appScopeNames = (
|
|
||||||
await ServerAppsScopes().select('scopeName').where({ appId: id })
|
|
||||||
).map((s) => s.scopeName)
|
|
||||||
|
|
||||||
app.scopes = allScopes.filter((scope) => appScopeNames.indexOf(scope.name) !== -1)
|
|
||||||
app.author = await Users()
|
|
||||||
.select('id', 'name', 'avatar')
|
|
||||||
.where({ id: app.authorId })
|
|
||||||
.first()
|
|
||||||
|
|
||||||
return addDefaultAppOverrides(app)
|
|
||||||
},
|
|
||||||
|
|
||||||
async getAllPublicApps() {
|
async getAllPublicApps() {
|
||||||
const apps = await ServerApps()
|
const apps = await ServerApps()
|
||||||
.select(
|
.select(
|
||||||
|
@ -288,8 +268,8 @@ module.exports = {
|
||||||
const valid = await bcrypt.compare(refreshTokenContent, refreshTokenDb.tokenDigest)
|
const valid = await bcrypt.compare(refreshTokenContent, refreshTokenDb.tokenDigest)
|
||||||
if (!valid) throw new Error('Invalid token') // sneky hackstors
|
if (!valid) throw new Error('Invalid token') // sneky hackstors
|
||||||
|
|
||||||
const app = await module.exports.getApp({ id: appId })
|
const app = await getAppFactory({ db: knex })({ id: appId })
|
||||||
if (app.secret !== appSecret) throw new Error('Invalid request')
|
if (!app || app.secret !== appSecret) throw new Error('Invalid request')
|
||||||
|
|
||||||
// Create the new token
|
// Create the new token
|
||||||
const appToken = await createAppToken({
|
const appToken = await createAppToken({
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { getDefaultApps } from '@/modules/auth/defaultApps'
|
||||||
|
import {
|
||||||
|
GetAllScopes,
|
||||||
|
GetApp,
|
||||||
|
InitializeDefaultApps,
|
||||||
|
RegisterDefaultApp,
|
||||||
|
UpdateDefaultApp
|
||||||
|
} from '@/modules/auth/domain/operations'
|
||||||
|
import { ScopeRecord } from '@/modules/auth/helpers/types'
|
||||||
|
import { ServerScope } from '@speckle/shared'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached all scopes. Caching occurs on first initializeDefaultApps() call
|
||||||
|
*/
|
||||||
|
let allScopes: ScopeRecord[] = []
|
||||||
|
|
||||||
|
export const initializeDefaultAppsFactory =
|
||||||
|
(deps: {
|
||||||
|
getAllScopes: GetAllScopes
|
||||||
|
getApp: GetApp
|
||||||
|
updateDefaultApp: UpdateDefaultApp
|
||||||
|
registerDefaultApp: RegisterDefaultApp
|
||||||
|
}): InitializeDefaultApps =>
|
||||||
|
async () => {
|
||||||
|
allScopes = await deps.getAllScopes()
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
getDefaultApps().map(async (app) => {
|
||||||
|
const scopes =
|
||||||
|
app?.scopes === 'all'
|
||||||
|
? allScopes.map((s) => s.name)
|
||||||
|
: (app.scopes as ServerScope[])
|
||||||
|
|
||||||
|
const existingApp = await deps.getApp({ id: app.id })
|
||||||
|
if (existingApp) {
|
||||||
|
await deps.updateDefaultApp(
|
||||||
|
{
|
||||||
|
...app,
|
||||||
|
scopes
|
||||||
|
},
|
||||||
|
existingApp
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await deps.registerDefaultApp({
|
||||||
|
...app,
|
||||||
|
scopes
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ const { createUser } = require(`@/modules/core/services/users`)
|
||||||
const { validateToken } = require(`@/modules/core/services/tokens`)
|
const { validateToken } = require(`@/modules/core/services/tokens`)
|
||||||
const { beforeEachContext } = require(`@/test/hooks`)
|
const { beforeEachContext } = require(`@/test/hooks`)
|
||||||
const {
|
const {
|
||||||
getApp,
|
|
||||||
getAllPublicApps,
|
getAllPublicApps,
|
||||||
createApp,
|
createApp,
|
||||||
updateApp,
|
updateApp,
|
||||||
|
@ -17,9 +16,15 @@ const {
|
||||||
} = require('../services/apps')
|
} = require('../services/apps')
|
||||||
|
|
||||||
const { Scopes } = require('@/modules/core/helpers/mainConstants')
|
const { Scopes } = require('@/modules/core/helpers/mainConstants')
|
||||||
const { updateDefaultApp } = require('@/modules/auth/manageDefaultApps')
|
|
||||||
const knex = require('@/db/knex')
|
const knex = require('@/db/knex')
|
||||||
const cryptoRandomString = require('crypto-random-string')
|
const cryptoRandomString = require('crypto-random-string')
|
||||||
|
const {
|
||||||
|
getAppFactory,
|
||||||
|
updateDefaultAppFactory
|
||||||
|
} = require('@/modules/auth/repositories/apps')
|
||||||
|
|
||||||
|
const getApp = getAppFactory({ db: knex })
|
||||||
|
const updateDefaultApp = updateDefaultAppFactory({ db: knex })
|
||||||
|
|
||||||
describe('Services @apps-services', () => {
|
describe('Services @apps-services', () => {
|
||||||
const actor = {
|
const actor = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче