@adonis-agora/authkit-server 1.0.0-rc.6 → 1.0.0-rc.7
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/CHANGELOG.md +6 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/src/accounts/account_store.d.ts +6 -0
- package/build/src/accounts/lucid_store/organizations.js +6 -0
- package/build/src/tenancy/tenant_labels.d.ts +30 -0
- package/build/src/tenancy/tenant_labels.js +64 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @adonis-agora/authkit-server
|
|
2
2
|
|
|
3
|
+
## 1.0.0-rc.7
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#465](https://github.com/DavideCarvalho/adonis-agora-authkit/pull/465) [`6bd9575`](https://github.com/DavideCarvalho/adonis-agora-authkit/commit/6bd95759752c0fac14a061875abebb38c0e238b7) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - The active organization is published as the request's tenant in `@adonis-agora/context`: `Context.tenant()` returns `{ id, kind: 'organization', source: 'authkit', slug, role }` (and `tenantId` as before). New client option `tenancy`: `eager` resolves the session at request start (default on when `config/context.ts` enables tenancy and the resolver is `jwt`), `personal` makes the user the tenant when there is no active organization (off by default), and `resolve` maps the session to your own (optionally nested) tenants. A tenant the app sets itself with `Context.setTenant` is never overwritten. authkit-server ships `authkitTenantLabels()`, a label resolver for `config/context.ts` → `tenancy.label` that shows organization names in the consoles, and account stores gain the optional `findOrgsByIds` (implemented by the Lucid store).
|
|
8
|
+
|
|
3
9
|
## 1.0.0-rc.6
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/build/index.d.ts
CHANGED
|
@@ -161,4 +161,5 @@ export { ensureAuthkitSchema, ensureAuthkitTables } from './src/schema/ensure.js
|
|
|
161
161
|
export type { ServiceTenantInfo } from './src/service_tenants/client_metadata.js';
|
|
162
162
|
export type { ResolvedServiceTenantResource, ResolvedServiceTenantsConfig, ServiceTenantResourceInput, ServiceTenantsConfigInput, } from './src/service_tenants/config.js';
|
|
163
163
|
export { AuthkitTenantVerifier, type AuthkitTenantVerifierFn, type AuthkitTenantVerifierOptions, authkitTenantVerifier, type TenantTokenIssuer, type TenantVerifierInput, type VerifiedTenant, } from './src/service_tenants/tenant_verifier.js';
|
|
164
|
+
export { type AuthkitTenantLabelsOptions, authkitTenantLabels, type TenantLabelResolver, } from './src/tenancy/tenant_labels.js';
|
|
164
165
|
export { stubsRoot } from './stubs/main.js';
|
package/build/index.js
CHANGED
|
@@ -137,4 +137,5 @@ export { checkClientRegistration, classifyRedirect, RegistrationPolicyError, } f
|
|
|
137
137
|
export { registerOidcRoutes } from './src/register_routes.js';
|
|
138
138
|
export { ensureAuthkitSchema, ensureAuthkitTables } from './src/schema/ensure.js';
|
|
139
139
|
export { AuthkitTenantVerifier, authkitTenantVerifier, } from './src/service_tenants/tenant_verifier.js';
|
|
140
|
+
export { authkitTenantLabels, } from './src/tenancy/tenant_labels.js';
|
|
140
141
|
export { stubsRoot } from './stubs/main.js';
|
|
@@ -605,6 +605,12 @@ export interface OrganizationsCapability {
|
|
|
605
605
|
}): Promise<OrgSummary>;
|
|
606
606
|
findOrgById(orgId: string): Promise<OrgSummary | null>;
|
|
607
607
|
findOrgBySlug(slug: string): Promise<OrgSummary | null>;
|
|
608
|
+
/**
|
|
609
|
+
* OPTIONAL: the orgs among `orgIds` that exist, in a bounded number of queries
|
|
610
|
+
* (any order; unknown ids are left out). Absent → callers fall back to
|
|
611
|
+
* `findOrgById` per id.
|
|
612
|
+
*/
|
|
613
|
+
findOrgsByIds?(orgIds: readonly string[]): Promise<OrgSummary[]>;
|
|
608
614
|
listOrgsForAccount(accountId: string): Promise<Array<OrgSummary & {
|
|
609
615
|
role: string;
|
|
610
616
|
}>>;
|
|
@@ -137,6 +137,12 @@ export function buildOrganizations(ctx) {
|
|
|
137
137
|
const row = await OrgModel.find(orgId);
|
|
138
138
|
return row ? toOrgSummary(row) : null;
|
|
139
139
|
},
|
|
140
|
+
async findOrgsByIds(orgIds) {
|
|
141
|
+
const ids = [...new Set(orgIds)];
|
|
142
|
+
if (ids.length === 0)
|
|
143
|
+
return [];
|
|
144
|
+
return (await findManyChunked(OrgModel, ids)).map(toOrgSummary);
|
|
145
|
+
},
|
|
140
146
|
async findOrgBySlug(slug) {
|
|
141
147
|
const row = await OrgModel.query().where('slug', slug).first();
|
|
142
148
|
return row ? toOrgSummary(row) : null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AccountStore, OrgSummary } from '../accounts/account_store.js';
|
|
2
|
+
/** What `config/context.ts` → `tenancy.label` expects: tenant id → display label. */
|
|
3
|
+
export type TenantLabelResolver = (ids: readonly string[]) => Promise<Record<string, string>>;
|
|
4
|
+
export interface AuthkitTenantLabelsOptions {
|
|
5
|
+
/** Which field labels an organization: `'name'` (default), `'slug'`, or your own function. */
|
|
6
|
+
label?: 'name' | 'slug' | ((org: OrgSummary) => string);
|
|
7
|
+
/**
|
|
8
|
+
* Where the account store comes from. Default: the `authkit.server` binding of the
|
|
9
|
+
* booted app (`config/authkit.ts` → `accountStore`).
|
|
10
|
+
*/
|
|
11
|
+
store?: () => AccountStore | Promise<AccountStore>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A tenant label resolver backed by authkit organizations, for
|
|
15
|
+
* `config/context.ts` → `tenancy.label`. Consoles call it with the tenant ids they
|
|
16
|
+
* are about to show; it returns `{ [orgId]: name }` for the ids that are authkit
|
|
17
|
+
* organizations. Ids it does not know (personal tenants, other kinds) are left
|
|
18
|
+
* out, so the console shows the id. It only reads labels: no membership, role or
|
|
19
|
+
* metadata leaves it.
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* // config/context.ts
|
|
23
|
+
* import { authkitTenantLabels } from '@adonis-agora/authkit-server'
|
|
24
|
+
*
|
|
25
|
+
* export default defineConfig({
|
|
26
|
+
* tenancy: { enabled: true, kinds: ['organization'], label: authkitTenantLabels() },
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function authkitTenantLabels(options?: AuthkitTenantLabelsOptions): TenantLabelResolver;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getBootedApp } from '../../services/booted_app.js';
|
|
2
|
+
import { supportsOrganizations } from '../accounts/account_store.js';
|
|
3
|
+
/** Fallback walk without `findOrgsByIds`: one lookup per id, at most this many ids. */
|
|
4
|
+
const FALLBACK_MAX = 200;
|
|
5
|
+
const defaultStore = async () => {
|
|
6
|
+
const service = (await getBootedApp().container.make('authkit.server'));
|
|
7
|
+
return service.config.accountStore;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A tenant label resolver backed by authkit organizations, for
|
|
11
|
+
* `config/context.ts` → `tenancy.label`. Consoles call it with the tenant ids they
|
|
12
|
+
* are about to show; it returns `{ [orgId]: name }` for the ids that are authkit
|
|
13
|
+
* organizations. Ids it does not know (personal tenants, other kinds) are left
|
|
14
|
+
* out, so the console shows the id. It only reads labels: no membership, role or
|
|
15
|
+
* metadata leaves it.
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* // config/context.ts
|
|
19
|
+
* import { authkitTenantLabels } from '@adonis-agora/authkit-server'
|
|
20
|
+
*
|
|
21
|
+
* export default defineConfig({
|
|
22
|
+
* tenancy: { enabled: true, kinds: ['organization'], label: authkitTenantLabels() },
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function authkitTenantLabels(options = {}) {
|
|
27
|
+
const pick = typeof options.label === 'function'
|
|
28
|
+
? options.label
|
|
29
|
+
: options.label === 'slug'
|
|
30
|
+
? (org) => org.slug
|
|
31
|
+
: (org) => org.name;
|
|
32
|
+
return async (ids) => {
|
|
33
|
+
const wanted = [
|
|
34
|
+
...new Set((Array.isArray(ids) ? ids : []).filter((id) => typeof id === 'string' && id)),
|
|
35
|
+
];
|
|
36
|
+
if (wanted.length === 0)
|
|
37
|
+
return {};
|
|
38
|
+
const store = await (options.store ?? defaultStore)();
|
|
39
|
+
if (!store || !supportsOrganizations(store))
|
|
40
|
+
return {};
|
|
41
|
+
let orgs;
|
|
42
|
+
if (typeof store.findOrgsByIds === 'function') {
|
|
43
|
+
orgs = await store.findOrgsByIds(wanted);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
orgs = [];
|
|
47
|
+
for (const id of wanted.slice(0, FALLBACK_MAX)) {
|
|
48
|
+
const org = await store.findOrgById(id);
|
|
49
|
+
if (org)
|
|
50
|
+
orgs.push(org);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const asked = new Set(wanted);
|
|
54
|
+
const labels = {};
|
|
55
|
+
for (const org of orgs) {
|
|
56
|
+
if (!asked.has(org.id))
|
|
57
|
+
continue;
|
|
58
|
+
const label = pick(org);
|
|
59
|
+
if (typeof label === 'string' && label !== '')
|
|
60
|
+
labels[org.id] = label;
|
|
61
|
+
}
|
|
62
|
+
return labels;
|
|
63
|
+
};
|
|
64
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonis-agora/authkit-server",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.7",
|
|
4
4
|
"description": "AdonisJS OIDC/OAuth2 provider (Identity Provider) toolkit: ejectable auth server with sessions, rate-limiting, MFA/TOTP, audit log, federated logout and OpenTelemetry metrics.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dudousxd",
|