mirror of https://github.com/requarks/wiki
parent
dc78af9156
commit
68e6a2787a
@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"$schema": "./backend/node_modules/oxfmt/configuration_schema.json",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
@ -1,14 +1,14 @@
|
||||
{
|
||||
"eslint.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.tabSize": 2,
|
||||
"i18n-ally.localesPaths": [
|
||||
"backend/locales",
|
||||
],
|
||||
"i18n-ally.localesPaths": ["backend/locales"],
|
||||
"i18n-ally.pathMatcher": "{locale}.json",
|
||||
"i18n-ally.keystyle": "flat",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.enabledFrameworks": [
|
||||
"vue"
|
||||
]
|
||||
"i18n-ally.enabledFrameworks": ["vue"],
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,100 +1,204 @@
|
||||
|
||||
/**
|
||||
* Authentication API Routes
|
||||
*/
|
||||
async function routes (app, options) {
|
||||
async function routes(app, options) {
|
||||
/**
|
||||
* GET SITE AUTHENTICATION STRATEGIES
|
||||
*/
|
||||
app.get('/sites/:siteId/auth/strategies', {
|
||||
schema: {
|
||||
summary: 'List all site authentication strategies',
|
||||
tags: ['Authentication'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
app.get(
|
||||
'/sites/:siteId/auth/strategies',
|
||||
{
|
||||
schema: {
|
||||
summary: 'List all site authentication strategies',
|
||||
tags: ['Authentication'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
visibleOnly: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
visibleOnly: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
const site = await WIKI.models.sites.getSiteById({ id: req.params.siteId })
|
||||
const activeStrategies = await WIKI.models.authentication.getStrategies({ enabledOnly: true })
|
||||
const siteStrategies = activeStrategies.map(str => {
|
||||
const authModule = WIKI.data.authentication.find(m => m.key === str.module)
|
||||
const siteStr = site.config.authStrategies.find(s => s.id === str.id) || {}
|
||||
return {
|
||||
id: str.id,
|
||||
displayName: str.displayName,
|
||||
useForm: authModule.useForm,
|
||||
usernameType: authModule.usernameType,
|
||||
color: authModule.color,
|
||||
icon: authModule.icon,
|
||||
order: siteStr.order ?? 0,
|
||||
isVisible: siteStr.isVisible ?? false
|
||||
},
|
||||
async (req, reply) => {
|
||||
const site = await WIKI.models.sites.getSiteById({ id: req.params.siteId })
|
||||
if (!site) {
|
||||
return reply.badRequest('Invalid Site ID')
|
||||
}
|
||||
}).sort((a,b) => a.order - b.order)
|
||||
return req.query.visibleOnly ? siteStrategies.filter(s => s.isVisible) : siteStrategies
|
||||
})
|
||||
const activeStrategies = await WIKI.models.authentication.getStrategies({ enabledOnly: true })
|
||||
const siteStrategies = activeStrategies
|
||||
.map((str) => {
|
||||
const authModule = WIKI.data.authentication.find((m) => m.key === str.module)
|
||||
const siteStr = site.config.authStrategies.find((s) => s.id === str.id) || {}
|
||||
return {
|
||||
id: str.id,
|
||||
displayName: str.displayName,
|
||||
useForm: authModule.useForm,
|
||||
usernameType: authModule.usernameType,
|
||||
color: authModule.color,
|
||||
icon: authModule.icon,
|
||||
order: siteStr.order ?? 0,
|
||||
isVisible: siteStr.isVisible ?? false
|
||||
}
|
||||
})
|
||||
.sort((a, b) => a.order - b.order)
|
||||
return req.query.visibleOnly ? siteStrategies.filter((s) => s.isVisible) : siteStrategies
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* LOGIN USING USER/PASS
|
||||
*/
|
||||
app.post('/sites/:siteId/auth/login', {
|
||||
schema: {
|
||||
summary: 'Login',
|
||||
tags: ['Authentication'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
app.put(
|
||||
'/sites/:siteId/auth/login',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Login',
|
||||
tags: ['Authentication'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['strategyId'],
|
||||
properties: {
|
||||
strategyId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['strategyId', 'username', 'password'],
|
||||
properties: {
|
||||
strategyId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
try {
|
||||
const result = await WIKI.models.users.login(
|
||||
{
|
||||
siteId: req.params.siteId,
|
||||
strategyId: req.body.strategyId,
|
||||
username: req.body.username,
|
||||
password: req.body.password,
|
||||
ip: req.ip
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
req
|
||||
)
|
||||
if (!result) {
|
||||
throw new Error('Unexpected empty login response.')
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
...result
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.message.startsWith('ERR_')) {
|
||||
return reply.badRequest(err.message)
|
||||
} else {
|
||||
WIKI.logger.info(err) // TODO: change to debug once stable
|
||||
return reply.badRequest('ERR_LOGIN_FAILED')
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* CHANGE PASSWORD
|
||||
*/
|
||||
app.put(
|
||||
'/sites/:siteId/auth/changePassword',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Change Password From Login',
|
||||
tags: ['Authentication'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['strategyId', 'continuationToken', 'newPassword'],
|
||||
properties: {
|
||||
strategyId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
},
|
||||
continuationToken: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
newPassword: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
try {
|
||||
const result = await WIKI.models.users.loginChangePassword(
|
||||
{
|
||||
siteId: req.params.siteId,
|
||||
strategyId: req.body.strategyId,
|
||||
continuationToken: req.body.continuationToken,
|
||||
newPassword: req.body.newPassword,
|
||||
ip: req.ip
|
||||
},
|
||||
req
|
||||
)
|
||||
if (!result) {
|
||||
throw new Error('Unexpected empty change password response.')
|
||||
}
|
||||
if (result?.authenticated) {
|
||||
req.session.authenticated = true
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
...result
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.message.startsWith('ERR_')) {
|
||||
return reply.badRequest(err.message)
|
||||
} else {
|
||||
WIKI.logger.debug(err)
|
||||
return reply.badRequest('ERR_CHANGE_PASSWORD_FAILED')
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
return WIKI.models.users.login({
|
||||
siteId: req.params.siteId,
|
||||
strategyId: req.body.strategyId,
|
||||
username: req.body.username,
|
||||
password: req.body.password,
|
||||
ip: req.ip
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export default routes
|
||||
|
||||
@ -1,92 +1,101 @@
|
||||
/**
|
||||
* Pages API Routes
|
||||
*/
|
||||
async function routes (app, options) {
|
||||
app.get('/sites/:siteId/pages', {
|
||||
schema: {
|
||||
summary: 'List all pages',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
async function routes(app, options) {
|
||||
app.get(
|
||||
'/sites/:siteId/pages',
|
||||
{
|
||||
schema: {
|
||||
summary: 'List all pages',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
return []
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
return []
|
||||
})
|
||||
)
|
||||
|
||||
app.get('/sites/:siteId/pages/:pageIdOrHash', {
|
||||
schema: {
|
||||
summary: 'List all pages',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
},
|
||||
pageIdOrHash: {
|
||||
type: 'string',
|
||||
oneOf: [
|
||||
{ format: 'uuid' },
|
||||
{ pattern: '^[a-f0-9]+$' }
|
||||
]
|
||||
app.get(
|
||||
'/sites/:siteId/pages/:pageIdOrHash',
|
||||
{
|
||||
schema: {
|
||||
summary: 'List all pages',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
},
|
||||
pageIdOrHash: {
|
||||
type: 'string',
|
||||
oneOf: [{ format: 'uuid' }, { pattern: '^[a-f0-9]+$' }]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
withContent: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
withContent: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
return []
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
return []
|
||||
})
|
||||
)
|
||||
|
||||
app.post('/sites/:siteId/pages/userPermissions', {
|
||||
schema: {
|
||||
summary: 'Get page user permissions',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['path'],
|
||||
properties: {
|
||||
path: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
app.post(
|
||||
'/sites/:siteId/pages/userPermissions',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Get page user permissions',
|
||||
tags: ['Pages'],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
siteId: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
path: 'foo/bar'
|
||||
}
|
||||
]
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['path'],
|
||||
properties: {
|
||||
path: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
path: 'foo/bar'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
return []
|
||||
}
|
||||
}, async (req, reply) => {
|
||||
return []
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export default routes
|
||||
|
||||
@ -1,24 +1,74 @@
|
||||
import path from 'node:path'
|
||||
import os from 'node:os'
|
||||
import { DateTime } from 'luxon'
|
||||
import { filesize } from 'filesize'
|
||||
import { isNil } from 'es-toolkit/predicate'
|
||||
import { gte, sql } from 'drizzle-orm'
|
||||
import {
|
||||
groups as groupsTable,
|
||||
pages as pagesTable,
|
||||
tags as tagsTable,
|
||||
users as usersTable
|
||||
} from '../db/schema.mjs'
|
||||
|
||||
/**
|
||||
* System API Routes
|
||||
*/
|
||||
async function routes (app, options) {
|
||||
app.get('/info', {
|
||||
schema: {
|
||||
summary: 'System Info',
|
||||
tags: ['System']
|
||||
async function routes(app, options) {
|
||||
app.get(
|
||||
'/info',
|
||||
{
|
||||
config: {
|
||||
permissions: ['read:dashboard', 'manage:sites']
|
||||
},
|
||||
schema: {
|
||||
summary: 'System Info',
|
||||
tags: ['System']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return {
|
||||
configFile: path.join(process.cwd(), 'config.yml'),
|
||||
cpuCores: os.cpus().length,
|
||||
currentVersion: WIKI.version,
|
||||
dbHost: WIKI.config.db.host,
|
||||
dbVersion: WIKI.dbManager.VERSION,
|
||||
groupsTotal: await WIKI.db.$count(groupsTable),
|
||||
hostname: os.hostname(),
|
||||
httpPort: 0,
|
||||
isMailConfigured: WIKI.config?.mail?.host?.length > 2,
|
||||
isSchedulerHealthy: true,
|
||||
latestVersion: WIKI.config.update.version,
|
||||
latestVersionReleaseDate: DateTime.fromISO(WIKI.config.update.versionDate).toJSDate(),
|
||||
loginsPastDay: await WIKI.db.$count(
|
||||
usersTable,
|
||||
gte(usersTable.lastLoginAt, sql`NOW() - INTERVAL '1 DAY'`)
|
||||
),
|
||||
nodeVersion: process.version.substring(1),
|
||||
operatingSystem: `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}`,
|
||||
pagesTotal: await WIKI.db.$count(pagesTable),
|
||||
platform: os.platform(),
|
||||
ramTotal: filesize(os.totalmem()),
|
||||
tagsTotal: await WIKI.db.$count(tagsTable),
|
||||
upgradeCapable: !isNil(process.env.UPGRADE_COMPANION),
|
||||
usersTotal: await WIKI.db.$count(usersTable),
|
||||
workingDirectory: process.cwd()
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.get('/flags', {
|
||||
schema: {
|
||||
summary: 'System Flags',
|
||||
tags: ['System']
|
||||
app.get(
|
||||
'/flags',
|
||||
{
|
||||
schema: {
|
||||
summary: 'System Flags',
|
||||
tags: ['System']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return WIKI.config.flags
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export default routes
|
||||
|
||||
@ -1,51 +1,95 @@
|
||||
/**
|
||||
* Users API Routes
|
||||
*/
|
||||
async function routes (app, options) {
|
||||
app.get('/', {
|
||||
schema: {
|
||||
summary: 'List all users',
|
||||
tags: ['Users']
|
||||
async function routes(app, options) {
|
||||
app.get(
|
||||
'/',
|
||||
{
|
||||
schema: {
|
||||
summary: 'List all users',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.get('/:userId', {
|
||||
schema: {
|
||||
summary: 'Get user info',
|
||||
tags: ['Users']
|
||||
app.get(
|
||||
'/whoami',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Get currently logged in user info',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (req, reply) => {
|
||||
reply.preventCache()
|
||||
if (req.session?.authenticated) {
|
||||
return {
|
||||
authenticated: true,
|
||||
...req.session.user,
|
||||
permissions: ['manage:system']
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
authenticated: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.post('/', {
|
||||
schema: {
|
||||
summary: 'Create a new user',
|
||||
tags: ['Users']
|
||||
app.get(
|
||||
'/:userId',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Get user info',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.put('/:userId', {
|
||||
schema: {
|
||||
summary: 'Update a user',
|
||||
tags: ['Users']
|
||||
app.post(
|
||||
'/',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Create a new user',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.delete('/:userId', {
|
||||
schema: {
|
||||
summary: 'Delete a user',
|
||||
tags: ['Users']
|
||||
app.put(
|
||||
'/:userId',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Update a user',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
}
|
||||
}, async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
)
|
||||
|
||||
app.delete(
|
||||
'/:userId',
|
||||
{
|
||||
schema: {
|
||||
summary: 'Delete a user',
|
||||
tags: ['Users']
|
||||
}
|
||||
},
|
||||
async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export default routes
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
import { defineRelations } from 'drizzle-orm'
|
||||
import * as schema from './schema.mjs'
|
||||
|
||||
export const relations = defineRelations(schema,
|
||||
r => ({
|
||||
users: {
|
||||
groups: r.many.groups({
|
||||
from: r.users.id.through(r.userGroups.userId),
|
||||
to: r.groups.id.through(r.userGroups.groupId)
|
||||
})
|
||||
},
|
||||
groups: {
|
||||
members: r.many.users()
|
||||
}
|
||||
})
|
||||
)
|
||||
export const relations = defineRelations(schema, (r) => ({
|
||||
users: {
|
||||
groups: r.many.groups({
|
||||
from: r.users.id.through(r.userGroups.userId),
|
||||
to: r.groups.id.through(r.userGroups.groupId)
|
||||
})
|
||||
},
|
||||
groups: {
|
||||
members: r.many.users()
|
||||
},
|
||||
userKeys: {
|
||||
user: r.one.users({
|
||||
from: r.userKeys.userId,
|
||||
to: r.users.id
|
||||
})
|
||||
}
|
||||
}))
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { sessions as sessionsTable } from '../db/schema.mjs'
|
||||
|
||||
/**
|
||||
* Sessions model
|
||||
*/
|
||||
class Sessions {
|
||||
/**
|
||||
* Fetch all sessions from a single user
|
||||
*
|
||||
* @param {String} userId User ID
|
||||
* @returns Promise<Array> User Sessions
|
||||
*/
|
||||
async getByUser(userId) {
|
||||
return WIKI.db.select().from(sessionsTable).where(eq(sessionsTable.userId, userId))
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single session by id
|
||||
*
|
||||
* @param {String} id Session ID
|
||||
* @returns Promise<Object> Session data
|
||||
*/
|
||||
async get(id) {
|
||||
const res = await WIKI.db.select().from(sessionsTable).where(eq(sessionsTable.id, id))
|
||||
return res?.[0]?.data ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* Set / Update a session
|
||||
*
|
||||
* @param {String} id Session ID
|
||||
* @param {Object} data Session Data
|
||||
*/
|
||||
async set(id, data) {
|
||||
await WIKI.db
|
||||
.insert(sessionsTable)
|
||||
.values([
|
||||
{
|
||||
id,
|
||||
userId: data?.user?.id ?? null,
|
||||
data
|
||||
}
|
||||
])
|
||||
.onConflictDoUpdate({
|
||||
target: sessionsTable.id,
|
||||
set: {
|
||||
data,
|
||||
userId: data?.user?.id ?? null,
|
||||
updatedAt: sql`now()`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session
|
||||
*
|
||||
* @param {String} id Session ID
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async destroy(id) {
|
||||
return WIKI.db.delete(sessionsTable).where(eq(sessionsTable.id, id))
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all sessions from all users
|
||||
*
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async clearAllSessions() {
|
||||
return WIKI.db.delete(sessionsTable)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all sessions from a single user
|
||||
*
|
||||
* @param {String} userId User ID
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async clearSessionsFromUser(userId) {
|
||||
return WIKI.db.delete(sessionsTable).where(eq(sessionsTable.userId, userId))
|
||||
}
|
||||
}
|
||||
|
||||
export const sessions = new Sessions()
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSameLine": true,
|
||||
"endOfLine": "lf",
|
||||
"insertFinalNewline": true
|
||||
}
|
||||
Loading…
Reference in new issue