@authyon/server 0.2.0-beta.20 → 0.2.0-beta.22
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/README.md +541 -473
- package/dist/{authorization-DfFCoDQ6.d.ts → authorization-BLENxur8.d.cts} +18 -4
- package/dist/{authorization-DcA5oKZT.d.cts → authorization-Clf0Jx-U.d.ts} +18 -4
- package/dist/{authyonServerClient-UA7HdjtD.d.cts → authyonServerClient-CW46xIRD.d.cts} +233 -11
- package/dist/{authyonServerClient-UA7HdjtD.d.ts → authyonServerClient-CW46xIRD.d.ts} +233 -11
- package/dist/bff.cjs +8 -1
- package/dist/bff.d.cts +1 -1
- package/dist/bff.d.ts +1 -1
- package/dist/bff.js +1 -1
- package/dist/{chunk-TDJNBD3Z.js → chunk-SUL2HLRR.js} +8 -1
- package/dist/{chunk-NKWQMYB3.js → chunk-WF26WYSX.js} +37 -7
- package/dist/index.cjs +239 -16
- package/dist/index.d.cts +54 -4
- package/dist/index.d.ts +54 -4
- package/dist/index.js +190 -9
- package/dist/next.cjs +11 -1
- package/dist/next.d.cts +2 -2
- package/dist/next.d.ts +2 -2
- package/dist/next.js +1 -1
- package/package.json +81 -81
package/dist/index.cjs
CHANGED
|
@@ -33,10 +33,16 @@ __export(index_exports, {
|
|
|
33
33
|
AuthyonError: () => AuthyonError,
|
|
34
34
|
AuthyonServerClient: () => AuthyonServerClient,
|
|
35
35
|
AuthyonServerClientBuilder: () => AuthyonServerClientBuilder,
|
|
36
|
+
CLIENT_IP_HEADER: () => CLIENT_IP_HEADER,
|
|
36
37
|
ErrorCodes: () => ErrorCodes,
|
|
37
38
|
FetchHttpAdapter: () => FetchHttpAdapter,
|
|
38
39
|
JwksTokenVerifier: () => JwksTokenVerifier,
|
|
39
40
|
LoggingHttpAdapter: () => LoggingHttpAdapter,
|
|
41
|
+
SubtenantPermissions: () => SubtenantPermissions,
|
|
42
|
+
TENANT_FILTER_MAX_DEPTH: () => TENANT_FILTER_MAX_DEPTH,
|
|
43
|
+
TENANT_FILTER_MAX_VALUES: () => TENANT_FILTER_MAX_VALUES,
|
|
44
|
+
TENANT_FILTER_MAX_VALUE_LENGTH: () => TENANT_FILTER_MAX_VALUE_LENGTH,
|
|
45
|
+
TenantPermissions: () => TenantPermissions,
|
|
40
46
|
TenantScopedClient: () => TenantScopedClient,
|
|
41
47
|
TokenVerificationError: () => TokenVerificationError,
|
|
42
48
|
UserScopedClient: () => UserScopedClient,
|
|
@@ -49,7 +55,8 @@ __export(index_exports, {
|
|
|
49
55
|
createExpressAuthorizationMiddleware: () => createExpressAuthorizationMiddleware,
|
|
50
56
|
hasPermission: () => hasPermission,
|
|
51
57
|
hasPermissionGroup: () => hasPermissionGroup,
|
|
52
|
-
normalizeClientIp: () => normalizeClientIp
|
|
58
|
+
normalizeClientIp: () => normalizeClientIp,
|
|
59
|
+
tenantFilter: () => tenantFilter
|
|
53
60
|
});
|
|
54
61
|
module.exports = __toCommonJS(index_exports);
|
|
55
62
|
|
|
@@ -436,7 +443,14 @@ function appendQuery(path2, params) {
|
|
|
436
443
|
if (!params) return path2;
|
|
437
444
|
const query = new URLSearchParams();
|
|
438
445
|
for (const [key, value2] of Object.entries(params)) {
|
|
439
|
-
if (value2
|
|
446
|
+
if (value2 === void 0) continue;
|
|
447
|
+
if (Array.isArray(value2)) {
|
|
448
|
+
for (const item of value2) {
|
|
449
|
+
if (item !== void 0) query.append(key, String(item));
|
|
450
|
+
}
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
query.set(key, String(value2));
|
|
440
454
|
}
|
|
441
455
|
const value = query.toString();
|
|
442
456
|
return value ? `${path2}${path2.includes("?") ? "&" : "?"}${value}` : path2;
|
|
@@ -634,9 +648,11 @@ var JsonHttpClient = class {
|
|
|
634
648
|
};
|
|
635
649
|
|
|
636
650
|
// ../../internal/core/http/clientIp.ts
|
|
651
|
+
var CLIENT_IP_HEADER = "X-Authyon-Client-Ip";
|
|
637
652
|
function clientIpHeaders(context) {
|
|
638
653
|
if (!context?.clientIp) return {};
|
|
639
|
-
|
|
654
|
+
const ip = normalizeClientIp(context.clientIp);
|
|
655
|
+
return { "X-Forwarded-For": ip, [CLIENT_IP_HEADER]: ip };
|
|
640
656
|
}
|
|
641
657
|
function normalizeClientIp(value) {
|
|
642
658
|
let ip = value.trim();
|
|
@@ -791,6 +807,11 @@ function isRecord(value) {
|
|
|
791
807
|
}
|
|
792
808
|
|
|
793
809
|
// src/client/authyonServerClient.ts
|
|
810
|
+
var ROOT_PARENT_ID = "00000000-0000-0000-0000-000000000000";
|
|
811
|
+
function tenantListQuery({ parentId, ...rest }) {
|
|
812
|
+
if (parentId === void 0) return rest;
|
|
813
|
+
return { ...rest, parentId: parentId === null ? ROOT_PARENT_ID : parentId };
|
|
814
|
+
}
|
|
794
815
|
var _clientSecret;
|
|
795
816
|
var AuthyonServerClient = class {
|
|
796
817
|
constructor(options = {}) {
|
|
@@ -1016,13 +1037,64 @@ var AuthyonServerClient = class {
|
|
|
1016
1037
|
* is found by the number, and `cnpj` alone finds every tenant carrying
|
|
1017
1038
|
* that key. `take` defaults to 25 and is capped at 100.
|
|
1018
1039
|
*
|
|
1040
|
+
* `filter` is the structured half, and the one to reach for when more
|
|
1041
|
+
* than one condition has to hold: each entry is a condition on a JSON
|
|
1042
|
+
* document, they are ANDed with each other and with `search`, and they
|
|
1043
|
+
* run inside the statement — so the envelope keeps describing the
|
|
1044
|
+
* filtered set and you can page through it. Build them with
|
|
1045
|
+
* `tenantFilter`:
|
|
1046
|
+
*
|
|
1047
|
+
* ```ts
|
|
1048
|
+
* const page = await authyon.environment.tenants.list({
|
|
1049
|
+
* filter: [
|
|
1050
|
+
* tenantFilter.in("public.kind", ["reseller", "partner"]),
|
|
1051
|
+
* tenantFilter.in("custom.cnpj", [a, b]),
|
|
1052
|
+
* ],
|
|
1053
|
+
* take: 100,
|
|
1054
|
+
* });
|
|
1055
|
+
* ```
|
|
1056
|
+
*
|
|
1057
|
+
* `parentId` narrows the page to one level of the tree — `children()`
|
|
1058
|
+
* and `roots()` below are the same call with that one option set.
|
|
1059
|
+
*
|
|
1019
1060
|
* Against an Authyon API older than 2026-10-21 this route ignored
|
|
1020
|
-
* skip/take/search and answered with a bare array
|
|
1061
|
+
* skip/take/search and answered with a bare array; one older than
|
|
1062
|
+
* 2026-10-22 ignores `filter` and one older than 2026-10-31 ignores
|
|
1063
|
+
* `parentId`, which read as a page that is too wide rather than an error.
|
|
1064
|
+
*/
|
|
1065
|
+
list: (params = {}) => this.request("/env/tenants", { envBearer: true, query: tenantListQuery(params) }),
|
|
1066
|
+
/**
|
|
1067
|
+
* One page of a tenant's direct sub-tenants — `list()` with `parentId`.
|
|
1068
|
+
*
|
|
1069
|
+
* Only one level: a node's own children carry `childCount`, so a tree
|
|
1070
|
+
* view asks again where that is above zero instead of reading the whole
|
|
1071
|
+
* subtree to draw the first level of it.
|
|
1072
|
+
*/
|
|
1073
|
+
children: (parentTenantId, params = {}) => this.environment.tenants.list({ ...params, parentId: parentTenantId }),
|
|
1074
|
+
/**
|
|
1075
|
+
* One page of the environment's root tenants — `list()` with no parent.
|
|
1076
|
+
*
|
|
1077
|
+
* This is the first level of the tree, and the difference from `list()`
|
|
1078
|
+
* is worth keeping straight: `list()` returns every tenant at every
|
|
1079
|
+
* depth, which is what a flat picker wants and what a tree view must not
|
|
1080
|
+
* start from.
|
|
1081
|
+
*/
|
|
1082
|
+
roots: (params = {}) => this.environment.tenants.list({ ...params, parentId: null }),
|
|
1083
|
+
/**
|
|
1084
|
+
* POST /env/tenants — create a tenant in the environment.
|
|
1085
|
+
*
|
|
1086
|
+
* `parentTenantId` nests it under an existing tenant. The environment's
|
|
1087
|
+
* `maxTenantDepth` has to allow the level — it ships as `1`, roots only,
|
|
1088
|
+
* so this answers `tenant.depth.not_allowed` until an operator raises it
|
|
1089
|
+
* in the console.
|
|
1021
1090
|
*/
|
|
1022
|
-
list: (params = {}) => this.request("/env/tenants", { envBearer: true, query: params }),
|
|
1023
|
-
/** POST /env/tenants — create a tenant in the environment. */
|
|
1024
1091
|
create: (input) => this.request("/env/tenants", { method: "POST", envBearer: true, body: input }),
|
|
1025
|
-
/**
|
|
1092
|
+
/**
|
|
1093
|
+
* GET /env/tenants/{tenantId} — fetch a tenant by id.
|
|
1094
|
+
*
|
|
1095
|
+
* Returns `ancestors` as well, the chain above it root first, so a
|
|
1096
|
+
* breadcrumb costs this one call rather than one per level.
|
|
1097
|
+
*/
|
|
1026
1098
|
get: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, { envBearer: true }),
|
|
1027
1099
|
/** PUT /env/tenants/{tenantId} — update a tenant. */
|
|
1028
1100
|
update: (tenantId, input) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, {
|
|
@@ -1036,12 +1108,23 @@ var AuthyonServerClient = class {
|
|
|
1036
1108
|
envBearer: true,
|
|
1037
1109
|
body: input
|
|
1038
1110
|
}),
|
|
1039
|
-
/**
|
|
1111
|
+
/**
|
|
1112
|
+
* POST /env/tenants/{tenantId}/disable — disable without removing tenant
|
|
1113
|
+
* data.
|
|
1114
|
+
*
|
|
1115
|
+
* Disables the branch below it too. A sub-tenant left live under a
|
|
1116
|
+
* disabled parent would go on authenticating its users, which is the one
|
|
1117
|
+
* thing switching a tenant off is there to stop — so check `childCount`
|
|
1118
|
+
* before calling this on a node with children.
|
|
1119
|
+
*/
|
|
1040
1120
|
disable: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/disable`, {
|
|
1041
1121
|
method: "POST",
|
|
1042
1122
|
envBearer: true
|
|
1043
1123
|
}),
|
|
1044
|
-
/**
|
|
1124
|
+
/**
|
|
1125
|
+
* DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant,
|
|
1126
|
+
* and the branch below it. Same handler as `disable()`.
|
|
1127
|
+
*/
|
|
1045
1128
|
delete: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, {
|
|
1046
1129
|
method: "DELETE",
|
|
1047
1130
|
envBearer: true
|
|
@@ -1539,6 +1622,86 @@ var AuthyonServerClientBuilder = class {
|
|
|
1539
1622
|
};
|
|
1540
1623
|
_options = new WeakMap();
|
|
1541
1624
|
|
|
1625
|
+
// src/client/tenantFilters.ts
|
|
1626
|
+
var TENANT_FILTER_MAX_VALUES = 25;
|
|
1627
|
+
var TENANT_FILTER_MAX_VALUE_LENGTH = 200;
|
|
1628
|
+
var TENANT_FILTER_MAX_DEPTH = 3;
|
|
1629
|
+
var SCOPES = ["public", "private", "custom"];
|
|
1630
|
+
var KEY_SEGMENT = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1631
|
+
function assertPath(path2) {
|
|
1632
|
+
if (typeof path2 !== "string" || path2.length === 0) {
|
|
1633
|
+
throw new RangeError("Authyon: a filter path is required, e.g. public.kind.");
|
|
1634
|
+
}
|
|
1635
|
+
const [scope, ...keys] = path2.split(".");
|
|
1636
|
+
if (!SCOPES.includes(scope)) {
|
|
1637
|
+
throw new RangeError(
|
|
1638
|
+
`Authyon: unknown filter scope "${scope}" \u2014 use ${SCOPES.join(", ")} (e.g. public.kind).`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
if (keys.length === 0) {
|
|
1642
|
+
throw new RangeError(`Authyon: filter path "${path2}" needs a key after the scope.`);
|
|
1643
|
+
}
|
|
1644
|
+
if (keys.length > TENANT_FILTER_MAX_DEPTH) {
|
|
1645
|
+
throw new RangeError(
|
|
1646
|
+
`Authyon: filter path "${path2}" goes deeper than ${TENANT_FILTER_MAX_DEPTH} levels.`
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
for (const key of keys) {
|
|
1650
|
+
if (!KEY_SEGMENT.test(key)) {
|
|
1651
|
+
throw new RangeError(
|
|
1652
|
+
`Authyon: invalid filter key "${key}" \u2014 letters, digits, "_" and "-", up to 64 characters.`
|
|
1653
|
+
);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
return path2;
|
|
1657
|
+
}
|
|
1658
|
+
function assertValue(value, forIn) {
|
|
1659
|
+
if (value === void 0 || value === null) {
|
|
1660
|
+
throw new RangeError("Authyon: a filter value is required.");
|
|
1661
|
+
}
|
|
1662
|
+
const text = String(value);
|
|
1663
|
+
if (text.length === 0) {
|
|
1664
|
+
throw new RangeError("Authyon: a filter value may not be empty.");
|
|
1665
|
+
}
|
|
1666
|
+
if (text.length > TENANT_FILTER_MAX_VALUE_LENGTH) {
|
|
1667
|
+
throw new RangeError(
|
|
1668
|
+
`Authyon: a filter value may hold at most ${TENANT_FILTER_MAX_VALUE_LENGTH} characters.`
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
if (text.includes(",")) {
|
|
1672
|
+
throw new RangeError(
|
|
1673
|
+
forIn ? "Authyon: an `in` value may not contain a comma \u2014 pass separate values instead." : "Authyon: a filter value may not contain a comma."
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
return text;
|
|
1677
|
+
}
|
|
1678
|
+
var tenantFilter = {
|
|
1679
|
+
/** `public.kind:eq:reseller` — the key equals this value. */
|
|
1680
|
+
eq(path2, value) {
|
|
1681
|
+
return `${assertPath(path2)}:eq:${assertValue(value, false)}`;
|
|
1682
|
+
},
|
|
1683
|
+
/** `public.kind:in:reseller,partner` — the key equals any of these (SQL IN). */
|
|
1684
|
+
in(path2, values) {
|
|
1685
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
1686
|
+
throw new RangeError("Authyon: `in` needs at least one value.");
|
|
1687
|
+
}
|
|
1688
|
+
if (values.length > TENANT_FILTER_MAX_VALUES) {
|
|
1689
|
+
throw new RangeError(`Authyon: \`in\` takes at most ${TENANT_FILTER_MAX_VALUES} values.`);
|
|
1690
|
+
}
|
|
1691
|
+
const unique = [...new Set(values.map((value) => assertValue(value, true)))];
|
|
1692
|
+
return `${assertPath(path2)}:in:${unique.join(",")}`;
|
|
1693
|
+
},
|
|
1694
|
+
/** `public.notes:like:nacional` — the key contains this text, case-insensitive.
|
|
1695
|
+
* The server escapes the LIKE metacharacters, so `100%` means `100%`. */
|
|
1696
|
+
like(path2, text) {
|
|
1697
|
+
return `${assertPath(path2)}:like:${assertValue(text, false)}`;
|
|
1698
|
+
},
|
|
1699
|
+
/** `custom.cnpj:exists` — the key is present, whatever its value. */
|
|
1700
|
+
exists(path2) {
|
|
1701
|
+
return `${assertPath(path2)}:exists`;
|
|
1702
|
+
}
|
|
1703
|
+
};
|
|
1704
|
+
|
|
1542
1705
|
// ../../internal/core/authorization/ability.ts
|
|
1543
1706
|
var AuthyonAbility = class {
|
|
1544
1707
|
constructor(rules = [], detectSubjectType = defaultSubjectType) {
|
|
@@ -1602,12 +1765,29 @@ function createAuthyonAbility(source = {}, options = {}) {
|
|
|
1602
1765
|
return new AuthyonAbility(createAuthyonRules(source, options), options.detectSubjectType);
|
|
1603
1766
|
}
|
|
1604
1767
|
function hasPermission(source, requiredPermission) {
|
|
1605
|
-
const
|
|
1606
|
-
if (!
|
|
1607
|
-
return false;
|
|
1608
|
-
}
|
|
1768
|
+
const required = requiredPermission?.trim() ?? "";
|
|
1769
|
+
if (!isWellFormedPermission(required)) return false;
|
|
1609
1770
|
const permissionSource = isPermissionList(source) ? { permissions: source } : source;
|
|
1610
|
-
|
|
1771
|
+
const granted = [
|
|
1772
|
+
...permissionSource.permissions ?? [],
|
|
1773
|
+
...permissionSource.scope?.split(/\s+/).filter(Boolean) ?? []
|
|
1774
|
+
];
|
|
1775
|
+
return granted.some((permission) => grants(permission.trim(), required));
|
|
1776
|
+
}
|
|
1777
|
+
function grants(granted, required) {
|
|
1778
|
+
if (!isWellFormedPermission(granted)) return false;
|
|
1779
|
+
if (isFullWildcard(granted)) return true;
|
|
1780
|
+
const grantedSegments = granted.split(":");
|
|
1781
|
+
const requiredSegments = required.split(":");
|
|
1782
|
+
if (grantedSegments.length !== requiredSegments.length) return false;
|
|
1783
|
+
return grantedSegments.every(
|
|
1784
|
+
(segment2, index) => segment2 === "*" || segment2 === requiredSegments[index]
|
|
1785
|
+
);
|
|
1786
|
+
}
|
|
1787
|
+
function isWellFormedPermission(permission) {
|
|
1788
|
+
if (!permission) return false;
|
|
1789
|
+
const segments = permission.split(":");
|
|
1790
|
+
return segments.length >= 2 && segments.every((segment2) => segment2.length > 0);
|
|
1611
1791
|
}
|
|
1612
1792
|
function hasPermissionGroup(source, group) {
|
|
1613
1793
|
const hasAll = (group.allOf ?? []).every((permission) => hasPermission(source, permission));
|
|
@@ -1622,13 +1802,23 @@ function createAuthyonRules(source = {}, options = {}) {
|
|
|
1622
1802
|
...source.permissions ?? [],
|
|
1623
1803
|
...source.scope?.split(/\s+/).filter(Boolean) ?? []
|
|
1624
1804
|
]);
|
|
1625
|
-
const rules = [...permissions].map(
|
|
1805
|
+
const rules = [...permissions].map(grantToRule).filter(isAbilityRule);
|
|
1626
1806
|
for (const role of /* @__PURE__ */ new Set([...source.roles ?? [], ...options.roles ?? []])) {
|
|
1627
1807
|
rules.push(...(options.roleRules?.[role] ?? []).map(cloneRule));
|
|
1628
1808
|
}
|
|
1629
1809
|
rules.push(...(options.rules ?? []).map(cloneRule));
|
|
1630
1810
|
return rules;
|
|
1631
1811
|
}
|
|
1812
|
+
function grantToRule(permission) {
|
|
1813
|
+
const normalized = permission.trim();
|
|
1814
|
+
if (normalized && isFullWildcard(normalized)) {
|
|
1815
|
+
return { action: "manage", subject: "all" };
|
|
1816
|
+
}
|
|
1817
|
+
return permissionToRule(normalized);
|
|
1818
|
+
}
|
|
1819
|
+
function isFullWildcard(permission) {
|
|
1820
|
+
return permission.split(":").every((segment2) => segment2 === "*");
|
|
1821
|
+
}
|
|
1632
1822
|
function permissionToRule(permission) {
|
|
1633
1823
|
const normalized = permission.trim();
|
|
1634
1824
|
if (!normalized) return null;
|
|
@@ -1845,6 +2035,32 @@ function unauthenticated() {
|
|
|
1845
2035
|
"A valid bearer token is required"
|
|
1846
2036
|
);
|
|
1847
2037
|
}
|
|
2038
|
+
|
|
2039
|
+
// ../../internal/core/authorization/tenantPermissions.ts
|
|
2040
|
+
var TenantPermissions = {
|
|
2041
|
+
/** Rename the tenant and change its settings. */
|
|
2042
|
+
SettingsManage: "tenants:settings:manage",
|
|
2043
|
+
/** Invite an address to the tenant. */
|
|
2044
|
+
MembersInvite: "tenants:members:invite",
|
|
2045
|
+
/** Remove a member from the tenant. */
|
|
2046
|
+
MembersRemove: "tenants:members:remove"
|
|
2047
|
+
};
|
|
2048
|
+
var SubtenantPermissions = {
|
|
2049
|
+
/** Read any tenant below one you belong to. */
|
|
2050
|
+
TreeRead: "subtenants:tree:read",
|
|
2051
|
+
/** Rename a tenant below yours, and add or remove its members. */
|
|
2052
|
+
TreeManage: "subtenants:tree:manage",
|
|
2053
|
+
/** Create a tenant underneath one you belong to. */
|
|
2054
|
+
TreeCreate: "subtenants:tree:create",
|
|
2055
|
+
/**
|
|
2056
|
+
* Make a tenant below yours the ACTIVE tenant of the session — acting inside
|
|
2057
|
+
* it rather than on it from outside. Deliberately not the same permission as
|
|
2058
|
+
* {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
|
|
2059
|
+
* the management endpoints and operating as that sub-tenant are different
|
|
2060
|
+
* powers, and granting the first should not hand over the second.
|
|
2061
|
+
*/
|
|
2062
|
+
TreeSwitch: "subtenants:tree:switch"
|
|
2063
|
+
};
|
|
1848
2064
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1849
2065
|
0 && (module.exports = {
|
|
1850
2066
|
AuthorizationError,
|
|
@@ -1853,10 +2069,16 @@ function unauthenticated() {
|
|
|
1853
2069
|
AuthyonError,
|
|
1854
2070
|
AuthyonServerClient,
|
|
1855
2071
|
AuthyonServerClientBuilder,
|
|
2072
|
+
CLIENT_IP_HEADER,
|
|
1856
2073
|
ErrorCodes,
|
|
1857
2074
|
FetchHttpAdapter,
|
|
1858
2075
|
JwksTokenVerifier,
|
|
1859
2076
|
LoggingHttpAdapter,
|
|
2077
|
+
SubtenantPermissions,
|
|
2078
|
+
TENANT_FILTER_MAX_DEPTH,
|
|
2079
|
+
TENANT_FILTER_MAX_VALUES,
|
|
2080
|
+
TENANT_FILTER_MAX_VALUE_LENGTH,
|
|
2081
|
+
TenantPermissions,
|
|
1860
2082
|
TenantScopedClient,
|
|
1861
2083
|
TokenVerificationError,
|
|
1862
2084
|
UserScopedClient,
|
|
@@ -1869,5 +2091,6 @@ function unauthenticated() {
|
|
|
1869
2091
|
createExpressAuthorizationMiddleware,
|
|
1870
2092
|
hasPermission,
|
|
1871
2093
|
hasPermissionGroup,
|
|
1872
|
-
normalizeClientIp
|
|
2094
|
+
normalizeClientIp,
|
|
2095
|
+
tenantFilter
|
|
1873
2096
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
-
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials,
|
|
3
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-
|
|
1
|
+
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.cjs';
|
|
2
|
+
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, m as AuthyonTenantClaim, C as CLIENT_IP_HEADER, n as ClientCredentials, o as ClientRequestContext, p as ConfirmApprovalInput, q as ConsumedApproval, r as CreateApprovalInput, s as CreateCredentialInput, t as CreateOrganizationInput, u as CreatePermissionInput, v as CreateTenantCredentialInput, w as CreateUserInput, x as CredentialCreator, y as CredentialDetail, z as CredentialListOptions, B as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, D as HttpAdapterRequest, G as HttpLogEvent, I as HttpLogger, K as IntrospectResult, L as InviteTenantMemberInput, M as IssuePasswordResetInput, N as JsonWebKeySet, J as JwksTokenVerifier, O as JwksTokenVerifierOptions, P as LoggingHttpAdapter, Q as LoginActivity, R as OpenIdConfiguration, S as Organization, T as OtpCheckResult, U as Paged, V as PaginationOptions, W as PasswordResetCompleted, X as PasswordResetIssued, Y as PasswordResetPreview, Z as Permission, _ as PermissionsByRole, $ as ReservedPermissions, a0 as Role, a1 as RoleGrant, a2 as RoleInput, a3 as RoleList, a4 as RolePermissions, a5 as SafeJwtAlgorithm, a6 as SecurityMethods, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TENANT_FILTER_MAX_DEPTH, aa as TENANT_FILTER_MAX_VALUES, ab as TENANT_FILTER_MAX_VALUE_LENGTH, ac as TenantAncestor, ad as TenantClientValidationResult, ae as TenantCredentialIssued, af as TenantCredentialSummary, ag as TenantFilterExpression, ah as TenantFilterValue, ai as TenantInvite, aj as TenantInviteAccepted, ak as TenantInviteInput, al as TenantInviteIssued, am as TenantInvitePreview, an as TenantInviteStatus, ao as TenantListOptions, ap as TenantMember, aq as TenantMemberPage, ar as TenantMembership, as as TenantScopedClient, at as TokenResult, au as TokenVerificationError, av as TokenVerificationErrorCode, aw as UpdateOrganizationInput, ax as User, ay as UserScopedClient, az as ValidateResult, aA as VerifiedAccessToken, aB as createClient, aC as normalizeClientIp, aD as tenantFilter } from './authyonServerClient-CW46xIRD.cjs';
|
|
3
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-BLENxur8.cjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
declare const ErrorCodes: {
|
|
@@ -94,4 +94,54 @@ declare class AuthyonServerClientBuilder {
|
|
|
94
94
|
build(): AuthyonServerClient;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
/**
|
|
98
|
+
* The permission values the tenant surface checks, as constants.
|
|
99
|
+
*
|
|
100
|
+
* They are strings on the wire and nothing forces you through here — the point
|
|
101
|
+
* is that a rename shows up as a type error instead of as a 403 nobody can
|
|
102
|
+
* explain. `tenants:settings:manage` is exactly that case: it used to be
|
|
103
|
+
* written `tenants:manage`, a two-segment value the API could not even store,
|
|
104
|
+
* so the endpoint requiring it refused every caller.
|
|
105
|
+
*/
|
|
106
|
+
declare const TenantPermissions: {
|
|
107
|
+
/** Rename the tenant and change its settings. */
|
|
108
|
+
readonly SettingsManage: "tenants:settings:manage";
|
|
109
|
+
/** Invite an address to the tenant. */
|
|
110
|
+
readonly MembersInvite: "tenants:members:invite";
|
|
111
|
+
/** Remove a member from the tenant. */
|
|
112
|
+
readonly MembersRemove: "tenants:members:remove";
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* What lets a member of one tenant reach the tenants beneath it.
|
|
116
|
+
*
|
|
117
|
+
* A separate domain, not a suffix on `tenants:…`, and the reason is worth
|
|
118
|
+
* knowing before you grant one: permissions match per segment, so naming these
|
|
119
|
+
* `tenants:tree:manage` would have handed every role already holding
|
|
120
|
+
* `tenants:*:*` power over the whole subtree the day the hierarchy shipped — a
|
|
121
|
+
* widening that appears in no diff. `subtenants:…` is only covered by `*:*:*`,
|
|
122
|
+
* which is explicit superuser.
|
|
123
|
+
*
|
|
124
|
+
* Reaching down is opt-in at every level: holding `tenants:settings:manage` on
|
|
125
|
+
* a parent grants nothing below it, and each of these is granted at the node
|
|
126
|
+
* the caller belongs to, never at the target.
|
|
127
|
+
*/
|
|
128
|
+
declare const SubtenantPermissions: {
|
|
129
|
+
/** Read any tenant below one you belong to. */
|
|
130
|
+
readonly TreeRead: "subtenants:tree:read";
|
|
131
|
+
/** Rename a tenant below yours, and add or remove its members. */
|
|
132
|
+
readonly TreeManage: "subtenants:tree:manage";
|
|
133
|
+
/** Create a tenant underneath one you belong to. */
|
|
134
|
+
readonly TreeCreate: "subtenants:tree:create";
|
|
135
|
+
/**
|
|
136
|
+
* Make a tenant below yours the ACTIVE tenant of the session — acting inside
|
|
137
|
+
* it rather than on it from outside. Deliberately not the same permission as
|
|
138
|
+
* {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
|
|
139
|
+
* the management endpoints and operating as that sub-tenant are different
|
|
140
|
+
* powers, and granting the first should not hand over the second.
|
|
141
|
+
*/
|
|
142
|
+
readonly TreeSwitch: "subtenants:tree:switch";
|
|
143
|
+
};
|
|
144
|
+
type TenantPermission = (typeof TenantPermissions)[keyof typeof TenantPermissions];
|
|
145
|
+
type SubtenantPermission = (typeof SubtenantPermissions)[keyof typeof SubtenantPermissions];
|
|
146
|
+
|
|
147
|
+
export { AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, AuthyonServerClient, AuthyonServerClientBuilder, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, type SubtenantPermission, SubtenantPermissions, type TenantPermission, TenantPermissions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
-
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials,
|
|
3
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-
|
|
1
|
+
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.js';
|
|
2
|
+
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, m as AuthyonTenantClaim, C as CLIENT_IP_HEADER, n as ClientCredentials, o as ClientRequestContext, p as ConfirmApprovalInput, q as ConsumedApproval, r as CreateApprovalInput, s as CreateCredentialInput, t as CreateOrganizationInput, u as CreatePermissionInput, v as CreateTenantCredentialInput, w as CreateUserInput, x as CredentialCreator, y as CredentialDetail, z as CredentialListOptions, B as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, D as HttpAdapterRequest, G as HttpLogEvent, I as HttpLogger, K as IntrospectResult, L as InviteTenantMemberInput, M as IssuePasswordResetInput, N as JsonWebKeySet, J as JwksTokenVerifier, O as JwksTokenVerifierOptions, P as LoggingHttpAdapter, Q as LoginActivity, R as OpenIdConfiguration, S as Organization, T as OtpCheckResult, U as Paged, V as PaginationOptions, W as PasswordResetCompleted, X as PasswordResetIssued, Y as PasswordResetPreview, Z as Permission, _ as PermissionsByRole, $ as ReservedPermissions, a0 as Role, a1 as RoleGrant, a2 as RoleInput, a3 as RoleList, a4 as RolePermissions, a5 as SafeJwtAlgorithm, a6 as SecurityMethods, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TENANT_FILTER_MAX_DEPTH, aa as TENANT_FILTER_MAX_VALUES, ab as TENANT_FILTER_MAX_VALUE_LENGTH, ac as TenantAncestor, ad as TenantClientValidationResult, ae as TenantCredentialIssued, af as TenantCredentialSummary, ag as TenantFilterExpression, ah as TenantFilterValue, ai as TenantInvite, aj as TenantInviteAccepted, ak as TenantInviteInput, al as TenantInviteIssued, am as TenantInvitePreview, an as TenantInviteStatus, ao as TenantListOptions, ap as TenantMember, aq as TenantMemberPage, ar as TenantMembership, as as TenantScopedClient, at as TokenResult, au as TokenVerificationError, av as TokenVerificationErrorCode, aw as UpdateOrganizationInput, ax as User, ay as UserScopedClient, az as ValidateResult, aA as VerifiedAccessToken, aB as createClient, aC as normalizeClientIp, aD as tenantFilter } from './authyonServerClient-CW46xIRD.js';
|
|
3
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-Clf0Jx-U.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
declare const ErrorCodes: {
|
|
@@ -94,4 +94,54 @@ declare class AuthyonServerClientBuilder {
|
|
|
94
94
|
build(): AuthyonServerClient;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
/**
|
|
98
|
+
* The permission values the tenant surface checks, as constants.
|
|
99
|
+
*
|
|
100
|
+
* They are strings on the wire and nothing forces you through here — the point
|
|
101
|
+
* is that a rename shows up as a type error instead of as a 403 nobody can
|
|
102
|
+
* explain. `tenants:settings:manage` is exactly that case: it used to be
|
|
103
|
+
* written `tenants:manage`, a two-segment value the API could not even store,
|
|
104
|
+
* so the endpoint requiring it refused every caller.
|
|
105
|
+
*/
|
|
106
|
+
declare const TenantPermissions: {
|
|
107
|
+
/** Rename the tenant and change its settings. */
|
|
108
|
+
readonly SettingsManage: "tenants:settings:manage";
|
|
109
|
+
/** Invite an address to the tenant. */
|
|
110
|
+
readonly MembersInvite: "tenants:members:invite";
|
|
111
|
+
/** Remove a member from the tenant. */
|
|
112
|
+
readonly MembersRemove: "tenants:members:remove";
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* What lets a member of one tenant reach the tenants beneath it.
|
|
116
|
+
*
|
|
117
|
+
* A separate domain, not a suffix on `tenants:…`, and the reason is worth
|
|
118
|
+
* knowing before you grant one: permissions match per segment, so naming these
|
|
119
|
+
* `tenants:tree:manage` would have handed every role already holding
|
|
120
|
+
* `tenants:*:*` power over the whole subtree the day the hierarchy shipped — a
|
|
121
|
+
* widening that appears in no diff. `subtenants:…` is only covered by `*:*:*`,
|
|
122
|
+
* which is explicit superuser.
|
|
123
|
+
*
|
|
124
|
+
* Reaching down is opt-in at every level: holding `tenants:settings:manage` on
|
|
125
|
+
* a parent grants nothing below it, and each of these is granted at the node
|
|
126
|
+
* the caller belongs to, never at the target.
|
|
127
|
+
*/
|
|
128
|
+
declare const SubtenantPermissions: {
|
|
129
|
+
/** Read any tenant below one you belong to. */
|
|
130
|
+
readonly TreeRead: "subtenants:tree:read";
|
|
131
|
+
/** Rename a tenant below yours, and add or remove its members. */
|
|
132
|
+
readonly TreeManage: "subtenants:tree:manage";
|
|
133
|
+
/** Create a tenant underneath one you belong to. */
|
|
134
|
+
readonly TreeCreate: "subtenants:tree:create";
|
|
135
|
+
/**
|
|
136
|
+
* Make a tenant below yours the ACTIVE tenant of the session — acting inside
|
|
137
|
+
* it rather than on it from outside. Deliberately not the same permission as
|
|
138
|
+
* {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
|
|
139
|
+
* the management endpoints and operating as that sub-tenant are different
|
|
140
|
+
* powers, and granting the first should not hand over the second.
|
|
141
|
+
*/
|
|
142
|
+
readonly TreeSwitch: "subtenants:tree:switch";
|
|
143
|
+
};
|
|
144
|
+
type TenantPermission = (typeof TenantPermissions)[keyof typeof TenantPermissions];
|
|
145
|
+
type SubtenantPermission = (typeof SubtenantPermissions)[keyof typeof SubtenantPermissions];
|
|
146
|
+
|
|
147
|
+
export { AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, AuthyonServerClient, AuthyonServerClientBuilder, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, type SubtenantPermission, SubtenantPermissions, type TenantPermission, TenantPermissions };
|