refactor: remove eslint + lodash-es, use oxc + es-toolkit

scarlett
NGPixel 1 week ago
parent f4707f31d9
commit dc78af9156
No known key found for this signature in database

@ -18,15 +18,14 @@
"dbaeumer.vscode-eslint",
"eamodio.gitlens",
"Vue.volar",
"oxc.oxc-vscode",
"oderwat.indent-rainbow",
"redhat.vscode-yaml",
"editorconfig.editorconfig",
"lokalise.i18n-ally",
"mrmlnc.vscode-duplicate",
"mutantdino.resourcemonitor",
"wayou.vscode-todo-highlight",
"GraphQL.vscode-graphql",
"GitHub.copilot"
"wayou.vscode-todo-highlight"
]
}
},

@ -1,6 +1,7 @@
{
"recommendations": [
"Vue.volar",
"EditorConfig.editorconfig",
"dbaeumer.vscode-eslint"
"oxc.oxc-vscode"
]
}

@ -1,17 +1,9 @@
{
"eslint.enable": true,
"puglint.enable": true,
"eslint.enable": false,
"editor.formatOnSave": false,
"editor.tabSize": 2,
"eslint.validate": [
"javascript",
"vue"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"i18n-ally.localesPaths": [
"server/locales",
"backend/locales",
],
"i18n-ally.pathMatcher": "{locale}.json",
"i18n-ally.keystyle": "flat",

@ -0,0 +1,9 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSameLine": true,
"endOfLine": "lf",
"insertFinalNewline": true
}

@ -0,0 +1,21 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["eslint", "typescript", "unicorn", "oxc"],
"env": {
"node": true
},
"globals": {
"WIKI": "readonly"
},
"categories": {
"correctness": "error"
},
"ignorePatterns": [
"node_modules/**",
"**/*.min.js",
"repo/**",
"data/**",
"logs/**",
"locales/**"
]
}

