@sixb/pg 0.1.12 → 0.1.14
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/auth-storage/access-tokens.d.ts.map +1 -1
- package/dist/auth-storage/auth-storage.d.ts +2 -1
- package/dist/auth-storage/auth-storage.d.ts.map +1 -1
- package/dist/auth-storage/device-authorizations.d.ts.map +1 -1
- package/dist/auth-storage/rows.d.ts +7 -4
- package/dist/auth-storage/rows.d.ts.map +1 -1
- package/dist/auth-storage/sessions.d.ts +8 -1
- package/dist/auth-storage/sessions.d.ts.map +1 -1
- package/dist/auth-storage/shared.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +403 -115
- package/dist/index.js.map +16 -15
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/storage.d.ts.map +1 -1
- package/dist/ontology-storage/materializations.d.ts +0 -2
- package/dist/ontology-storage/materializations.d.ts.map +1 -1
- package/dist/ontology-storage/shared.d.ts +2 -1
- package/dist/ontology-storage/shared.d.ts.map +1 -1
- package/dist/pg-file-upload-session-storage.d.ts +6 -0
- package/dist/pg-file-upload-session-storage.d.ts.map +1 -0
- package/dist/pg-workflow-intervention-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/auth-storage/access-tokens.ts +10 -14
- package/src/auth-storage/auth-storage.ts +47 -81
- package/src/auth-storage/device-authorizations.ts +3 -4
- package/src/auth-storage/rows.ts +18 -8
- package/src/auth-storage/sessions.ts +82 -4
- package/src/auth-storage/shared.ts +8 -2
- package/src/index.ts +5 -0
- package/src/migrations/046-workflow-intervention-principals.sql +15 -0
- package/src/migrations/047-ontology-commit-attribution.sql +50 -0
- package/src/migrations/048-file-upload-sessions.sql +34 -0
- package/src/migrations/049-native-sessions.sql +19 -0
- package/src/migrations/050-directory-group-memberships.sql +5 -0
- package/src/migrations.ts +16 -0
- package/src/objects/storage.ts +2 -0
- package/src/ontology-storage/materializations.ts +15 -58
- package/src/ontology-storage/shared.ts +7 -3
- package/src/pg-file-upload-session-storage.ts +143 -0
- package/src/pg-workflow-intervention-storage.ts +11 -15
package/dist/migrations.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAuG3B,OAAO,KAAK,EAAE,GAAG,EAAa,MAAM,aAAa,CAAA;AAEjD,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC;AAED,eAAO,MAAM,2BAA2B,wBAAwB,CAAA;AAEhE,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,wBAAwB,CAAC,CAE1F;AAED,wBAAgB,MAAM,CACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/D,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,wBAAwB,CAAC,CAEzC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,GACjB,SAAS,eAAe,EAAE,CAQ5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,wBAAwB,CAAC,CAAA;CAC5D,GAAG,eAAe,CAqBlB;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxF;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AA6KD,eAAO,MAAM,yBAAyB,wCAsDpC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/objects/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,KAAK,aAAa,EAAkC,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/objects/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,8 +20,6 @@ export declare class PgOntologyMaterializationStorage implements OntologyMateria
|
|
|
20
20
|
private assertCommitAbsent;
|
|
21
21
|
private assertSources;
|
|
22
22
|
private assertSourceRow;
|
|
23
|
-
private assertObject;
|
|
24
|
-
private assertLink;
|
|
25
23
|
private assertFinalization;
|
|
26
24
|
private assertFinalCardinality;
|
|
27
25
|
private projectionCounts;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materializations.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/materializations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"materializations.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/materializations.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,4BAA4B,EAC5B,8BAA8B,EAC9B,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EAEvB,8BAA8B,EAC9B,uCAAuC,EAEvC,0BAA0B,EAC1B,6BAA6B,EAC7B,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,EAClC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAG7C,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,2BAA2B,CAAA;AAqClC,qBAAa,gCAAiC,YAAW,8BAA8B;IAKnF,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAG7B,GAAG,EAAE,SAAS,EAC/B,OAAO,EAAE,4BAA4B,GAAG,IAAI;IAM9C,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAY1F,KAAK,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqDvE,WAAW,CAChB,KAAK,EAAE,+BAA+B,GACrC,aAAa,CAAC,wBAAwB,CAAC;IAqDnC,4BAA4B,CACjC,KAAK,EAAE,iCAAiC,GACvC,aAAa,CAAC,0BAA0B,CAAC;IA6FtC,SAAS,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,UAAU,CAAC,KAAK,EAAE,8BAA8B,GAAG,aAAa,CAAC,uBAAuB,CAAC;IAKnF,mBAAmB,CACvB,KAAK,EAAE,uCAAuC,GAC7C,OAAO,CAAC,SAAS,8BAA8B,EAAE,CAAC;IAK/C,UAAU,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,IAAI,CAAC;IAahE,QAAQ,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAgBxF,kBAAkB,IAAI,IAAI;YAIZ,kBAAkB;YA6DlB,kBAAkB;YAmDlB,aAAa;IAoB3B,OAAO,CAAC,eAAe;YAeT,kBAAkB;YAqDlB,sBAAsB;YAyDtB,gBAAgB;YA2DhB,gBAAgB;YAiChB,cAAc;YA6Gd,YAAY;YAqCZ,eAAe;YAcf,SAAS;CAgBxB"}
|
|
@@ -12,7 +12,8 @@ export interface PgOntologyCommitRow {
|
|
|
12
12
|
readonly origin_run_id: string | null;
|
|
13
13
|
readonly origin_batch_ordinal: number | string | null;
|
|
14
14
|
readonly origin: unknown;
|
|
15
|
-
readonly
|
|
15
|
+
readonly requested_by: unknown | null;
|
|
16
|
+
readonly executor: unknown;
|
|
16
17
|
readonly ontology_revision: string;
|
|
17
18
|
readonly projection_revision: string | null;
|
|
18
19
|
readonly ownership_hash: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/shared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,yCAAyC,EACzC,oBAAoB,EAEpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,eAAe,GAChB,MAAM,+CAA+C,CAAA;AAEtD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAIpF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/shared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,yCAAyC,EACzC,oBAAoB,EAEpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,eAAe,GAChB,MAAM,+CAA+C,CAAA;AAEtD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAIpF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAA;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,eAAe,EAAE,QAAQ,GAAG,MAAM,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAC/C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,0BAA0B,EAAE,IAAI,GAAG,MAAM,CAAA;IAClD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC3C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAChD,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IAC3C,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,MAAM,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAA;IACzC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAA;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IAC/C,QAAQ,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IAC3C,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;CACnC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAE3F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAE5E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASjF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,oBAAoB,CAuC3E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,4BAA4B,GAAG,oBAAoB,CAMvF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,oBAAoB,CAwB3E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,oBAAoB,CAc3E;AAED,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,SAAS,EACd,KAAK,EAAE;IACL,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,yCAAyC,CAAC,UAAU,CAAC,CAAA;CAC1E,GACA,OAAO,CAAC,IAAI,CAAC,CA2Df;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEjF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DurableFileUploadSessions } from "@sixb/core/internal/file-upload-session-storage-provider";
|
|
2
|
+
import { type PgStoreClient } from "./transactions";
|
|
3
|
+
export declare class PgFileUploadSessionStorage extends DurableFileUploadSessions {
|
|
4
|
+
constructor(sql: PgStoreClient);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=pg-file-upload-session-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-file-upload-session-storage.d.ts","sourceRoot":"","sources":["../src/pg-file-upload-session-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAK1B,MAAM,0DAA0D,CAAA;AAEjE,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AAErE,qBAAa,0BAA2B,SAAQ,yBAAyB;gBAC3D,GAAG,EAAE,aAAa;CAG/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-workflow-intervention-storage.d.ts","sourceRoot":"","sources":["../src/pg-workflow-intervention-storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,+BAA+B,
|
|
1
|
+
{"version":3,"file":"pg-workflow-intervention-storage.d.ts","sourceRoot":"","sources":["../src/pg-workflow-intervention-storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,+BAA+B,EAE/B,+BAA+B,EAC/B,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,oBAAoB,CAAA;AAI3B,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AAErE,qBAAa,6BAA8B,YAAW,2BAA2B;IACnE,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEzC,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmDnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmBnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAkBnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAiBnF,OAAO,CAAC,MAAM,EAAE;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,EAAE,EAAE,MAAM,CAAA;KACX,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC;IASxC,IAAI,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,+BAA+B,CAAC;CAiG5F"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sixb/pg",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "PostgreSQL storage provider for Sixb",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sixb",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"postgres": "^3.4.5"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@sixb/core": "0.1.
|
|
43
|
+
"@sixb/core": "0.1.14"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@sixb/core": "0.1.
|
|
46
|
+
"@sixb/core": "0.1.14",
|
|
47
47
|
"@types/bun": "latest",
|
|
48
48
|
"typescript": "^5.7.0"
|
|
49
49
|
},
|
|
@@ -24,10 +24,10 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
24
24
|
const id = assertNonEmpty(input.id, "Access token id")
|
|
25
25
|
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
26
26
|
const name = assertNonEmpty(input.name, "Access token name")
|
|
27
|
-
const subjectId = assertNonEmpty(input.
|
|
27
|
+
const subjectId = assertNonEmpty(input.subject.id, "Access token subject id")
|
|
28
28
|
const tokenHash = assertNonEmpty(input.tokenHash, "Access token hash")
|
|
29
29
|
assertKindMatchesSubject(input)
|
|
30
|
-
await this.assertSubjectExists(projectId, input.
|
|
30
|
+
await this.assertSubjectExists(projectId, input.subject.type, subjectId)
|
|
31
31
|
const groupIds = input.groupIds === undefined ? undefined : normalizeGroupIds(input.groupIds)
|
|
32
32
|
|
|
33
33
|
try {
|
|
@@ -52,7 +52,7 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
52
52
|
${id},
|
|
53
53
|
${name},
|
|
54
54
|
${input.kind},
|
|
55
|
-
${input.
|
|
55
|
+
${input.subject.type},
|
|
56
56
|
${subjectId},
|
|
57
57
|
${tokenHash},
|
|
58
58
|
${serializeOptionalStringArray(groupIds)},
|
|
@@ -99,13 +99,9 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
99
99
|
whereClauses.push(`kind = $${nextIndex++}`)
|
|
100
100
|
params.push(input.kind)
|
|
101
101
|
}
|
|
102
|
-
if (input.
|
|
103
|
-
whereClauses.push(`subject_type = $${nextIndex++}`)
|
|
104
|
-
params.push(input.
|
|
105
|
-
}
|
|
106
|
-
if (input.subjectId) {
|
|
107
|
-
whereClauses.push(`subject_id = $${nextIndex++}`)
|
|
108
|
-
params.push(input.subjectId)
|
|
102
|
+
if (input.subject) {
|
|
103
|
+
whereClauses.push(`subject_type = $${nextIndex++}`, `subject_id = $${nextIndex++}`)
|
|
104
|
+
params.push(input.subject.type, input.subject.id)
|
|
109
105
|
}
|
|
110
106
|
if (!input.includeRevoked) {
|
|
111
107
|
whereClauses.push("revoked_at IS NULL")
|
|
@@ -208,7 +204,7 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
208
204
|
|
|
209
205
|
private async assertSubjectExists(
|
|
210
206
|
projectId: string,
|
|
211
|
-
subjectType: CreateAuthAccessTokenInput["
|
|
207
|
+
subjectType: CreateAuthAccessTokenInput["subject"]["type"],
|
|
212
208
|
subjectId: string
|
|
213
209
|
): Promise<void> {
|
|
214
210
|
if (subjectType === "user") {
|
|
@@ -241,14 +237,14 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
241
237
|
|
|
242
238
|
function assertKindMatchesSubject(input: CreateAuthAccessTokenInput): void {
|
|
243
239
|
if (
|
|
244
|
-
(input.kind === "personal" && input.
|
|
245
|
-
(input.kind === "serviceAccount" && input.
|
|
240
|
+
(input.kind === "personal" && input.subject.type === "user") ||
|
|
241
|
+
(input.kind === "serviceAccount" && input.subject.type === "serviceAccount")
|
|
246
242
|
) {
|
|
247
243
|
return
|
|
248
244
|
}
|
|
249
245
|
|
|
250
246
|
throw new AuthStorageError(
|
|
251
247
|
"invalid_input",
|
|
252
|
-
`[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.
|
|
248
|
+
`[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.subject.type}'.`
|
|
253
249
|
)
|
|
254
250
|
}
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
CompleteSignInResult,
|
|
8
8
|
DeviceAuthorizationRecord,
|
|
9
9
|
GroupMembershipRecord,
|
|
10
|
+
GroupMembershipSource,
|
|
10
11
|
InvitationRecord,
|
|
11
12
|
SessionRecord,
|
|
12
13
|
SuspendUserAndRevokeSessionsInput,
|
|
@@ -113,7 +114,7 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
113
114
|
)
|
|
114
115
|
}
|
|
115
116
|
assertCompletableDeviceAuthorization(authorization, input)
|
|
116
|
-
const
|
|
117
|
+
const session = await createSession(tx, input.session)
|
|
117
118
|
const [consumed] = await tx`
|
|
118
119
|
UPDATE auth_device_authorizations
|
|
119
120
|
SET status = 'consumed', consumed_at = ${input.completedAt}
|
|
@@ -132,7 +133,7 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
132
133
|
status: "consumed" as const,
|
|
133
134
|
consumedAt: new Date(input.completedAt),
|
|
134
135
|
},
|
|
135
|
-
|
|
136
|
+
session,
|
|
136
137
|
}
|
|
137
138
|
})
|
|
138
139
|
}
|
|
@@ -232,27 +233,6 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
232
233
|
}
|
|
233
234
|
}
|
|
234
235
|
|
|
235
|
-
if (
|
|
236
|
-
shouldCreateUser &&
|
|
237
|
-
!activeInvitation &&
|
|
238
|
-
input.allowUserCreationWithoutInvitation &&
|
|
239
|
-
input.requireNoActiveUsersForUserCreation &&
|
|
240
|
-
(await hasActiveUsers(tx, projectId))
|
|
241
|
-
) {
|
|
242
|
-
await consumeMagicLink(tx, {
|
|
243
|
-
projectId,
|
|
244
|
-
id: input.magicLinkId,
|
|
245
|
-
tokenHash: input.tokenHash,
|
|
246
|
-
consumedAt: completedAt,
|
|
247
|
-
})
|
|
248
|
-
return {
|
|
249
|
-
error: new AuthStorageError(
|
|
250
|
-
"user_creation_not_allowed",
|
|
251
|
-
`[Sixb] Magic link '${input.magicLinkId}' cannot create a user for project '${projectId}'.`
|
|
252
|
-
),
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
236
|
await validateCompleteSessionInput(tx, projectId, input.session)
|
|
257
237
|
assertSignInSessionAudience(projectId, input.session.audience, magicLink.audience)
|
|
258
238
|
|
|
@@ -294,8 +274,9 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
294
274
|
projectId,
|
|
295
275
|
user,
|
|
296
276
|
})
|
|
297
|
-
const groupMemberships = await this.
|
|
277
|
+
const groupMemberships = await this.applyGroups(tx, {
|
|
298
278
|
completedAt,
|
|
279
|
+
source: "manual",
|
|
299
280
|
existing: invitation.groupMemberships,
|
|
300
281
|
groupIds: manualGroupIds,
|
|
301
282
|
projectId,
|
|
@@ -392,16 +373,6 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
392
373
|
}
|
|
393
374
|
}
|
|
394
375
|
|
|
395
|
-
if (!identity && userRow && (!input.autoLinkByVerifiedEmail || !input.emailVerified)) {
|
|
396
|
-
await this.consumeOidcAttempt(input, completedAt, projectId, tx)
|
|
397
|
-
return {
|
|
398
|
-
error: new AuthStorageError(
|
|
399
|
-
"email_link_not_allowed",
|
|
400
|
-
`[Sixb] OIDC identity cannot auto-link to user '${userRow.id}' for project '${projectId}'.`
|
|
401
|
-
),
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
376
|
if (userRow?.status === "suspended") {
|
|
406
377
|
await this.consumeOidcAttempt(input, completedAt, projectId, tx)
|
|
407
378
|
return {
|
|
@@ -412,16 +383,6 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
412
383
|
}
|
|
413
384
|
}
|
|
414
385
|
|
|
415
|
-
if (shouldCreateUser && !input.emailVerified) {
|
|
416
|
-
await this.consumeOidcAttempt(input, completedAt, projectId, tx)
|
|
417
|
-
return {
|
|
418
|
-
error: new AuthStorageError(
|
|
419
|
-
"user_creation_not_allowed",
|
|
420
|
-
`[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' cannot create a user for project '${projectId}'.`
|
|
421
|
-
),
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
386
|
if (shouldCreateUser && !activeInvitation && !input.allowUserCreationWithoutInvitation) {
|
|
426
387
|
await this.consumeOidcAttempt(input, completedAt, projectId, tx)
|
|
427
388
|
return {
|
|
@@ -432,22 +393,6 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
432
393
|
}
|
|
433
394
|
}
|
|
434
395
|
|
|
435
|
-
if (
|
|
436
|
-
shouldCreateUser &&
|
|
437
|
-
!activeInvitation &&
|
|
438
|
-
input.allowUserCreationWithoutInvitation &&
|
|
439
|
-
input.requireNoActiveUsersForUserCreation &&
|
|
440
|
-
(await hasActiveUsers(tx, projectId))
|
|
441
|
-
) {
|
|
442
|
-
await this.consumeOidcAttempt(input, completedAt, projectId, tx)
|
|
443
|
-
return {
|
|
444
|
-
error: new AuthStorageError(
|
|
445
|
-
"user_creation_not_allowed",
|
|
446
|
-
`[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' cannot create a user for project '${projectId}'.`
|
|
447
|
-
),
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
396
|
await validateCompleteSessionInput(tx, projectId, input.session)
|
|
452
397
|
assertSignInSessionAudience(projectId, input.session.audience, attempt.audience)
|
|
453
398
|
|
|
@@ -497,10 +442,17 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
497
442
|
projectId,
|
|
498
443
|
user,
|
|
499
444
|
})
|
|
500
|
-
const groupMemberships = await this.
|
|
445
|
+
const groupMemberships = await this.syncDirectoryGroups(tx, {
|
|
501
446
|
completedAt,
|
|
502
|
-
existing:
|
|
503
|
-
|
|
447
|
+
existing: await this.applyGroups(tx, {
|
|
448
|
+
completedAt,
|
|
449
|
+
source: "manual",
|
|
450
|
+
existing: invitation.groupMemberships,
|
|
451
|
+
groupIds: manualGroupIds,
|
|
452
|
+
projectId,
|
|
453
|
+
userId: user.id,
|
|
454
|
+
}),
|
|
455
|
+
groupIds: input.directoryGroupIds,
|
|
504
456
|
projectId,
|
|
505
457
|
userId: user.id,
|
|
506
458
|
})
|
|
@@ -703,13 +655,14 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
703
655
|
return { invitation, groupMemberships }
|
|
704
656
|
}
|
|
705
657
|
|
|
706
|
-
private async
|
|
658
|
+
private async applyGroups(
|
|
707
659
|
sql: SQLClient,
|
|
708
660
|
input: {
|
|
709
661
|
readonly completedAt: Date
|
|
710
662
|
readonly existing: readonly GroupMembershipRecord[]
|
|
711
663
|
readonly groupIds: readonly string[]
|
|
712
664
|
readonly projectId: string
|
|
665
|
+
readonly source: GroupMembershipSource
|
|
713
666
|
readonly userId: string
|
|
714
667
|
}
|
|
715
668
|
): Promise<readonly GroupMembershipRecord[]> {
|
|
@@ -721,7 +674,7 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
721
674
|
projectId: input.projectId,
|
|
722
675
|
userId: input.userId,
|
|
723
676
|
groupId,
|
|
724
|
-
source:
|
|
677
|
+
source: input.source,
|
|
725
678
|
createdAt: input.completedAt,
|
|
726
679
|
})
|
|
727
680
|
)
|
|
@@ -729,6 +682,33 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
729
682
|
|
|
730
683
|
return groupMemberships
|
|
731
684
|
}
|
|
685
|
+
// Directory memberships become exactly `groupIds`. A group the user already holds from another
|
|
686
|
+
// source keeps that source, and memberships from other sources are never removed.
|
|
687
|
+
private async syncDirectoryGroups(
|
|
688
|
+
sql: SQLClient,
|
|
689
|
+
input: {
|
|
690
|
+
readonly completedAt: Date
|
|
691
|
+
readonly existing: readonly GroupMembershipRecord[]
|
|
692
|
+
readonly groupIds?: readonly string[]
|
|
693
|
+
readonly projectId: string
|
|
694
|
+
readonly userId: string
|
|
695
|
+
}
|
|
696
|
+
): Promise<readonly GroupMembershipRecord[]> {
|
|
697
|
+
if (!input.groupIds) {
|
|
698
|
+
return input.existing
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const groupIds = normalizeGroupIds(input.groupIds)
|
|
702
|
+
await sql`
|
|
703
|
+
DELETE FROM auth_group_memberships
|
|
704
|
+
WHERE project_id = ${input.projectId}
|
|
705
|
+
AND user_id = ${input.userId}
|
|
706
|
+
AND source = 'directory'
|
|
707
|
+
${groupIds.length > 0 ? sql`AND group_id NOT IN ${sql(groupIds)}` : sql``}
|
|
708
|
+
`
|
|
709
|
+
|
|
710
|
+
return this.applyGroups(sql, { ...input, groupIds, source: "directory" })
|
|
711
|
+
}
|
|
732
712
|
|
|
733
713
|
private async createSignInSession(
|
|
734
714
|
sql: SQLClient,
|
|
@@ -815,18 +795,6 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
815
795
|
}
|
|
816
796
|
}
|
|
817
797
|
|
|
818
|
-
async function hasActiveUsers(sql: SQLClient, projectId: string): Promise<boolean> {
|
|
819
|
-
const rows = (await sql`
|
|
820
|
-
SELECT 1 AS active
|
|
821
|
-
FROM auth_users
|
|
822
|
-
WHERE project_id = ${projectId}
|
|
823
|
-
AND status = 'active'
|
|
824
|
-
LIMIT 1
|
|
825
|
-
`) as Array<{ readonly active: number }>
|
|
826
|
-
|
|
827
|
-
return rows.length > 0
|
|
828
|
-
}
|
|
829
|
-
|
|
830
798
|
function assertSignInSessionAudience(
|
|
831
799
|
projectId: string,
|
|
832
800
|
sessionAudience: string,
|
|
@@ -869,10 +837,8 @@ function assertCompletableDeviceAuthorization(
|
|
|
869
837
|
authorization.expiresAt <= input.completedAt ||
|
|
870
838
|
!authorization.approvedUserId ||
|
|
871
839
|
!authorization.approvedSessionId ||
|
|
872
|
-
input.
|
|
873
|
-
input.
|
|
874
|
-
input.accessToken.subjectId !== authorization.approvedUserId ||
|
|
875
|
-
input.accessToken.createdBySessionId !== authorization.approvedSessionId
|
|
840
|
+
input.session.projectId !== input.projectId ||
|
|
841
|
+
input.session.userId !== authorization.approvedUserId
|
|
876
842
|
) {
|
|
877
843
|
throw new AuthStorageError(
|
|
878
844
|
"invalid_device_authorization",
|
|
@@ -37,16 +37,15 @@ export class PgAuthDeviceAuthorizationStore implements AuthDeviceAuthorizationSt
|
|
|
37
37
|
try {
|
|
38
38
|
const [row] = await tx<PgAuthDeviceAuthorizationRow[]>`
|
|
39
39
|
INSERT INTO auth_device_authorizations (
|
|
40
|
-
project_id, id, device_code_hash, user_code, client_name,
|
|
41
|
-
|
|
40
|
+
project_id, id, device_code_hash, user_code, client_name, status, created_at,
|
|
41
|
+
expires_at
|
|
42
42
|
) VALUES (
|
|
43
43
|
${assertNonEmpty(input.projectId, "Project id")},
|
|
44
44
|
${assertNonEmpty(input.id, "Device authorization id")},
|
|
45
45
|
${assertNonEmpty(input.deviceCodeHash, "Device code hash")},
|
|
46
46
|
${assertNonEmpty(input.userCode, "User code")},
|
|
47
47
|
${assertNonEmpty(input.clientName, "Client name")},
|
|
48
|
-
${
|
|
49
|
-
${input.tokenExpiresAt}, 'pending', ${input.createdAt}, ${input.expiresAt}
|
|
48
|
+
'pending', ${input.createdAt}, ${input.expiresAt}
|
|
50
49
|
) RETURNING *
|
|
51
50
|
`
|
|
52
51
|
return rowToDeviceAuthorizationRecord(row)
|
package/src/auth-storage/rows.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface PgAuthServiceAccountGroupMembershipRow {
|
|
|
58
58
|
readonly project_id: string
|
|
59
59
|
readonly service_account_id: string
|
|
60
60
|
readonly group_id: string
|
|
61
|
-
readonly source:
|
|
61
|
+
readonly source: ServiceAccountGroupMembershipRecord["source"]
|
|
62
62
|
readonly created_at: PgDate
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -76,6 +76,11 @@ export interface PgAuthSessionRow {
|
|
|
76
76
|
readonly last_seen_at: PgDate | null
|
|
77
77
|
readonly user_agent: string | null
|
|
78
78
|
readonly ip_address: string | null
|
|
79
|
+
readonly client_name: string | null
|
|
80
|
+
readonly access_expires_at: PgDate | null
|
|
81
|
+
readonly refresh_token_hash: string | null
|
|
82
|
+
readonly previous_refresh_token_hash: string | null
|
|
83
|
+
readonly refreshed_at: PgDate | null
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
export interface PgAuthAccessTokenRow {
|
|
@@ -83,7 +88,7 @@ export interface PgAuthAccessTokenRow {
|
|
|
83
88
|
readonly id: string
|
|
84
89
|
readonly name: string
|
|
85
90
|
readonly kind: AccessTokenRecord["kind"]
|
|
86
|
-
readonly subject_type: AccessTokenRecord["
|
|
91
|
+
readonly subject_type: AccessTokenRecord["subject"]["type"]
|
|
87
92
|
readonly subject_id: string
|
|
88
93
|
readonly token_hash: string
|
|
89
94
|
readonly group_ids: readonly string[] | string | null
|
|
@@ -157,8 +162,6 @@ export interface PgAuthDeviceAuthorizationRow {
|
|
|
157
162
|
readonly device_code_hash: string
|
|
158
163
|
readonly user_code: string
|
|
159
164
|
readonly client_name: string
|
|
160
|
-
readonly token_name: string
|
|
161
|
-
readonly token_expires_at: PgDate
|
|
162
165
|
readonly status: DeviceAuthorizationRecord["status"]
|
|
163
166
|
readonly approved_user_id: string | null
|
|
164
167
|
readonly approved_session_id: string | null
|
|
@@ -235,6 +238,16 @@ export function rowToSessionRecord(row: PgAuthSessionRow): SessionRecord {
|
|
|
235
238
|
lastSeenAt: row.last_seen_at ? toDate(row.last_seen_at) : undefined,
|
|
236
239
|
userAgent: row.user_agent ?? undefined,
|
|
237
240
|
ipAddress: row.ip_address ?? undefined,
|
|
241
|
+
bearer:
|
|
242
|
+
row.refresh_token_hash !== null && row.client_name !== null && row.access_expires_at !== null
|
|
243
|
+
? {
|
|
244
|
+
clientName: row.client_name,
|
|
245
|
+
accessExpiresAt: toDate(row.access_expires_at),
|
|
246
|
+
refreshTokenHash: row.refresh_token_hash,
|
|
247
|
+
previousRefreshTokenHash: row.previous_refresh_token_hash ?? undefined,
|
|
248
|
+
refreshedAt: row.refreshed_at ? toDate(row.refreshed_at) : undefined,
|
|
249
|
+
}
|
|
250
|
+
: undefined,
|
|
238
251
|
}
|
|
239
252
|
}
|
|
240
253
|
|
|
@@ -244,8 +257,7 @@ export function rowToAccessTokenRecord(row: PgAuthAccessTokenRow): AccessTokenRe
|
|
|
244
257
|
projectId: row.project_id,
|
|
245
258
|
name: row.name,
|
|
246
259
|
kind: row.kind,
|
|
247
|
-
|
|
248
|
-
subjectId: row.subject_id,
|
|
260
|
+
subject: { type: row.subject_type, id: row.subject_id },
|
|
249
261
|
tokenHash: row.token_hash,
|
|
250
262
|
groupIds: parseOptionalStringArray(row.group_ids),
|
|
251
263
|
createdByPrincipal: principalFromColumns(row),
|
|
@@ -332,8 +344,6 @@ export function rowToDeviceAuthorizationRecord(
|
|
|
332
344
|
deviceCodeHash: row.device_code_hash,
|
|
333
345
|
userCode: row.user_code,
|
|
334
346
|
clientName: row.client_name,
|
|
335
|
-
tokenName: row.token_name,
|
|
336
|
-
tokenExpiresAt: toDate(row.token_expires_at),
|
|
337
347
|
status: row.status,
|
|
338
348
|
approvedUserId: row.approved_user_id ?? undefined,
|
|
339
349
|
approvedSessionId: row.approved_session_id ?? undefined,
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AuthSessionAudience } from "@sixb/core"
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AuthSessionStore,
|
|
4
|
+
CreateAuthSessionInput,
|
|
5
|
+
RotateSessionRefreshTokenResult,
|
|
6
|
+
SessionRecord,
|
|
7
|
+
} from "@sixb/core/storage"
|
|
3
8
|
import { AuthStorageError } from "@sixb/core/storage"
|
|
4
9
|
import {
|
|
5
10
|
authLockKey,
|
|
@@ -85,11 +90,10 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
85
90
|
|
|
86
91
|
if (
|
|
87
92
|
!row ||
|
|
93
|
+
row.refresh_token_hash !== null ||
|
|
88
94
|
row.audience !== params.audience ||
|
|
89
95
|
row.token_hash !== params.tokenHash ||
|
|
90
|
-
row.
|
|
91
|
-
new Date(row.expires_at) <= params.now ||
|
|
92
|
-
(row.absolute_expires_at !== null && new Date(row.absolute_expires_at) <= params.now)
|
|
96
|
+
!isLiveSessionRow(row, params.now)
|
|
93
97
|
) {
|
|
94
98
|
return null
|
|
95
99
|
}
|
|
@@ -97,6 +101,71 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
97
101
|
return rowToSessionRecord(row)
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
async findValidByAccessTokenHash(params: {
|
|
105
|
+
readonly projectId: string
|
|
106
|
+
readonly id: string
|
|
107
|
+
readonly tokenHash: string
|
|
108
|
+
readonly now: Date
|
|
109
|
+
}): Promise<SessionRecord | null> {
|
|
110
|
+
const row = await getSessionRowById(this.sql, params)
|
|
111
|
+
if (
|
|
112
|
+
!row ||
|
|
113
|
+
row.access_expires_at === null ||
|
|
114
|
+
row.token_hash !== params.tokenHash ||
|
|
115
|
+
new Date(row.access_expires_at) <= params.now ||
|
|
116
|
+
!isLiveSessionRow(row, params.now)
|
|
117
|
+
) {
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return rowToSessionRecord(row)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async rotateRefreshToken(
|
|
125
|
+
params: Parameters<AuthSessionStore["rotateRefreshToken"]>[0]
|
|
126
|
+
): Promise<RotateSessionRefreshTokenResult> {
|
|
127
|
+
return runPgTransaction(this.sql, async (tx): Promise<RotateSessionRefreshTokenResult> => {
|
|
128
|
+
const row = await getSessionRowById(tx, params, { forUpdate: true })
|
|
129
|
+
if (!row?.refresh_token_hash || !isLiveSessionRow(row, params.now)) {
|
|
130
|
+
return { status: "invalid" }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const replacedRecently =
|
|
134
|
+
row.previous_refresh_token_hash === params.refreshTokenHash &&
|
|
135
|
+
row.refreshed_at !== null &&
|
|
136
|
+
params.now.getTime() - new Date(row.refreshed_at).getTime() <= params.reuseGraceMs
|
|
137
|
+
if (row.refresh_token_hash !== params.refreshTokenHash && !replacedRecently) {
|
|
138
|
+
if (row.previous_refresh_token_hash !== params.refreshTokenHash) {
|
|
139
|
+
return { status: "invalid" }
|
|
140
|
+
}
|
|
141
|
+
await tx`
|
|
142
|
+
UPDATE auth_sessions SET revoked_at = ${params.now}
|
|
143
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
144
|
+
`
|
|
145
|
+
return { status: "reused" }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const [rotated] = await tx<PgAuthSessionRow[]>`
|
|
149
|
+
UPDATE auth_sessions
|
|
150
|
+
SET token_hash = ${params.next.tokenHash},
|
|
151
|
+
access_expires_at = ${params.next.accessExpiresAt},
|
|
152
|
+
previous_refresh_token_hash = refresh_token_hash,
|
|
153
|
+
refresh_token_hash = ${params.next.refreshTokenHash},
|
|
154
|
+
refreshed_at = ${params.now},
|
|
155
|
+
last_seen_at = ${params.now},
|
|
156
|
+
expires_at = GREATEST(
|
|
157
|
+
expires_at,
|
|
158
|
+
LEAST(${params.next.expiresAt}, COALESCE(absolute_expires_at, ${params.next.expiresAt}))
|
|
159
|
+
)
|
|
160
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
161
|
+
RETURNING *
|
|
162
|
+
`
|
|
163
|
+
return rotated
|
|
164
|
+
? { status: "rotated", session: rowToSessionRecord(rotated) }
|
|
165
|
+
: { status: "invalid" }
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
100
169
|
async renewIfValid(params: {
|
|
101
170
|
readonly projectId: string
|
|
102
171
|
readonly id: string
|
|
@@ -119,6 +188,7 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
119
188
|
AND id = ${params.id}
|
|
120
189
|
AND audience = ${params.audience}
|
|
121
190
|
AND token_hash = ${params.tokenHash}
|
|
191
|
+
AND refresh_token_hash IS NULL
|
|
122
192
|
AND revoked_at IS NULL
|
|
123
193
|
AND expires_at > ${params.now}
|
|
124
194
|
AND (absolute_expires_at IS NULL OR absolute_expires_at > ${params.now})
|
|
@@ -191,3 +261,11 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
191
261
|
})
|
|
192
262
|
}
|
|
193
263
|
}
|
|
264
|
+
|
|
265
|
+
function isLiveSessionRow(row: PgAuthSessionRow, now: Date): boolean {
|
|
266
|
+
return (
|
|
267
|
+
row.revoked_at === null &&
|
|
268
|
+
new Date(row.expires_at) > now &&
|
|
269
|
+
(row.absolute_expires_at === null || new Date(row.absolute_expires_at) > now)
|
|
270
|
+
)
|
|
271
|
+
}
|
|
@@ -487,7 +487,10 @@ export async function createSession(
|
|
|
487
487
|
expires_at,
|
|
488
488
|
absolute_expires_at,
|
|
489
489
|
user_agent,
|
|
490
|
-
ip_address
|
|
490
|
+
ip_address,
|
|
491
|
+
client_name,
|
|
492
|
+
access_expires_at,
|
|
493
|
+
refresh_token_hash
|
|
491
494
|
) VALUES (
|
|
492
495
|
${projectId},
|
|
493
496
|
${id},
|
|
@@ -499,7 +502,10 @@ export async function createSession(
|
|
|
499
502
|
${input.expiresAt},
|
|
500
503
|
${input.absoluteExpiresAt ?? null},
|
|
501
504
|
${input.userAgent ?? null},
|
|
502
|
-
${input.ipAddress ?? null}
|
|
505
|
+
${input.ipAddress ?? null},
|
|
506
|
+
${input.bearer ? assertNonEmpty(input.bearer.clientName, "Session client name") : null},
|
|
507
|
+
${input.bearer?.accessExpiresAt ?? null},
|
|
508
|
+
${input.bearer ? assertNonEmpty(input.bearer.refreshTokenHash, "Refresh token hash") : null}
|
|
503
509
|
)
|
|
504
510
|
RETURNING *
|
|
505
511
|
`
|