@things-factory/auth-base 10.1.265 → 10.1.269

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.
@@ -135,6 +135,27 @@ let AuditQuery = class AuditQuery {
135
135
  return `action.createdAt = ${latest}`;
136
136
  })
137
137
  .getMany()).map(action => [action.actor?.id, action.createdAt]));
138
+ /*
139
+ * The last use - the member's latest request to this domain, at any time. Every GraphQL request has its line, so
140
+ * this is the last time the app was open and talking to the server, the reads an open screen makes by itself
141
+ * included. Read as rows, like the check-in above.
142
+ */
143
+ const lastUses = new Map((await (0, shell_1.getRepository)(audit_request_js_1.AuditRequest)
144
+ .createQueryBuilder('request')
145
+ .leftJoinAndSelect('request.actor', 'actor')
146
+ .where('request.domain = :domainId', { domainId: domain.id })
147
+ .andWhere('actor.id IN (:...ids)', { ids })
148
+ .andWhere(qb => {
149
+ const latest = qb
150
+ .subQuery()
151
+ .select('MAX(latest.createdAt)')
152
+ .from(audit_request_js_1.AuditRequest, 'latest')
153
+ .where('latest.domain = :domainId')
154
+ .andWhere('latest.actor = request.actor')
155
+ .getQuery();
156
+ return `request.createdAt = ${latest}`;
157
+ })
158
+ .getMany()).map(request => [request.actor?.id, request.createdAt]));
138
159
  /* A sign-in may come before any domain is chosen, so failures are the member's wherever they were. */
139
160
  const failures = sums(await (0, shell_1.getRepository)(audit_action_js_1.AuditAction)
140
161
  .createQueryBuilder('action')
@@ -163,6 +184,7 @@ let AuditQuery = class AuditQuery {
163
184
  user,
164
185
  roles: roleRows.filter(row => row.userId === user.id).map(row => row.name),
165
186
  lastCheckinAt: lastCheckins.get(user.id),
187
+ lastUsedAt: lastUses.get(user.id),
166
188
  checkins: Number(checkins.get(user.id)?.inPeriod || 0),
167
189
  failedSignins: Number(failures.get(user.id)?.failed || 0),
168
190
  granted: Number(doors.get(user.id)?.granted || 0),
@@ -1 +1 @@
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 /* 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 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
+ {"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"]}
@@ -23,6 +23,7 @@ export declare class AuditPerson {
23
23
  user: User;
24
24
  roles: string[];
25
25
  lastCheckinAt?: Date;
26
+ lastUsedAt?: Date;
26
27
  checkins: number;
27
28
  failedSignins: number;
28
29
  granted: number;
@@ -87,6 +87,10 @@ tslib_1.__decorate([
87
87
  (0, type_graphql_1.Field)({ nullable: true, description: 'The last check-in to this domain, at any time.' }),
88
88
  tslib_1.__metadata("design:type", Date)
89
89
  ], AuditPerson.prototype, "lastCheckinAt", void 0);
90
+ tslib_1.__decorate([
91
+ (0, type_graphql_1.Field)({ nullable: true, description: "The member's latest request to this domain, at any time - reads an open screen makes by itself included." }),
92
+ tslib_1.__metadata("design:type", Date)
93
+ ], AuditPerson.prototype, "lastUsedAt", void 0);
90
94
  tslib_1.__decorate([
91
95
  (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Check-ins in the period.' }),
92
96
  tslib_1.__metadata("design:type", Number)
@@ -1 +1 @@
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(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
+ {"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,6 +1,6 @@
1
1
  import { AuditAction } from './audit-action.js';
2
2
  import { AuditQuery } from './audit-query.js';
3
3
  import { AuditRequest } from './audit-request.js';
4
- export declare const entities: (typeof AuditAction | typeof AuditRequest)[];
4
+ export declare const entities: (typeof AuditRequest | typeof AuditAction)[];
5
5
  export declare const resolvers: (typeof AuditQuery)[];
6
6
  export declare const subscribers: (typeof import("./audit-subscriber.js").GrantAuditSubscriber | typeof import("./audit-subscriber.js").UserAuditSubscriber | typeof import("./audit-subscriber.js").DomainOwnerAuditSubscriber | typeof import("./audit-subscriber.js").WebAuthCredentialAuditSubscriber)[];
@@ -37,7 +37,7 @@ export * from './role/role-types.js';
37
37
  export * from './user/user-types.js';
38
38
  export * from './domain-link/domain-link-types.js';
39
39
  export * from './access-request/access-request-types.js';
40
- export declare const entities: (typeof import("./web-auth-credential/web-auth-credential.js").WebAuthCredential | typeof import("./user/user.js").User | typeof import("./auth-provider/auth-provider.js").AuthProvider | typeof import("./users-auth-providers/users-auth-providers.js").UsersAuthProviders | typeof import("./domain-owner/domain-owner.js").DomainOwner | typeof import("./granted-role/granted-role.js").GrantedRole | typeof import("./role/role.js").Role | typeof import("./privilege/privilege.js").Privilege | typeof import("./audit/audit-action.js").AuditAction | typeof import("./audit/audit-request.js").AuditRequest | typeof import("./verification-token/verification-token.js").VerificationToken | typeof import("./verification-token/verification-token.js").VerificationTokenType | typeof import("./password-history/password-history.js").PasswordHistory | typeof import("./application/application.js").Application | typeof import("./access-request/access-request.js").AccessRequest | typeof import("./appliance/appliance.js").Appliance | typeof import("./partner/partner.js").Partner | typeof import("./domain-link/domain-link.js").DomainLink)[];
40
+ export declare const entities: (typeof import("./audit/audit-request.js").AuditRequest | typeof import("./audit/audit-action.js").AuditAction | typeof import("./user/user.js").User | typeof import("./role/role.js").Role | typeof import("./privilege/privilege.js").Privilege | typeof import("./domain-owner/domain-owner.js").DomainOwner | typeof import("./web-auth-credential/web-auth-credential.js").WebAuthCredential | typeof import("./users-auth-providers/users-auth-providers.js").UsersAuthProviders | typeof import("./auth-provider/auth-provider.js").AuthProvider | typeof import("./application/application.js").Application | typeof import("./appliance/appliance.js").Appliance | typeof import("./partner/partner.js").Partner | typeof import("./granted-role/granted-role.js").GrantedRole | typeof import("./password-history/password-history.js").PasswordHistory | typeof import("./verification-token/verification-token.js").VerificationToken | typeof import("./verification-token/verification-token.js").VerificationTokenType | typeof import("./domain-link/domain-link.js").DomainLink | typeof import("./access-request/access-request.js").AccessRequest)[];
41
41
  export declare const subscribers: (typeof import("./audit/audit-subscriber.js").GrantAuditSubscriber | typeof import("./audit/audit-subscriber.js").UserAuditSubscriber | typeof import("./audit/audit-subscriber.js").DomainOwnerAuditSubscriber | typeof import("./audit/audit-subscriber.js").WebAuthCredentialAuditSubscriber)[];
42
42
  export declare const schema: {
43
43
  typeDefs: {