@alinsafawi/aegis-auth 0.1.3 → 0.1.5
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 +94 -100
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22720,54 +22720,24 @@ async function promptFeatures(roleIds) {
|
|
|
22720
22720
|
${import_chalk5.default.dim("All features can be toggled later in auth.config.ts \u2192 features")}
|
|
22721
22721
|
`
|
|
22722
22722
|
);
|
|
22723
|
-
const
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
|
|
22728
|
-
|
|
22729
|
-
|
|
22730
|
-
|
|
22731
|
-
|
|
22732
|
-
|
|
22733
|
-
|
|
22734
|
-
|
|
22735
|
-
|
|
22736
|
-
|
|
22737
|
-
value: "passwordReset",
|
|
22738
|
-
label: "Password Reset",
|
|
22739
|
-
hint: '"Forgot password" via email'
|
|
22740
|
-
},
|
|
22741
|
-
{
|
|
22742
|
-
value: "accountLockout",
|
|
22743
|
-
label: "Account Lockout",
|
|
22744
|
-
hint: "per-account, not per-IP \u2014 locks after failed logins"
|
|
22745
|
-
},
|
|
22746
|
-
{
|
|
22747
|
-
value: "apiKeys",
|
|
22748
|
-
label: "API Keys",
|
|
22749
|
-
hint: "users generate keys for programmatic access"
|
|
22750
|
-
},
|
|
22751
|
-
{
|
|
22752
|
-
value: "auditLog",
|
|
22753
|
-
label: "Audit Log",
|
|
22754
|
-
hint: "records every auth event to a DB table"
|
|
22755
|
-
},
|
|
22756
|
-
{
|
|
22757
|
-
value: "sessionTracking",
|
|
22758
|
-
label: "Session Tracking",
|
|
22759
|
-
hint: '"Sign out all devices" \u2014 without this, JWTs are stateless'
|
|
22760
|
-
}
|
|
22761
|
-
],
|
|
22762
|
-
initialValues: ["twoFactor", "emailVerification", "passwordReset", "accountLockout"],
|
|
22763
|
-
required: false
|
|
22764
|
-
});
|
|
22765
|
-
if (p4.isCancel(selected)) process.exit(0);
|
|
22766
|
-
const has = (f) => selected.includes(f);
|
|
22723
|
+
const twoFactor = await p4.confirm({ message: "Two-Factor Authentication (TOTP via Authy, 1Password + backup codes)", initialValue: true });
|
|
22724
|
+
if (p4.isCancel(twoFactor)) process.exit(0);
|
|
22725
|
+
const emailVerification = await p4.confirm({ message: "Email Verification (6-digit code, 15 min expiry, resend flow)", initialValue: true });
|
|
22726
|
+
if (p4.isCancel(emailVerification)) process.exit(0);
|
|
22727
|
+
const passwordReset = await p4.confirm({ message: 'Password Reset ("Forgot password" via email)', initialValue: true });
|
|
22728
|
+
if (p4.isCancel(passwordReset)) process.exit(0);
|
|
22729
|
+
const accountLockout = await p4.confirm({ message: "Account Lockout (locks after N failed logins, per-account)", initialValue: true });
|
|
22730
|
+
if (p4.isCancel(accountLockout)) process.exit(0);
|
|
22731
|
+
const apiKeys = await p4.confirm({ message: "API Keys (users generate keys for programmatic access)", initialValue: false });
|
|
22732
|
+
if (p4.isCancel(apiKeys)) process.exit(0);
|
|
22733
|
+
const auditLog = await p4.confirm({ message: "Audit Log (records every auth event to a DB table)", initialValue: false });
|
|
22734
|
+
if (p4.isCancel(auditLog)) process.exit(0);
|
|
22735
|
+
const sessionTracking = await p4.confirm({ message: 'Session Tracking ("Sign out all devices" \u2014 without this, JWTs are stateless)', initialValue: false });
|
|
22736
|
+
if (p4.isCancel(sessionTracking)) process.exit(0);
|
|
22767
22737
|
let lockoutAttempts = 5;
|
|
22768
22738
|
let lockoutMinutes = 15;
|
|
22769
22739
|
let enforced2FARoles = [];
|
|
22770
|
-
if (
|
|
22740
|
+
if (accountLockout) {
|
|
22771
22741
|
console.log(
|
|
22772
22742
|
`
|
|
22773
22743
|
${import_chalk5.default.dim("\u2500 Account Lockout Settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
@@ -22798,7 +22768,7 @@ async function promptFeatures(roleIds) {
|
|
|
22798
22768
|
if (p4.isCancel(duration)) process.exit(0);
|
|
22799
22769
|
lockoutMinutes = duration;
|
|
22800
22770
|
}
|
|
22801
|
-
if (
|
|
22771
|
+
if (twoFactor && roleIds.length > 0) {
|
|
22802
22772
|
console.log(
|
|
22803
22773
|
`
|
|
22804
22774
|
${import_chalk5.default.dim("\u2500 2FA Enforcement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
|
|
@@ -22809,17 +22779,14 @@ async function promptFeatures(roleIds) {
|
|
|
22809
22779
|
${import_chalk5.default.dim("access the app until setup is complete.")}
|
|
22810
22780
|
`
|
|
22811
22781
|
);
|
|
22812
|
-
const
|
|
22813
|
-
|
|
22814
|
-
|
|
22815
|
-
|
|
22816
|
-
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
});
|
|
22821
|
-
if (p4.isCancel(enforced)) process.exit(0);
|
|
22822
|
-
enforced2FARoles = enforced.filter((r) => r !== "__none__");
|
|
22782
|
+
for (const roleId of roleIds) {
|
|
22783
|
+
const enforce = await p4.confirm({
|
|
22784
|
+
message: `Require 2FA for role "${roleId}"?`,
|
|
22785
|
+
initialValue: false
|
|
22786
|
+
});
|
|
22787
|
+
if (p4.isCancel(enforce)) process.exit(0);
|
|
22788
|
+
if (enforce) enforced2FARoles.push(roleId);
|
|
22789
|
+
}
|
|
22823
22790
|
}
|
|
22824
22791
|
console.log(
|
|
22825
22792
|
`
|
|
@@ -22858,15 +22825,15 @@ async function promptFeatures(roleIds) {
|
|
|
22858
22825
|
});
|
|
22859
22826
|
if (p4.isCancel(reuse)) process.exit(0);
|
|
22860
22827
|
return {
|
|
22861
|
-
twoFactor
|
|
22862
|
-
emailVerification
|
|
22863
|
-
passwordReset
|
|
22864
|
-
accountLockout
|
|
22828
|
+
twoFactor,
|
|
22829
|
+
emailVerification,
|
|
22830
|
+
passwordReset,
|
|
22831
|
+
accountLockout,
|
|
22865
22832
|
lockoutAttempts,
|
|
22866
22833
|
lockoutMinutes,
|
|
22867
|
-
apiKeys
|
|
22868
|
-
auditLog
|
|
22869
|
-
sessionTracking
|
|
22834
|
+
apiKeys,
|
|
22835
|
+
auditLog,
|
|
22836
|
+
sessionTracking,
|
|
22870
22837
|
enforced2FARoles,
|
|
22871
22838
|
minPasswordLength: Number(minLen),
|
|
22872
22839
|
passwordExpiry: expiry,
|
|
@@ -23840,48 +23807,75 @@ async function runInit() {
|
|
|
23840
23807
|
`);
|
|
23841
23808
|
}
|
|
23842
23809
|
printSection(mode === "new" ? `STEP 2 of ${STEPS.length} \u25B8 PROJECT \u2713 \u25B8 APP` : `STEP 1 of ${STEPS.length - 1} \u25B8 APP`);
|
|
23843
|
-
|
|
23810
|
+
let app = await promptApp(projectName);
|
|
23844
23811
|
printSection(mode === "new" ? `STEP 3 of ${STEPS.length} \u25B8 PROJECT \u2713 APP \u2713 \u25B8 ROLES` : `STEP 2 \u25B8 APP \u2713 \u25B8 ROLES`);
|
|
23845
|
-
|
|
23812
|
+
let roles = await promptRoles();
|
|
23846
23813
|
printSection(mode === "new" ? `STEP 4 of ${STEPS.length} \u25B8 ... ROLES \u2713 \u25B8 FEATURES` : `STEP 3 \u25B8 ROLES \u2713 \u25B8 FEATURES`);
|
|
23847
|
-
|
|
23814
|
+
let features = await promptFeatures(Object.keys(roles));
|
|
23848
23815
|
printSection(mode === "new" ? `STEP 5 of ${STEPS.length} \u25B8 ... FEATURES \u2713 \u25B8 INFRA` : `STEP 4 \u25B8 FEATURES \u2713 \u25B8 INFRA`);
|
|
23849
|
-
|
|
23816
|
+
let infra = await promptInfrastructure();
|
|
23850
23817
|
printSection(mode === "new" ? `STEP 6 of ${STEPS.length} \u25B8 ... INFRA \u2713 \u25B8 STYLE` : `STEP 5 \u25B8 INFRA \u2713 \u25B8 STYLE`);
|
|
23851
|
-
|
|
23852
|
-
|
|
23853
|
-
|
|
23818
|
+
let style = await promptStyle();
|
|
23819
|
+
let isDry = false;
|
|
23820
|
+
while (true) {
|
|
23821
|
+
printSection("REVIEW \xB7 Everything that's about to happen");
|
|
23822
|
+
console.log(` ${import_chalk8.default.bold("Configuration")}
|
|
23854
23823
|
`);
|
|
23855
|
-
|
|
23856
|
-
|
|
23857
|
-
|
|
23858
|
-
|
|
23859
|
-
|
|
23860
|
-
|
|
23861
|
-
|
|
23862
|
-
|
|
23863
|
-
|
|
23864
|
-
|
|
23865
|
-
|
|
23866
|
-
|
|
23867
|
-
|
|
23868
|
-
|
|
23869
|
-
|
|
23870
|
-
|
|
23871
|
-
|
|
23872
|
-
|
|
23873
|
-
|
|
23874
|
-
|
|
23875
|
-
|
|
23876
|
-
|
|
23877
|
-
|
|
23878
|
-
|
|
23879
|
-
|
|
23880
|
-
|
|
23881
|
-
p7.
|
|
23882
|
-
|
|
23824
|
+
console.log(` App ${import_chalk8.default.cyan(app.appName)}`);
|
|
23825
|
+
console.log(` Cookie prefix ${import_chalk8.default.cyan(app.cookiePrefix)}`);
|
|
23826
|
+
console.log(` Session ${import_chalk8.default.cyan(app.sessionDuration / 3600 + " hours")}`);
|
|
23827
|
+
if (mode === "new") {
|
|
23828
|
+
console.log(` Language ${import_chalk8.default.cyan(language)}`);
|
|
23829
|
+
console.log(` Package manager ${import_chalk8.default.cyan(packageManager)}`);
|
|
23830
|
+
console.log(` Database ${import_chalk8.default.cyan(database)}`);
|
|
23831
|
+
}
|
|
23832
|
+
console.log();
|
|
23833
|
+
console.log(` ${import_chalk8.default.bold("Roles")}`);
|
|
23834
|
+
for (const [id, role] of Object.entries(roles)) {
|
|
23835
|
+
console.log(` ${import_chalk8.default.dim("\xB7")} ${import_chalk8.default.magentaBright(id)} ${import_chalk8.default.dim("\u2192")} ${role.prismaModel} ${import_chalk8.default.dim("(")}${role.loginField}${import_chalk8.default.dim(")")}`);
|
|
23836
|
+
}
|
|
23837
|
+
console.log();
|
|
23838
|
+
const onFeatures = Object.entries(features).filter(([k, v]) => v === true && ["twoFactor", "emailVerification", "passwordReset", "accountLockout", "apiKeys", "auditLog", "sessionTracking"].includes(k)).map(([k]) => k);
|
|
23839
|
+
console.log(` ${import_chalk8.default.bold("Features")} ${onFeatures.map((f) => import_chalk8.default.cyan(f)).join(import_chalk8.default.dim(" \xB7 "))}`);
|
|
23840
|
+
console.log();
|
|
23841
|
+
const action = await p7.select({
|
|
23842
|
+
message: "Proceed?",
|
|
23843
|
+
options: [
|
|
23844
|
+
{ value: "go", label: mode === "new" ? "Create project" : "Create files" },
|
|
23845
|
+
{ value: "dry", label: "Dry run \u2014 show me what will be created without writing" },
|
|
23846
|
+
{ value: "edit", label: "Edit a section" },
|
|
23847
|
+
{ value: "no", label: "Cancel" }
|
|
23848
|
+
]
|
|
23849
|
+
});
|
|
23850
|
+
if (p7.isCancel(action) || action === "no") {
|
|
23851
|
+
p7.cancel("Cancelled.");
|
|
23852
|
+
process.exit(0);
|
|
23853
|
+
}
|
|
23854
|
+
if (action === "edit") {
|
|
23855
|
+
const section = await p7.select({
|
|
23856
|
+
message: "Which section would you like to change?",
|
|
23857
|
+
options: [
|
|
23858
|
+
{ value: "app", label: "App identity (name, cookie prefix, session duration)" },
|
|
23859
|
+
{ value: "roles", label: "Roles" },
|
|
23860
|
+
{ value: "features", label: "Features" },
|
|
23861
|
+
{ value: "infra", label: "Infrastructure (SMTP, rate limiting)" },
|
|
23862
|
+
{ value: "style", label: "Style (primary colour, logo)" }
|
|
23863
|
+
]
|
|
23864
|
+
});
|
|
23865
|
+
if (p7.isCancel(section)) {
|
|
23866
|
+
p7.cancel("Cancelled.");
|
|
23867
|
+
process.exit(0);
|
|
23868
|
+
}
|
|
23869
|
+
if (section === "app") app = await promptApp(projectName);
|
|
23870
|
+
if (section === "roles") roles = await promptRoles();
|
|
23871
|
+
if (section === "features") features = await promptFeatures(Object.keys(roles));
|
|
23872
|
+
if (section === "infra") infra = await promptInfrastructure();
|
|
23873
|
+
if (section === "style") style = await promptStyle();
|
|
23874
|
+
continue;
|
|
23875
|
+
}
|
|
23876
|
+
isDry = action === "dry";
|
|
23877
|
+
break;
|
|
23883
23878
|
}
|
|
23884
|
-
const isDry = confirm4 === "dry";
|
|
23885
23879
|
printSection(mode === "new" ? `BUILDING ${projectName}` : "INSTALLING");
|
|
23886
23880
|
const spin = p7.spinner();
|
|
23887
23881
|
async function writeFile(relPath, content) {
|