miolo 3.0.0-beta.21 → 3.0.0-beta.210
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/build/build.mjs +53 -0
- package/bin/build/build_bin.mjs +17 -0
- package/bin/build/cli/client.mjs +52 -0
- package/bin/build/cli/css.mjs +22 -0
- package/bin/build/cli/index.mjs +40 -0
- package/bin/build/cli/ssr.mjs +21 -0
- package/bin/build/server/aliases.mjs +112 -0
- package/bin/build/server/babel.config.js +24 -0
- package/bin/build/server/banner.mjs +20 -0
- package/bin/build/server/bundle.mjs +111 -0
- package/bin/build/server/fix.mjs +15 -0
- package/bin/build/server/index.mjs +69 -0
- package/bin/build/server/options.mjs +83 -0
- package/bin/create/auth.mjs +23 -0
- package/bin/create/copy.mjs +175 -0
- package/bin/create/docker.mjs +25 -0
- package/bin/create/index.mjs +137 -0
- package/bin/create/pkgjson.mjs +72 -0
- package/bin/create/prepare-template.mjs +158 -0
- package/bin/create/validation.mjs +27 -0
- package/bin/dev/dev.mjs +32 -23
- package/bin/dev/dev_start.mjs +6 -5
- package/bin/index.mjs +94 -52
- package/bin/prod-bin/create-bin.mjs +42 -27
- package/bin/prod-bin/run.mjs +13 -9
- package/bin/{prod-run → run}/pid.mjs +4 -4
- package/bin/run/restart.mjs +13 -0
- package/bin/run/start.mjs +18 -0
- package/bin/run/stop.mjs +20 -0
- package/bin/util.mjs +35 -11
- package/package.json +59 -39
- package/src/config/.env +34 -12
- package/src/config/defaults.mjs +253 -185
- package/src/config/env.mjs +40 -22
- package/src/config/index.mjs +19 -24
- package/src/config/util.mjs +25 -10
- package/src/db-conn.mjs +34 -0
- package/src/engines/cron/emails.mjs +10 -5
- package/src/engines/cron/index.mjs +45 -51
- package/src/engines/cron/init.mjs +16 -17
- package/src/engines/cron/ipsum.mjs +65 -60
- package/src/engines/cron/syscheck.mjs +30 -30
- package/src/engines/emailer/index.mjs +1 -2
- package/src/engines/emailer/queue.mjs +14 -20
- package/src/engines/emailer/transporter.mjs +86 -74
- package/src/engines/geoip/index.mjs +23 -28
- package/src/engines/http/index.mjs +26 -15
- package/src/engines/logger/buildErrorEmailBody.mjs +72 -0
- package/src/engines/logger/index.mjs +114 -122
- package/src/engines/logger/injectStackTrace.mjs +59 -0
- package/src/engines/logger/logger_mail.mjs +47 -61
- package/src/engines/logger/reopenTransportOnHupSignal.mjs +12 -13
- package/src/engines/parser/Parser.mjs +77 -60
- package/src/engines/parser/index.mjs +1 -1
- package/src/engines/schema/diffObjs.mjs +41 -0
- package/src/engines/schema/index.mjs +4 -0
- package/src/engines/schema/input.mjs +54 -0
- package/src/engines/schema/output.mjs +66 -0
- package/src/engines/socket/index.mjs +44 -46
- package/src/index.mjs +15 -10
- package/src/middleware/auth/basic.mjs +41 -40
- package/src/middleware/auth/custom.mjs +10 -13
- package/src/middleware/auth/guest.mjs +27 -27
- package/src/middleware/auth/passport/index.mjs +374 -0
- package/src/middleware/auth/passport/session/index.mjs +43 -0
- package/src/middleware/auth/{credentials → passport}/session/store.mjs +35 -15
- package/src/middleware/auth/passport/session/store_koa_redis.mjs +3 -0
- package/src/middleware/context/cache/index.mjs +78 -33
- package/src/middleware/context/cache/options.mjs +19 -21
- package/src/middleware/context/db.mjs +45 -20
- package/src/middleware/context/index.mjs +12 -12
- package/src/middleware/extra.mjs +4 -5
- package/src/middleware/http/body.mjs +25 -25
- package/src/middleware/http/catcher.mjs +81 -8
- package/src/middleware/http/custom_blacklist.mjs +19 -16
- package/src/middleware/http/headers.mjs +37 -34
- package/src/middleware/http/ratelimit.mjs +16 -23
- package/src/middleware/http/request.mjs +60 -65
- package/src/middleware/routes/catch_js_error.mjs +30 -23
- package/src/middleware/routes/robots.mjs +4 -7
- package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +108 -90
- package/src/middleware/routes/router/crud/getCrudConfig.mjs +31 -55
- package/src/middleware/routes/router/defaults.mjs +6 -19
- package/src/middleware/routes/router/index.mjs +17 -21
- package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +227 -50
- package/src/middleware/routes/router/queries/getQueriesConfig.mjs +45 -55
- package/src/middleware/routes/router/utils.mjs +41 -26
- package/src/middleware/ssr/context.mjs +5 -7
- package/src/middleware/ssr/html.mjs +66 -43
- package/src/middleware/ssr/loader.mjs +11 -14
- package/src/middleware/ssr/ssr_render.mjs +39 -22
- package/src/middleware/static/index.mjs +33 -14
- package/src/middleware/vite/devserver.mjs +38 -22
- package/src/middleware/vite/watcher.mjs +12 -14
- package/src/server-cron.mjs +13 -8
- package/src/server-dev.mjs +13 -16
- package/src/server.mjs +49 -51
- package/template/.agent/skills/miolo-app-arch/SKILL.md +218 -0
- package/template/.agent/skills/miolo-auth/SKILL.md +450 -0
- package/template/.agent/skills/miolo-cli-router/SKILL.md +394 -0
- package/template/.agent/skills/miolo-database/SKILL.md +358 -0
- package/template/.agent/skills/miolo-react-patterns/SKILL.md +426 -0
- package/template/.agent/skills/miolo-routing/SKILL.md +326 -0
- package/template/.agent/skills/miolo-schemas/SKILL.md +329 -0
- package/template/.agent/skills/miolo-session-context/SKILL.md +397 -0
- package/template/.agent/skills/miolo-ssr/SKILL.md +433 -0
- package/template/.editorconfig +18 -0
- package/template/.env +120 -0
- package/template/biome.json +63 -0
- package/template/components.json +21 -0
- package/template/db/init.sh +89 -0
- package/template/db/sql/00_drop.sql +2 -0
- package/template/db/sql/01_users.sql +31 -0
- package/template/db/sql/02_todos.sql +20 -0
- package/template/docker/Dockerfile +13 -0
- package/template/docker/docker-compose.yaml +79 -0
- package/template/gitignore +42 -0
- package/template/jsconfig.json +18 -0
- package/template/package.json +88 -0
- package/template/postcss.config.js +9 -0
- package/template/src/cli/App.jsx +25 -0
- package/template/src/cli/components/JsonTreeViewer.jsx +128 -0
- package/template/src/cli/components/shadcn-io/spinner/index.jsx +232 -0
- package/template/src/cli/components/stepper.jsx +408 -0
- package/template/src/cli/components/ui/avatar.jsx +36 -0
- package/template/src/cli/components/ui/badge.jsx +31 -0
- package/template/src/cli/components/ui/breadcrumb.jsx +97 -0
- package/template/src/cli/components/ui/card.jsx +73 -0
- package/template/src/cli/components/ui/collapsible.jsx +16 -0
- package/template/src/cli/components/ui/dropdown-menu.jsx +179 -0
- package/template/src/cli/components/ui/field.jsx +217 -0
- package/template/src/cli/components/ui/input.jsx +19 -0
- package/template/src/cli/components/ui/label.jsx +17 -0
- package/template/src/cli/components/ui/pagination.jsx +99 -0
- package/template/src/cli/components/ui/patched/alert.jsx +56 -0
- package/template/src/cli/components/ui/patched/button.jsx +45 -0
- package/template/src/cli/components/ui/patched/dialog.jsx +114 -0
- package/template/src/cli/components/ui/patched/sidebar.jsx +660 -0
- package/template/src/cli/components/ui/select.jsx +141 -0
- package/template/src/cli/components/ui/separator.jsx +21 -0
- package/template/src/cli/components/ui/sheet.jsx +115 -0
- package/template/src/cli/components/ui/skeleton.jsx +13 -0
- package/template/src/cli/components/ui/sonner.jsx +22 -0
- package/template/src/cli/components/ui/switch.jsx +25 -0
- package/template/src/cli/components/ui/table.jsx +88 -0
- package/template/src/cli/components/ui/textarea.jsx +16 -0
- package/template/src/cli/components/ui/tooltip.jsx +45 -0
- package/template/src/cli/config/store_keys.mjs +2 -0
- package/template/src/cli/context/data/DataContext.jsx +5 -0
- package/template/src/cli/context/data/DataProvider.jsx +44 -0
- package/template/src/cli/context/data/useBreads.mjs +15 -0
- package/template/src/cli/context/data/useDataContext.mjs +4 -0
- package/template/src/cli/context/session/SessionContext.mjs +4 -0
- package/template/src/cli/context/session/SessionProvider.jsx +31 -0
- package/template/src/cli/context/session/makePermissioner.mjs +34 -0
- package/template/src/cli/context/session/useSessionContext.mjs +6 -0
- package/template/src/cli/context/theme/ThemeContext.mjs +4 -0
- package/template/src/cli/context/theme/ThemeProvider.jsx +49 -0
- package/template/src/cli/context/theme/useThemeContext.mjs +6 -0
- package/template/src/cli/context/ui/UIContext.jsx +5 -0
- package/template/src/cli/context/ui/UIProvider.jsx +16 -0
- package/template/src/cli/context/ui/useUIContext.mjs +4 -0
- package/template/src/cli/context/util.mjs +17 -0
- package/template/src/cli/entry-cli.jsx +33 -0
- package/template/src/cli/hooks/useIsMobile.mjs +19 -0
- package/template/src/cli/hooks/useStoragedState.mjs +63 -0
- package/template/src/cli/index.html +29 -0
- package/template/src/cli/layout/app-sidebar.jsx +25 -0
- package/template/src/cli/layout/main-layout.jsx +63 -0
- package/template/src/cli/layout/nav-last-todos.jsx +72 -0
- package/template/src/cli/layout/nav-main.jsx +39 -0
- package/template/src/cli/layout/nav-user.jsx +105 -0
- package/template/src/cli/layout/prop-switcher.jsx +93 -0
- package/template/src/cli/lib/utils.mjs +10 -0
- package/template/src/cli/pages/Index.jsx +13 -0
- package/template/src/cli/pages/IndexOffline.jsx +13 -0
- package/template/src/cli/pages/IndexOnline.jsx +18 -0
- package/template/src/cli/pages/dash/Dashboard.jsx +29 -0
- package/template/src/cli/pages/offline/Login.jsx +43 -0
- package/template/src/cli/pages/offline/LoginForm.jsx +115 -0
- package/template/src/cli/pages/security/Security.jsx +39 -0
- package/template/src/cli/pages/security/SecurityForm.jsx +106 -0
- package/template/src/cli/pages/todos/TodoActions.jsx +99 -0
- package/template/src/cli/pages/todos/TodoAdd.jsx +43 -0
- package/template/src/cli/pages/todos/TodoList.jsx +60 -0
- package/template/src/cli/pages/todos/Todos.jsx +23 -0
- package/template/src/cli/pages/todos/context/TodosContext.jsx +5 -0
- package/template/src/cli/pages/todos/context/TodosProvider.jsx +191 -0
- package/template/src/cli/pages/todos/context/useTodosContext.mjs +4 -0
- package/template/src/ns/models/Todo.mjs +29 -0
- package/template/src/ns/models/TodoList.mjs +8 -0
- package/template/src/ns/models/User.mjs +40 -0
- package/template/src/server/bot/check_today.mjs +10 -0
- package/template/src/server/io/cache/base.mjs +21 -0
- package/template/src/server/io/db/filter.mjs +92 -0
- package/template/src/server/io/db/todos/delete.mjs +29 -0
- package/template/src/server/io/db/todos/find.mjs +13 -0
- package/template/src/server/io/db/todos/read.mjs +83 -0
- package/template/src/server/io/db/todos/toggle.mjs +37 -0
- package/template/src/server/io/db/todos/upsave.mjs +32 -0
- package/template/src/server/io/db/triggers/user.mjs +13 -0
- package/template/src/server/io/db/users/auth.mjs +132 -0
- package/template/src/server/io/db/users/pwd.mjs +38 -0
- package/template/src/server/io/db/users/save.mjs +17 -0
- package/template/src/server/miolo/auth/basic.mjs +15 -0
- package/template/src/server/miolo/auth/guest.mjs +3 -0
- package/template/src/server/miolo/auth/passport.mjs +73 -0
- package/template/src/server/miolo/cache.mjs +11 -0
- package/template/src/server/miolo/cron/foo.mjs +7 -0
- package/template/src/server/miolo/cron/index.mjs +28 -0
- package/template/src/server/miolo/cron/invalidate.mjs +21 -0
- package/template/src/server/miolo/db.mjs +36 -0
- package/template/src/server/miolo/http.mjs +14 -0
- package/template/src/server/miolo/index.mjs +43 -0
- package/template/src/server/miolo/routes/crud.mjs +16 -0
- package/template/src/server/miolo/routes/index.mjs +8 -0
- package/template/src/server/miolo/ssr/entry-server.jsx +13 -0
- package/template/src/server/miolo/ssr/loader.mjs +18 -0
- package/template/src/server/routes/index.mjs +66 -0
- package/template/src/server/routes/todos/mod.mjs +52 -0
- package/template/src/server/routes/todos/read.mjs +45 -0
- package/template/src/server/routes/todos/special.mjs +47 -0
- package/template/src/server/routes/users/user.mjs +54 -0
- package/template/src/server/server.mjs +10 -0
- package/template/src/server/utils/crypt.mjs +38 -0
- package/template/src/server/utils/io.mjs +15 -0
- package/template/src/server/utils/pwdfor.mjs +25 -0
- package/template/src/server/utils/schema.mjs +22 -0
- package/template/src/static/img/default/profile.png +0 -0
- package/template/src/static/img/favicon.ico +0 -0
- package/template/src/static/img/miolo_logo.png +0 -0
- package/template/src/static/img/miolo_name.png +0 -0
- package/template/src/static/public/manifest.json +21 -0
- package/template/src/static/public/sw.js +79 -0
- package/template/src/static/style/globals.css +156 -0
- package/template/src/static/style/json-tree.css +54 -0
- package/template/src/static/style/skeleton.css +49 -0
- package/bin/prod-build/build-client.mjs +0 -67
- package/bin/prod-build/build-server.mjs +0 -58
- package/bin/prod-run/restart.mjs +0 -9
- package/bin/prod-run/start.mjs +0 -15
- package/bin/prod-run/stop.mjs +0 -20
- package/src/engines/logger/verify.mjs +0 -22
- package/src/middleware/auth/credentials/index.mjs +0 -151
- package/src/middleware/auth/credentials/session/index.mjs +0 -24
- package/src/middleware/auth/credentials/session/store_koa_redis.mjs +0 -3
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import Router from "@koa/router"
|
|
2
|
+
import passport from "koa-passport"
|
|
3
|
+
import { Strategy as GoogleStrategy } from "passport-google-oauth20"
|
|
4
|
+
import LocalStrategy from "passport-local"
|
|
5
|
+
import { init_session_middleware } from "./session/index.mjs"
|
|
6
|
+
|
|
7
|
+
// local: {
|
|
8
|
+
// get_user_id: (user, done) => done(null, user.id), // default
|
|
9
|
+
// find_user_by_id: (id, done) => done(null, {id: 1}), // ok=> done(null, user) err=> done(error, null)
|
|
10
|
+
// local_auth_user: (username, password, done) => done(null, {id: 1})
|
|
11
|
+
// // auth=> done(null, user) noauth=> done(null, false, {message: ''}) err=> done(error, null)
|
|
12
|
+
// local_url_login : '/login',
|
|
13
|
+
// local_url_logout: '/logout',
|
|
14
|
+
// local_url_login_redirect: undefined
|
|
15
|
+
// local_url_logout_redirect: '/'
|
|
16
|
+
// google_auth_user: (accessToken, refreshToken, profile, done, ctx) => done(null, {id: 1})
|
|
17
|
+
// // auth=> done(null, user) noauth=> done(null, false, {message: ''}) err=> done(error, null)
|
|
18
|
+
// google_client_id: 'your-google-client-id',
|
|
19
|
+
// google_client_secret: 'your-google-client-secret',
|
|
20
|
+
// google_url_login : '/auth/google',
|
|
21
|
+
// google_url_callback : '/auth/google/callback',
|
|
22
|
+
// google_url_logout: '/logout',
|
|
23
|
+
// google_url_login_redirect: undefined
|
|
24
|
+
// google_url_logout_redirect: '/'
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
const def_get_user_id = async (user, _ctx) => user?.id
|
|
28
|
+
|
|
29
|
+
const def_find_user_by_id = async (_id, _ctx) => {
|
|
30
|
+
throw new Error("You need to define auth.passport.find_user_by_id")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const def_local_auth_user = async (_username, _password, _ctx) => {
|
|
34
|
+
throw new Error("You need to define auth.passport.local_auth_user")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const def_google_auth_user = async (_accessToken, _refreshToken, _profile, _ctx) => {
|
|
38
|
+
throw new Error("You need to define auth.passport.google_auth_user")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const init_passport_auth_middleware = (app, options, sessionConfig, cacheConfig) => {
|
|
42
|
+
const {
|
|
43
|
+
get_user_id,
|
|
44
|
+
find_user_by_id,
|
|
45
|
+
local_auth_user,
|
|
46
|
+
local_url_login,
|
|
47
|
+
local_url_logout,
|
|
48
|
+
local_url_login_redirect,
|
|
49
|
+
local_url_logout_redirect,
|
|
50
|
+
google_auth_user,
|
|
51
|
+
google_client_id,
|
|
52
|
+
google_client_secret,
|
|
53
|
+
google_url_login,
|
|
54
|
+
google_url_callback,
|
|
55
|
+
google_url_logout,
|
|
56
|
+
google_url_login_redirect,
|
|
57
|
+
google_url_logout_redirect
|
|
58
|
+
} = options
|
|
59
|
+
|
|
60
|
+
//const local_options = {}
|
|
61
|
+
|
|
62
|
+
// fallback funcs
|
|
63
|
+
const get_user_id_f = get_user_id || def_get_user_id
|
|
64
|
+
const find_user_by_id_f = find_user_by_id || def_find_user_by_id
|
|
65
|
+
const local_auth_user_f = local_auth_user || def_local_auth_user
|
|
66
|
+
const local_url_login_f = local_url_login || "/login"
|
|
67
|
+
const local_url_logout_f = local_url_logout || "/logout"
|
|
68
|
+
const google_auth_user_f = google_auth_user || def_google_auth_user
|
|
69
|
+
|
|
70
|
+
const google_url_login_f = google_url_login || "/auth/google"
|
|
71
|
+
const google_url_callback_f = google_url_callback || "/auth/google/callback"
|
|
72
|
+
const google_url_logout_f = google_url_logout || "/logout"
|
|
73
|
+
|
|
74
|
+
// init passport
|
|
75
|
+
const serialize_user = (ctx) => (user, done) => {
|
|
76
|
+
process.nextTick(() => {
|
|
77
|
+
try {
|
|
78
|
+
ctx.miolo.logger.debug(`[auth][passport] serializing user...`)
|
|
79
|
+
ctx.sessionId = ctx.session?.externalKey
|
|
80
|
+
? ctx.getSessionStoreKey(ctx.session?.externalKey)
|
|
81
|
+
: undefined
|
|
82
|
+
get_user_id_f(user, ctx).then((uid) => {
|
|
83
|
+
return done(null, uid || false)
|
|
84
|
+
})
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const msg = `Error serializing user: ${error}`
|
|
87
|
+
ctx.miolo.logger.error(`[auth][passport] ${msg}`)
|
|
88
|
+
return done(null, false, { message: msg })
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const deserialize_user = (ctx) => (id, done) => {
|
|
94
|
+
process.nextTick(() => {
|
|
95
|
+
try {
|
|
96
|
+
ctx.miolo.logger.debug(`[auth][passport] deserializing user...`)
|
|
97
|
+
ctx.sessionId = ctx.session?.externalKey
|
|
98
|
+
? ctx.getSessionStoreKey(ctx.session?.externalKey)
|
|
99
|
+
: undefined
|
|
100
|
+
find_user_by_id_f(id, ctx).then((user) => {
|
|
101
|
+
return done(null, user || false)
|
|
102
|
+
})
|
|
103
|
+
} catch (error) {
|
|
104
|
+
const msg = `Error deserializing user: ${error}`
|
|
105
|
+
ctx.miolo.logger.error(`[auth][passport] ${msg}`)
|
|
106
|
+
return done(null, false, { message: msg })
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const local_strategy = (ctx) =>
|
|
112
|
+
new LocalStrategy.Strategy((username, password, done) => {
|
|
113
|
+
ctx.sessionId = ctx.session?.externalKey
|
|
114
|
+
? ctx.getSessionStoreKey(ctx.session?.externalKey)
|
|
115
|
+
: undefined
|
|
116
|
+
try {
|
|
117
|
+
local_auth_user_f(username, password, ctx).then(([user, msg]) => {
|
|
118
|
+
ctx.body = {
|
|
119
|
+
authenticated: user || false,
|
|
120
|
+
message: msg,
|
|
121
|
+
user: user,
|
|
122
|
+
config: {
|
|
123
|
+
auth_method: "local"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return done(null, user || false, { message: msg || "" })
|
|
127
|
+
})
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const msg = `Error local auth user: ${error}`
|
|
130
|
+
ctx.miolo.logger.error(`[auth][passport] ${msg}`)
|
|
131
|
+
return done(null, false, { message: msg })
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
let google_strategy
|
|
136
|
+
|
|
137
|
+
if (google_client_id) {
|
|
138
|
+
google_strategy = (ctx) =>
|
|
139
|
+
new GoogleStrategy(
|
|
140
|
+
{
|
|
141
|
+
clientID: google_client_id,
|
|
142
|
+
clientSecret: google_client_secret,
|
|
143
|
+
callbackURL: google_url_callback_f,
|
|
144
|
+
passReqToCallback: true,
|
|
145
|
+
proxy: process.env.NODE_ENV === "production"
|
|
146
|
+
},
|
|
147
|
+
(_req, accessToken, refreshToken, profile, done) => {
|
|
148
|
+
ctx.sessionId = ctx.session?.externalKey
|
|
149
|
+
? ctx.getSessionStoreKey(ctx.session?.externalKey)
|
|
150
|
+
: undefined
|
|
151
|
+
try {
|
|
152
|
+
google_auth_user_f(accessToken, refreshToken, profile, ctx).then(([user, msg]) => {
|
|
153
|
+
ctx.body = {
|
|
154
|
+
authenticated: user || false,
|
|
155
|
+
message: msg,
|
|
156
|
+
user: user,
|
|
157
|
+
config: {
|
|
158
|
+
auth_method: "google"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return done(null, user || false, { message: msg || "" })
|
|
162
|
+
})
|
|
163
|
+
} catch (error) {
|
|
164
|
+
const msg = `Error google auth user: ${error}`
|
|
165
|
+
ctx.miolo.logger.error(`[auth][passport] ${msg}`)
|
|
166
|
+
return done(null, false, { message: msg })
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
app.use((ctx, next) => {
|
|
173
|
+
passport.serializeUser(serialize_user(ctx))
|
|
174
|
+
passport.deserializeUser(deserialize_user(ctx))
|
|
175
|
+
passport.use(local_strategy(ctx))
|
|
176
|
+
if (google_client_id) {
|
|
177
|
+
passport.use("google", google_strategy(ctx))
|
|
178
|
+
}
|
|
179
|
+
return next()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
init_session_middleware(app, sessionConfig, cacheConfig)
|
|
183
|
+
|
|
184
|
+
app.use(passport.initialize())
|
|
185
|
+
app.use(passport.session())
|
|
186
|
+
|
|
187
|
+
async function _ensure_ctx_user(ctx, next) {
|
|
188
|
+
try {
|
|
189
|
+
if (ctx.session.authenticated) {
|
|
190
|
+
ctx.session.user = ctx.state.user
|
|
191
|
+
}
|
|
192
|
+
} catch (_) {}
|
|
193
|
+
await next()
|
|
194
|
+
}
|
|
195
|
+
app.use(_ensure_ctx_user)
|
|
196
|
+
|
|
197
|
+
// handle auth routes
|
|
198
|
+
const handleLocalLogIn = (ctx, _next) => {
|
|
199
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - authenticating...`)
|
|
200
|
+
return passport.authenticate("local", async (err, user, info, _status) => {
|
|
201
|
+
const noUser = user === false || user === undefined || user === null
|
|
202
|
+
const hasErr = err !== undefined && err !== null
|
|
203
|
+
if (noUser || hasErr) {
|
|
204
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - user not authenticated`)
|
|
205
|
+
ctx.session.user = undefined
|
|
206
|
+
ctx.session.authenticated = false
|
|
207
|
+
ctx.session.auth_method = undefined
|
|
208
|
+
ctx.sessionId = undefined
|
|
209
|
+
|
|
210
|
+
// This will show error logs on the catcher middleware
|
|
211
|
+
// ctx.throw(401)
|
|
212
|
+
|
|
213
|
+
ctx.status = 401
|
|
214
|
+
|
|
215
|
+
ctx.body = {
|
|
216
|
+
ok: false,
|
|
217
|
+
data: {
|
|
218
|
+
user: undefined,
|
|
219
|
+
authenticated: false,
|
|
220
|
+
info: info
|
|
221
|
+
},
|
|
222
|
+
error: err?.message || err?.stack || err
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - user authenticated`)
|
|
226
|
+
await ctx.login(user)
|
|
227
|
+
ctx.session.user = user // ctx.state.user
|
|
228
|
+
ctx.session.authenticated = true
|
|
229
|
+
ctx.session.auth_method = "local"
|
|
230
|
+
|
|
231
|
+
ctx.body = {
|
|
232
|
+
ok: true,
|
|
233
|
+
data: {
|
|
234
|
+
user: user,
|
|
235
|
+
authenticated: true,
|
|
236
|
+
config: {
|
|
237
|
+
auth_method: "local"
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (local_url_login_redirect !== undefined) {
|
|
243
|
+
ctx.redirect(local_url_login_redirect)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
})(ctx)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// handle auth routes
|
|
250
|
+
const handleGoogleLogin = (ctx, next) => {
|
|
251
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleLogin() - authenticating...`)
|
|
252
|
+
|
|
253
|
+
const redirectUrl = ctx.query.redirect || "/"
|
|
254
|
+
|
|
255
|
+
ctx.miolo.logger.info(
|
|
256
|
+
`[auth][google] handleGoogleLogin() - authenticating with redirectUrl: ${redirectUrl}`
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
const strategy = passport.authenticate("google", {
|
|
260
|
+
scope: ["profile", "email"],
|
|
261
|
+
state: redirectUrl
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
return strategy(ctx, next)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const handleGoogleCallback = (ctx, next) => {
|
|
268
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - authenticating...`)
|
|
269
|
+
return passport.authenticate("google", async (err, user, info, _status) => {
|
|
270
|
+
if (err || user === false) {
|
|
271
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - user not authenticated`)
|
|
272
|
+
ctx.session.user = undefined
|
|
273
|
+
ctx.session.authenticated = false
|
|
274
|
+
ctx.session.auth_method = undefined
|
|
275
|
+
ctx.sessionId = undefined
|
|
276
|
+
|
|
277
|
+
// This will show error logs on the catcher middleware
|
|
278
|
+
// ctx.throw(401)
|
|
279
|
+
|
|
280
|
+
ctx.status = 401
|
|
281
|
+
|
|
282
|
+
ctx.body = {
|
|
283
|
+
ok: err === undefined,
|
|
284
|
+
data: {
|
|
285
|
+
user: undefined,
|
|
286
|
+
authenticated: false,
|
|
287
|
+
info: info
|
|
288
|
+
},
|
|
289
|
+
error: err
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
ctx.redirect(google_url_logout_redirect || "/")
|
|
293
|
+
} else {
|
|
294
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - user authenticated`)
|
|
295
|
+
await ctx.login(user)
|
|
296
|
+
ctx.session.user = user // ctx.state.user
|
|
297
|
+
ctx.session.authenticated = true
|
|
298
|
+
ctx.session.auth_method = "google"
|
|
299
|
+
|
|
300
|
+
// ctx.body = {
|
|
301
|
+
// ok: true,
|
|
302
|
+
// data: {
|
|
303
|
+
// user: user,
|
|
304
|
+
// authenticated: true,
|
|
305
|
+
// config: {
|
|
306
|
+
// auth_method: "google"
|
|
307
|
+
// }
|
|
308
|
+
// }
|
|
309
|
+
// }
|
|
310
|
+
|
|
311
|
+
const redirectUrl = ctx.query.state || google_url_login_redirect || "/"
|
|
312
|
+
|
|
313
|
+
ctx.miolo.logger.info(
|
|
314
|
+
`[auth][google] handleGoogleCallback() - redirecting to: ${redirectUrl}. query.state: ${ctx.query.state}. google_url_login_redirect: ${google_url_login_redirect}`
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
ctx.redirect(redirectUrl)
|
|
318
|
+
}
|
|
319
|
+
})(ctx, next)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const handleLogOut = async (ctx, _next) => {
|
|
323
|
+
if (ctx.session.authenticated) {
|
|
324
|
+
ctx.miolo.logger.debug(`[auth][passport] handleLogOut() - logging out...`)
|
|
325
|
+
|
|
326
|
+
ctx.session.user = undefined
|
|
327
|
+
ctx.session.authenticated = false
|
|
328
|
+
ctx.session.auth_method = undefined
|
|
329
|
+
ctx.sessionId = undefined
|
|
330
|
+
|
|
331
|
+
ctx.body = {
|
|
332
|
+
ok: true,
|
|
333
|
+
data: {
|
|
334
|
+
user: undefined,
|
|
335
|
+
authenticated: false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (local_url_logout_redirect !== undefined) {
|
|
340
|
+
ctx.redirect(local_url_logout_redirect)
|
|
341
|
+
} else {
|
|
342
|
+
await ctx.logout()
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
ctx.miolo.logger.debug(`[auth][passport] handleLogOut() - logging out (unauthed)...`)
|
|
346
|
+
|
|
347
|
+
// This will show error logs on the catcher middleware
|
|
348
|
+
// ctx.throw(401)
|
|
349
|
+
|
|
350
|
+
ctx.status = 401
|
|
351
|
+
ctx.body = {
|
|
352
|
+
ok: true,
|
|
353
|
+
data: {
|
|
354
|
+
user: undefined,
|
|
355
|
+
authenticated: false
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Init the router
|
|
362
|
+
const login_router = new Router()
|
|
363
|
+
login_router.post(local_url_login_f, handleLocalLogIn)
|
|
364
|
+
login_router.get(local_url_logout_f, handleLogOut)
|
|
365
|
+
login_router.post(local_url_logout_f, handleLogOut)
|
|
366
|
+
login_router.get(google_url_login_f, handleGoogleLogin)
|
|
367
|
+
login_router.get(google_url_callback_f, handleGoogleCallback)
|
|
368
|
+
login_router.get(google_url_logout_f, handleLogOut)
|
|
369
|
+
login_router.post(google_url_logout_f, handleLogOut)
|
|
370
|
+
|
|
371
|
+
app.use(login_router.routes())
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export { init_passport_auth_middleware }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createSession } from "koa-session"
|
|
2
|
+
// import store_koa_redis from './store_koa_redis.mjs'
|
|
3
|
+
import { init_session_cache_store } from "./store.mjs"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Middleware for session
|
|
7
|
+
* @param ctx
|
|
8
|
+
* @param next
|
|
9
|
+
*/
|
|
10
|
+
function init_session_middleware(app, sessionConfig, cacheConfig) {
|
|
11
|
+
const store = init_session_cache_store(cacheConfig, app.context.miolo.logger)
|
|
12
|
+
|
|
13
|
+
app.keys = [sessionConfig.secret || "*secret*"]
|
|
14
|
+
|
|
15
|
+
const options = {
|
|
16
|
+
// store: store_koa_redis,
|
|
17
|
+
store,
|
|
18
|
+
...(sessionConfig.options || {})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
app.context.miolo.session = {
|
|
22
|
+
store,
|
|
23
|
+
options
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
app.use(createSession(options, app))
|
|
27
|
+
|
|
28
|
+
app.use(async (ctx, next) => {
|
|
29
|
+
ctx.getSessionStoreKey = (externalKey) => {
|
|
30
|
+
return store.getInnerKey(externalKey)
|
|
31
|
+
}
|
|
32
|
+
await next()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
app.initSessionStore = async () => {
|
|
36
|
+
await store.initCache()
|
|
37
|
+
}
|
|
38
|
+
app.closeSessionStore = async () => {
|
|
39
|
+
await store.closeCache()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { init_session_middleware }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {cacheiro} from
|
|
2
|
-
import { miolo_cacher_options_for_session } from
|
|
1
|
+
import { cacheiro } from "cacheiro"
|
|
2
|
+
import { miolo_cacher_options_for_session } from "../../../context/cache/options.mjs"
|
|
3
3
|
|
|
4
4
|
class SessionStore {
|
|
5
5
|
constructor(options, logger) {
|
|
@@ -8,52 +8,72 @@ class SessionStore {
|
|
|
8
8
|
this._cache = undefined
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
async
|
|
12
|
-
if (this._cache
|
|
11
|
+
async initCache() {
|
|
12
|
+
if (this._cache === undefined) {
|
|
13
13
|
this.logger.silly(`[session-store] Initing store`)
|
|
14
14
|
this._cache = await cacheiro(this.options)
|
|
15
15
|
}
|
|
16
16
|
return this._cache
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
async closeCache() {
|
|
20
|
+
if (this._cache !== undefined) {
|
|
21
|
+
this.logger.silly(`[session-store] Closing store`)
|
|
22
|
+
try {
|
|
23
|
+
await this._cache.close()
|
|
24
|
+
} catch (error) {
|
|
25
|
+
this.logger.warn(error)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: keep definition for koa-session store
|
|
19
31
|
async get(key, maxAge, { rolling, ctx }) {
|
|
20
|
-
|
|
21
|
-
const cache = await this.init_cache()
|
|
32
|
+
const cache = await this.initCache()
|
|
22
33
|
const jvalue = await cache.getItem(key)
|
|
23
34
|
try {
|
|
24
35
|
const value = JSON.parse(jvalue)
|
|
25
36
|
this.logger.silly(`[session-store] Get session for ${key}: ${JSON.stringify(value)}`)
|
|
26
37
|
//console.log(`[session-store] Get session for ${key}: ${JSON.stringify(value)}`)
|
|
27
38
|
return value
|
|
28
|
-
} catch(_) {
|
|
39
|
+
} catch (_) {
|
|
29
40
|
this.logger.silly(`[session-store] No session for ${key}`)
|
|
30
41
|
//console.log(`[session-store] No session for ${key}`)
|
|
31
42
|
return undefined
|
|
32
43
|
}
|
|
33
44
|
}
|
|
34
45
|
|
|
46
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: keep definition for koa-session store
|
|
35
47
|
async set(key, sess, maxAge, { rolling, changed, ctx }) {
|
|
36
48
|
this.logger.silly(`[session-store] Set session for ${key}`)
|
|
37
|
-
const cache = await this.
|
|
38
|
-
let svalue
|
|
49
|
+
const cache = await this.initCache()
|
|
50
|
+
let svalue
|
|
39
51
|
try {
|
|
40
52
|
svalue = JSON.stringify(sess)
|
|
41
|
-
} catch(_) {}
|
|
53
|
+
} catch (_) {}
|
|
42
54
|
|
|
43
55
|
// Rely on miolo settings for ttl / maxAge
|
|
44
56
|
await cache.setItem(key, svalue /*, maxAge*/)
|
|
45
57
|
}
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
|
|
59
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: keep definition for koa-session store
|
|
60
|
+
async destroy(key, { ctx }) {
|
|
48
61
|
this.logger.silly(`[session-store] Destroy session for ${key}`)
|
|
49
|
-
const cache = await this.
|
|
62
|
+
const cache = await this.initCache()
|
|
50
63
|
await cache.unsetItem(key)
|
|
51
64
|
}
|
|
52
|
-
}
|
|
53
65
|
|
|
66
|
+
getInnerKey(key) {
|
|
67
|
+
if (this._cache === undefined) {
|
|
68
|
+
this.logger.error("[session-store] Calling getInnerKey() before cache is inited")
|
|
69
|
+
return key
|
|
70
|
+
}
|
|
71
|
+
return this._cache.getInnerKey(key)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
54
74
|
|
|
55
75
|
export function init_session_cache_store(cacheConfig, logger) {
|
|
56
|
-
const options = miolo_cacher_options_for_session({cache: cacheConfig}, logger)
|
|
76
|
+
const options = miolo_cacher_options_for_session({ cache: cacheConfig }, logger)
|
|
57
77
|
const store = new SessionStore(options, logger)
|
|
58
78
|
return store
|
|
59
79
|
}
|
|
@@ -1,61 +1,106 @@
|
|
|
1
|
-
import { cacheiro } from
|
|
2
|
-
import { miolo_cacher_options_for_custom } from
|
|
1
|
+
import { cacheiro } from "cacheiro"
|
|
2
|
+
import { miolo_cacher_options_for_custom, miolo_cacher_options_for_fly } from "./options.mjs"
|
|
3
3
|
|
|
4
|
-
let
|
|
4
|
+
let _glob_cache_mother
|
|
5
|
+
const _local_cache_instances = new Map()
|
|
6
|
+
|
|
7
|
+
const _get_cache_mother = async (config, logger) => {
|
|
8
|
+
if (_glob_cache_mother === undefined) {
|
|
9
|
+
const default_options = miolo_cacher_options_for_fly(
|
|
10
|
+
config,
|
|
11
|
+
{
|
|
12
|
+
type: process.env.MIOLO_CACHE_TYPE || "combined",
|
|
13
|
+
namespace: "miolo-cache-mother"
|
|
14
|
+
},
|
|
15
|
+
logger
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_glob_cache_mother = await cacheiro(default_options)
|
|
19
|
+
}
|
|
20
|
+
return _glob_cache_mother
|
|
21
|
+
}
|
|
5
22
|
|
|
6
23
|
export function init_context_cache(config, logger) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
return _glob_cache_stores
|
|
24
|
+
const custom_options = miolo_cacher_options_for_custom(config, logger)
|
|
25
|
+
|
|
26
|
+
const _init_cache_instance = async (name) => {
|
|
27
|
+
const cache_mother = await _get_cache_mother(config, logger)
|
|
28
|
+
|
|
29
|
+
const cache_instance = await cacheiro(custom_options?.[name] || {})
|
|
30
|
+
await cache_mother.setItem(name, "1")
|
|
31
|
+
_local_cache_instances.set(name, cache_instance)
|
|
32
|
+
return cache_instance
|
|
20
33
|
}
|
|
21
34
|
|
|
35
|
+
const init = async () => {
|
|
36
|
+
await _get_cache_mother(config, logger)
|
|
37
|
+
}
|
|
22
38
|
|
|
23
39
|
const get_cache = async (name) => {
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
if (_local_cache_instances.has(name)) {
|
|
41
|
+
return _local_cache_instances.get(name)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cache_mother = await _get_cache_mother(config, logger)
|
|
45
|
+
|
|
46
|
+
const exists_in_mother = await cache_mother.getItem(name)
|
|
47
|
+
if (exists_in_mother) {
|
|
48
|
+
const cache_instance = await cacheiro(custom_options?.[name] || {})
|
|
49
|
+
_local_cache_instances.set(name, cache_instance)
|
|
50
|
+
return cache_instance
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return await _init_cache_instance(name)
|
|
26
54
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
55
|
+
|
|
56
|
+
const get_cache_names = async (pattern = "*") => {
|
|
57
|
+
const cache_mother = await _get_cache_mother(config, logger)
|
|
58
|
+
|
|
59
|
+
return await cache_mother.getKeys(pattern)
|
|
30
60
|
}
|
|
31
61
|
|
|
32
|
-
const drop_cache = async (name, clean) => {
|
|
33
|
-
const cache_stores = await _init_cache_stores()
|
|
62
|
+
const drop_cache = async (name, clean = true) => {
|
|
34
63
|
if (clean) {
|
|
35
64
|
const cache = await get_cache(name)
|
|
36
|
-
cache
|
|
65
|
+
if (cache) {
|
|
66
|
+
try {
|
|
67
|
+
await cache.close()
|
|
68
|
+
} catch (error) {
|
|
69
|
+
logger.warn(error)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
37
72
|
}
|
|
38
|
-
delete
|
|
73
|
+
_local_cache_instances.delete(name)
|
|
74
|
+
|
|
75
|
+
const cache_mother = await _get_cache_mother(config, logger)
|
|
76
|
+
await cache_mother.unsetItem(name)
|
|
39
77
|
}
|
|
40
78
|
|
|
41
|
-
const
|
|
79
|
+
const close = async (clean = true) => {
|
|
80
|
+
const cache_mother = await _get_cache_mother(config, logger)
|
|
81
|
+
|
|
42
82
|
if (clean) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
83
|
+
for (const cache of _local_cache_instances.values()) {
|
|
84
|
+
try {
|
|
85
|
+
await cache.close()
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logger.warn(error)
|
|
88
|
+
}
|
|
46
89
|
}
|
|
47
90
|
}
|
|
48
|
-
|
|
49
|
-
|
|
91
|
+
_local_cache_instances.clear()
|
|
92
|
+
|
|
93
|
+
await cache_mother.close()
|
|
94
|
+
_glob_cache_mother = undefined
|
|
50
95
|
}
|
|
51
96
|
|
|
52
97
|
const cache_ctx = {
|
|
98
|
+
init,
|
|
53
99
|
get_cache,
|
|
54
100
|
get_cache_names,
|
|
55
101
|
drop_cache,
|
|
56
|
-
|
|
102
|
+
close
|
|
57
103
|
}
|
|
58
104
|
|
|
59
105
|
return cache_ctx
|
|
60
|
-
|
|
61
106
|
}
|