fix: various auth improvements + other fixes

pull/6775/head
NGPixel 10 months ago
parent 349f4e5730
commit 5a60fb11b5
No known key found for this signature in database
GPG Key ID: B755FB6870B30F63

@ -28,7 +28,7 @@ services:
# (Adding the "ports" property to this file will not forward from a Codespace.) # (Adding the "ports" property to this file will not forward from a Codespace.)
db: db:
image: postgres:16beta1 image: postgres:16rc1
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- postgres-data:/var/lib/postgresql/data - postgres-data:/var/lib/postgresql/data

@ -2,7 +2,7 @@
# Wiki.js - CONFIGURATION # # Wiki.js - CONFIGURATION #
####################################################################### #######################################################################
# Full documentation + examples: # Full documentation + examples:
# https://js.wiki/docs/install # https://next.js.wiki/docs/install
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# Port the server should listen to # Port the server should listen to
@ -13,7 +13,7 @@ port: 3000
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# Database # Database
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# PostgreSQL 11 or later required # PostgreSQL 12 or later required
db: db:
host: localhost host: localhost
@ -21,9 +21,7 @@ db:
user: postgres user: postgres
pass: postgres pass: postgres
db: postgres db: postgres
schemas: schema: wiki
wiki: wiki
scheduler: scheduler
ssl: false ssl: false
# Optional # Optional

@ -16,9 +16,7 @@ defaults:
ssl: false ssl: false
sslOptions: sslOptions:
auto: true auto: true
schemas: schema: wiki
wiki: wiki
scheduler: scheduler
ssl: ssl:
enabled: false enabled: false
pool: pool:

