Skip to content

Commit e1b9491

Browse files
author
DylanBulmer
committed
implement new policy, rule, authorization, and organization models
1 parent 8109cc6 commit e1b9491

23 files changed

Lines changed: 276 additions & 162 deletions

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@codrjs/models",
3-
"version": "1.0.14",
3+
"version": "1.0.15",
44
"description": "",
55
"main": "./cjs/index.js",
66
"module": "./esm/index.js",
@@ -57,6 +57,6 @@
5757
"uuid": "^9.0.0"
5858
},
5959
"peerDependencies": {
60-
"@codrjs/config": "^1.0.6"
60+
"@codrjs/config": "^1.0.7"
6161
}
6262
}

src/entities/Audit.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { Types } from "mongoose";
22
import type { IBase } from "./Base";
3-
import type { ActionType, EntityType } from "../types";
3+
import type { ActionEnum, ResourceEnum } from "../types";
44

55
export interface IAudit extends Omit<IBase<"Audit">, "createdBy"> {
6-
entityType: EntityType; // (where) what entity got modified
7-
action: ActionType; // action taken
6+
entityType: ResourceEnum; // (where) what entity got modified
7+
action: ActionEnum; // action taken
88
userId: Types.ObjectId; // who
99
payload: object; // what data got modified
1010
}

src/entities/Authorization.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { Types } from "mongoose";
2+
import { Base, IBase } from "./Base";
3+
import type { ActionType, AtLeast, ResourceType } from "@/types";
4+
5+
export interface IAuthorization extends IBase<"Authorization"> {
6+
userId: Types.ObjectId;
7+
roleId: Types.ObjectId[];
8+
}
9+
10+
export interface IAuthorizationResponse {
11+
userId: Types.ObjectId;
12+
roleCodes: string[];
13+
grants: Partial<Record<ResourceType, Partial<Record<ActionType, boolean>>>>;
14+
}
15+
16+
export class Authorization extends Base {
17+
userId: Types.ObjectId;
18+
roleId: Types.ObjectId[];
19+
20+
constructor({
21+
userId,
22+
roleId = [],
23+
_id,
24+
__v,
25+
createdAt,
26+
updatedAt,
27+
createdBy,
28+
updatedBy,
29+
}: AtLeast<IAuthorization, "createdBy" | "userId">) {
30+
super({ _id, __v, createdAt, updatedAt, createdBy, updatedBy });
31+
this.userId = userId;
32+
this.roleId = roleId;
33+
}
34+
35+
toJSON() {
36+
const json = super.toJSON();
37+
return {
38+
userId: this.userId,
39+
roles: this.roleId,
40+
...json,
41+
};
42+
}
43+
}

src/entities/Base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Types } from "mongoose";
2-
import { AtLeast, IModelKind } from "../types";
2+
import { AtLeast } from "../types";
33

