Skip to content

Commit

Permalink
fix: various auth improvements + other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
NGPixel committed Sep 2, 2023
1 parent 349f4e5 commit 5a60fb1
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 108 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ services:
# (Adding the "ports" property to this file will not forward from a Codespace.)

db:
image: postgres:16beta1
image: postgres:16rc1
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
Expand Down
8 changes: 3 additions & 5 deletions config.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Wiki.js - CONFIGURATION #
#######################################################################
# Full documentation + examples:
# https://js.wiki/docs/install
# https://next.js.wiki/docs/install

# ---------------------------------------------------------------------
# Port the server should listen to
Expand All @@ -13,17 +13,15 @@ port: 3000
# ---------------------------------------------------------------------
# Database
# ---------------------------------------------------------------------
# PostgreSQL 11 or later required
# PostgreSQL 12 or later required

db:
host: localhost
port: 5432
user: postgres
pass: postgres
db: postgres
schemas:
wiki: wiki
scheduler: scheduler
schema: wiki
ssl: false

# Optional
Expand Down
4 changes: 1 addition & 3 deletions server/app/data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ defaults:
ssl: false
sslOptions:
auto: true
schemas:
wiki: wiki
scheduler: scheduler
schema: wiki
ssl:
enabled: false
pool:
Expand Down
6 changes: 3 additions & 3 deletions server/core/db.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default {
useNullAsDefault: true,
asyncStackTraces: WIKI.IS_DEBUG,
connection: this.config,
searchPath: [WIKI.config.db.schemas.wiki],
searchPath: [WIKI.config.db.schema],
pool: {
...workerMode ? { min: 0, max: 1 } : WIKI.config.pool,
async afterCreate(conn, done) {
Expand Down Expand Up @@ -223,12 +223,12 @@ export default {
*/
async syncSchemas () {
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...')
return this.knex.migrate.latest({
tableName: 'migrations',
migrationSource,
schemaName: WIKI.config.db.schemas.wiki
schemaName: WIKI.config.db.schema
})
},
/**
Expand Down
4 changes: 2 additions & 2 deletions server/db/migrations/3.0.0.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export async function up (knex) {
table.string('displayName').notNullable().defaultTo('')
table.jsonb('config').notNullable().defaultTo('{}')
table.boolean('selfRegistration').notNullable().defaultTo(false)
table.jsonb('domainWhitelist').notNullable().defaultTo('[]')
table.jsonb('autoEnrollGroups').notNullable().defaultTo('[]')
table.string('allowedEmailRegex')
table.specificType('autoEnrollGroups', 'uuid[]')
})
.createTable('commentProviders', table => {
table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))
Expand Down
47 changes: 44 additions & 3 deletions server/graph/resolvers/authentication.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,16 @@ export default {
async authSiteStrategies (obj, args, context, info) {
const site = await WIKI.db.sites.query().findById(args.siteId)
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]) || {}
return {
id: str.id,
activeStrategy: str,
order: siteAuth.order ?? 0,
isVisible: siteAuth.isVisible ?? false
}
})
}), ['order'])
return args.visibleOnly ? siteStrategies.filter(s => s.isVisible) : siteStrategies
}
},
Mutation: {
Expand Down Expand Up @@ -196,6 +197,10 @@ export default {
*/
async setApiState (obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

WIKI.config.api.isEnabled = args.enabled
await WIKI.configSvc.saveToDb(['api'])
return {
Expand All @@ -210,6 +215,10 @@ export default {
*/
async revokeApiKey (obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

await WIKI.db.apiKeys.query().findById(args.id).patch({
isRevoked: true
})
Expand All @@ -227,11 +236,14 @@ export default {
*/
async updateAuthStrategies (obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

const previousStrategies = await WIKI.db.authentication.getStrategies()
for (const str of args.strategies) {
const newStr = {
displayName: str.displayName,
order: str.order,
isEnabled: str.isEnabled,
config: _.reduce(str.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
Expand Down Expand Up @@ -280,6 +292,10 @@ export default {
*/
async regenerateCertificates (obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

await WIKI.auth.regenerateCertificates()
return {
responseResult: generateSuccess('Certificates have been regenerated successfully.')
Expand All @@ -293,6 +309,10 @@ export default {
*/
async resetGuestUser (obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

await WIKI.auth.resetGuestUser()
return {
responseResult: generateSuccess('Guest user has been reset successfully.')
Expand All @@ -302,7 +322,28 @@ export default {
}
}
},
// ------------------------------------------------------------------
// TYPE: 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) {
return _.find(WIKI.data.authentication, ['key', obj.module])
}
Expand Down
22 changes: 11 additions & 11 deletions server/graph/resolvers/page.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ export default {
user: context.req.user
})
return {
responseResult: generateSuccess('Page has been converted.')
operation: generateSuccess('Page has been converted.')
}
} catch (err) {
return generateError(err)
Expand All @@ -499,7 +499,7 @@ export default {
user: context.req.user
})
return {
responseResult: generateSuccess('Page has been moved.')
operation: generateSuccess('Page has been moved.')
}
} catch (err) {
return generateError(err)
Expand All @@ -515,7 +515,7 @@ export default {
user: context.req.user
})
return {
responseResult: generateSuccess('Page has been deleted.')
operation: generateSuccess('Page has been deleted.')
}
} catch (err) {
return generateError(err)
Expand All @@ -534,7 +534,7 @@ export default {
throw new Error('This tag does not exist.')
}
return {
responseResult: generateSuccess('Tag has been deleted.')
operation: generateSuccess('Tag has been deleted.')
}
} catch (err) {
return generateError(err)
Expand All @@ -555,7 +555,7 @@ export default {
throw new Error('This tag does not exist.')
}
return {
responseResult: generateSuccess('Tag has been updated successfully.')
operation: generateSuccess('Tag has been updated successfully.')
}
} catch (err) {
return generateError(err)
Expand All @@ -569,7 +569,7 @@ export default {
await WIKI.db.pages.flushCache()
WIKI.events.outbound.emit('flushCache')
return {
responseResult: generateSuccess('Pages Cache has been flushed successfully.')
operation: generateSuccess('Pages Cache has been flushed successfully.')
}
} catch (err) {
return generateError(err)
Expand All @@ -582,7 +582,7 @@ export default {
try {
const count = await WIKI.db.pages.migrateToLocale(args)
return {
responseResult: generateSuccess('Migrated content to target locale successfully.'),
operation: generateSuccess('Migrated content to target locale successfully.'),
count
}
} catch (err) {
Expand All @@ -596,7 +596,7 @@ export default {
try {
await WIKI.db.pages.rebuildTree()
return {
responseResult: generateSuccess('Page tree rebuilt successfully.')
operation: generateSuccess('Page tree rebuilt successfully.')
}
} catch (err) {
return generateError(err)
Expand All @@ -613,7 +613,7 @@ export default {
}
await WIKI.db.pages.renderPage(page)
return {
responseResult: generateSuccess('Page rendered successfully.')
operation: generateSuccess('Page rendered successfully.')
}
} catch (err) {
return generateError(err)
Expand Down Expand Up @@ -649,7 +649,7 @@ export default {
})

return {
responseResult: generateSuccess('Page version restored successfully.')
operation: generateSuccess('Page version restored successfully.')
}
} catch (err) {
return generateError(err)
Expand All @@ -662,7 +662,7 @@ export default {
try {
await WIKI.db.pageHistory.purge(args.olderThan)
return {
responseResult: generateSuccess('Page history purged successfully.')
operation: generateSuccess('Page history purged successfully.')
}
} catch (err) {
return generateError(err)
Expand Down
9 changes: 4 additions & 5 deletions server/graph/schemas/authentication.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,13 @@ type AuthenticationActiveStrategy {
isEnabled: Boolean
config: JSON
selfRegistration: Boolean
domainWhitelist: [String]
autoEnrollGroups: [Int]
allowedEmailRegex: String
autoEnrollGroups: [UUID]
}

type AuthenticationSiteStrategy {
id: UUID
activeStrategy: AuthenticationActiveStrategy
order: Int
isVisible: Boolean
}

Expand Down Expand Up @@ -146,8 +145,8 @@ input AuthenticationStrategyInput {
order: Int!
isEnabled: Boolean!
selfRegistration: Boolean!
domainWhitelist: [String]!
autoEnrollGroups: [Int]!
allowedEmailRegex: String!
autoEnrollGroups: [UUID]!
}

type AuthenticationApiKey {
Expand Down
6 changes: 3 additions & 3 deletions server/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@
"admin.audit.title": "Audit Log",
"admin.auth.activeStrategies": "Active Strategies",
"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.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.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.displayName": "Display Name",
"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.enabledForced": "This strategy cannot be disabled.",
"admin.auth.enabledHint": "Should this strategy be available to sites for login.",
Expand Down
7 changes: 1 addition & 6 deletions server/models/authentication.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ export class Authentication extends Model {
}

static async getStrategies({ enabledOnly = false } = {}) {
const strategies = await WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {})
return strategies.map(str => ({
...str,
domainWhitelist: get(str.domainWhitelist, 'v', []),
autoEnrollGroups: get(str.autoEnrollGroups, 'v', [])
}))
return WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {})
}

static async refreshStrategiesFromDisk() {
Expand Down
Loading

0 comments on commit 5a60fb1

Please sign in to comment.