@things-factory/auth-base 10.1.278 → 10.1.280
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +24 -7
- package/CHANGELOG.md +0 -55
- package/dist-client/actions/auth.js.map +0 -1
- package/dist-client/apply-domain-theme.js.map +0 -1
- package/dist-client/auth.js.map +0 -1
- package/dist-client/bootstrap.js.map +0 -1
- package/dist-client/directive/privileged.js.map +0 -1
- package/dist-client/domain-required.js.map +0 -1
- package/dist-client/index.js.map +0 -1
- package/dist-client/profiled.js.map +0 -1
- package/dist-client/reducers/auth.js.map +0 -1
- package/dist-client/tsconfig.tsbuildinfo +0 -1
- package/dist-client/verify-webauthn.js.map +0 -1
- package/dist-server/ai-entry/access-assistant.js.map +0 -1
- package/dist-server/ai-entry/access-entry-targets.js.map +0 -1
- package/dist-server/ai-entry/entry-target-shape.js.map +0 -1
- package/dist-server/constants/error-code.js.map +0 -1
- package/dist-server/constants/error-message.js.map +0 -1
- package/dist-server/constants/max-age.js.map +0 -1
- package/dist-server/controllers/access-request.js.map +0 -1
- package/dist-server/controllers/account-mail.js.map +0 -1
- package/dist-server/controllers/auth.js.map +0 -1
- package/dist-server/controllers/change-pwd.js.map +0 -1
- package/dist-server/controllers/confirm-identity.js.map +0 -1
- package/dist-server/controllers/delete-user.js.map +0 -1
- package/dist-server/controllers/passkey.js.map +0 -1
- package/dist-server/controllers/password-setup.js.map +0 -1
- package/dist-server/controllers/profile.js.map +0 -1
- package/dist-server/controllers/reset-password.js.map +0 -1
- package/dist-server/controllers/signin.js.map +0 -1
- package/dist-server/controllers/signup.js.map +0 -1
- package/dist-server/controllers/unlock-user.js.map +0 -1
- package/dist-server/controllers/utils/find-verification-token.js.map +0 -1
- package/dist-server/controllers/utils/make-verification-token.js.map +0 -1
- package/dist-server/controllers/utils/password-rule.js.map +0 -1
- package/dist-server/controllers/utils/save-verification-token.js.map +0 -1
- package/dist-server/controllers/verification.js.map +0 -1
- package/dist-server/errors/auth-error.js.map +0 -1
- package/dist-server/errors/index.js.map +0 -1
- package/dist-server/errors/user-domain-not-match-error.js.map +0 -1
- package/dist-server/index.js.map +0 -1
- package/dist-server/middlewares/audit-scope-middleware.js.map +0 -1
- package/dist-server/middlewares/authenticate-401-middleware.js.map +0 -1
- package/dist-server/middlewares/bypass-signin-middleware.js.map +0 -1
- package/dist-server/middlewares/domain-authenticate-middleware.js.map +0 -1
- package/dist-server/middlewares/graphql-authenticate-middleware.js.map +0 -1
- package/dist-server/middlewares/index.js.map +0 -1
- package/dist-server/middlewares/jwt-authenticate-middleware.js.map +0 -1
- package/dist-server/middlewares/signin-middleware.js.map +0 -1
- package/dist-server/middlewares/verify-recaptcha-middleware.js.map +0 -1
- package/dist-server/migrations/1548206416130-SeedUser.js.map +0 -1
- package/dist-server/migrations/1566805283882-SeedPrivilege.js.map +0 -1
- package/dist-server/migrations/1745000000000-MigrateDomainOwnersToTable.js.map +0 -1
- package/dist-server/migrations/index.js.map +0 -1
- package/dist-server/role-tasks.js.map +0 -1
- package/dist-server/router/auth-checkin-router.js.map +0 -1
- package/dist-server/router/auth-private-process-router.js.map +0 -1
- package/dist-server/router/auth-public-process-router.js.map +0 -1
- package/dist-server/router/auth-signin-router.js.map +0 -1
- package/dist-server/router/auth-signup-router.js.map +0 -1
- package/dist-server/router/index.js.map +0 -1
- package/dist-server/router/oauth2/index.js.map +0 -1
- package/dist-server/router/oauth2/oauth2-authorize-router.js.map +0 -1
- package/dist-server/router/oauth2/oauth2-router.js.map +0 -1
- package/dist-server/router/oauth2/oauth2-server.js.map +0 -1
- package/dist-server/router/oauth2/passport-oauth2-client-password.js.map +0 -1
- package/dist-server/router/oauth2/passport-refresh-token.js.map +0 -1
- package/dist-server/router/path-base-domain-router.js.map +0 -1
- package/dist-server/router/site-root-router.js.map +0 -1
- package/dist-server/router/webauthn-router.js.map +0 -1
- package/dist-server/routes.js.map +0 -1
- package/dist-server/service/access-request/access-request-mutation.js.map +0 -1
- package/dist-server/service/access-request/access-request-query.js.map +0 -1
- package/dist-server/service/access-request/access-request-types.js.map +0 -1
- package/dist-server/service/access-request/access-request.js.map +0 -1
- package/dist-server/service/access-request/index.js.map +0 -1
- package/dist-server/service/app-binding/app-binding-mutation.js.map +0 -1
- package/dist-server/service/app-binding/app-binding-query.js.map +0 -1
- package/dist-server/service/app-binding/app-binding-types.js.map +0 -1
- package/dist-server/service/app-binding/app-binding.js.map +0 -1
- package/dist-server/service/app-binding/index.js.map +0 -1
- package/dist-server/service/appliance/appliance-mutation.js.map +0 -1
- package/dist-server/service/appliance/appliance-query.js.map +0 -1
- package/dist-server/service/appliance/appliance-types.js.map +0 -1
- package/dist-server/service/appliance/appliance.js.map +0 -1
- package/dist-server/service/appliance/index.js.map +0 -1
- package/dist-server/service/application/application-mutation.js.map +0 -1
- package/dist-server/service/application/application-query.js.map +0 -1
- package/dist-server/service/application/application-types.js.map +0 -1
- package/dist-server/service/application/application.js.map +0 -1
- package/dist-server/service/application/index.js.map +0 -1
- package/dist-server/service/audit/audit-action.js.map +0 -1
- package/dist-server/service/audit/audit-kinds.js.map +0 -1
- package/dist-server/service/audit/audit-query.js.map +0 -1
- package/dist-server/service/audit/audit-recorder.js.map +0 -1
- package/dist-server/service/audit/audit-request.js.map +0 -1
- package/dist-server/service/audit/audit-retention.js.map +0 -1
- package/dist-server/service/audit/audit-subscriber.js.map +0 -1
- package/dist-server/service/audit/audit-target.js.map +0 -1
- package/dist-server/service/audit/audit-types.js.map +0 -1
- package/dist-server/service/audit/audit-work.js.map +0 -1
- package/dist-server/service/audit/index.js.map +0 -1
- package/dist-server/service/auth-provider/auth-provider-mutation.js.map +0 -1
- package/dist-server/service/auth-provider/auth-provider-parameter-spec.js.map +0 -1
- package/dist-server/service/auth-provider/auth-provider-query.js.map +0 -1
- package/dist-server/service/auth-provider/auth-provider-type.js.map +0 -1
- package/dist-server/service/auth-provider/auth-provider.js.map +0 -1
- package/dist-server/service/auth-provider/index.js.map +0 -1
- package/dist-server/service/domain-generator/domain-generator-mutation.js.map +0 -1
- package/dist-server/service/domain-generator/domain-generator-types.js.map +0 -1
- package/dist-server/service/domain-generator/index.js.map +0 -1
- package/dist-server/service/domain-link/domain-link-mutation.js.map +0 -1
- package/dist-server/service/domain-link/domain-link-query.js.map +0 -1
- package/dist-server/service/domain-link/domain-link-types.js.map +0 -1
- package/dist-server/service/domain-link/domain-link.js.map +0 -1
- package/dist-server/service/domain-link/index.js.map +0 -1
- package/dist-server/service/domain-owner/domain-owner-mutation.js.map +0 -1
- package/dist-server/service/domain-owner/domain-owner-query.js.map +0 -1
- package/dist-server/service/domain-owner/domain-owner.js.map +0 -1
- package/dist-server/service/domain-owner/index.js.map +0 -1
- package/dist-server/service/granted-role/granted-role-mutation.js.map +0 -1
- package/dist-server/service/granted-role/granted-role-query.js.map +0 -1
- package/dist-server/service/granted-role/granted-role.js.map +0 -1
- package/dist-server/service/granted-role/index.js.map +0 -1
- package/dist-server/service/identity-confirmation/identity-confirmation.js.map +0 -1
- package/dist-server/service/index.js.map +0 -1
- package/dist-server/service/open-fields.js.map +0 -1
- package/dist-server/service/partner/index.js.map +0 -1
- package/dist-server/service/partner/partner-mutation.js.map +0 -1
- package/dist-server/service/partner/partner-query.js.map +0 -1
- package/dist-server/service/partner/partner-types.js.map +0 -1
- package/dist-server/service/partner/partner.js.map +0 -1
- package/dist-server/service/password-history/index.js.map +0 -1
- package/dist-server/service/password-history/password-history.js.map +0 -1
- package/dist-server/service/privilege/index.js.map +0 -1
- package/dist-server/service/privilege/open-field-rule.js.map +0 -1
- package/dist-server/service/privilege/privilege-axis.js.map +0 -1
- package/dist-server/service/privilege/privilege-deprecation.js.map +0 -1
- package/dist-server/service/privilege/privilege-directive.js.map +0 -1
- package/dist-server/service/privilege/privilege-mutation.js.map +0 -1
- package/dist-server/service/privilege/privilege-query.js.map +0 -1
- package/dist-server/service/privilege/privilege-rejection.js.map +0 -1
- package/dist-server/service/privilege/privilege-sync.js.map +0 -1
- package/dist-server/service/privilege/privilege-types.js.map +0 -1
- package/dist-server/service/privilege/privilege.js.map +0 -1
- package/dist-server/service/role/index.js.map +0 -1
- package/dist-server/service/role/role-mutation.js.map +0 -1
- package/dist-server/service/role/role-privilege-query.js.map +0 -1
- package/dist-server/service/role/role-query.js.map +0 -1
- package/dist-server/service/role/role-types.js.map +0 -1
- package/dist-server/service/role/role.js.map +0 -1
- package/dist-server/service/role-template/index.js.map +0 -1
- package/dist-server/service/role-template/role-task.js.map +0 -1
- package/dist-server/service/role-template/role-template-gap-resolver.js.map +0 -1
- package/dist-server/service/role-template/role-template-mutation.js.map +0 -1
- package/dist-server/service/role-template/role-template-query.js.map +0 -1
- package/dist-server/service/role-template/role-template-types.js.map +0 -1
- package/dist-server/service/role-template/role-template.js.map +0 -1
- package/dist-server/service/user/domain-query.js.map +0 -1
- package/dist-server/service/user/index.js.map +0 -1
- package/dist-server/service/user/user-mutation.js.map +0 -1
- package/dist-server/service/user/user-query.js.map +0 -1
- package/dist-server/service/user/user-types.js.map +0 -1
- package/dist-server/service/user/user.js.map +0 -1
- package/dist-server/service/users-auth-providers/index.js.map +0 -1
- package/dist-server/service/users-auth-providers/users-auth-providers.js.map +0 -1
- package/dist-server/service/verification-token/index.js.map +0 -1
- package/dist-server/service/verification-token/verification-token.js.map +0 -1
- package/dist-server/service/web-auth-credential/index.js.map +0 -1
- package/dist-server/service/web-auth-credential/web-auth-credential-mutation.js.map +0 -1
- package/dist-server/service/web-auth-credential/web-auth-credential-query.js.map +0 -1
- package/dist-server/service/web-auth-credential/web-auth-credential.js.map +0 -1
- package/dist-server/tsconfig.tsbuildinfo +0 -1
- package/dist-server/types.js.map +0 -1
- package/dist-server/utils/accepts.js.map +0 -1
- package/dist-server/utils/access-request-review.js.map +0 -1
- package/dist-server/utils/access-token-cookie.js.map +0 -1
- package/dist-server/utils/account-lock-rule.js.map +0 -1
- package/dist-server/utils/assignable-roles.js.map +0 -1
- package/dist-server/utils/build-auth-url.js.map +0 -1
- package/dist-server/utils/can-user-checkin-domain.js.map +0 -1
- package/dist-server/utils/check-permission.js.map +0 -1
- package/dist-server/utils/check-user-belongs-domain.js.map +0 -1
- package/dist-server/utils/check-user-has-role.js.map +0 -1
- package/dist-server/utils/checkin-domain-facts.js.map +0 -1
- package/dist-server/utils/checkin-domain-rule.js.map +0 -1
- package/dist-server/utils/credential-at-rest.js.map +0 -1
- package/dist-server/utils/credential-features.js.map +0 -1
- package/dist-server/utils/credential-serial-rule.js.map +0 -1
- package/dist-server/utils/domain-ownership.js.map +0 -1
- package/dist-server/utils/encrypt-state.js.map +0 -1
- package/dist-server/utils/get-aes-256-key.js.map +0 -1
- package/dist-server/utils/get-domain-users.js.map +0 -1
- package/dist-server/utils/get-secret.js.map +0 -1
- package/dist-server/utils/get-user-domains.js.map +0 -1
- package/dist-server/utils/lock-duration.js.map +0 -1
- package/dist-server/utils/password-reset-rule.js.map +0 -1
- package/dist-server/utils/profile-user.js.map +0 -1
- package/dist-server/utils/refuse-role-name.js.map +0 -1
- package/dist-server/utils/role-name-standing.js.map +0 -1
- package/dist-server/utils/same-origin-redirect.js.map +0 -1
- package/dist-server/utils/verification-token-rule.js.map +0 -1
- package/spec/unit/checkin-domain.spec.ts +0 -307
- package/spec/unit/checkin-privilege.spec.ts +0 -205
- package/spec/unit/domain-owner-entity.spec.ts +0 -179
- package/spec/unit/domain-owner-granted.spec.ts +0 -215
- package/spec/unit/domain-owner-migration.spec.ts +0 -236
- package/spec/unit/domain-owner-mutation.spec.ts +0 -337
- package/spec/unit/domain-ownership.spec.ts +0 -188
- package/tests/access-assistant-db.test.ts +0 -155
- package/tests/access-entry-targets-db.test.ts +0 -176
- package/tests/access-request-db.test.ts +0 -394
- package/tests/access-request-pg.test.ts +0 -83
- package/tests/access-request-review.test.ts +0 -193
- package/tests/account-lock-db.test.ts +0 -216
- package/tests/account-lock-rule.test.ts +0 -141
- package/tests/account-mail.test.ts +0 -69
- package/tests/activate-page-case.test.ts +0 -53
- package/tests/add-user-gates.test.ts +0 -34
- package/tests/app-binding-db.test.ts +0 -210
- package/tests/app-binding-delete-db.test.ts +0 -188
- package/tests/appliance-credential-state-db.test.ts +0 -207
- package/tests/appliance-delete-db.test.ts +0 -119
- package/tests/appliance-revoke-db.test.ts +0 -294
- package/tests/appliance-schema.test.ts +0 -129
- package/tests/application-delete-db.test.ts +0 -190
- package/tests/application-token-payload-db.test.ts +0 -185
- package/tests/assignable-roles-db.test.ts +0 -219
- package/tests/audit-db.test.ts +0 -410
- package/tests/audit-work.test.ts +0 -58
- package/tests/auth-base-role-tasks.test.ts +0 -58
- package/tests/checkin-domain-rule.test.ts +0 -128
- package/tests/checkin-privilege-seam-db.test.ts +0 -158
- package/tests/compiled.ts +0 -41
- package/tests/confirm-identity-db.test.ts +0 -85
- package/tests/credential-at-rest-db.test.ts +0 -246
- package/tests/credential-features-off-db.test.ts +0 -189
- package/tests/credential-serial-rule.test.ts +0 -84
- package/tests/declare-privileges.test.ts +0 -29
- package/tests/domain-assignees-db.test.ts +0 -95
- package/tests/domain-inheritance-sentinel.test.ts +0 -93
- package/tests/domain-required.test.ts +0 -127
- package/tests/has-privilege-db.test.ts +0 -198
- package/tests/identity-confirmation.test.ts +0 -146
- package/tests/list-inheritance-db.test.ts +0 -127
- package/tests/lock-recovery.test.ts +0 -206
- package/tests/mail-request-answers-db.test.ts +0 -142
- package/tests/open-doors.test.ts +0 -121
- package/tests/open-fields-enforcement.test.ts +0 -215
- package/tests/open-fields-framework.test.ts +0 -212
- package/tests/open-redirect-db.test.ts +0 -143
- package/tests/passkey-authenticator.ts +0 -104
- package/tests/passkey-db.test.ts +0 -295
- package/tests/passkey-signin-route-db.test.ts +0 -139
- package/tests/password-hashing.test.ts +0 -131
- package/tests/password-persistence.test.ts +0 -147
- package/tests/password-reset-rule-db.test.ts +0 -159
- package/tests/password-setup-db.test.ts +0 -215
- package/tests/permission-gate.test.ts +0 -228
- package/tests/picture-reducer.test.ts +0 -25
- package/tests/privilege-axis.test.ts +0 -157
- package/tests/privilege-deprecation.test.ts +0 -65
- package/tests/privilege-directive.test.ts +0 -332
- package/tests/privilege-rejection.test.ts +0 -104
- package/tests/privilege-sync-db.test.ts +0 -58
- package/tests/profile-user.test.ts +0 -24
- package/tests/refusal-cause.test.ts +0 -80
- package/tests/refusals-have-korean.test.ts +0 -24
- package/tests/request-holds.test.ts +0 -53
- package/tests/role-inheritance-db.test.ts +0 -286
- package/tests/role-mutation-db.test.ts +0 -293
- package/tests/role-name-lookup-sentinel.test.ts +0 -79
- package/tests/role-name-standing.test.ts +0 -83
- package/tests/role-privileges-db.test.ts +0 -252
- package/tests/role-task.test.ts +0 -168
- package/tests/role-template-gap-db.test.ts +0 -268
- package/tests/role-template-seed-db.test.ts +0 -180
- package/tests/role-template.test.ts +0 -162
- package/tests/role-users-gate.test.ts +0 -22
- package/tests/signin-policy.test.ts +0 -200
- package/tests/signup-duplicate-db.test.ts +0 -68
- package/tests/token-issuance.test.ts +0 -244
- package/tests/user-roles-field-db.test.ts +0 -134
- package/tests/verification-token-db.test.ts +0 -285
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"application-mutation.js","sourceRoot":"","sources":["../../../server/service/application/application-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Directive, Arg, Ctx, Mutation, Resolver } from 'type-graphql'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { User } from '../user/user.js'\nimport { Application } from './application.js'\nimport { AccessToken, ApplicationPatch, NewApplication } from './application-types.js'\n\n@Resolver(Application)\nexport class ApplicationMutation {\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Application, { description: 'To create new application' })\n async createApplication(@Arg('application') application: NewApplication, @Ctx() context: ResolverContext) {\n const { domain } = context.state\n return await getRepository(Application).save({\n ...application,\n domain,\n appKey: Application.generateAppKey(),\n appSecret: Application.generateAppSecret(),\n creator: context.state.user,\n updater: context.state.user\n })\n }\n\n /*\n * Deleting an application takes its bindings with it.\n *\n * ── Why the row alone was not enough ────────────────────────────────────\n * A binding is a shadow `User` standing in for the client, and that user is what a token\n * names. `User.checkAuth` looks the subject up by the id baked into the token and never asks\n * whether the application still exists, so a surviving binding keeps authenticating — and\n * `/oauth2/refresh-token` finds it by the refresh token in `password` and mints another year.\n *\n * So the screen said the application was gone while its clients kept working, with nothing\n * left on any screen to reach them: the list they appear in is keyed on an application that\n * no longer exists. `deleteAppliance` has always deleted its shadow user; this is the same\n * shape, and the asymmetry was the defect.\n *\n * ── Why the application is read before anything is deleted ──────────────\n * The bindings are found by `reference`, which carries no tenant of its own. Deleting them\n * first and scoping only the row afterwards would clear another tenant's bindings on the way\n * to discovering the application is not ours.\n */\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete application' })\n async deleteApplication(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { domain, tx } = context.state\n\n const application = await getRepository(Application, tx).findOneBy({ domain: { id: domain.id }, id })\n\n if (!application) {\n return true\n }\n\n /* `userType` matters: `reference` is a plain column both kinds of shadow user write to. */\n await getRepository(User, tx).delete({\n reference: id,\n userType: 'application'\n })\n\n await getRepository(Application, tx).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@privilege(category: \"security\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Application)\n async generateApplicationSecret(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { domain } = context.state\n const repository = getRepository(Application)\n const application = await repository.findOneBy({ domain: { id: domain.id }, id })\n\n return await repository.save({\n ...application,\n appSecret: Application.generateAppSecret(),\n updater: context.state.user\n })\n }\n\n @Directive('@privilege(category: \"security\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => AccessToken)\n async renewApplicationAccessToken(\n @Arg('id') id: string,\n @Ctx() context: ResolverContext,\n @Arg('scope') scope?: string\n ) {\n const { domain } = context.state\n\n var appuser: User = await getRepository(User).findOneBy({\n id,\n userType: 'application'\n })\n\n if (!appuser) {\n throw new Error('application is not bound')\n }\n\n const repository = getRepository(Application)\n const application = await repository.findOneBy({ id: appuser.reference })\n if (!application) {\n throw new Error('application not found')\n }\n\n /*\n * `appKey`, not `appSecret`.\n *\n * These two are both 32 hex characters on the same object and they are opposite kinds of\n * thing: the key is the client id and is public, the secret is what `/oauth2/access-token`\n * compares against to decide a caller is that client. This line passed the secret from the\n * day the file was written, and it cost twice over.\n *\n * the secret went out a JWT payload is base64, not encryption. Whoever held one of\n * these tokens could read the client secret out of it and then\n * authenticate as the application.\n * refreshing was broken the OAuth2 refresh exchange reads this field back and does\n * `findOneBy({ appKey })` (`router/oauth2/oauth2-server.ts`). A\n * payload naming the secret matched no row, so the exchange\n * answered \"application is not exist\".\n *\n * Tokens minted before this fix still carry the live secret and are left alone\n * (2026-09-20 사용자 결정). Nothing new goes out that way.\n */\n var accessToken = Application.generateAccessToken(domain, appuser, application, scope || '')\n var refreshToken = Application.generateRefreshToken(domain, appuser, application, scope || '')\n\n await getRepository(User).save({\n ...(appuser as any),\n password: refreshToken\n })\n\n return {\n accessToken,\n refreshToken\n }\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Application)\n async updateApplication(\n @Arg('id') id: string,\n @Arg('patch') patch: ApplicationPatch,\n @Ctx() context: ResolverContext\n ) {\n const repository = getRepository(Application)\n const application = await repository.findOneBy({ id })\n\n return await repository.save({\n ...application,\n ...patch,\n updater: context.state.user\n })\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"application-query.js","sourceRoot":"","sources":["../../../server/service/application/application-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Directive, Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { getQueryBuilderFromListParams, InheritedValueType, Domain, getRepository, ListParam } from '@things-factory/shell'\n\nimport { buildAuthURL } from '../../utils/build-auth-url.js'\n\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\nimport { Application } from './application.js'\nimport { ApplicationList } from './application-types.js'\n\n@Resolver(Application)\nexport class ApplicationQuery {\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => Application, { description: 'To fetch application' })\n async application(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Application> {\n const repository = getRepository(Application)\n\n return await repository.findOneBy({ id })\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => ApplicationList, { description: 'To fetch multiple application' })\n async applications(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext) {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n // this domain's rows only - a parent domain's are another tenant's, whatever `inherited` the caller sent\n params: { ...params, inherited: InheritedValueType.None },\n repository: getRepository(Application),\n alias: 'application',\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => String)\n async availableScopes(@Ctx() context: ResolverContext): Promise<string> {\n const { domain } = context.state\n const roles = await getRepository(Role).findBy({ domain: { id: domain.id } })\n\n return roles.map((role: Role) => role.name).join(' ')\n }\n\n @FieldResolver(type => String)\n async accessTokenUrl(@Ctx() context: ResolverContext): Promise<string> {\n return buildAuthURL('/oauth/access-token', context)\n }\n\n @FieldResolver(type => String)\n async authUrl(@Ctx() context: ResolverContext): Promise<string> {\n return buildAuthURL('/oauth/authorize', context)\n }\n\n @FieldResolver(type => Domain)\n async domain(@Ctx() context: ResolverContext) {\n return context.state.domain\n }\n\n @FieldResolver(type => User)\n async updater(@Root() application: Application): Promise<User> {\n return await getRepository(User).findOneBy({ id: application.updaterId })\n }\n\n @FieldResolver(type => User)\n async creator(@Root() application: Application): Promise<User> {\n return await getRepository(User).findOneBy({ id: application.creatorId })\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"application-types.js","sourceRoot":"","sources":["../../../server/service/application/application-types.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, InputType, Int, ObjectType } from 'type-graphql'\nimport { GraphQLEmailAddress } from 'graphql-scalars'\n\nimport { Application, ApplicationType } from './application.js'\n\n@ObjectType({ description: 'Represents a pair of access and refresh tokens.' })\nexport class AccessToken {\n @Field({ description: 'The access token for API authentication.' })\n accesToken: string\n\n @Field({ description: 'The refresh token to obtain a new access token.' })\n refreshToken: string\n}\n\n@ObjectType({ description: 'A paginated list of applications.' })\nexport class ApplicationList {\n @Field(type => [Application], { nullable: true, description: 'The list of application items.' })\n items?: Application[]\n\n @Field(type => Int, { nullable: true, description: 'The total number of applications.' })\n total?: number\n}\n\n@InputType({ description: 'Input for updating (patching) an existing application.' })\nexport class ApplicationPatch {\n @Field({ nullable: true, description: 'The new name for the application.' })\n name?: string\n\n @Field({ nullable: true, description: 'The new description for the application.' })\n description?: string\n\n @Field(type => GraphQLEmailAddress, { nullable: true, description: 'The new contact email for the application.' })\n email?: string\n\n @Field({ nullable: true, description: 'The new URL for the application.' })\n url?: string\n\n @Field({ nullable: true, description: 'The new icon URL for the application.' })\n icon?: string\n\n @Field({ nullable: true, description: 'The new redirect URL for the application.' })\n redirectUrl?: string\n\n @Field({ nullable: true, description: 'The new webhook URL for the application.' })\n webhook?: string\n\n @Field(type => ApplicationType, { nullable: true, description: 'The new type for the application.' })\n type?: ApplicationType\n}\n\n@InputType({ description: 'Input for creating a new application.' })\nexport class NewApplication {\n @Field({ description: 'The name of the new application.' })\n name: string\n\n @Field({ nullable: true, description: 'A description for the new application.' })\n description?: string\n\n @Field(type => GraphQLEmailAddress, { nullable: true, description: 'The contact email for the new application.' })\n email?: string\n\n @Field({ nullable: true, description: 'The URL of the new application.' })\n url?: string\n\n @Field({ nullable: true, description: 'A URL to the icon for the new application.' })\n icon?: string\n\n @Field({ nullable: true, description: 'The redirect URL for the new application.' })\n redirectUrl?: string\n\n @Field({ nullable: true, description: 'The webhook URL for the new application.' })\n webhook?: string\n\n @Field(type => ApplicationType, { nullable: true, description: 'The type of the new application.' })\n type?: ApplicationType\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"application.js","sourceRoot":"","sources":["../../../server/service/application/application.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'crypto'\nimport jwt from 'jsonwebtoken'\nimport { Directive, Field, ID, ObjectType, registerEnumType } from 'type-graphql'\nimport { GraphQLEmailAddress } from 'graphql-scalars'\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\n\nimport { config } from '@things-factory/env'\nimport { Domain } from '@things-factory/shell'\n\nimport { SECRET } from '../../utils/get-secret.js'\nimport { User, UserStatus } from '../user/user.js'\nimport { credentialAtRestTransformer } from '../../utils/credential-at-rest.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum ApplicationStatus {\n DRAFT = 'DRAFT', // The application is in a draft state and not yet active.\n ACTIVATED = 'ACTIVATED' // The application is active and can be used.\n}\n\nregisterEnumType(ApplicationStatus, {\n name: 'ApplicationStatus',\n description: 'The activation status of an application.'\n})\n\nexport enum ApplicationType {\n SELLERCRAFT = 'SELLERCRAFT', // Represents a Sellercraft application.\n XILNEX = 'XILNEX', // Represents a Xilnex application.\n MMS = 'MMS', // Represents a MMS application.\n XERO = 'XERO', // Represents a Xero application.\n OTHERS = 'OTHERS', // Represents other types of applications.\n SFTP = 'SFTP' // Represents an SFTP application.\n}\n\nregisterEnumType(ApplicationType, {\n name: 'ApplicationType',\n description: 'The type of an application.'\n})\n@Entity()\n@Index('ix_application_0', (application: Application) => [application.appKey], { unique: true })\n@ObjectType({ description: 'Represents a third-party application that can be integrated with the system.' })\nexport class Application {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the application.' })\n readonly id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain to which the application belongs.' })\n domain?: Domain\n\n @RelationId((application: Application) => application.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'The name of the application.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A description of the application.' })\n description?: string\n\n @Column()\n @Field(type => GraphQLEmailAddress, { description: 'The contact email for the application.' })\n email?: string\n\n @Column()\n @Field({ description: 'The URL of the application.' })\n url?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A URL to the icon for the application.' })\n icon?: string\n\n @Column()\n @Field({ description: 'The redirect URL for OAuth2 flows.' })\n redirectUrl?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The webhook URL for the application to receive events.' })\n webhook?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The unique key for the application (client ID).' })\n appKey?: string\n\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n transformer: credentialAtRestTransformer\n })\n @Field({ nullable: true, description: 'The secret key for the application (client secret).' })\n @Directive('@privilege(category: \"security\", privilege: \"query\", domainOwnerGranted: true)')\n appSecret?: string\n\n @Column({ default: ApplicationStatus.DRAFT })\n @Field({ description: 'The status of the application (e.g., DRAFT, ACTIVATED).' })\n status?: ApplicationStatus\n\n @Column({\n type:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'enum'\n : DATABASE_TYPE == 'oracle'\n ? 'varchar2'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n enum:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? ApplicationType\n : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,\n default: ApplicationType.OTHERS\n })\n @Field({ description: 'The type of the application.' })\n type?: ApplicationType\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the application was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the application was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created the application.' })\n creator?: User\n\n @RelationId((application: Application) => application.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated the application.' })\n updater?: User\n\n @RelationId((application: Application) => application.updater)\n updaterId?: string\n\n /* generateAppSecret */\n static generateAppSecret() {\n return crypto.randomBytes(16).toString('hex')\n }\n\n static generateAppKey() {\n return crypto.randomBytes(16).toString('hex')\n }\n\n /*\n * Signing a token for an application.\n *\n * ── Why this slot takes an object and not the key ───────────────────────\n * An application has two 32-character hex strings on it — `appKey`, the public client id, and\n * `appSecret`, the client secret. A positional `appKey: string` parameter accepts either, and\n * a call site reading `..., application.appSecret, ...` looks no different from the right one.\n * `renewApplicationAccessToken` passed the secret that way from the day it was written, which\n * put the client secret into a payload anyone holding the token can read.\n *\n * Taking `{ appKey }` does not make the wrong value unreachable, but it moves the mistake to\n * where it is visible: the call site has to write the field name, and a bare string no longer\n * type-checks. The caller that genuinely holds only a key (the refresh route, which reads it\n * back out of a token) writes `{ appKey }` and says so.\n */\n static sign(subject, expiresIn, domain, user, client: { appKey?: string }, scope) {\n var application = {\n id: user.id,\n userType: 'application',\n application: {\n appKey: client?.appKey\n },\n status: UserStatus.ACTIVATED,\n domain: {\n subdomain: domain.subdomain\n },\n scope\n }\n\n return jwt.sign(application, SECRET, {\n expiresIn,\n issuer: 'hatiolab.com',\n subject\n })\n }\n\n static generateAccessToken(domain, user, client: { appKey?: string }, scope) {\n /* how to set expiresIn https://github.com/vercel/ms */\n return this.sign('access-token', '30d', domain, user, client, scope)\n }\n\n static generateRefreshToken(domain, user, client: { appKey?: string }, scope) {\n /* how to set expiresIn https://github.com/vercel/ms */\n return this.sign('refresh-token', '1y', domain, user, client, scope)\n }\n\n /* auth-code signing for jsonwebtoken */\n static generateAuthCode(email, appKey, subdomain, scopes, state) {\n var credential = {\n email,\n appKey,\n subdomain,\n scopes,\n state\n }\n\n return jwt.sign(credential, SECRET, {\n expiresIn: '1m'\n })\n }\n\n /* auth-code signing for jsonwebtoken */\n static verifyAuthCode(authcode) {\n return jwt.verify(authcode, SECRET)\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/application/index.ts"],"names":[],"mappings":";;;AAAA,qDAA8C;AAC9C,iEAAyD;AACzD,uEAA+D;AAElD,QAAA,QAAQ,GAAG,CAAC,4BAAW,CAAC,CAAA;AACxB,QAAA,SAAS,GAAG,CAAC,uCAAgB,EAAE,6CAAmB,CAAC,CAAA","sourcesContent":["import { Application } from './application.js'\nimport { ApplicationQuery } from './application-query.js'\nimport { ApplicationMutation } from './application-mutation.js'\n\nexport const entities = [Application]\nexport const resolvers = [ApplicationQuery, ApplicationMutation]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-action.js","sourceRoot":"","sources":["../../../server/service/audit/audit-action.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, Int, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\nimport { User } from '../user/user.js'\n\n/**\n * One thing done, as the audit keeps it (ADR-0141 §3.2 · §3.3).\n *\n * `kind` says which: `door.check` (a `@privilege` judgement), `door.result` (what a passed door\n * did), or an event a service or the audit subscriber wrote (`role.grant`, `auth.signin`, ...).\n * Only the columns below exist, and `detail` takes only the keys its kind registered\n * (`audit-kinds.ts`) - no business value, secret or request text has a place to go.\n *\n * Immutable like `AuditRequest`, and for the same reason without foreign keys.\n */\n@Entity()\n@Index('ix_audit_action_0', (action: AuditAction) => [action.domain, action.createdAt])\n@Index('ix_audit_action_1', (action: AuditAction) => [action.actor, action.createdAt])\n@Index('ix_audit_action_2', (action: AuditAction) => [action.requestId])\n@ObjectType({ description: 'One thing done, as the audit keeps it.' })\nexport class AuditAction {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier.' })\n readonly id: string\n\n @Column({ type: 'uuid', nullable: true })\n @Field({ nullable: true, description: 'The request this was done in. Empty for work outside any request.' })\n requestId?: string\n\n @ManyToOne(type => Domain, { nullable: true, createForeignKeyConstraints: false })\n @Field(type => Domain, { nullable: true, description: 'The domain it was done in.' })\n domain?: Domain\n\n @RelationId((action: AuditAction) => action.domain)\n domainId?: string\n\n @ManyToOne(type => User, { nullable: true, createForeignKeyConstraints: false })\n @Field(type => User, { nullable: true, description: 'Who did it. Empty when nobody is known - a sign-in to an account that does not exist.' })\n actor?: User\n\n @RelationId((action: AuditAction) => action.actor)\n actorId?: string\n\n @CreateDateColumn()\n @Field({ description: 'When it was written.' })\n createdAt: Date\n\n @Column({ length: 64 })\n @Field({ description: 'What kind of action: door.check, door.result, role.grant, auth.signin, ...' })\n kind: string\n\n @Column({ nullable: true, length: 128 })\n @Field({ nullable: true, description: 'The door, as category:privilege, or owner / super for a door that asks ownership only.' })\n door?: string\n\n @Column({ nullable: true, length: 16 })\n @Field({ nullable: true, description: 'granted or denied - for a door check.' })\n decision?: string\n\n @Column({ nullable: true, length: 32 })\n @Field({ nullable: true, description: 'Why: role, domain-owner, superuser when granted; role, address, license, ownership, unknown when denied.' })\n basis?: string\n\n @Column({ nullable: true, length: 16 })\n @Field({ nullable: true, description: 'ok or error - what was done after the door, or how an event ended.' })\n outcome?: string\n\n @Column({ nullable: true, length: 64 })\n @Field({ nullable: true, description: 'A fixed code for an error or a refusal. Never a message.' })\n code?: string\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'How many times this happened in the request - equal checks are kept as one row.' })\n count: number\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'How many items a list returned, summed over the request.' })\n returned?: number\n\n @Column({ nullable: true, length: 64 })\n @Field({ nullable: true, description: 'Kind of the target - User, Role, ...' })\n targetKind?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], { nullable: true, description: 'Target ids, up to 100.' })\n targetIds?: string[]\n\n @Column({ default: false })\n @Field({ description: 'Whether more targets than were kept.' })\n truncated: boolean\n\n @Column({ nullable: true, length: 16 })\n @Field({ nullable: true, description: 'requested - named by the caller; handled - confirmed by the service.' })\n targetRole?: string\n\n @Column({ nullable: true, length: 64 })\n @Field({ nullable: true, description: 'Kind of the second object - the Role granted, the Privilege added.' })\n objectKind?: string\n\n @Column({ nullable: true, length: 128 })\n @Field({ nullable: true, description: 'Id or name of the second object.' })\n objectId?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Further facts, only the keys the kind registered.' })\n detail?: Record<string, string | number | boolean | null>\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-kinds.js","sourceRoot":"","sources":["../../../server/service/audit/audit-kinds.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAMH,8CAMC;AAED,kCAEC;AAMD,sCAkBC;AApCD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAA;AAElD,SAAgB,iBAAiB,CAAC,IAAY,EAAE,SAA4B,EAAE;IAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,mDAAmD,CAAC,CAAA;IACzF,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AACzB,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAC3B,IAAY,EACZ,MAAyC;IAEzC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kEAAkE,CAAC,CAAA;IACxG,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAE7B,MAAM,IAAI,GAAqC,EAAE,CAAA;IACjD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,4BAA4B,GAAG,eAAe,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAA;QAChH,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACpE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AACpD,CAAC;AAED,WAAW;AACX,iBAAiB,CAAC,YAAY,CAAC,CAAA;AAC/B,iBAAiB,CAAC,aAAa,CAAC,CAAA;AAEhC,2FAA2F;AAC3F,4DAA4D;AAC5D,iBAAiB,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC5C,iBAAiB,CAAC,cAAc,CAAC,CAAA;AACjC,iBAAiB,CAAC,cAAc,CAAC,CAAA;AACjC,8GAA8G;AAC9G,iBAAiB,CAAC,uBAAuB,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;AACtD,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;AACpC,iBAAiB,CAAC,yBAAyB,CAAC,CAAA;AAC5C,iBAAiB,CAAC,kBAAkB,CAAC,CAAA;AACrC,iBAAiB,CAAC,mBAAmB,CAAC,CAAA;AACtC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;AAEpC,qBAAqB;AACrB,iBAAiB,CAAC,YAAY,CAAC,CAAA;AAC/B,iBAAiB,CAAC,aAAa,CAAC,CAAA;AAChC,iBAAiB,CAAC,oBAAoB,CAAC,CAAA;AACvC,iBAAiB,CAAC,uBAAuB,CAAC,CAAA;AAC1C,iBAAiB,CAAC,aAAa,CAAC,CAAA;AAChC,iBAAiB,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;AAChD,iBAAiB,CAAC,kBAAkB,CAAC,CAAA;AACrC,iBAAiB,CAAC,qBAAqB,CAAC,CAAA;AACxC,wFAAwF;AACxF,iBAAiB,CAAC,mBAAmB,CAAC,CAAA;AACtC,iBAAiB,CAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA","sourcesContent":["/**\n * The kinds of audit action, and the `detail` keys each may carry (ADR-0141 §3.4).\n *\n * The audit stores only fields it allows. The fixed columns of `AuditAction` hold no business\n * value; `detail` is the one open place, so it takes only the keys its kind registered here, and\n * a kind nobody registered is refused - a module that wants a new event says so here, at import,\n * and a typo does not become a new kind quietly.\n *\n * A key holds a security state or a count, never a business value: a user's status (`activated` →\n * `locked`) is the account's security state; a salary is not, and has no key to go in.\n */\n\nexport type AuditDetailValue = string | number | boolean | null\n\nconst KINDS = new Map<string, readonly string[]>()\n\nexport function registerAuditKind(kind: string, detail: readonly string[] = []) {\n const known = KINDS.get(kind)\n if (known && known.join() !== detail.join()) {\n throw new Error(`Audit kind \"${kind}\" is registered twice with different detail keys.`)\n }\n KINDS.set(kind, detail)\n}\n\nexport function isAuditKind(kind: string): boolean {\n return KINDS.has(kind)\n}\n\n/**\n * The detail as it may be stored: unknown kinds throw, keys the kind did not register throw, and\n * values are cut to 64 characters. Throwing is right - this is a program writing the wrong thing.\n */\nexport function allowedDetail(\n kind: string,\n detail?: Record<string, AuditDetailValue>\n): Record<string, AuditDetailValue> | undefined {\n const keys = KINDS.get(kind)\n if (!keys) {\n throw new Error(`Audit kind \"${kind}\" is not registered. Register it with registerAuditKind() first.`)\n }\n if (!detail) return undefined\n\n const kept: Record<string, AuditDetailValue> = {}\n for (const [key, value] of Object.entries(detail)) {\n if (!keys.includes(key)) {\n throw new Error(`Audit kind \"${kind}\" does not allow detail \"${key}\". Allowed: ${keys.join(', ') || 'none'}.`)\n }\n kept[key] = typeof value === 'string' ? value.slice(0, 64) : value\n }\n return Object.keys(kept).length ? kept : undefined\n}\n\n/* Doors */\nregisterAuditKind('door.check')\nregisterAuditKind('door.result')\n\n/* Signing in and out (ADR-0141 §3.3). The reason of a failure is the error code column. */\n/* `method` is password or passkey (ADR-0156 decision 4). */\nregisterAuditKind('auth.signin', ['method'])\nregisterAuditKind('auth.checkin')\nregisterAuditKind('auth.signout')\n/* Confirming it is still the signed-in person before a door that asks so (ADR-0168) - password or passkey. */\nregisterAuditKind('auth.confirm-identity', ['method'])\nregisterAuditKind('password.change')\nregisterAuditKind('password.reset-by-admin')\nregisterAuditKind('credential.issue')\nregisterAuditKind('webauthn.register')\nregisterAuditKind('webauthn.remove')\n\n/* Who may do what */\nregisterAuditKind('role.grant')\nregisterAuditKind('role.revoke')\nregisterAuditKind('role.privilege.add')\nregisterAuditKind('role.privilege.remove')\nregisterAuditKind('role.delete')\nregisterAuditKind('user.status', ['from', 'to'])\nregisterAuditKind('domain.owner.add')\nregisterAuditKind('domain.owner.remove')\n/* Invitations are gone (ADR-0161 decision 6); their records stay and are still read. */\nregisterAuditKind('invitation.create')\nregisterAuditKind('invitation.status', ['from', 'to'])\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-query.js","sourceRoot":"","sources":["../../../server/service/audit/audit-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root } from 'type-graphql'\nimport { Brackets, In } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { findDomainOwnerUserIds } from '../../utils/domain-ownership.js'\nimport { getDomainUsers } from '../../utils/get-domain-users.js'\nimport { Privilege } from '../privilege/privilege.js'\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\nimport { AuditAction } from './audit-action.js'\nimport { auditHealth } from './audit-recorder.js'\nimport { AuditRequest } from './audit-request.js'\nimport { AuditDoor, AuditHealth, AuditPerson, AuditRecordFilter, AuditRecordList } from './audit-types.js'\n\n/*\n * Everybody's audit is `audit:query` (ADR-0141 §5). The domain owner does not pass on ownership - this is\n * a sensitive door (ADR-0139) - and the superuser does, as a stated exception whose basis the check records.\n * Every answer is this domain's only.\n */\nconst AUDIT_QUERY = '@privilege(category: \"audit\", privilege: \"query\", superUserGranted: true)'\n\n/* Reading the audit is recorded like any door, and left out of usage counts (§5-8 · §6.3). */\nconst AUDIT_DOOR = 'audit:query'\n\nconst MAX_PAGE = 200\n\nfunction period(from: Date, to: Date) {\n return { from: new Date(from), to: new Date(to) }\n}\n\n@Resolver(AuditAction)\nexport class AuditQuery {\n @Directive(AUDIT_QUERY)\n @Query(returns => AuditRecordList, { description: \"This domain's audit records - requests and what was done in them.\" })\n async auditRecords(@Arg('filter') filter: AuditRecordFilter, @Ctx() context: ResolverContext): Promise<AuditRecordList> {\n const { domain } = context.state\n const { from, to } = period(filter.from, filter.to)\n const limit = Math.min(Math.max(filter.limit || 50, 1), MAX_PAGE)\n const page = Math.max(filter.page || 1, 1)\n\n const qb = getRepository(AuditRequest)\n .createQueryBuilder('request')\n .leftJoinAndSelect('request.actor', 'actor')\n .where('request.domain = :domainId', { domainId: domain.id })\n .andWhere('request.createdAt >= :from AND request.createdAt <= :to', { from, to })\n\n if (filter.actorId) qb.andWhere('request.actor = :actorId', { actorId: filter.actorId })\n\n /* A request is kept when one of its actions matches - the request line alone says nothing of doors. */\n const conditions: string[] = []\n const params: Record<string, any> = {}\n if (filter.door) {\n conditions.push('action.door = :door')\n params.door = filter.door\n }\n if (filter.kind) {\n conditions.push('action.kind = :kind')\n params.kind = filter.kind\n }\n if (filter.outcome === 'denied') conditions.push(\"action.decision = 'denied'\")\n if (filter.outcome === 'error') conditions.push(\"action.outcome = 'error' AND action.kind = 'door.result'\")\n if (filter.outcome === 'failed') conditions.push(\"action.outcome = 'error' AND action.kind <> 'door.result'\")\n\n if (conditions.length) {\n const exists = qb\n .subQuery()\n .select('1')\n .from(AuditAction, 'action')\n .where('action.requestId = request.id')\n .andWhere(conditions.join(' AND '))\n .getQuery()\n qb.andWhere(`EXISTS ${exists}`, params)\n }\n\n const [requests, total] = await qb\n .orderBy('request.createdAt', 'DESC')\n .skip((page - 1) * limit)\n .take(limit)\n .getManyAndCount()\n\n const ids = requests.map(request => request.id)\n const actions = ids.length\n ? await getRepository(AuditAction)\n .createQueryBuilder('action')\n .where('action.requestId IN (:...ids)', { ids })\n .andWhere(new Brackets(where => where.where('action.domain = :domainId', { domainId: domain.id }).orWhere('action.domain IS NULL')))\n .orderBy('action.createdAt', 'ASC')\n .getMany()\n : []\n\n return {\n items: requests.map(request => ({ request, actions: actions.filter(action => action.requestId === request.id) })),\n total\n }\n }\n\n @Directive(AUDIT_QUERY)\n @Query(returns => [AuditPerson], { description: \"Each member's audit summary over a period, in this domain.\" })\n async auditPeople(@Arg('from') from: Date, @Arg('to') to: Date, @Ctx() context: ResolverContext): Promise<AuditPerson[]> {\n const { domain } = context.state\n const range = period(from, to)\n\n const members = await getDomainUsers(domain)\n const ownerIds = [...(await findDomainOwnerUserIds(domain))].filter(id => !members.some(one => one.id === id))\n const people = [...members, ...(ownerIds.length ? await getRepository(User).find({ where: { id: In(ownerIds) } }) : [])]\n if (!people.length) return []\n\n const ids = people.map(one => one.id)\n\n const roleRows = await getRepository(Role)\n .createQueryBuilder('role')\n .innerJoin('role.users', 'holder')\n .select(['role.name AS \"name\"', 'holder.id AS \"userId\"'])\n .where('role.domain = :domainId', { domainId: domain.id })\n .andWhere('holder.id IN (:...ids)', { ids })\n .getRawMany()\n\n const sums = (rows: any[]) => new Map(rows.map(row => [row.actorId, row]))\n\n const checkins = sums(\n await getRepository(AuditAction)\n .createQueryBuilder('action')\n .innerJoin('action.actor', 'actor')\n .select('actor.id', 'actorId')\n .addSelect('COUNT(*)', 'inPeriod')\n .where(\"action.kind = 'auth.checkin'\")\n .andWhere('action.domain = :domainId', { domainId: domain.id })\n .andWhere('action.createdAt >= :from AND action.createdAt <= :to', range)\n .andWhere('actor.id IN (:...ids)', { ids })\n .groupBy('actor.id')\n .getRawMany()\n )\n\n /*\n * The last check-in is read as rows, not as a raw MAX(): a raw value is the driver's text - sqlite\n * gives UTC without a zone - and only the entity path turns it into the right moment.\n */\n const lastCheckins = new Map(\n (\n await getRepository(AuditAction)\n .createQueryBuilder('action')\n .leftJoinAndSelect('action.actor', 'actor')\n .where(\"action.kind = 'auth.checkin'\")\n .andWhere('action.domain = :domainId', { domainId: domain.id })\n .andWhere('actor.id IN (:...ids)', { ids })\n .andWhere(qb => {\n const latest = qb\n .subQuery()\n .select('MAX(latest.createdAt)')\n .from(AuditAction, 'latest')\n .where(\"latest.kind = 'auth.checkin'\")\n .andWhere('latest.domain = :domainId')\n .andWhere('latest.actor = action.actor')\n .getQuery()\n return `action.createdAt = ${latest}`\n })\n .getMany()\n ).map(action => [action.actor?.id, action.createdAt] as [string, Date])\n )\n\n /*\n * The last use - the member's latest request to this domain, at any time. Every GraphQL request has its line, so\n * this is the last time the app was open and talking to the server, the reads an open screen makes by itself\n * included. Read as rows, like the check-in above.\n */\n const lastUses = new Map(\n (\n await getRepository(AuditRequest)\n .createQueryBuilder('request')\n .leftJoinAndSelect('request.actor', 'actor')\n .where('request.domain = :domainId', { domainId: domain.id })\n .andWhere('actor.id IN (:...ids)', { ids })\n .andWhere(qb => {\n const latest = qb\n .subQuery()\n .select('MAX(latest.createdAt)')\n .from(AuditRequest, 'latest')\n .where('latest.domain = :domainId')\n .andWhere('latest.actor = request.actor')\n .getQuery()\n return `request.createdAt = ${latest}`\n })\n .getMany()\n ).map(request => [request.actor?.id, request.createdAt] as [string, Date])\n )\n\n /* A sign-in may come before any domain is chosen, so failures are the member's wherever they were. */\n const failures = sums(\n await getRepository(AuditAction)\n .createQueryBuilder('action')\n .innerJoin('action.actor', 'actor')\n .select('actor.id', 'actorId')\n .addSelect('COUNT(*)', 'failed')\n .where(\"action.kind = 'auth.signin' AND action.outcome = 'error'\")\n .andWhere('action.createdAt >= :from AND action.createdAt <= :to', range)\n .andWhere(new Brackets(where => where.where('action.domain = :domainId', { domainId: domain.id }).orWhere('action.domain IS NULL')))\n .andWhere('actor.id IN (:...ids)', { ids })\n .groupBy('actor.id')\n .getRawMany()\n )\n\n const doors = sums(\n await getRepository(AuditAction)\n .createQueryBuilder('action')\n .innerJoin('action.actor', 'actor')\n .select('actor.id', 'actorId')\n .addSelect(\"SUM(CASE WHEN action.decision = 'granted' THEN action.count ELSE 0 END)\", 'granted')\n .addSelect(\"SUM(CASE WHEN action.decision = 'denied' THEN action.count ELSE 0 END)\", 'denied')\n .where(\"action.kind = 'door.check'\")\n .andWhere('action.door <> :auditDoor', { auditDoor: AUDIT_DOOR })\n .andWhere('action.domain = :domainId', { domainId: domain.id })\n .andWhere('action.createdAt >= :from AND action.createdAt <= :to', range)\n .groupBy('actor.id')\n .getRawMany()\n )\n\n return people.map(user => ({\n user,\n roles: roleRows.filter(row => row.userId === user.id).map(row => row.name),\n lastCheckinAt: lastCheckins.get(user.id),\n lastUsedAt: lastUses.get(user.id),\n checkins: Number(checkins.get(user.id)?.inPeriod || 0),\n failedSignins: Number(failures.get(user.id)?.failed || 0),\n granted: Number(doors.get(user.id)?.granted || 0),\n denied: Number(doors.get(user.id)?.denied || 0)\n }))\n }\n\n @Directive(AUDIT_QUERY)\n @Query(returns => [AuditDoor], {\n description: 'Each door over a period, in this domain - every declared privilege, a door with no record in the period too.'\n })\n async auditDoors(@Arg('from') from: Date, @Arg('to') to: Date, @Ctx() context: ResolverContext): Promise<AuditDoor[]> {\n const { domain } = context.state\n\n const observed = await getRepository(AuditAction)\n .createQueryBuilder('action')\n .leftJoin('action.actor', 'actor')\n .select('action.door', 'door')\n .addSelect('COUNT(DISTINCT actor.id)', 'people')\n .addSelect(\"SUM(CASE WHEN action.decision = 'granted' THEN action.count ELSE 0 END)\", 'granted')\n .addSelect(\"SUM(CASE WHEN action.decision = 'denied' THEN action.count ELSE 0 END)\", 'denied')\n .where(\"action.kind = 'door.check'\")\n .andWhere('action.door <> :auditDoor', { auditDoor: AUDIT_DOOR })\n .andWhere('action.domain = :domainId', { domainId: domain.id })\n .andWhere('action.createdAt >= :from AND action.createdAt <= :to', period(from, to))\n .groupBy('action.door')\n .getRawMany()\n\n const byDoor = new Map(observed.map(row => [row.door, row]))\n const declared = await getRepository(Privilege).find({ order: { category: 'ASC', name: 'ASC' } })\n\n const doors = new Map<string, AuditDoor>()\n for (const one of declared) {\n const door = `${one.category}:${one.name}`\n if (door === AUDIT_DOOR) continue\n doors.set(door, { door, category: one.category, privilege: one.name, people: 0, granted: 0, denied: 0 })\n }\n for (const [door, row] of byDoor) {\n const [category, privilege] = door.includes(':') ? door.split(':') : [undefined, undefined]\n doors.set(door, {\n door,\n category,\n privilege,\n people: Number(row.people || 0),\n granted: Number(row.granted || 0),\n denied: Number(row.denied || 0)\n })\n }\n\n return [...doors.values()]\n }\n\n @Directive(AUDIT_QUERY)\n @Query(returns => AuditHealth, { description: 'Audit writes this server process failed to store.' })\n async auditHealth(): Promise<AuditHealth> {\n return auditHealth() as AuditHealth\n }\n\n /*\n * One's own record is what one did (ADR-0141 §5-5): the actor is the session's user, whatever is asked.\n * What somebody else did to me is not here.\n */\n @Query(returns => [AuditAction], { description: 'What I did - in this domain, and my sign-ins.' })\n async myAuditActions(\n @Arg('kind', { nullable: true }) kind: string,\n @Arg('limit', type => Int, { nullable: true }) limit: number,\n @Ctx() context: ResolverContext\n ): Promise<AuditAction[]> {\n const { domain, user } = context.state\n if (!user) throw new Error('No user specified')\n\n const qb = getRepository(AuditAction)\n .createQueryBuilder('action')\n .leftJoinAndSelect('action.domain', 'domain')\n .where('action.actor = :userId', { userId: user.id })\n .andWhere(new Brackets(where => where.where('action.domain = :domainId', { domainId: domain?.id }).orWhere('action.domain IS NULL')))\n\n if (kind) qb.andWhere('action.kind = :kind', { kind })\n\n return await qb\n .orderBy('action.createdAt', 'DESC')\n .take(Math.min(Math.max(limit || 20, 1), MAX_PAGE))\n .getMany()\n }\n\n /* Where an action came from - its request's address and browser. */\n @FieldResolver(type => AuditRequest, { nullable: true })\n async request(@Root() action: AuditAction): Promise<AuditRequest | null> {\n return action.requestId ? await getRepository(AuditRequest).findOneBy({ id: action.requestId }) : null\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-recorder.js","sourceRoot":"","sources":["../../../server/service/audit/audit-recorder.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from 'async_hooks'\nimport { randomUUID } from 'crypto'\nimport { Kind, OperationDefinitionNode, parse, SelectionSetNode } from 'graphql'\nimport { EntityManager } from 'typeorm'\n\nimport { logger } from '@things-factory/env'\nimport { getRepository } from '@things-factory/shell'\n\nimport { AuditAction } from './audit-action.js'\nimport { allowedDetail, AuditDetailValue } from './audit-kinds.js'\nimport { AuditRequest } from './audit-request.js'\n\n/**\n * ── The audit recorder (ADR-0141) ──────────────────────────────────────────\n *\n * A request runs inside a scope (`runInAuditScope`, installed once by the auth middleware). Door\n * checks and results are merged into the scope while the request runs and written with the request\n * row when it ends - one write per request, apart from the business transaction, and never in the\n * way of the answer (§4-4). Events (`recordAuditAction`) are written when they happen: inside the\n * caller's transaction when it hands one (§4-1, they fail together), on their own otherwise (§4-2 ·\n * §4-3, a failure is counted and does not undo what already happened).\n *\n * Who and where are read from the request's context at write time, so a door checked before the\n * user was known still lands under them once they are.\n */\n\nconst MAX_TARGETS = 100\n\nexport type AuditChannel = 'graphql' | 'http'\n\nexport interface AuditActionInput {\n kind: string\n door?: string\n decision?: 'granted' | 'denied'\n basis?: string\n outcome?: 'ok' | 'error'\n code?: string\n returned?: number\n targetKind?: string\n targetIds?: string[]\n targetRole?: 'requested' | 'handled'\n objectKind?: string\n objectId?: string\n detail?: Record<string, AuditDetailValue>\n}\n\ninterface MergedAction extends AuditActionInput {\n count: number\n targets: Set<string>\n truncated: boolean\n}\n\nexport interface AuditScope {\n requestId: string\n channel: AuditChannel\n context: any\n startedAt: number\n merged: Map<string, MergedAction>\n /* An http request is kept only when something in it was recorded. */\n recorded: boolean\n /* Who and where its events named, for a request that ran before the context knew (a sign-in, a check-in). */\n eventActorId?: string\n eventDomainId?: string\n}\n\nconst storage = new AsyncLocalStorage<AuditScope>()\n\n/** Runs `work` as one audited request; the request row and merged actions are written when it ends. */\nexport async function runInAuditScope<T>(context: any, channel: AuditChannel, work: () => Promise<T>): Promise<T> {\n const scope: AuditScope = {\n requestId: randomUUID(),\n channel,\n context,\n startedAt: Date.now(),\n merged: new Map(),\n recorded: false\n }\n\n try {\n return await storage.run(scope, work)\n } finally {\n track(finishAuditScope(scope))\n }\n}\n\nexport function currentAuditScope(): AuditScope | undefined {\n return storage.getStore()\n}\n\n/* ── merging door checks and results ───────────────────────────────────── */\n\nfunction keyOf(input: AuditActionInput) {\n return [input.kind, input.door, input.decision, input.basis, input.outcome, input.code, input.targetKind, input.targetRole].join('|')\n}\n\n/**\n * Notes a door check or result in the running request. Equal ones become one row with a count; their\n * targets are kept together, up to 100 (ADR-0141 §3.2). Outside any request this does nothing - a\n * subscription stream or a boot task is not audited at the door (§9 step 4).\n */\nexport function noteAuditAction(input: AuditActionInput) {\n const scope = currentAuditScope()\n if (!scope) return\n\n allowedDetail(input.kind, input.detail)\n\n const key = keyOf(input)\n let merged = scope.merged.get(key)\n if (!merged) {\n merged = { ...input, count: 0, targets: new Set(), truncated: false, returned: undefined }\n scope.merged.set(key, merged)\n }\n\n merged.count++\n if (typeof input.returned === 'number') {\n merged.returned = (merged.returned ?? 0) + input.returned\n }\n for (const id of input.targetIds || []) {\n if (merged.targets.has(id)) continue\n if (merged.targets.size >= MAX_TARGETS) {\n merged.truncated = true\n break\n }\n merged.targets.add(id)\n }\n}\n\n/* ── events ─────────────────────────────────────────────────────────────── */\n\nexport interface RecordOptions {\n /** The business transaction. Given, the event is written in it and a failure fails the change (§4-1). */\n manager?: EntityManager\n /** Who did it, when the context does not know yet (a sign-in). `null` says nobody is known. */\n actorId?: string | null\n /** Where, when it is not the request's domain (a role of another domain, a sign-in with no domain). */\n domainId?: string | null\n}\n\n/**\n * Writes one event now. With `manager` it shares the caller's transaction and throws with it;\n * without, it is written on its own and a failure is only counted (ADR-0141 §4-2 · §4-3 · §4-5).\n */\nexport async function recordAuditAction(input: AuditActionInput, options: RecordOptions = {}): Promise<void> {\n const scope = currentAuditScope()\n const row = rowOf(input, scope, options)\n\n if (scope) {\n scope.recorded = true\n if (options.actorId) scope.eventActorId ??= options.actorId\n if (options.domainId) scope.eventDomainId ??= options.domainId\n }\n\n if (options.manager) {\n await options.manager.getRepository(AuditAction).insert(row)\n return\n }\n\n const writing = getRepository(AuditAction)\n .insert(row)\n .then(\n () => undefined,\n error => countFailure(error, input.kind)\n )\n track(writing)\n await writing\n}\n\nfunction rowOf(input: AuditActionInput, scope: AuditScope | undefined, options: RecordOptions, count = 1, targets?: string[], truncated = false) {\n const state = scope?.context?.state || {}\n const actorId = options.actorId !== undefined ? options.actorId : state.user?.id\n const domainId = options.domainId !== undefined ? options.domainId : state.domain?.id\n const ids = targets ?? (input.targetIds || []).slice(0, MAX_TARGETS)\n\n return {\n requestId: scope?.requestId ?? null,\n domain: domainId ? { id: domainId } : null,\n actor: actorId ? { id: actorId } : null,\n kind: input.kind,\n door: input.door ?? null,\n decision: input.decision ?? null,\n basis: input.basis ?? null,\n outcome: input.outcome ?? null,\n code: input.code ? String(input.code).slice(0, 64) : null,\n count,\n returned: input.returned ?? null,\n targetKind: input.targetKind ?? null,\n targetIds: ids.length ? ids : null,\n truncated: truncated || (input.targetIds || []).length > MAX_TARGETS,\n targetRole: input.targetRole ?? null,\n objectKind: input.objectKind ?? null,\n objectId: input.objectId ? String(input.objectId).slice(0, 128) : null,\n detail: allowedDetail(input.kind, input.detail) ?? null\n } as any\n}\n\n/* ── the request row ────────────────────────────────────────────────────── */\n\n/** The address a request came from - the first `x-forwarded-for` value, as the check-in record always took it. */\nexport function addressOf(context: any): string | undefined {\n const forwarded = context?.req?.headers?.['x-forwarded-for'] as string | undefined\n const address = forwarded ? forwarded.split(',')[0].trim() : context?.req?.socket?.remoteAddress\n return address ? String(address).slice(0, 64) : undefined\n}\n\n/**\n * What a GraphQL request asked: its operation type and the root fields by their schema names - never\n * an argument or a variable (ADR-0141 §3.4). A field with no `@privilege` leaves no action, so these\n * names are what says which open door a request used. The parsed document is Apollo's and is not\n * reachable from here; parsing again is the cost of knowing.\n */\nexport function operationOf(body: any): { operationType?: string; operationName?: string; fields?: string } {\n const first = Array.isArray(body) ? body[0] : body\n if (!first || typeof first !== 'object' || typeof first.query !== 'string') return {}\n\n const name = typeof first.operationName === 'string' ? first.operationName.slice(0, 128) : undefined\n\n try {\n const document = parse(first.query)\n const operations = document.definitions.filter((one): one is OperationDefinitionNode => one.kind === Kind.OPERATION_DEFINITION)\n const operation = operations.find(one => !name || one.name?.value === name) ?? operations[0]\n if (!operation) return { operationName: name }\n\n const fragments = new Map(\n document.definitions.flatMap(one => (one.kind === Kind.FRAGMENT_DEFINITION ? [[one.name.value, one.selectionSet] as const] : []))\n )\n const names = new Set<string>()\n const walk = (set: SelectionSetNode, seen: Set<string>) => {\n for (const selection of set.selections) {\n if (selection.kind === Kind.FIELD) names.add(selection.name.value)\n else if (selection.kind === Kind.INLINE_FRAGMENT) walk(selection.selectionSet, seen)\n else if (selection.kind === Kind.FRAGMENT_SPREAD && !seen.has(selection.name.value)) {\n const spread = fragments.get(selection.name.value)\n if (spread) walk(spread, new Set([...seen, selection.name.value]))\n }\n }\n }\n walk(operation.selectionSet, new Set())\n\n return { operationType: operation.operation, operationName: name, fields: [...names].join(',').slice(0, 256) || undefined }\n } catch {\n return { operationName: name }\n }\n}\n\nasync function finishAuditScope(scope: AuditScope): Promise<void> {\n if (scope.channel === 'http' && !scope.recorded && scope.merged.size === 0) return\n\n const context = scope.context\n const state = context?.state || {}\n\n const domainId = state.domain?.id ?? scope.eventDomainId\n const actorId = state.user?.id ?? scope.eventActorId\n\n const request = {\n id: scope.requestId,\n domain: domainId ? { id: domainId } : null,\n actor: actorId ? { id: actorId } : null,\n ip: addressOf(context) ?? null,\n userAgent: (context?.request?.header?.['user-agent'] as string | undefined)?.slice(0, 256) ?? null,\n durationMs: Date.now() - scope.startedAt,\n channel: scope.channel,\n route: scope.channel === 'http' ? (context?._matchedRoute ? String(context._matchedRoute).slice(0, 128) : null) : null,\n ...(scope.channel === 'graphql' ? operationOf(context?.request?.body) : {})\n } as any\n\n const actions = [...scope.merged.values()].map(merged =>\n rowOf(merged, scope, {}, merged.count, [...merged.targets], merged.truncated)\n )\n\n /*\n * Two plain inserts, no transaction of their own: a sqlite database has one connection, and a\n * transaction opened here collided with the requests' own (「cannot start a transaction within a\n * transaction」, seen on Office's development database). The line and its actions are both best\n * effort (§4-4); one failing is counted like the other.\n */\n try {\n await getRepository(AuditRequest).insert(request)\n if (actions.length) await getRepository(AuditAction).insert(actions)\n } catch (error) {\n countFailure(error, 'request')\n }\n}\n\n/* ── failures, counted apart from the audit store (ADR-0141 §4-5) ──────── */\n\nconst health = {\n since: new Date(),\n failures: 0,\n firstFailedAt: null as Date | null,\n lastFailedAt: null as Date | null\n}\n\nfunction countFailure(error: unknown, what: string) {\n const now = new Date()\n health.failures++\n health.firstFailedAt ??= now\n health.lastFailedAt = now\n logger.error(`[audit] not written (${what}): ${(error as Error)?.message}`)\n}\n\n/** Failures this server process detected since it started. Not those it never got to try. */\nexport function auditHealth() {\n return { ...health }\n}\n\n/* ── for tests: wait for every write started so far ────────────────────── */\n\nconst pending = new Set<Promise<unknown>>()\n\nfunction track(promise: Promise<unknown>) {\n pending.add(promise)\n promise.finally(() => pending.delete(promise))\n}\n\nexport async function flushAudit(): Promise<void> {\n while (pending.size) {\n await Promise.allSettled([...pending])\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-request.js","sourceRoot":"","sources":["../../../server/service/audit/audit-request.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, Int, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryColumn, RelationId } from 'typeorm'\n\nimport { Domain } from '@things-factory/shell'\n\nimport { User } from '../user/user.js'\n\n/**\n * One request that reached the server, as the audit keeps it (ADR-0141 §3.1).\n *\n * Every GraphQL request has one; any other request has one when it left at least one action\n * (a sign-in, a check-in). What happened inside is in `AuditAction` rows carrying this id.\n *\n * The row is never changed or deleted by the application (ADR-0141 §4-6), so the entity has no\n * updater, `updatedAt` or `deletedAt`. Its relations carry no foreign key: an audit row must\n * neither stop a user or domain from being removed nor go with them.\n */\n@Entity()\n@Index('ix_audit_request_0', (request: AuditRequest) => [request.domain, request.createdAt])\n@Index('ix_audit_request_1', (request: AuditRequest) => [request.actor, request.createdAt])\n@ObjectType({ description: 'A request that reached the server, as the audit keeps it.' })\nexport class AuditRequest {\n /* Given by the recorder at the start of the request, so actions written mid-request can name it. */\n @PrimaryColumn('uuid')\n @Field(type => ID, { description: 'Request id, shared by the actions of this request.' })\n id: string\n\n @ManyToOne(type => Domain, { nullable: true, createForeignKeyConstraints: false })\n @Field(type => Domain, { nullable: true, description: 'The domain the request was made in.' })\n domain?: Domain\n\n @RelationId((request: AuditRequest) => request.domain)\n domainId?: string\n\n @ManyToOne(type => User, { nullable: true, createForeignKeyConstraints: false })\n @Field(type => User, { nullable: true, description: 'Who made the request. Empty when nobody was signed in.' })\n actor?: User\n\n @RelationId((request: AuditRequest) => request.actor)\n actorId?: string\n\n @CreateDateColumn()\n @Field({ description: 'When the server finished the request.' })\n createdAt: Date\n\n @Column({ nullable: true, length: 64 })\n @Field({ nullable: true, description: 'Address the request came from.' })\n ip?: string\n\n @Column({ nullable: true, length: 256 })\n @Field({ nullable: true, description: 'User-Agent header, cut at 256 characters.' })\n userAgent?: string\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Milliseconds the server spent on the request.' })\n durationMs?: number\n\n @Column({ length: 16 })\n @Field({ description: 'graphql, or http for any other request.' })\n channel: string\n\n @Column({ nullable: true, length: 16 })\n @Field({ nullable: true, description: 'query, mutation or subscription - for a GraphQL request.' })\n operationType?: string\n\n @Column({ nullable: true, length: 128 })\n @Field({ nullable: true, description: 'The operation name the client gave. For reference only - the client chooses it.' })\n operationName?: string\n\n @Column({ nullable: true, length: 256 })\n @Field({ nullable: true, description: 'The root fields a GraphQL request asked, by their schema names - never an argument.' })\n fields?: string\n\n @Column({ nullable: true, length: 128 })\n @Field({ nullable: true, description: 'The route pattern of a request outside GraphQL. Never the path itself.' })\n route?: string\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-retention.js","sourceRoot":"","sources":["../../../server/service/audit/audit-retention.ts"],"names":[],"mappings":";;AAcA,gDAGC;AAGD,8CAOC;AAID,kDAYC;AA3CD,qCAAkC;AAElC,6CAAoD;AACpD,iDAAqD;AACrD,2DAA8D;AAE9D,uDAA+C;AAC/C,yDAAiD;AAEjD;;;;GAIG;AACH,SAAgB,kBAAkB;IAChC,MAAM,IAAI,GAAG,MAAM,CAAC,YAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAA;IACtD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;AACvD,CAAC;AAED,oEAAoE;AAC7D,KAAK,UAAU,iBAAiB,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;IACtD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IAEnF,MAAM,OAAO,GAAG,MAAM,IAAA,qBAAa,EAAC,6BAAW,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAA,kBAAQ,EAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACxF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAA,kBAAQ,EAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAE1F,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAA;AAC7E,CAAC;AAED,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAElC,SAAgB,mBAAmB;IACjC,OAAO,IAAA,8BAAiB,EAAC;QACvB,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,OAAO,GAAG,MAAM,iBAAiB,EAAE,CAAA;YACzC,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACxC,YAAM,CAAC,IAAI,CAAC,mBAAmB,OAAO,CAAC,QAAQ,iBAAiB,OAAO,CAAC,OAAO,iBAAiB,kBAAkB,EAAE,OAAO,CAAC,CAAA;YAC9H,CAAC;QACH,CAAC;QACD,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,YAAM,CAAC,KAAK,CAAC,mCAAmC,OAAO,CAAC,KAAK,EAAE,CAAC;KACvF,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { LessThan } from 'typeorm'\n\nimport { config, logger } from '@things-factory/env'\nimport { getRepository } from '@things-factory/shell'\nimport { startPeriodicTask } from '@things-factory/task-lease'\n\nimport { AuditAction } from './audit-action.js'\nimport { AuditRequest } from './audit-request.js'\n\n/**\n * Audit rows older than the retention are removed by this task and by nothing else - the\n * application has no door that changes or deletes them (ADR-0141 §4-6 · §7). One year unless\n * `audit/retentionDays` says otherwise.\n */\nexport function auditRetentionDays(): number {\n const days = Number(config.get('audit/retentionDays'))\n return Number.isFinite(days) && days > 0 ? days : 365\n}\n\n/** Removes what is older than the retention, counted from `now`. */\nexport async function purgeExpiredAudit(now = new Date()): Promise<{ requests: number; actions: number }> {\n const before = new Date(now.getTime() - auditRetentionDays() * 24 * 60 * 60 * 1000)\n\n const actions = await getRepository(AuditAction).delete({ createdAt: LessThan(before) })\n const requests = await getRepository(AuditRequest).delete({ createdAt: LessThan(before) })\n\n return { requests: requests.affected ?? 0, actions: actions.affected ?? 0 }\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nexport function startAuditRetention() {\n return startPeriodicTask({\n name: 'audit-retention',\n intervalMs: DAY_MS,\n work: async () => {\n const removed = await purgeExpiredAudit()\n if (removed.requests || removed.actions) {\n logger.info(`[audit] removed ${removed.requests} requests and ${removed.actions} actions past ${auditRetentionDays()} days`)\n }\n },\n onFailure: failure => logger.error(`[audit] retention round failed: ${failure.error}`)\n })\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-subscriber.js","sourceRoot":"","sources":["../../../server/service/audit/audit-subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm'\n\nimport { DomainOwner } from '../domain-owner/domain-owner.js'\nimport { Privilege } from '../privilege/privilege.js'\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\nimport { WebAuthCredential } from '../web-auth-credential/web-auth-credential.js'\nimport { currentAuditScope, recordAuditAction } from './audit-recorder.js'\n\n/**\n * ── Who may do what, recorded where it is saved (ADR-0141 §3.3 · §4-1) ───────\n *\n * A role is granted in a dozen places - the user screen, an access request, a\n * template, Office's role plan. Each saves through TypeORM, so the change is caught here, once, and\n * written in the same transaction as the save: the grant and its record stand or fall together.\n *\n * A write that bypasses the entity manager's events (a query builder, `delete()`) is not seen here;\n * those few paths record themselves.\n */\n\nconst idOf = (one: any): string | undefined => (typeof one === 'string' ? one : one?.id)\n\n/** The id a junction row holds for `target`, read from what the event carries. */\nfunction junctionIdOf(event: InsertEvent<any> | RemoveEvent<any>, target: Function): string | undefined {\n const source = (event as any).entityId ?? event.entity ?? (event as RemoveEvent<any>).databaseEntity\n if (!source) return undefined\n const column = event.metadata.columns.find(one => one.referencedColumn?.entityMetadata.target === target)\n if (!column) return undefined\n const value = column.getEntityValue(source) ?? source[column.propertyName] ?? source[column.databaseName]\n return idOf(value)\n}\n\n/** The domain of a role, read in the same transaction - a role being deleted has none left to read. */\nasync function domainOfRole(event: InsertEvent<any> | RemoveEvent<any>, roleId: string) {\n const role = await event.manager.getRepository(Role).findOne({ where: { id: roleId }, relations: ['domain'] })\n return role?.domain?.id\n}\n\n/**\n * ── Grants are junction rows ──────────────────────────────────────────────\n *\n * A role given to a user is a `users_roles` row; a privilege given to a role, a `roles_privileges`\n * row. When only those change, TypeORM updates no entity and sends no update event - it inserts and\n * removes junction rows, and those it does announce. So grants are read here, from the junction, for\n * every path that saves a user's roles or a role's privileges, a new user's or role's included.\n *\n * This listens to every entity (a junction has no class to name) and leaves at once on anything\n * that is not one of the two junctions.\n */\n@EventSubscriber()\nexport class GrantAuditSubscriber implements EntitySubscriberInterface<any> {\n async afterInsert(event: InsertEvent<any>) {\n await this.record(event, 'insert')\n }\n\n async afterRemove(event: RemoveEvent<any>) {\n await this.record(event, 'remove')\n }\n\n private async record(event: InsertEvent<any> | RemoveEvent<any>, change: 'insert' | 'remove') {\n if (!event.metadata.isJunction) return\n\n const roleId = junctionIdOf(event, Role)\n const userId = junctionIdOf(event, User)\n const privilegeId = junctionIdOf(event, Privilege)\n if (!roleId) return\n\n const domainId = await domainOfRole(event, roleId)\n const where = { manager: event.manager, ...(domainId ? { domainId } : {}) }\n\n if (userId) {\n await recordAuditAction(\n {\n kind: change === 'insert' ? 'role.grant' : 'role.revoke',\n targetKind: 'User',\n targetIds: [userId],\n targetRole: 'handled',\n objectKind: 'Role',\n objectId: roleId\n },\n where\n )\n } else if (privilegeId) {\n await recordAuditAction(\n {\n kind: change === 'insert' ? 'role.privilege.add' : 'role.privilege.remove',\n targetKind: 'Role',\n targetIds: [roleId],\n targetRole: 'handled',\n objectKind: 'Privilege',\n objectId: privilegeId\n },\n where\n )\n }\n }\n}\n\n@EventSubscriber()\nexport class UserAuditSubscriber implements EntitySubscriberInterface<User> {\n listenTo() {\n return User\n }\n\n async afterUpdate(event: UpdateEvent<User>) {\n const user = event.entity as User | undefined\n const before = event.databaseEntity as User | undefined\n const userId = user?.id ?? before?.id\n if (!user || !before || !userId) return\n\n const target = { targetKind: 'User', targetIds: [userId], targetRole: 'handled' as const }\n\n if (user.status !== undefined && user.status !== before.status) {\n await recordAuditAction(\n { kind: 'user.status', ...target, detail: { from: before.status ?? null, to: user.status } },\n { manager: event.manager }\n )\n }\n\n if (user.password !== undefined && user.password !== before.password) {\n /* One's own change, or somebody else setting it - the actor tells which. */\n const actorId = currentAuditScope()?.context?.state?.user?.id\n const kind = actorId && actorId !== userId ? 'password.reset-by-admin' : 'password.change'\n await recordAuditAction({ kind, ...target }, { manager: event.manager })\n }\n\n if (user.credentialSerial !== undefined && user.credentialSerial !== before.credentialSerial) {\n await recordAuditAction({ kind: 'credential.issue', ...target }, { manager: event.manager })\n }\n }\n}\n\n@EventSubscriber()\nexport class DomainOwnerAuditSubscriber implements EntitySubscriberInterface<DomainOwner> {\n listenTo() {\n return DomainOwner\n }\n\n async afterInsert(event: InsertEvent<DomainOwner>) {\n const owner = event.entity\n const userId = idOf(owner?.user)\n const domainId = idOf(owner?.domain)\n if (!userId) return\n\n await recordAuditAction(\n { kind: 'domain.owner.add', targetKind: 'User', targetIds: [userId], targetRole: 'handled' },\n { manager: event.manager, ...(domainId ? { domainId } : {}) }\n )\n }\n}\n\n@EventSubscriber()\nexport class WebAuthCredentialAuditSubscriber implements EntitySubscriberInterface<WebAuthCredential> {\n listenTo() {\n return WebAuthCredential\n }\n\n async afterInsert(event: InsertEvent<WebAuthCredential>) {\n const userId = idOf(event.entity?.user)\n if (!userId) return\n\n await recordAuditAction(\n { kind: 'webauthn.register', targetKind: 'User', targetIds: [userId], targetRole: 'handled' },\n { manager: event.manager, actorId: userId }\n )\n }\n}\n\nexport const auditSubscribers = [\n GrantAuditSubscriber,\n UserAuditSubscriber,\n DomainOwnerAuditSubscriber,\n WebAuthCredentialAuditSubscriber\n]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-target.js","sourceRoot":"","sources":["../../../server/service/audit/audit-target.ts"],"names":[],"mappings":";;;AAeA,kCAOC;AAGD,0CAIC;AAOD,kCAIC;;AAxCD,sEAA6B;AAE7B;;;;;;;GAOG;AACU,QAAA,4BAA4B,GAAG,IAAA,qBAAG,EAAA;;CAE9C,CAAA;AAED,sGAAsG;AACtG,SAAgB,WAAW,CAAC,IAAqC,EAAE,GAAW;IAC5E,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAElG,OAAO,MAAM;SACV,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAChH,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AACvC,CAAC;AAED,mGAAmG;AACnG,SAAgB,eAAe,CAAC,MAAW;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC,MAAM,CAAA;IAC/C,IAAI,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;IACrE,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW,CAAC,KAAU;IACpC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IAC3E,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,iCAAiC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3G,OAAO,IAAI,IAAI,OAAO,CAAA;AACxB,CAAC","sourcesContent":["import gql from 'graphql-tag'\n\n/**\n * `@auditTarget(kind: \"User\", arg: \"id\")` - which argument of a door names what it acts on\n * (ADR-0141 §3.3). The server declares it beside the field; the audit does not guess from argument\n * names. What it reads is the **requested** target: what the caller named. What a service actually\n * handled - an id created, a set changed in bulk - the service records itself.\n *\n * Read by the `@privilege` wrapper, so it only means something on a field that carries `@privilege`.\n */\nexport const auditTargetDirectiveTypeDefs = gql`\n directive @auditTarget(kind: String!, arg: String!) on FIELD_DEFINITION\n`\n\n/** Ids named by `args[arg]`: a string, a list of strings, an object with `id`, or a list of those. */\nexport function targetIdsOf(args: Record<string, any> | undefined, arg: string): string[] {\n const value = args?.[arg]\n const values = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value]\n\n return values\n .map(one => (typeof one === 'string' || typeof one === 'number' ? String(one) : one?.id ? String(one.id) : null))\n .filter((id): id is string => !!id)\n}\n\n/** How many items a list answer holds: an array, or `{ items }`. Not a list - nothing to count. */\nexport function returnedCountOf(result: any): number | undefined {\n if (Array.isArray(result)) return result.length\n if (result && Array.isArray(result.items)) return result.items.length\n return undefined\n}\n\n/**\n * A fixed code for an error - never its message (ADR-0141 §3.4). Codes are the names a program gave\n * in a code field (`FORBIDDEN`, `password-not-matched`, `user not found`, `SQLITE_CONSTRAINT`); the\n * message is never read, and a code field that does not look like a name is `error`.\n */\nexport function errorCodeOf(error: any): string {\n const candidates = [error?.errorCode, error?.extensions?.code, error?.code]\n const code = candidates.find(one => typeof one === 'string' && /^[A-Za-z][A-Za-z0-9 _.-]{0,63}$/.test(one))\n return code ?? 'error'\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-types.js","sourceRoot":"","sources":["../../../server/service/audit/audit-types.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { User } from '../user/user.js'\nimport { AuditAction } from './audit-action.js'\nimport { AuditRequest } from './audit-request.js'\n\n@InputType({ description: 'What to narrow the audit records to.' })\nexport class AuditRecordFilter {\n @Field({ description: 'From this moment.' })\n from: Date\n\n @Field({ description: 'Up to this moment.' })\n to: Date\n\n @Field({ nullable: true, description: 'Only requests by this user.' })\n actorId?: string\n\n @Field({ nullable: true, description: 'Only requests that passed through this door (category:privilege).' })\n door?: string\n\n @Field({ nullable: true, description: 'Only requests with an action of this kind.' })\n kind?: string\n\n @Field({ nullable: true, description: 'denied, error or failed - only requests where that happened.' })\n outcome?: string\n\n @Field(type => Int, { nullable: true, description: 'Page, from 1.' })\n page?: number\n\n @Field(type => Int, { nullable: true, description: 'Rows per page, up to 200.' })\n limit?: number\n}\n\n@ObjectType({ description: 'A request with what was done in it.' })\nexport class AuditRecord {\n @Field(type => AuditRequest, { description: 'The request.' })\n request: AuditRequest\n\n @Field(type => [AuditAction], { description: 'Its actions in this domain.' })\n actions: AuditAction[]\n}\n\n@ObjectType({ description: 'A page of audit records.' })\nexport class AuditRecordList {\n @Field(type => [AuditRecord], { description: 'The records on this page.' })\n items: AuditRecord[]\n\n @Field(type => Int, { description: 'How many requests match.' })\n total: number\n}\n\n@ObjectType({ description: \"One member's audit summary over a period.\" })\nexport class AuditPerson {\n @Field(type => User, { description: 'The member.' })\n user: User\n\n @Field(type => [String], { description: 'Names of the roles held in this domain.' })\n roles: string[]\n\n @Field({ nullable: true, description: 'The last check-in to this domain, at any time.' })\n lastCheckinAt?: Date\n\n @Field({ nullable: true, description: \"The member's latest request to this domain, at any time - reads an open screen makes by itself included.\" })\n lastUsedAt?: Date\n\n @Field(type => Int, { description: 'Check-ins in the period.' })\n checkins: number\n\n @Field(type => Int, { description: 'Failed sign-ins in the period.' })\n failedSignins: number\n\n @Field(type => Int, { description: 'Door checks passed in the period, audit reads left out.' })\n granted: number\n\n @Field(type => Int, { description: 'Door checks refused in the period.' })\n denied: number\n}\n\n@ObjectType({ description: \"One door's audit summary over a period.\" })\nexport class AuditDoor {\n @Field({ description: 'The door, as category:privilege - or owner / super.' })\n door: string\n\n @Field({ nullable: true, description: 'The category, when the door names a privilege.' })\n category?: string\n\n @Field({ nullable: true, description: 'The privilege, when the door names one.' })\n privilege?: string\n\n @Field(type => Int, { description: 'People who passed or were refused here in the period.' })\n people: number\n\n @Field(type => Int, { description: 'Checks passed in the period.' })\n granted: number\n\n @Field(type => Int, { description: 'Checks refused in the period.' })\n denied: number\n}\n\n@ObjectType({ description: 'Audit writes this server process failed, counted apart from the audit store.' })\nexport class AuditHealth {\n @Field({ description: 'When this process started counting.' })\n since: Date\n\n @Field(type => Int, { description: 'Writes that failed since then. Writes never attempted are not counted.' })\n failures: number\n\n @Field({ nullable: true, description: 'The first failure.' })\n firstFailedAt?: Date\n\n @Field({ nullable: true, description: 'The last failure.' })\n lastFailedAt?: Date\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-work.js","sourceRoot":"","sources":["../../../server/service/audit/audit-work.ts"],"names":[],"mappings":"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","sourcesContent":["import { Between, EntityManager, In } from 'typeorm'\n\nimport { AuditAction } from './audit-action.js'\nimport { AuditRequest } from './audit-request.js'\n\n/*\n * Work done through the system's doors (ADR-0185 decision 6, Q5) - read from the audit, never kept twice. A module\n * declares which of its mutations are a piece of work and under what name (\"the bank lines kept\", \"the payroll worked\n * on\"); a report of one's week reads, from the audit, how many times a person did each on each day. A mutation no\n * module declared - a save of one's own draft, a read - is not work here; nor is one that failed.\n *\n * The name is a translation key of the declaring module: the screen says it in the reader's words.\n */\n\nexport interface WorkDoor {\n /** The translation key that names the work - `work.<module>.<what>`. */\n work: string\n /** The GraphQL mutation fields that do it. */\n fields: readonly string[]\n}\n\nconst WORK = new Map<string, string>()\n\n/** Declares a module's mutations that are a piece of work. A field is one work only. */\nexport function registerWorkDoors(doors: readonly WorkDoor[]) {\n for (const door of doors)\n for (const field of door.fields) {\n const held = WORK.get(field)\n if (held && held !== door.work) throw new Error(`The mutation \"${field}\" is declared as the work \"${held}\" and \"${door.work}\".`)\n WORK.set(field, door.work)\n }\n}\n\n/** The work a mutation field is declared as, if any. */\nexport const workOfField = (field: string) => WORK.get(field)\n\nexport interface WorkDone {\n /** When the request was made. */\n at: Date\n /** The work's translation key. */\n work: string\n /** The request it was done in. */\n requestId: string\n}\n\n/** Each declared piece of work a person did in [from, to) - one per request and work, the requests that went through. */\nexport async function workDoneBy(tx: EntityManager, domain: { id: string }, actorId: string, from: Date, to: Date): Promise<WorkDone[]> {\n if (!WORK.size) return []\n const requests = await tx.getRepository(AuditRequest).find({\n where: { domain: { id: domain.id }, actor: { id: actorId }, operationType: 'mutation', createdAt: Between(from, new Date(to.getTime() - 1)) } as any,\n order: { createdAt: 'ASC' } as any\n })\n const declared = requests\n .map(request => ({ request, works: [...new Set(String(request.fields ?? '').split(',').map(field => WORK.get(field.trim())).filter(Boolean))] as string[] }))\n .filter(one => one.works.length)\n if (!declared.length) return []\n const results = await tx.getRepository(AuditAction).find({ where: { requestId: In(declared.map(one => one.request.id)), kind: 'door.result' } as any })\n const went = new Set(results.filter(one => one.outcome === 'ok').map(one => one.requestId))\n const failed = new Set(results.filter(one => one.outcome === 'error').map(one => one.requestId))\n return declared\n .filter(one => went.has(one.request.id) && !failed.has(one.request.id))\n .flatMap(one => one.works.map(work => ({ at: one.request.createdAt, work, requestId: one.request.id })))\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/audit/index.ts"],"names":[],"mappings":";;;AAAA,uDAA+C;AAC/C,qDAA6C;AAC7C,yDAAiD;AACjD,+DAAwD;AAE3C,QAAA,QAAQ,GAAG,CAAC,+BAAY,EAAE,6BAAW,CAAC,CAAA;AACtC,QAAA,SAAS,GAAG,CAAC,2BAAU,CAAC,CAAA;AACxB,QAAA,WAAW,GAAG,sCAAgB,CAAA","sourcesContent":["import { AuditAction } from './audit-action.js'\nimport { AuditQuery } from './audit-query.js'\nimport { AuditRequest } from './audit-request.js'\nimport { auditSubscribers } from './audit-subscriber.js'\n\nexport const entities = [AuditRequest, AuditAction]\nexport const resolvers = [AuditQuery]\nexport const subscribers = auditSubscribers\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider-mutation.js","sourceRoot":"","sources":["../../../server/service/auth-provider/auth-provider-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAsE;AACtE,qCAA4B;AAE5B,yDAAiD;AACjD,mEAA4E;AAGrE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAIzB,AAAN,KAAK,CAAC,kBAAkB,CACD,YAA6B,EAC3C,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,OAAO,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,IAAI,CAAC;YAC/C,GAAG,YAAY;YACf,MAAM;YACN,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;IACJ,CAAC;IAKK,AAAN,KAAK,CAAC,kBAAkB,CACX,EAAU,EACP,KAAwB,EAC/B,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAA;QACjD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;YAC5C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;SACzC,CAAC,CAAA;QAEF,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC;YAC3B,GAAG,YAAY;YACf,GAAG,KAAK;YACR,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;IACJ,CAAC;IAKK,AAAN,KAAK,CAAC,0BAA0B,CACe,OAA4B,EAClE,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,IAAI,OAAO,GAAG,EAAE,CAAA;QAChB,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,CAAA;QAC3E,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;QAEzF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBAEnC,IAAI,iBAAiB,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,OAAO,CAAC;oBACnE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE;iBAC3D,CAAC,CAAA;gBAEF,IAAI,iBAAiB,EAAE,CAAC;oBACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBAClD,CAAC;gBAED,MAAM,MAAM,GAAiB,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,IAAI,CAAC;oBACrE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,IAAI;oBACb,GAAG,SAAS;iBACb,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBACvC,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,OAAO,CAAC;oBAChE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE;iBAC3D,CAAC,CAAA;gBAEF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,IAAI,CAAC;oBACvD,GAAG,YAAY;oBACf,GAAG,aAAa;oBAChB,OAAO,EAAE,IAAI;iBACd,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAKK,AAAN,KAAK,CAAC,kBAAkB,CAAY,EAAU,EAAS,OAAwB;QAC7E,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAE9E,OAAO,IAAI,CAAA;IACb,CAAC;IAKK,AAAN,KAAK,CAAC,mBAAmB,CACO,GAAa,EACpC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,IAAI,CAAC;YAC9D,KAAK,EAAE;gBACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,EAAE,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC;aACZ;SACF,CAAC,CAAA;QAEF,MAAM,OAAO,CAAC,GAAG,CACf,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,YAA0B,EAAE,EAAE;YACrD,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAC,IAAI,CAAC;gBACxC,GAAG,YAAY;gBACf,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,OAAO,EAAE,IAAI;aACd,CAAC,CAAA;QACJ,CAAC,CAAC,CACH,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAKK,AAAN,KAAK,CAAC,4BAA4B,CAAY,EAAU,EAAS,OAAwB;QACvF,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,+BAAY,CAAC,CAAA;QACjD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;YAC5C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;YACxC,SAAS,EAAE,CAAC,QAAQ,CAAC;SACtB,CAAC,CAAA;QAEF,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,CAAA;QAC7B,MAAM,EAAE,gBAAgB,EAAE,GAAG,+BAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;QAEzE,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,MAAM,gBAAgB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,GAAG,CAAC,CAAA;QAC/D,CAAC;IACH,CAAC;CACF,CAAA;AA5JY,oDAAoB;AAIzB;IAHL,IAAA,wBAAS,EAAC,+EAA+E,CAAC;IAC1F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,+BAAY,EAAE,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAE9E,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD6B,uCAAe;;8DAWnD;AAKK;IAHL,IAAA,wBAAS,EAAC,+EAA+E,CAAC;IAC1F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,+BAAY,EAAE,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;IAEtF,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IACT,mBAAA,IAAA,kBAAG,EAAC,OAAO,CAAC,CAAA;IACZ,mBAAA,IAAA,kBAAG,GAAE,CAAA;;qDADe,yCAAiB;;8DAevC;AAKK;IAHL,IAAA,wBAAS,EAAC,+EAA+E,CAAC;IAC1F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,+BAAY,CAAC,CAAC;IAEjC,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,yCAAiB,CAAC,CAAC,CAAA;IAC3C,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;sEAiDP;AAKK;IAHL,IAAA,wBAAS,EAAC,+EAA+E,CAAC;IAC1F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;IAC9C,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;8DAMrD;AAKK;IAHL,IAAA,wBAAS,EAAC,+EAA+E,CAAC;IAC1F,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC;IAE1B,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;+DAqBP;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,mCAAmC,CAAC;IAC9C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;IACjD,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wEAiB/D;+BA3JU,oBAAoB;IADhC,IAAA,uBAAQ,EAAC,+BAAY,CAAC;GACV,oBAAoB,CA4JhC","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { AuthProvider } from './auth-provider.js'\nimport { NewAuthProvider, AuthProviderPatch } from './auth-provider-type.js'\n\n@Resolver(AuthProvider)\nexport class AuthProviderMutation {\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => AuthProvider, { description: 'To create new AuthProvider' })\n async createAuthProvider(\n @Arg('authProvider') authProvider: NewAuthProvider,\n @Ctx() context: ResolverContext\n ): Promise<AuthProvider> {\n const { domain, user, tx } = context.state\n\n return await tx.getRepository(AuthProvider).save({\n ...authProvider,\n domain,\n creator: user,\n updater: user\n })\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => AuthProvider, { description: 'To modify AuthProvider information' })\n async updateAuthProvider(\n @Arg('id') id: string,\n @Arg('patch') patch: AuthProviderPatch,\n @Ctx() context: ResolverContext\n ): Promise<AuthProvider> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(AuthProvider)\n const authProvider = await repository.findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n return await repository.save({\n ...authProvider,\n ...patch,\n updater: user\n })\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [AuthProvider])\n async updateMultipleAuthProvider(\n @Arg('patches', type => [AuthProviderPatch]) patches: AuthProviderPatch[],\n @Ctx() context: ResolverContext\n ): Promise<AuthProvider[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n let foundAuthProvider = await tx.getRepository(AuthProvider).findOne({\n where: { domain: { id: domain.id }, type: newRecord.type }\n })\n\n if (foundAuthProvider) {\n throw new Error('Duplicated authProvider found')\n }\n\n const result: AuthProvider = await tx.getRepository(AuthProvider).save({\n domain: domain,\n creator: user,\n updater: user,\n ...newRecord\n })\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updatedRecord = _updateRecords[i]\n const authProvider = await tx.getRepository(AuthProvider).findOne({\n where: { domain: { id: domain.id }, id: updatedRecord.id }\n })\n\n const result = await tx.getRepository(AuthProvider).save({\n ...authProvider,\n ...updatedRecord,\n updater: user\n })\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete AuthProvider' })\n async deleteAuthProvider(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await tx.getRepository(AuthProvider).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Boolean)\n async deleteAuthProviders(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<Boolean> {\n const { domain, user, tx } = context.state\n\n const authProviders = await tx.getRepository(AuthProvider).find({\n where: {\n domain: { id: domain.id },\n id: In(ids)\n }\n })\n\n await Promise.all(\n authProviders.map(async (authProvider: AuthProvider) => {\n await tx.getRepository(AuthProvider).save({\n ...authProvider,\n deletedAt: new Date(),\n updater: user\n })\n })\n )\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted:true)')\n @Mutation(returns => Boolean, { description: 'To synchronize auth-providers users' })\n async synchronizeAuthProviderUsers(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(AuthProvider)\n const authProvider = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['domain']\n })\n\n const { type } = authProvider\n const { synchronizeUsers } = AuthProvider.getAuthProviderImpl(type) || {}\n\n if (synchronizeUsers) {\n return await synchronizeUsers(authProvider, context)\n } else {\n throw new Error(`No AuthProviderImpl for the type '${type}'`)\n }\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider-parameter-spec.js","sourceRoot":"","sources":["../../../server/service/auth-provider/auth-provider-parameter-spec.ts"],"names":[],"mappings":";;;;AAAA,+CAAgD;AAEhD,iDAAoD;AAK7C,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAqBrC,CAAA;AArBY,8DAAyB;AAEpC;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;;uDAC5E;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;;wDACtE;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,kEAAkE,EAAE,CAAC;;uDAC/E;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;;8DAC5D;AAMpB;IAJC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE;QAC3B,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,2DAA2D;KACzE,CAAC;;2DAC+B;AAGjC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;;yDACjE;oCApBpB,yBAAyB;IAHrC,IAAA,yBAAU,EAAC;QACV,WAAW,EAAE,4EAA4E;KAC1F,CAAC;GACW,yBAAyB,CAqBrC","sourcesContent":["import { Field, ObjectType } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\n@ObjectType({\n description: 'Describes a single configuration parameter for an authentication provider.'\n})\nexport class AuthProviderParameterSpec {\n @Field({ description: 'The data type of the parameter (e.g., text, number, boolean).' })\n type: string\n\n @Field({ description: 'The human-readable label for the parameter, shown in UI.' })\n label: string\n\n @Field({ description: 'The name of the parameter, used as the key in the params object.' })\n name: string\n\n @Field({ nullable: true, description: 'Placeholder text for the input field.' })\n placeholder?: string\n\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'Additional properties for the parameter (e.g., min, max).'\n })\n property?: { [key: string]: any }\n\n @Field(type => ScalarObject, { nullable: true, description: 'CSS styles for the input field.' })\n styles?: { [key: string]: any }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider-query.js","sourceRoot":"","sources":["../../../server/service/auth-provider/auth-provider-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\nimport { Domain, getQueryBuilderFromListParams, InheritedValueType, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '../user/user.js'\nimport { AuthProvider, AuthProviderTypeList } from './auth-provider.js'\nimport { AuthProviderList } from './auth-provider-type.js'\n\n@Resolver(AuthProvider)\nexport class AuthProviderQuery {\n @Query(returns => AuthProviderTypeList!, { nullable: true, description: 'To fetch a AuthProvider' })\n authProviderTypes(@Ctx() context: ResolverContext): AuthProviderTypeList {\n const { domain } = context.state\n\n return AuthProvider.getAuthProviderTypes()\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => AuthProvider!, { nullable: true, description: 'To fetch a AuthProvider' })\n async authProvider(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AuthProvider> {\n const { domain } = context.state\n\n return await getRepository(AuthProvider).findOne({\n where: { domain: { id: domain.id }, id }\n })\n }\n\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => AuthProviderList, { description: 'To fetch multiple AuthProviders' })\n async authProviders(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<AuthProviderList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n // this domain's rows only - a parent domain's are another tenant's, whatever `inherited` the caller sent\n params: { ...params, inherited: InheritedValueType.None },\n repository: await getRepository(AuthProvider),\n searchables: ['type']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => String)\n clientSecret(@Root() authProvider: AuthProvider): string {\n const clientSecret = authProvider.clientSecret\n\n if (!clientSecret || clientSecret.length <= 2) {\n return clientSecret // 입력 문자열의 길이가 2 이하인 경우 그대로 반환\n }\n const firstChar = clientSecret.charAt(0)\n const lastChar = clientSecret.charAt(clientSecret.length - 1)\n const maskedPart = '*'.repeat(clientSecret.length - 2)\n\n return firstChar + maskedPart + lastChar\n }\n\n @FieldResolver(type => String)\n privateKey(@Root() authProvider: AuthProvider): string {\n const privateKey = authProvider.privateKey\n\n if (!privateKey || privateKey.length <= 2) {\n return privateKey // 입력 문자열의 길이가 2 이하인 경우 그대로 반환\n }\n const firstChar = privateKey.charAt(0)\n const lastChar = privateKey.charAt(privateKey.length - 1)\n const maskedPart = '*'.repeat(privateKey.length - 2)\n\n return firstChar + maskedPart + lastChar\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() authProvider: AuthProvider): Promise<Domain> {\n return authProvider.domainId && (await getRepository(Domain).findOneBy({ id: authProvider.domainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() authProvider: AuthProvider): Promise<User> {\n return authProvider.updaterId && (await getRepository(User).findOneBy({ id: authProvider.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() authProvider: AuthProvider): Promise<User> {\n return authProvider.creatorId && (await getRepository(User).findOneBy({ id: authProvider.creatorId }))\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider-type.js","sourceRoot":"","sources":["../../../server/service/auth-provider/auth-provider-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\nimport { AuthProvider } from './auth-provider.js'\n\n@InputType({ description: 'Input for creating a new authentication provider instance.' })\nexport class NewAuthProvider {\n @Field({ description: 'The type of the authentication provider (e.g., keycloak, google).' })\n type: string\n\n @Field({ nullable: true, description: 'Whether the new provider instance should be active.' })\n active?: boolean\n\n @Field({ nullable: true, description: 'Tenant ID, for multi-tenant providers.' })\n tenantId?: string\n\n @Field({ nullable: true, description: 'Client ID for OAuth/OIDC providers.' })\n clientId?: string\n\n @Field({ nullable: true, description: 'Client secret for OAuth/OIDC providers.' })\n clientSecret?: string\n\n @Field({ nullable: true, description: 'Private key, for certain types of providers.' })\n privateKey?: string\n\n @Field(type => ScalarObject, { nullable: true, description: 'Provider-specific parameters.' })\n params?: { [key: string]: any }\n}\n\n@InputType({ description: 'Input for updating (patching) an existing authentication provider instance.' })\nexport class AuthProviderPatch {\n @Field(type => ID, { nullable: true, description: 'The unique identifier of the provider instance to update.' })\n id?: string\n\n @Field({ nullable: true, description: 'The new type for the provider.' })\n type?: string\n\n @Field({ nullable: true, description: 'The new active status for the provider.' })\n active?: boolean\n\n @Field({ nullable: true, description: 'The new tenant ID for the provider.' })\n tenantId?: string\n\n @Field({ nullable: true, description: 'The new client ID for the provider.' })\n clientId?: string\n\n @Field({ nullable: true, description: 'The new client secret for the provider.' })\n clientSecret?: string\n\n @Field({ nullable: true, description: 'The new private key for the provider.' })\n privateKey?: string\n\n @Field(type => ScalarObject, { nullable: true, description: 'The new provider-specific parameters.' })\n params?: { [key: string]: any }\n\n @Field({\n nullable: true,\n description: 'A flag indicating whether the provider is being created, updated, or deleted.'\n })\n cuFlag?: string\n}\n\n@ObjectType({ description: 'A paginated list of configured authentication provider instances.' })\nexport class AuthProviderList {\n @Field(type => [AuthProvider], { description: 'The list of authentication provider items.' })\n items: AuthProvider[]\n\n @Field(type => Int, { description: 'The total number of authentication providers.' })\n total: number\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../../../server/service/auth-provider/auth-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n OneToMany,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { Directive, ObjectType, Field, Int, ID } from 'type-graphql'\n\nimport { Domain, ScalarObject, encryptTransformer } from '@things-factory/shell'\nimport { User } from '../user/user.js'\nimport { UsersAuthProviders } from '../users-auth-providers/users-auth-providers.js'\nimport { AuthProviderParameterSpec } from './auth-provider-parameter-spec.js'\n\nexport type AuthProviderImpl = {\n type: string\n description: string\n help: string\n parameterSpec: AuthProviderParameterSpec\n synchronizeUsers: (authProvider: AuthProvider, context: ResolverContext) => Promise<boolean>\n}\n\nexport type AuthProviderRegistry = {\n [type: string]: AuthProviderImpl\n}\n\n@ObjectType({ description: 'Describes a type of authentication provider available in the system.' })\nexport class AuthProviderType {\n @Field({ description: 'The unique type name of the authentication provider (e.g., keycloak, google).' })\n type: string\n\n @Field({ nullable: true, description: 'A brief description of the authentication provider.' })\n description: string\n\n @Field({ nullable: true, description: 'Helpful information or a link to documentation for the provider.' })\n help: string\n\n @Field(type => [AuthProviderParameterSpec], {\n nullable: true,\n description: 'A list of parameters required to configure this authentication provider.'\n })\n parameterSpec: AuthProviderParameterSpec[]\n}\n\n@ObjectType({ description: 'A list of available authentication provider types.' })\nexport class AuthProviderTypeList {\n @Field(type => [AuthProviderType], { description: 'The list of authentication provider type items.' })\n items: AuthProviderType[]\n\n @Field(type => Int, { description: 'The total number of authentication provider types.' })\n total: number\n}\n\n@Entity()\n@Index('ix_auth_provider_0', (authProvider: AuthProvider) => [authProvider.domain, authProvider.type], {\n unique: true\n})\n@ObjectType({ description: 'Represents a configured instance of an authentication provider for a specific domain.' })\nexport class AuthProvider {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the configured authentication provider.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain to which this authentication provider belongs.' })\n domain?: Domain\n\n @RelationId((authProvider: AuthProvider) => authProvider.domain)\n domainId?: string\n\n @Column()\n @Field({ nullable: true, description: 'The type of the authentication provider (e.g., keycloak, google).' })\n type?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Indicates whether this authentication provider is currently active.' })\n active?: boolean\n\n @Directive('@privilege(category: \"security\", privilege: \"query\", domainOwnerGranted: true)')\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Tenant ID, used by some multi-tenant authentication providers.' })\n tenantId?: string\n\n @Directive('@privilege(category: \"security\", privilege: \"query\", domainOwnerGranted: true)')\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Client ID for OAuth/OIDC providers.' })\n clientId?: string\n\n @Directive('@privilege(category: \"security\", privilege: \"query\", domainOwnerGranted: true)')\n @Column({ nullable: true, transformer: encryptTransformer })\n @Field({ nullable: true, description: 'Client secret for OAuth/OIDC providers (stored encrypted).' })\n clientSecret?: string\n\n @Directive('@privilege(category: \"security\", privilege: \"query\", domainOwnerGranted: true)')\n @Column({ nullable: true, transformer: encryptTransformer })\n @Field({ nullable: true, description: 'Private key, used by some authentication providers (stored encrypted).' })\n privateKey?: string\n\n @Column('simple-json', { nullable: true })\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'A key-value map for additional provider-specific parameters.'\n })\n params?: { [key: string]: any }\n\n @OneToMany(() => UsersAuthProviders, usersAuthProviders => usersAuthProviders.authProvider)\n @Field(type => [UsersAuthProviders], {\n nullable: true,\n description: 'A list of user-provider associations for this provider.'\n })\n usersAuthProviders?: UsersAuthProviders[]\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when this provider instance was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when this provider instance was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created this provider instance.' })\n creator?: User\n\n @RelationId((authProvider: AuthProvider) => authProvider.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated this provider instance.' })\n updater?: User\n\n @RelationId((authProvider: AuthProvider) => authProvider.updater)\n updaterId?: string\n\n static registry = {}\n\n public static register(type: string, provider: AuthProviderImpl) {\n AuthProvider.registry[type] = provider\n }\n\n public static getAuthProviderTypes(): AuthProviderTypeList {\n const items = Object.values(AuthProvider.registry).map(({ type, description, help, parameterSpec }) => {\n return {\n type,\n description,\n help,\n parameterSpec\n }\n })\n\n return {\n items,\n total: items.length\n }\n }\n\n public static getAuthProviderImpl(type: string) {\n return AuthProvider.registry[type]\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/auth-provider/index.ts"],"names":[],"mappings":";;;AAAA,yDAAiD;AACjD,qEAA4D;AAC5D,2EAAkE;AAErD,QAAA,QAAQ,GAAG,CAAC,+BAAY,CAAC,CAAA;AACzB,QAAA,SAAS,GAAG,CAAC,0CAAiB,EAAE,gDAAoB,CAAC,CAAA;AACrD,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { AuthProvider } from './auth-provider.js'\nimport { AuthProviderQuery } from './auth-provider-query.js'\nimport { AuthProviderMutation } from './auth-provider-mutation.js'\n\nexport const entities = [AuthProvider]\nexport const resolvers = [AuthProviderQuery, AuthProviderMutation]\nexport const subscribers = []\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"domain-generator-mutation.js","sourceRoot":"","sources":["../../../server/service/domain-generator/domain-generator-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\nimport { ILike, In, Repository } from 'typeorm'\n\nimport { Domain, getRepository } from '@things-factory/shell'\nimport { slugger } from '@things-factory/utils'\n\nimport { setPrimaryDomainOwner } from '../../utils/domain-ownership.js'\nimport { Privilege } from '../privilege/privilege.js'\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\nimport { DomainGeneratorInput, DomainUserRoleInput } from './domain-generator-types.js'\n\n@Resolver()\nexport class DomainGeneratorMutation {\n @Directive('@privilege(superUserGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Domain)\n async domainRegister(\n @Arg('domainInput') domainInput: DomainGeneratorInput,\n @Ctx() context: ResolverContext\n ): Promise<Domain> {\n const { user } = context.state\n const { name, description } = domainInput\n const domainRepo: Repository<Domain> = getRepository(Domain)\n const subdomain: string = slugger(name)\n\n const domain: Domain = await domainRepo.findOneBy({ subdomain })\n if (domain) {\n throw new Error('domain is duplicated')\n }\n\n const newDomain: Domain = await domainRepo.save({ name, description, subdomain })\n\n /* 대표 오너 컬럼과 `DomainOwner` 테이블을 함께 세팅한다 (컬럼만 쓰면 오너 목록에 나오지 않는다). */\n await setPrimaryDomainOwner(newDomain, user.id, user)\n\n return await domainRepo.findOneBy({ id: newDomain.id })\n }\n\n /* `domainRegister` beside it makes a domain and is super-user only. This makes a domain,\n its roles and its users, and carried nothing at all. */\n @Directive('@privilege(superUserGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => Domain)\n async domainUserRoleRegister(\n @Arg('newDomainInfo') newDomainInfo: DomainUserRoleInput,\n @Ctx() context: ResolverContext\n ): Promise<Domain> {\n const { tx } = context.state\n // 도메인 생성\n const { domain, users, roles } = newDomainInfo\n const domainOwner = users.find(user => user.owner === true)\n\n const domainRepository: Repository<Domain> = tx.getRepository(Domain)\n const roleRepository: Repository<Role> = tx.getRepository(Role)\n const userRepository: Repository<User> = tx.getRepository(User)\n const privilegeRepository: Repository<Privilege> = tx.getRepository(Privilege)\n\n const subdomain: string = slugger(domain.name)\n\n const newDomain = await domainRepository.save({\n name: domain.name,\n description: domain.description,\n subdomain\n })\n\n // 역할 생성\n const newRoles: Role[] = await Promise.all(\n roles.map(async (role: Role) => {\n if (role.privileges?.length) {\n const privilegeIds: string[] = role.privileges.map((p: Privilege) => p.id)\n role.privileges = await privilegeRepository.findBy({\n id: In(privilegeIds)\n })\n }\n\n role.domain = newDomain\n return await roleRepository.save(role)\n })\n )\n\n // 사용자 생성\n let inviteUsers = []\n let createUsers = []\n users.forEach(user => (user.isInvitee ? inviteUsers.push(user) : createUsers.push(user)))\n\n // create user\n await Promise.all(\n createUsers.map(async user => {\n user.domains = [newDomain]\n user.password = User.encode(user.password, user.salt)\n user.salt = User.generateSalt()\n user.passwordUpdatedAt = new Date()\n user.userType = 'user'\n user.roles = filterUserRoles(user.roles, newRoles)\n\n return await userRepository.save(user)\n })\n )\n\n // invite user\n await Promise.all(\n inviteUsers.map(async inviteUser => {\n const user: User = await userRepository.findOne({\n where: { email: inviteUser.email },\n relations: ['domains', 'roles']\n })\n\n user.domains = [...user.domains, newDomain]\n user.roles = [...user.roles, ...filterUserRoles(inviteUser.roles, newRoles)]\n\n return await userRepository.save(user)\n })\n )\n\n // domain owner — 대표 오너 컬럼과 `DomainOwner` 테이블을 함께 세팅한다.\n const { id } = await userRepository.findOne({ where: { email: ILike(domainOwner.email) } })\n await setPrimaryDomainOwner(newDomain, id, context.state.user, tx)\n\n return await domainRepository.findOneBy({ id: newDomain.id })\n }\n}\n\nfunction filterUserRoles(userRoles: Role[], newRoles: Role[]): Role[] {\n const userRoleNames: string[] = userRoles.map((r: Role) => r.name)\n return newRoles.filter((r: Role) => userRoleNames.indexOf(r.name) >= 0)\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"domain-generator-types.js","sourceRoot":"","sources":["../../../server/service/domain-generator/domain-generator-types.ts"],"names":[],"mappings":";;;;AAAA,+CAA+C;AAC/C,qDAAqD;AACrD,iDAAmD;AACnD,yDAA+C;AAGxC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAMhC,CAAA;AANY,oDAAoB;AAE/B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;;kDAC1C;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;;yDACxD;+BALT,oBAAoB;IADhC,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;GACpD,oBAAoB,CAMhC;AAGM,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAS/B,CAAA;AATY,kDAAmB;AAE9B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,mBAAW,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;sCACpF,mBAAW;mDAAA;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,0BAA0B,CAAC,EAAE,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;kDAClF;AAGnC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,uBAAO,CAAC,EAAE,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;kDAClF;8BARL,mBAAmB;IAD/B,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;GAC3F,mBAAmB,CAS/B;AAGM,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;CAqBtC,CAAA;AArBY,gEAA0B;AAErC;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;wDAC7C;AAGZ;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,qCAAmB,EAAE,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;;yDAC7E;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6EAA6E,EAAE,CAAC;;4DACtG;AAMhB;IAJC,IAAA,oBAAK,EAAC;QACL,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,qFAAqF;KACnG,CAAC;sCACS,OAAO;6DAAA;AAGlB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;sCAC1E,OAAO;yDAAA;AAGd;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,uBAAO,CAAC,EAAE,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;;yDAC7E;qCApBL,0BAA0B;IADtC,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,sEAAsE,EAAE,CAAC;GACtF,0BAA0B,CAqBtC","sourcesContent":["import { Field, InputType } from 'type-graphql'\nimport { GraphQLEmailAddress } from 'graphql-scalars'\nimport { DomainInput } from '@things-factory/shell'\nimport { NewRole } from '../role/role-types.js'\n\n@InputType({ description: 'Input for generating a new domain.' })\nexport class DomainGeneratorInput {\n @Field({ description: 'The name of the new domain.' })\n name: string\n\n @Field({ nullable: true, description: 'A description for the new domain.' })\n description?: string\n}\n\n@InputType({ description: 'Input for the domain creation wizard, including domain, users, and roles.' })\nexport class DomainUserRoleInput {\n @Field(type => DomainInput, { description: 'The details of the new domain to be created.' })\n domain: DomainInput\n\n @Field(type => [NewUserByDomainWizardInput], { description: 'A list of new users to be created within the domain.' })\n users: NewUserByDomainWizardInput[]\n\n @Field(type => [NewRole], { description: 'A list of new roles to be created within the domain.' })\n roles: NewRole[]\n}\n\n@InputType({ description: 'Input for creating a new user as part of the domain creation wizard.' })\nexport class NewUserByDomainWizardInput {\n @Field({ description: 'The full name of the new user.' })\n name: string\n\n @Field(type => GraphQLEmailAddress, { description: 'The email address of the new user.' })\n email: string\n\n @Field({ nullable: true, description: 'The password for the new user. If not provided, an invitation will be sent.' })\n password: string\n\n @Field({\n nullable: true,\n description: 'Indicates whether the user should be invited via email instead of created directly.'\n })\n isInvitee: Boolean\n\n @Field({ description: 'Indicates whether this user is an owner of the domain.' })\n owner: Boolean\n\n @Field(type => [NewRole], { description: 'A list of roles to be assigned to the new user.' })\n roles: NewRole[]\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/domain-generator/index.ts"],"names":[],"mappings":";;;AAAA,iFAAwE;AAE3D,QAAA,SAAS,GAAG,CAAC,sDAAuB,CAAC,CAAA","sourcesContent":["import { DomainGeneratorMutation } from './domain-generator-mutation.js'\n\nexport const resolvers = [DomainGeneratorMutation]\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"domain-link-mutation.js","sourceRoot":"","sources":["../../../server/service/domain-link/domain-link-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAsE;AACtE,qCAA4B;AAC5B,iDAAqD;AAErD,qDAA6C;AAC7C,iEAAuE;AAGhE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAIvB,AAAN,KAAK,CAAC,gBAAgB,CACD,UAAyB,EACrC,OAAwB;QAE/B,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAElC,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,2BAAU,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;YACtD,GAAG,UAAU;YACb,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;QAEF,OAAO,MAAM,CAAA;IACf,CAAC;IAKK,AAAN,KAAK,CAAC,gBAAgB,CACT,EAAU,EACP,KAAsB,EAC7B,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,2BAAU,EAAE,EAAE,CAAC,CAAA;QAChD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;YAC1C,KAAK,EAAE,EAAE,EAAE,EAAE;SACd,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC;YACnC,GAAG,UAAU;YACb,GAAG,KAAK;YACR,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;QAEF,OAAO,MAAM,CAAA;IACf,CAAC;IAKK,AAAN,KAAK,CAAC,wBAAwB,CACe,OAA0B,EAC9D,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,IAAI,OAAO,GAAG,EAAE,CAAA;QAChB,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;QACzF,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;QACzF,MAAM,cAAc,GAAG,IAAA,qBAAa,EAAC,2BAAU,EAAE,EAAE,CAAC,CAAA;QAEpD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBAEnC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;oBACvC,GAAG,SAAS;oBACZ,MAAM;oBACN,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,IAAI;iBACd,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBACtC,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,CAAC,CAAA;gBAE1E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;oBACvC,GAAG,UAAU;oBACb,GAAG,YAAY;oBACf,OAAO,EAAE,IAAI;iBACd,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAKK,AAAN,KAAK,CAAC,gBAAgB,CAAY,EAAU,EAAS,OAAwB;QAC3E,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,IAAA,qBAAa,EAAC,2BAAU,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAElD,OAAO,IAAI,CAAA;IACb,CAAC;IAKK,AAAN,KAAK,CAAC,iBAAiB,CACS,GAAa,EACpC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,IAAA,qBAAa,EAAC,2BAAU,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;YACzC,EAAE,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC;SACZ,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AApHY,gDAAkB;AAIvB;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,2BAAU,EAAE,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;IAE1E,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADyB,oCAAa;;0DAY7C;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,2BAAU,EAAE,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;IAElF,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IACT,mBAAA,IAAA,kBAAG,EAAC,OAAO,CAAC,CAAA;IACZ,mBAAA,IAAA,kBAAG,GAAE,CAAA;;qDADe,sCAAe;;0DAiBrC;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,2BAAU,CAAC,EAAE,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;IAE/F,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,sCAAe,CAAC,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kEAwCP;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAC9C,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;0DAMnD;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;IAE7E,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DASP;6BAnHU,kBAAkB;IAD9B,IAAA,uBAAQ,EAAC,2BAAU,CAAC;GACR,kBAAkB,CAoH9B","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In } from 'typeorm'\nimport { getRepository } from '@things-factory/shell'\n\nimport { DomainLink } from './domain-link.js'\nimport { NewDomainLink, DomainLinkPatch } from './domain-link-types.js'\n\n@Resolver(DomainLink)\nexport class DomainLinkMutation {\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => DomainLink, { description: 'To create new DomainLink' })\n async createDomainLink(\n @Arg('domainLink') domainLink: NewDomainLink,\n @Ctx() context: ResolverContext\n ): Promise<DomainLink> {\n const { user, tx } = context.state\n\n const result = await getRepository(DomainLink, tx).save({\n ...domainLink,\n creator: user,\n updater: user\n })\n\n return result\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => DomainLink, { description: 'To modify DomainLink information' })\n async updateDomainLink(\n @Arg('id') id: string,\n @Arg('patch') patch: DomainLinkPatch,\n @Ctx() context: ResolverContext\n ): Promise<DomainLink> {\n const { domain, user, tx } = context.state\n\n const repository = getRepository(DomainLink, tx)\n const domainLink = await repository.findOne({\n where: { id }\n })\n\n const result = await repository.save({\n ...domainLink,\n ...patch,\n updater: user\n })\n\n return result\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => [DomainLink], { description: \"To modify multiple DomainLinks' information\" })\n async updateMultipleDomainLink(\n @Arg('patches', type => [DomainLinkPatch]) patches: DomainLinkPatch[],\n @Ctx() context: ResolverContext\n ): Promise<DomainLink[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const domainLinkRepo = getRepository(DomainLink, tx)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n const result = await domainLinkRepo.save({\n ...newRecord,\n domain,\n creator: user,\n updater: user\n })\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updateRecord = _updateRecords[i]\n const domainLink = await domainLinkRepo.findOneBy({ id: updateRecord.id })\n\n const result = await domainLinkRepo.save({\n ...domainLink,\n ...updateRecord,\n updater: user\n })\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete DomainLink' })\n async deleteDomainLink(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(DomainLink, tx).delete({ id })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete multiple DomainLinks' })\n async deleteDomainLinks(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(DomainLink, tx).delete({\n id: In(ids)\n })\n\n return true\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"domain-link-query.js","sourceRoot":"","sources":["../../../server/service/domain-link/domain-link-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;AAC9F,iDAAuG;AACvG,6CAAsC;AACtC,qDAA6C;AAC7C,iEAAuD;AAGhD,IAAM,eAAe,GAArB,MAAM,eAAe;IAGpB,AAAN,KAAK,CAAC,WAAW,CACU,MAAiB,EACnC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,MAAM;YACN,UAAU,EAAE,MAAM,IAAA,qBAAa,EAAC,2BAAU,CAAC;YAC3C,WAAW,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC;SACtD,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;QAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAAS,UAAsB;QAC/C,OAAO,UAAU,CAAC,cAAc,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;IAChH,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAAS,UAAsB;QAC/C,OAAO,UAAU,CAAC,cAAc,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC,CAAA;IAChH,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,UAAsB;QAC1C,OAAO,UAAU,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACpG,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,UAAsB;QAC1C,OAAO,UAAU,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACpG,CAAC;CACF,CAAA;AAvCY,0CAAe;AAGpB;IAFL,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,qCAAc,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;IAEhF,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;kDAc3C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACV,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,2BAAU;;mDAEhD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACV,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,2BAAU;;mDAEhD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,2BAAU;;8CAE3C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,2BAAU;;8CAE3C;0BAtCU,eAAe;IAD3B,IAAA,uBAAQ,EAAC,2BAAU,CAAC;GACR,eAAe,CAuC3B","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '../user/user.js'\nimport { DomainLink } from './domain-link.js'\nimport { DomainLinkList } from './domain-link-types.js'\n\n@Resolver(DomainLink)\nexport class DomainLinkQuery {\n @Directive('@privilege(superUserGranted: true)')\n @Query(returns => DomainLinkList, { description: 'To fetch multiple DomainLinks' })\n async domainLinks(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<DomainLinkList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n params,\n repository: await getRepository(DomainLink),\n searchables: ['sourceDomain', 'targetDomain', 'type']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => Domain)\n async sourceDomain(@Root() domainLink: DomainLink): Promise<Domain> {\n return domainLink.sourceDomainId && (await getRepository(Domain).findOneBy({ id: domainLink.sourceDomainId }))\n }\n\n @FieldResolver(type => Domain)\n async targetDomain(@Root() domainLink: DomainLink): Promise<Domain> {\n return domainLink.targetDomainId && (await getRepository(Domain).findOneBy({ id: domainLink.targetDomainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() domainLink: DomainLink): Promise<User> {\n return domainLink.updaterId && (await getRepository(User).findOneBy({ id: domainLink.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() domainLink: DomainLink): Promise<User> {\n return domainLink.creatorId && (await getRepository(User).findOneBy({ id: domainLink.creatorId }))\n }\n}\n"]}
|