kreftjs 0.0.9-beta → 0.0.10-beta

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.
@@ -90,6 +90,10 @@ const loadModuleAsync = async (file) => {
90
90
  function createBackend(baseDir, { db = null, production = false, log = console, prefix = '/api' } = {}) {
91
91
  const isProd = Boolean(production || process.env.APP_ENV === 'production' || process.env.NODE_ENV === 'production');
92
92
  const isDebug = process.env.APP_DEBUG !== undefined ? (process.env.APP_DEBUG === 'true' || process.env.APP_DEBUG === '1') : !isProd;
93
+ // .env from an older template says SESSION_SECURE_COOKIE=false: in production that sends the session cookie over plain HTTP too
94
+ if (isProd && process.env.SESSION_SECURE_COOKIE === 'false') {
95
+ log.warn(' SECURITY: SESSION_SECURE_COOKIE=false in production. The login cookie is also sent over plain http://. Remove that line from .env (cookies are Secure in production by default).');
96
+ }
93
97
  const { startAutoGarbageCollector } = require('./gc.js');
94
98
  startAutoGarbageCollector({ thresholdMB: Number(process.env.AUTO_GC_THRESHOLD_MB) || 200, log: !isProd && process.env.VERBOSE_GC === '1' });
95
99
  installAlias();
package/bin/build.js CHANGED
@@ -253,7 +253,8 @@ ${indent(components.join('\n\n'))}
253
253
  };
254
254
 
255
255
  // Apache (Hostinger, cPanel …) answers /docs with a 404, because only index.html exists on disk. These rules send every page address
256
- // (no file extension, not under /api/) that is not a real file or folder to index.html, so reloading a page works. A missing file such as
256
+ // (no file extension, not under /api/) that is not a real file, or a folder with its own index.html (a prerendered page), to index.html,
257
+ // so reloading a page works even when a folder has the page's name (the docs/ folder next to the /docs page). A missing file such as
257
258
  // app.js, or an /api/ address the host cannot answer, stays a real 404: sending it index.html would hand the page's HTML to code
258
259
  // that expects data (a list, JSON). An .htaccess you keep in public/ is left alone;
259
260
  // a relative base (./, as the desktop build uses) has no server and gets no file.
@@ -267,7 +268,7 @@ function writeHtaccess(dist, html) {
267
268
  RewriteBase ${base}
268
269
  RewriteRule ^index\\.html$ - [L]
269
270
  RewriteCond %{REQUEST_FILENAME} !-f
270
- RewriteCond %{REQUEST_FILENAME} !-d
271
+ RewriteCond %{REQUEST_FILENAME}/index.html !-f
271
272
  RewriteCond %{REQUEST_URI} !^${base}api/
272
273
  RewriteCond %{REQUEST_URI} !\\.[A-Za-z0-9]+$
273
274
  RewriteRule . ${base}index.html [L]
package/docs/README.md CHANGED
@@ -82,7 +82,7 @@ npx kreftjs dev
82
82
  ### Check that it works
83
83
 
84
84
  ```bash
85
- kreft --version # for example 0.0.9-beta
85
+ kreft --version # for example 0.0.10-beta
86
86
  kreft about # Kreft and Node.js versions, this project's settings and drivers
87
87
  kreft list # every command your version has
88
88
  ```
@@ -1045,6 +1045,16 @@ Without a form, `validate(values, rules)` gives `{}` or `{ field: ['…'] }`. Cu
1045
1045
 
1046
1046
  The same rule names work on the server in `req.validate()` (see [Controllers and requests](#controllers-and-requests)), so one set of rules can describe both sides.
1047
1047
 
1048
+ ### Passwords
1049
+
1050
+ `not_common_password` refuses a password that is among the most used ones (`password`, `12345678`, `qwertyuiop` …), one character repeated (`aaaaaaaa`), a plain run (`12345678`, `abcdefgh`), or the same as the email address. A new app uses it next to `min:8` when people register, reset or change a password, in the pages and in the controllers:
1051
+
1052
+ ```js
1053
+ password: 'required|min:8|confirmed|not_common_password'
1054
+ ```
1055
+
1056
+ It is a short list that runs offline, with no service called, so it catches the worst choices and nothing more. For longer ones, raise `min` (a passphrase of four words beats a short mix of symbols). Change the message in `lang/en/validation.json` (`not_common_password`).
1057
+
1048
1058
  ## Internationalization and RTL
1049
1059
 
1050
1060
  Kreft translates text and flips direction for right-to-left languages such as Arabic, Hebrew, Persian and Urdu.
@@ -1735,13 +1745,13 @@ RewriteEngine On
1735
1745
  RewriteBase /
1736
1746
  RewriteRule ^index\.html$ - [L]
1737
1747
  RewriteCond %{REQUEST_FILENAME} !-f
1738
- RewriteCond %{REQUEST_FILENAME} !-d
1748
+ RewriteCond %{REQUEST_FILENAME}/index.html !-f
1739
1749
  RewriteCond %{REQUEST_URI} !^/api/
1740
1750
  RewriteCond %{REQUEST_URI} !\.[A-Za-z0-9]+$
1741
1751
  RewriteRule . /index.html [L]
1742
1752
  ```
1743
1753
 
1744
- Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every page address (no file extension, not under `/api/`) that is not a real file or folder opens `index.html` and the router takes over. A missing file such as `app.js`, or an `/api/` address, stays a plain 404, so code that asks for data never receives the page's HTML. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
1754
+ Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every page address (no file extension, not under `/api/`) that is not a real file, or a folder with its own `index.html`, opens `index.html` and the router takes over. A missing file such as `app.js`, or an `/api/` address, stays a plain 404, so code that asks for data never receives the page's HTML. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
1745
1755
 
1746
1756
  > [!NOTE]
1747
1757
  > This hosts the front end only. Login, the database and everything under `/api` need the Node.js server, which Apache does not run.
@@ -2195,7 +2205,8 @@ Go through this before your first real user:
2195
2205
  | `MCP_TOKEN` set, or MCP left off | The MCP endpoint is disabled in production without it. |
2196
2206
  | Tables listed in `kreftjs.config.json`, or no `--db` at all | `kreft serve` serves only the tables you list. |
2197
2207
  | No test user | Do not run `--seed` against production; delete `test@example.com` if it exists. |
2198
- | HTTPS in front of the app | Cookies are `Secure` in production and on `https` URLs. |
2208
+ | HTTPS in front of the app, and `FORCE_HTTPS=true` | Cookies are `Secure` in production and on `https` URLs. Plain HTTP is only redirected to HTTPS with `FORCE_HTTPS=true` or an `https://` `APP_URL`. |
2209
+ | No `SESSION_SECURE_COOKIE=false` in `.env` | It switches the `Secure` flag off, so the login cookie is also sent over plain `http://`. Older templates wrote it; the server warns about it at start-up in production. |
2199
2210
  | `npm audit` and `kreft update` | Fix known vulnerabilities before release. |
2200
2211
 
2201
2212
  > [!NOTE]
package/kreftjs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Type definitions for Kreft 0.0.9-beta
1
+ // Type definitions for Kreft 0.0.10-beta
2
2
  // Use from TypeScript or for editor hints in plain JavaScript (// @ts-check).
3
3
 
4
4
  export interface Signal<T> { value: T }
package/kreftjs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Kreft v0.0.9-beta — reactive by nature
2
+ * Kreft v0.0.10-beta — reactive by nature
3
3
  * The .kreft component language (state · derive · action · when · watch · on),
4
4
  * { } views with k-if / k-each / k-model, components, slots, router, stores,
5
5
  * share / receive, event bus and a template engine.
@@ -4678,6 +4678,7 @@
4678
4678
  same: 'The :attribute field must match :other.',
4679
4679
  different: 'The :attribute field and :other must be different.',
4680
4680
  confirmed: 'The :attribute field confirmation does not match.',
4681
+ not_common_password: 'The :attribute is too common or too easy to guess. Choose another one.',
4681
4682
  regex: 'The :attribute field format is invalid.',
4682
4683
  digits: 'The :attribute field must be :digits digits.',
4683
4684
  min: { string: 'The :attribute field must be at least :min characters.', numeric: 'The :attribute field must be at least :min.', array: 'The :attribute field must have at least :min items.' },
@@ -4687,6 +4688,17 @@
4687
4688
  };
4688
4689
  const isEmptyValue = (v) => v === undefined || v === null || (typeof v === 'string' && v.trim() === '') || (isArray(v) && !v.length);
4689
4690
  const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4691
+ // not_common_password: the passwords people choose most (8+ characters, so they pass `min:8`), one character repeated, a run like
4692
+ // 12345678 or abcdefgh, or the same as the email address. Not a replacement for a long passphrase.
4693
+ const COMMON_PASSWORDS = new Set('00000000 11111111 111111111 123123123 12345678 123456789 1234567890 12345678910 123456789a 123456abc 1q2w3e4r 1q2w3e4r5t 1qaz2wsx 88888888 987654321 abc12345 abcd1234 abcdefg1 abcdefgh admin123 admin1234 administrator asdfghjk asdfghjkl baseball1 changeme changeme1 dragon123 football1 freedom1 google123 hello123 hello1234 iloveyou iloveyou1 kreft123 kreftjs123 letmein1 letmein123 login123 master123 monkey123 p@ssw0rd p@ssword pass1234 passpass passw0rd password password1 password12 password123 password1234 princess1 qazwsxedc qwerty12 qwerty123 qwertyui qwertyuiop secret123 shadow123 starwars1 sunshine1 superman1 test1234 testing123 trustno1 welcome1 welcome123 whatever1 zxcvbnm1'.split(' '));
4694
+ const isCommonPassword = (v, data) => {
4695
+ const p = String(v).toLowerCase();
4696
+ if (COMMON_PASSWORDS.has(p) || /^(.)\1+$/.test(p)) return true;
4697
+ const runs = (s) => { let up = true, down = true; for (let i = 1; i < s.length; i++) { const d = s.charCodeAt(i) - s.charCodeAt(i - 1); if (d !== 1) up = false; if (d !== -1) down = false; } return up || down; };
4698
+ if (p.length >= 6 && runs(p)) return true;
4699
+ const email = data && typeof data.email === 'string' ? data.email.toLowerCase() : '';
4700
+ return Boolean(email) && (p === email || p === email.split('@')[0]);
4701
+ };
4690
4702
  const dateOf = (v, data) => { const d = new Date(hasOwn(data, v) ? data[v] : v === 'today' ? new Date().toDateString() : v); return isNaN(d) ? null : d; };
4691
4703
  function parseRules(rules) {
4692
4704
  return (isArray(rules) ? rules : String(rules || '').split('|')).filter(Boolean).map((r) => {
@@ -4746,6 +4758,7 @@
4746
4758
  case 'same': failed = value !== getPath(data, a); extra = { other: a.replace(/_/g, ' ') }; break;
4747
4759
  case 'different': failed = value === getPath(data, a); extra = { other: a.replace(/_/g, ' ') }; break;
4748
4760
  case 'confirmed': failed = value !== getPath(data, field + '_confirmation'); break;
4761
+ case 'not_common_password': failed = isCommonPassword(value, data); break;
4749
4762
  case 'regex': { const m = r.arg.match(/^\/(.*)\/([a-z]*)$/); failed = !new RegExp(m ? m[1] : r.arg, m ? m[2] : '').test(String(value)); break; }
4750
4763
  case 'digits': failed = !new RegExp(`^\\d{${Number(a)}}$`).test(String(value)); extra = { digits: a }; break;
4751
4764
  case 'min': failed = sizeOf(value) < Number(a); extra = { min: a }; break;
@@ -5023,7 +5036,7 @@
5023
5036
  stores, storeLog, busLog,
5024
5037
  };
5025
5038
 
5026
- const VERSION = '0.0.9-beta';
5039
+ const VERSION = '0.0.10-beta';
5027
5040
  const Kreftjs = {
5028
5041
  version: VERSION,
5029
5042
  // PUBLIC_ values from .env (kreft dev and kreft build put them here); never secrets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kreftjs",
3
- "version": "0.0.9-beta",
3
+ "version": "0.0.10-beta",
4
4
  "description": "A tiny reactive framework with its own component language (.kreft files): router with nested routes, stores, saved data, animations, an API client, hot reload, DevTools and a template engine.",
5
5
  "license": "Elastic-2.0",
6
6
  "main": "kreftjs.js",
@@ -14,7 +14,7 @@
14
14
  "start": "node bin/kreftjs.js dev --api demo/db.json --db sqlite:demo/database/demo.db --migrations demo/database/migrations --server demo/server --backend demo --seed",
15
15
  "build": "node bin/kreftjs.js build demo --out dist/demo --include docs",
16
16
  "preview": "node bin/kreftjs.js dev dist --api demo/db.json --db sqlite:demo/database/demo.db --migrations demo/database/migrations --server demo/server --backend demo --seed",
17
- "test": "node --test test/security.test.js test/prerender.test.js test/seo.test.js test/rebrand.test.js test/noauth.test.js test/winspawn.test.js test/htaccess.test.js",
17
+ "test": "node --test test/security.test.js test/prerender.test.js test/seo.test.js test/rebrand.test.js test/noauth.test.js test/winspawn.test.js test/htaccess.test.js test/cookie-secure.test.js test/password-rule.test.js",
18
18
  "electron": "kreftjs electron",
19
19
  "electron:dev": "kreftjs electron:dev",
20
20
  "electron:build": "kreftjs electron:build"
@@ -30,16 +30,17 @@ FILESYSTEM_DISK=local
30
30
  # REDIS_PORT=6379
31
31
  # REDIS_PASSWORD=
32
32
  # REDIS_DB=0
33
- # REDIS_PREFIX=som:
33
+ # REDIS_PREFIX=kreft:
34
34
  # Environment & Debugging:
35
35
  # - local: plain HTTP allowed on localhost, interactive bug diagnostics & stack traces shown
36
36
  # - production: plain HTTP disallowed for security (enforces HTTPS & HSTS), bug details & stack traces hidden
37
37
  APP_ENV=local
38
38
  APP_DEBUG=true
39
39
 
40
- # Force all traffic over secure HTTPS in production (auto-redirects HTTP -> HTTPS with HSTS)
41
- FORCE_HTTPS=false
42
- SESSION_SECURE_COOKIE=false
40
+ # Redirect plain HTTP to HTTPS in production (with HSTS). Turn it on once the site has HTTPS:
41
+ # FORCE_HTTPS=true
42
+ # The login cookie is Secure in production and on an https:// APP_URL by itself. Do not set this to false in production:
43
+ # SESSION_SECURE_COOKIE=true
43
44
 
44
45
  # Security & Sessions
45
46
  # A login token nobody used for this many days stops working
@@ -10,7 +10,7 @@ class NewPasswordController {
10
10
  const data = await req.validate({
11
11
  token: 'required',
12
12
  email: 'required|email',
13
- password: 'required|min:8|confirmed',
13
+ password: 'required|min:8|confirmed|not_common_password',
14
14
  })
15
15
  const email = data.email.toLowerCase()
16
16
  const row = await DB.table('password_reset_tokens').where('email', email).first()
@@ -8,7 +8,7 @@ class RegisteredUserController {
8
8
  const data = await req.validate({
9
9
  name: 'required|string|max:255',
10
10
  email: 'required|string|email|max:255|unique:users,email',
11
- password: 'required|min:8|confirmed',
11
+ password: 'required|min:8|confirmed|not_common_password',
12
12
  })
13
13
  const user = await User.create({ name: data.name, email: data.email.toLowerCase(), password: Hash.make(data.password) })
14
14
  await user.sendEmailVerificationNotification()
@@ -42,7 +42,7 @@ class ProfileController {
42
42
  if (req.accessToken && req.accessToken.type !== 'session' && !req.accessToken.can('*')) {
43
43
  abort(403, 'Changing the account password requires a browser session.')
44
44
  }
45
- const data = await req.validate({ current_password: 'required|string|max:255', password: 'required|string|min:8|max:255|confirmed' })
45
+ const data = await req.validate({ current_password: 'required|string|max:255', password: 'required|string|min:8|max:255|confirmed|not_common_password' })
46
46
  if (!Hash.check(data.current_password, req.user.password)) {
47
47
  throw new ValidationError({ current_password: ['The password is incorrect.'] })
48
48
  }
@@ -16,6 +16,6 @@
16
16
  "password": "كلمة المرور",
17
17
  "title": "العنوان",
18
18
  "name": "الاسم"
19
- }
19
+ },
20
+ "not_common_password": "كلمة :attribute شائعة جداً أو يسهل تخمينها. اختر كلمة أخرى."
20
21
  }
21
-
@@ -14,6 +14,6 @@
14
14
  "attributes": {
15
15
  "email": "email address",
16
16
  "password": "password"
17
- }
17
+ },
18
+ "not_common_password": "The :attribute is too common or too easy to guess. Choose another one."
18
19
  }
19
-
@@ -92,7 +92,7 @@ state docs = (Kreftjs.env.PUBLIC_DOCS_URL || 'http://kreftjs.com').replace(/\/+$
92
92
  <div class="badges">
93
93
  <span class="badge danger-badge">HTTP {status}</span>
94
94
  <span class="badge solid">{currentTitle}</span>
95
- <span class="badge">Kreft {Kreftjs.version || '0.0.9-beta'}</span>
95
+ <span class="badge">Kreft {Kreftjs.version || '0.0.10-beta'}</span>
96
96
  </div>
97
97
  <div class="actions">
98
98
  <button class="sm" @click={copyReport}>{copied ? 'Copied Markdown' : 'Copy Report'}</button>
@@ -189,7 +189,7 @@ state docs = (Kreftjs.env.PUBLIC_DOCS_URL || 'http://kreftjs.com').replace(/\/+$
189
189
  <h3>Kreft Runtime</h3>
190
190
  <table>
191
191
  <tbody>
192
- <tr><th>Engine</th><td><code>Kreft v{Kreftjs.version || '0.0.9-beta'}</code></td></tr>
192
+ <tr><th>Engine</th><td><code>Kreft v{Kreftjs.version || '0.0.10-beta'}</code></td></tr>
193
193
  <tr><th>Sanitizer</th><td><code>Active (cleanHtml / SafeHtml)</code></td></tr>
194
194
  <tr><th>Environment</th><td><code>development (APP_DEBUG=true)</code></td></tr>
195
195
  </tbody>
@@ -1,4 +1,4 @@
1
- // Type definitions for Kreft 0.0.9-beta
1
+ // Type definitions for Kreft 0.0.10-beta
2
2
  // Use from TypeScript or for editor hints in plain JavaScript (// @ts-check).
3
3
 
4
4
  export interface Signal<T> { value: T }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Kreft v0.0.9-beta — reactive by nature
2
+ * Kreft v0.0.10-beta — reactive by nature
3
3
  * The .kreft component language (state · derive · action · when · watch · on),
4
4
  * { } views with k-if / k-each / k-model, components, slots, router, stores,
5
5
  * share / receive, event bus and a template engine.
@@ -4678,6 +4678,7 @@
4678
4678
  same: 'The :attribute field must match :other.',
4679
4679
  different: 'The :attribute field and :other must be different.',
4680
4680
  confirmed: 'The :attribute field confirmation does not match.',
4681
+ not_common_password: 'The :attribute is too common or too easy to guess. Choose another one.',
4681
4682
  regex: 'The :attribute field format is invalid.',
4682
4683
  digits: 'The :attribute field must be :digits digits.',
4683
4684
  min: { string: 'The :attribute field must be at least :min characters.', numeric: 'The :attribute field must be at least :min.', array: 'The :attribute field must have at least :min items.' },
@@ -4687,6 +4688,17 @@
4687
4688
  };
4688
4689
  const isEmptyValue = (v) => v === undefined || v === null || (typeof v === 'string' && v.trim() === '') || (isArray(v) && !v.length);
4689
4690
  const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4691
+ // not_common_password: the passwords people choose most (8+ characters, so they pass `min:8`), one character repeated, a run like
4692
+ // 12345678 or abcdefgh, or the same as the email address. Not a replacement for a long passphrase.
4693
+ const COMMON_PASSWORDS = new Set('00000000 11111111 111111111 123123123 12345678 123456789 1234567890 12345678910 123456789a 123456abc 1q2w3e4r 1q2w3e4r5t 1qaz2wsx 88888888 987654321 abc12345 abcd1234 abcdefg1 abcdefgh admin123 admin1234 administrator asdfghjk asdfghjkl baseball1 changeme changeme1 dragon123 football1 freedom1 google123 hello123 hello1234 iloveyou iloveyou1 kreft123 kreftjs123 letmein1 letmein123 login123 master123 monkey123 p@ssw0rd p@ssword pass1234 passpass passw0rd password password1 password12 password123 password1234 princess1 qazwsxedc qwerty12 qwerty123 qwertyui qwertyuiop secret123 shadow123 starwars1 sunshine1 superman1 test1234 testing123 trustno1 welcome1 welcome123 whatever1 zxcvbnm1'.split(' '));
4694
+ const isCommonPassword = (v, data) => {
4695
+ const p = String(v).toLowerCase();
4696
+ if (COMMON_PASSWORDS.has(p) || /^(.)\1+$/.test(p)) return true;
4697
+ const runs = (s) => { let up = true, down = true; for (let i = 1; i < s.length; i++) { const d = s.charCodeAt(i) - s.charCodeAt(i - 1); if (d !== 1) up = false; if (d !== -1) down = false; } return up || down; };
4698
+ if (p.length >= 6 && runs(p)) return true;
4699
+ const email = data && typeof data.email === 'string' ? data.email.toLowerCase() : '';
4700
+ return Boolean(email) && (p === email || p === email.split('@')[0]);
4701
+ };
4690
4702
  const dateOf = (v, data) => { const d = new Date(hasOwn(data, v) ? data[v] : v === 'today' ? new Date().toDateString() : v); return isNaN(d) ? null : d; };
4691
4703
  function parseRules(rules) {
4692
4704
  return (isArray(rules) ? rules : String(rules || '').split('|')).filter(Boolean).map((r) => {
@@ -4746,6 +4758,7 @@
4746
4758
  case 'same': failed = value !== getPath(data, a); extra = { other: a.replace(/_/g, ' ') }; break;
4747
4759
  case 'different': failed = value === getPath(data, a); extra = { other: a.replace(/_/g, ' ') }; break;
4748
4760
  case 'confirmed': failed = value !== getPath(data, field + '_confirmation'); break;
4761
+ case 'not_common_password': failed = isCommonPassword(value, data); break;
4749
4762
  case 'regex': { const m = r.arg.match(/^\/(.*)\/([a-z]*)$/); failed = !new RegExp(m ? m[1] : r.arg, m ? m[2] : '').test(String(value)); break; }
4750
4763
  case 'digits': failed = !new RegExp(`^\\d{${Number(a)}}$`).test(String(value)); extra = { digits: a }; break;
4751
4764
  case 'min': failed = sizeOf(value) < Number(a); extra = { min: a }; break;
@@ -5023,7 +5036,7 @@
5023
5036
  stores, storeLog, busLog,
5024
5037
  };
5025
5038
 
5026
- const VERSION = '0.0.9-beta';
5039
+ const VERSION = '0.0.10-beta';
5027
5040
  const Kreftjs = {
5028
5041
  version: VERSION,
5029
5042
  // PUBLIC_ values from .env (kreft dev and kreft build put them here); never secrets
@@ -112,7 +112,7 @@ state docs = (Kreftjs.env.PUBLIC_DOCS_URL || 'http://kreftjs.com').replace(/\/+$
112
112
  <div class="info-list">
113
113
  <div class="info-item">
114
114
  <span class="info-label">Framework Engine</span>
115
- <span class="info-value">Kreft {Kreftjs.version || '0.0.9-beta'}</span>
115
+ <span class="info-value">Kreft {Kreftjs.version || '0.0.10-beta'}</span>
116
116
  </div>
117
117
  <div class="info-item">
118
118
  <span class="info-label">Active Database</span>
@@ -9,7 +9,7 @@ state info = form(
9
9
  )
10
10
  state pass = form(
11
11
  { current_password: '', password: '', password_confirmation: '' },
12
- { current_password: 'required', password: 'required|min:8|confirmed' },
12
+ { current_password: 'required', password: 'required|min:8|confirmed|not_common_password' },
13
13
  )
14
14
  state saved = ''
15
15
  state passSaved = ''
@@ -1,7 +1,7 @@
1
1
  <!-- /register: make an account (POST /api/register, app/Http/Controllers/Auth/RegisteredUserController.js) -->
2
2
  state f = form(
3
3
  { name: '', email: '', password: '', password_confirmation: '' },
4
- { name: 'required|max:255', email: 'required|email|max:255', password: 'required|min:8|confirmed' },
4
+ { name: 'required|max:255', email: 'required|email|max:255', password: 'required|min:8|confirmed|not_common_password' },
5
5
  )
6
6
  state problem = ''
7
7
 
@@ -3,7 +3,7 @@ prop token = ''
3
3
 
4
4
  state f = form(
5
5
  { email: $route.query.email || '', password: '', password_confirmation: '' },
6
- { email: 'required|email', password: 'required|min:8|confirmed' },
6
+ { email: 'required|email', password: 'required|min:8|confirmed|not_common_password' },
7
7
  )
8
8
  state problem = ''
9
9
 
@@ -12,6 +12,7 @@
12
12
  "array": "يجب ألا يحتوي :attribute على أكثر من :max عناصر."
13
13
  },
14
14
  "confirmed": "تأكيد :attribute غير متطابق.",
15
+ "not_common_password": "كلمة :attribute شائعة جداً أو يسهل تخمينها. اختر كلمة أخرى.",
15
16
  "attributes": {
16
17
  "email": "البريد الإلكتروني",
17
18
  "password": "كلمة المرور",
@@ -19,4 +20,3 @@
19
20
  "title": "العنوان"
20
21
  }
21
22
  }
22
-
@@ -12,6 +12,7 @@
12
12
  "array": "The :attribute field must not have more than :max items."
13
13
  },
14
14
  "confirmed": "The :attribute confirmation does not match.",
15
+ "not_common_password": "The :attribute is too common or too easy to guess. Choose another one.",
15
16
  "attributes": {
16
17
  "email": "email address",
17
18
  "password": "password",
@@ -19,4 +20,3 @@
19
20
  "title": "title"
20
21
  }
21
22
  }
22
-
@@ -118,7 +118,7 @@ state docs = (Kreftjs.env.PUBLIC_DOCS_URL || 'http://kreftjs.com').replace(/\/+$
118
118
  <div class="hero-badges">
119
119
  <span class="badge-exception">{currentTitle}</span>
120
120
  <span class="badge-env">Node.js {typeof process !== 'undefined' ? process.version : 'v22.0.0'}</span>
121
- <span class="badge-env">Kreft v0.0.9-beta</span>
121
+ <span class="badge-env">Kreft v0.0.10-beta</span>
122
122
  </div>
123
123
  <h1 class="hero-error-message">{currentMessage}</h1>
124
124
  </div>