@shamar/adonis 0.1.3 → 0.1.4
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 +75 -2
- package/assets/admin.css +1 -1
- package/dist/auth/ldap.d.ts +115 -0
- package/dist/auth/ldap.d.ts.map +1 -0
- package/dist/auth/ldap.js +275 -0
- package/dist/auth/ldap.js.map +1 -0
- package/dist/auth/masquerade.d.ts +31 -0
- package/dist/auth/masquerade.d.ts.map +1 -0
- package/dist/auth/masquerade.js +36 -0
- package/dist/auth/masquerade.js.map +1 -0
- package/dist/auth_login_view.d.ts +56 -0
- package/dist/auth_login_view.d.ts.map +1 -0
- package/dist/auth_login_view.js +56 -0
- package/dist/auth_login_view.js.map +1 -0
- package/dist/commands/commands.json +1 -0
- package/dist/commands/main.d.ts +4 -0
- package/dist/commands/main.js +36 -0
- package/dist/commands/publish_auth.d.ts +13 -0
- package/dist/commands/publish_auth.d.ts.map +1 -0
- package/dist/commands/publish_auth.js +26 -0
- package/dist/commands/publish_auth.js.map +1 -0
- package/dist/config.d.ts +32 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/configure.d.ts +16 -1
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +6 -0
- package/dist/configure.js.map +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/controllers/admin_controller.d.ts.map +1 -1
- package/dist/controllers/admin_controller.js +14 -6
- package/dist/controllers/admin_controller.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/publish_auth.d.ts +45 -0
- package/dist/publish_auth.d.ts.map +1 -0
- package/dist/publish_auth.js +69 -0
- package/dist/publish_auth.js.map +1 -0
- package/dist/resources/api_key_resource.d.ts +4 -6
- package/dist/resources/api_key_resource.d.ts.map +1 -1
- package/dist/resources/api_key_resource.js +4 -16
- package/dist/resources/api_key_resource.js.map +1 -1
- package/dist/shamar/auth.d.ts +13 -1
- package/dist/shamar/auth.d.ts.map +1 -1
- package/dist/shamar/auth.js +42 -5
- package/dist/shamar/auth.js.map +1 -1
- package/dist/shamar/relation-fields.d.ts.map +1 -1
- package/dist/shamar/relation-fields.js +3 -2
- package/dist/shamar/relation-fields.js.map +1 -1
- package/dist/shamar/view-context.d.ts +8 -0
- package/dist/shamar/view-context.d.ts.map +1 -1
- package/dist/shamar/view-context.js +1 -0
- package/dist/shamar/view-context.js.map +1 -1
- package/package.json +15 -6
- package/resources/views/shamar/partials/nav.edge +6 -1
- package/resources/views/shamar/partials/shell-open.edge +14 -0
- package/resources/views/shamar/partials/topbar.edge +3 -0
- package/stubs/views/auth/layout.edge +244 -0
- package/stubs/views/auth/login.edge +65 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { mapGroupsToRoleIds, parseLdapUsername, } from '@shamar/cherubim';
|
|
2
|
+
export const LDAP_TIMEOUT_MESSAGE = 'Directory server timed out. Please try again.';
|
|
3
|
+
/** Thrown / rethrown when ldapts (or the network) times out contacting a domain. */
|
|
4
|
+
export class LdapTimeoutError extends Error {
|
|
5
|
+
domainId;
|
|
6
|
+
constructor(domainId, cause) {
|
|
7
|
+
const detail = cause instanceof Error && cause.message.trim()
|
|
8
|
+
? cause.message.trim()
|
|
9
|
+
: 'operation timed out';
|
|
10
|
+
super(`LDAP domain "${domainId}" timed out: ${detail}`);
|
|
11
|
+
this.name = 'LdapTimeoutError';
|
|
12
|
+
this.domainId = domainId;
|
|
13
|
+
if (cause !== undefined) {
|
|
14
|
+
this.cause = cause;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function isLdapTimeoutError(error) {
|
|
19
|
+
if (error instanceof LdapTimeoutError)
|
|
20
|
+
return true;
|
|
21
|
+
if (!error || typeof error !== 'object')
|
|
22
|
+
return false;
|
|
23
|
+
const err = error;
|
|
24
|
+
const code = String(err.code ?? '').toUpperCase();
|
|
25
|
+
if (code === 'ETIMEDOUT' || code === 'TIMEOUT' || code === 'ECONNABORTED') {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
const name = String(err.name ?? '');
|
|
29
|
+
if (/timeout/i.test(name))
|
|
30
|
+
return true;
|
|
31
|
+
const message = String(err.message ?? '').toLowerCase();
|
|
32
|
+
return (message.includes('timed out') ||
|
|
33
|
+
message.includes('timeout') ||
|
|
34
|
+
message.includes('connect timeout'));
|
|
35
|
+
}
|
|
36
|
+
export function resolveLdapProvisioning(mode) {
|
|
37
|
+
return mode === 'create' ? 'create' : 'existing';
|
|
38
|
+
}
|
|
39
|
+
export function resolveAuthLoginMode(mode, domains) {
|
|
40
|
+
if (mode === 'local' || mode === 'ldap' || mode === 'both')
|
|
41
|
+
return mode;
|
|
42
|
+
return domains?.length ? 'both' : 'local';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Order domains: hinted matches first, then remaining config order.
|
|
46
|
+
*/
|
|
47
|
+
export function orderLdapDomains(usernameInput, domains) {
|
|
48
|
+
const parsed = parseLdapUsername(usernameInput);
|
|
49
|
+
const preferred = [];
|
|
50
|
+
const rest = [];
|
|
51
|
+
for (const domain of domains) {
|
|
52
|
+
let match = false;
|
|
53
|
+
if (parsed.netbios && domain.netbios) {
|
|
54
|
+
match = domain.netbios.toUpperCase() === parsed.netbios.toUpperCase();
|
|
55
|
+
}
|
|
56
|
+
if (!match && parsed.emailDomain && domain.emailDomains?.length) {
|
|
57
|
+
const needle = parsed.emailDomain.toLowerCase();
|
|
58
|
+
match = domain.emailDomains.some((d) => d.toLowerCase() === needle);
|
|
59
|
+
}
|
|
60
|
+
if (match)
|
|
61
|
+
preferred.push(domain);
|
|
62
|
+
else
|
|
63
|
+
rest.push(domain);
|
|
64
|
+
}
|
|
65
|
+
return [...preferred, ...rest];
|
|
66
|
+
}
|
|
67
|
+
export function searchUsernameForDomain(usernameInput, _domain) {
|
|
68
|
+
const parsed = parseLdapUsername(usernameInput);
|
|
69
|
+
return parsed.username || usernameInput.trim();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Try domains in order until one authenticates.
|
|
73
|
+
* Returns `{ identity: null }` when none succeed (caller decides local fallback).
|
|
74
|
+
* Sets `timedOut` when any domain attempt hit a connect/operation timeout.
|
|
75
|
+
*/
|
|
76
|
+
export async function authenticateLdap(usernameInput, password, domains, client) {
|
|
77
|
+
if (!password || !usernameInput.trim() || domains.length === 0) {
|
|
78
|
+
return { identity: null, timedOut: false };
|
|
79
|
+
}
|
|
80
|
+
const ordered = orderLdapDomains(usernameInput, domains);
|
|
81
|
+
let timedOut = false;
|
|
82
|
+
for (const domain of ordered) {
|
|
83
|
+
const username = searchUsernameForDomain(usernameInput, domain);
|
|
84
|
+
try {
|
|
85
|
+
const identity = await client.authenticate(username, password, domain);
|
|
86
|
+
if (identity)
|
|
87
|
+
return { identity, timedOut };
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (isLdapTimeoutError(error)) {
|
|
91
|
+
timedOut = true;
|
|
92
|
+
console.warn(`[shamar/ldap] domain "${domain.id}" timed out:`, error instanceof Error ? error.message : error);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Unreachable / misconfigured domain — try the next one.
|
|
96
|
+
console.warn(`[shamar/ldap] domain "${domain.id}" failed:`, error instanceof Error ? error.message : error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { identity: null, timedOut };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Orchestrate local / LDAP / both login modes.
|
|
103
|
+
*
|
|
104
|
+
* After a successful directory bind, {@link linkFromLdap} must resolve a local
|
|
105
|
+
* user (matched by sync UID / externalId). When `provisioning` is `existing`
|
|
106
|
+
* and no local row exists, LDAP login fails (or falls through to local when
|
|
107
|
+
* `loginMode` is `both`).
|
|
108
|
+
*/
|
|
109
|
+
export async function resolvePasswordLogin(options) {
|
|
110
|
+
const mode = resolveAuthLoginMode(options.loginMode, options.domains);
|
|
111
|
+
const domains = options.domains ?? [];
|
|
112
|
+
const provisioning = resolveLdapProvisioning(options.provisioning);
|
|
113
|
+
if (mode === 'local') {
|
|
114
|
+
const user = await options.verifyLocal(options.username, options.password);
|
|
115
|
+
if (!user)
|
|
116
|
+
return { ok: false, message: 'Invalid user credentials' };
|
|
117
|
+
return { ok: true, user, method: 'local' };
|
|
118
|
+
}
|
|
119
|
+
if (domains.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
message: 'LDAP login is enabled but no domains are configured',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const { identity, timedOut } = await authenticateLdap(options.username, options.password, domains, options.client);
|
|
126
|
+
if (identity) {
|
|
127
|
+
const user = await options.linkFromLdap(identity);
|
|
128
|
+
if (user) {
|
|
129
|
+
return { ok: true, user, method: 'ldap' };
|
|
130
|
+
}
|
|
131
|
+
if (provisioning === 'existing') {
|
|
132
|
+
// Bound in LDAP but no local sync row — do not invent a user.
|
|
133
|
+
if (mode === 'ldap') {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
message: 'No local account is linked to this directory user',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// both: fall through to local password check
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// create mode with null link is a host bug
|
|
143
|
+
return {
|
|
144
|
+
ok: false,
|
|
145
|
+
message: 'Unable to provision local account for directory user',
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (mode === 'ldap') {
|
|
150
|
+
if (timedOut) {
|
|
151
|
+
return { ok: false, message: LDAP_TIMEOUT_MESSAGE, code: 'ldap_timeout' };
|
|
152
|
+
}
|
|
153
|
+
return { ok: false, message: 'Invalid user credentials' };
|
|
154
|
+
}
|
|
155
|
+
// both → local fallback (also when LDAP user is not linked locally)
|
|
156
|
+
const user = await options.verifyLocal(options.username, options.password);
|
|
157
|
+
if (user)
|
|
158
|
+
return { ok: true, user, method: 'local' };
|
|
159
|
+
if (timedOut) {
|
|
160
|
+
return { ok: false, message: LDAP_TIMEOUT_MESSAGE, code: 'ldap_timeout' };
|
|
161
|
+
}
|
|
162
|
+
return { ok: false, message: 'Invalid user credentials' };
|
|
163
|
+
}
|
|
164
|
+
/** Apply domain groupRoleMap to an identity's groups. */
|
|
165
|
+
export function roleIdsFromLdapIdentity(identity, domain) {
|
|
166
|
+
return mapGroupsToRoleIds(identity.groups, domain.groupRoleMap ?? {});
|
|
167
|
+
}
|
|
168
|
+
function attrValue(entry, name) {
|
|
169
|
+
const raw = entry[name] ?? entry[name.toLowerCase()];
|
|
170
|
+
if (raw == null)
|
|
171
|
+
return undefined;
|
|
172
|
+
if (Array.isArray(raw)) {
|
|
173
|
+
const first = raw[0];
|
|
174
|
+
return first != null ? String(first) : undefined;
|
|
175
|
+
}
|
|
176
|
+
return String(raw);
|
|
177
|
+
}
|
|
178
|
+
function attrValues(entry, name) {
|
|
179
|
+
const raw = entry[name] ?? entry[name.toLowerCase()];
|
|
180
|
+
if (raw == null)
|
|
181
|
+
return [];
|
|
182
|
+
if (Array.isArray(raw)) {
|
|
183
|
+
return raw
|
|
184
|
+
.filter((item) => item != null && String(item).trim() !== '')
|
|
185
|
+
.map((item) => String(item));
|
|
186
|
+
}
|
|
187
|
+
const value = String(raw).trim();
|
|
188
|
+
return value ? [value] : [];
|
|
189
|
+
}
|
|
190
|
+
function buildSearchFilter(template, username) {
|
|
191
|
+
const escaped = username.replace(/[\\*()]/g, (ch) => `\\${ch}`);
|
|
192
|
+
return template.replaceAll('{{username}}', escaped);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Default ldapts-backed client. Requires the optional `ldapts` peer dependency.
|
|
196
|
+
*/
|
|
197
|
+
export function createLdaptsDirectoryClient() {
|
|
198
|
+
return {
|
|
199
|
+
async authenticate(username, password, domain) {
|
|
200
|
+
let Client;
|
|
201
|
+
try {
|
|
202
|
+
({ Client } = await import('ldapts'));
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
throw new Error('LDAP login requires the optional peer dependency "ldapts". Install it in your app.');
|
|
206
|
+
}
|
|
207
|
+
const timeout = domain.timeoutMs ?? 10_000;
|
|
208
|
+
const client = new Client({
|
|
209
|
+
url: domain.url,
|
|
210
|
+
timeout,
|
|
211
|
+
connectTimeout: domain.connectTimeoutMs ?? timeout,
|
|
212
|
+
tlsOptions: domain.tls,
|
|
213
|
+
});
|
|
214
|
+
try {
|
|
215
|
+
if (domain.bindDn) {
|
|
216
|
+
await client.bind(domain.bindDn, domain.bindPassword ?? '');
|
|
217
|
+
}
|
|
218
|
+
const filter = buildSearchFilter(domain.searchFilter || '(uid={{username}})', username);
|
|
219
|
+
const emailAttr = domain.emailAttribute ?? 'mail';
|
|
220
|
+
const nameAttr = domain.nameAttribute ?? 'cn';
|
|
221
|
+
const groupsAttr = domain.groupsAttribute ?? 'memberOf';
|
|
222
|
+
const { searchEntries } = await client.search(domain.searchBase, {
|
|
223
|
+
scope: 'sub',
|
|
224
|
+
filter,
|
|
225
|
+
attributes: [
|
|
226
|
+
'dn',
|
|
227
|
+
'distinguishedName',
|
|
228
|
+
emailAttr,
|
|
229
|
+
nameAttr,
|
|
230
|
+
groupsAttr,
|
|
231
|
+
'uid',
|
|
232
|
+
'sAMAccountName',
|
|
233
|
+
],
|
|
234
|
+
sizeLimit: 1,
|
|
235
|
+
});
|
|
236
|
+
const entry = searchEntries[0];
|
|
237
|
+
if (!entry)
|
|
238
|
+
return null;
|
|
239
|
+
const dn = (typeof entry.dn === 'string' && entry.dn) ||
|
|
240
|
+
attrValue(entry, 'distinguishedName') ||
|
|
241
|
+
attrValue(entry, 'dn');
|
|
242
|
+
if (!dn)
|
|
243
|
+
return null;
|
|
244
|
+
// Re-bind as the user to verify credentials.
|
|
245
|
+
await client.bind(dn, password);
|
|
246
|
+
const groups = attrValues(entry, groupsAttr);
|
|
247
|
+
return {
|
|
248
|
+
provider: 'ldap',
|
|
249
|
+
domainId: domain.id,
|
|
250
|
+
subject: dn,
|
|
251
|
+
username,
|
|
252
|
+
email: attrValue(entry, emailAttr),
|
|
253
|
+
name: attrValue(entry, nameAttr),
|
|
254
|
+
groups,
|
|
255
|
+
raw: { ...entry },
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
if (isLdapTimeoutError(error)) {
|
|
260
|
+
throw new LdapTimeoutError(domain.id, error);
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
try {
|
|
266
|
+
await client.unbind();
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
/* ignore */
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=ldap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldap.js","sourceRoot":"","sources":["../../src/auth/ldap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Session flag set after a successful masquerade login. */
|
|
2
|
+
export declare const MASQUERADE_SESSION_KEY = "shamar_masquerade";
|
|
3
|
+
/**
|
|
4
|
+
* True when a non-empty masquerade password is configured and
|
|
5
|
+
* `NODE_ENV` is not `production`. Production never activates.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isMasqueradeEnabled(config?: {
|
|
8
|
+
auth?: {
|
|
9
|
+
masquerade?: {
|
|
10
|
+
password?: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
} | null, env?: NodeJS.ProcessEnv): boolean;
|
|
14
|
+
/** Timing-safe string compare (false when lengths differ or either is empty). */
|
|
15
|
+
export declare function passwordsMatch(provided: string, expected: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the submitted password matches the configured masquerade
|
|
18
|
+
* password while masquerade is enabled.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isMasqueradePassword(provided: string, config?: {
|
|
21
|
+
auth?: {
|
|
22
|
+
masquerade?: {
|
|
23
|
+
password?: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
} | null, env?: NodeJS.ProcessEnv): boolean;
|
|
27
|
+
/** Read the session flag set at masquerade login. */
|
|
28
|
+
export declare function isMasqueradeSession(session: {
|
|
29
|
+
get?(key: string): unknown;
|
|
30
|
+
}): boolean;
|
|
31
|
+
//# sourceMappingURL=masquerade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masquerade.d.ts","sourceRoot":"","sources":["../../src/auth/masquerade.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,EACjE,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAIT;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,EACjE,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAIT;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B,GAAG,OAAO,CAEV"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
2
|
+
/** Session flag set after a successful masquerade login. */
|
|
3
|
+
export const MASQUERADE_SESSION_KEY = 'shamar_masquerade';
|
|
4
|
+
/**
|
|
5
|
+
* True when a non-empty masquerade password is configured and
|
|
6
|
+
* `NODE_ENV` is not `production`. Production never activates.
|
|
7
|
+
*/
|
|
8
|
+
export function isMasqueradeEnabled(config, env = process.env) {
|
|
9
|
+
if (String(env.NODE_ENV ?? '').toLowerCase() === 'production')
|
|
10
|
+
return false;
|
|
11
|
+
const password = config?.auth?.masquerade?.password;
|
|
12
|
+
return typeof password === 'string' && password.trim() !== '';
|
|
13
|
+
}
|
|
14
|
+
/** Timing-safe string compare (false when lengths differ or either is empty). */
|
|
15
|
+
export function passwordsMatch(provided, expected) {
|
|
16
|
+
const a = Buffer.from(String(provided ?? ''), 'utf8');
|
|
17
|
+
const b = Buffer.from(String(expected ?? ''), 'utf8');
|
|
18
|
+
if (a.length === 0 || b.length === 0 || a.length !== b.length)
|
|
19
|
+
return false;
|
|
20
|
+
return timingSafeEqual(a, b);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether the submitted password matches the configured masquerade
|
|
24
|
+
* password while masquerade is enabled.
|
|
25
|
+
*/
|
|
26
|
+
export function isMasqueradePassword(provided, config, env = process.env) {
|
|
27
|
+
if (!isMasqueradeEnabled(config, env))
|
|
28
|
+
return false;
|
|
29
|
+
const expected = config?.auth?.masquerade?.password ?? '';
|
|
30
|
+
return passwordsMatch(provided, expected);
|
|
31
|
+
}
|
|
32
|
+
/** Read the session flag set at masquerade login. */
|
|
33
|
+
export function isMasqueradeSession(session) {
|
|
34
|
+
return session.get?.(MASQUERADE_SESSION_KEY) === true;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=masquerade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masquerade.js","sourceRoot":"","sources":["../../src/auth/masquerade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAiE,EACjE,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,YAAY;QAAE,OAAO,KAAK,CAAC;IAC5E,MAAM,QAAQ,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC;IACpD,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAChE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAgB;IAC/D,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC5E,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,MAAiE,EACjE,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,QAAQ,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC;IAC1D,OAAO,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,mBAAmB,CAAC,OAEnC;IACC,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AuthLoginMode } from '@shamar/cherubim';
|
|
2
|
+
import type { PanelBranding } from '@shamar/core';
|
|
3
|
+
import { type ShamarBranding } from './shamar/branding.js';
|
|
4
|
+
export interface AuthLoginCopy {
|
|
5
|
+
/** Subtitle under the brand name. */
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
/** Optional hint under the form. Empty/omit hides it. */
|
|
8
|
+
footer?: string;
|
|
9
|
+
/** Placeholder for the username / email field. */
|
|
10
|
+
usernamePlaceholder?: string;
|
|
11
|
+
/** Label for the username / email field. */
|
|
12
|
+
usernameLabel?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AuthLoginViewConfig {
|
|
15
|
+
branding?: PanelBranding;
|
|
16
|
+
auth?: {
|
|
17
|
+
loginMode?: AuthLoginMode | string;
|
|
18
|
+
login?: AuthLoginCopy;
|
|
19
|
+
masquerade?: {
|
|
20
|
+
password?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface AuthLoginViewData {
|
|
25
|
+
loginMode: AuthLoginMode | string;
|
|
26
|
+
branding: ShamarBranding;
|
|
27
|
+
brandingCss: string;
|
|
28
|
+
/** Convenience alias for templates / titles. */
|
|
29
|
+
brandName: string;
|
|
30
|
+
/** Resolved subtitle under the brand. */
|
|
31
|
+
loginSubtitle: string;
|
|
32
|
+
/** Resolved footer hint; empty string means hide. */
|
|
33
|
+
loginFooter: string;
|
|
34
|
+
/** Username / email field label. */
|
|
35
|
+
loginUsernameLabel: string;
|
|
36
|
+
/** Username / email field placeholder. */
|
|
37
|
+
loginUsernamePlaceholder: string;
|
|
38
|
+
/** True when non-production masquerade login is available. */
|
|
39
|
+
masqueradeEnabled: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve login page subtitle / footer / username field copy from config.
|
|
43
|
+
* Footer defaults to empty (hidden).
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveAuthLoginCopy(loginMode?: AuthLoginMode | string, copy?: AuthLoginCopy): {
|
|
46
|
+
subtitle: string;
|
|
47
|
+
footer: string;
|
|
48
|
+
usernameLabel: string;
|
|
49
|
+
usernamePlaceholder: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* View locals for the published Shamar login page.
|
|
53
|
+
* Uses the same branding resolution as the admin shell.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildAuthLoginViewData(config?: AuthLoginViewConfig): AuthLoginViewData;
|
|
56
|
+
//# sourceMappingURL=auth_login_view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth_login_view.d.ts","sourceRoot":"","sources":["../src/auth_login_view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;QACnC,KAAK,CAAC,EAAE,aAAa,CAAC;QACtB,UAAU,CAAC,EAAE;YACX,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,aAAa,GAAG,MAAM,CAAC;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0CAA0C;IAC1C,wBAAwB,EAAE,MAAM,CAAC;IACjC,8DAA8D;IAC9D,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAoBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,GAAE,aAAa,GAAG,MAAgB,EAC3C,IAAI,CAAC,EAAE,aAAa,GACnB;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAgBA;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,mBAAwB,GAAG,iBAAiB,CAkB1F"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isMasqueradeEnabled } from './auth/masquerade.js';
|
|
2
|
+
import { buildBrandingCss, resolveBranding, } from './shamar/branding.js';
|
|
3
|
+
const DEFAULT_SUBTITLES = {
|
|
4
|
+
local: 'Sign in to continue.',
|
|
5
|
+
ldap: 'Sign in with your directory account.',
|
|
6
|
+
both: 'Sign in with your directory or local account.',
|
|
7
|
+
};
|
|
8
|
+
const DEFAULT_USERNAME_LABELS = {
|
|
9
|
+
local: 'Email',
|
|
10
|
+
ldap: 'Email or username',
|
|
11
|
+
both: 'Email or username',
|
|
12
|
+
};
|
|
13
|
+
const DEFAULT_USERNAME_PLACEHOLDERS = {
|
|
14
|
+
local: 'you@example.com',
|
|
15
|
+
ldap: 'user@domain or DOMAIN\\user',
|
|
16
|
+
both: 'user@domain or DOMAIN\\user',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Resolve login page subtitle / footer / username field copy from config.
|
|
20
|
+
* Footer defaults to empty (hidden).
|
|
21
|
+
*/
|
|
22
|
+
export function resolveAuthLoginCopy(loginMode = 'local', copy) {
|
|
23
|
+
const mode = String(loginMode || 'local');
|
|
24
|
+
const subtitle = copy?.subtitle?.trim() ||
|
|
25
|
+
DEFAULT_SUBTITLES[mode] ||
|
|
26
|
+
DEFAULT_SUBTITLES.local;
|
|
27
|
+
const footer = copy?.footer?.trim() ?? '';
|
|
28
|
+
const usernameLabel = copy?.usernameLabel?.trim() ||
|
|
29
|
+
DEFAULT_USERNAME_LABELS[mode] ||
|
|
30
|
+
DEFAULT_USERNAME_LABELS.local;
|
|
31
|
+
const usernamePlaceholder = copy?.usernamePlaceholder?.trim() ||
|
|
32
|
+
DEFAULT_USERNAME_PLACEHOLDERS[mode] ||
|
|
33
|
+
DEFAULT_USERNAME_PLACEHOLDERS.local;
|
|
34
|
+
return { subtitle, footer, usernameLabel, usernamePlaceholder };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* View locals for the published Shamar login page.
|
|
38
|
+
* Uses the same branding resolution as the admin shell.
|
|
39
|
+
*/
|
|
40
|
+
export function buildAuthLoginViewData(config = {}) {
|
|
41
|
+
const loginMode = config.auth?.loginMode ?? 'local';
|
|
42
|
+
const branding = resolveBranding(config.branding);
|
|
43
|
+
const { subtitle, footer, usernameLabel, usernamePlaceholder } = resolveAuthLoginCopy(loginMode, config.auth?.login);
|
|
44
|
+
return {
|
|
45
|
+
loginMode,
|
|
46
|
+
branding,
|
|
47
|
+
brandingCss: buildBrandingCss(branding),
|
|
48
|
+
brandName: branding.brandName,
|
|
49
|
+
loginSubtitle: subtitle,
|
|
50
|
+
loginFooter: footer,
|
|
51
|
+
loginUsernameLabel: usernameLabel,
|
|
52
|
+
loginUsernamePlaceholder: usernamePlaceholder,
|
|
53
|
+
masqueradeEnabled: isMasqueradeEnabled(config),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=auth_login_view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth_login_view.js","sourceRoot":"","sources":["../src/auth_login_view.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAChB,eAAe,GAEhB,MAAM,sBAAsB,CAAC;AA0C9B,MAAM,iBAAiB,GAA2B;IAChD,KAAK,EAAE,sBAAsB;IAC7B,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE,+CAA+C;CACtD,CAAC;AAEF,MAAM,uBAAuB,GAA2B;IACtD,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;CAC1B,CAAC;AAEF,MAAM,6BAA6B,GAA2B;IAC5D,KAAK,EAAE,iBAAiB;IACxB,IAAI,EAAE,6BAA6B;IACnC,IAAI,EAAE,6BAA6B;CACpC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,YAAoC,OAAO,EAC3C,IAAoB;IAOpB,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC;IAC1C,MAAM,QAAQ,GACZ,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtB,iBAAiB,CAAC,IAAI,CAAC;QACvB,iBAAiB,CAAC,KAAM,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1C,MAAM,aAAa,GACjB,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QAC3B,uBAAuB,CAAC,IAAI,CAAC;QAC7B,uBAAuB,CAAC,KAAM,CAAC;IACjC,MAAM,mBAAmB,GACvB,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE;QACjC,6BAA6B,CAAC,IAAI,CAAC;QACnC,6BAA6B,CAAC,KAAM,CAAC;IACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAA8B,EAAE;IACrE,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC;IACpD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,GAAG,oBAAoB,CACnF,SAAS,EACT,MAAM,CAAC,IAAI,EAAE,KAAK,CACnB,CAAC;IACF,OAAO;QACL,SAAS;QACT,QAAQ;QACR,WAAW,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACvC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,aAAa,EAAE,QAAQ;QACvB,WAAW,EAAE,MAAM;QACnB,kBAAkB,EAAE,aAAa;QACjC,wBAAwB,EAAE,mBAAmB;QAC7C,iBAAiB,EAAE,mBAAmB,CAAC,MAAM,CAAC;KAC/C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"commands":[{"commandName":"shamar:publish-auth","description":"Publish opinionated Shamar auth layout and login page into the application","help":"","namespace":"shamar","aliases":[],"flags":[{"name":"force","flagName":"force","required":false,"type":"boolean","description":"Overwrite existing auth views without confirmation","alias":"f"}],"args":[],"options":{},"filePath":"publish_auth.js"}],"version":1}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-memory cache of commands after they have been loaded
|
|
5
|
+
*/
|
|
6
|
+
let commandsMetaData
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Reads the commands from the "./commands.json" file. Since, the commands.json
|
|
10
|
+
* file is generated automatically, we do not have to validate its contents
|
|
11
|
+
*/
|
|
12
|
+
export async function getMetaData() {
|
|
13
|
+
if (commandsMetaData) {
|
|
14
|
+
return commandsMetaData
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const commandsIndex = await readFile(new URL('./commands.json', import.meta.url), 'utf-8')
|
|
18
|
+
commandsMetaData = JSON.parse(commandsIndex).commands
|
|
19
|
+
|
|
20
|
+
return commandsMetaData
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Imports the command by lookingup its path from the commands
|
|
25
|
+
* metadata
|
|
26
|
+
*/
|
|
27
|
+
export async function getCommand(metaData) {
|
|
28
|
+
const commands = await getMetaData()
|
|
29
|
+
const command = commands.find(({ commandName }) => metaData.commandName === commandName)
|
|
30
|
+
if (!command) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { default: commandConstructor } = await import(new URL(command.filePath, import.meta.url).href)
|
|
35
|
+
return commandConstructor
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
import type { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
+
/**
|
|
4
|
+
* Publish the opinionated Shamar login layout + page into the host app.
|
|
5
|
+
*/
|
|
6
|
+
export default class PublishAuth extends BaseCommand {
|
|
7
|
+
static commandName: string;
|
|
8
|
+
static description: string;
|
|
9
|
+
static options: CommandOptions;
|
|
10
|
+
force: boolean;
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=publish_auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish_auth.d.ts","sourceRoot":"","sources":["../../src/commands/publish_auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,MAAM,CAAC,WAAW,SAAyB;IAC3C,MAAM,CAAC,WAAW,SAC6D;IAE/E,MAAM,CAAC,OAAO,EAAE,cAAc,CAAM;IAM5B,KAAK,EAAE,OAAO,CAAC;IAEjB,GAAG;CAGV"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseCommand, flags } from '@adonisjs/core/ace';
|
|
8
|
+
import { publishAuthViews } from '../publish_auth.js';
|
|
9
|
+
/**
|
|
10
|
+
* Publish the opinionated Shamar login layout + page into the host app.
|
|
11
|
+
*/
|
|
12
|
+
export default class PublishAuth extends BaseCommand {
|
|
13
|
+
static commandName = 'shamar:publish-auth';
|
|
14
|
+
static description = 'Publish opinionated Shamar auth layout and login page into the application';
|
|
15
|
+
static options = {};
|
|
16
|
+
async run() {
|
|
17
|
+
await publishAuthViews(this, { force: this.force });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
__decorate([
|
|
21
|
+
flags.boolean({
|
|
22
|
+
description: 'Overwrite existing auth views without confirmation',
|
|
23
|
+
alias: 'f',
|
|
24
|
+
})
|
|
25
|
+
], PublishAuth.prototype, "force", void 0);
|
|
26
|
+
//# sourceMappingURL=publish_auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish_auth.js","sourceRoot":"","sources":["../../src/commands/publish_auth.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,MAAM,CAAC,WAAW,GAAG,qBAAqB,CAAC;IAC3C,MAAM,CAAC,WAAW,GAChB,4EAA4E,CAAC;IAE/E,MAAM,CAAC,OAAO,GAAmB,EAAE,CAAC;IAQpC,KAAK,CAAC,GAAG;QACP,MAAM,gBAAgB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;;AAJO;IAJP,KAAK,CAAC,OAAO,CAAC;QACb,WAAW,EAAE,oDAAoD;QACjE,KAAK,EAAE,GAAG;KACX,CAAC;0CACqB"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { AuthorizerOptions, CherubimUser, RoleResolver } from '@shamar/cherubim';
|
|
1
|
+
import type { AuthLoginMode, AuthorizerOptions, CherubimUser, RoleResolver } from '@shamar/cherubim';
|
|
2
2
|
import type { PolicyClass } from '@shamar/core';
|
|
3
3
|
import type { DataAdapter, PanelConfig, Resource } from '@shamar/core';
|
|
4
4
|
import { panel as createPanel, type PanelBuilder } from '@shamar/core';
|
|
5
5
|
import type { ShamarHttpContext } from './context.js';
|
|
6
|
+
import type { LdapAuthSettings } from './auth/ldap.js';
|
|
6
7
|
export type ShamarOrm = 'lucid' | 'mongoose';
|
|
7
8
|
export interface ShamarConfig {
|
|
8
9
|
/** @deprecated Prefer `panels`. Kept for single-panel apps. */
|
|
@@ -68,6 +69,36 @@ export interface ShamarConfig {
|
|
|
68
69
|
};
|
|
69
70
|
/** Custom principal resolver (overrides guard-based mapping). */
|
|
70
71
|
resolveUser?: (ctx: ShamarHttpContext) => CherubimUser | null | Promise<CherubimUser | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Password login strategy:
|
|
74
|
+
* - `local` — local passwords only (default when no LDAP domains)
|
|
75
|
+
* - `ldap` — LDAP directories only
|
|
76
|
+
* - `both` — try LDAP first, then fall back to local
|
|
77
|
+
*/
|
|
78
|
+
loginMode?: AuthLoginMode;
|
|
79
|
+
/**
|
|
80
|
+
* Copy for the published login page (`buildAuthLoginViewData`).
|
|
81
|
+
* When omitted, sensible mode-based subtitles are used and the footer is hidden.
|
|
82
|
+
*/
|
|
83
|
+
login?: {
|
|
84
|
+
/** Subtitle under the brand name. */
|
|
85
|
+
subtitle?: string;
|
|
86
|
+
/** Optional hint under the form. Empty/omit hides it. */
|
|
87
|
+
footer?: string;
|
|
88
|
+
/** Placeholder for the username / email field. */
|
|
89
|
+
usernamePlaceholder?: string;
|
|
90
|
+
/** Label for the username / email field. */
|
|
91
|
+
usernameLabel?: string;
|
|
92
|
+
};
|
|
93
|
+
/** Multi-domain LDAP directory settings. */
|
|
94
|
+
ldap?: LdapAuthSettings;
|
|
95
|
+
/**
|
|
96
|
+
* Dev-only shared password: login as any existing local user.
|
|
97
|
+
* Ignored unless `NODE_ENV !== 'production'` and `password` is non-empty.
|
|
98
|
+
*/
|
|
99
|
+
masquerade?: {
|
|
100
|
+
password?: string;
|
|
101
|
+
};
|
|
71
102
|
};
|
|
72
103
|
/** Default branding inherited by panels without their own. */
|
|
73
104
|
branding?: PanelConfig['branding'];
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EAET,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|