@ -1,13 +1,14 @@
|
|||||||
query {
|
query {
|
||||||
authentication {
|
authentication {
|
||||||
strategies(
|
strategies(
|
||||||
filter: "isEnabled eq true",
|
isEnabled: true
|
||||||
orderBy: "title ASC"
|
|
||||||
) {
|
) {
|
||||||
key
|
key
|
||||||
title
|
title
|
||||||
useForm
|
useForm
|
||||||
icon
|
icon
|
||||||
|
color
|
||||||
|
selfRegistration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
.md2 {
|
||||||
|
|
||||||
|
&.v-text-field .v-input__slot {
|
||||||
|
border-radius: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 1005 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 469 B |
After Width: | Height: | Size: 783 B |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,54 @@
|
|||||||
|
const { SchemaDirectiveVisitor } = require('graphql-tools')
|
||||||
|
const { defaultFieldResolver } = require('graphql')
|
||||||
|
|
||||||
|
class AuthDirective extends SchemaDirectiveVisitor {
|
||||||
|
visitObject(type) {
|
||||||
|
this.ensureFieldsWrapped(type)
|
||||||
|
type._requiredAuthScopes = this.args.requires
|
||||||
|
}
|
||||||
|
// Visitor methods for nested types like fields and arguments
|
||||||
|
// also receive a details object that provides information about
|
||||||
|
// the parent and grandparent types.
|
||||||
|
visitFieldDefinition(field, details) {
|
||||||
|
this.ensureFieldsWrapped(details.objectType)
|
||||||
|
field._requiredAuthScopes = this.args.requires
|
||||||
|
}
|
||||||
|
|
||||||
|
visitArgumentDefinition(argument, details) {
|
||||||
|
this.ensureFieldsWrapped(details.objectType)
|
||||||
|
argument._requiredAuthScopes = this.args.requires
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureFieldsWrapped(objectType) {
|
||||||
|
// Mark the GraphQLObjectType object to avoid re-wrapping:
|
||||||
|
if (objectType._authFieldsWrapped) return
|
||||||
|
objectType._authFieldsWrapped = true
|
||||||
|
|
||||||
|
const fields = objectType.getFields()
|
||||||
|
|
||||||
|
Object.keys(fields).forEach(fieldName => {
|
||||||
|
const field = fields[fieldName]
|
||||||
|
const { resolve = defaultFieldResolver } = field
|
||||||
|
field.resolve = async function (...args) {
|
||||||
|
// Get the required scopes from the field first, falling back
|
||||||
|
// to the objectType if no scopes is required by the field:
|
||||||
|
const requiredScopes = field._requiredAuthScopes || objectType._requiredAuthScopes
|
||||||
|
|
||||||
|
if (!requiredScopes) {
|
||||||
|
return resolve.apply(this, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = args[2]
|
||||||
|
console.info(context.req.user)
|
||||||
|
// const user = await getUser(context.headers.authToken)
|
||||||
|
// if (!user.hasRole(requiredScopes)) {
|
||||||
|
// throw new Error('not authorized')
|
||||||
|
// }
|
||||||
|
|
||||||
|
return resolve.apply(this, args)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AuthDirective
|
@ -1,33 +1,75 @@
|
|||||||
|
const jwt = require('jsonwebtoken')
|
||||||
|
const moment = require('moment')
|
||||||
|
|
||||||
|
const securityHelper = require('../helpers/security')
|
||||||
|
|
||||||
/* global WIKI */
|
/* global WIKI */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication middleware
|
* Authentication middleware
|
||||||
*/
|
*/
|
||||||
module.exports = (req, res, next) => {
|
module.exports = {
|
||||||
// Is user authenticated ?
|
jwt(req, res, next) {
|
||||||
|
WIKI.auth.passport.authenticate('jwt', {session: false}, async (err, user, info) => {
|
||||||
|
if (err) { return next() }
|
||||||
|
|
||||||
|
console.info(err, user, info)
|
||||||
|
|
||||||
|
// Expired but still valid within 7 days, just renew
|
||||||
|
if (info instanceof jwt.TokenExpiredError && moment().subtract(7, 'days').isBefore(info.expiredAt)) {
|
||||||
|
const jwtPayload = jwt.decode(securityHelper.extractJWT(req))
|
||||||
|
console.info(jwtPayload)
|
||||||
|
try {
|
||||||
|
const newToken = await WIKI.models.users.refreshToken(jwtPayload.id)
|
||||||
|
user = newToken.user
|
||||||
|
|
||||||
|
// Try headers, otherwise cookies for response
|
||||||
|
if (req.get('content-type') === 'application/json') {
|
||||||
|
res.headers('new-jwt', newToken.token)
|
||||||
|
} else {
|
||||||
|
res.cookie('jwt', newToken.token, { expires: moment().add(7, 'days').toDate() })
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!req.isAuthenticated()) {
|
// JWT is NOT valid
|
||||||
if (WIKI.config.public !== true) {
|
if (!user) { return next() }
|
||||||
return res.redirect('/login')
|
|
||||||
|
// JWT is valid
|
||||||
|
req.logIn(user, { session: false }, (err) => {
|
||||||
|
if (err) { return next(err) }
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
})(req, res, next)
|
||||||
|
},
|
||||||
|
checkPath(req, res, next) {
|
||||||
|
// Is user authenticated ?
|
||||||
|
|
||||||
|
if (!req.isAuthenticated()) {
|
||||||
|
if (WIKI.config.public !== true) {
|
||||||
|
return res.redirect('/login')
|
||||||
|
} else {
|
||||||
|
// req.user = rights.guest
|
||||||
|
res.locals.isGuest = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// req.user = rights.guest
|
res.locals.isGuest = false
|
||||||
res.locals.isGuest = true
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res.locals.isGuest = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check permissions
|
// Check permissions
|
||||||
|
|
||||||
// res.locals.rights = rights.check(req)
|
// res.locals.rights = rights.check(req)
|
||||||
|
|
||||||
// if (!res.locals.rights.read) {
|
// if (!res.locals.rights.read) {
|
||||||
// return res.render('error-forbidden')
|
// return res.render('error-forbidden')
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Expose user data
|
// Expose user data
|
||||||
|
|
||||||
res.locals.user = req.user
|
res.locals.user = req.user
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|