All files / src UserModule.ts

88% Statements 22/25
76.47% Branches 26/34
77.78% Functions 7/9
91.67% Lines 22/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 1068x   8x 8x 8x   8x     8x                                           8x   42x 42x   42x 42x               42x 42x   42x                   42x       22x       53x       11x       87x       25x         18x 18x                                          
import { Commun, ConfigManager, RegisterEntityOptions } from '@commun/core'
import { UserModel } from './types/UserModel'
import { UserController } from './controllers/UserController'
import { UserRouter } from './routers/UserRouter'
import { UserConfig } from './config/UserConfig'
import jwt from 'jsonwebtoken'
import { AccessTokenSecurity } from './security/AccessTokenSecurity'
import { AccessTokenKeys } from './types/UserTokens'
import { AuthProvider } from './types/ExternalAuth'
import { ExternalAuth } from './security/ExternalAuth'
 
export type UserModuleSettings = {
  accessToken: jwt.SignOptions,
  refreshToken: {
    enabled: boolean
  },
  externalAuth?: {
    callbackUrl: string
    autoGenerateUsername: boolean
    providers: {
      [key in AuthProvider]?: {
        enabled: boolean
      }
    }
  },
}
 
let userModuleSettings: UserModuleSettings
let entityName: string
let keys: AccessTokenKeys
 
export const UserModule = {
  async setup<MODEL extends UserModel> (options: UserModuleSettings, entityOptions?: RegisterEntityOptions<MODEL>) {
    const config = entityOptions?.config || await getUserEntityConfig<MODEL>()
    entityName = config.entityName
 
    const { publicKey, privateKey } = await ConfigManager.getKeys('accessToken')
    this.accessTokenKeys = {
      publicKey,
      privateKey: {
        key: privateKey,
        passphrase: process.env.COMMUN_ACCESS_TOKEN_PK_PASSPHRASE!,
      }
    }
 
    this.setOptions(options)
    Commun.registerLogsToken('user-id', req => req.auth?.id)
 
    Commun.registerEntity<MODEL>({
      config,
      controller: new UserController<MODEL>(config.entityName),
      router: UserRouter,
      onExpressAppCreated: app => {
        ExternalAuth.setupPassport(app)
        app.use(AccessTokenSecurity.setRequestAuthMiddleware)
      },
      ...entityOptions
    })
    await Commun.registerPlugin('users', { config: options })
  },
 
  getOptions () {
    return userModuleSettings
  },
 
  setOptions (options: UserModuleSettings) {
    userModuleSettings = options
  },
 
  get accessTokenKeys () {
    return keys
  },
 
  set accessTokenKeys (accessTokenKeys: AccessTokenKeys) {
    keys = accessTokenKeys
  },
 
  get entityName () {
    return entityName
  },
}
 
async function getUserEntityConfig<MODEL extends UserModel> () {
  const config = await ConfigManager.readEntityConfig<MODEL>('users')
  return {
    ...UserConfig,
    ...config,
    schema: {
      ...UserConfig.schema,
      ...(config.schema || {}),
      properties: {
        ...UserConfig.schema?.properties,
        ...(config.schema?.properties || {}),
      },
    },
    permissions: {
      ...UserConfig.permissions,
      ...(config.permissions || {}),
      properties: {
        ...UserConfig.permissions?.properties,
        ...(config.permissions?.properties || {}),
      }
    }
  }
}