miolo 3.0.0-beta.13 → 3.0.0-beta.131
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/bin/{dev.mjs → dev/dev.mjs} +19 -5
- package/bin/{dev_start.mjs → dev/dev_start.mjs} +3 -2
- package/bin/index.mjs +47 -33
- package/bin/prod-bin/create-bin.mjs +33 -0
- package/bin/prod-bin/run.mjs +35 -0
- package/bin/{build-client.mjs → prod-build/build-client.mjs} +17 -5
- package/bin/{build-server.mjs → prod-build/build-server.mjs} +12 -10
- package/bin/prod-run/pid.mjs +13 -0
- package/bin/{restart.mjs → prod-run/restart.mjs} +3 -4
- package/bin/prod-run/start.mjs +14 -0
- package/bin/{stop.mjs → prod-run/stop.mjs} +4 -3
- package/bin/util.mjs +2 -29
- package/package.json +25 -26
- package/{bin → src/config}/.env +17 -6
- package/src/config/defaults.mjs +443 -422
- package/src/config/env.mjs +52 -0
- package/src/config/index.mjs +17 -10
- package/src/config/util.mjs +41 -0
- package/src/engines/emailer/queue.mjs +3 -2
- package/src/engines/emailer/transporter.mjs +10 -9
- package/src/engines/http/index.mjs +1 -1
- package/src/engines/parser/Parser.mjs +25 -7
- package/src/engines/schema/index.mjs +40 -0
- package/src/index.mjs +3 -1
- package/src/middleware/auth/basic.mjs +5 -2
- package/src/middleware/auth/credentials/index.mjs +75 -43
- package/src/middleware/auth/credentials/session/index.mjs +7 -0
- package/src/middleware/auth/credentials/session/store.mjs +9 -0
- package/src/middleware/context/index.mjs +1 -1
- package/src/middleware/http/catcher.mjs +78 -2
- package/src/middleware/http/catcher.old.mjs +82 -0
- package/src/middleware/http/custom_blacklist.mjs +3 -1
- package/src/middleware/routes/catch_js_error.mjs +14 -2
- package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +24 -12
- package/src/middleware/routes/router/crud/getCrudConfig.mjs +4 -6
- package/src/middleware/routes/router/defaults.mjs +1 -11
- package/src/middleware/routes/router/index.mjs +0 -1
- package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +70 -13
- package/src/middleware/routes/router/queries/getQueriesConfig.mjs +21 -21
- package/src/middleware/routes/router/utils.mjs +43 -25
- package/src/middleware/ssr/context.mjs +1 -1
- package/src/middleware/ssr/fallbackIndex.mjs +2 -8
- package/src/middleware/ssr/html.mjs +39 -31
- package/src/middleware/vite/devserver.mjs +22 -8
- package/src/server-cron.mjs +3 -4
- package/src/server-dev.mjs +3 -3
- package/src/server.mjs +3 -5
- package/bin/create-bin.mjs +0 -38
- package/bin/env.mjs +0 -39
- package/bin/prod_start.mjs +0 -9
- package/bin/start.mjs +0 -17
- package/src/engines/logger/verify.mjs +0 -22
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { config } from '@dotenvx/dotenvx'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { intre_locale_init } from 'intre'
|
|
5
|
+
import { getInfoFromPkg, findClosestPackageJson } from './util.mjs'
|
|
6
|
+
|
|
7
|
+
function _get_miolo_config_path(proyEnvPath, appName) {
|
|
8
|
+
const mioloEnv = appName=='miolo-demo'
|
|
9
|
+
? '../miolo/src/config/.env'
|
|
10
|
+
: 'node_modules/miolo/src/config/.env'
|
|
11
|
+
|
|
12
|
+
const mioloPath = path.join(proyEnvPath, mioloEnv)
|
|
13
|
+
if (existsSync(mioloPath)) {
|
|
14
|
+
return mioloPath
|
|
15
|
+
}
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function _get_miolo_config_path_on_build(proyEnvPath, srvDest) {
|
|
20
|
+
|
|
21
|
+
const mioloPath = path.join(proyEnvPath, srvDest, '.env')
|
|
22
|
+
if (existsSync(mioloPath)) {
|
|
23
|
+
return mioloPath
|
|
24
|
+
}
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export function init_env_config() {
|
|
30
|
+
intre_locale_init(process.env.MIOLO_INTRE_LOCALE)
|
|
31
|
+
|
|
32
|
+
const proyEnvPath = findClosestPackageJson(process.cwd())
|
|
33
|
+
const [appName, srvDest] = getInfoFromPkg(proyEnvPath)
|
|
34
|
+
const debug = process.env.DOTENVX_DEBUG === 'true'
|
|
35
|
+
|
|
36
|
+
// miolo defaults
|
|
37
|
+
const libEnvPath = _get_miolo_config_path(proyEnvPath, appName)
|
|
38
|
+
if (libEnvPath) {
|
|
39
|
+
config({ path: libEnvPath, debug })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Maybe miolo defs are on proyect's build folder
|
|
43
|
+
const buildEnvPath = _get_miolo_config_path_on_build(proyEnvPath, srvDest)
|
|
44
|
+
if (buildEnvPath) {
|
|
45
|
+
config({ path: buildEnvPath, debug })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// proyect root config
|
|
49
|
+
if (proyEnvPath) {
|
|
50
|
+
config({ path: path.join(proyEnvPath, '.env'), override: true, debug })
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/config/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import merge from 'deepmerge'
|
|
2
|
-
import
|
|
2
|
+
import { init_env_config } from './env.mjs'
|
|
3
|
+
import make_config_defaults from './defaults.mjs'
|
|
4
|
+
import {isPlainObject} from 'is-plain-object'
|
|
3
5
|
|
|
4
6
|
function _get_auth_type(config) {
|
|
5
7
|
if (config?.auth?.basic) {
|
|
@@ -18,15 +20,20 @@ function _get_auth_type(config) {
|
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
function init_config(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
export function init_config(makeConfig) {
|
|
24
|
+
// Init environment vars
|
|
25
|
+
init_env_config()
|
|
26
|
+
|
|
27
|
+
// delay import of defaults, so env vars can be there
|
|
28
|
+
const base_config = make_config_defaults()
|
|
29
|
+
const custom_config = makeConfig()
|
|
30
|
+
|
|
31
|
+
// isMergeableObject: objects like Joi schemas should be copied not merged
|
|
32
|
+
const all_config= merge(base_config, custom_config, {isMergeableObject: isPlainObject})
|
|
33
|
+
|
|
34
|
+
// Some addendum
|
|
35
|
+
all_config.auth_type = _get_auth_type(all_config)
|
|
25
36
|
all_config.use_catcher = all_config?.http?.catcher_url ? true : false
|
|
26
|
-
|
|
37
|
+
|
|
27
38
|
return all_config
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
export {
|
|
31
|
-
init_config
|
|
32
|
-
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {readFileSync, existsSync} from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
export function getInfoFromPkg(pkgPath) {
|
|
5
|
+
try {
|
|
6
|
+
const packageJsonPath = path.join(pkgPath, 'package.json')
|
|
7
|
+
const content = readFileSync(packageJsonPath, 'utf8')
|
|
8
|
+
const packageData = JSON.parse(content)
|
|
9
|
+
const appName = packageData.name
|
|
10
|
+
|
|
11
|
+
let srvDest = './dist/server'
|
|
12
|
+
try {
|
|
13
|
+
const start = packageData.scripts.start
|
|
14
|
+
if (start) {
|
|
15
|
+
const regex = /^node\s+(.*?)\/run\.mjs(?:$|\s)/;
|
|
16
|
+
const match = start.match(regex);
|
|
17
|
+
if (match) {
|
|
18
|
+
srvDest = match[1]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
} catch(err) {
|
|
22
|
+
console.error('[miolo] Error reading <start> package.json:', err)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return [appName, srvDest]
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('[miolo] Error reading <name> package.json:', error)
|
|
28
|
+
return ['miolo', './dist/server']
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function findClosestPackageJson(dir) {
|
|
33
|
+
if (existsSync(path.join(dir, 'package.json'))) {
|
|
34
|
+
return dir
|
|
35
|
+
}
|
|
36
|
+
const parentDir = path.dirname(dir)
|
|
37
|
+
if (parentDir === dir) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
return findClosestPackageJson(parentDir)
|
|
41
|
+
}
|
|
@@ -3,7 +3,7 @@ import { v4 as uuidv4 } from 'uuid'
|
|
|
3
3
|
export let EMAIL_QUEUE = {}
|
|
4
4
|
|
|
5
5
|
export async function email_queue_an_email(email, logger= undefined) {
|
|
6
|
-
const _loge = logger?.
|
|
6
|
+
const _loge = logger?.error || console.error
|
|
7
7
|
|
|
8
8
|
try {
|
|
9
9
|
const id = uuidv4()
|
|
@@ -18,7 +18,8 @@ export async function email_queue_an_email(email, logger= undefined) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
/* eslint-disable no-unused-vars */
|
|
22
|
+
export function email_queue_pop_pendings(logger= undefined) {
|
|
22
23
|
|
|
23
24
|
let grouped = {}
|
|
24
25
|
|
|
@@ -2,8 +2,9 @@ import nodemailer from 'nodemailer'
|
|
|
2
2
|
import { email_queue_an_email, email_queue_pop_pendings, email_queue_remove_ids } from './queue.mjs'
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
const _logi = (logger, msg) => logger?.info ? logger.info(msg) : console.
|
|
6
|
-
const
|
|
5
|
+
const _logi = (logger, msg) => logger?.info ? logger.info(msg) : console.log(msg)
|
|
6
|
+
const _logs = (logger, msg) => logger?.silly ? logger.silly(msg) : console.log(msg)
|
|
7
|
+
const _loge = (logger, msg) => logger?.error ? logger.error(msg) : console.error(msg)
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
export function _init_emailer_transporter({options, defaults, silent}) {
|
|
@@ -11,13 +12,13 @@ export function _init_emailer_transporter({options, defaults, silent}) {
|
|
|
11
12
|
const nmailer = nodemailer.createTransport(options, defaults)
|
|
12
13
|
|
|
13
14
|
function verify_emailer(logger= undefined) {
|
|
14
|
-
|
|
15
|
+
_logs(logger, '[emailer] Verifying...')
|
|
15
16
|
nmailer.verify(function(error, _success) {
|
|
16
17
|
if (error) {
|
|
17
18
|
_loge(logger, '[emailer] Verifying ERROR')
|
|
18
19
|
_loge(logger, error?.message || error?.stack || error || 'Unknown error')
|
|
19
20
|
} else {
|
|
20
|
-
|
|
21
|
+
_logs(logger, '[emailer] Verifyed OK: Server is ready to take our messages')
|
|
21
22
|
}
|
|
22
23
|
})
|
|
23
24
|
}
|
|
@@ -78,7 +79,7 @@ export function _init_emailer_transporter({options, defaults, silent}) {
|
|
|
78
79
|
} else {
|
|
79
80
|
try {
|
|
80
81
|
const q = email_queue_an_email(mail, logger)
|
|
81
|
-
|
|
82
|
+
_logs(logger, `[emailer] Queued email: ${mail?.from || ''} => ${mail?.to || ''} (${mail?.subject || ''})`)
|
|
82
83
|
|
|
83
84
|
return {
|
|
84
85
|
ok: q.ok,
|
|
@@ -112,20 +113,20 @@ export function _init_emailer_transporter({options, defaults, silent}) {
|
|
|
112
113
|
|
|
113
114
|
for (const email of pending) {
|
|
114
115
|
if (email.count > 1) {
|
|
115
|
-
|
|
116
|
+
_logs(logger, `[emailer] Sending queued and stacked email [${email.subject}](x${email.count})...`)
|
|
116
117
|
email.subject = `${email.subject} (x${email.count})`
|
|
117
118
|
} else {
|
|
118
|
-
|
|
119
|
+
_logs(logger, `[emailer] Sending queued email [${email.subject}]...`)
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
send_email(email).then((res) => {
|
|
122
|
-
|
|
123
|
+
_logs(logger, `[emailer] Queued email [${email.subject}]sent ${res.ok ? 'OK' : 'NOT OK'}`)
|
|
123
124
|
if (res.ok) {
|
|
124
125
|
delete email_queue_remove_ids(email.ids, logger)
|
|
125
126
|
}
|
|
126
127
|
})
|
|
127
128
|
}
|
|
128
|
-
|
|
129
|
+
_logs(logger, `[emailer] Sent emails ${pending.length} from queue`)
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
const emailer= {
|
|
@@ -69,7 +69,7 @@ export function init_http_server(app, config) {
|
|
|
69
69
|
server: undefined,
|
|
70
70
|
start: _http_start,
|
|
71
71
|
stop: async () => {
|
|
72
|
-
logger.warn(`[http] stop()
|
|
72
|
+
logger.warn(`[http] stop() function still not attached. Is server running?`)
|
|
73
73
|
},
|
|
74
74
|
hostname: config.hostname,
|
|
75
75
|
port: config.port
|
|
@@ -18,7 +18,11 @@ export default class Parser {
|
|
|
18
18
|
}
|
|
19
19
|
return def
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
try {
|
|
22
|
+
return this.parse_value_str(fields[name], required, def)
|
|
23
|
+
} catch (e) {
|
|
24
|
+
throw `parse_field_str() Error for ${name}: ${e}`
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
parse_value_int(v, required= false, def= undefined) {
|
|
@@ -40,7 +44,11 @@ export default class Parser {
|
|
|
40
44
|
}
|
|
41
45
|
return def
|
|
42
46
|
}
|
|
43
|
-
|
|
47
|
+
try {
|
|
48
|
+
return this.parse_value_int(fields[name], required, def)
|
|
49
|
+
} catch (e) {
|
|
50
|
+
throw `parse_field_int() Error for ${name}: ${e}`
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
parse_value_float(v, required= false, def= undefined) {
|
|
@@ -62,8 +70,11 @@ export default class Parser {
|
|
|
62
70
|
}
|
|
63
71
|
return def
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
try {
|
|
74
|
+
return this.parse_value_float(fields[name], required, def)
|
|
75
|
+
} catch (e) {
|
|
76
|
+
throw `parse_field_float() Error for ${name}: ${e}`
|
|
77
|
+
}
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
parse_value_bool(v, required= false, def= undefined) {
|
|
@@ -90,8 +101,11 @@ export default class Parser {
|
|
|
90
101
|
}
|
|
91
102
|
return def
|
|
92
103
|
}
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
try {
|
|
105
|
+
return this.parse_value_bool(fields[name], required, def)
|
|
106
|
+
} catch (e) {
|
|
107
|
+
throw `parse_field_bool() Error for ${name}: ${e}`
|
|
108
|
+
}
|
|
95
109
|
}
|
|
96
110
|
|
|
97
111
|
parse_value_obj(v, required= false, def= undefined) {
|
|
@@ -121,6 +135,10 @@ export default class Parser {
|
|
|
121
135
|
}
|
|
122
136
|
return def
|
|
123
137
|
}
|
|
124
|
-
|
|
138
|
+
try {
|
|
139
|
+
return this.parse_value_obj(fields[name], required, def)
|
|
140
|
+
} catch (e) {
|
|
141
|
+
throw `parse_field_obj() Error for ${name}: ${e}`
|
|
142
|
+
}
|
|
125
143
|
}
|
|
126
144
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Joi from "joi"
|
|
2
|
+
|
|
3
|
+
export function with_miolo_schema(fn, schema) {
|
|
4
|
+
return async function (ctx, params) {
|
|
5
|
+
let error
|
|
6
|
+
|
|
7
|
+
// Check schema is actually a schema
|
|
8
|
+
if ((!schema) || (! Joi.isSchema(schema))) {
|
|
9
|
+
error = `Expecting schema for ${fn.name} but something else was found (${typeof schema})`
|
|
10
|
+
ctx.miolo.logger.silly(`[validation][${fn.name}] ${error}`)
|
|
11
|
+
throw new Error(error)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// perform validation
|
|
15
|
+
let v
|
|
16
|
+
try {
|
|
17
|
+
v = schema.validate(params)
|
|
18
|
+
} catch(uerror) {
|
|
19
|
+
error = `Unexpected error validating data for ${fn.name}: ${uerror?.message || uerror}`
|
|
20
|
+
ctx.miolo.logger.silly(`[validation][${fn.name}] ${error}`)
|
|
21
|
+
throw new Error(error)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// raise validation errors
|
|
25
|
+
if (v?.error) {
|
|
26
|
+
error = `Schema invalidated data for ${fn.name}: ${v.error}\n${v.error.annotate(true)}`
|
|
27
|
+
ctx.miolo.logger.silly(`[validation][${fn.name}] ${error}`)
|
|
28
|
+
throw new Error(error)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// check parsed value is ok
|
|
32
|
+
if (!v?.value) {
|
|
33
|
+
error = `Schema returned unknown result for ${fn.name}: ${JSON.stringify(v)}`
|
|
34
|
+
ctx.miolo.logger.silly(`[validation][${fn.name}] ${error}`)
|
|
35
|
+
throw new Error(error)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return await fn(ctx, v.value)
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { miolo_cron } from './server-cron.mjs'
|
|
|
3
3
|
import { init_emailer_transporter as miolo_emailer} from './engines/emailer/index.mjs'
|
|
4
4
|
import { init_logger as miolo_logger } from './engines/logger/index.mjs'
|
|
5
5
|
import { init_parser as miolo_parser } from './engines/parser/index.mjs'
|
|
6
|
+
import { with_miolo_schema } from './engines/schema/index.mjs'
|
|
6
7
|
|
|
7
8
|
import { cacheiro as miolo_cacher} from 'cacheiro'
|
|
8
9
|
import { getConnection as miolo_db_connection} from 'calustra/conn-postgres'
|
|
@@ -14,5 +15,6 @@ export {
|
|
|
14
15
|
miolo_logger,
|
|
15
16
|
miolo_parser,
|
|
16
17
|
miolo_cacher,
|
|
17
|
-
miolo_db_connection
|
|
18
|
+
miolo_db_connection,
|
|
19
|
+
with_miolo_schema
|
|
18
20
|
}
|
|
@@ -52,8 +52,11 @@ const init_basic_auth_middleware = ( app, options ) => {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
ctx.body= {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
ok: true,
|
|
56
|
+
data: {
|
|
57
|
+
user: undefined,
|
|
58
|
+
authenticated: false
|
|
59
|
+
}
|
|
57
60
|
}
|
|
58
61
|
ctx.response.status= 401
|
|
59
62
|
ctx.response.headers['WWW-Authenticate']= 'Basic realm="' + realm.replace(/"/g, '\\"') + '"'
|
|
@@ -12,14 +12,14 @@ import { init_session_middleware } from './session/index.mjs'
|
|
|
12
12
|
// }
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
const def_get_user_id = (user, done,
|
|
15
|
+
const def_get_user_id = (user, done, ctx) => done(null, user.id)
|
|
16
16
|
|
|
17
|
-
const def_find_user_by_id = (id, done,
|
|
17
|
+
const def_find_user_by_id = (id, done, ctx) => {
|
|
18
18
|
const err = Error('You need to define auth.passport.find_user_by_id')
|
|
19
19
|
done(err, null)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const def_local_auth_user = (username, password, done,
|
|
22
|
+
const def_local_auth_user = (username, password, done, ctx) => {
|
|
23
23
|
const err = Error('You need to define auth.passport.local_auth_user')
|
|
24
24
|
done(err, null)
|
|
25
25
|
}
|
|
@@ -39,29 +39,48 @@ const init_credentials_auth_middleware = ( app, options, sessionConfig, cacheCon
|
|
|
39
39
|
const url_logout_f = url_logout || '/logout'
|
|
40
40
|
|
|
41
41
|
// init passport
|
|
42
|
-
const serialize_user = (user, done) => {
|
|
42
|
+
const serialize_user = (ctx) => (user, done) => {
|
|
43
43
|
process.nextTick(function() {
|
|
44
|
-
|
|
44
|
+
try {
|
|
45
|
+
ctx.miolo.logger.debug(`[auth] serializing user...`)
|
|
46
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
47
|
+
return get_user_id_f(user, done, ctx)
|
|
48
|
+
} catch(error) {
|
|
49
|
+
ctx.miolo.logger.error(`[auth] Error serializing user: ${error}`)
|
|
50
|
+
return done(error, null)
|
|
51
|
+
}
|
|
45
52
|
})
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
const deserialize_user = (id, done) => {
|
|
55
|
+
const deserialize_user = (ctx) => (id, done) => {
|
|
49
56
|
process.nextTick(function() {
|
|
50
|
-
|
|
57
|
+
try {
|
|
58
|
+
ctx.miolo.logger.debug(`[auth] deserializing user...`)
|
|
59
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
60
|
+
return find_user_by_id_f(id, done, ctx)
|
|
61
|
+
} catch(error) {
|
|
62
|
+
ctx.miolo.logger.error(`[auth] Error deserializing user: ${error}`)
|
|
63
|
+
return done(error, null)
|
|
64
|
+
}
|
|
51
65
|
})
|
|
52
66
|
}
|
|
53
67
|
|
|
54
|
-
const local_strategy= new LocalStrategy.Strategy (
|
|
68
|
+
const local_strategy= (ctx) => new LocalStrategy.Strategy (
|
|
55
69
|
(username, password, done) => {
|
|
56
|
-
|
|
70
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
71
|
+
return local_auth_user_f(username, password, done, ctx)
|
|
57
72
|
})
|
|
58
73
|
|
|
59
|
-
|
|
74
|
+
app.use((ctx, next) => {
|
|
75
|
+
passport.serializeUser(serialize_user(ctx));
|
|
76
|
+
passport.deserializeUser(deserialize_user(ctx));
|
|
77
|
+
passport.use(local_strategy(ctx));
|
|
78
|
+
return next();
|
|
79
|
+
});
|
|
60
80
|
|
|
61
|
-
passport.serializeUser(serialize_user)
|
|
62
|
-
passport.deserializeUser(deserialize_user)
|
|
63
|
-
passport.use(local_strategy)
|
|
64
81
|
|
|
82
|
+
init_session_middleware(app, sessionConfig, cacheConfig)
|
|
83
|
+
|
|
65
84
|
app.use(passport.initialize())
|
|
66
85
|
app.use(passport.session())
|
|
67
86
|
|
|
@@ -70,7 +89,7 @@ const init_credentials_auth_middleware = ( app, options, sessionConfig, cacheCon
|
|
|
70
89
|
if (ctx.session.authenticated) {
|
|
71
90
|
ctx.session.user = ctx.state.user
|
|
72
91
|
}
|
|
73
|
-
} catch(_) {}
|
|
92
|
+
} catch(_) {}
|
|
74
93
|
await next()
|
|
75
94
|
}
|
|
76
95
|
app.use(_ensure_ctx_user)
|
|
@@ -81,34 +100,38 @@ const init_credentials_auth_middleware = ( app, options, sessionConfig, cacheCon
|
|
|
81
100
|
if (user === false) {
|
|
82
101
|
ctx.session.user = undefined
|
|
83
102
|
ctx.session.authenticated = false
|
|
84
|
-
|
|
85
|
-
ctx.body = {
|
|
86
|
-
user: undefined,
|
|
87
|
-
authenticated: false,
|
|
88
|
-
info: info,
|
|
89
|
-
error: err
|
|
90
|
-
}
|
|
103
|
+
ctx.sessionId = undefined
|
|
91
104
|
|
|
92
105
|
// This will show error logs on the catcher middleware
|
|
93
106
|
// ctx.throw(401)
|
|
94
107
|
|
|
95
|
-
ctx.
|
|
96
|
-
} else {
|
|
108
|
+
ctx.status= 401
|
|
97
109
|
|
|
98
|
-
ctx.
|
|
110
|
+
ctx.body = {
|
|
111
|
+
ok: err==undefined,
|
|
112
|
+
data: {
|
|
113
|
+
user: undefined,
|
|
114
|
+
authenticated: false,
|
|
115
|
+
info: info,
|
|
116
|
+
},
|
|
117
|
+
error: err
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
await ctx.login(user)
|
|
121
|
+
ctx.session.user = user // ctx.state.user
|
|
99
122
|
ctx.session.authenticated = true
|
|
100
|
-
|
|
123
|
+
|
|
101
124
|
ctx.body = {
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
ok: true,
|
|
126
|
+
data: {
|
|
127
|
+
user : user,
|
|
128
|
+
authenticated: true
|
|
129
|
+
}
|
|
104
130
|
}
|
|
131
|
+
|
|
105
132
|
if (url_login_redirect!=undefined) {
|
|
106
133
|
ctx.redirect(url_login_redirect)
|
|
107
134
|
}
|
|
108
|
-
|
|
109
|
-
const res= await ctx.login(user)
|
|
110
|
-
|
|
111
|
-
return res
|
|
112
135
|
}
|
|
113
136
|
})(ctx)
|
|
114
137
|
}
|
|
@@ -117,25 +140,33 @@ const init_credentials_auth_middleware = ( app, options, sessionConfig, cacheCon
|
|
|
117
140
|
if (ctx.session.authenticated) {
|
|
118
141
|
ctx.session.user = undefined
|
|
119
142
|
ctx.session.authenticated = false
|
|
143
|
+
ctx.sessionId = undefined
|
|
120
144
|
|
|
121
|
-
await ctx.logout()
|
|
122
145
|
ctx.body = {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
146
|
+
ok: true,
|
|
147
|
+
data: {
|
|
148
|
+
user: undefined,
|
|
149
|
+
authenticated: false
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
126
153
|
if (url_logout_redirect!=undefined) {
|
|
127
154
|
ctx.redirect(url_logout_redirect)
|
|
128
|
-
}
|
|
155
|
+
} else {
|
|
156
|
+
await ctx.logout()
|
|
157
|
+
}
|
|
129
158
|
} else {
|
|
130
|
-
|
|
131
|
-
ctx.body = {
|
|
132
|
-
user: undefined,
|
|
133
|
-
authenticated: false
|
|
134
|
-
}
|
|
135
159
|
// This will show error logs on the catcher middleware
|
|
136
160
|
// ctx.throw(401)
|
|
137
161
|
|
|
138
|
-
ctx.
|
|
162
|
+
ctx.status= 401
|
|
163
|
+
ctx.body = {
|
|
164
|
+
ok: true,
|
|
165
|
+
data: {
|
|
166
|
+
user: undefined,
|
|
167
|
+
authenticated: false
|
|
168
|
+
}
|
|
169
|
+
}
|
|
139
170
|
}
|
|
140
171
|
}
|
|
141
172
|
|
|
@@ -145,7 +176,8 @@ const init_credentials_auth_middleware = ( app, options, sessionConfig, cacheCon
|
|
|
145
176
|
login_router.get (url_logout_f, handleLogOut)
|
|
146
177
|
login_router.post(url_logout_f, handleLogOut)
|
|
147
178
|
|
|
148
|
-
app.use(login_router.routes())
|
|
179
|
+
app.use(login_router.routes())
|
|
180
|
+
|
|
149
181
|
}
|
|
150
182
|
|
|
151
183
|
export {init_credentials_auth_middleware}
|
|
@@ -19,6 +19,13 @@ function init_session_middleware(app, sessionConfig, cacheConfig) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
app.use(createSession(options, app))
|
|
22
|
+
|
|
23
|
+
app.use (async (ctx, next) => {
|
|
24
|
+
ctx.getSessionStoreKey = (externalKey) => {
|
|
25
|
+
return store.getInnerKey(externalKey)
|
|
26
|
+
}
|
|
27
|
+
await next()
|
|
28
|
+
})
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
export {init_session_middleware}
|
|
@@ -49,11 +49,20 @@ class SessionStore {
|
|
|
49
49
|
const cache = await this.init_cache()
|
|
50
50
|
await cache.unsetItem(key)
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
getInnerKey(key) {
|
|
54
|
+
if (this._cache === undefined) {
|
|
55
|
+
this.logger.error('[session-store] Calling getInnerKey() before cache is inited')
|
|
56
|
+
return key
|
|
57
|
+
}
|
|
58
|
+
return this._cache.getInnerKey(key)
|
|
59
|
+
}
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
|
|
55
63
|
export function init_session_cache_store(cacheConfig, logger) {
|
|
56
64
|
const options = miolo_cacher_options_for_session({cache: cacheConfig}, logger)
|
|
57
65
|
const store = new SessionStore(options, logger)
|
|
66
|
+
store.init_cache()
|
|
58
67
|
return store
|
|
59
68
|
}
|