@ -86,7 +86,7 @@ export default {
useNullAsDefault: true, useNullAsDefault: true,
asyncStackTraces: WIKI.IS_DEBUG, asyncStackTraces: WIKI.IS_DEBUG,
connection: this.config, connection: this.config,
searchPath: [WIKI.config.db.schemas.wiki], searchPath: [WIKI.config.db.schema],
pool: { pool: {
...workerMode ? { min: 0, max: 1 } : WIKI.config.pool, ...workerMode ? { min: 0, max: 1 } : WIKI.config.pool,
async afterCreate(conn, done) { async afterCreate(conn, done) {
@ -223,12 +223,12 @@ export default {
*/ */
async syncSchemas () { async syncSchemas () {
WIKI.logger.info('Ensuring DB schema exists...') WIKI.logger.info('Ensuring DB schema exists...')
await this.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${WIKI.config.db.schemas.wiki}`) await this.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${WIKI.config.db.schema}`)
WIKI.logger.info('Ensuring DB migrations have been applied...') WIKI.logger.info('Ensuring DB migrations have been applied...')
return this.knex.migrate.latest({ return this.knex.migrate.latest({
tableName: 'migrations', tableName: 'migrations',
migrationSource, migrationSource,
schemaName: WIKI.config.db.schemas.wiki schemaName: WIKI.config.db.schema
}) })
}, },
/** /**

@ -67,8 +67,8 @@ export async function up (knex) {
table.string('displayName').notNullable().defaultTo('') table.string('displayName').notNullable().defaultTo('')
table.jsonb('config').notNullable().defaultTo('{}') table.jsonb('config').notNullable().defaultTo('{}')
table.boolean('selfRegistration').notNullable().defaultTo(false) table.boolean('selfRegistration').notNullable().defaultTo(false)
table.jsonb('domainWhitelist').notNullable().defaultTo('[]') table.string('allowedEmailRegex')
table.jsonb('autoEnrollGroups').notNullable().defaultTo('[]') table.specificType('autoEnrollGroups', 'uuid[]')
}) })
.createTable('commentProviders', table => { .createTable('commentProviders', table => {
table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()')) table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))

@ -57,7 +57,7 @@ export default {
async authSiteStrategies (obj, args, context, info) { async authSiteStrategies (obj, args, context, info) {
const site = await WIKI.db.sites.query().findById(args.siteId) const site = await WIKI.db.sites.query().findById(args.siteId)
const activeStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true }) const activeStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true })
return activeStrategies.map(str => { const siteStrategies = _.sortBy(activeStrategies.map(str => {
const siteAuth = _.find(site.config.authStrategies, ['id', str.id]) || {} const siteAuth = _.find(site.config.authStrategies, ['id', str.id]) || {}
return { return {
id: str.id, id: str.id,
@ -65,7 +65,8 @@ export default {
order: siteAuth.order ?? 0, order: siteAuth.order ?? 0,
isVisible: siteAuth.isVisible ?? false isVisible: siteAuth.isVisible ?? false
} }
}) }), ['order'])
return args.visibleOnly ? siteStrategies.filter(s => s.isVisible) : siteStrategies
} }
}, },
Mutation: { Mutation: {
@ -196,6 +197,10 @@ export default {
*/ */
async setApiState (obj, args, context) { async setApiState (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
WIKI.config.api.isEnabled = args.enabled WIKI.config.api.isEnabled = args.enabled
await WIKI.configSvc.saveToDb(['api']) await WIKI.configSvc.saveToDb(['api'])
return { return {
@ -210,6 +215,10 @@ export default {
*/ */
async revokeApiKey (obj, args, context) { async revokeApiKey (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
await WIKI.db.apiKeys.query().findById(args.id).patch({ await WIKI.db.apiKeys.query().findById(args.id).patch({
isRevoked: true isRevoked: true
}) })
@ -227,11 +236,14 @@ export default {
*/ */
async updateAuthStrategies (obj, args, context) { async updateAuthStrategies (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
const previousStrategies = await WIKI.db.authentication.getStrategies() const previousStrategies = await WIKI.db.authentication.getStrategies()
for (const str of args.strategies) { for (const str of args.strategies) {
const newStr = { const newStr = {
displayName: str.displayName, displayName: str.displayName,
order: str.order,
isEnabled: str.isEnabled, isEnabled: str.isEnabled,
config: _.reduce(str.config, (result, value, key) => { config: _.reduce(str.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null)) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
@ -280,6 +292,10 @@ export default {
*/ */
async regenerateCertificates (obj, args, context) { async regenerateCertificates (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
await WIKI.auth.regenerateCertificates() await WIKI.auth.regenerateCertificates()
return { return {
responseResult: generateSuccess('Certificates have been regenerated successfully.') responseResult: generateSuccess('Certificates have been regenerated successfully.')
@ -293,6 +309,10 @@ export default {
*/ */
async resetGuestUser (obj, args, context) { async resetGuestUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
await WIKI.auth.resetGuestUser() await WIKI.auth.resetGuestUser()
return { return {
responseResult: generateSuccess('Guest user has been reset successfully.') responseResult: generateSuccess('Guest user has been reset successfully.')
@ -302,7 +322,28 @@ export default {
} }
} }
}, },
// ------------------------------------------------------------------
// TYPE: AuthenticationActiveStrategy
// ------------------------------------------------------------------
AuthenticationActiveStrategy: { AuthenticationActiveStrategy: {
config (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return obj.config ?? {}
},
allowedEmailRegex (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return obj.allowedEmailRegex ?? ''
},
autoEnrollGroups (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return obj.autoEnrollGroups ?? []
},
strategy (obj, args, context) { strategy (obj, args, context) {
return _.find(WIKI.data.authentication, ['key', obj.module]) return _.find(WIKI.data.authentication, ['key', obj.module])
} }

@ -483,7 +483,7 @@ export default {
user: context.req.user user: context.req.user
}) })
return { return {
responseResult: generateSuccess('Page has been converted.') operation: generateSuccess('Page has been converted.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -499,7 +499,7 @@ export default {
user: context.req.user user: context.req.user
}) })
return { return {
responseResult: generateSuccess('Page has been moved.') operation: generateSuccess('Page has been moved.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -515,7 +515,7 @@ export default {
user: context.req.user user: context.req.user
}) })
return { return {
responseResult: generateSuccess('Page has been deleted.') operation: generateSuccess('Page has been deleted.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -534,7 +534,7 @@ export default {
throw new Error('This tag does not exist.') throw new Error('This tag does not exist.')
} }
return { return {
responseResult: generateSuccess('Tag has been deleted.') operation: generateSuccess('Tag has been deleted.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -555,7 +555,7 @@ export default {
throw new Error('This tag does not exist.') throw new Error('This tag does not exist.')
} }
return { return {
responseResult: generateSuccess('Tag has been updated successfully.') operation: generateSuccess('Tag has been updated successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -569,7 +569,7 @@ export default {
await WIKI.db.pages.flushCache() await WIKI.db.pages.flushCache()
WIKI.events.outbound.emit('flushCache') WIKI.events.outbound.emit('flushCache')
return { return {
responseResult: generateSuccess('Pages Cache has been flushed successfully.') operation: generateSuccess('Pages Cache has been flushed successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -582,7 +582,7 @@ export default {
try { try {
const count = await WIKI.db.pages.migrateToLocale(args) const count = await WIKI.db.pages.migrateToLocale(args)
return { return {
responseResult: generateSuccess('Migrated content to target locale successfully.'), operation: generateSuccess('Migrated content to target locale successfully.'),
count count
} }
} catch (err) { } catch (err) {
@ -596,7 +596,7 @@ export default {
try { try {
await WIKI.db.pages.rebuildTree() await WIKI.db.pages.rebuildTree()
return { return {
responseResult: generateSuccess('Page tree rebuilt successfully.') operation: generateSuccess('Page tree rebuilt successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -613,7 +613,7 @@ export default {
} }
await WIKI.db.pages.renderPage(page) await WIKI.db.pages.renderPage(page)
return { return {
responseResult: generateSuccess('Page rendered successfully.') operation: generateSuccess('Page rendered successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -649,7 +649,7 @@ export default {
}) })
return { return {
responseResult: generateSuccess('Page version restored successfully.') operation: generateSuccess('Page version restored successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)
@ -662,7 +662,7 @@ export default {
try { try {
await WIKI.db.pageHistory.purge(args.olderThan) await WIKI.db.pageHistory.purge(args.olderThan)
return { return {
responseResult: generateSuccess('Page history purged successfully.') operation: generateSuccess('Page history purged successfully.')
} }
} catch (err) { } catch (err) {
return generateError(err) return generateError(err)

@ -106,14 +106,13 @@ type AuthenticationActiveStrategy {
isEnabled: Boolean isEnabled: Boolean
config: JSON config: JSON
selfRegistration: Boolean selfRegistration: Boolean
domainWhitelist: [String] allowedEmailRegex: String
autoEnrollGroups: [Int] autoEnrollGroups: [UUID]
} }
type AuthenticationSiteStrategy { type AuthenticationSiteStrategy {
id: UUID id: UUID
activeStrategy: AuthenticationActiveStrategy activeStrategy: AuthenticationActiveStrategy
order: Int
isVisible: Boolean isVisible: Boolean
} }
@ -146,8 +145,8 @@ input AuthenticationStrategyInput {
order: Int! order: Int!
isEnabled: Boolean! isEnabled: Boolean!
selfRegistration: Boolean! selfRegistration: Boolean!
domainWhitelist: [String]! allowedEmailRegex: String!
autoEnrollGroups: [Int]! autoEnrollGroups: [UUID]!
} }
type AuthenticationApiKey { type AuthenticationApiKey {

@ -66,16 +66,16 @@
"admin.audit.title": "Audit Log", "admin.audit.title": "Audit Log",
"admin.auth.activeStrategies": "Active Strategies", "admin.auth.activeStrategies": "Active Strategies",
"admin.auth.addStrategy": "Add Strategy", "admin.auth.addStrategy": "Add Strategy",
"admin.auth.allowedEmailRegex": "Allowed Email Address Regex",
"admin.auth.allowedEmailRegexHint": "(optional) Only allow users to register with an email address that matches the regex expression.",
"admin.auth.allowedWebOrigins": "Allowed Web Origins", "admin.auth.allowedWebOrigins": "Allowed Web Origins",
"admin.auth.autoEnrollGroups": "Assign to group(s)", "admin.auth.autoEnrollGroups": "Assign to group(s)",
"admin.auth.autoEnrollGroupsHint": "Automatically assign new users to these groups. New users are always added to the Users group regardless of this setting.", "admin.auth.autoEnrollGroupsHint": "(optional) Automatically assign new users to these groups. New users are always added to the Users group regardless of this setting.",
"admin.auth.callbackUrl": "Callback URL / Redirect URI", "admin.auth.callbackUrl": "Callback URL / Redirect URI",
"admin.auth.configReference": "Configuration Reference", "admin.auth.configReference": "Configuration Reference",
"admin.auth.configReferenceSubtitle": "Some strategies may require some configuration values to be set on your provider. These are provided for reference only and may not be needed by the current strategy.", "admin.auth.configReferenceSubtitle": "Some strategies may require some configuration values to be set on your provider. These are provided for reference only and may not be needed by the current strategy.",
"admin.auth.displayName": "Display Name", "admin.auth.displayName": "Display Name",
"admin.auth.displayNameHint": "The title shown to the end user for this authentication strategy.", "admin.auth.displayNameHint": "The title shown to the end user for this authentication strategy.",
"admin.auth.domainsWhitelist": "Email Address Allowlist",
"admin.auth.domainsWhitelistHint": "Only allow users to register with an email address that matches the regex expression.",
"admin.auth.enabled": "Enabled", "admin.auth.enabled": "Enabled",
"admin.auth.enabledForced": "This strategy cannot be disabled.", "admin.auth.enabledForced": "This strategy cannot be disabled.",
"admin.auth.enabledHint": "Should this strategy be available to sites for login.", "admin.auth.enabledHint": "Should this strategy be available to sites for login.",

@ -34,12 +34,7 @@ export class Authentication extends Model {
} }
static async getStrategies({ enabledOnly = false } = {}) { static async getStrategies({ enabledOnly = false } = {}) {
const strategies = await WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {}) return WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {})
return strategies.map(str => ({
...str,
domainWhitelist: get(str.domainWhitelist, 'v', []),
autoEnrollGroups: get(str.autoEnrollGroups, 'v', [])
}))
} }
static async refreshStrategiesFromDisk() { static async refreshStrategiesFromDisk() {

@ -1045,15 +1045,12 @@ export class Page extends Model {
await WIKI.db.pages.deletePageFromCache(page.hash) await WIKI.db.pages.deletePageFromCache(page.hash)
WIKI.events.outbound.emit('deletePageFromCache', page.hash) WIKI.events.outbound.emit('deletePageFromCache', page.hash)
// -> Delete from Search Index
await WIKI.data.searchEngine.deleted(page)
// -> Delete from Storage // -> Delete from Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.db.storage.pageEvent({ // await WIKI.db.storage.pageEvent({
event: 'deleted', // event: 'deleted',
page // page
}) // })
} }
// -> Reconnect Links // -> Reconnect Links
@ -1076,6 +1073,8 @@ export class Page extends Model {
* @returns {Promise} Promise with no value * @returns {Promise} Promise with no value
*/ */
static async reconnectLinks (opts) { static async reconnectLinks (opts) {
return
// TODO: fix this
const pageHref = `/${opts.locale}/${opts.path}` const pageHref = `/${opts.locale}/${opts.path}`
let replaceArgs = { let replaceArgs = {
from: '', from: '',
@ -1142,20 +1141,6 @@ export class Page extends Model {
} }
} }
/**
* Rebuild page tree for new/updated/deleted page
*
* @returns {Promise} Promise with no value
*/
static async rebuildTree() {
const rebuildJob = await WIKI.scheduler.registerJob({
name: 'rebuild-tree',
immediate: true,
worker: true
})
return rebuildJob.finished
}
/** /**
* Trigger the rendering of a page * Trigger the rendering of a page
* *

@ -461,7 +461,6 @@ async function fetchStrategies (showAll = false) {
} }
selfRegistration selfRegistration
} }
order
} }
} }
`, `,

@ -171,15 +171,15 @@ q-page.admin-mail
q-item q-item
blueprint-icon(icon='private') blueprint-icon(icon='private')
q-item-section q-item-section
q-item-label {{t(`admin.auth.domainsWhitelist`)}} q-item-label {{t(`admin.auth.allowedEmailRegex`)}}
q-item-label(caption) {{t(`admin.auth.domainsWhitelistHint`)}} q-item-label(caption) {{t(`admin.auth.allowedEmailRegexHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='state.strategy.domainWhitelist' v-model='state.strategy.allowedEmailRegex'
dense dense
hide-bottom-space hide-bottom-space
:aria-label='t(`admin.auth.domainsWhitelist`)' :aria-label='t(`admin.auth.allowedEmailRegex`)'
prefix='/' prefix='/'
suffix='/' suffix='/'
) )
@ -193,8 +193,8 @@ q-page.admin-mail
q-banner.q-mt-md( q-banner.q-mt-md(
v-if='!state.strategy.config || Object.keys(state.strategy.config).length < 1' v-if='!state.strategy.config || Object.keys(state.strategy.config).length < 1'
rounded rounded
:class='$q.dark.isActive ? `bg-negative text-white` : `bg-grey-2 text-grey-7`' :class='$q.dark.isActive ? `bg-dark-4 text-grey-5` : `bg-grey-2 text-grey-7`'
) {{t('admin.auth.noConfigOption')}} ): em {{t('admin.auth.noConfigOption')}}
template( template(
v-for='(cfg, cfgKey, idx) in state.strategy.config' v-for='(cfg, cfgKey, idx) in state.strategy.config'
) )
@ -213,7 +213,7 @@ q-page.admin-mail
color='primary' color='primary'
checked-icon='las la-check' checked-icon='las la-check'
unchecked-icon='las la-times' unchecked-icon='las la-times'
:aria-label='t(`admin.general.allowComments`)' :aria-label='cfg.title'
:disable='cfg.readOnly' :disable='cfg.readOnly'
) )
q-item(v-else) q-item(v-else)
@ -432,7 +432,7 @@ async function load () {
isEnabled isEnabled
config config
selfRegistration selfRegistration
domainWhitelist allowedEmailRegex
autoEnrollGroups autoEnrollGroups
} }
} }
@ -505,7 +505,7 @@ function addStrategy (str) {
isEnabled: true, isEnabled: true,
displayName: str.title, displayName: str.title,
selfRegistration: true, selfRegistration: true,
domainWhitelist: [], allowedEmailRegex: '',
autoEnrollGroups: [] autoEnrollGroups: []
} }
state.activeStrategies = [...state.activeStrategies, newStr] state.activeStrategies = [...state.activeStrategies, newStr]

@ -145,30 +145,30 @@ q-page.admin-login
q-card-section q-card-section
.text-subtitle1 {{t('admin.login.providers')}} .text-subtitle1 {{t('admin.login.providers')}}
q-card-section.admin-login-providers.q-pt-none q-card-section.admin-login-providers.q-pt-none
draggable( sortable(
class='q-list rounded-borders' class='q-list'
:list='state.providers' :list='state.providers'
:animation='150'
handle='.handle'
@end='dragStarted = false'
item-key='id' item-key='id'
:options='sortableOptions'
@end='updateAuthPosition'
) )
template(#item='{element}') template(#item='{element}')
q-item q-item
q-item-section(side) q-item-section(side)
q-icon.handle(name='las la-bars') q-icon.handle(name='mdi-drag-horizontal')
blueprint-icon(:icon='element.icon') q-item-section(side)
q-icon(:name='`img:` + element.activeStrategy.strategy.icon')
q-item-section q-item-section
q-item-label {{element.label}} q-item-label {{element.activeStrategy.displayName}}
q-item-label(caption) {{element.provider}} q-item-label(caption) {{element.activeStrategy.strategy.title}}
q-item-section(side) q-item-section(side)
q-toggle( q-toggle(
v-model='element.isActive' v-model='element.isVisible'
color='primary' color='primary'
checked-icon='las la-check' checked-icon='las la-check'
unchecked-icon='las la-times' unchecked-icon='las la-times'
label='Visible' label='Visible'
:aria-label='element.label' :aria-label='element.activeStrategy.displayName'
) )
q-item.q-pt-none q-item.q-pt-none
q-item-section q-item-section
@ -183,7 +183,7 @@ q-page.admin-login
<script setup> <script setup>
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import draggable from 'vuedraggable' import { Sortable } from 'sortablejs-vue3'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
@ -224,11 +224,18 @@ const state = reactive({
welcomeRedirect: '/', welcomeRedirect: '/',
logoutRedirect: '/' logoutRedirect: '/'
}, },
providers: [ providers: []
{ id: 'local', label: 'Local Authentication', provider: 'Username-Password', icon: 'database', isActive: true }, })
{ id: 'google', label: 'Google', provider: 'Google', icon: 'google', isActive: true },
{ id: 'slack', label: 'Slack', provider: 'Slack', icon: 'slack', isActive: false } const sortableOptions = {
] handle: '.handle',
animation: 150
}
// WATCHERS
watch(() => adminStore.currentSiteId, (newValue) => {
load()
}) })
// METHODS // METHODS
@ -236,24 +243,34 @@ const state = reactive({
async function load () { async function load () {
state.loading++ state.loading++
$q.loading.show() $q.loading.show()
// const resp = await APOLLO_CLIENT.query({ const resp = await APOLLO_CLIENT.query({
// query: gql` query: gql`
// query getSite ( query getSiteAuthStrategies (
// $id: UUID! $siteId: UUID!
// ) { ) {
// siteById( authSiteStrategies(
// id: $id siteId: $siteId
// ) { visibleOnly: false
// id ) {
// } id
// } activeStrategy {
// `, displayName
// variables: { strategy {
// id: adminStore.currentSiteId key
// }, title
// fetchPolicy: 'network-only' icon
// }) }
// this.config = cloneDeep(resp?.data?.siteById) }
isVisible
}
}
`,
variables: {
siteId: adminStore.currentSiteId
},
fetchPolicy: 'network-only'
})
state.providers = cloneDeep(resp?.data?.authSiteStrategies)
$q.loading.hide() $q.loading.hide()
state.loading-- state.loading--
} }
@ -300,6 +317,11 @@ async function save () {
state.loading-- state.loading--
} }
function updateAuthPosition (ev) {
const item = state.providers.splice(ev.oldIndex, 1)[0]
state.providers.splice(ev.newIndex, 0, item)
}
async function uploadBg () { async function uploadBg () {
const input = document.createElement('input') const input = document.createElement('input')
input.type = 'file' input.type = 'file'

Loading…
Cancel
Save