deploro 0.3.2 → 0.3.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/dist/index.js +148 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -391,6 +391,21 @@ async function authInviteCommand(email, opts) {
|
|
|
391
391
|
console.log(` Accept URL: ${data.acceptUrl}`);
|
|
392
392
|
}
|
|
393
393
|
}
|
|
394
|
+
async function authSiteUrlCommand(url, opts) {
|
|
395
|
+
const config = requireProject();
|
|
396
|
+
if (!url && !opts.clear) {
|
|
397
|
+
const data2 = await apiRequest(
|
|
398
|
+
`/api/projects/${config.projectId}/auth/settings`
|
|
399
|
+
);
|
|
400
|
+
console.log(data2.site_url ?? "(not set \u2014 confirmation links fall back to this project's own deployment URL)");
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const data = await apiRequest(
|
|
404
|
+
`/api/projects/${config.projectId}/auth/settings`,
|
|
405
|
+
{ method: "PUT", body: JSON.stringify({ site_url: opts.clear ? null : url }) }
|
|
406
|
+
);
|
|
407
|
+
console.log(opts.clear ? "\u2713 Site URL cleared" : `\u2713 Site URL set to ${data.site_url}`);
|
|
408
|
+
}
|
|
394
409
|
async function authWhoamiCommand() {
|
|
395
410
|
requireConfig();
|
|
396
411
|
const data = await apiRequestNoProject("/api/auth/whoami");
|
|
@@ -478,6 +493,128 @@ async function tokenRevokeCommand(id, opts) {
|
|
|
478
493
|
await apiRequestNoProject(`/api/auth/tokens/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
479
494
|
console.log(`\u2713 Token ${id} revoked`);
|
|
480
495
|
}
|
|
496
|
+
function isEmailProvider(provider) {
|
|
497
|
+
return provider === "email" || provider === "email_password";
|
|
498
|
+
}
|
|
499
|
+
async function authProvidersListCommand() {
|
|
500
|
+
const config = requireProject();
|
|
501
|
+
const data = await apiRequest(
|
|
502
|
+
`/api/projects/${config.projectId}/auth/providers`
|
|
503
|
+
);
|
|
504
|
+
const known = [
|
|
505
|
+
"email",
|
|
506
|
+
"email_password",
|
|
507
|
+
"google",
|
|
508
|
+
"github",
|
|
509
|
+
"facebook",
|
|
510
|
+
"twitter",
|
|
511
|
+
"discord",
|
|
512
|
+
"microsoft",
|
|
513
|
+
"linkedin",
|
|
514
|
+
"slack",
|
|
515
|
+
"gitlab",
|
|
516
|
+
"twitch",
|
|
517
|
+
"spotify",
|
|
518
|
+
"reddit",
|
|
519
|
+
"dropbox",
|
|
520
|
+
"notion",
|
|
521
|
+
"apple"
|
|
522
|
+
];
|
|
523
|
+
const byProvider = new Map(data.providers.map((p) => [p.provider, p]));
|
|
524
|
+
const rows = known.map((provider) => {
|
|
525
|
+
const row = byProvider.get(provider);
|
|
526
|
+
const enabled = row?.enabled ?? false;
|
|
527
|
+
const configured = isEmailProvider(provider) || !!(row?.client_id && row?.client_secret);
|
|
528
|
+
return {
|
|
529
|
+
provider,
|
|
530
|
+
status: enabled && configured ? "active" : enabled ? "setup required" : "disabled"
|
|
531
|
+
};
|
|
532
|
+
});
|
|
533
|
+
table(rows);
|
|
534
|
+
}
|
|
535
|
+
async function authProviderEnableCommand(provider, enabled) {
|
|
536
|
+
const config = requireProject();
|
|
537
|
+
await apiRequest(
|
|
538
|
+
`/api/projects/${config.projectId}/auth/providers/${encodeURIComponent(provider)}`,
|
|
539
|
+
{ method: "PUT", body: JSON.stringify({ enabled }) }
|
|
540
|
+
);
|
|
541
|
+
console.log(`\u2713 ${provider} ${enabled ? "enabled" : "disabled"}`);
|
|
542
|
+
}
|
|
543
|
+
async function authProviderConfigureCommand(provider, opts) {
|
|
544
|
+
const config = requireProject();
|
|
545
|
+
if (isEmailProvider(provider)) {
|
|
546
|
+
console.error(
|
|
547
|
+
`'${provider}' doesn't take OAuth credentials \u2014 it just needs enabling.
|
|
548
|
+
Run: deploro auth providers enable ${provider}`
|
|
549
|
+
);
|
|
550
|
+
process.exit(1);
|
|
551
|
+
}
|
|
552
|
+
if (!opts.clientId || !opts.clientSecret) {
|
|
553
|
+
console.error("Both --client-id and --client-secret are required.");
|
|
554
|
+
process.exit(1);
|
|
555
|
+
}
|
|
556
|
+
if (provider === "apple" && (!opts.teamId || !opts.keyId)) {
|
|
557
|
+
console.error("Apple also requires --team-id and --key-id (--client-secret is the .p8 private key contents).");
|
|
558
|
+
process.exit(1);
|
|
559
|
+
}
|
|
560
|
+
await apiRequest(
|
|
561
|
+
`/api/projects/${config.projectId}/auth/providers/${encodeURIComponent(provider)}`,
|
|
562
|
+
{
|
|
563
|
+
method: "PUT",
|
|
564
|
+
body: JSON.stringify({
|
|
565
|
+
client_id: opts.clientId,
|
|
566
|
+
client_secret: opts.clientSecret,
|
|
567
|
+
...provider === "apple" ? { extra_config: { team_id: opts.teamId, key_id: opts.keyId } } : {}
|
|
568
|
+
})
|
|
569
|
+
}
|
|
570
|
+
);
|
|
571
|
+
console.log(`\u2713 ${provider} credentials saved (still needs enabling \u2014 run: deploro auth providers enable ${provider})`);
|
|
572
|
+
}
|
|
573
|
+
async function authEndUsersListCommand(opts) {
|
|
574
|
+
const config = requireProject();
|
|
575
|
+
const page = Math.max(1, Number(opts.page ?? 1) || 1);
|
|
576
|
+
const data = await apiRequest(
|
|
577
|
+
`/api/projects/${config.projectId}/auth/users?page=${page}`
|
|
578
|
+
);
|
|
579
|
+
table(
|
|
580
|
+
data.users.map((u) => ({
|
|
581
|
+
id: u.id,
|
|
582
|
+
email: u.email ?? "",
|
|
583
|
+
name: u.name ?? "",
|
|
584
|
+
methods: u.providers.join(", "),
|
|
585
|
+
verified: u.email_verified,
|
|
586
|
+
lastLogin: u.last_login_at ? u.last_login_at.slice(0, 10) : "never"
|
|
587
|
+
}))
|
|
588
|
+
);
|
|
589
|
+
console.log(`
|
|
590
|
+
${data.total} total end user(s), page ${data.page}`);
|
|
591
|
+
}
|
|
592
|
+
async function authEndUserAddCommand(email, opts) {
|
|
593
|
+
const config = requireProject();
|
|
594
|
+
const data = await apiRequest(
|
|
595
|
+
`/api/projects/${config.projectId}/auth/users`,
|
|
596
|
+
{ method: "POST", body: JSON.stringify({ email, name: opts.name }) }
|
|
597
|
+
);
|
|
598
|
+
console.log(`\u2713 Added ${data.user.email}`);
|
|
599
|
+
console.log(" A confirmation email was sent \u2014 they can't sign in until they click the link (one time, first use only).");
|
|
600
|
+
}
|
|
601
|
+
async function authEndUserDeleteCommand(id, opts) {
|
|
602
|
+
const config = requireProject();
|
|
603
|
+
await confirmOrDie(`Delete end user ${id}? This removes every sign-in method and session linked to them.`, opts.yes);
|
|
604
|
+
await apiRequest(`/api/projects/${config.projectId}/auth/users/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
605
|
+
console.log(`\u2713 End user ${id} deleted`);
|
|
606
|
+
}
|
|
607
|
+
async function authStatsCommand() {
|
|
608
|
+
const config = requireProject();
|
|
609
|
+
const data = await apiRequest(`/api/projects/${config.projectId}/auth/stats`);
|
|
610
|
+
console.log(`Total end users : ${data.total_users}`);
|
|
611
|
+
console.log(`Active sessions : ${data.sessions_active}`);
|
|
612
|
+
console.log(`Providers enabled : ${data.providers_enabled}`);
|
|
613
|
+
if (data.users_by_provider.length > 0) {
|
|
614
|
+
console.log("\nBy sign-in method:");
|
|
615
|
+
table(data.users_by_provider.map((p) => ({ provider: p.provider, users: p.count })));
|
|
616
|
+
}
|
|
617
|
+
}
|
|
481
618
|
|
|
482
619
|
// src/commands/migrate.ts
|
|
483
620
|
import { readFileSync as readFileSync2 } from "fs";
|
|
@@ -835,6 +972,17 @@ var auth = program.command("auth").description("Auth management commands");
|
|
|
835
972
|
auth.command("whoami").description("Show the current identity, and \u2014 for a token login \u2014 exactly what it's scoped to").action(authWhoamiCommand);
|
|
836
973
|
auth.command("users").description("List platform users").action(authUsersCommand);
|
|
837
974
|
auth.command("invite <email>").description("Invite a user by email").option("--admin", "Grant admin role").action(authInviteCommand);
|
|
975
|
+
auth.command("site-url [url]").description("Get or set the active project's Auth Site URL (where end-user confirmation-email links redirect back to)").option("--clear", "Clear the Site URL \u2014 confirmation links fall back to the project's own deployment URL").action(authSiteUrlCommand);
|
|
976
|
+
auth.command("stats").description("Show Auth-as-a-Service stats for the active project's end users").action(authStatsCommand);
|
|
977
|
+
var authProviders = auth.command("providers").description("Manage the active project's end-user sign-in providers");
|
|
978
|
+
authProviders.command("list").description("List sign-in providers and their status").action(authProvidersListCommand);
|
|
979
|
+
authProviders.command("enable <provider>").description("Enable a sign-in provider (e.g. email, email_password, google, github, apple, ...)").action((provider) => authProviderEnableCommand(provider, true));
|
|
980
|
+
authProviders.command("disable <provider>").description("Disable a sign-in provider").action((provider) => authProviderEnableCommand(provider, false));
|
|
981
|
+
authProviders.command("configure <provider>").description("Set OAuth client credentials for a provider (not applicable to email / email_password)").option("--client-id <id>", "OAuth client ID").option("--client-secret <secret>", "OAuth client secret (Apple: the .p8 private key contents)").option("--team-id <id>", "Apple only \u2014 Team ID").option("--key-id <id>", "Apple only \u2014 Key ID").action(authProviderConfigureCommand);
|
|
982
|
+
var authEndUsers = auth.command("end-users").description("Manage the active project's end users (your app's sign-ups)");
|
|
983
|
+
authEndUsers.command("list").description("List end users").option("--page <n>", "Page number", "1").action(authEndUsersListCommand);
|
|
984
|
+
authEndUsers.command("add <email>").description("Manually add an end user \u2014 sends a confirmation email; they can't sign in until they click it").option("--name <name>", "Display name").action(authEndUserAddCommand);
|
|
985
|
+
authEndUsers.command("delete <id>").description("Delete an end user and all their sign-in methods/sessions").option("--yes", "Skip confirmation prompt").action(authEndUserDeleteCommand);
|
|
838
986
|
var token = program.command("token").description("Personal access token commands");
|
|
839
987
|
token.command("list").description("List your personal access tokens").action(tokenListCommand);
|
|
840
988
|
token.command("create <name>").description("Create a new project-scoped personal access token").option("--read", "Grant read scope").option("--write", "Grant write scope").option("--project <slugs>", "Comma-separated project slugs/ids/names (defaults to the active project)").option("--days <n>", "Expiry in days (1-365)", "90").action(tokenCreateCommand);
|
package/package.json
CHANGED