nixamp 0.5.0 → 0.5.1

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.
@@ -46,6 +46,23 @@ export interface AuthLike {
46
46
  export declare function readResult(value: unknown): AuthResult;
47
47
  /** `validateToken` answers claims directly, unlike login and register. */
48
48
  export declare function readClaims(value: unknown): Account | null;
49
+ /**
50
+ * How short a password may be, and what it must contain.
51
+ *
52
+ * Eight characters, a number somewhere in it, and no requirement about case.
53
+ * That is deliberately weaker than it was: the composition rules were the kind
54
+ * that make people write a password down, and a password is no longer the only
55
+ * way in -- a provider or a token is a better one, and is what the CLI offers
56
+ * first. What this floor is really for is keeping a one-character password out
57
+ * of the database, not pretending eight digits are strong.
58
+ */
59
+ export declare const PASSWORD_RULES: {
60
+ readonly minLength: 8;
61
+ readonly requireUppercase: false;
62
+ readonly requireLowercase: false;
63
+ readonly requireNumbers: true;
64
+ readonly requireSpecialChars: false;
65
+ };
49
66
  /** An address that could exist, and a password long enough to be worth having. */
50
67
  export declare function checkCredentials(email: unknown, password: unknown): string;
51
68
  export declare class Accounts {
package/dist/accounts.js CHANGED
@@ -47,16 +47,35 @@ export function readClaims(value) {
47
47
  const email = typeof claims["email"] === "string" ? claims["email"] : "";
48
48
  return id ? { id, email } : null;
49
49
  }
50
+ /**
51
+ * How short a password may be, and what it must contain.
52
+ *
53
+ * Eight characters, a number somewhere in it, and no requirement about case.
54
+ * That is deliberately weaker than it was: the composition rules were the kind
55
+ * that make people write a password down, and a password is no longer the only
56
+ * way in -- a provider or a token is a better one, and is what the CLI offers
57
+ * first. What this floor is really for is keeping a one-character password out
58
+ * of the database, not pretending eight digits are strong.
59
+ */
60
+ export const PASSWORD_RULES = {
61
+ minLength: 8,
62
+ requireUppercase: false,
63
+ requireLowercase: false,
64
+ requireNumbers: true,
65
+ requireSpecialChars: false,
66
+ };
50
67
  /** An address that could exist, and a password long enough to be worth having. */
51
68
  export function checkCredentials(email, password) {
52
69
  if (typeof email !== "string" || !/^[^@\s]+@[^@\s.]+\.[^@\s]+$/.test(email)) {
53
70
  return "that does not look like an email address";
54
71
  }
55
- if (typeof password !== "string" || password.length < 10) {
72
+ if (typeof password !== "string" || password.length < PASSWORD_RULES.minLength) {
56
73
  // Length is checked here so a hopeless password never reaches the
57
74
  // database. The auth module then applies its own composition rules on top,
58
- // and its refusals are passed through rather than swallowed.
59
- return "a password needs at least 10 characters";
75
+ // and its refusals are passed through rather than swallowed -- which is why
76
+ // the two have to agree about the minimum, or a password this accepts is
77
+ // refused a layer down with a different sentence.
78
+ return `a password needs at least ${PASSWORD_RULES.minLength} characters`;
60
79
  }
61
80
  if (password.length > 200)
62
81
  return "that password is too long";
@@ -80,6 +99,10 @@ export class Accounts {
80
99
  createAuthSystem({
81
100
  adapter,
82
101
  jwtSecret: options.secret,
102
+ // The module defaults to requiring an uppercase and a lowercase
103
+ // letter. Its rules have to match the ones checked above, or a password
104
+ // this accepts is refused a layer down in a different sentence.
105
+ passwordOptions: { ...PASSWORD_RULES },
83
106
  });
84
107
  this.tokens = adapter ? new Tokens(adapter) : null;
85
108
  this.identities = adapter ? new Identities(adapter, adapter) : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nixamp",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "It really whips the terminal's ass. A Winamp-shaped audio player for your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/accounts.ts CHANGED
@@ -90,16 +90,36 @@ export function readClaims(value: unknown): Account | null {
90
90
  return id ? { id, email } : null;
91
91
  }
92
92
 
93
+ /**
94
+ * How short a password may be, and what it must contain.
95
+ *
96
+ * Eight characters, a number somewhere in it, and no requirement about case.
97
+ * That is deliberately weaker than it was: the composition rules were the kind
98
+ * that make people write a password down, and a password is no longer the only
99
+ * way in -- a provider or a token is a better one, and is what the CLI offers
100
+ * first. What this floor is really for is keeping a one-character password out
101
+ * of the database, not pretending eight digits are strong.
102
+ */
103
+ export const PASSWORD_RULES = {
104
+ minLength: 8,
105
+ requireUppercase: false,
106
+ requireLowercase: false,
107
+ requireNumbers: true,
108
+ requireSpecialChars: false,
109
+ } as const;
110
+
93
111
  /** An address that could exist, and a password long enough to be worth having. */
94
112
  export function checkCredentials(email: unknown, password: unknown): string {
95
113
  if (typeof email !== "string" || !/^[^@\s]+@[^@\s.]+\.[^@\s]+$/.test(email)) {
96
114
  return "that does not look like an email address";
97
115
  }
98
- if (typeof password !== "string" || password.length < 10) {
116
+ if (typeof password !== "string" || password.length < PASSWORD_RULES.minLength) {
99
117
  // Length is checked here so a hopeless password never reaches the
100
118
  // database. The auth module then applies its own composition rules on top,
101
- // and its refusals are passed through rather than swallowed.
102
- return "a password needs at least 10 characters";
119
+ // and its refusals are passed through rather than swallowed -- which is why
120
+ // the two have to agree about the minimum, or a password this accepts is
121
+ // refused a layer down with a different sentence.
122
+ return `a password needs at least ${PASSWORD_RULES.minLength} characters`;
103
123
  }
104
124
  if (password.length > 200) return "that password is too long";
105
125
  return "";
@@ -125,6 +145,10 @@ export class Accounts {
125
145
  (createAuthSystem({
126
146
  adapter,
127
147
  jwtSecret: options.secret,
148
+ // The module defaults to requiring an uppercase and a lowercase
149
+ // letter. Its rules have to match the ones checked above, or a password
150
+ // this accepts is refused a layer down in a different sentence.
151
+ passwordOptions: { ...PASSWORD_RULES },
128
152
  }) as AuthLike);
129
153
  this.tokens = adapter ? new Tokens(adapter) : null;
130
154
  this.identities = adapter ? new Identities(adapter, adapter) : null;
@@ -73,5 +73,16 @@ declare module "@profullstack/auth-system" {
73
73
  jwtSecret?: string;
74
74
  accessTokenExpiry?: string | number;
75
75
  refreshTokenExpiry?: string | number;
76
+ /**
77
+ * Composition rules. Every "require" defaults to true except
78
+ * requireSpecialChars, so leaving this out is stricter than passing it.
79
+ */
80
+ passwordOptions?: {
81
+ minLength?: number;
82
+ requireUppercase?: boolean;
83
+ requireLowercase?: boolean;
84
+ requireNumbers?: boolean;
85
+ requireSpecialChars?: boolean;
86
+ };
76
87
  }): AuthSystem;
77
88
  }
package/web/dist/sw.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* nixamp service worker — generated, do not edit */
2
- const CACHE = "nixamp-1788934163965";
2
+ const CACHE = "nixamp-1788934596148";
3
3
  const PRECACHE = [
4
4
  "/",
5
5
  "/apple-touch-icon.png",