@things-factory/auth-base 10.1.192 → 10.1.202
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/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/ai-entry/access-assistant.js +4 -3
- package/dist-server/ai-entry/access-assistant.js.map +1 -1
- package/dist-server/controllers/access-request.d.ts +8 -2
- package/dist-server/controllers/access-request.js +33 -6
- package/dist-server/controllers/access-request.js.map +1 -1
- package/dist-server/controllers/signin.d.ts +5 -0
- package/dist-server/controllers/signin.js +25 -0
- package/dist-server/controllers/signin.js.map +1 -1
- package/dist-server/index.js +7 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/middlewares/audit-scope-middleware.d.ts +7 -0
- package/dist-server/middlewares/audit-scope-middleware.js +15 -0
- package/dist-server/middlewares/audit-scope-middleware.js.map +1 -0
- package/dist-server/middlewares/index.js +3 -0
- package/dist-server/middlewares/index.js.map +1 -1
- package/dist-server/role-tasks.d.ts +2 -0
- package/dist-server/role-tasks.js +20 -0
- package/dist-server/role-tasks.js.map +1 -0
- package/dist-server/router/auth-checkin-router.js +3 -5
- package/dist-server/router/auth-checkin-router.js.map +1 -1
- package/dist-server/router/auth-public-process-router.js +7 -1
- package/dist-server/router/auth-public-process-router.js.map +1 -1
- package/dist-server/router/site-root-router.d.ts +2 -0
- package/dist-server/router/site-root-router.js +2 -0
- package/dist-server/router/site-root-router.js.map +1 -1
- package/dist-server/service/access-request/access-request-query.d.ts +7 -2
- package/dist-server/service/access-request/access-request-query.js +25 -4
- package/dist-server/service/access-request/access-request-query.js.map +1 -1
- package/dist-server/service/access-request/access-request-types.d.ts +7 -0
- package/dist-server/service/access-request/access-request-types.js +27 -1
- package/dist-server/service/access-request/access-request-types.js.map +1 -1
- package/dist-server/service/access-request/access-request.d.ts +1 -0
- package/dist-server/service/access-request/access-request.js +5 -0
- package/dist-server/service/access-request/access-request.js.map +1 -1
- package/dist-server/service/audit/audit-action.d.ts +36 -0
- package/dist-server/service/audit/audit-action.js +137 -0
- package/dist-server/service/audit/audit-action.js.map +1 -0
- package/dist-server/service/audit/audit-kinds.d.ts +19 -0
- package/dist-server/service/audit/audit-kinds.js +70 -0
- package/dist-server/service/audit/audit-kinds.js.map +1 -0
- package/dist-server/service/audit/audit-query.d.ts +11 -0
- package/dist-server/service/audit/audit-query.js +295 -0
- package/dist-server/service/audit/audit-query.js.map +1 -0
- package/dist-server/service/audit/audit-recorder.d.ts +77 -0
- package/dist-server/service/audit/audit-recorder.js +247 -0
- package/dist-server/service/audit/audit-recorder.js.map +1 -0
- package/dist-server/service/audit/audit-request.d.ts +28 -0
- package/dist-server/service/audit/audit-request.js +96 -0
- package/dist-server/service/audit/audit-request.js.map +1 -0
- package/dist-server/service/audit/audit-retention.d.ts +12 -0
- package/dist-server/service/audit/audit-retention.js +42 -0
- package/dist-server/service/audit/audit-retention.js.map +1 -0
- package/dist-server/service/audit/audit-subscriber.d.ts +39 -0
- package/dist-server/service/audit/audit-subscriber.js +191 -0
- package/dist-server/service/audit/audit-subscriber.js.map +1 -0
- package/dist-server/service/audit/audit-target.d.ts +19 -0
- package/dist-server/service/audit/audit-target.js +46 -0
- package/dist-server/service/audit/audit-target.js.map +1 -0
- package/dist-server/service/audit/audit-types.d.ts +44 -0
- package/dist-server/service/audit/audit-types.js +161 -0
- package/dist-server/service/audit/audit-types.js.map +1 -0
- package/dist-server/service/audit/index.d.ts +6 -0
- package/dist-server/service/audit/index.js +11 -0
- package/dist-server/service/audit/index.js.map +1 -0
- package/dist-server/service/domain-owner/domain-owner-mutation.js +3 -0
- package/dist-server/service/domain-owner/domain-owner-mutation.js.map +1 -1
- package/dist-server/service/index.d.ts +9 -2
- package/dist-server/service/index.js +19 -4
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/open-fields.js +2 -1
- package/dist-server/service/open-fields.js.map +1 -1
- package/dist-server/service/privilege/privilege-directive.js +25 -1
- package/dist-server/service/privilege/privilege-directive.js.map +1 -1
- package/dist-server/service/role/role-mutation.js +8 -1
- package/dist-server/service/role/role-mutation.js.map +1 -1
- package/dist-server/service/role-template/role-task.d.ts +81 -0
- package/dist-server/service/role-template/role-task.js +129 -0
- package/dist-server/service/role-template/role-task.js.map +1 -0
- package/dist-server/service/role-template/role-template-gap-resolver.d.ts +9 -5
- package/dist-server/service/role-template/role-template-gap-resolver.js +41 -13
- package/dist-server/service/role-template/role-template-gap-resolver.js.map +1 -1
- package/dist-server/service/role-template/role-template-mutation.js +10 -1
- package/dist-server/service/role-template/role-template-mutation.js.map +1 -1
- package/dist-server/service/role-template/role-template-query.js +4 -2
- package/dist-server/service/role-template/role-template-query.js.map +1 -1
- package/dist-server/service/role-template/role-template-types.d.ts +24 -0
- package/dist-server/service/role-template/role-template-types.js +63 -1
- package/dist-server/service/role-template/role-template-types.js.map +1 -1
- package/dist-server/service/role-template/role-template.d.ts +63 -10
- package/dist-server/service/role-template/role-template.js +92 -18
- package/dist-server/service/role-template/role-template.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/access-request-review.d.ts +12 -2
- package/dist-server/utils/access-request-review.js +13 -3
- package/dist-server/utils/access-request-review.js.map +1 -1
- package/dist-server/utils/check-permission.d.ts +6 -0
- package/dist-server/utils/check-permission.js +23 -8
- package/dist-server/utils/check-permission.js.map +1 -1
- package/package.json +3 -2
- package/tests/access-assistant-db.test.ts +1 -1
- package/tests/access-request-db.test.ts +71 -0
- package/tests/access-request-review.test.ts +30 -0
- package/tests/audit-db.test.ts +394 -0
- package/tests/auth-base-role-tasks.test.ts +58 -0
- package/tests/list-inheritance-db.test.ts +0 -7
- package/tests/open-doors.test.ts +2 -2
- package/tests/refusal-cause.test.ts +1 -1
- package/tests/role-task.test.ts +168 -0
- package/tests/role-template-gap-db.test.ts +77 -2
- package/translations/en.json +14 -1
- package/translations/es.json +14 -1
- package/translations/ja.json +14 -1
- package/translations/ko.json +14 -1
- package/translations/ms.json +14 -1
- package/translations/zh.json +14 -1
- package/dist-server/service/login-history/index.d.ts +0 -4
- package/dist-server/service/login-history/index.js +0 -8
- package/dist-server/service/login-history/index.js.map +0 -1
- package/dist-server/service/login-history/login-history-query.d.ts +0 -10
- package/dist-server/service/login-history/login-history-query.js +0 -80
- package/dist-server/service/login-history/login-history-query.js.map +0 -1
- package/dist-server/service/login-history/login-history-type.d.ts +0 -5
- package/dist-server/service/login-history/login-history-type.js +0 -21
- package/dist-server/service/login-history/login-history-type.js.map +0 -1
- package/dist-server/service/login-history/login-history.d.ts +0 -12
- package/dist-server/service/login-history/login-history.js +0 -58
- package/dist-server/service/login-history/login-history.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-public-process-router.js","sourceRoot":"","sources":["../../server/router/auth-public-process-router.ts"],"names":[],"mappings":"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","sourcesContent":["import Router from 'koa-router'\nimport { ILike } from 'typeorm'\n\nimport { config } from '@things-factory/env'\nimport { getRepository, getSiteRootPath } from '@things-factory/shell'\n\nimport { acceptInvitation } from '../controllers/invitation.js'\nimport { resetPassword, sendPasswordResetEmail } from '../controllers/reset-password.js'\nimport { unlockUser } from '../controllers/unlock-user.js'\nimport { resendVerificationEmail, verify } from '../controllers/verification.js'\nimport { User } from '../service/user/user.js'\nimport { accepts } from '../utils/accepts.js'\nimport { clearAccessTokenCookie } from '../utils/access-token-cookie.js'\n\nconst disableUserSignupProcess = config.get('disableUserSignupProcess', false)\nconst disableUserFavoredLanguage = config.get('i18n/disableUserFavoredLanguage', false)\nconst languages = config.get('i18n/languages', false)\nconst passwordRule = config.get('password') || {\n lowerCase: true,\n upperCase: true,\n digit: true,\n specialCharacter: true,\n allowRepeat: false,\n useTightPattern: true,\n useLoosePattern: false,\n tightCharacterLength: 8,\n looseCharacterLength: 15\n}\n\nexport const authPublicProcessRouter = new Router({\n prefix: '/auth'\n})\n\nauthPublicProcessRouter.post('/join', async (context, next) => {\n const { email } = context.request.body || {}\n\n const repository = getRepository(User)\n\n var user = await repository.findOne({\n where: { username: email },\n relations: ['domains']\n })\n\n if (!user && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n user = await repository.findOne({\n where: { email: ILike(email) },\n relations: ['domains']\n })\n }\n\n if (user) {\n context.redirect(`/auth/signin?username=${email}`)\n } else {\n context.redirect(`/auth/signup?username=${email}&email=${email}`)\n }\n})\n\nauthPublicProcessRouter.all('/signout', async (context, next) => {\n const { header, t } = context\n clearAccessTokenCookie(context)\n\n context.body = t('text.signout successfully')\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n context.redirect(getSiteRootPath(context))\n }\n})\n\nauthPublicProcessRouter.get('/forgot-password', async (context, next) => {\n const { email } = context.request.query\n\n await context.render('auth-page', {\n pageElement: 'forgot-password',\n elementScript: '/auth/forgot-password.js',\n data: {\n email,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * The mailed link is `/auth/reset-password#<token>` (and the same shape for unlock and verify). The\n * page reads the token from the fragment; this request never carries it, so nothing here reads one.\n */\nauthPublicProcessRouter.get('/reset-password', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.get('/unlock-user', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'unlock-user',\n elementScript: '/auth/unlock-user.js',\n data: {\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.get('/activate/:email', async (context, next) => {\n const { email } = context.params\n\n await context.render('auth-page', {\n pageElement: 'auth-activate',\n elementScript: '/auth/activate.js',\n data: {\n email,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * Confirming an address is a POST from the page, not the GET of the link. The link used to be\n * `/auth/verify/<token>` and opening it confirmed — so did any mail scanner that fetched it, and the\n * token sat in every access log on the way.\n */\nauthPublicProcessRouter.get('/verify', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'auth-verify',\n elementScript: '/auth/verify.js',\n data: {\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.post('/verify', async (context, next) => {\n const { header, t } = context\n const { token } = context.request.body || {}\n\n let message: string\n\n try {\n await verify(token)\n message = t('text.user activated successfully')\n } catch (e) {\n context.status = 404\n message = t('text.invalid verification token')\n }\n\n context.body = message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n})\n\n/*\n * This and forgot-password give one answer whether or not the address has an account to mail - a\n * different one would tell anyone which addresses are registered. Only a mail that was due and did\n * not go is a failure. Both used to set nothing in those cases, and koa answered a bare 404 that the\n * page showed as \"Not Found\".\n */\nauthPublicProcessRouter.post('/resend-verification-email', async (context, next) => {\n const { t } = context\n const { email } = context.request.body || {}\n\n if ((await resendVerificationEmail(email, context)) == 'failed') {\n context.status = 503\n context.body = t('error.mail could not be sent')\n return\n }\n\n context.status = 200\n context.body = t('text.verification email sent')\n})\n\n/*\n * ── The invitation page ─────────────────────────────────────────────────────\n * Public on purpose: the person following this link is not a member of the domain yet, which is\n * the entire point of an invitation. The old link went to `/auth/accept/<token>`, a path with no\n * route on any router, so it fell through to the private history-fallback — and the domain gate\n * there turned the invitee away for not being a member. It asked somebody trying to join to\n * already have joined.\n *\n * ── Why the token is not in this path ───────────────────────────────────────\n * It rides in the link's fragment (`#<token>`), which browsers do not send. So the request line\n * here carries nothing, and the token stays out of access logs, proxy logs and `Referer`. The\n * page reads it from the fragment, clears it from the address bar, and posts it below.\n */\nauthPublicProcessRouter.get('/accept-invitation', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'auth-accept-invitation',\n elementScript: '/auth/accept-invitation.js',\n data: {\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * The address is asked for as well as the token. A forwarded mail is the one way the token can\n * still travel, and nothing about where it sits can prevent that — so holding the link is not\n * enough on its own.\n */\nauthPublicProcessRouter.post('/accept-invitation', async (context, next) => {\n const { token, email, name, password } = context.request.body || ({} as any)\n\n const { domain, created } = await acceptInvitation({ token, email, name, password, context })\n\n context.body = {\n subdomain: domain?.subdomain,\n created,\n redirectTo: `/auth/signin?redirect_to=${encodeURIComponent('/')}`\n }\n})\n\nauthPublicProcessRouter.post('/forgot-password', async (context, next) => {\n const { t } = context\n const { email } = context.request.body\n\n if (!email) return next()\n\n const userRepo = getRepository(User)\n const user = await userRepo.findOne({\n where: {\n email\n }\n })\n\n if (user && !(await sendPasswordResetEmail({ user, context }))) {\n context.status = 503\n context.body = t('error.mail could not be sent')\n return\n }\n\n context.status = 200\n context.body = t('text.password reset email sent')\n})\n\nauthPublicProcessRouter.post('/reset-password', async (context, next) => {\n const { header, t } = context\n const { password, token } = context.request.body\n\n try {\n if (!(token && password)) {\n let message = t('error.token or password is invalid')\n\n context.status = 404\n context.body = {\n message\n }\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n token,\n message,\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n\n return\n }\n\n await resetPassword(token, password, context)\n\n var message = t('text.password changed successfully')\n context.body = message\n\n clearAccessTokenCookie(context)\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n } catch (e) {\n context.status = 404\n context.body = e.message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n token,\n message: e.message,\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n }\n})\n\nauthPublicProcessRouter.post('/unlock-user', async (context, next) => {\n const { header, t } = context\n const { password, token } = context.request.body\n\n /* Both are required, the way `/auth/reset-password` requires them. This read `||`, so a body\n carrying a password and no token passed the guard and reached the unlock with no token —\n see the note in `unlockUser`. */\n if (!(token && password)) {\n context.status = 404\n context.body = t('error.token or password is invalid')\n\n return\n }\n\n const succeed = await unlockUser(token, password)\n\n /*\n * Say what happened. The success page used to render whether or not the unlock took, so a\n * reused link, a token for another account, or an account that was never locked all read as\n * \"account is reactivated\" — and the person then could not sign in.\n *\n * A refusal returns to the form with a reason, the shape `/auth/reset-password` already uses.\n */\n if (!succeed) {\n const message = t('text.invalid verification token')\n\n context.status = 404\n context.body = message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'unlock-user',\n elementScript: '/auth/unlock-user.js',\n data: {\n token,\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n\n return\n }\n\n context.body = t('text.password reset succeed')\n\n clearAccessTokenCookie(context)\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message: t('text.account is reactivated'),\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n})\n"]}
|
|
1
|
+
{"version":3,"file":"auth-public-process-router.js","sourceRoot":"","sources":["../../server/router/auth-public-process-router.ts"],"names":[],"mappings":"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","sourcesContent":["import Router from 'koa-router'\nimport { ILike } from 'typeorm'\n\nimport { config } from '@things-factory/env'\nimport { getRepository, getSiteRootPath } from '@things-factory/shell'\n\nimport { acceptInvitation } from '../controllers/invitation.js'\nimport { resetPassword, sendPasswordResetEmail } from '../controllers/reset-password.js'\nimport { unlockUser } from '../controllers/unlock-user.js'\nimport { resendVerificationEmail, verify } from '../controllers/verification.js'\nimport { User } from '../service/user/user.js'\nimport { accepts } from '../utils/accepts.js'\nimport { recordAuditAction } from '../service/audit/audit-recorder.js'\nimport { findAuth } from './site-root-router.js'\nimport { clearAccessTokenCookie } from '../utils/access-token-cookie.js'\n\nconst disableUserSignupProcess = config.get('disableUserSignupProcess', false)\nconst disableUserFavoredLanguage = config.get('i18n/disableUserFavoredLanguage', false)\nconst languages = config.get('i18n/languages', false)\nconst passwordRule = config.get('password') || {\n lowerCase: true,\n upperCase: true,\n digit: true,\n specialCharacter: true,\n allowRepeat: false,\n useTightPattern: true,\n useLoosePattern: false,\n tightCharacterLength: 8,\n looseCharacterLength: 15\n}\n\nexport const authPublicProcessRouter = new Router({\n prefix: '/auth'\n})\n\nauthPublicProcessRouter.post('/join', async (context, next) => {\n const { email } = context.request.body || {}\n\n const repository = getRepository(User)\n\n var user = await repository.findOne({\n where: { username: email },\n relations: ['domains']\n })\n\n if (!user && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n user = await repository.findOne({\n where: { email: ILike(email) },\n relations: ['domains']\n })\n }\n\n if (user) {\n context.redirect(`/auth/signin?username=${email}`)\n } else {\n context.redirect(`/auth/signup?username=${email}&email=${email}`)\n }\n})\n\nauthPublicProcessRouter.all('/signout', findAuth, async (context, next) => {\n const { header, t } = context\n clearAccessTokenCookie(context)\n\n /* After the cookie is gone: an audit failure never keeps anyone signed in (ADR-0141 §4-2). */\n if (context.state.user) {\n await recordAuditAction({ kind: 'auth.signout', outcome: 'ok' }, { domainId: null })\n }\n\n context.body = t('text.signout successfully')\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n context.redirect(getSiteRootPath(context))\n }\n})\n\nauthPublicProcessRouter.get('/forgot-password', async (context, next) => {\n const { email } = context.request.query\n\n await context.render('auth-page', {\n pageElement: 'forgot-password',\n elementScript: '/auth/forgot-password.js',\n data: {\n email,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * The mailed link is `/auth/reset-password#<token>` (and the same shape for unlock and verify). The\n * page reads the token from the fragment; this request never carries it, so nothing here reads one.\n */\nauthPublicProcessRouter.get('/reset-password', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.get('/unlock-user', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'unlock-user',\n elementScript: '/auth/unlock-user.js',\n data: {\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.get('/activate/:email', async (context, next) => {\n const { email } = context.params\n\n await context.render('auth-page', {\n pageElement: 'auth-activate',\n elementScript: '/auth/activate.js',\n data: {\n email,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * Confirming an address is a POST from the page, not the GET of the link. The link used to be\n * `/auth/verify/<token>` and opening it confirmed — so did any mail scanner that fetched it, and the\n * token sat in every access log on the way.\n */\nauthPublicProcessRouter.get('/verify', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'auth-verify',\n elementScript: '/auth/verify.js',\n data: {\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\nauthPublicProcessRouter.post('/verify', async (context, next) => {\n const { header, t } = context\n const { token } = context.request.body || {}\n\n let message: string\n\n try {\n await verify(token)\n message = t('text.user activated successfully')\n } catch (e) {\n context.status = 404\n message = t('text.invalid verification token')\n }\n\n context.body = message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n})\n\n/*\n * This and forgot-password give one answer whether or not the address has an account to mail - a\n * different one would tell anyone which addresses are registered. Only a mail that was due and did\n * not go is a failure. Both used to set nothing in those cases, and koa answered a bare 404 that the\n * page showed as \"Not Found\".\n */\nauthPublicProcessRouter.post('/resend-verification-email', async (context, next) => {\n const { t } = context\n const { email } = context.request.body || {}\n\n if ((await resendVerificationEmail(email, context)) == 'failed') {\n context.status = 503\n context.body = t('error.mail could not be sent')\n return\n }\n\n context.status = 200\n context.body = t('text.verification email sent')\n})\n\n/*\n * ── The invitation page ─────────────────────────────────────────────────────\n * Public on purpose: the person following this link is not a member of the domain yet, which is\n * the entire point of an invitation. The old link went to `/auth/accept/<token>`, a path with no\n * route on any router, so it fell through to the private history-fallback — and the domain gate\n * there turned the invitee away for not being a member. It asked somebody trying to join to\n * already have joined.\n *\n * ── Why the token is not in this path ───────────────────────────────────────\n * It rides in the link's fragment (`#<token>`), which browsers do not send. So the request line\n * here carries nothing, and the token stays out of access logs, proxy logs and `Referer`. The\n * page reads it from the fragment, clears it from the address bar, and posts it below.\n */\nauthPublicProcessRouter.get('/accept-invitation', async (context, next) => {\n await context.render('auth-page', {\n pageElement: 'auth-accept-invitation',\n elementScript: '/auth/accept-invitation.js',\n data: {\n disableUserFavoredLanguage,\n languages\n }\n })\n})\n\n/*\n * The address is asked for as well as the token. A forwarded mail is the one way the token can\n * still travel, and nothing about where it sits can prevent that — so holding the link is not\n * enough on its own.\n */\nauthPublicProcessRouter.post('/accept-invitation', async (context, next) => {\n const { token, email, name, password } = context.request.body || ({} as any)\n\n const { domain, created } = await acceptInvitation({ token, email, name, password, context })\n\n context.body = {\n subdomain: domain?.subdomain,\n created,\n redirectTo: `/auth/signin?redirect_to=${encodeURIComponent('/')}`\n }\n})\n\nauthPublicProcessRouter.post('/forgot-password', async (context, next) => {\n const { t } = context\n const { email } = context.request.body\n\n if (!email) return next()\n\n const userRepo = getRepository(User)\n const user = await userRepo.findOne({\n where: {\n email\n }\n })\n\n if (user && !(await sendPasswordResetEmail({ user, context }))) {\n context.status = 503\n context.body = t('error.mail could not be sent')\n return\n }\n\n context.status = 200\n context.body = t('text.password reset email sent')\n})\n\nauthPublicProcessRouter.post('/reset-password', async (context, next) => {\n const { header, t } = context\n const { password, token } = context.request.body\n\n try {\n if (!(token && password)) {\n let message = t('error.token or password is invalid')\n\n context.status = 404\n context.body = {\n message\n }\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n token,\n message,\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n\n return\n }\n\n await resetPassword(token, password, context)\n\n var message = t('text.password changed successfully')\n context.body = message\n\n clearAccessTokenCookie(context)\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n } catch (e) {\n context.status = 404\n context.body = e.message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'reset-password',\n elementScript: '/auth/reset-password.js',\n data: {\n token,\n message: e.message,\n passwordRule,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n }\n})\n\nauthPublicProcessRouter.post('/unlock-user', async (context, next) => {\n const { header, t } = context\n const { password, token } = context.request.body\n\n /* Both are required, the way `/auth/reset-password` requires them. This read `||`, so a body\n carrying a password and no token passed the guard and reached the unlock with no token —\n see the note in `unlockUser`. */\n if (!(token && password)) {\n context.status = 404\n context.body = t('error.token or password is invalid')\n\n return\n }\n\n const succeed = await unlockUser(token, password)\n\n /*\n * Say what happened. The success page used to render whether or not the unlock took, so a\n * reused link, a token for another account, or an account that was never locked all read as\n * \"account is reactivated\" — and the person then could not sign in.\n *\n * A refusal returns to the form with a reason, the shape `/auth/reset-password` already uses.\n */\n if (!succeed) {\n const message = t('text.invalid verification token')\n\n context.status = 404\n context.body = message\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'unlock-user',\n elementScript: '/auth/unlock-user.js',\n data: {\n token,\n message,\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n\n return\n }\n\n context.body = t('text.password reset succeed')\n\n clearAccessTokenCookie(context)\n\n if (accepts(header.accept, ['text/html', '*/*'])) {\n await context.render('auth-page', {\n pageElement: 'auth-result',\n elementScript: '/auth/result.js',\n data: {\n message: t('text.account is reactivated'),\n disableUserSignupProcess,\n disableUserFavoredLanguage,\n languages\n }\n })\n }\n})\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.siteRootRouter = void 0;
|
|
4
|
+
exports.findAuth = findAuth;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const koa_router_1 = tslib_1.__importDefault(require("koa-router"));
|
|
6
7
|
const koa_passport_1 = tslib_1.__importDefault(require("koa-passport"));
|
|
@@ -10,6 +11,7 @@ const user_js_1 = require("../service/user/user.js");
|
|
|
10
11
|
const get_user_domains_js_1 = require("../utils/get-user-domains.js");
|
|
11
12
|
const PUBLIC_HOME_ROUTE = env_1.config.get('publicHomeRoute', '/public/home');
|
|
12
13
|
exports.siteRootRouter = new koa_router_1.default();
|
|
14
|
+
/** Who the access token says this is, when it says anyone - the route goes on either way. */
|
|
13
15
|
async function findAuth(context, next) {
|
|
14
16
|
return await koa_passport_1.default.authenticate('jwt', { session: false }, async (err, decoded, info) => {
|
|
15
17
|
if (decoded) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site-root-router.js","sourceRoot":"","sources":["../../server/router/site-root-router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"site-root-router.js","sourceRoot":"","sources":["../../server/router/site-root-router.ts"],"names":[],"mappings":";;;AAcA,4BAWC;;AAzBD,oEAA+B;AAC/B,wEAAmC;AAEnC,iDAAgE;AAChE,6CAA4C;AAE5C,qDAA8C;AAC9C,sEAA6D;AAE7D,MAAM,iBAAiB,GAAG,YAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;AAE1D,QAAA,cAAc,GAAG,IAAI,oBAAM,EAAE,CAAA;AAE1C,6FAA6F;AACtF,KAAK,UAAU,QAAQ,CAAC,OAAO,EAAE,IAAI;IAC1C,OAAO,MAAM,sBAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QACzF,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,cAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;gBAC1C,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;YAC3B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AACnB,CAAC;AAED,sBAAc,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,wBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC1E,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAEtC,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,CAAA;IAEnC,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;QACtB,MAAM,WAAW,GAAsB,MAAM,IAAA,oCAAc,EAAC,IAAI,CAAC,CAAA;QACjE,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,IAAI,SAAS,CAAC,EAAE,CAAC;YACtE,OAAO,MAAM,IAAI,EAAE,CAAA;QACrB,CAAC;QAED,OAAO,OAAO,CAAC,QAAQ,CAAC,iBAAiB,SAAS,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAA;QAEjC,OAAM;IACR,CAAC;IAED,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAA;AACrC,CAAC,CAAC,CAAA","sourcesContent":["import Router from 'koa-router'\nimport passport from 'koa-passport'\n\nimport { Domain, domainMiddleware } from '@things-factory/shell'\nimport { config } from '@things-factory/env'\n\nimport { User } from '../service/user/user.js'\nimport { getUserDomains } from '../utils/get-user-domains.js'\n\nconst PUBLIC_HOME_ROUTE = config.get('publicHomeRoute', '/public/home')\n\nexport const siteRootRouter = new Router()\n\n/** Who the access token says this is, when it says anyone - the route goes on either way. */\nexport async function findAuth(context, next) {\n return await passport.authenticate('jwt', { session: false }, async (err, decoded, info) => {\n if (decoded) {\n try {\n const user = await User.checkAuth(decoded)\n context.state.user = user\n } catch (e) {}\n }\n\n await next()\n })(context, next)\n}\n\nsiteRootRouter.get('/', findAuth, domainMiddleware, async (context, next) => {\n const { user, domain } = context.state\n\n const subdomain = domain?.subdomain\n\n if (user && subdomain) {\n const userDomains: Partial<Domain>[] = await getUserDomains(user)\n if (userDomains.find(userDomain => userDomain.subdomain == subdomain)) {\n return await next()\n }\n\n return context.redirect(`/auth/checkin/${subdomain}`)\n }\n\n if (user && !subdomain) {\n context.redirect('/auth/checkin')\n\n return\n }\n\n context.redirect(PUBLIC_HOME_ROUTE)\n})\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ListParam } from '@things-factory/shell';
|
|
2
2
|
import { AccessRequest } from './access-request.js';
|
|
3
|
-
import { AccessDecisionInput, AccessDecisionIssue, AccessRequestList, AccessRoleCandidate } from './access-request-types.js';
|
|
3
|
+
import { AccessDecisionInput, AccessDecisionIssue, AccessRequestList, AccessRoleCandidate, AccessTaskChoice } from './access-request-types.js';
|
|
4
4
|
export declare class AccessRequestQuery {
|
|
5
5
|
accessRequests(params: ListParam, context: ResolverContext): Promise<AccessRequestList>;
|
|
6
6
|
/** Open by design: the caller's own requests - where they see what became of them. */
|
|
@@ -10,7 +10,12 @@ export declare class AccessRequestQuery {
|
|
|
10
10
|
* as what it is. A number, never who.
|
|
11
11
|
*/
|
|
12
12
|
accessRequestDeciderCount(context: ResolverContext): Promise<number>;
|
|
13
|
-
rolesGranting(category: string, privilege: string, context: ResolverContext): Promise<AccessRoleCandidate[]>;
|
|
13
|
+
rolesGranting(category: string, privilege: string, context: ResolverContext, taskId?: string): Promise<AccessRoleCandidate[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Open by design: the tasks a person refused may ask for - the code catalog of work, nothing of this domain's data.
|
|
16
|
+
* The person asking is refused by definition, so no privilege can close it (ADR-0103 decision 9).
|
|
17
|
+
*/
|
|
18
|
+
tasksGranting(category: string, privilege: string): Promise<AccessTaskChoice[]>;
|
|
14
19
|
/** The roles of this domain's assignable scope (own, parent, granted) with exactly this name - what a decision may name. */
|
|
15
20
|
assignableRolesNamed(name: string, context: ResolverContext): Promise<AccessRoleCandidate[]>;
|
|
16
21
|
/** The same review the decision runs - the list screen and the AI draft card show this (ADR-0103 decision 4). */
|
|
@@ -7,6 +7,7 @@ const shell_1 = require("@things-factory/shell");
|
|
|
7
7
|
const access_request_js_1 = require("../../controllers/access-request.js");
|
|
8
8
|
const assignable_roles_js_1 = require("../../utils/assignable-roles.js");
|
|
9
9
|
const access_request_js_2 = require("./access-request.js");
|
|
10
|
+
const role_task_js_1 = require("../role-template/role-task.js");
|
|
10
11
|
const access_request_types_js_1 = require("./access-request-types.js");
|
|
11
12
|
/* The review and the candidates serve a decision - the deciding declaration. */
|
|
12
13
|
const DECIDE = '@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)';
|
|
@@ -46,13 +47,24 @@ let AccessRequestQuery = class AccessRequestQuery {
|
|
|
46
47
|
const { domain, user } = context.state;
|
|
47
48
|
return (await (0, access_request_js_1.findDeciderIds)(domain, user.id)).length;
|
|
48
49
|
}
|
|
49
|
-
async rolesGranting(category, privilege, context) {
|
|
50
|
-
return (await (0, access_request_js_1.rolesGranting)(category, privilege, context.state.domain)).map(({ id, name, privilegeCount }) => ({ id, name, privilegeCount }));
|
|
50
|
+
async rolesGranting(category, privilege, context, taskId) {
|
|
51
|
+
return (await (0, access_request_js_1.rolesGranting)(category, privilege, context.state.domain, undefined, taskId)).map(({ id, name, privilegeCount, holdsTask }) => ({ id, name, privilegeCount, holdsTask }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Open by design: the tasks a person refused may ask for - the code catalog of work, nothing of this domain's data.
|
|
55
|
+
* The person asking is refused by definition, so no privilege can close it (ADR-0103 decision 9).
|
|
56
|
+
*/
|
|
57
|
+
async tasksGranting(category, privilege) {
|
|
58
|
+
return (0, role_task_js_1.tasksHolding)(category, privilege).map(task => ({
|
|
59
|
+
taskId: task.id,
|
|
60
|
+
module: task.id.split('.')[0],
|
|
61
|
+
privilegeCount: task.grants.reduce((count, grant) => count + grant.axes.length, 0)
|
|
62
|
+
}));
|
|
51
63
|
}
|
|
52
64
|
/** The roles of this domain's assignable scope (own, parent, granted) with exactly this name - what a decision may name. */
|
|
53
65
|
async assignableRolesNamed(name, context) {
|
|
54
66
|
const roles = await (0, assignable_roles_js_1.findAssignableRolesNamed)(name, context.state.domain);
|
|
55
|
-
return roles.map(role => ({ id: role.id, name: role.name, privilegeCount: role.privileges?.length ?? 0 }));
|
|
67
|
+
return roles.map(role => ({ id: role.id, name: role.name, privilegeCount: role.privileges?.length ?? 0, holdsTask: false }));
|
|
56
68
|
}
|
|
57
69
|
/** The same review the decision runs - the list screen and the AI draft card show this (ADR-0103 decision 4). */
|
|
58
70
|
async reviewAccessDecision(decision, context) {
|
|
@@ -89,10 +101,19 @@ tslib_1.__decorate([
|
|
|
89
101
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('category')),
|
|
90
102
|
tslib_1.__param(1, (0, type_graphql_1.Arg)('privilege')),
|
|
91
103
|
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
104
|
+
tslib_1.__param(3, (0, type_graphql_1.Arg)('taskId', { nullable: true, description: 'The task asked for - roles holding all of it come first.' })),
|
|
92
105
|
tslib_1.__metadata("design:type", Function),
|
|
93
|
-
tslib_1.__metadata("design:paramtypes", [String, String, Object]),
|
|
106
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object, String]),
|
|
94
107
|
tslib_1.__metadata("design:returntype", Promise)
|
|
95
108
|
], AccessRequestQuery.prototype, "rolesGranting", null);
|
|
109
|
+
tslib_1.__decorate([
|
|
110
|
+
(0, type_graphql_1.Query)(returns => [access_request_types_js_1.AccessTaskChoice], { description: 'To list the tasks that hold a privilege, fewest privileges first - what a person refused may ask for.' }),
|
|
111
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('category')),
|
|
112
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('privilege')),
|
|
113
|
+
tslib_1.__metadata("design:type", Function),
|
|
114
|
+
tslib_1.__metadata("design:paramtypes", [String, String]),
|
|
115
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
116
|
+
], AccessRequestQuery.prototype, "tasksGranting", null);
|
|
96
117
|
tslib_1.__decorate([
|
|
97
118
|
(0, type_graphql_1.Directive)(DECIDE),
|
|
98
119
|
(0, type_graphql_1.Query)(returns => [access_request_types_js_1.AccessRoleCandidate], { description: 'To find, by exact name, the roles this domain can assign.' }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-request-query.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, Int, Query, Resolver } from 'type-graphql'\n\nimport { getQueryBuilderFromListParams, getRepository, InheritedValueType, ListParam } from '@things-factory/shell'\n\nimport { findDeciderIds, reviewDecision, rolesGranting } from '../../controllers/access-request.js'\nimport { findAssignableRolesNamed } from '../../utils/assignable-roles.js'\nimport { AccessRequest } from './access-request.js'\nimport { AccessDecisionInput, AccessDecisionIssue, AccessRequestList, AccessRoleCandidate } from './access-request-types.js'\n\n/* The review and the candidates serve a decision - the deciding declaration. */\nconst DECIDE = '@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)'\n\n@Resolver(AccessRequest)\nexport class AccessRequestQuery {\n /*\n * A decider's list - the same declaration as the decision, so the people told of a request can open it (ADR-0103).\n * This domain's rows only: `inherited` is pinned, a parent domain's requests are not this domain's to read.\n */\n @Directive(DECIDE)\n @Query(returns => AccessRequestList, { description: \"To fetch this domain's access requests.\" })\n async accessRequests(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AccessRequestList> {\n const { domain } = context.state\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params: { ...params, inherited: InheritedValueType.None },\n repository: getRepository(AccessRequest),\n alias: 'accessRequest',\n searchables: ['category', 'privilege', 'reason']\n })\n queryBuilder.leftJoinAndSelect('accessRequest.requester', 'requester').leftJoinAndSelect('accessRequest.decidedBy', 'decidedBy').leftJoinAndSelect('accessRequest.grantedRole', 'grantedRole')\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n /** Open by design: the caller's own requests - where they see what became of them. */\n @Query(returns => [AccessRequest], { description: \"To fetch the caller's own access requests in this domain, newest first.\" })\n async myAccessRequests(@Ctx() context: ResolverContext): Promise<AccessRequest[]> {\n const { domain, user } = context.state\n return await getRepository(AccessRequest).find({\n where: { domain: { id: domain.id }, requester: { id: user.id } },\n relations: ['domain', 'requester', 'grantedRole'],\n order: { createdAt: 'DESC' },\n take: 100\n })\n }\n\n /**\n * Open by design: how many people a request would reach - the popup says it before the person sends, so asking reads\n * as what it is. A number, never who.\n */\n @Query(returns => Int, { description: 'To count the people who would be told of an access request from the caller in this domain.' })\n async accessRequestDeciderCount(@Ctx() context: ResolverContext): Promise<number> {\n const { domain, user } = context.state\n return (await findDeciderIds(domain, user.id)).length\n }\n\n @Directive(DECIDE)\n @Query(returns => [AccessRoleCandidate], { description: 'To list the roles this domain can assign that grant a privilege, fewest privileges first.' })\n async rolesGranting(@Arg('category') category: string, @Arg('privilege') privilege: string, @Ctx() context: ResolverContext): Promise<AccessRoleCandidate[]> {\n return (await rolesGranting(category, privilege, context.state.domain)).map(({ id, name, privilegeCount }) => ({ id, name, privilegeCount }))\n }\n\n /** The roles of this domain's assignable scope (own, parent, granted) with exactly this name - what a decision may name. */\n @Directive(DECIDE)\n @Query(returns => [AccessRoleCandidate], { description: 'To find, by exact name, the roles this domain can assign.' })\n async assignableRolesNamed(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<AccessRoleCandidate[]> {\n const roles = await findAssignableRolesNamed(name, context.state.domain)\n return roles.map(role => ({ id: role.id, name: role.name, privilegeCount: role.privileges?.length ?? 0 }))\n }\n\n /** The same review the decision runs - the list screen and the AI draft card show this (ADR-0103 decision 4). */\n @Directive(DECIDE)\n @Query(returns => [AccessDecisionIssue], { description: 'To review a decision before it is made: what blocks it and what the person deciding should know.' })\n async reviewAccessDecision(@Arg('decision', type => AccessDecisionInput) decision: AccessDecisionInput, @Ctx() context: ResolverContext): Promise<AccessDecisionIssue[]> {\n return (await reviewDecision(decision as any, context)) as AccessDecisionIssue[]\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"access-request-query.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, Int, Query, Resolver } from 'type-graphql'\n\nimport { getQueryBuilderFromListParams, getRepository, InheritedValueType, ListParam } from '@things-factory/shell'\n\nimport { findDeciderIds, reviewDecision, rolesGranting } from '../../controllers/access-request.js'\nimport { findAssignableRolesNamed } from '../../utils/assignable-roles.js'\nimport { AccessRequest } from './access-request.js'\nimport { tasksHolding } from '../role-template/role-task.js'\nimport { AccessDecisionInput, AccessDecisionIssue, AccessRequestList, AccessRoleCandidate, AccessTaskChoice } from './access-request-types.js'\n\n/* The review and the candidates serve a decision - the deciding declaration. */\nconst DECIDE = '@privilege(category: \"user\", privilege: \"mutation\", domainOwnerGranted: true)'\n\n@Resolver(AccessRequest)\nexport class AccessRequestQuery {\n /*\n * A decider's list - the same declaration as the decision, so the people told of a request can open it (ADR-0103).\n * This domain's rows only: `inherited` is pinned, a parent domain's requests are not this domain's to read.\n */\n @Directive(DECIDE)\n @Query(returns => AccessRequestList, { description: \"To fetch this domain's access requests.\" })\n async accessRequests(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AccessRequestList> {\n const { domain } = context.state\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params: { ...params, inherited: InheritedValueType.None },\n repository: getRepository(AccessRequest),\n alias: 'accessRequest',\n searchables: ['category', 'privilege', 'reason']\n })\n queryBuilder.leftJoinAndSelect('accessRequest.requester', 'requester').leftJoinAndSelect('accessRequest.decidedBy', 'decidedBy').leftJoinAndSelect('accessRequest.grantedRole', 'grantedRole')\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n /** Open by design: the caller's own requests - where they see what became of them. */\n @Query(returns => [AccessRequest], { description: \"To fetch the caller's own access requests in this domain, newest first.\" })\n async myAccessRequests(@Ctx() context: ResolverContext): Promise<AccessRequest[]> {\n const { domain, user } = context.state\n return await getRepository(AccessRequest).find({\n where: { domain: { id: domain.id }, requester: { id: user.id } },\n relations: ['domain', 'requester', 'grantedRole'],\n order: { createdAt: 'DESC' },\n take: 100\n })\n }\n\n /**\n * Open by design: how many people a request would reach - the popup says it before the person sends, so asking reads\n * as what it is. A number, never who.\n */\n @Query(returns => Int, { description: 'To count the people who would be told of an access request from the caller in this domain.' })\n async accessRequestDeciderCount(@Ctx() context: ResolverContext): Promise<number> {\n const { domain, user } = context.state\n return (await findDeciderIds(domain, user.id)).length\n }\n\n @Directive(DECIDE)\n @Query(returns => [AccessRoleCandidate], { description: 'To list the roles this domain can assign that grant a privilege, fewest privileges first.' })\n async rolesGranting(\n @Arg('category') category: string,\n @Arg('privilege') privilege: string,\n @Ctx() context: ResolverContext,\n @Arg('taskId', { nullable: true, description: 'The task asked for - roles holding all of it come first.' }) taskId?: string\n ): Promise<AccessRoleCandidate[]> {\n return (await rolesGranting(category, privilege, context.state.domain, undefined, taskId)).map(({ id, name, privilegeCount, holdsTask }) => ({ id, name, privilegeCount, holdsTask }))\n }\n\n /**\n * Open by design: the tasks a person refused may ask for - the code catalog of work, nothing of this domain's data.\n * The person asking is refused by definition, so no privilege can close it (ADR-0103 decision 9).\n */\n @Query(returns => [AccessTaskChoice], { description: 'To list the tasks that hold a privilege, fewest privileges first - what a person refused may ask for.' })\n async tasksGranting(@Arg('category') category: string, @Arg('privilege') privilege: string): Promise<AccessTaskChoice[]> {\n return tasksHolding(category, privilege).map(task => ({\n taskId: task.id,\n module: task.id.split('.')[0],\n privilegeCount: task.grants.reduce((count, grant) => count + grant.axes.length, 0)\n }))\n }\n\n /** The roles of this domain's assignable scope (own, parent, granted) with exactly this name - what a decision may name. */\n @Directive(DECIDE)\n @Query(returns => [AccessRoleCandidate], { description: 'To find, by exact name, the roles this domain can assign.' })\n async assignableRolesNamed(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<AccessRoleCandidate[]> {\n const roles = await findAssignableRolesNamed(name, context.state.domain)\n return roles.map(role => ({ id: role.id, name: role.name, privilegeCount: role.privileges?.length ?? 0, holdsTask: false }))\n }\n\n /** The same review the decision runs - the list screen and the AI draft card show this (ADR-0103 decision 4). */\n @Directive(DECIDE)\n @Query(returns => [AccessDecisionIssue], { description: 'To review a decision before it is made: what blocks it and what the person deciding should know.' })\n async reviewAccessDecision(@Arg('decision', type => AccessDecisionInput) decision: AccessDecisionInput, @Ctx() context: ResolverContext): Promise<AccessDecisionIssue[]> {\n return (await reviewDecision(decision as any, context)) as AccessDecisionIssue[]\n }\n}\n"]}
|
|
@@ -7,6 +7,7 @@ export declare class NewAccessRequest {
|
|
|
7
7
|
category: string;
|
|
8
8
|
privilege: string;
|
|
9
9
|
operationName?: string;
|
|
10
|
+
taskId?: string;
|
|
10
11
|
reason?: string;
|
|
11
12
|
}
|
|
12
13
|
export declare class AccessDecisionInput {
|
|
@@ -25,6 +26,12 @@ export declare class AccessRoleCandidate {
|
|
|
25
26
|
id: string;
|
|
26
27
|
name: string;
|
|
27
28
|
privilegeCount: number;
|
|
29
|
+
holdsTask: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare class AccessTaskChoice {
|
|
32
|
+
taskId: string;
|
|
33
|
+
module: string;
|
|
34
|
+
privilegeCount: number;
|
|
28
35
|
}
|
|
29
36
|
export declare class AccessRequestList {
|
|
30
37
|
items: AccessRequest[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AccessRequestList = exports.AccessRoleCandidate = exports.AccessDecisionIssue = exports.AccessDecisionInput = exports.NewAccessRequest = exports.AccessDecision = void 0;
|
|
3
|
+
exports.AccessRequestList = exports.AccessTaskChoice = exports.AccessRoleCandidate = exports.AccessDecisionIssue = exports.AccessDecisionInput = exports.NewAccessRequest = exports.AccessDecision = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const type_graphql_1 = require("type-graphql");
|
|
6
6
|
const shell_1 = require("@things-factory/shell");
|
|
@@ -29,6 +29,10 @@ tslib_1.__decorate([
|
|
|
29
29
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The operation that was refused, shown to the person deciding.' }),
|
|
30
30
|
tslib_1.__metadata("design:type", String)
|
|
31
31
|
], NewAccessRequest.prototype, "operationName", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'The task asked for - one of the tasks that hold the refused privilege (tasksGranting).' }),
|
|
34
|
+
tslib_1.__metadata("design:type", String)
|
|
35
|
+
], NewAccessRequest.prototype, "taskId", void 0);
|
|
32
36
|
tslib_1.__decorate([
|
|
33
37
|
(0, type_graphql_1.Field)({ nullable: true, description: "The requester's reason." }),
|
|
34
38
|
tslib_1.__metadata("design:type", String)
|
|
@@ -95,9 +99,31 @@ tslib_1.__decorate([
|
|
|
95
99
|
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'How many privileges the role carries - fewer is closer to what was asked.' }),
|
|
96
100
|
tslib_1.__metadata("design:type", Number)
|
|
97
101
|
], AccessRoleCandidate.prototype, "privilegeCount", void 0);
|
|
102
|
+
tslib_1.__decorate([
|
|
103
|
+
(0, type_graphql_1.Field)({ description: 'Whether the role holds every privilege of the task asked for. False when no task was asked.' }),
|
|
104
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
105
|
+
], AccessRoleCandidate.prototype, "holdsTask", void 0);
|
|
98
106
|
exports.AccessRoleCandidate = AccessRoleCandidate = tslib_1.__decorate([
|
|
99
107
|
(0, type_graphql_1.ObjectType)({ description: 'A role this domain can assign that grants the asked privilege.' })
|
|
100
108
|
], AccessRoleCandidate);
|
|
109
|
+
let AccessTaskChoice = class AccessTaskChoice {
|
|
110
|
+
};
|
|
111
|
+
exports.AccessTaskChoice = AccessTaskChoice;
|
|
112
|
+
tslib_1.__decorate([
|
|
113
|
+
(0, type_graphql_1.Field)({ description: 'The task id, `<module>.<work>`.' }),
|
|
114
|
+
tslib_1.__metadata("design:type", String)
|
|
115
|
+
], AccessTaskChoice.prototype, "taskId", void 0);
|
|
116
|
+
tslib_1.__decorate([
|
|
117
|
+
(0, type_graphql_1.Field)({ description: 'The module or application that declares the task.' }),
|
|
118
|
+
tslib_1.__metadata("design:type", String)
|
|
119
|
+
], AccessTaskChoice.prototype, "module", void 0);
|
|
120
|
+
tslib_1.__decorate([
|
|
121
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'How many privileges the task holds - fewer is closer to what was refused.' }),
|
|
122
|
+
tslib_1.__metadata("design:type", Number)
|
|
123
|
+
], AccessTaskChoice.prototype, "privilegeCount", void 0);
|
|
124
|
+
exports.AccessTaskChoice = AccessTaskChoice = tslib_1.__decorate([
|
|
125
|
+
(0, type_graphql_1.ObjectType)({ description: 'A task that holds a refused privilege - what a person refused may ask for. Words are task.<id>.name and .description.' })
|
|
126
|
+
], AccessTaskChoice);
|
|
101
127
|
let AccessRequestList = class AccessRequestList {
|
|
102
128
|
};
|
|
103
129
|
exports.AccessRequestList = AccessRequestList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-request-types.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request-types.ts"],"names":[],"mappings":";;;;AAAA,+CAAkF;AAClF,iDAAoD;AAEpD,2DAAmD;AAEnD,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,8BAAd,cAAc,QAGzB;AAED,IAAA,+BAAgB,EAAC,cAAc,EAAE;IAC/B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,wGAAwG;CACtH,CAAC,CAAA;AAGK,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;
|
|
1
|
+
{"version":3,"file":"access-request-types.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request-types.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, InputType, Int, ObjectType, registerEnumType } from 'type-graphql'\nimport { ScalarObject } from '@things-factory/shell'\n\nimport { AccessRequest } from './access-request.js'\n\nexport enum AccessDecision {\n GRANT = 'GRANT',\n DENY = 'DENY'\n}\n\nregisterEnumType(AccessDecision, {\n name: 'AccessDecision',\n description: 'What the person deciding an access request does: put the requester into a role, or deny with a reason.'\n})\n\n@InputType({ description: 'An access request for one privilege in this domain - what a refusal carried, and why it is needed.' })\nexport class NewAccessRequest {\n @Field({ description: \"The category of the refused privilege, from the refusal's extensions.requires.\" })\n category: string\n\n @Field({ description: \"The refused privilege, from the refusal's extensions.requires.\" })\n privilege: string\n\n @Field({ nullable: true, description: 'The operation that was refused, shown to the person deciding.' })\n operationName?: string\n\n @Field({ nullable: true, description: 'The task asked for - one of the tasks that hold the refused privilege (tasksGranting).' })\n taskId?: string\n\n @Field({ nullable: true, description: \"The requester's reason.\" })\n reason?: string\n}\n\n@InputType({ description: 'A decision on one access request.' })\nexport class AccessDecisionInput {\n @Field({ description: 'The access request decided.' })\n requestId: string\n\n @Field(type => AccessDecision, { description: 'Grant or deny.' })\n decision: AccessDecision\n\n @Field({ nullable: true, description: 'The role to put the requester into - required to grant, one this domain can assign that holds the privilege.' })\n roleId?: string\n\n @Field({ nullable: true, description: 'Why - required to deny.' })\n reason?: string\n}\n\n@ObjectType({ description: 'One finding of the access decision review - blocking ones keep the decision from being made.' })\nexport class AccessDecisionIssue {\n @Field({ description: 'What was found, as a code the screen words.' })\n code: string\n\n @Field({ description: 'Whether it keeps the decision from being made.' })\n blocking: boolean\n\n @Field({ nullable: true, description: 'The part of the decision it is about: request, decision, role or reason.' })\n field?: string\n\n @Field(type => ScalarObject, { nullable: true, description: 'The values the sentence is built from.' })\n params?: Record<string, unknown>\n}\n\n@ObjectType({ description: 'A role this domain can assign that grants the asked privilege.' })\nexport class AccessRoleCandidate {\n @Field({ description: 'The role id.' })\n id: string\n\n @Field({ description: 'The role name.' })\n name: string\n\n @Field(type => Int, { description: 'How many privileges the role carries - fewer is closer to what was asked.' })\n privilegeCount: number\n\n @Field({ description: 'Whether the role holds every privilege of the task asked for. False when no task was asked.' })\n holdsTask: boolean\n}\n\n@ObjectType({ description: 'A task that holds a refused privilege - what a person refused may ask for. Words are task.<id>.name and .description.' })\nexport class AccessTaskChoice {\n @Field({ description: 'The task id, `<module>.<work>`.' })\n taskId: string\n\n @Field({ description: 'The module or application that declares the task.' })\n module: string\n\n @Field(type => Int, { description: 'How many privileges the task holds - fewer is closer to what was refused.' })\n privilegeCount: number\n}\n\n@ObjectType({ description: 'A paginated list of access requests.' })\nexport class AccessRequestList {\n @Field(type => [AccessRequest], { nullable: true, description: 'The access requests.' })\n items: AccessRequest[]\n\n @Field(type => Int, { nullable: true, description: 'The total number of access requests.' })\n total: number\n}\n"]}
|
|
@@ -75,6 +75,11 @@ tslib_1.__decorate([
|
|
|
75
75
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The operation that was refused - shown to the person deciding.' }),
|
|
76
76
|
tslib_1.__metadata("design:type", String)
|
|
77
77
|
], AccessRequest.prototype, "operationName", void 0);
|
|
78
|
+
tslib_1.__decorate([
|
|
79
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
80
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'The task the requester asked for - one that holds the refused privilege (`<module>.<work>`).' }),
|
|
81
|
+
tslib_1.__metadata("design:type", String)
|
|
82
|
+
], AccessRequest.prototype, "taskId", void 0);
|
|
78
83
|
tslib_1.__decorate([
|
|
79
84
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
80
85
|
(0, type_graphql_1.Field)({ nullable: true, description: "The requester's reason." }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-request.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, Int, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { Domain } from '@things-factory/shell'\n\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum AccessRequestStatus {\n PENDING = 'PENDING',\n GRANTED = 'GRANTED',\n DENIED = 'DENIED',\n WITHDRAWN = 'WITHDRAWN',\n EXPIRED = 'EXPIRED'\n}\n\nregisterEnumType(AccessRequestStatus, {\n name: 'AccessRequestStatus',\n description: 'Where an access request stands: waiting, granted, denied, withdrawn by the requester, or expired unanswered.'\n})\n\n/*\n * A person refused for want of a role asks for the privilege (ADR-0103, docs/design/access-request.md).\n *\n * ── The row is the record ────────────────────────────────────────────────\n * Who asked, for what, why, who decided, which role, why not - all here, and never deleted. A notification\n * is a courtesy on top: it is not stored per person and does nothing where FCM is not set up.\n *\n * ── At most one pending per person and privilege ─────────────────────────\n * Asking again bumps `count` and `lastRequestedAt` instead of adding a row. A partial unique index would say\n * it and is not portable across the databases this framework supports, so it is held where the request is\n * made (as `Invitation` does). The index below is for reading.\n */\n@Entity()\n@Index('ix_access_request_0', (request: AccessRequest) => [request.domain, request.state])\n@Index('ix_access_request_1', (request: AccessRequest) => [request.domain, request.requester, request.category, request.privilege])\n@ObjectType({ description: 'A request by a person refused for want of a role, for one privilege in this domain.' })\nexport class AccessRequest {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the access request.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain the privilege is asked in.' })\n domain: Domain\n\n @RelationId((request: AccessRequest) => request.domain)\n domainId: string\n\n @ManyToOne(type => User)\n @Field(type => User, { description: 'The person who asked.' })\n requester: User\n\n @RelationId((request: AccessRequest) => request.requester)\n requesterId: string\n\n @Column()\n @Field({ description: 'The category of the privilege asked for, as the refusal carried it.' })\n category: string\n\n @Column()\n @Field({ description: 'The privilege asked for, as the refusal carried it.' })\n privilege: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The operation that was refused - shown to the person deciding.' })\n operationName?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"The requester's reason.\" })\n reason?: string\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'How many times it was asked while pending.' })\n count: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was last asked.' })\n lastRequestedAt?: Date\n\n /* The same column shape as Invitation.status - an enum where the database has one, a string elsewhere. */\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' ? AccessRequestStatus : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,\n default: AccessRequestStatus.PENDING\n })\n @Field(type => AccessRequestStatus, { description: 'Where the request stands.' })\n state: AccessRequestStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When a pending request expires unanswered.' })\n expiresAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who decided it.' })\n decidedBy?: User\n\n @RelationId((request: AccessRequest) => request.decidedBy)\n decidedById?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was decided.' })\n decidedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"The decider's reason - required to deny.\" })\n decisionReason?: string\n\n @ManyToOne(type => Role, { nullable: true })\n @Field(type => Role, { nullable: true, description: 'The role the requester was put into.' })\n grantedRole?: Role\n\n @RelationId((request: AccessRequest) => request.grantedRole)\n grantedRoleId?: string\n\n @CreateDateColumn()\n @Field({ description: 'When it was first asked.' })\n createdAt: Date\n\n @UpdateDateColumn()\n @Field({ description: 'When it last changed.' })\n updatedAt: Date\n}\n"]}
|
|
1
|
+
{"version":3,"file":"access-request.js","sourceRoot":"","sources":["../../../server/service/access-request/access-request.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, Int, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { Domain } from '@things-factory/shell'\n\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum AccessRequestStatus {\n PENDING = 'PENDING',\n GRANTED = 'GRANTED',\n DENIED = 'DENIED',\n WITHDRAWN = 'WITHDRAWN',\n EXPIRED = 'EXPIRED'\n}\n\nregisterEnumType(AccessRequestStatus, {\n name: 'AccessRequestStatus',\n description: 'Where an access request stands: waiting, granted, denied, withdrawn by the requester, or expired unanswered.'\n})\n\n/*\n * A person refused for want of a role asks for the privilege (ADR-0103, docs/design/access-request.md).\n *\n * ── The row is the record ────────────────────────────────────────────────\n * Who asked, for what, why, who decided, which role, why not - all here, and never deleted. A notification\n * is a courtesy on top: it is not stored per person and does nothing where FCM is not set up.\n *\n * ── At most one pending per person and privilege ─────────────────────────\n * Asking again bumps `count` and `lastRequestedAt` instead of adding a row. A partial unique index would say\n * it and is not portable across the databases this framework supports, so it is held where the request is\n * made (as `Invitation` does). The index below is for reading.\n */\n@Entity()\n@Index('ix_access_request_0', (request: AccessRequest) => [request.domain, request.state])\n@Index('ix_access_request_1', (request: AccessRequest) => [request.domain, request.requester, request.category, request.privilege])\n@ObjectType({ description: 'A request by a person refused for want of a role, for one privilege in this domain.' })\nexport class AccessRequest {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the access request.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain the privilege is asked in.' })\n domain: Domain\n\n @RelationId((request: AccessRequest) => request.domain)\n domainId: string\n\n @ManyToOne(type => User)\n @Field(type => User, { description: 'The person who asked.' })\n requester: User\n\n @RelationId((request: AccessRequest) => request.requester)\n requesterId: string\n\n @Column()\n @Field({ description: 'The category of the privilege asked for, as the refusal carried it.' })\n category: string\n\n @Column()\n @Field({ description: 'The privilege asked for, as the refusal carried it.' })\n privilege: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The operation that was refused - shown to the person deciding.' })\n operationName?: string\n\n /*\n * The work the person asked for, by task id (ADR-0103 decision 9) - their own words for the refused privilege,\n * picked from the tasks that hold it. The request is still keyed by the refused privilege; this explains it. A task is\n * a code catalog and may be gone later: the screen then draws the id, and the review says nothing of it.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The task the requester asked for - one that holds the refused privilege (`<module>.<work>`).' })\n taskId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"The requester's reason.\" })\n reason?: string\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'How many times it was asked while pending.' })\n count: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was last asked.' })\n lastRequestedAt?: Date\n\n /* The same column shape as Invitation.status - an enum where the database has one, a string elsewhere. */\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' ? AccessRequestStatus : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,\n default: AccessRequestStatus.PENDING\n })\n @Field(type => AccessRequestStatus, { description: 'Where the request stands.' })\n state: AccessRequestStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When a pending request expires unanswered.' })\n expiresAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who decided it.' })\n decidedBy?: User\n\n @RelationId((request: AccessRequest) => request.decidedBy)\n decidedById?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When it was decided.' })\n decidedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"The decider's reason - required to deny.\" })\n decisionReason?: string\n\n @ManyToOne(type => Role, { nullable: true })\n @Field(type => Role, { nullable: true, description: 'The role the requester was put into.' })\n grantedRole?: Role\n\n @RelationId((request: AccessRequest) => request.grantedRole)\n grantedRoleId?: string\n\n @CreateDateColumn()\n @Field({ description: 'When it was first asked.' })\n createdAt: Date\n\n @UpdateDateColumn()\n @Field({ description: 'When it last changed.' })\n updatedAt: Date\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '../user/user.js';
|
|
3
|
+
/**
|
|
4
|
+
* One thing done, as the audit keeps it (ADR-0141 §3.2 · §3.3).
|
|
5
|
+
*
|
|
6
|
+
* `kind` says which: `door.check` (a `@privilege` judgement), `door.result` (what a passed door
|
|
7
|
+
* did), or an event a service or the audit subscriber wrote (`role.grant`, `auth.signin`, ...).
|
|
8
|
+
* Only the columns below exist, and `detail` takes only the keys its kind registered
|
|
9
|
+
* (`audit-kinds.ts`) - no business value, secret or request text has a place to go.
|
|
10
|
+
*
|
|
11
|
+
* Immutable like `AuditRequest`, and for the same reason without foreign keys.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuditAction {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
domain?: Domain;
|
|
17
|
+
domainId?: string;
|
|
18
|
+
actor?: User;
|
|
19
|
+
actorId?: string;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
kind: string;
|
|
22
|
+
door?: string;
|
|
23
|
+
decision?: string;
|
|
24
|
+
basis?: string;
|
|
25
|
+
outcome?: string;
|
|
26
|
+
code?: string;
|
|
27
|
+
count: number;
|
|
28
|
+
returned?: number;
|
|
29
|
+
targetKind?: string;
|
|
30
|
+
targetIds?: string[];
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
targetRole?: string;
|
|
33
|
+
objectKind?: string;
|
|
34
|
+
objectId?: string;
|
|
35
|
+
detail?: Record<string, string | number | boolean | null>;
|
|
36
|
+
}
|