4-
export interface IBase<K extends string = string> extends IModelKind<K> {
4+
export interface IBase<K extends string = string> {
55
readonly kind: K;
66
__v?: number;
77
_id: Types.ObjectId;

src/entities/Dataset.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { Types } from "mongoose";
22
import { Group, IGroup } from "./Group";
3-
import { AtLeast } from "@/types";
3+
import { AtLeast, Flags } from "@/types";
44

55
// eslint-disable-next-line @typescript-eslint/no-empty-interface
6-
export interface IDataset extends IGroup<"Dataset"> {
6+
export interface IDataset extends IGroup<"Dataset", Flags> {
77
projectId: Types.ObjectId;
88
}
99

@@ -19,12 +19,11 @@ export class Dataset extends Group {
1919
updatedAt,
2020
name,
2121
members,
22-
teams,
2322
createdBy,
2423
updatedBy,
2524
}: AtLeast<
2625
IDataset,
27-
"createdBy" | "name" | "members" | "teams" | "flags" | "projectId"
26+
"createdBy" | "name" | "members" | "flags" | "projectId"
2827
>) {
2928
super({
3029
_id,
@@ -35,7 +34,6 @@ export class Dataset extends Group {
3534
updatedBy,
3635
name,
3736
members,
38-
teams,
3937
flags,
4038
});
4139
this.projectId = projectId;

src/entities/Group.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11
import type { Types } from "mongoose";
22
import { Base, IBase } from "./Base";
3-
import { Flags } from "../types/Flags";
43
import { AtLeast } from "@/types";
54

6-
export interface IGroup<Kind extends string = "Group", F = object>
7-
extends IBase<Kind> {
8-
createdBy: Types.ObjectId;
9-
members: Types.ObjectId[];
5+
export interface IGroup<
6+
Kind extends string = "Group",
7+
F extends object = object,
8+
> extends IBase<Kind> {
9+
members: IGroupMember[];
1010
name: string;
11-
teams: Types.ObjectId[];
12-
flags: Flags & F;
11+
flags: F;
12+
}
13+
14+
export interface IGroupMember {
15+
type: GroupMemberEnum;
16+
_id: Types.ObjectId;
17+
}
18+
19+
export enum GroupMemberEnum {
20+
"USER" = "USER",
21+
"TEAM" = "TEAM",
1322
}
1423

1524
export class Group extends Base {
16-
members: Types.ObjectId[];
25+
members: IGroupMember[];
1726
name: string;
18-
teams: Types.ObjectId[];
19-
flags: Flags & object;
27+
flags: object;
2028

2129
constructor({
2230
name,
2331
members,
24-
teams,
2532
flags,
2633
_id,
2734
__v,
2835
createdAt,
2936
updatedAt,
3037
createdBy,
3138
updatedBy,
32-
}: AtLeast<IGroup, "createdBy" | "name" | "members" | "teams" | "flags">) {
39+
}: AtLeast<IGroup, "createdBy" | "name" | "members" | "flags">) {
3340
super({ _id, __v, createdAt, updatedAt, createdBy, updatedBy });
3441
this.name = name;
3542
this.members = members;
36-
this.teams = teams;
3743
this.flags = flags;
3844
}
3945

@@ -43,7 +49,6 @@ export class Group extends Base {
4349
...json,
4450
members: this.members,
4551
name: this.name,
46-
teams: this.teams,
4752
flags: this.flags,
4853
};
4954
}

src/entities/Organization.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Group, IGroup } from "./Group";
2+
3+
interface Flags {
4+
isActive: boolean;
5+
isDeleted: boolean;
6+
}
7+
export interface IOrganization extends IGroup<"Organization", Flags> {
8+
slug: string;
9+
domain: string; // to restrict signin to a specified domain
10+
}
11+
12+
export class Organization extends Group {
13+
readonly slug: string;
14+
readonly domain: string;
15+
16+
constructor({
17+
flags = {
18+
isActive: true,
19+
isDeleted: false,
20+
},
21+
_id,
22+
__v,
23+
createdAt,
24+
updatedAt,
25+
createdBy,
26+
updatedBy,
27+
name,
28+
members,
29+
slug,
30+
domain,
31+
}: IOrganization) {
32+
super({
33+
_id,
34+
__v,
35+
createdAt,
36+
updatedAt,
37+
createdBy,
38+
updatedBy,
39+
name,
40+
members,
41+
flags,
42+
});
43+
this.slug = slug;
44+
this.domain = domain;
45+
}
46+
47+
toJSON() {
48+
const json = super.toJSON();
49+
return {
50+
...json,
51+
slug: this.slug,
52+
};
53+
}
54+
}

src/entities/Role.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Base, IBase } from "./Base";
2+
import { User } from "./User";
3+
import { AtLeast, JwtPayload } from "@/types";
4+
import { ActionEnum, ResourceEnum } from "@/types/Permissions";
5+
6+
export interface IGrant<R = object> {
7+
resource: ResourceEnum;
8+
actions: ActionEnum[];
9+
conditions: {
10+
operator: "eq" | "within";
11+
subjectField: keyof JwtPayload;
12+
resourceField: keyof R;
13+
actions?: ActionEnum[];
14+
}[];
15+
}
16+
17+
export interface IRole extends IBase<"Role"> {
18+
name: string;
19+
code: string;
20+
description: string;
21+
grants: IGrant[];
22+
}
23+
24+
export class Role extends Base {
25+
name: string;
26+
code: string;
27+
description?: string;
28+
grants: IGrant[];
29+
30+
constructor({
31+
name,
32+
code,
33+
description,
34+
grants,
35+
_id,
36+
__v,
37+
createdAt,
38+
updatedAt,
39+
createdBy,
40+
updatedBy,
41+
}: AtLeast<
42+
IRole & { user: User },
43+
"createdBy" | "name" | "code" | "description" | "grants"
44+
>) {
45+
super({ _id, __v, createdAt, updatedAt, createdBy, updatedBy });
46+
this.name = name;
47+
this.code = code;
48+
this.description = description;
49+
this.grants = grants;
50+
}
51+
52+
toJSON() {
53+
const json = super.toJSON();
54+
return {
55+
name: this.name,
56+
code: this.code,
57+
description: this.description,
58+
grants: this.grants,
59+
...json,
60+
};
61+
}
62+
}

src/entities/User.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Base, IBase } from "./Base";
2-
import { AtLeast, UserEnum, UserRoleEnum } from "../types";
2+
import { AtLeast, UserEnum } from "../types";
3+
import { Types } from "mongoose";
34

45
export interface IUser extends IBase<"User"> {
6+
organizationId: Types.ObjectId;
57
type: UserEnum;
68
email: string;
7-
role: UserRoleEnum;
89
flags: {
910
isAnonymous: boolean;
1011
isDeleted: boolean;
@@ -15,7 +16,6 @@ export interface IUser extends IBase<"User"> {
1516
export class User extends Base {
1617
type: UserEnum;
1718
email: string;
18-
role: UserRoleEnum;
1919
flags: {
2020
isAnonymous: boolean;
2121
isDeleted: boolean;
@@ -25,28 +25,25 @@ export class User extends Base {
2525
constructor({
2626
type,
2727
email,
28-
role,
2928
flags = { isDisabled: false, isAnonymous: false, isDeleted: false },
3029
_id,
3130
__v,
3231
createdAt,
3332
updatedAt,
3433
createdBy,
3534
updatedBy,
36-
}: AtLeast<IUser, "createdBy" | "type" | "role" | "email" | "flags">) {
35+
}: AtLeast<IUser, "createdBy" | "type" | "email" | "flags">) {
3736
super({ _id, __v, createdAt, updatedAt, createdBy, updatedBy });
3837
this.type = type;
3938
this.email = email;
4039
this.flags = flags;
41-
this.role = role;
4240
}
4341

4442
toJSON() {
4543
const json = super.toJSON();
4644
return {
4745
type: this.type,
4846
email: this.email,
49-
role: this.role,
5047
flags: this.flags,
5148
...json,
5249
};

src/entities/UserGroup.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { Flags } from "@/types";
12
import { Group, IGroup } from "./Group";
23

3-
interface IAdditionalFlags {
4+
interface IAdditionalFlags extends Flags {
45
// anonymize the data?
56
isAnonymous: boolean;
67
// others can join?
@@ -24,7 +25,6 @@ export class UserGroup extends Group {
2425
updatedBy,
2526
name,
2627
members,
27-
teams,
2828
}: IUserGroup) {
2929
super({
3030
_id,
@@ -35,7 +35,6 @@ export class UserGroup extends Group {
3535
updatedBy,
3636
name,
3737
members,
38-
teams,
3938
flags,
4039
});
4140
}

0 commit comments

Comments
 (0)