Skip to content

Commit aaef69c

Browse files
authored
Merge pull request #3235 from SeedCompany/finish-actor
2 parents 4a93c35 + 57899d1 commit aaef69c

17 files changed

+198
-28
lines changed

src/common/resource.dto.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ export type ResourceRelationsShape = ResourceShape<any>['Relations'];
8585
export class EnhancedResource<T extends ResourceShape<any>> {
8686
/** @internal */
8787
static readonly dbTypes = new WeakMap<ResourceShape<any>, $.$expr_PathNode>();
88+
/** @internal */
89+
static readonly dbSkipAccessPolicies = new Set<string>();
8890

8991
private constructor(readonly type: T) {}
9092
private static readonly refs = new WeakMap<
@@ -255,6 +257,10 @@ export class EnhancedResource<T extends ResourceShape<any>> {
255257
return type as any;
256258
}
257259

260+
get generateAccessPolicies() {
261+
return this.hasDB && !EnhancedResource.dbSkipAccessPolicies.has(this.dbFQN);
262+
}
263+
258264
get dbFQN(): ResourceShape<any> extends T ? string : DBName<DBType<T>> {
259265
return this.db.__element__.__name__ as any;
260266
}

src/components/admin/admin.edgedb.repository.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { ID, Role } from '~/common';
33
import { RootUserAlias } from '~/core/config/root-user.config';
44
import { disableAccessPolicies, e, EdgeDB } from '~/core/edgedb';
55
import { AuthenticationRepository } from '../authentication/authentication.repository';
6-
import { ActorRepository } from '../user/actor.repository';
6+
import { SystemAgentRepository } from '../user/system-agent.repository';
77

88
@Injectable()
99
export class AdminEdgeDBRepository {
1010
private readonly db: EdgeDB;
1111
constructor(
1212
edgedb: EdgeDB,
1313
readonly auth: AuthenticationRepository,
14-
readonly actors: ActorRepository,
14+
readonly agents: SystemAgentRepository,
1515
) {
1616
this.db = edgedb.withOptions(disableAccessPolicies);
1717
}
@@ -38,7 +38,7 @@ export class AdminEdgeDBRepository {
3838
}
3939

4040
async createRootUser(id: ID, email: string, passwordHash: string) {
41-
const ghost = await this.actors.getGhost();
41+
const ghost = await this.agents.getGhost();
4242

4343
const newUser = e.insert(e.User, {
4444
id,
@@ -63,7 +63,7 @@ export class AdminEdgeDBRepository {
6363
}
6464

6565
async updateEmail(id: ID, email: string) {
66-
const ghost = await this.actors.getGhost();
66+
const ghost = await this.agents.getGhost();
6767
const u = e.cast(e.User, e.uuid(id));
6868
const query = e.update(u, () => ({ set: { email } }));
6969
await this.db

src/components/authentication/authentication.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { ForgotPassword } from '~/core/email/templates';
2222
import { Privileges } from '../authorization';
2323
import { rolesForScope, withoutScope } from '../authorization/dto';
2424
import { AssignableRoles } from '../authorization/dto/assignable-roles';
25-
import { ActorRepository } from '../user/actor.repository';
25+
import { SystemAgentRepository } from '../user/system-agent.repository';
2626
import { AuthenticationRepository } from './authentication.repository';
2727
import { CryptoService } from './crypto.service';
2828
import { LoginInput, RegisterInput, ResetPasswordInput } from './dto';
@@ -42,7 +42,7 @@ export class AuthenticationService {
4242
@Logger('authentication:service') private readonly logger: ILogger,
4343
private readonly repo: AuthenticationRepository,
4444
private readonly edgedb: EdgeDB,
45-
private readonly actors: ActorRepository,
45+
private readonly agents: SystemAgentRepository,
4646
private readonly moduleRef: ModuleRef,
4747
) {}
4848

@@ -121,7 +121,7 @@ export class AuthenticationService {
121121

122122
const [result, anon] = await Promise.all([
123123
this.repo.resumeSession(token, impersonatee?.id),
124-
this.actors.getAnonymous(),
124+
this.agents.getAnonymous(),
125125
]);
126126

127127
if (!result) {

src/components/authorization/policy/edgedb-access-policy.generator.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export class EdgeDBAccessPolicyGenerator {
1717

1818
makeSdl(params: AsEdgeQLParams<any>) {
1919
const { resource } = params;
20+
21+
if (!resource.generateAccessPolicies) {
22+
return undefined;
23+
}
24+
2025
const actions = {
2126
select: 'read',
2227
'update read': 'read',
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ID } from '~/common';
2+
import { LoaderFactory, SessionAwareLoaderStrategy } from '~/core';
3+
import { Actor } from './dto';
4+
import { UserService } from './user.service';
5+
6+
@LoaderFactory(() => Actor)
7+
export class ActorLoader extends SessionAwareLoaderStrategy<Actor> {
8+
constructor(private readonly users: UserService) {
9+
super();
10+
}
11+
12+
async loadMany(ids: readonly ID[]) {
13+
return await this.users.readManyActors(ids, this.session);
14+
}
15+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { InterfaceType, ObjectType } from '@nestjs/graphql';
2+
import { keys as keysOf } from 'ts-transformer-keys';
3+
import {
4+
DataObject,
5+
ID,
6+
IdField,
7+
NameField,
8+
resolveByTypename,
9+
Role,
10+
SecuredProperty,
11+
SecuredProps,
12+
} from '~/common';
13+
import { RegisterResource } from '~/core';
14+
import { e } from '~/core/edgedb';
15+
16+
@RegisterResource({
17+
db: e.Actor,
18+
skipAccessPolicies: true,
19+
})
20+
@InterfaceType({
21+
resolveType: resolveByTypename(Actor.name),
22+
})
23+
export class Actor extends DataObject {
24+
static readonly Props: string[] = keysOf<Actor>();
25+
static readonly SecuredProps: string[] = keysOf<SecuredProps<Actor>>();
26+
27+
@IdField()
28+
readonly id: ID;
29+
}
30+
31+
@ObjectType({
32+
implements: [Actor],
33+
})
34+
export abstract class SystemAgent extends Actor {
35+
__typename?: 'SystemAgent';
36+
37+
@NameField()
38+
readonly name: string;
39+
40+
readonly roles: readonly Role[];
41+
}
42+
43+
@ObjectType({
44+
description: SecuredProperty.descriptionFor('a actor'),
45+
})
46+
export class SecuredActor extends SecuredProperty(Actor) {}
47+
48+
declare module '~/core/resources/map' {
49+
interface ResourceMap {
50+
Actor: typeof Actor;
51+
}
52+
interface ResourceDBMap {
53+
Actor: typeof e.Actor;
54+
}
55+
}

src/components/user/dto/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './actor.dto';
12
export * from './user.dto';
23
export * from './list-users.dto';
34
export * from './create-person.dto';

src/components/user/dto/user.dto.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Field, ObjectType } from '@nestjs/graphql';
22
import { keys as keysOf } from 'ts-transformer-keys';
33
import {
4+
DbLabel,
45
DbUnique,
56
IntersectTypes,
67
NameField,
@@ -21,15 +22,17 @@ import { Pinnable } from '../../pin/dto';
2122
import { IProject as Project } from '../../project/dto';
2223
import { Education } from '../education/dto';
2324
import { Unavailability } from '../unavailability/dto';
25+
import { Actor } from './actor.dto';
2426
import { KnownLanguage } from './known-language.dto';
2527
import { SecuredUserStatus } from './user-status.enum';
2628

27-
const Interfaces = IntersectTypes(Resource, Pinnable);
29+
const Interfaces = IntersectTypes(Resource, Actor, Pinnable);
2830

2931
@RegisterResource({ db: e.User })
3032
@ObjectType({
3133
implements: Interfaces.members,
3234
})
35+
@DbLabel('User', 'Actor')
3336
export class User extends Interfaces {
3437
static readonly Props = keysOf<User>();
3538
static readonly SecuredProps = keysOf<SecuredProps<User>>();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { BaseMigration, Migration } from '~/core/database';
2+
3+
@Migration('2024-06-07T12:00:00')
4+
export class AddActorLabelMigration extends BaseMigration {
5+
async up() {
6+
await this.db.query().raw`
7+
match (n)
8+
where n:User or n:SystemAgent
9+
set n:Actor
10+
return count(n)
11+
`.executeAndLogStats();
12+
}
13+
}

src/components/user/actor.edgedb.repository.ts renamed to src/components/user/system-agent.edgedb.repository.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Injectable } from '@nestjs/common';
22
import { Role } from '~/common';
33
import { disableAccessPolicies, EdgeDB, edgeql } from '~/core/edgedb';
4-
import { ActorRepository } from './actor.repository';
4+
import { SystemAgentRepository } from './system-agent.repository';
55

66
@Injectable()
7-
export class ActorEdgeDBRepository extends ActorRepository {
7+
export class SystemAgentEdgeDBRepository extends SystemAgentRepository {
88
private readonly db: EdgeDB;
99
constructor(edgedb: EdgeDB) {
1010
super();

0 commit comments

Comments
 (0)