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,397 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: miolo-session-context
|
|
3
|
+
description: Session and context management for miolo applications. Use when working with user authentication, session state, context properties in routes/middleware (backend), or useMioloContext/SessionProvider (client). For permissions, fetcher, and SSR, see separate skills.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Miolo Session & Context Management
|
|
7
|
+
|
|
8
|
+
Session and authentication context management in miolo applications (backend and client).
|
|
9
|
+
|
|
10
|
+
## Backend (Server-Side Context)
|
|
11
|
+
|
|
12
|
+
In route handlers and middleware, the `ctx` object provides access to request data and session state.
|
|
13
|
+
|
|
14
|
+
### Request Properties
|
|
15
|
+
|
|
16
|
+
Access request data through `ctx.request`:
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
export async function r_create_item(ctx, params) {
|
|
20
|
+
// Request body (POST data)
|
|
21
|
+
const body = ctx.request.body
|
|
22
|
+
|
|
23
|
+
// Client IP address
|
|
24
|
+
const clientIp = ctx.request.ip
|
|
25
|
+
|
|
26
|
+
ctx.miolo.logger.info(`Request from IP: ${clientIp}`)
|
|
27
|
+
|
|
28
|
+
return { ok: true, data: body }
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Available properties:**
|
|
33
|
+
- `ctx.request.body` - POST/PUT request body
|
|
34
|
+
- `ctx.request.ip` - Client IP address
|
|
35
|
+
|
|
36
|
+
### Session Properties (All Auth Methods)
|
|
37
|
+
|
|
38
|
+
Common session properties available regardless of auth strategy:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
export async function r_get_profile(ctx, params) {
|
|
42
|
+
// User object (null if not authenticated)
|
|
43
|
+
const user = ctx.session.user
|
|
44
|
+
|
|
45
|
+
// Authentication status (boolean)
|
|
46
|
+
const isAuth = ctx.session.authenticated
|
|
47
|
+
|
|
48
|
+
// Token (if using guest auth)
|
|
49
|
+
const token = ctx.session.token
|
|
50
|
+
|
|
51
|
+
if (!ctx.session.authenticated) {
|
|
52
|
+
return { ok: false, error: 'Not authenticated' }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { ok: true, data: ctx.session.user }
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Available properties:**
|
|
60
|
+
- `ctx.session.user` - User object (or `null`)
|
|
61
|
+
- `ctx.session.authenticated` - Boolean authentication status
|
|
62
|
+
- `ctx.session.auth_method` - Authentication method (local, google, etc.)
|
|
63
|
+
- `ctx.session.token` - Auth token (guest auth only)
|
|
64
|
+
|
|
65
|
+
### Credentials Auth Methods
|
|
66
|
+
|
|
67
|
+
When using local authentication strategy, additional methods are available:
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
export async function r_user_login(ctx, params) {
|
|
71
|
+
const { username, password } = params
|
|
72
|
+
|
|
73
|
+
// Attempt login
|
|
74
|
+
await ctx.login(username, password)
|
|
75
|
+
|
|
76
|
+
// Check authentication status
|
|
77
|
+
if (ctx.isAuthenticated()) {
|
|
78
|
+
ctx.miolo.logger.info(`User ${ctx.state.user.id} logged in`)
|
|
79
|
+
return { ok: true, user: ctx.state.user }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { ok: false, error: 'Invalid credentials' }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function r_user_logout(ctx, params) {
|
|
86
|
+
ctx.logout()
|
|
87
|
+
return { ok: true }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function r_protected_route(ctx, params) {
|
|
91
|
+
// Check if NOT authenticated
|
|
92
|
+
if (ctx.isUnauthenticated()) {
|
|
93
|
+
return { ok: false, error: 'Authentication required' }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Access authenticated user
|
|
97
|
+
const user = ctx.state.user
|
|
98
|
+
|
|
99
|
+
return { ok: true, data: user }
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Available methods (local auth):**
|
|
104
|
+
- `ctx.isAuthenticated()` - Returns `true` if user is authenticated
|
|
105
|
+
- `ctx.isUnauthenticated()` - Returns `true` if user is NOT authenticated
|
|
106
|
+
- `await ctx.login(username, password)` - Attempt to authenticate user
|
|
107
|
+
- `ctx.logout()` - End user session
|
|
108
|
+
|
|
109
|
+
**User access:**
|
|
110
|
+
- `ctx.state.user` - Authenticated user object (local auth)
|
|
111
|
+
- `ctx.session.user` - User object (all auth methods)
|
|
112
|
+
|
|
113
|
+
### Backend Usage Example
|
|
114
|
+
|
|
115
|
+
Complete route handler using session:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
export async function r_user_operation(ctx, params) {
|
|
119
|
+
try {
|
|
120
|
+
// Check authentication
|
|
121
|
+
if (!ctx.session.authenticated) {
|
|
122
|
+
return { ok: false, error: 'Authentication required' }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Access user data
|
|
126
|
+
const userId = ctx.session.user.id
|
|
127
|
+
const userEmail = ctx.session.user.email
|
|
128
|
+
|
|
129
|
+
// Log with user context
|
|
130
|
+
ctx.miolo.logger.info(`[r_user_operation] User ${userId} performing operation`)
|
|
131
|
+
|
|
132
|
+
// Perform operation
|
|
133
|
+
const result = await db_user_operation(ctx, {
|
|
134
|
+
...params,
|
|
135
|
+
user_id: userId
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return { ok: true, data: result }
|
|
139
|
+
|
|
140
|
+
} catch (error) {
|
|
141
|
+
ctx.miolo.logger.error(`[r_user_operation] Error: ${error}`)
|
|
142
|
+
return { ok: false, error: error?.message }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Client-Side (React Context)
|
|
148
|
+
|
|
149
|
+
### useMioloContext Hook
|
|
150
|
+
|
|
151
|
+
The `useMioloContext` hook from `miolo-react` provides core session functionality:
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
import { useMioloContext } from 'miolo-react'
|
|
155
|
+
|
|
156
|
+
function MyComponent() {
|
|
157
|
+
const {
|
|
158
|
+
user,
|
|
159
|
+
updateUser,
|
|
160
|
+
authenticated,
|
|
161
|
+
fetcher,
|
|
162
|
+
login,
|
|
163
|
+
logout,
|
|
164
|
+
useSsrData
|
|
165
|
+
} = useMioloContext()
|
|
166
|
+
|
|
167
|
+
if (!authenticated) {
|
|
168
|
+
return <div>Please log in</div>
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<div>
|
|
173
|
+
<h1>Welcome {user.name}</h1>
|
|
174
|
+
<button onClick={logout}>Logout</button>
|
|
175
|
+
</div>
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Available properties:**
|
|
181
|
+
- `user` - User object (or `null` if not authenticated)
|
|
182
|
+
- `updateUser(userData)` - Update user data in context
|
|
183
|
+
- `authenticated` - Boolean authentication status
|
|
184
|
+
- `fetcher` - Fetch wrapper with auth (see miolo-fetcher skill)
|
|
185
|
+
- `login(credentials)` - Authenticate user
|
|
186
|
+
- `logout()` - End session
|
|
187
|
+
- `useSsrData()` - Access SSR data (see miolo-ssr skill)
|
|
188
|
+
|
|
189
|
+
### SessionProvider Wrapper
|
|
190
|
+
|
|
191
|
+
The application typically wraps `useMioloContext` in a `SessionProvider` for additional functionality:
|
|
192
|
+
|
|
193
|
+
**File:** `src/cli/context/session/SessionProvider.jsx`
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
import { useState, useEffect } from 'react'
|
|
197
|
+
import { useMioloContext } from 'miolo-react'
|
|
198
|
+
import SessionContext from './SessionContext.mjs'
|
|
199
|
+
import makePermissioner from './makePermissioner.mjs'
|
|
200
|
+
|
|
201
|
+
const SessionProvider = ({ children }) => {
|
|
202
|
+
const { user, ...props } = useMioloContext()
|
|
203
|
+
const [permiss, setPermiss] = useState(makePermissioner(user))
|
|
204
|
+
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
setPermiss(makePermissioner(user))
|
|
207
|
+
}, [user])
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<SessionContext.Provider value={{
|
|
211
|
+
session: user,
|
|
212
|
+
permiss,
|
|
213
|
+
...props
|
|
214
|
+
}}>
|
|
215
|
+
{children}
|
|
216
|
+
</SessionContext.Provider>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export default SessionProvider
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Adds:**
|
|
224
|
+
- `session` - Alias for user object
|
|
225
|
+
- `permiss` - Permissions object (see miolo-permissions skill)
|
|
226
|
+
- Passes through all `useMioloContext` properties
|
|
227
|
+
|
|
228
|
+
### useSessionContext Hook
|
|
229
|
+
|
|
230
|
+
Access the wrapped session context:
|
|
231
|
+
|
|
232
|
+
**File:** `src/cli/context/session/useSessionContext.mjs`
|
|
233
|
+
|
|
234
|
+
```javascript
|
|
235
|
+
import { useContext } from 'react'
|
|
236
|
+
import SessionContext from './SessionContext.mjs'
|
|
237
|
+
|
|
238
|
+
export default function useSessionContext() {
|
|
239
|
+
const context = useContext(SessionContext)
|
|
240
|
+
|
|
241
|
+
if (!context) {
|
|
242
|
+
throw new Error('useSessionContext must be used within SessionProvider')
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return context
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Usage:**
|
|
250
|
+
```javascript
|
|
251
|
+
import useSessionContext from '#cli/context/session/useSessionContext.mjs'
|
|
252
|
+
|
|
253
|
+
function ProfilePage() {
|
|
254
|
+
const {
|
|
255
|
+
session, // User object
|
|
256
|
+
permiss, // Permissions
|
|
257
|
+
authenticated,
|
|
258
|
+
logout
|
|
259
|
+
} = useSessionContext()
|
|
260
|
+
|
|
261
|
+
if (!authenticated) {
|
|
262
|
+
return <LoginPage />
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<div>
|
|
267
|
+
<h1>{session.name}</h1>
|
|
268
|
+
<p>{session.email}</p>
|
|
269
|
+
{permiss.can('admin') && <AdminPanel />}
|
|
270
|
+
<button onClick={logout}>Logout</button>
|
|
271
|
+
</div>
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Client-Side Usage Examples
|
|
277
|
+
|
|
278
|
+
### Login Flow
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
import { useMioloContext } from 'miolo-react'
|
|
282
|
+
|
|
283
|
+
function LoginPage() {
|
|
284
|
+
const { login } = useMioloContext()
|
|
285
|
+
const [username, setUsername] = useState('')
|
|
286
|
+
const [password, setPassword] = useState('')
|
|
287
|
+
|
|
288
|
+
const handleSubmit = async (e) => {
|
|
289
|
+
e.preventDefault()
|
|
290
|
+
|
|
291
|
+
const result = await login({ username, password })
|
|
292
|
+
|
|
293
|
+
if (result.ok) {
|
|
294
|
+
// Login successful, user context updated automatically
|
|
295
|
+
navigate('/dashboard')
|
|
296
|
+
} else {
|
|
297
|
+
alert(result.error)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<form onSubmit={handleSubmit}>
|
|
303
|
+
<input
|
|
304
|
+
value={username}
|
|
305
|
+
onChange={(e) => setUsername(e.target.value)}
|
|
306
|
+
/>
|
|
307
|
+
<input
|
|
308
|
+
type="password"
|
|
309
|
+
value={password}
|
|
310
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
311
|
+
/>
|
|
312
|
+
<button type="submit">Login</button>
|
|
313
|
+
</form>
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Protected Component
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
import useSessionContext from '#cli/context/session/useSessionContext.mjs'
|
|
322
|
+
|
|
323
|
+
function ProtectedComponent() {
|
|
324
|
+
const { authenticated, session } = useSessionContext()
|
|
325
|
+
|
|
326
|
+
if (!authenticated) {
|
|
327
|
+
return null // Or redirect to login
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return (
|
|
331
|
+
<div>
|
|
332
|
+
<h2>Protected Content</h2>
|
|
333
|
+
<p>User ID: {session.id}</p>
|
|
334
|
+
</div>
|
|
335
|
+
)
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Update User Data
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
import { useMioloContext } from 'miolo-react'
|
|
343
|
+
|
|
344
|
+
function ProfileEditor() {
|
|
345
|
+
const { user, updateUser } = useMioloContext()
|
|
346
|
+
|
|
347
|
+
const handleUpdate = async (newData) => {
|
|
348
|
+
const response = await fetch('/api/user/update', {
|
|
349
|
+
method: 'POST',
|
|
350
|
+
body: JSON.stringify(newData)
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
const result = await response.json()
|
|
354
|
+
|
|
355
|
+
if (result.ok) {
|
|
356
|
+
// Update user in context
|
|
357
|
+
updateUser(result.data)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return <ProfileForm onSubmit={handleUpdate} />
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Best Practices
|
|
366
|
+
|
|
367
|
+
### Backend
|
|
368
|
+
|
|
369
|
+
1. **Always check authentication** - Use `ctx.session.authenticated` or `ctx.isAuthenticated()`
|
|
370
|
+
2. **Use auth in routes** - Configure `auth` in route definition (see miolo-routing skill)
|
|
371
|
+
3. **Log with user context** - Include user ID in logs for debugging
|
|
372
|
+
4. **Include user_id in queries** - Enforce data ownership in database queries
|
|
373
|
+
5. **Handle unauthenticated gracefully** - Return appropriate error messages
|
|
374
|
+
|
|
375
|
+
### Client
|
|
376
|
+
|
|
377
|
+
1. **Use SessionProvider** - Wrap useMioloContext for extended functionality
|
|
378
|
+
2. **Check authenticated state** - Always verify before rendering protected content
|
|
379
|
+
3. **Handle login errors** - Display meaningful error messages to users
|
|
380
|
+
4. **Update context on changes** - Use `updateUser()` after profile updates
|
|
381
|
+
5. **Centralize auth logic** - Use contexts, don't duplicate auth checks
|
|
382
|
+
|
|
383
|
+
## Related Skills
|
|
384
|
+
|
|
385
|
+
- **miolo-auth** - Authentication strategies and configuration
|
|
386
|
+
- **miolo-routing** - Route protection and auth configuration
|
|
387
|
+
- **miolo-permissions** - Permission system using `permiss` object
|
|
388
|
+
- **miolo-fetcher** - Authenticated API requests (future skill)
|
|
389
|
+
- **miolo-ssr** - Server-side rendering with session (future skill)
|
|
390
|
+
|
|
391
|
+
## Examples from miolo-sample
|
|
392
|
+
|
|
393
|
+
See actual implementations:
|
|
394
|
+
- `src/server/routes/users/user.mjs` - Backend session usage
|
|
395
|
+
- `src/cli/context/session/SessionProvider.jsx` - SessionProvider wrapper
|
|
396
|
+
- `src/cli/context/session/useSessionContext.mjs` - Session hook
|
|
397
|
+
- `src/cli/pages/Index.jsx` - Auth-based routing
|