Skip to content

Commit

Permalink
Merge pull request #153 from UKDanceBlue/casl
Browse files Browse the repository at this point in the history
Casl
  • Loading branch information
jthoward64 authored Dec 8, 2024
2 parents 7460282 + ade1d55 commit 43223c9
Show file tree
Hide file tree
Showing 182 changed files with 7,841 additions and 5,615 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"portsAttributes": {
"5173": {
"label": "Admin Portal",
"onAutoForward": "openBrowserOnce"
"onAutoForward": "silent"
},
"5001": {
"label": "Refine Devtools",
Expand Down
9 changes: 5 additions & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
"env": {
"REACT_EDITOR": "code"
},

"autoAttachChildProcesses": false
},
{
Expand All @@ -121,17 +120,19 @@
"request": "launch",
"type": "firefox",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/packages/portal/src",
"webRoot": "${workspaceFolder}/packages/portal",
"presentation": {
"group": "5portal"
}
},
"keepProfileChanges": true,
"profile": "default"
},
{
"name": "Debug Portal (chrome)",
"request": "launch",
"type": "chrome",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/packages/portal/src",
"webRoot": "${workspaceFolder}/packages/portal",
"presentation": {
"group": "5portal"
}
Expand Down
22 changes: 10 additions & 12 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,38 @@
],
"words": [
"autoincrement",
"bbnvolved",
"catchable",
"citext",
"codegen",
"collapsable",
"cooldown",
"danceblue",
"ukdanceblue",
"luxon",
"typedi",
"ukdb",
"msal",
"tada",
"xdate",
"skia",
"hstore",
"minifiable",
"refinedev",
"datasource",
"ddns",
"errorable",
"freshgum",
"hstore",
"jonasmerlin",
"linkblue",
"luxon",
"minifiable",
"msal",
"phonathon",
"refinedev",
"skia",
"spinnable",
"tada",
"timestamptz",
"typedi",
"uk",
"ukdanceblue",
"ukdb",
"uky",
"urql",
"whatwg",
"wysimark"
"wysimark",
"xdate"
],
"allowCompoundWords": true,
"ignoreWords": [],
Expand Down
1 change: 0 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ export default eslintTs.config(
"unicorn/prefer-regexp-test": "error",
"unicorn/prefer-set-has": "error",
"unicorn/prefer-set-size": "error",
"unicorn/prefer-spread": "error",
"unicorn/prefer-string-replace-all": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-trim-start-end": "error",
Expand Down
50 changes: 25 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,50 +63,50 @@
"urijs": "npm:uri-js-replace"
},
"devDependencies": {
"@eslint/compat": "^1.2.3",
"@eslint/compat": "^1.2.4",
"@eslint/config-inspector": "^0.5.6",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.15.0",
"@eslint/js": "^9.16.0",
"@expo/ngrok": "^4.1.3",
"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/client-preset": "patch:@graphql-codegen/client-preset@npm%3A4.4.0#~/.yarn/patches/@graphql-codegen-client-preset-npm-4.4.0-d441b92060.patch",
"@graphql-eslint/eslint-plugin": "^4.2.0",
"@graphql-eslint/eslint-plugin": "^4.3.0",
"@parcel/watcher": "^2.5.0",
"@types/eslint-config-prettier": "^6.11.3",
"@types/eslint__eslintrc": "^2.1.2",
"@types/eslint__js": "^8.42.3",
"@types/react": "~18.3.12",
"@types/react-dom": "~18.3.1",
"@typescript-eslint/utils": "^8.14.0",
"@vitest/coverage-v8": "^2.1.5",
"@vitest/eslint-plugin": "^1.1.10",
"@vitest/ui": "^2.1.5",
"@types/react": "~18.3.14",
"@types/react-dom": "~18.3.2",
"@typescript-eslint/utils": "^8.17.0",
"@vitest/coverage-v8": "^2.1.8",
"@vitest/eslint-plugin": "^1.1.14",
"@vitest/ui": "^2.1.8",
"@yarnpkg/types": "^4.0.0",
"babel-cli": "^6.26.0",
"chokidar-cli": "^3.0.0",
"eslint": "9.14.0",
"eslint": "9.16.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-n": "^17.13.2",
"eslint-plugin-n": "^17.14.0",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.16",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unicorn": "^56.0.0",
"globals": "^15.12.0",
"eslint-plugin-unicorn": "^56.0.1",
"globals": "^15.13.0",
"graphql": "^16.9.0",
"graphql-scalars": "^1.23.0",
"node-gyp": "^10.2.0",
"prettier": "^3.3.3",
"sort-package-json": "^2.10.1",
"graphql-scalars": "^1.24.0",
"node-gyp": "^11.0.0",
"prettier": "^3.4.2",
"sort-package-json": "^2.12.0",
"ts-node": "^10.9.2",
"typedoc": "^0.26.11",
"typedoc-plugin-dt-links": "^1.1.0",
"typedoc-plugin-mdn-links": "^4.0.1",
"typedoc": "^0.27.3",
"typedoc-plugin-dt-links": "^1.1.2",
"typedoc-plugin-mdn-links": "^4.0.4",
"typedoc-plugin-missing-exports": "^3.1.0",
"typedoc-plugin-zod": "^1.3.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.14.0",
"vitest": "^2.1.5"
"typescript": "^5.7.2",
"typescript-eslint": "^8.17.0",
"vitest": "^2.1.8"
},
"packageManager": "[email protected]+sha512.3003a14012e2987072d244c720506549c1aab73ee728208f1b2580a9fd67b92d61ba6b08fe93f6dce68fd771e3af1e59a0afa28dd242dd0940d73b95fedd4e90"
}
8 changes: 7 additions & 1 deletion packages/common/lib/api/params/LoginState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Field,ObjectType } from "type-graphql";
import { PackRule } from "@casl/ability/extra";
import { JSONResolver } from "graphql-scalars";
import { Field, ObjectType } from "type-graphql";