@ -1,7 +1,11 @@
/**
* Authentication API Routes
*/
async function routes (app, options) {
/**
* GET SITE AUTHENTICATION STRATEGIES
*/
app.get('/sites/:siteId/auth/strategies', {
schema: {
summary: 'List all site authentication strategies',
@ -26,32 +30,70 @@ async function routes (app, options) {
}
}
}, async (req, reply) => {
return []
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
}
}).sort((a,b) => a.order - b.order)
return req.query.visibleOnly ? siteStrategies.filter(s => s.isVisible) : siteStrategies
})
app.post('/auth/login', {
/**
* LOGIN USING USER/PASS
*/
app.post('/sites/:siteId/auth/login', {
schema: {
summary: 'Login',
tags: ['Authentication'],
params: {
type: 'object',
properties: {
siteId: {
type: 'string',
format: 'uuid'
}
}
},
body: {
type: 'object',
required: ['path'],
required: ['strategyId', 'username', 'password'],
properties: {
path: {
strategyId: {
type: 'string',
format: 'uuid'
},
username: {
type: 'string',
minLength: 1,
maxLength: 255
},
password: {
type: 'string',
minLength: 1,
maxLength: 255
}
},
examples: [
{
path: 'foo/bar'
}
]
}
}
}
}, async (req, reply) => {
return []
return WIKI.models.users.login({
siteId: req.params.siteId,
strategyId: req.body.strategyId,
username: req.body.username,
password: req.body.password,
ip: req.ip
})
})
}

@ -1,4 +1,5 @@
import { defaultsDeep, get, isPlainObject } from 'lodash-es'
import { toMerged } from 'es-toolkit/object'
import { isPlainObject } from 'es-toolkit/predicate'
import chalk from 'chalk'
import cfgHelper from '../helpers/config.mjs'
import fs from 'node:fs/promises'
@ -47,7 +48,7 @@ export default {
// Merge with defaults
appconfig = defaultsDeep(appconfig, appdata.defaults.config)
appconfig = toMerged(appdata.defaults.config, appconfig)
// Override port
@ -91,7 +92,7 @@ export default {
WIKI.logger.info('Loading settings from DB...')
const conf = await WIKI.models.settings.getConfig()
if (conf) {
WIKI.config = defaultsDeep(conf, WIKI.config)
WIKI.config = toMerged(WIKI.config, conf)
return true
} else {
return false
@ -106,7 +107,7 @@ export default {
async saveToDb (keys, propagate = true) {
try {
for (const key of keys) {
let value = get(WIKI.config, key, null)
let value = WIKI.config[key] ?? null
if (!isPlainObject(value)) {
value = { v: value }
}

@ -1,4 +1,4 @@
import { get, has, isEmpty, isPlainObject } from 'lodash-es'
import { isPlainObject } from 'es-toolkit/predicate'
import path from 'node:path'
import fs from 'node:fs/promises'
import { setTimeout } from 'node:timers/promises'
@ -32,7 +32,7 @@ export default {
// Fetch DB Config
this.config = (!isEmpty(process.env.DATABASE_URL))
this.config = (process.env.DATABASE_URL)
? {
connectionString: process.env.DATABASE_URL
}
@ -48,7 +48,7 @@ export default {
let dbUseSSL = (WIKI.config.db.ssl === true || WIKI.config.db.ssl === 'true' || WIKI.config.db.ssl === 1 || WIKI.config.db.ssl === '1')
let sslOptions = null
if (dbUseSSL && isPlainObject(this.config) && get(WIKI.config.db, 'sslOptions.auto', null) === false) {
if (dbUseSSL && isPlainObject(this.config) && WIKI.config.db?.sslOptions?.auto === false) {
sslOptions = WIKI.config.db.sslOptions
sslOptions.rejectUnauthorized = sslOptions.rejectUnauthorized !== false
if (sslOptions.ca && sslOptions.ca.indexOf('-----') !== 0) {
@ -68,7 +68,7 @@ export default {
}
// Handle inline SSL CA Certificate mode
if (!isEmpty(process.env.DB_SSL_CA)) {
if (process.env.DB_SSL_CA) {
const chunks = []
for (let i = 0, charsLength = process.env.DB_SSL_CA.length; i < charsLength; i += 64) {
chunks.push(process.env.DB_SSL_CA.substring(i, i + 64))
@ -146,7 +146,7 @@ export default {
// -> Outbound events handling
this.listener.addChannel('wiki', payload => {
if (has(payload, 'event') && payload.source !== WIKI.INSTANCE_ID) {
if (('event' in payload) && payload.source !== WIKI.INSTANCE_ID) {
WIKI.logger.info(`Received event ${payload.event} from instance ${payload.source}: [ OK ]`)
WIKI.events.inbound.emit(payload.event, payload.value)
}

@ -171,6 +171,14 @@ CREATE TABLE "pages" (
"siteId" uuid NOT NULL
);
--> statement-breakpoint
CREATE TABLE "sessions" (
"id" varchar(255) PRIMARY KEY,
"userId" uuid,
"data" jsonb DEFAULT '{}' NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "settings" (
"key" varchar(255) PRIMARY KEY,
"value" jsonb DEFAULT '{}' NOT NULL
@ -259,6 +267,7 @@ CREATE INDEX "pages_siteId_idx" ON "pages" ("siteId");--> statement-breakpoint
CREATE INDEX "pages_ts_idx" ON "pages" USING gin ("ts");--> statement-breakpoint
CREATE INDEX "pages_tags_idx" ON "pages" USING gin ("tags");--> statement-breakpoint
CREATE INDEX "pages_isSearchableComputed_idx" ON "pages" ("isSearchableComputed");--> statement-breakpoint
CREATE INDEX "sessions_userId_idx" ON "sessions" ("userId");--> statement-breakpoint
CREATE INDEX "tags_siteId_idx" ON "tags" ("siteId");--> statement-breakpoint
CREATE UNIQUE INDEX "tags_composite_idx" ON "tags" ("siteId","tag");--> statement-breakpoint
CREATE INDEX "tree_folderpath_idx" ON "tree" ("folderPath");--> statement-breakpoint
@ -284,6 +293,7 @@ ALTER TABLE "pages" ADD CONSTRAINT "pages_authorId_users_id_fkey" FOREIGN KEY ("
ALTER TABLE "pages" ADD CONSTRAINT "pages_creatorId_users_id_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id");--> statement-breakpoint
ALTER TABLE "pages" ADD CONSTRAINT "pages_ownerId_users_id_fkey" FOREIGN KEY ("ownerId") REFERENCES "users"("id");--> statement-breakpoint
ALTER TABLE "pages" ADD CONSTRAINT "pages_siteId_sites_id_fkey" FOREIGN KEY ("siteId") REFERENCES "sites"("id");--> statement-breakpoint
ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_users_id_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id");--> statement-breakpoint
ALTER TABLE "tags" ADD CONSTRAINT "tags_siteId_sites_id_fkey" FOREIGN KEY ("siteId") REFERENCES "sites"("id");--> statement-breakpoint
ALTER TABLE "tree" ADD CONSTRAINT "tree_siteId_sites_id_fkey" FOREIGN KEY ("siteId") REFERENCES "sites"("id");--> statement-breakpoint
ALTER TABLE "userGroups" ADD CONSTRAINT "userGroups_userId_users_id_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE;--> statement-breakpoint

@ -1,7 +1,7 @@
{
"version": "8",
"dialect": "postgres",
"id": "c8ce9873-2bb3-48d4-a8b8-40b0bfed5188",
"id": "ded00708-02ea-49a3-8d2b-647fe5fcda7e",
"prevIds": [
"061e8c84-e05e-40b0-a074-7a56bd794fc7"
],
@ -131,6 +131,12 @@
"entityType": "tables",
"schema": "public"
},
{
"isRlsEnabled": false,
"name": "sessions",
"entityType": "tables",
"schema": "public"
},
{
"isRlsEnabled": false,
"name": "settings",
@ -1898,6 +1904,71 @@
"schema": "public",
"table": "pages"
},
{
"type": "varchar(255)",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "id",
"entityType": "columns",
"schema": "public",
"table": "sessions"
},
{
"type": "uuid",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "userId",
"entityType": "columns",
"schema": "public",
"table": "sessions"
},
{
"type": "jsonb",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": "'{}'",
"generated": null,
"identity": null,
"name": "data",
"entityType": "columns",
"schema": "public",
"table": "sessions"
},
{
"type": "timestamp",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": "now()",
"generated": null,
"identity": null,
"name": "createdAt",
"entityType": "columns",
"schema": "public",
"table": "sessions"
},
{
"type": "timestamp",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": "now()",
"generated": null,
"identity": null,
"name": "updatedAt",
"entityType": "columns",
"schema": "public",
"table": "sessions"
},
{
"type": "varchar(255)",
"typeSchema": null,
@ -2805,6 +2876,27 @@
"schema": "public",
"table": "pages"
},
{
"nameExplicit": true,
"columns": [
{
"value": "userId",
"isExpression": false,
"asc": true,
"nullsFirst": false,
"opclass": null
}
],
"isUnique": false,
"where": null,
"with": "",
"method": "btree",
"concurrently": false,
"name": "sessions_userId_idx",
"entityType": "indexes",
"schema": "public",
"table": "sessions"
},
{
"nameExplicit": true,
"columns": [
@ -3312,6 +3404,23 @@
"schema": "public",
"table": "pages"
},
{
"nameExplicit": false,
"columns": [
"userId"
],
"schemaTo": "public",
"tableTo": "users",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "NO ACTION",
"name": "sessions_userId_users_id_fkey",
"entityType": "fks",
"schema": "public",
"table": "sessions"
},
{
"nameExplicit": false,
"columns": [
@ -3528,6 +3637,16 @@
"table": "pages",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "sessions_pkey",
"schema": "public",
"table": "sessions",
"entityType": "pks"
},
{
"columns": [
"key"

@ -221,6 +221,17 @@ export const settings = pgTable('settings', {
value: jsonb().notNull().default({})
})
// SESSIONS ----------------------------
export const sessions = pgTable('sessions', {
id: varchar({ length: 255 }).primaryKey(),
userId: uuid().references(() => users.id),
data: jsonb().notNull().default({}),
createdAt: timestamp().notNull().defaultNow(),
updatedAt: timestamp().notNull().defaultNow(),
}, (table) => [
index('sessions_userId_idx').on(table.userId)
])
// SITES -------------------------------
export const sites = pgTable('sites', {
id: uuid().primaryKey().defaultRandom(),

@ -1,19 +0,0 @@
import neostandard from 'neostandard'
export default neostandard({
globals: {
document: false,
navigator: false,
window: false,
WIKI: true
},
ignores: [
'**/node_modules/**',
'**/*.min.js',
'coverage/**',
'repo/**',
'data/**',
'logs/**',
'locales/**'
]
})

@ -1,4 +1,5 @@
import { isNil, isPlainObject, set, startCase, transform } from 'lodash-es'
import { isNil, isPlainObject } from 'es-toolkit/predicate'
import { startCase } from 'es-toolkit/string'
import crypto from 'node:crypto'
import mime from 'mime'
import fs from 'node:fs'
@ -80,14 +81,15 @@ export function getTypeDefaultValue (type) {
}
export function parseModuleProps (props) {
return transform(props, (result, value, key) => {
const result = {}
for (const [key, value] of Object.entries(props)) {
let defaultValue = ''
if (isPlainObject(value)) {
defaultValue = !isNil(value.default) ? value.default : getTypeDefaultValue(value.type)
} else {
defaultValue = getTypeDefaultValue(value)
}
set(result, key, {
result[key] = {
default: defaultValue,
type: (value.type || value).toLowerCase(),
title: value.title || startCase(key),
@ -99,9 +101,9 @@ export function parseModuleProps (props) {
icon: value.icon || 'rename',
order: value.order || 100,
if: value.if ?? []
})
return result
}, {})
}
}
return result
}
export function getDictNameFromLocale (locale) {

@ -1,5 +1,3 @@
import { replace } from 'lodash-es'
const isoDurationReg = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/
export default {
@ -14,11 +12,7 @@ export default {
* @returns Parse configuration value
*/
parseConfigValue (cfg) {
return replace(
cfg,
/\$\(([A-Z0-9_]+)(?::(.+))?\)/g,
(fm, m, d) => { return process.env[m] || d }
)
return cfg.replaceAll(/\$\(([A-Z0-9_]+)(?::(.+))?\)/g, (fm, m, d) => { return process.env[m] || d })
},
isValidDurationString (val) {

@ -8,7 +8,6 @@ import path from 'node:path'
import { DateTime } from 'luxon'
import semver from 'semver'
import { customAlphabet } from 'nanoid'
import { padEnd } from 'lodash-es'
import fastify from 'fastify'
import fastifyCompress from '@fastify/compress'
@ -80,7 +79,7 @@ WIKI.logger = logger.init()
// ----------------------------------------
WIKI.logger.info('=======================================')
WIKI.logger.info(`= Wiki.js ${padEnd(WIKI.version + ' ', 29, '=')}`)
WIKI.logger.info(`= Wiki.js ${(WIKI.version + ' ').padEnd(29, '=')}`)
WIKI.logger.info('=======================================')
WIKI.logger.info('Initializing...')
WIKI.logger.info(`Running node.js ${process.version} [ OK ]`)
@ -123,6 +122,8 @@ async function preBoot () {
async function postBoot () {
await WIKI.models.locales.refreshFromDisk()
await WIKI.models.authentication.refreshStrategiesFromDisk()
await WIKI.models.locales.reloadCache()
await WIKI.models.sites.reloadCache()
}
@ -179,6 +180,9 @@ async function initHTTPServer () {
WIKI.server.on(gracefulServer.SHUTDOWN, (err) => {
WIKI.logger.info(`HTTP Server has exited: [ STOPPED ] (${err.message})`)
if (err.message !== 'SIGINT') {
WIKI.logger.warn(err)
}
})
// ----------------------------------------
@ -237,12 +241,17 @@ async function initHTTPServer () {
})
app.register(fastifySession, {
secret: WIKI.config.auth.secret,
cookieName: 'wikiSession',
cookie: {
httpOnly: true,
secure: 'auto'
},
saveUninitialized: false,
store: {
get (sessionId, clb) {
},
set (sessionId, clb) {
set (sessionId, sessionData, clb) {
},
destroy (sessionId, clb) {

@ -1,6 +1,7 @@
import fs from 'node:fs/promises'
import path from 'node:path'
import yaml from 'js-yaml'
import { eq } from 'drizzle-orm'
import { parseModuleProps } from '../helpers/common.mjs'
import { authentication as authenticationTable } from '../db/schema.mjs'
@ -9,11 +10,11 @@ import { authentication as authenticationTable } from '../db/schema.mjs'
*/
class Authentication {
async getStrategy (module) {
return WIKI.db.authentication.query().findOne({ module })
return WIKI.db.select().from(authenticationTable).where(eq(authenticationTable.module, module))
}
async getStrategies ({ enabledOnly = false } = {}) {
return WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {})
return WIKI.db.select().from(authenticationTable).where(enabledOnly ? eq(authenticationTable.isEnabled, true) : undefined)
}
async refreshStrategiesFromDisk () {
@ -28,12 +29,12 @@ class Authentication {
defParsed.key = dir
defParsed.props = parseModuleProps(defParsed.props)
WIKI.data.authentication.push(defParsed)
WIKI.logger.debug(`Loaded authentication module definition ${dir}: [ OK ]`)
WIKI.logger.debug(`Loaded authentication module definition ${dir} [ OK ]`)
}
WIKI.logger.info(`Loaded ${WIKI.data.authentication.length} authentication module definitions: [ OK ]`)
WIKI.logger.info(`Loaded ${WIKI.data.authentication.length} authentication module definitions [ OK ]`)
} catch (err) {
WIKI.logger.error('Failed to scan or load authentication providers: [ FAILED ]')
WIKI.logger.error('Failed to scan or load authentication providers [ FAILED ]')
WIKI.logger.error(err)
}
}

@ -1,4 +1,3 @@
import { find } from 'lodash-es'
import { stat, readFile } from 'node:fs/promises'
import path from 'node:path'
import { DateTime } from 'luxon'
@ -12,7 +11,7 @@ class Locales {
async refreshFromDisk ({ force = false } = {}) {
try {
const localesMeta = (await import('../locales/metadata.mjs')).default
WIKI.logger.info(`Found ${localesMeta.languages.length} locales: [ OK ]`)
WIKI.logger.info(`Found ${localesMeta.languages.length} locales [ OK ]`)
const dbLocales = await WIKI.db.select({
code: localesTable.code,
@ -32,7 +31,7 @@ class Locales {
const langFilename = langFilenameParts.join('-')
// -> Get DB version
const dbLang = find(dbLocales, ['code', langFilename])
const dbLang = dbLocales.find(l => l.code === langFilename)
// -> Get File version
const flPath = path.join(WIKI.SERVERPATH, `locales/${langFilename}.json`)

@ -1,5 +1,4 @@
import { settings as settingsTable } from '../db/schema.mjs'
import { has, reduce, set } from 'lodash-es'
import { pem2jwk } from 'pem-jwk'
import crypto from 'node:crypto'
@ -14,8 +13,8 @@ class Settings {
async getConfig () {
const settings = await WIKI.db.select().from(settingsTable)
if (settings.length > 0) {
return reduce(settings, (res, val, key) => {
set(res, val.key, (has(val.value, 'v')) ? val.value.v : val.value)
return settings.reduce((res, val) => {
res[val.key] = ('v' in val.value) ? val.value.v : val.value
return res
}, {})
} else {

@ -1,4 +1,5 @@
import { defaultsDeep, keyBy } from 'lodash-es'
import { toMerged } from 'es-toolkit/object'
import { keyBy } from 'es-toolkit/array'
import { sites as sitesTable } from '../db/schema.mjs'
import { eq } from 'drizzle-orm'
@ -27,7 +28,7 @@ class Sites {
async reloadCache () {
WIKI.logger.info('Reloading site configurations...')
const sites = await WIKI.db.select().from(sitesTable).orderBy(sitesTable.id)
WIKI.sites = keyBy(sites, 'id')
WIKI.sites = keyBy(sites, s => s.id)
WIKI.sitesMappings = {}
for (const site of sites) {
WIKI.sitesMappings[site.hostname] = site.id
@ -39,7 +40,7 @@ class Sites {
const result = await WIKI.db.insert(sitesTable).values({
hostname,
isEnabled: true,
config: defaultsDeep(config, {
config: toMerged({
title: 'My Wiki Site',
description: '',
company: '',
@ -132,7 +133,7 @@ class Sites {
conflictBehavior: 'overwrite',
normalizeFilename: true
}
})
}, config)
}).returning({ id: sitesTable.id })
const newSite = result[0]

@ -71,6 +71,48 @@ class Users {
}
])
}
async login ({ siteId, strategyId, username, password, ip }) {
if (strategyId in WIKI.auth.strategies) {
const selStrategy = WIKI.auth.strategies[strategyId]
if (!selStrategy.isEnabled) {
throw new Error('Inactive Strategy ID')
}
const strInfo = WIKI.data.authentication.find(a => a.key === selStrategy.module)
// Inject form user/pass
if (strInfo.useForm) {
set(context.req, 'body.email', username)
set(context.req, 'body.password', password)
set(context.req.params, 'strategy', strategyId)
}
// Authenticate
return new Promise((resolve, reject) => {
WIKI.auth.passport.authenticate(selStrategy.id, {
session: !strInfo.useForm,
scope: strInfo.scopes ? strInfo.scopes : null
}, async (err, user, info) => {
if (err) { return reject(err) }
if (!user) { return reject(new WIKI.Error.AuthLoginFailed()) }
try {
const resp = await WIKI.db.users.afterLoginChecks(user, selStrategy.id, context, {
siteId,
skipTFA: !strInfo.useForm,
skipChangePwd: !strInfo.useForm
})
resolve(resp)
} catch (err) {
reject(err)
}
})(context.req, context.res, () => {})
})
} else {
throw new Error('Invalid Strategy ID')
}
}
}
export const users = new Users()

@ -0,0 +1,45 @@
/* global WIKI */
import bcrypt from 'bcryptjs'
// ------------------------------------
// Local Account
// ------------------------------------
import { Strategy } from 'passport-local'
export default {
init (passport, strategyId, conf) {
passport.use(strategyId,
new Strategy({
usernameField: 'email',
passwordField: 'password'
}, async (uEmail, uPassword, done) => {
try {
const user = await WIKI.db.users.query().findOne({
email: uEmail.toLowerCase()
})
if (user) {
const authStrategyData = user.auth[strategyId]
if (!authStrategyData) {
throw new Error('ERR_INVALID_STRATEGY')
} else if (await bcrypt.compare(uPassword, authStrategyData.password) !== true) {
throw new Error('ERR_LOGIN_FAILED')
} else if (!user.isActive) {
throw new Error('ERR_INACTIVE_USER')
} else if (authStrategyData.restrictLogin) {
throw new Error('ERR_LOGIN_RESTRICTED')
} else if (!user.isVerified) {
throw new Error('ERR_USER_NOT_VERIFIED')
} else {
done(null, user)
}
} else {
throw new Error('ERR_LOGIN_FAILED')
}
} catch (err) {
done(err, null)
}
})
)
}
}

@ -0,0 +1,25 @@
key: local
title: Local Database
description: Built-in authentication for Wiki.js
author: requarks.io
logo: https://static.requarks.io/logo/wikijs.svg
icon: /_assets/icons/ultraviolet-data-protection.svg
color: primary
vendor: 'Wiki.js'
website: 'https://js.wiki'
isAvailable: true
useForm: true
usernameType: email
props:
enforceTfa:
type: Boolean
title: Enforce Two-Factor Authentication
hint: Users will be required to setup 2FA the first time they login and cannot be disabled by the user.
icon: pin-pad
default: false
emailValidation:
type: Boolean
title: Email Validation
hint: Send a verification email to the user with a validation link when registering (if registration is enabled).
icon: received
default: true

File diff suppressed because it is too large Load Diff

@ -53,10 +53,12 @@
"@gquittet/graceful-server": "6.0.3",
"ajv-formats": "3.0.1",
"bcryptjs": "3.0.3",
"chalk": "5.6.2",
"drizzle-orm": "1.0.0-beta.15-859cf75",
"es-toolkit": "1.45.1",
"fastify": "5.7.1",
"fastify-favicon": "5.0.0",
"lodash-es": "4.17.23",
"js-yaml": "4.1.1",
"luxon": "3.7.2",
"mime": "4.1.0",
"nanoid": "5.1.6",
@ -70,13 +72,10 @@
},
"devDependencies": {
"drizzle-kit": "1.0.0-beta.15-859cf75",
"eslint": "9.39.2",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "7.2.1",
"neostandard": "0.12.2",
"nodemon": "3.1.11",
"npm-check-updates": "19.3.1"
"npm-check-updates": "19.3.1",
"oxfmt": "0.36.0",
"oxlint": "1.51.0"
},
"collective": {
"type": "opencollective",

@ -0,0 +1,9 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSameLine": true,
"endOfLine": "lf",
"insertFinalNewline": true
}

@ -0,0 +1,59 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["eslint", "typescript", "unicorn", "oxc", "vue"],
"env": {
"browser": true
},
"globals": {
"__statics": "readonly",
"__QUASAR_SSR__": "readonly",
"__QUASAR_SSR_SERVER__": "readonly",
"__QUASAR_SSR_CLIENT__": "readonly",
"__QUASAR_SSR_PWA__": "readonly",
"process": "readonly",
"chrome": "readonly",
"API_CLIENT": "readonly",
"EVENT_BUS": "readonly"
},
"ignorePatterns": [
"dist/**",
".quasar/**",
"node_modules/**"
],
"categories": {
"correctness": "error"
},
"rules": {
// allow async-await
"generator-star-spacing": "off",
// allow paren-less arrow functions
"arrow-parens": "off",
"one-var": "off",
"no-void": "off",
"multiline-ternary": "off",
"import/first": "off",
"import/named": "error",
"import/namespace": "error",
"import/default": "error",
"import/export": "error",
"import/extensions": "off",
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": "off",
"prefer-promise-reject-errors": "off",
"no-unused-vars": "off",
"vue/multi-word-component-names": "off",
// allow debugger during development only
"no-debugger": "error",
// disable bogus rules
"vue/valid-template-root": "off",
"vue/no-parsing-error": "off",
"vue/valid-v-for": "off",
"vue/html-quotes": ["warn", "single"],
"vue/max-attributes-per-line": "off"
}
}

@ -1,6 +1,5 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"johnsoncodehk.volar",
"wayou.vscode-todo-highlight"
@ -9,6 +8,7 @@
"octref.vetur",
"hookyqr.beautify",
"dbaeumer.jshint",
"ms-vscode.vscode-typescript-tslint-plugin"
"ms-vscode.vscode-typescript-tslint-plugin",
"dbaeumer.vscode-eslint"
]
}
}

@ -2,15 +2,5 @@
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.fixAll.eslint"
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"vue"
],
"i18n-ally.localesPaths": "src/i18n/locales"
}

@ -1,73 +0,0 @@
import js from '@eslint/js'
import neostandard from 'neostandard'
import pluginVue from 'eslint-plugin-vue'
import pluginVuePug from 'eslint-plugin-vue-pug'
import vueParser from 'vue-eslint-parser'
import { FlatCompat } from '@eslint/eslintrc'
const compat = new FlatCompat()
export default [
js.configs.recommended,
...pluginVue.configs['flat/essential'],
...pluginVuePug.configs['flat/recommended'],
...neostandard(),
{
ignores: [
'/dist',
'/.quasar',
'/node_modules'
],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: vueParser,
globals: {
__statics: 'readonly',
__QUASAR_SSR__: 'readonly',
__QUASAR_SSR_SERVER__: 'readonly',
__QUASAR_SSR_CLIENT__: 'readonly',
__QUASAR_SSR_PWA__: 'readonly',
process: 'readonly',
Capacitor: 'readonly',
chrome: 'readonly',
APOLLO_CLIENT: 'readonly',
EVENT_BUS: 'readonly'
}
},
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow paren-less arrow functions
'arrow-parens': 'off',
'one-var': 'off',
'no-void': 'off',
'multiline-ternary': 'off',
'import/first': 'off',
'import/named': 'error',
'import/namespace': 'error',
'import/default': 'error',
'import/export': 'error',
'import/extensions': 'off',
'import/no-unresolved': 'off',
'import/no-extraneous-dependencies': 'off',
'prefer-promise-reject-errors': 'off',
'no-unused-vars': 'off',
'vue/multi-word-component-names': 'off',
// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// disable bogus rules
'vue/valid-template-root': 'off',
'vue/no-parsing-error': 'off',
'vue-pug/no-parsing-error': 'off',
'vue/valid-v-for': 'off',
'vue/html-quotes': ['warn', 'single'],
'vue/max-attributes-per-line': 'off'
}
}
]

@ -84,6 +84,8 @@
"autoprefixer": "10.4.27",
"browserlist": "latest",
"npm-check-updates": "19.6.3",
"oxfmt": "0.36.0",
"oxlint": "1.51.0",
"sass": "1.97.3",
"vite-plugin-vue-devtools": "8.0.6"
},
@ -1775,6 +1777,652 @@
"node": ">= 8"
}
},
"node_modules/@oxfmt/binding-android-arm-eabi": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.36.0.tgz",
"integrity": "sha512-Z4yVHJWx/swHHjtr0dXrBZb6LxS+qNz1qdza222mWwPTUK4L790+5i3LTgjx3KYGBzcYpjaiZBw4vOx94dH7MQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-android-arm64": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.36.0.tgz",
"integrity": "sha512-3ElCJRFNPQl7jexf2CAa9XmAm8eC5JPrIDSjc9jSchkVSFTEqyL0NtZinBB2h1a4i4JgP1oGl/5G5n8YR4FN8Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-darwin-arm64": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.36.0.tgz",
"integrity": "sha512-nak4znWCqIExKhYSY/mz/lWsqWIpdsS7o0+SRzXR1Q0m7GrMcG1UrF1pS7TLGZhhkf7nTfEF7q6oZzJiodRDuw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-darwin-x64": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.36.0.tgz",
"integrity": "sha512-V4GP96thDnpKx6ADnMDnhIXNdtV+Ql9D4HUU+a37VTeVbs5qQSF/s6hhUP1b3xUqU7iRcwh72jUU2Y12rtGHAw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-freebsd-x64": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.36.0.tgz",
"integrity": "sha512-/xapWCADfI5wrhxpEUjhI9fnw7MV5BUZizVa8e24n3VSK6A3Y1TB/ClOP1tfxNspykFKXp4NBWl6NtDJP3osqQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-arm-gnueabihf": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.36.0.tgz",
"integrity": "sha512-1lOmv61XMFIH5uNm27620kRRzWt/RK6tdn250BRDoG9W7OXGOQ5UyI1HVT+SFkoOoKztBiinWgi68+NA1MjBVQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-arm-musleabihf": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.36.0.tgz",
"integrity": "sha512-vMH23AskdR1ujUS9sPck2Df9rBVoZUnCVY86jisILzIQ/QQ/yKUTi7tgnIvydPx7TyB/48wsQ5QMr5Knq5p/aw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-arm64-gnu": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.36.0.tgz",
"integrity": "sha512-Hy1V+zOBHpBiENRx77qrUTt5aPDHeCASRc8K5KwwAHkX2AKP0nV89eL17hsZrE9GmnXFjsNmd80lyf7aRTXsbw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-arm64-musl": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.36.0.tgz",
"integrity": "sha512-SPGLJkOIHSIC6ABUQ5V8NqJpvYhMJueJv26NYqfCnwi/Mn6A61amkpJJ9Suy0Nmvs+OWESJpcebrBUbXPGZyQQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-ppc64-gnu": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.36.0.tgz",
"integrity": "sha512-3EuoyB8x9x8ysYJjbEO/M9fkSk72zQKnXCvpZMDHXlnY36/1qMp55Nm0PrCwjGO/1pen5hdOVkz9WmP3nAp2IQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-riscv64-gnu": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.36.0.tgz",
"integrity": "sha512-MpY3itLwpGh8dnywtrZtaZ604T1m715SydCKy0+qTxetv+IHzuA+aO/AGzrlzUNYZZmtWtmDBrChZGibvZxbRQ==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-riscv64-musl": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.36.0.tgz",
"integrity": "sha512-mmDhe4Vtx+XwQPRPn/V25+APnkApYgZ23q+6GVsNYY98pf3aU0aI3Me96pbRs/AfJ1jIiGC+/6q71FEu8dHcHw==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-s390x-gnu": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.36.0.tgz",
"integrity": "sha512-AYXhU+DmNWLSnvVwkHM92fuYhogtVHab7UQrPNaDf1sxadugg9gWVmcgJDlIwxJdpk5CVW/TFvwUKwI432zhhA==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-x64-gnu": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.36.0.tgz",
"integrity": "sha512-H16QhhQ3usoakMleiAAQ2mg0NsBDAdyE9agUgfC8IHHh3jZEbr0rIKwjEqwbOHK5M0EmfhJmr+aGO/MgZPsneA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-linux-x64-musl": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.36.0.tgz",
"integrity": "sha512-EFFGkixA39BcmHiCe2ECdrq02D6FCve5ka6ObbvrheXl4V+R0U/E+/uLyVx1X65LW8TA8QQHdnbdDallRekohw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-openharmony-arm64": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.36.0.tgz",
"integrity": "sha512-zr/t369wZWFOj1qf06Z5gGNjFymfUNDrxKMmr7FKiDRVI1sNsdKRCuRL4XVjtcptKQ+ao3FfxLN1vrynivmCYg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-win32-arm64-msvc": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.36.0.tgz",
"integrity": "sha512-FxO7UksTv8h4olzACgrqAXNF6BP329+H322323iDrMB5V/+a1kcAw07fsOsUmqNrb9iJBsCQgH/zqcqp5903ag==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-win32-ia32-msvc": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.36.0.tgz",
"integrity": "sha512-OjoMQ89H01M0oLMfr/CPNH1zi48ZIwxAKObUl57oh7ssUBNDp/2Vjf7E1TQ8M4oj4VFQ/byxl2SmcPNaI2YNDg==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxfmt/binding-win32-x64-msvc": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.36.0.tgz",
"integrity": "sha512-MoyeQ9S36ZTz/4bDhOKJgOBIDROd4dQ5AkT9iezhEaUBxAPdNX9Oq0jD8OSnCj3G4wam/XNxVWKMA52kmzmPtQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-android-arm-eabi": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.51.0.tgz",
"integrity": "sha512-jJYIqbx4sX+suIxWstc4P7SzhEwb4ArWA2KVrmEuu9vH2i0qM6QIHz/ehmbGE4/2fZbpuMuBzTl7UkfNoqiSgw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-android-arm64": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.51.0.tgz",
"integrity": "sha512-GtXyBCcH4ti98YdiMNCrpBNGitx87EjEWxevnyhcBK12k/Vu4EzSB45rzSC4fGFUD6sQgeaxItRCEEWeVwPafw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-darwin-arm64": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.51.0.tgz",
"integrity": "sha512-3QJbeYaMHn6Bh2XeBXuITSsbnIctyTjvHf5nRjKYrT9pPeErNIpp5VDEeAXC0CZSwSVTsc8WOSDwgrAI24JolQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-darwin-x64": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.51.0.tgz",
"integrity": "sha512-NzErhMaTEN1cY0E8C5APy74lw5VwsNfJfVPBMWPVQLqAbO0k4FFLjvHURvkUL+Y18Wu+8Vs1kbqPh2hjXYA4pg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-freebsd-x64": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.51.0.tgz",
"integrity": "sha512-msAIh3vPAoKoHlOE/oe6Q5C/n9umypv/k81lED82ibrJotn+3YG2Qp1kiR8o/Dg5iOEU97c6tl0utxcyFenpFw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm-gnueabihf": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.51.0.tgz",
"integrity": "sha512-CqQPcvqYyMe9ZBot2stjGogEzk1z8gGAngIX7srSzrzexmXixwVxBdFZyxTVM0CjGfDeV+Ru0w25/WNjlMM2Hw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm-musleabihf": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.51.0.tgz",
"integrity": "sha512-dstrlYQgZMnyOssxSbolGCge/sDbko12N/35RBNuqLpoPbft2aeBidBAb0dvQlyBd9RJ6u8D4o4Eh8Un6iTgyQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm64-gnu": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.51.0.tgz",
"integrity": "sha512-QEjUpXO7d35rP1/raLGGbAsBLLGZIzV3ZbeSjqWlD3oRnxpRIZ6iL4o51XQHkconn3uKssc+1VKdtHJ81BBhDA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm64-musl": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.51.0.tgz",
"integrity": "sha512-YSJua5irtG4DoMAjUapDTPhkQLHhBIY0G9JqlZS6/SZPzqDkPku/1GdWs0D6h/wyx0Iz31lNCfIaWKBQhzP0wQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-ppc64-gnu": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.51.0.tgz",
"integrity": "sha512-7L4Wj2IEUNDETKssB9IDYt16T6WlF+X2jgC/hBq3diGHda9vJLpAgb09+D3quFq7TdkFtI7hwz/jmuQmQFPc1Q==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-riscv64-gnu": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.51.0.tgz",
"integrity": "sha512-cBUHqtOXy76G41lOB401qpFoKx1xq17qYkhWrLSM7eEjiHM9sOtYqpr6ZdqCnN9s6ZpzudX4EkeHOFH2E9q0vA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-riscv64-musl": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.51.0.tgz",
"integrity": "sha512-WKbg8CysgZcHfZX0ixQFBRSBvFZUHa3SBnEjHY2FVYt2nbNJEjzTxA3ZR5wMU0NOCNKIAFUFvAh5/XJKPRJuJg==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-s390x-gnu": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.51.0.tgz",
"integrity": "sha512-N1QRUvJTxqXNSu35YOufdjsAVmKVx5bkrggOWAhTWBc3J4qjcBwr1IfyLh/6YCg8sYRSR1GraldS9jUgJL/U4A==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-x64-gnu": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.51.0.tgz",
"integrity": "sha512-e0Mz0DizsCoqNIjeOg6OUKe8JKJWZ5zZlwsd05Bmr51Jo3AOL4UJnPvwKumr4BBtBrDZkCmOLhCvDGm95nJM2g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-x64-musl": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.51.0.tgz",
"integrity": "sha512-wD8HGTWhYBKXvRDvoBVB1y+fEYV01samhWQSy1Zkxq2vpezvMnjaFKRuiP6tBNITLGuffbNDEXOwcAhJ3gI5Ug==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-openharmony-arm64": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.51.0.tgz",
"integrity": "sha512-5NSwQ2hDEJ0GPXqikjWtwzgAQCsS7P9aLMNenjjKa+gknN3lTCwwwERsT6lKXSirfU3jLjexA2XQvQALh5h27w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-arm64-msvc": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.51.0.tgz",
"integrity": "sha512-JEZyah1M0RHMw8d+jjSSJmSmO8sABA1J1RtrHYujGPeCkYg1NeH0TGuClpe2h5QtioRTaF57y/TZfn/2IFV6fA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-ia32-msvc": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.51.0.tgz",
"integrity": "sha512-q3cEoKH6kwjz/WRyHwSf0nlD2F5Qw536kCXvmlSu+kaShzgrA0ojmh45CA81qL+7udfCaZL2SdKCZlLiGBVFlg==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-x64-msvc": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.51.0.tgz",
"integrity": "sha512-Q14+fOGb9T28nWF/0EUsYqERiRA7cl1oy4TJrGmLaqhm+aO2cV+JttboHI3CbdeMCAyDI1+NoSlrM7Melhp/cw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@parcel/watcher": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
@ -7425,6 +8073,91 @@
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
"license": "MIT"
},
"node_modules/oxfmt": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.36.0.tgz",
"integrity": "sha512-/ejJ+KoSW6J9bcNT9a9UtJSJNWhJ3yOLSBLbkoFHJs/8CZjmaZVZAJe4YgO1KMJlKpNQasrn/G9JQUEZI3p0EQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"tinypool": "2.1.0"
},
"bin": {
"oxfmt": "bin/oxfmt"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/sponsors/Boshen"
},
"optionalDependencies": {
"@oxfmt/binding-android-arm-eabi": "0.36.0",
"@oxfmt/binding-android-arm64": "0.36.0",
"@oxfmt/binding-darwin-arm64": "0.36.0",
"@oxfmt/binding-darwin-x64": "0.36.0",
"@oxfmt/binding-freebsd-x64": "0.36.0",
"@oxfmt/binding-linux-arm-gnueabihf": "0.36.0",
"@oxfmt/binding-linux-arm-musleabihf": "0.36.0",
"@oxfmt/binding-linux-arm64-gnu": "0.36.0",
"@oxfmt/binding-linux-arm64-musl": "0.36.0",
"@oxfmt/binding-linux-ppc64-gnu": "0.36.0",
"@oxfmt/binding-linux-riscv64-gnu": "0.36.0",
"@oxfmt/binding-linux-riscv64-musl": "0.36.0",
"@oxfmt/binding-linux-s390x-gnu": "0.36.0",
"@oxfmt/binding-linux-x64-gnu": "0.36.0",
"@oxfmt/binding-linux-x64-musl": "0.36.0",
"@oxfmt/binding-openharmony-arm64": "0.36.0",
"@oxfmt/binding-win32-arm64-msvc": "0.36.0",
"@oxfmt/binding-win32-ia32-msvc": "0.36.0",
"@oxfmt/binding-win32-x64-msvc": "0.36.0"
}
},
"node_modules/oxlint": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.51.0.tgz",
"integrity": "sha512-g6DNPaV9/WI9MoX2XllafxQuxwY1TV++j7hP8fTJByVBuCoVtm3dy9f/2vtH/HU40JztcgWF4G7ua+gkainklQ==",
"dev": true,
"license": "MIT",
"bin": {
"oxlint": "bin/oxlint"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/sponsors/Boshen"
},
"optionalDependencies": {
"@oxlint/binding-android-arm-eabi": "1.51.0",
"@oxlint/binding-android-arm64": "1.51.0",
"@oxlint/binding-darwin-arm64": "1.51.0",
"@oxlint/binding-darwin-x64": "1.51.0",
"@oxlint/binding-freebsd-x64": "1.51.0",
"@oxlint/binding-linux-arm-gnueabihf": "1.51.0",
"@oxlint/binding-linux-arm-musleabihf": "1.51.0",
"@oxlint/binding-linux-arm64-gnu": "1.51.0",
"@oxlint/binding-linux-arm64-musl": "1.51.0",
"@oxlint/binding-linux-ppc64-gnu": "1.51.0",
"@oxlint/binding-linux-riscv64-gnu": "1.51.0",
"@oxlint/binding-linux-riscv64-musl": "1.51.0",
"@oxlint/binding-linux-s390x-gnu": "1.51.0",
"@oxlint/binding-linux-x64-gnu": "1.51.0",
"@oxlint/binding-linux-x64-musl": "1.51.0",
"@oxlint/binding-openharmony-arm64": "1.51.0",
"@oxlint/binding-win32-arm64-msvc": "1.51.0",
"@oxlint/binding-win32-ia32-msvc": "1.51.0",
"@oxlint/binding-win32-x64-msvc": "1.51.0"
},
"peerDependencies": {
"oxlint-tsgolint": ">=0.15.0"
},
"peerDependenciesMeta": {
"oxlint-tsgolint": {
"optional": true
}
}
},
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@ -9551,6 +10284,16 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinypool": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz",
"integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
},
"node_modules/tippy.js": {
"version": "6.3.7",
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",

@ -89,6 +89,8 @@
"autoprefixer": "10.4.27",
"browserlist": "latest",
"npm-check-updates": "19.6.3",
"oxfmt": "0.36.0",
"oxlint": "1.51.0",
"sass": "1.97.3",
"vite-plugin-vue-devtools": "8.0.6"
},

@ -595,44 +595,18 @@ async function login () {
if (!isFormValid) {
throw new Error(t('auth.errors.login'))
}
const resp = await APOLLO_CLIENT.mutate({
mutation: `
mutation(
$username: String!
$password: String!
$strategyId: UUID!
$siteId: UUID!
) {
login(
username: $username
password: $password
strategyId: $strategyId
siteId: $siteId
) {
operation {
succeeded
message
}
jwt
nextAction
continuationToken
redirect
tfaQRImage
}
}
`,
variables: {
username: state.username,
password: state.password,
const resp = await API_CLIENT.post(`sites/${siteStore.id}/auth/login`, {
json: {
strategyId: state.selectedStrategyId,
siteId: siteStore.id
username: state.username,
password: state.password
}
})
if (resp.data?.login?.operation?.succeeded) {
}).json()
if (resp.operation?.succeeded) {
state.password = ''
handleLoginResponse(resp.data.login)
handleLoginResponse(resp)
} else {
throw new Error(resp.data?.login?.operation?.message || t('auth.errors.loginError'))
throw new Error(resp.operation?.message || t('auth.errors.loginError'))
}
} catch (err) {
$q.loading.hide()
@ -983,7 +957,7 @@ async function finishSetupTFA () {
// MOUNTED
onMounted(async () => {
// await fetchStrategies()
await fetchStrategies()
})
</script>

Loading…
Cancel
Save