@live-change/balance-frontend 0.8.53

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 (43) hide show
  1. package/Dockerfile +55 -0
  2. package/LICENSE +21 -0
  3. package/data/GeoLite2-Country.mmdb +0 -0
  4. package/dev.Dockerfile +35 -0
  5. package/docker/app.initd.sh +73 -0
  6. package/docker/build-and-upload.sh +30 -0
  7. package/docker/build-docker-and-upload.sh +33 -0
  8. package/docker/commit-new-version.sh +17 -0
  9. package/docker/k8s-rsync-helper.sh +4 -0
  10. package/docker/onlyDependencies.js +12 -0
  11. package/docker/parse-args-and-config.sh +19 -0
  12. package/docker/restore-backup-with-service.sh +14 -0
  13. package/docker/restore-backup.sh +22 -0
  14. package/docker/start-service.sh +4 -0
  15. package/docker/upload-backup-and-restore.sh +12 -0
  16. package/front/index.html +78 -0
  17. package/front/locales/en.js +26 -0
  18. package/front/locales/en.json +7 -0
  19. package/front/public/favicon.ico +0 -0
  20. package/front/public/images/empty-photo.svg +38 -0
  21. package/front/public/images/empty-user-photo.svg +33 -0
  22. package/front/public/images/logo.svg +34 -0
  23. package/front/public/images/logo128.png +0 -0
  24. package/front/src/App.vue +61 -0
  25. package/front/src/Index.vue +16 -0
  26. package/front/src/analytics/index.js +15 -0
  27. package/front/src/components/Clock.vue +22 -0
  28. package/front/src/config.js +26 -0
  29. package/front/src/entry-client.js +8 -0
  30. package/front/src/entry-server.js +8 -0
  31. package/front/src/router.js +76 -0
  32. package/front/tsconfig.json +26 -0
  33. package/front/tsconfig.node.json +11 -0
  34. package/front/vite.config.ts +53 -0
  35. package/index.js +2 -0
  36. package/package.json +106 -0
  37. package/server/app.config.js +103 -0
  38. package/server/init.js +10 -0
  39. package/server/page.documentType.js +103 -0
  40. package/server/security.config.js +53 -0
  41. package/server/services.list.js +49 -0
  42. package/server/start.js +11 -0
  43. package/start-dev-docker.sh +4 -0
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div>
3
+ <h1>Hello world!</h1>
4
+ <p>{{ currentTime }}</p>
5
+ <Clock :time="currentTime" />
6
+ </div>
7
+ </template>
8
+
9
+ <script setup>
10
+ import { currentTime } from "@live-change/frontend-base";
11
+
12
+ </script>
13
+
14
+ <style scoped>
15
+
16
+ </style>
@@ -0,0 +1,15 @@
1
+ import { analytics } from "@live-change/vue3-components"
2
+
3
+ analytics.on('*', (type, e) => console.log('ANALYTICS EVENT', type, e) )
4
+
5
+ analytics.on('formDone', ({ service, action }) => {
6
+
7
+ })
8
+
9
+ analytics.on('menuOpen', e => {
10
+
11
+ })
12
+
13
+ analytics.on('pageView', ({ to, fullPath }) => {
14
+
15
+ })
@@ -0,0 +1,22 @@
1
+
2
+ <template>
3
+ <div class="surface-card p-3 shadow-2 border-round">
4
+ {{ d(new Date(), 'long') }}
5
+ </div>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ import { defineProps, toRefs } from 'vue'
10
+ import { useI18n } from 'vue-i18n'
11
+ const { t, d, n } = useI18n()
12
+
13
+ const props = defineProps<{
14
+ time: number
15
+ }>()
16
+
17
+ const { time } = toRefs(props)
18
+ </script>
19
+
20
+ <style scoped>
21
+
22
+ </style>
@@ -0,0 +1,26 @@
1
+ import deepmerge from 'deepmerge';
2
+
3
+ import * as en from "../locales/en.js"
4
+ import { locales as autoFormLocales } from "@live-change/frontend-auto-form"
5
+
6
+ export default {
7
+ defaultLocale: 'en',
8
+ i18n: {
9
+ messages: {
10
+ en: deepmerge.all([
11
+ autoFormLocales.en,
12
+ en.messages
13
+ ])
14
+ },
15
+ numberFormats: {
16
+ en: deepmerge.all([
17
+ en.numberFormats
18
+ ])
19
+ },
20
+ datetimeFormats: {
21
+ en: deepmerge.all([
22
+ en.datetimeFormats
23
+ ])
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,8 @@
1
+ import { clientEntry } from '@live-change/frontend-base/client-entry.js'
2
+ import App from './App.vue'
3
+ import { createRouter } from './router'
4
+ import config from './config.js'
5
+
6
+ clientEntry(App, createRouter, config)
7
+
8
+ window.appStarted = true
@@ -0,0 +1,8 @@
1
+ import { serverEntry, sitemapEntry } from '@live-change/frontend-base/server-entry.js'
2
+ import App from './App.vue'
3
+ import { createRouter, sitemap as routerSitemap } from './router'
4
+ import config from './config.js'
5
+
6
+ const render = serverEntry(App, createRouter, config)
7
+ const sitemap = sitemapEntry(App, createRouter, routerSitemap, config)
8
+ export { render, sitemap }
@@ -0,0 +1,76 @@
1
+ import {
2
+ createMemoryHistory,
3
+ createRouter as _createRouter,
4
+ createWebHistory
5
+ } from 'vue-router'
6
+
7
+ import {
8
+ installRouterAnalytics
9
+ } from '@live-change/vue3-components'
10
+
11
+ import { dbAdminRoutes } from "@live-change/db-admin"
12
+ import { userRoutes } from "@live-change/user-frontend"
13
+ import { catchAllPagesRoute, contentEditRoutes, pagesSitemap } from "@live-change/content-frontend"
14
+
15
+ import pagesRoutes from '~pages'
16
+
17
+ export function routes(config = {}) {
18
+ const { prefix = '/', route = (r) => r } = config
19
+ return [
20
+ ...userRoutes({ ...config, prefix: prefix + 'user/' }),
21
+
22
+ route({
23
+ name: 'index', path: prefix, meta: { },
24
+ component: () => import("./Index.vue")
25
+ }),
26
+
27
+ ...pagesRoutes,
28
+
29
+ ...contentEditRoutes({ ...config }),
30
+
31
+ ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) }),
32
+ ...catchAllPagesRoute({ ...config }),
33
+ ]
34
+ }
35
+
36
+ export async function sitemap(route, api) {
37
+ route({
38
+ name: 'index'
39
+ })
40
+ await pagesSitemap(route, api)
41
+ }
42
+
43
+ import { client as useClient } from '@live-change/vue3-ssr'
44
+
45
+ export function createRouter(app, config) {
46
+ const client = useClient(app._context)
47
+
48
+ const router = _createRouter({
49
+ // use appropriate history implementation for server/client
50
+ // import.meta.env.SSR is injected by Vite.
51
+ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
52
+ routes: routes(config)
53
+ })
54
+ installRouterAnalytics(router)
55
+ router.beforeEach(async (to, from) => {
56
+ if(to?.matched.find(m => m?.meta.signedIn)) {
57
+ if(!client.value.user) {
58
+ console.log("REDIRECT TO LOGIN BECAUSE PAGE REQUIRES LOGIN!")
59
+ router.redirectAfterSignIn = to.fullPath
60
+ return { name: 'user:signInEmail' }
61
+ }
62
+ }
63
+ if(to?.matched.find(m => m?.meta.signedOut)) {
64
+ if(client.value.user) {
65
+ console.log("REDIRECT TO USER INDEX BECAUSE PAGE REQUIRES LOGOUT!")
66
+ return { name: 'user:settings' }
67
+ }
68
+ }
69
+ if(to && to.name === 'user:signInEmail' && from?.matched.find(m => m?.meta.saveForSignIn)) {
70
+ console.log("SAVE FOR LOGIN", from.fullPath)
71
+ localStorage.redirectAfterLogin = from.fullPath
72
+ }
73
+ })
74
+ return router
75
+ }
76
+
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "preserve",
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
24
+ "references": [{ "path": "./tsconfig.node.json" }]
25
+ }
26
+
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
@@ -0,0 +1,53 @@
1
+ import { defineConfig } from 'vite'
2
+ import Pages from 'vite-plugin-pages'
3
+
4
+ import { fileURLToPath } from 'url'
5
+ import { dirname, join } from 'path'
6
+ import { accessSync, readFileSync } from 'fs'
7
+ const currentModuleDir = dirname(fileURLToPath(import.meta.url))
8
+ const packageJsonPath = dirname(fileURLToPath(import.meta.url))
9
+ .split('/').map((part, i, arr) =>
10
+ join(arr.slice(0, arr.length - i).join('/'), 'package.json')
11
+ ).find(p => { try { accessSync(p); return true } catch(e) { return false }})
12
+ const packageJson = packageJsonPath ? JSON.parse(readFileSync(packageJsonPath, 'utf-8')) : {}
13
+ const name = packageJson.name ?? "Example"
14
+ const version = process.env.VERSION ?? packageJson.version ?? 'unknown'
15
+ const homepage = process.env.BASE_HREF ?? packageJson.homepage
16
+ const domain = (homepage && homepage.match(/https\:\/\/([^\/]+)/)?.[1]) || 'example.com'
17
+
18
+ // @ts-ignore
19
+ import baseViteConfig from '@live-change/frontend-base/vite-config.js'
20
+
21
+ export default defineConfig(async ({ command, mode }) => {
22
+ const baseConfig = (await baseViteConfig({ command, mode }))
23
+ return {
24
+ ...baseConfig,
25
+
26
+ define: {
27
+ ...baseConfig.define,
28
+ ENV_VERSION: JSON.stringify(version),
29
+ ENV_BRAND_NAME: JSON.stringify(name[0].toUpperCase() + name.slice(1)),
30
+ ENV_BRAND_DOMAIN: JSON.stringify(domain),
31
+ },
32
+
33
+ plugins: [
34
+ ...baseConfig.plugins,
35
+ Pages({
36
+ dirs: [
37
+ // basic
38
+ { dir: 'src/pages', baseRoute: '' },
39
+ // blog
40
+ // { dir: 'src/blog', baseRoute: 'blog' },
41
+ ],
42
+ extensions: ['vue', 'md'],
43
+ }),
44
+ ],
45
+
46
+ resolve: {
47
+ ...baseConfig.resolve,
48
+ alias: [
49
+ ...baseConfig.resolve.alias,
50
+ ]
51
+ }
52
+ }
53
+ })
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/package.json ADDED
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "@live-change/balance-frontend",
3
+ "version": "0.8.53",
4
+ "scripts": {
5
+ "memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
6
+ "localDevInit": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js",
7
+ "localDev": "node server/start.js localDev --enableSessions --dbAccess",
8
+ "dev": "node server/start.js dev --enableSessions",
9
+ "ssrDev": "node server/start.js ssrDev --enableSessions",
10
+ "serveAllMem": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb",
11
+ "serveAll": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions",
12
+ "serve": "cross-env NODE_ENV=production node server/start.js ssrServer --enableSessions",
13
+ "memDev:spa": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess --spa",
14
+ "localDevInit:spa": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js --spa",
15
+ "localDev:spa": "node server/start.js localDev --enableSessions --spa",
16
+ "dev:spa": "node server/start.js dev --enableSessions --spa",
17
+ "ssrDev:spa": "node server/start.js ssrDev --enableSessions --spa",
18
+ "serveAllMem:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb --spa",
19
+ "serveAll:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --spa",
20
+ "serve:spa": "cross-env NODE_ENV=production node server/start.js server --enableSessions --spa",
21
+ "apiServer": "node server/start.js apiServer --enableSessions",
22
+ "devApiServer": "node server/start.js devApiServer --enableSessions",
23
+ "memApiServer": "node server/start.js memApiServer --enableSessions",
24
+ "build": "cd front; yarn build:client && yarn build:server",
25
+ "build:client": "cd front; dotenvx run -f ../.env -- vite build --ssrManifest --outDir dist/client",
26
+ "build:server": "cd front; dotenvx run -f ../.env -- vite build --ssr src/entry-server.js --outDir dist/server",
27
+ "build:spa": "cd front; dotenvx run -f ../.env -- vite build --outDir dist/spa",
28
+ "generate": "vite build --ssrManifest --outDir dist/static && yarn build:server && node prerender",
29
+ "debug": "node --inspect-brk server",
30
+ "describe": "node server/start.js describe",
31
+ "changes": "node server/start.js changes"
32
+ },
33
+ "type": "module",
34
+ "dependencies": {
35
+ "@codemirror/language": "6.10.1",
36
+ "@dotenvx/dotenvx": "0.27.0",
37
+ "@fortawesome/fontawesome-free": "^6.5.2",
38
+ "@live-change/access-control-frontend": "^0.8.53",
39
+ "@live-change/access-control-service": "^0.8.53",
40
+ "@live-change/backup-service": "^0.8.53",
41
+ "@live-change/blog-frontend": "^0.8.53",
42
+ "@live-change/blog-service": "^0.8.53",
43
+ "@live-change/cli": "^0.8.53",
44
+ "@live-change/content-frontend": "^0.8.53",
45
+ "@live-change/content-service": "^0.8.53",
46
+ "@live-change/dao": "^0.8.53",
47
+ "@live-change/dao-vue3": "^0.8.53",
48
+ "@live-change/dao-websocket": "^0.8.53",
49
+ "@live-change/db-client": "^0.8.53",
50
+ "@live-change/email-service": "^0.8.53",
51
+ "@live-change/framework": "^0.8.53",
52
+ "@live-change/frontend-auto-form": "^0.8.53",
53
+ "@live-change/frontend-base": "^0.8.53",
54
+ "@live-change/geoip-service": "^0.8.53",
55
+ "@live-change/image-frontend": "^0.8.53",
56
+ "@live-change/locale-settings-service": "^0.8.53",
57
+ "@live-change/password-authentication-service": "^0.8.53",
58
+ "@live-change/prosemirror-service": "^0.8.53",
59
+ "@live-change/secret-code-service": "^0.8.53",
60
+ "@live-change/secret-link-service": "^0.8.53",
61
+ "@live-change/session-service": "^0.8.53",
62
+ "@live-change/task-service": "^0.8.53",
63
+ "@live-change/upload-frontend": "^0.8.53",
64
+ "@live-change/url-frontend": "^0.8.53",
65
+ "@live-change/url-service": "^0.8.53",
66
+ "@live-change/user-frontend": "^0.8.53",
67
+ "@live-change/user-identification-service": "^0.8.53",
68
+ "@live-change/user-service": "^0.8.53",
69
+ "@live-change/vote-service": "^0.8.53",
70
+ "@live-change/vue3-components": "^0.8.53",
71
+ "@live-change/vue3-ssr": "^0.8.53",
72
+ "@live-change/wysiwyg-frontend": "^0.8.53",
73
+ "@vueuse/core": "^10.11.0",
74
+ "codeceptjs-assert": "^0.0.5",
75
+ "compression": "^1.7.4",
76
+ "cross-env": "^7.0.3",
77
+ "get-port-sync": "1.0.1",
78
+ "pica": "^9.0.1",
79
+ "pretty-bytes": "^6.1.1",
80
+ "primeflex": "^3.3.1",
81
+ "primeicons": "^7.0.0",
82
+ "primevue": "^3.52.0",
83
+ "rollup-plugin-node-builtins": "^2.1.2",
84
+ "rollup-plugin-visualizer": "5.12.0",
85
+ "serialize-javascript": "^6.0.2",
86
+ "serve-static": "^1.15.0",
87
+ "v-shared-element": "3.1.1",
88
+ "vue": "^3.4.29",
89
+ "vue-i18n": "^9.10.1",
90
+ "vue-router": "^4.3.3",
91
+ "vue3-scroll-border": "0.1.6"
92
+ },
93
+ "devDependencies": {
94
+ "@live-change/codeceptjs-helper": "^0.8.53",
95
+ "codeceptjs": "^3.6.5",
96
+ "generate-password": "1.7.1",
97
+ "playwright": "^1.41.2",
98
+ "random-profile-generator": "^2.3.0",
99
+ "txtgen": "^3.0.6",
100
+ "webdriverio": "^8.40.2"
101
+ },
102
+ "author": "Michał Łaszczewski <michal@laszczewski.pl>",
103
+ "license": "ISC",
104
+ "description": "",
105
+ "gitHead": "39422adadd1863fa396fc4e875936e09428d6cf1"
106
+ }
@@ -0,0 +1,103 @@
1
+ import dotenv from 'dotenv'
2
+ dotenv.config()
3
+
4
+ import App from "@live-change/framework"
5
+ const app = App.app()
6
+
7
+ const contactTypes = ['email']
8
+
9
+ import securityConfig from './security.config.js'
10
+ import documentTypePage from './page.documentType.js'
11
+
12
+ app.config = {
13
+ services: [
14
+ {
15
+ name: 'session',
16
+ createSessionOnUpdate: true
17
+ },
18
+ {
19
+ name: 'user',
20
+ },
21
+ {
22
+ name: 'email',
23
+ },
24
+ {
25
+ name: 'passwordAuthentication',
26
+ contactTypes,
27
+ signInWithoutPassword: true
28
+ },
29
+ {
30
+ name: 'userIdentification',
31
+ },
32
+ {
33
+ name: 'localeSettings',
34
+ },
35
+ {
36
+ name: 'identicon',
37
+ },
38
+ {
39
+ name: 'accessControl',
40
+ createSessionOnUpdate: true,
41
+ contactTypes,
42
+ },
43
+ {
44
+ name: 'security',
45
+ ...securityConfig,
46
+ },
47
+ {
48
+ name: 'notification',
49
+ contactTypes,
50
+ notificationTypes: ['example_TestNotification']
51
+ },
52
+ {
53
+ name: 'upload',
54
+ },
55
+ {
56
+ name: 'image',
57
+ },
58
+ {
59
+ name: 'secretCode',
60
+ },
61
+ {
62
+ name: 'secretLink',
63
+ },
64
+ {
65
+ name: 'messageAuthentication',
66
+ contactTypes,
67
+ signUp: true,
68
+ signIn: true,
69
+ connect: true
70
+ },
71
+ {
72
+ name: 'url',
73
+ },
74
+ {
75
+ name: 'prosemirror',
76
+ documentTypes: {
77
+ page: documentTypePage,
78
+ /*rich: require('./rich.documentType.js'),*/
79
+ },
80
+ testLatency: 2000
81
+ },
82
+ {
83
+ name: 'content',
84
+ },
85
+ {
86
+ name: 'geoIp',
87
+ geoIpCountryPath: "./data/GeoLite2-Country.mmdb",
88
+ //geoIpDefaultCountry: "pl"
89
+ },
90
+ {
91
+ name: 'vote',
92
+ },
93
+ {
94
+ name: 'task',
95
+ },
96
+ {
97
+ name: 'backup',
98
+ port: 8007
99
+ },
100
+ ]
101
+ }
102
+
103
+ export default app.config
package/server/init.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createUser } from "@live-change/user-frontend/server/init-functions.js"
2
+ import App from '@live-change/framework'
3
+ const app = App.app()
4
+
5
+ export default async function(services) {
6
+
7
+ const testUser = await createUser(services,
8
+ 'Test User', 'test@test.com', 'Testy123', 'u1', ['writer'])
9
+
10
+ }
@@ -0,0 +1,103 @@
1
+ export default {
2
+ "marks": {
3
+ "bold": {},
4
+ "italic": {},
5
+ "underline": {},
6
+ "strike": {}
7
+ },
8
+ "nodes": {
9
+ "paragraph": {
10
+ "content": "inline*",
11
+ "group": "block"
12
+ },
13
+ "horizontalRule": {
14
+ "group": "block"
15
+ },
16
+ "heading": {
17
+ "content": "inline*",
18
+ "group": "block",
19
+ "defining": true,
20
+ "attrs": {
21
+ "level": {
22
+ "default": 1
23
+ }
24
+ }
25
+ },
26
+ "blockquote": {
27
+ "content": "block+",
28
+ "group": "block",
29
+ "defining": true
30
+ },
31
+ "codeBlock": {
32
+ "content": "text*",
33
+ "marks": "",
34
+ "group": "block",
35
+ "code": true,
36
+ "defining": true,
37
+ "attrs": {
38
+ "language": {
39
+ "default": null
40
+ }
41
+ }
42
+ },
43
+ "bulletList": {
44
+ "content": "listItem+",
45
+ "group": "block list"
46
+ },
47
+ "orderedList": {
48
+ "content": "listItem+",
49
+ "group": "block list",
50
+ "attrs": {
51
+ "start": {
52
+ "default": 1
53
+ }
54
+ }
55
+ },
56
+ "listItem": {
57
+ "content": "paragraph block*",
58
+ "defining": true
59
+ },
60
+ "image": {
61
+ "content": "",
62
+ "marks": "",
63
+ "group": "block",
64
+ "inline": false,
65
+ "atom": true,
66
+ "selectable": true,
67
+ "draggable": true,
68
+ "attrs": {
69
+ "image": {
70
+ "default": null
71
+ }
72
+ }
73
+ },
74
+ "doc": {
75
+ "content": "block+"
76
+ },
77
+ "text": {
78
+ "group": "inline"
79
+ },
80
+ "hardBreak": {
81
+ "group": "inline",
82
+ "inline": true,
83
+ "selectable": false
84
+ },
85
+ "component": {
86
+ "content": "block*",
87
+ "marks": "",
88
+ "group": "block",
89
+ "inline": false,
90
+ "selectable": true,
91
+ "draggable": true,
92
+ "attrs": {
93
+ "is": {
94
+ "default": "card"
95
+ },
96
+ "attrs": {
97
+ "default": {}
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "topNode": "doc"
103
+ }
@@ -0,0 +1,53 @@
1
+ import lcp from "@live-change/pattern"
2
+
3
+ const clientKeys = (client) => [
4
+ { key: 'user', value: client.user },
5
+ { key: 'session', value: client.session },
6
+ { key: 'ip', value: client.ip }
7
+ ]
8
+
9
+ const failedAuthCodes = lcp.chain([
10
+ { type: "wrong-secret-code", id: "1st-failed-secret-code" },
11
+ { eq: "ip", expire: "10m" },
12
+ { type: "wrong-secret-code", id: "2nd-failed-secret-code" },
13
+ { eq: "ip", expire: "10m" },
14
+ { type: "wrong-secret-code", id: "3rd-failed-secret-code",
15
+ actions: [
16
+ { type: 'ban', keys: ['ip'], ban: { type: 'captcha', actions: ['checkSecretCode'], expire: "30m" } }
17
+ ]
18
+ }
19
+ ]).model
20
+
21
+ const patterns = lcp.mergeModels(
22
+ //failedAuthCodes
23
+ )
24
+
25
+ const counters = [
26
+ {
27
+ id: 'wrong-codes-captcha',
28
+ match: ['wrong-secret-code'],
29
+ keys: ['ip'],
30
+ max: 2,
31
+ duration: '1m',
32
+ actions: [
33
+ { type: 'ban', keys: ['ip'], ban: { type: 'captcha', actions: ['checkSecretCode'], expire: "30m" } }
34
+ ]
35
+ },
36
+ {
37
+ id: 'wrong-codes-ban',
38
+ visible: true,
39
+ match: ['wrong-secret-code'],
40
+ keys: ['ip'],
41
+ max: 5,
42
+ duration: '10m',
43
+ actions: [
44
+ { type: 'ban', keys: ['ip'], ban: { type: 'block', actions: ['checkSecretCode'], expire: "2m" } }
45
+ ]
46
+ }
47
+ ]
48
+
49
+ export default {
50
+ clientKeys,
51
+ patterns,
52
+ counters
53
+ }