import { AppAbility } from "../../authorization/accessControl.js";
import {
AccessLevel,
Authorization,
Expand All @@ -24,4 +27,7 @@ export class LoginState implements Authorization {

@Field(() => [EffectiveCommitteeRole])
effectiveCommitteeRoles!: EffectiveCommitteeRole[];

@Field(() => [[JSONResolver]])
abilityRules!: PackRule<AppAbility["rules"][number]>[];
}
5 changes: 3 additions & 2 deletions packages/common/lib/api/params/eventParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ export class SetEventOccurrenceInput {
@Field(() => GlobalIdScalar, {
nullable: true,
description:
"If updating an existing occurrence, the UUID of the occurrence to update",
"If updating an existing occurrence, the GlobalId of the occurrence to update",
})
uuid!: GlobalId | null;
id!: GlobalId | null;

@Field(() => IntervalISO)
interval!: IntervalISO;
@Field(() => Boolean)
Expand Down
18 changes: 1 addition & 17 deletions packages/common/lib/api/params/fundraisingAccess.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { Field,InputType } from "type-graphql";

import { AccessControlParam } from "../../authorization/accessControl.js";
import {
CommitteeIdentifier,
CommitteeRole,
} from "../../authorization/structures.js";
import { FundraisingAssignmentNode } from "../resources/Fundraising.js";
import { Field, InputType } from "type-graphql";

@InputType()
export class AssignEntryToPersonInput {
Expand All @@ -18,12 +11,3 @@ export class UpdateFundraisingAssignmentInput {
@Field()
amount!: number;
}
export const fundraisingAccess: AccessControlParam<FundraisingAssignmentNode> =
{
authRules: [
{
minCommitteeRole: CommitteeRole.Coordinator,
committeeIdentifiers: [CommitteeIdentifier.fundraisingCommittee, CommitteeIdentifier.dancerRelationsCommittee],
},
],
};
15 changes: 4 additions & 11 deletions packages/common/lib/api/resources/Event.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Field, ID, ObjectType } from "type-graphql";
import { Field, ObjectType } from "type-graphql";

import { createNodeClasses, Node } from "../relay.js";
import type { GlobalId } from "../scalars/GlobalId.js";
Expand Down Expand Up @@ -45,26 +45,19 @@ export class EventNode extends TimestampedResource implements Node {
implements: [],
})
export class EventOccurrenceNode extends Resource {
@Field(() => ID)
id!: string;
@Field(() => GlobalIdScalar)
id!: GlobalId;
@Field(() => IntervalISO)
interval!: IntervalISO;
@Field(() => Boolean)
fullDay!: boolean;

public getUniqueId(): string {
return this.id;
}

public static init(init: {
id: string;
interval: IntervalISO;
fullDay: boolean;
}) {
const resource = this.createInstance();
resource.id = init.id;
resource.interval = init.interval;
resource.fullDay = init.fullDay;
const resource = this.createInstance().withValues(init);
return resource;
}
}
Expand Down
31 changes: 14 additions & 17 deletions packages/common/lib/api/resources/Notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { DateTimeISOResolver, URLResolver } from "graphql-scalars";
import type { DateTime } from "luxon";
import { Field, ObjectType } from "type-graphql";

import { AccessControlAuthorized } from "../../authorization/accessControl.js";
import { AccessLevel } from "../../authorization/structures.js";
import { AccessControlAuthorized } from "../../authorization/AccessControlParam.js";
import { dateTimeFromSomething } from "../../utility/time/intervalTools.js";
import { createNodeClasses, Node } from "../relay.js";
import type { GlobalId } from "../scalars/GlobalId.js";
Expand All @@ -27,15 +26,15 @@ export class NotificationNode extends TimestampedResource implements Node {
url?: URL | undefined | null;

@Field(() => String, { nullable: true })
@AccessControlAuthorized({
accessLevel: AccessLevel.CommitteeChairOrCoordinator,
})
@AccessControlAuthorized("get", "NotificationNode", ".deliveryIssue")
deliveryIssue?: string | undefined | null;

@Field(() => DateTimeISOResolver, { nullable: true })
@AccessControlAuthorized({
accessLevel: AccessLevel.CommitteeChairOrCoordinator,
})
@AccessControlAuthorized(
"get",
"NotificationNode",
".deliveryIssueAcknowledgedAt"
)
deliveryIssueAcknowledgedAt?: Date | undefined | null;
get deliveryIssueAcknowledgedAtDateTime(): DateTime | null {
return dateTimeFromSomething(this.deliveryIssueAcknowledgedAt ?? null);
Expand Down Expand Up @@ -105,29 +104,27 @@ export class NotificationDeliveryNode
description:
"The time the server received a delivery receipt from the user.",
})
@AccessControlAuthorized({
accessLevel: AccessLevel.CommitteeChairOrCoordinator,
})
@AccessControlAuthorized(
"get",
"NotificationDeliveryNode",
".receiptCheckedAt"
)
receiptCheckedAt?: Date | undefined | null;

@Field(() => String, {
nullable: true,
description:
"A unique identifier corresponding the group of notifications this was sent to Expo with.",
})
@AccessControlAuthorized({
accessLevel: AccessLevel.CommitteeChairOrCoordinator,
})
@AccessControlAuthorized("get", "NotificationDeliveryNode", ".chunkUuid")
chunkUuid?: string | undefined | null;

@Field(() => String, {
nullable: true,
description:
"Any error message returned by Expo when sending the notification.",
})
@AccessControlAuthorized({
accessLevel: AccessLevel.CommitteeChairOrCoordinator,
})
@AccessControlAuthorized("get", "NotificationDeliveryNode", ".deliveryError")
deliveryError?: string | undefined | null;

public getUniqueId(): string {
Expand Down
9 changes: 8 additions & 1 deletion packages/common/lib/api/resources/Resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Field, ObjectType } from "type-graphql";
import type { Class } from "utility-types";

import { dateTimeFromSomething } from "../../utility/time/intervalTools.js";
import { GlobalId } from "../scalars/GlobalId.js";
import { GlobalId, isGlobalId } from "../scalars/GlobalId.js";

@ObjectType()
export abstract class Resource {
Expand All @@ -17,6 +17,13 @@ export abstract class Resource {
* implements it.
*/
public getUniqueId(): string {
if ("id" in this) {
if (isGlobalId(this.id)) {
return this.id.id;
} else if (typeof this.id === "string") {
return this.id;
}
}
throw new Error(`Method not implemented by subclass.`);
}

Expand Down
Loading

0 comments on commit 43223c9

Please sign in to comment.