@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.
Files changed (2) hide show
  1. package/dist/index.js +94 -100
  2. 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 selected = await p4.multiselect({
22724
- message: "Which security features do you want?",
22725
- options: [
22726
- {
22727
- value: "twoFactor",
22728
- label: "Two-Factor Authentication",
22729
- hint: "TOTP (Authy, 1Password) + backup codes"
22730
- },
22731
- {
22732
- value: "emailVerification",
22733
- label: "Email Verification",
22734
- hint: "6-digit code, 15 min expiry, resend flow"
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 (has("accountLockout")) {
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 (has("twoFactor") && roleIds.length > 0) {
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 enforced = await p4.multiselect({
22813
- message: "Require 2FA for any roles? (cannot be skipped)",
22814
- options: [
22815
- { value: "__none__", label: "No role requires it" },
22816
- ...roleIds.map((id) => ({ value: id, label: id }))
22817
- ],
22818
- initialValues: ["__none__"],
22819
- required: false
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: has("twoFactor"),
22862
- emailVerification: has("emailVerification"),
22863
- passwordReset: has("passwordReset"),
22864
- accountLockout: has("accountLockout"),
22828
+ twoFactor,
22829
+ emailVerification,
22830
+ passwordReset,
22831
+ accountLockout,
22865
22832
  lockoutAttempts,
22866
22833
  lockoutMinutes,
22867
- apiKeys: has("apiKeys"),
22868
- auditLog: has("auditLog"),
22869
- sessionTracking: has("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
- const app = await promptApp(projectName);
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
- const roles = await promptRoles();
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
- const features = await promptFeatures(Object.keys(roles));
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
- const infra = await promptInfrastructure();
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
- const style = await promptStyle();
23852
- printSection("REVIEW \xB7 Everything that's about to happen");
23853
- console.log(` ${import_chalk8.default.bold("Configuration")}
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
- console.log(` App ${import_chalk8.default.cyan(app.appName)}`);
23856
- console.log(` Cookie prefix ${import_chalk8.default.cyan(app.cookiePrefix)}`);
23857
- console.log(` Session ${import_chalk8.default.cyan(app.sessionDuration / 3600 + " hours")}`);
23858
- if (mode === "new") {
23859
- console.log(` Language ${import_chalk8.default.cyan(language)}`);
23860
- console.log(` Package manager ${import_chalk8.default.cyan(packageManager)}`);
23861
- console.log(` Database ${import_chalk8.default.cyan(database)}`);
23862
- }
23863
- console.log();
23864
- console.log(` ${import_chalk8.default.bold("Roles")}`);
23865
- for (const [id, role] of Object.entries(roles)) {
23866
- 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(")")}`);
23867
- }
23868
- console.log();
23869
- const onFeatures = Object.entries(features).filter(([k, v]) => v === true && ["twoFactor", "emailVerification", "passwordReset", "accountLockout", "apiKeys", "auditLog", "sessionTracking"].includes(k)).map(([k]) => k);
23870
- console.log(` ${import_chalk8.default.bold("Features")} ${onFeatures.map((f) => import_chalk8.default.cyan(f)).join(import_chalk8.default.dim(" \xB7 "))}`);
23871
- console.log();
23872
- const confirm4 = await p7.select({
23873
- message: "Proceed?",
23874
- options: [
23875
- { value: "go", label: mode === "new" ? "Create project" : "Create files" },
23876
- { value: "dry", label: "Dry run \u2014 show me what will be created without writing" },
23877
- { value: "no", label: "Cancel" }
23878
- ]
23879
- });
23880
- if (p7.isCancel(confirm4) || confirm4 === "no") {
23881
- p7.cancel("Cancelled.");
23882
- process.exit(0);
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alinsafawi/aegis-auth",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "The shield your Next.js app deserves — full-stack auth in minutes",
5
5
  "bin": {
6
6
  "aegis-auth": "dist/index.js"