@schemavaults/auth-common 0.23.0 → 0.25.0
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/oidc/index.d.ts +3 -0
- package/dist/oidc/index.js +2 -0
- package/dist/oidc/index.js.map +1 -1
- package/dist/oidc/profile-claims.d.ts +34 -0
- package/dist/oidc/profile-claims.js +45 -0
- package/dist/oidc/profile-claims.js.map +1 -0
- package/dist/oidc/sub-claim.d.ts +21 -0
- package/dist/oidc/sub-claim.js +57 -0
- package/dist/oidc/sub-claim.js.map +1 -0
- package/dist/request_tokens_result.d.ts +35 -0
- package/dist/user_data/index.d.ts +1 -0
- package/dist/user_data/index.js +1 -0
- package/dist/user_data/index.js.map +1 -1
- package/dist/user_data/user_data.d.ts +25 -0
- package/dist/user_data/user_data.js +10 -0
- package/dist/user_data/user_data.js.map +1 -1
- package/dist/user_data/user_profile.d.ts +119 -0
- package/dist/user_data/user_profile.js +79 -0
- package/dist/user_data/user_profile.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { ERROR_MESSAGE_CATALOG, isValidErrorId, } from "./auth-error-message-catalog";
|
|
2
2
|
export type { SchemaVaultsAuthErrorId } from "./auth-error-message-catalog";
|
|
3
3
|
export { AppAlreadyConnectedToApiServerError, isAppAlreadyConnectedToApiServerError, } from "./app-to-api-connection-errors";
|
|
4
|
-
export { userDataSchema, type UserData } from "./user_data";
|
|
4
|
+
export { userDataSchema, type UserData, USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, MAX_USER_NAME_PART_LENGTH, USERNAME_REGEX, usernameFormatSchema, userNamePartSchema, userDisplayNameSchema, userProfileNamesSchema, updateUserProfileRequestSchema, userProfileResponseSchema, type Username, type UserProfileNames, type UpdateUserProfileRequest, type UserProfileResponse, } from "./user_data";
|
|
5
5
|
export * from "./credentials";
|
|
6
6
|
export type * from "./credentials";
|
|
7
7
|
export * from "./token-data";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ERROR_MESSAGE_CATALOG, isValidErrorId, } from "./auth-error-message-catalog";
|
|
2
2
|
export { AppAlreadyConnectedToApiServerError, isAppAlreadyConnectedToApiServerError, } from "./app-to-api-connection-errors";
|
|
3
|
-
export { userDataSchema } from "./user_data";
|
|
3
|
+
export { userDataSchema, USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, MAX_USER_NAME_PART_LENGTH, USERNAME_REGEX, usernameFormatSchema, userNamePartSchema, userDisplayNameSchema, userProfileNamesSchema, updateUserProfileRequestSchema, userProfileResponseSchema, } from "./user_data";
|
|
4
4
|
export * from "./credentials";
|
|
5
5
|
// Shapes of tokens
|
|
6
6
|
export * from "./token-data";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,mCAAmC,EACnC,qCAAqC,GACtC,MAAM,gCAAgC,CAAC;AAExC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,mCAAmC,EACnC,qCAAqC,GACtC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,cAAc,EAEd,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,GAK1B,MAAM,aAAa,CAAC;AAErB,cAAc,eAAe,CAAC;AAG9B,mBAAmB;AACnB,cAAc,cAAc,CAAC;AAM7B,cAAc,cAAc,CAAC;AAG7B,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,wBAAwB,EACxB,qCAAqC,EACrC,mCAAmC,EACnC,+BAA+B,EAC/B,wCAAwC,EACxC,wBAAwB,EACxB,uBAAuB,GAOxB,MAAM,uBAAuB,CAAC;AAE/B,cAAc,OAAO,CAAC;AACtB,OAAO,EACL,+BAA+B,EAE/B,6CAA6C,GAE9C,MAAM,yBAAyB,CAAC;AAEjC,cAAc,mCAAmC,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,gBAAgB,EAChB,gCAAgC,EAChC,yCAAyC,EACzC,kCAAkC,EAClC,2CAA2C,EAC3C,0BAA0B,EAC1B,8BAA8B,EAC9B,8BAA8B,EAC9B,sBAAsB,EACtB,sBAAsB,EACtB,iCAAiC,EACjC,kCAAkC,EAClC,4BAA4B,EAC5B,+BAA+B,EAC/B,oCAAoC,EACpC,qCAAqC,EACrC,uCAAuC,EACvC,wCAAwC,GACzC,MAAM,iBAAiB,CAAC;AAezB,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AAEtG,OAAO,EAAE,kCAAkC,EAAE,MAAM,0CAA0C,CAAC;AAE9F,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,qCAAqC,EACrC,gCAAgC,GACjC,MAAM,mCAAmC,CAAC"}
|
package/dist/oidc/index.d.ts
CHANGED
|
@@ -2,3 +2,6 @@ export { OIDC_OPENID_SCOPE, OIDC_SUPPORTED_SCOPES, DEFAULT_AUTH_SCOPE, OIDC_SCOP
|
|
|
2
2
|
export type { OidcSupportedScope, OidcScope, ParsedOidcScopes, } from "./scope";
|
|
3
3
|
export { oidcNonceSchema, OIDC_NONCE_VSCHAR_REGEX, parseOidcNonce, OidcNonceValidationError, } from "./nonce";
|
|
4
4
|
export type { OidcNonce } from "./nonce";
|
|
5
|
+
export { OIDC_SUB_CLAIM_DELIMITER, formatOidcSubClaim, parseOidcSubClaim, } from "./sub-claim";
|
|
6
|
+
export { buildOidcProfileClaims } from "./profile-claims";
|
|
7
|
+
export type { OidcProfileClaims, OidcProfileClaimsSource, } from "./profile-claims";
|
package/dist/oidc/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { OIDC_OPENID_SCOPE, OIDC_SUPPORTED_SCOPES, DEFAULT_AUTH_SCOPE, OIDC_SCOPE_REGEX, oidcScopeSchema, parseAndGrantScopes, serializeOidcScopes, } from "./scope";
|
|
2
2
|
export { oidcNonceSchema, OIDC_NONCE_VSCHAR_REGEX, parseOidcNonce, OidcNonceValidationError, } from "./nonce";
|
|
3
|
+
export { OIDC_SUB_CLAIM_DELIMITER, formatOidcSubClaim, parseOidcSubClaim, } from "./sub-claim";
|
|
4
|
+
export { buildOidcProfileClaims } from "./profile-claims";
|
|
3
5
|
//# sourceMappingURL=index.js.map
|
package/dist/oidc/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oidc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAOjB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,cAAc,EACd,wBAAwB,GACzB,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oidc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAOjB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,cAAc,EACd,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC Core §5.1 standard claims gated by the `profile` scope, built
|
|
3
|
+
* from the user's stored profile name fields. Shared by every surface
|
|
4
|
+
* that emits profile claims — the id_token (`generateIdToken` in
|
|
5
|
+
* @schemavaults/jwt) and GET/POST /api/oidc/userinfo — so the two
|
|
6
|
+
* always agree for the same user.
|
|
7
|
+
*/
|
|
8
|
+
/** The profile name fields the claims are derived from (all optional). */
|
|
9
|
+
export interface OidcProfileClaimsSource {
|
|
10
|
+
username?: string;
|
|
11
|
+
first_name?: string;
|
|
12
|
+
middle_name?: string;
|
|
13
|
+
last_name?: string;
|
|
14
|
+
display_name?: string;
|
|
15
|
+
}
|
|
16
|
+
/** The OIDC Core §5.1 claims emitted under the `profile` scope. */
|
|
17
|
+
export interface OidcProfileClaims {
|
|
18
|
+
/**
|
|
19
|
+
* The user's full name in displayable form: the public display name
|
|
20
|
+
* when set, otherwise the joined first/middle/last name parts.
|
|
21
|
+
*/
|
|
22
|
+
name?: string;
|
|
23
|
+
given_name?: string;
|
|
24
|
+
middle_name?: string;
|
|
25
|
+
family_name?: string;
|
|
26
|
+
preferred_username?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Builds the `profile`-scoped claim set from a user's stored name
|
|
30
|
+
* fields. Claims without a stored value are omitted entirely (OIDC Core
|
|
31
|
+
* §5.3.2 — absent, not null/empty). Callers are responsible for only
|
|
32
|
+
* emitting the result when the `profile` scope was actually granted.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildOidcProfileClaims(user: OidcProfileClaimsSource): OidcProfileClaims;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC Core §5.1 standard claims gated by the `profile` scope, built
|
|
3
|
+
* from the user's stored profile name fields. Shared by every surface
|
|
4
|
+
* that emits profile claims — the id_token (`generateIdToken` in
|
|
5
|
+
* @schemavaults/jwt) and GET/POST /api/oidc/userinfo — so the two
|
|
6
|
+
* always agree for the same user.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Builds the `profile`-scoped claim set from a user's stored name
|
|
10
|
+
* fields. Claims without a stored value are omitted entirely (OIDC Core
|
|
11
|
+
* §5.3.2 — absent, not null/empty). Callers are responsible for only
|
|
12
|
+
* emitting the result when the `profile` scope was actually granted.
|
|
13
|
+
*/
|
|
14
|
+
export function buildOidcProfileClaims(user) {
|
|
15
|
+
const claims = {};
|
|
16
|
+
const joined_name_parts = [
|
|
17
|
+
user.first_name,
|
|
18
|
+
user.middle_name,
|
|
19
|
+
user.last_name,
|
|
20
|
+
]
|
|
21
|
+
.filter((part) => typeof part === "string" && part.length > 0)
|
|
22
|
+
.join(" ");
|
|
23
|
+
const full_name = user.display_name && user.display_name.length > 0
|
|
24
|
+
? user.display_name
|
|
25
|
+
: joined_name_parts.length > 0
|
|
26
|
+
? joined_name_parts
|
|
27
|
+
: undefined;
|
|
28
|
+
if (full_name) {
|
|
29
|
+
claims.name = full_name;
|
|
30
|
+
}
|
|
31
|
+
if (user.first_name) {
|
|
32
|
+
claims.given_name = user.first_name;
|
|
33
|
+
}
|
|
34
|
+
if (user.middle_name) {
|
|
35
|
+
claims.middle_name = user.middle_name;
|
|
36
|
+
}
|
|
37
|
+
if (user.last_name) {
|
|
38
|
+
claims.family_name = user.last_name;
|
|
39
|
+
}
|
|
40
|
+
if (user.username) {
|
|
41
|
+
claims.preferred_username = user.username;
|
|
42
|
+
}
|
|
43
|
+
return claims;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=profile-claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-claims.js","sourceRoot":"","sources":["../../src/oidc/profile-claims.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwBH;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA6B;IAE7B,MAAM,MAAM,GAAsB,EAAE,CAAC;IAErC,MAAM,iBAAiB,GAAW;QAChC,IAAI,CAAC,UAAU;QACf,IAAI,CAAC,WAAW;QAChB,IAAI,CAAC,SAAS;KACf;SACE,MAAM,CACL,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CACtE;SACA,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,SAAS,GACb,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC,YAAY;QACnB,CAAC,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC;YAC5B,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,SAAS,CAAC;IAElB,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;IAC1B,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACtC,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACxC,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;IACtC,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type AppId } from "@schemavaults/app-definitions";
|
|
2
|
+
export declare const OIDC_SUB_CLAIM_DELIMITER: "|";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the OIDC-facing `sub` claim for a platform user:
|
|
5
|
+
* `<auth_server_app_id>|<uid>`. The auth server app id is stable per
|
|
6
|
+
* deployment, so the resulting subject is stable for the lifetime of
|
|
7
|
+
* the user (OIDC Core §2: `sub` must be locally unique and never
|
|
8
|
+
* reassigned within the issuer).
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatOidcSubClaim(auth_server_app_id: AppId | string, uid: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Splits an OIDC-facing `sub` claim back into the issuing deployment's
|
|
13
|
+
* app id and the platform user id. Returns `null` for values not in the
|
|
14
|
+
* `<app_id>|<uid>` shape (e.g. subjects issued by other providers).
|
|
15
|
+
* Only the FIRST delimiter splits — the uid keeps any later characters
|
|
16
|
+
* verbatim.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseOidcSubClaim(sub: string): {
|
|
19
|
+
auth_server_app_id: AppId;
|
|
20
|
+
uid: string;
|
|
21
|
+
} | null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { appIdSchema } from "@schemavaults/app-definitions";
|
|
2
|
+
// The OIDC-facing `sub` claim namespaces the platform user id with the
|
|
3
|
+
// deployment's own app id (SCHEMAVAULTS_AUTH_SERVER_APP_ID), Auth0-style:
|
|
4
|
+
// `<auth_server_app_id>|<uid>` (e.g. "schemavaults-auth|4f7c…"). The
|
|
5
|
+
// prefix marks which auth deployment a subject came from, so RPs that
|
|
6
|
+
// aggregate identities from several issuers / white-label deployments
|
|
7
|
+
// can't collide or confuse them. It applies ONLY at the OIDC boundary —
|
|
8
|
+
// the id_token, /api/oidc/userinfo, and RFC 7662 introspection, which
|
|
9
|
+
// OIDC Core §5.3.2 requires to agree exactly — never inside the
|
|
10
|
+
// platform's own encrypted access/refresh token payloads, whose
|
|
11
|
+
// `sub === uid` invariant (payload_data.ts) resource servers rely on.
|
|
12
|
+
// The app id charset ([a-z0-9_-]) can never contain the delimiter, so
|
|
13
|
+
// the encoding is unambiguous.
|
|
14
|
+
export const OIDC_SUB_CLAIM_DELIMITER = "|";
|
|
15
|
+
/**
|
|
16
|
+
* Builds the OIDC-facing `sub` claim for a platform user:
|
|
17
|
+
* `<auth_server_app_id>|<uid>`. The auth server app id is stable per
|
|
18
|
+
* deployment, so the resulting subject is stable for the lifetime of
|
|
19
|
+
* the user (OIDC Core §2: `sub` must be locally unique and never
|
|
20
|
+
* reassigned within the issuer).
|
|
21
|
+
*/
|
|
22
|
+
export function formatOidcSubClaim(auth_server_app_id, uid) {
|
|
23
|
+
const app_id = appIdSchema.safeParse(auth_server_app_id);
|
|
24
|
+
if (!app_id.success) {
|
|
25
|
+
throw new TypeError("Invalid auth server app id for OIDC 'sub' claim prefix!", { cause: app_id.error });
|
|
26
|
+
}
|
|
27
|
+
if (typeof uid !== "string" || uid.length === 0) {
|
|
28
|
+
throw new TypeError("A user id is required to build an OIDC 'sub' claim!");
|
|
29
|
+
}
|
|
30
|
+
return `${app_id.data}${OIDC_SUB_CLAIM_DELIMITER}${uid}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Splits an OIDC-facing `sub` claim back into the issuing deployment's
|
|
34
|
+
* app id and the platform user id. Returns `null` for values not in the
|
|
35
|
+
* `<app_id>|<uid>` shape (e.g. subjects issued by other providers).
|
|
36
|
+
* Only the FIRST delimiter splits — the uid keeps any later characters
|
|
37
|
+
* verbatim.
|
|
38
|
+
*/
|
|
39
|
+
export function parseOidcSubClaim(sub) {
|
|
40
|
+
if (typeof sub !== "string") {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const delimiter_index = sub.indexOf(OIDC_SUB_CLAIM_DELIMITER);
|
|
44
|
+
if (delimiter_index <= 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const app_id = appIdSchema.safeParse(sub.slice(0, delimiter_index));
|
|
48
|
+
if (!app_id.success) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const uid = sub.slice(delimiter_index + OIDC_SUB_CLAIM_DELIMITER.length);
|
|
52
|
+
if (uid.length === 0) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return { auth_server_app_id: app_id.data, uid };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=sub-claim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sub-claim.js","sourceRoot":"","sources":["../../src/oidc/sub-claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAc,MAAM,+BAA+B,CAAC;AAExE,uEAAuE;AACvE,0EAA0E;AAC1E,qEAAqE;AACrE,sEAAsE;AACtE,sEAAsE;AACtE,wEAAwE;AACxE,sEAAsE;AACtE,gEAAgE;AAChE,gEAAgE;AAChE,sEAAsE;AACtE,sEAAsE;AACtE,+BAA+B;AAE/B,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAY,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,kBAAkC,EAClC,GAAW;IAEX,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CACjB,yDAAyD,EACzD,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CACxB,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,GAAG,MAAM,CAAC,IAAI,GAAG,wBAAwB,GAAG,GAAG,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAW;IAEX,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9D,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,eAAe,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,kBAAkB,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -371,6 +371,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
371
371
|
}>>;
|
|
372
372
|
userData: zod.ZodOptional<zod.ZodEffects<zod.ZodObject<{
|
|
373
373
|
uid: zod.ZodString;
|
|
374
|
+
username: zod.ZodOptional<zod.ZodString>;
|
|
375
|
+
first_name: zod.ZodOptional<zod.ZodString>;
|
|
376
|
+
middle_name: zod.ZodOptional<zod.ZodString>;
|
|
377
|
+
last_name: zod.ZodOptional<zod.ZodString>;
|
|
378
|
+
display_name: zod.ZodOptional<zod.ZodString>;
|
|
374
379
|
sub: zod.ZodString;
|
|
375
380
|
email: zod.ZodString;
|
|
376
381
|
email_verified: zod.ZodOptional<zod.ZodBoolean>;
|
|
@@ -385,6 +390,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
385
390
|
sub: string;
|
|
386
391
|
email: string;
|
|
387
392
|
created_at: number;
|
|
393
|
+
username?: string | undefined;
|
|
394
|
+
first_name?: string | undefined;
|
|
395
|
+
middle_name?: string | undefined;
|
|
396
|
+
last_name?: string | undefined;
|
|
397
|
+
display_name?: string | undefined;
|
|
388
398
|
email_verified?: boolean | undefined;
|
|
389
399
|
admin?: boolean | undefined;
|
|
390
400
|
phone_number?: string | undefined;
|
|
@@ -396,6 +406,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
396
406
|
sub: string;
|
|
397
407
|
email: string;
|
|
398
408
|
created_at: number;
|
|
409
|
+
username?: string | undefined;
|
|
410
|
+
first_name?: string | undefined;
|
|
411
|
+
middle_name?: string | undefined;
|
|
412
|
+
last_name?: string | undefined;
|
|
413
|
+
display_name?: string | undefined;
|
|
399
414
|
email_verified?: boolean | undefined;
|
|
400
415
|
admin?: boolean | undefined;
|
|
401
416
|
phone_number?: string | undefined;
|
|
@@ -407,6 +422,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
407
422
|
sub: string;
|
|
408
423
|
email: string;
|
|
409
424
|
created_at: number;
|
|
425
|
+
username?: string | undefined;
|
|
426
|
+
first_name?: string | undefined;
|
|
427
|
+
middle_name?: string | undefined;
|
|
428
|
+
last_name?: string | undefined;
|
|
429
|
+
display_name?: string | undefined;
|
|
410
430
|
email_verified?: boolean | undefined;
|
|
411
431
|
admin?: boolean | undefined;
|
|
412
432
|
phone_number?: string | undefined;
|
|
@@ -418,6 +438,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
418
438
|
sub: string;
|
|
419
439
|
email: string;
|
|
420
440
|
created_at: number;
|
|
441
|
+
username?: string | undefined;
|
|
442
|
+
first_name?: string | undefined;
|
|
443
|
+
middle_name?: string | undefined;
|
|
444
|
+
last_name?: string | undefined;
|
|
445
|
+
display_name?: string | undefined;
|
|
421
446
|
email_verified?: boolean | undefined;
|
|
422
447
|
admin?: boolean | undefined;
|
|
423
448
|
phone_number?: string | undefined;
|
|
@@ -458,6 +483,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
458
483
|
sub: string;
|
|
459
484
|
email: string;
|
|
460
485
|
created_at: number;
|
|
486
|
+
username?: string | undefined;
|
|
487
|
+
first_name?: string | undefined;
|
|
488
|
+
middle_name?: string | undefined;
|
|
489
|
+
last_name?: string | undefined;
|
|
490
|
+
display_name?: string | undefined;
|
|
461
491
|
email_verified?: boolean | undefined;
|
|
462
492
|
admin?: boolean | undefined;
|
|
463
493
|
phone_number?: string | undefined;
|
|
@@ -498,6 +528,11 @@ export declare function createRequestTokensResultSchema(z: typeof zod, environme
|
|
|
498
528
|
sub: string;
|
|
499
529
|
email: string;
|
|
500
530
|
created_at: number;
|
|
531
|
+
username?: string | undefined;
|
|
532
|
+
first_name?: string | undefined;
|
|
533
|
+
middle_name?: string | undefined;
|
|
534
|
+
last_name?: string | undefined;
|
|
535
|
+
display_name?: string | undefined;
|
|
501
536
|
email_verified?: boolean | undefined;
|
|
502
537
|
admin?: boolean | undefined;
|
|
503
538
|
phone_number?: string | undefined;
|
|
@@ -1 +1,2 @@
|
|
|
1
1
|
export { userDataSchema, type UserData } from './user_data';
|
|
2
|
+
export { USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, MAX_USER_NAME_PART_LENGTH, USERNAME_REGEX, usernameFormatSchema, userNamePartSchema, userDisplayNameSchema, userProfileNamesSchema, updateUserProfileRequestSchema, userProfileResponseSchema, type Username, type UserProfileNames, type UpdateUserProfileRequest, type UserProfileResponse, } from './user_profile';
|
package/dist/user_data/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { userDataSchema } from './user_data';
|
|
2
|
+
export { USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, MAX_USER_NAME_PART_LENGTH, USERNAME_REGEX, usernameFormatSchema, userNamePartSchema, userDisplayNameSchema, userProfileNamesSchema, updateUserProfileRequestSchema, userProfileResponseSchema, } from './user_profile';
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/user_data/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EAEf,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/user_data/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EAEf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,GAK1B,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const userDataSchema: z.ZodEffects<z.ZodObject<{
|
|
3
3
|
uid: z.ZodString;
|
|
4
|
+
username: z.ZodOptional<z.ZodString>;
|
|
5
|
+
first_name: z.ZodOptional<z.ZodString>;
|
|
6
|
+
middle_name: z.ZodOptional<z.ZodString>;
|
|
7
|
+
last_name: z.ZodOptional<z.ZodString>;
|
|
8
|
+
display_name: z.ZodOptional<z.ZodString>;
|
|
4
9
|
sub: z.ZodString;
|
|
5
10
|
email: z.ZodString;
|
|
6
11
|
email_verified: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -15,6 +20,11 @@ export declare const userDataSchema: z.ZodEffects<z.ZodObject<{
|
|
|
15
20
|
sub: string;
|
|
16
21
|
email: string;
|
|
17
22
|
created_at: number;
|
|
23
|
+
username?: string | undefined;
|
|
24
|
+
first_name?: string | undefined;
|
|
25
|
+
middle_name?: string | undefined;
|
|
26
|
+
last_name?: string | undefined;
|
|
27
|
+
display_name?: string | undefined;
|
|
18
28
|
email_verified?: boolean | undefined;
|
|
19
29
|
admin?: boolean | undefined;
|
|
20
30
|
phone_number?: string | undefined;
|
|
@@ -26,6 +36,11 @@ export declare const userDataSchema: z.ZodEffects<z.ZodObject<{
|
|
|
26
36
|
sub: string;
|
|
27
37
|
email: string;
|
|
28
38
|
created_at: number;
|
|
39
|
+
username?: string | undefined;
|
|
40
|
+
first_name?: string | undefined;
|
|
41
|
+
middle_name?: string | undefined;
|
|
42
|
+
last_name?: string | undefined;
|
|
43
|
+
display_name?: string | undefined;
|
|
29
44
|
email_verified?: boolean | undefined;
|
|
30
45
|
admin?: boolean | undefined;
|
|
31
46
|
phone_number?: string | undefined;
|
|
@@ -37,6 +52,11 @@ export declare const userDataSchema: z.ZodEffects<z.ZodObject<{
|
|
|
37
52
|
sub: string;
|
|
38
53
|
email: string;
|
|
39
54
|
created_at: number;
|
|
55
|
+
username?: string | undefined;
|
|
56
|
+
first_name?: string | undefined;
|
|
57
|
+
middle_name?: string | undefined;
|
|
58
|
+
last_name?: string | undefined;
|
|
59
|
+
display_name?: string | undefined;
|
|
40
60
|
email_verified?: boolean | undefined;
|
|
41
61
|
admin?: boolean | undefined;
|
|
42
62
|
phone_number?: string | undefined;
|
|
@@ -48,6 +68,11 @@ export declare const userDataSchema: z.ZodEffects<z.ZodObject<{
|
|
|
48
68
|
sub: string;
|
|
49
69
|
email: string;
|
|
50
70
|
created_at: number;
|
|
71
|
+
username?: string | undefined;
|
|
72
|
+
first_name?: string | undefined;
|
|
73
|
+
middle_name?: string | undefined;
|
|
74
|
+
last_name?: string | undefined;
|
|
75
|
+
display_name?: string | undefined;
|
|
51
76
|
email_verified?: boolean | undefined;
|
|
52
77
|
admin?: boolean | undefined;
|
|
53
78
|
phone_number?: string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { inviteCodeFormatSchema } from "../invite-code/invite-code-format";
|
|
2
|
+
import { usernameFormatSchema, userNamePartSchema, userDisplayNameSchema, } from "../user_data/user_profile";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
const _baseUserDataSchema = z
|
|
4
5
|
.object({
|
|
@@ -8,6 +9,15 @@ const _baseUserDataSchema = z
|
|
|
8
9
|
// Email
|
|
9
10
|
email: z.string().email(),
|
|
10
11
|
email_verified: z.boolean().optional(),
|
|
12
|
+
// Profile names (user-editable; absent for accounts that never set
|
|
13
|
+
// them). Only present when the UserData was built from the database
|
|
14
|
+
// row (loadUserData) — UserData derived from a decoded token payload
|
|
15
|
+
// does not carry them.
|
|
16
|
+
username: usernameFormatSchema.optional(),
|
|
17
|
+
first_name: userNamePartSchema.optional(),
|
|
18
|
+
middle_name: userNamePartSchema.optional(),
|
|
19
|
+
last_name: userNamePartSchema.optional(),
|
|
20
|
+
display_name: userDisplayNameSchema.optional(),
|
|
11
21
|
// Admin
|
|
12
22
|
admin: z.boolean().optional(),
|
|
13
23
|
// Phone
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_data.js","sourceRoot":"","sources":["../../src/user_data/user_data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,UAAU;IACV,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IACtB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,mBAAmB;IAE3C,QAAQ;IACR,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACzB,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEtC,QAAQ;IACR,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAE7B,QAAQ;IACR,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACnD,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEtC,4BAA4B;IAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEhC,qBAAqB;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAEvC,cAAc;IACd,WAAW,EAAE,sBAAsB,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,QAAQ,CAAC;IACR,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IACT,UAAU,EAAE,IAAI;CACjB,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IAChE,OAAO,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC;AAC/B,CAAC,EAAE,6BAA6B,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"user_data.js","sourceRoot":"","sources":["../../src/user_data/user_data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,UAAU;IACV,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IACtB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,mBAAmB;IAE3C,QAAQ;IACR,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACzB,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEtC,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,uBAAuB;IACvB,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACzC,UAAU,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IACzC,WAAW,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IACxC,YAAY,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IAE9C,QAAQ;IACR,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAE7B,QAAQ;IACR,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACnD,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEtC,4BAA4B;IAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAEhC,qBAAqB;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAEvC,cAAc;IACd,WAAW,EAAE,sBAAsB,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,QAAQ,CAAC;IACR,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IACT,UAAU,EAAE,IAAI;CACjB,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IAChE,OAAO,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC;AAC/B,CAAC,EAAE,6BAA6B,CAAC,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const USERNAME_MIN_LENGTH: number;
|
|
3
|
+
export declare const USERNAME_MAX_LENGTH: number;
|
|
4
|
+
/**
|
|
5
|
+
* Maximum length for each individual person-name part (first / middle /
|
|
6
|
+
* last) and for the public display name.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MAX_USER_NAME_PART_LENGTH: number;
|
|
9
|
+
/**
|
|
10
|
+
* Usernames are unique per deployment (case-insensitively — the database
|
|
11
|
+
* enforces uniqueness on LOWER(username), while the stored casing is
|
|
12
|
+
* preserved for display). Format: alphanumeric start and end with `.`,
|
|
13
|
+
* `_`, and `-` permitted in between. `@` is deliberately excluded so a
|
|
14
|
+
* username can never be confused with an email address, and `|` can
|
|
15
|
+
* never appear (the OIDC sub-claim delimiter).
|
|
16
|
+
*/
|
|
17
|
+
export declare const USERNAME_REGEX: RegExp;
|
|
18
|
+
export declare const usernameFormatSchema: z.ZodString;
|
|
19
|
+
export type Username = z.infer<typeof usernameFormatSchema>;
|
|
20
|
+
/** A single part of a user's personal name (first / middle / last). */
|
|
21
|
+
export declare const userNamePartSchema: z.ZodString;
|
|
22
|
+
/**
|
|
23
|
+
* The user's public display name. Shown to other users and exposed to
|
|
24
|
+
* OIDC relying parties as the `name` claim when the `profile` scope is
|
|
25
|
+
* granted.
|
|
26
|
+
*/
|
|
27
|
+
export declare const userDisplayNameSchema: z.ZodString;
|
|
28
|
+
/**
|
|
29
|
+
* The user-editable profile name fields stored on the USERS row. All
|
|
30
|
+
* fields are optional — accounts predating this feature (and accounts
|
|
31
|
+
* that never fill them in) simply have none set.
|
|
32
|
+
*/
|
|
33
|
+
export declare const userProfileNamesSchema: z.ZodObject<{
|
|
34
|
+
username: z.ZodOptional<z.ZodString>;
|
|
35
|
+
first_name: z.ZodOptional<z.ZodString>;
|
|
36
|
+
middle_name: z.ZodOptional<z.ZodString>;
|
|
37
|
+
last_name: z.ZodOptional<z.ZodString>;
|
|
38
|
+
display_name: z.ZodOptional<z.ZodString>;
|
|
39
|
+
}, "strict", z.ZodTypeAny, {
|
|
40
|
+
username?: string | undefined;
|
|
41
|
+
first_name?: string | undefined;
|
|
42
|
+
middle_name?: string | undefined;
|
|
43
|
+
last_name?: string | undefined;
|
|
44
|
+
display_name?: string | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
username?: string | undefined;
|
|
47
|
+
first_name?: string | undefined;
|
|
48
|
+
middle_name?: string | undefined;
|
|
49
|
+
last_name?: string | undefined;
|
|
50
|
+
display_name?: string | undefined;
|
|
51
|
+
}>;
|
|
52
|
+
export type UserProfileNames = z.infer<typeof userProfileNamesSchema>;
|
|
53
|
+
/**
|
|
54
|
+
* PUT /api/user/profile request body. Full-replacement semantics: every
|
|
55
|
+
* field the user wants to keep must be present; `null` (or an omitted
|
|
56
|
+
* field) clears the stored value.
|
|
57
|
+
*/
|
|
58
|
+
export declare const updateUserProfileRequestSchema: z.ZodObject<{
|
|
59
|
+
username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
first_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
middle_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
62
|
+
last_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
|
+
display_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
|
+
}, "strict", z.ZodTypeAny, {
|
|
65
|
+
username?: string | null | undefined;
|
|
66
|
+
first_name?: string | null | undefined;
|
|
67
|
+
middle_name?: string | null | undefined;
|
|
68
|
+
last_name?: string | null | undefined;
|
|
69
|
+
display_name?: string | null | undefined;
|
|
70
|
+
}, {
|
|
71
|
+
username?: string | null | undefined;
|
|
72
|
+
first_name?: string | null | undefined;
|
|
73
|
+
middle_name?: string | null | undefined;
|
|
74
|
+
last_name?: string | null | undefined;
|
|
75
|
+
display_name?: string | null | undefined;
|
|
76
|
+
}>;
|
|
77
|
+
export type UpdateUserProfileRequest = z.infer<typeof updateUserProfileRequestSchema>;
|
|
78
|
+
/** GET/PUT /api/user/profile success response body. */
|
|
79
|
+
export declare const userProfileResponseSchema: z.ZodObject<{
|
|
80
|
+
success: z.ZodLiteral<true>;
|
|
81
|
+
profile: z.ZodObject<{
|
|
82
|
+
username: z.ZodOptional<z.ZodString>;
|
|
83
|
+
first_name: z.ZodOptional<z.ZodString>;
|
|
84
|
+
middle_name: z.ZodOptional<z.ZodString>;
|
|
85
|
+
last_name: z.ZodOptional<z.ZodString>;
|
|
86
|
+
display_name: z.ZodOptional<z.ZodString>;
|
|
87
|
+
}, "strict", z.ZodTypeAny, {
|
|
88
|
+
username?: string | undefined;
|
|
89
|
+
first_name?: string | undefined;
|
|
90
|
+
middle_name?: string | undefined;
|
|
91
|
+
last_name?: string | undefined;
|
|
92
|
+
display_name?: string | undefined;
|
|
93
|
+
}, {
|
|
94
|
+
username?: string | undefined;
|
|
95
|
+
first_name?: string | undefined;
|
|
96
|
+
middle_name?: string | undefined;
|
|
97
|
+
last_name?: string | undefined;
|
|
98
|
+
display_name?: string | undefined;
|
|
99
|
+
}>;
|
|
100
|
+
}, "strict", z.ZodTypeAny, {
|
|
101
|
+
success: true;
|
|
102
|
+
profile: {
|
|
103
|
+
username?: string | undefined;
|
|
104
|
+
first_name?: string | undefined;
|
|
105
|
+
middle_name?: string | undefined;
|
|
106
|
+
last_name?: string | undefined;
|
|
107
|
+
display_name?: string | undefined;
|
|
108
|
+
};
|
|
109
|
+
}, {
|
|
110
|
+
success: true;
|
|
111
|
+
profile: {
|
|
112
|
+
username?: string | undefined;
|
|
113
|
+
first_name?: string | undefined;
|
|
114
|
+
middle_name?: string | undefined;
|
|
115
|
+
last_name?: string | undefined;
|
|
116
|
+
display_name?: string | undefined;
|
|
117
|
+
};
|
|
118
|
+
}>;
|
|
119
|
+
export type UserProfileResponse = z.infer<typeof userProfileResponseSchema>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const USERNAME_MIN_LENGTH = 3;
|
|
3
|
+
export const USERNAME_MAX_LENGTH = 32;
|
|
4
|
+
/**
|
|
5
|
+
* Maximum length for each individual person-name part (first / middle /
|
|
6
|
+
* last) and for the public display name.
|
|
7
|
+
*/
|
|
8
|
+
export const MAX_USER_NAME_PART_LENGTH = 64;
|
|
9
|
+
/**
|
|
10
|
+
* Usernames are unique per deployment (case-insensitively — the database
|
|
11
|
+
* enforces uniqueness on LOWER(username), while the stored casing is
|
|
12
|
+
* preserved for display). Format: alphanumeric start and end with `.`,
|
|
13
|
+
* `_`, and `-` permitted in between. `@` is deliberately excluded so a
|
|
14
|
+
* username can never be confused with an email address, and `|` can
|
|
15
|
+
* never appear (the OIDC sub-claim delimiter).
|
|
16
|
+
*/
|
|
17
|
+
export const USERNAME_REGEX = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
18
|
+
export const usernameFormatSchema = z
|
|
19
|
+
.string()
|
|
20
|
+
.min(USERNAME_MIN_LENGTH, `Username must be at least ${USERNAME_MIN_LENGTH} characters long!`)
|
|
21
|
+
.max(USERNAME_MAX_LENGTH, `Username may not be longer than ${USERNAME_MAX_LENGTH} characters!`)
|
|
22
|
+
.regex(USERNAME_REGEX, "Username may only contain letters, numbers, '.', '_', and '-', and must start and end with a letter or number.");
|
|
23
|
+
/**
|
|
24
|
+
* Rejects ASCII control characters (including CR/LF) that could pollute
|
|
25
|
+
* logs, headers, or rendered UI. All other unicode is permitted — names
|
|
26
|
+
* are human text.
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line no-control-regex -- rejecting control chars is the point
|
|
29
|
+
const NO_CONTROL_CHARS_REGEX = /^[^\u0000-\u001F\u007F]*$/;
|
|
30
|
+
const namePartSchema = z
|
|
31
|
+
.string()
|
|
32
|
+
.trim()
|
|
33
|
+
.min(1)
|
|
34
|
+
.max(MAX_USER_NAME_PART_LENGTH, `Name may not be longer than ${MAX_USER_NAME_PART_LENGTH} characters!`)
|
|
35
|
+
.regex(NO_CONTROL_CHARS_REGEX, "Name may not contain control characters!");
|
|
36
|
+
/** A single part of a user's personal name (first / middle / last). */
|
|
37
|
+
export const userNamePartSchema = namePartSchema;
|
|
38
|
+
/**
|
|
39
|
+
* The user's public display name. Shown to other users and exposed to
|
|
40
|
+
* OIDC relying parties as the `name` claim when the `profile` scope is
|
|
41
|
+
* granted.
|
|
42
|
+
*/
|
|
43
|
+
export const userDisplayNameSchema = namePartSchema;
|
|
44
|
+
/**
|
|
45
|
+
* The user-editable profile name fields stored on the USERS row. All
|
|
46
|
+
* fields are optional — accounts predating this feature (and accounts
|
|
47
|
+
* that never fill them in) simply have none set.
|
|
48
|
+
*/
|
|
49
|
+
export const userProfileNamesSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
username: usernameFormatSchema.optional(),
|
|
52
|
+
first_name: userNamePartSchema.optional(),
|
|
53
|
+
middle_name: userNamePartSchema.optional(),
|
|
54
|
+
last_name: userNamePartSchema.optional(),
|
|
55
|
+
display_name: userDisplayNameSchema.optional(),
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
/**
|
|
59
|
+
* PUT /api/user/profile request body. Full-replacement semantics: every
|
|
60
|
+
* field the user wants to keep must be present; `null` (or an omitted
|
|
61
|
+
* field) clears the stored value.
|
|
62
|
+
*/
|
|
63
|
+
export const updateUserProfileRequestSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
username: usernameFormatSchema.nullable().optional(),
|
|
66
|
+
first_name: userNamePartSchema.nullable().optional(),
|
|
67
|
+
middle_name: userNamePartSchema.nullable().optional(),
|
|
68
|
+
last_name: userNamePartSchema.nullable().optional(),
|
|
69
|
+
display_name: userDisplayNameSchema.nullable().optional(),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
/** GET/PUT /api/user/profile success response body. */
|
|
73
|
+
export const userProfileResponseSchema = z
|
|
74
|
+
.object({
|
|
75
|
+
success: z.literal(true),
|
|
76
|
+
profile: userProfileNamesSchema,
|
|
77
|
+
})
|
|
78
|
+
.strict();
|
|
79
|
+
//# sourceMappingURL=user_profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user_profile.js","sourceRoot":"","sources":["../../src/user_data/user_profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAW,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAW,EAAE,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAW,EAAE,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,8CAA8C,CAAC;AAEjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,EAAE;KACR,GAAG,CACF,mBAAmB,EACnB,6BAA6B,mBAAmB,mBAAmB,CACpE;KACA,GAAG,CACF,mBAAmB,EACnB,mCAAmC,mBAAmB,cAAc,CACrE;KACA,KAAK,CACJ,cAAc,EACd,gHAAgH,CACjH,CAAC;AAIJ;;;;GAIG;AACH,oFAAoF;AACpF,MAAM,sBAAsB,GAAW,2BAA2B,CAAC;AAEnE,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CACF,yBAAyB,EACzB,+BAA+B,yBAAyB,cAAc,CACvE;KACA,KAAK,CAAC,sBAAsB,EAAE,0CAA0C,CAAC,CAAC;AAE7E,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC;KACpC,MAAM,CAAC;IACN,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACzC,UAAU,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IACzC,WAAW,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IACxC,YAAY,EAAE,qBAAqB,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,MAAM,EAAE,CAAC;AAIZ;;;;GAIG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC;KAC5C,MAAM,CAAC;IACN,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACpD,UAAU,EAAE,kBAAkB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACpD,WAAW,EAAE,kBAAkB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrD,SAAS,EAAE,kBAAkB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACnD,YAAY,EAAE,qBAAqB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC1D,CAAC;KACD,MAAM,EAAE,CAAC;AAMZ,uDAAuD;AACvD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC;KACvC,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACxB,OAAO,EAAE,sBAAsB;CAChC,CAAC;KACD,MAAM,EAAE,CAAC"}
|