squash new oauth2 flow
This commit is contained in:
@@ -196,7 +196,7 @@ const eventController = {
|
||||
|
||||
async get(req, res) {
|
||||
const format = req.params.format || 'json'
|
||||
const is_admin = res.locals.user && res.locals.user.is_admin
|
||||
const is_admin = req.user && req.user.is_admin
|
||||
const slug = req.params.event_slug
|
||||
|
||||
// retrocompatibility, old events URL does not use slug, use id as fallback
|
||||
@@ -301,7 +301,7 @@ const eventController = {
|
||||
log.warn(`Trying to confirm a unknown event, id: ${id}`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||
if (!req.user.is_admin && req.user.id !== event.userId) {
|
||||
log.warn(`Someone not allowed is trying to confirm -> "${event.title} `)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
@@ -327,7 +327,7 @@ const eventController = {
|
||||
const id = Number(req.params.event_id)
|
||||
const event = await Event.findByPk(id)
|
||||
if (!event) { return req.sendStatus(404) }
|
||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||
if (!req.user.is_admin && req.user.id !== event.userId) {
|
||||
log.warn(`Someone not allowed is trying to unconfirm -> "${event.title} `)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
@@ -386,8 +386,8 @@ const eventController = {
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
async isAnonEventAllowed(_req, res, next) {
|
||||
if (!res.locals.settings.allow_anon_event && !res.locals.user) {
|
||||
async isAnonEventAllowed(req, res, next) {
|
||||
if (!res.locals.settings.allow_anon_event && !req.user) {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
next()
|
||||
@@ -432,7 +432,7 @@ const eventController = {
|
||||
end_datetime: body.end_datetime,
|
||||
recurrent,
|
||||
// publish this event only if authenticated
|
||||
is_visible: !!res.locals.user
|
||||
is_visible: !!req.user
|
||||
}
|
||||
|
||||
if (req.file || body.image_url) {
|
||||
@@ -466,9 +466,9 @@ const eventController = {
|
||||
}
|
||||
|
||||
// associate user to event and reverse
|
||||
if (res.locals.user) {
|
||||
await res.locals.user.addEvent(event)
|
||||
await event.setUser(res.locals.user)
|
||||
if (req.user) {
|
||||
await req.user.addEvent(event)
|
||||
await event.setUser(req.user)
|
||||
}
|
||||
|
||||
event = event.get()
|
||||
@@ -502,7 +502,7 @@ const eventController = {
|
||||
const body = req.body
|
||||
const event = await Event.findByPk(body.id)
|
||||
if (!event) { return res.sendStatus(404) }
|
||||
if (!res.locals.user.is_admin && event.userId !== res.locals.user.id) {
|
||||
if (!req.user.is_admin && event.userId !== req.user.id) {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
@@ -596,7 +596,7 @@ const eventController = {
|
||||
async remove(req, res) {
|
||||
const event = await Event.findByPk(req.params.id)
|
||||
// check if event is mine (or user is admin)
|
||||
if (event && (res.locals.user.is_admin || res.locals.user.id === event.userId)) {
|
||||
if (event && (req.user.is_admin || req.user.id === event.userId)) {
|
||||
if (event.media && event.media.length && !event.recurrent) {
|
||||
try {
|
||||
const old_path = path.join(config.upload_path, event.media[0].url)
|
||||
|
||||
@@ -1,26 +1,357 @@
|
||||
const crypto = require('crypto')
|
||||
const { promisify } = require('util')
|
||||
const randomBytes = promisify(crypto.randomBytes)
|
||||
const bodyParser = require('body-parser')
|
||||
const cookieParser = require('cookie-parser')
|
||||
const session = require('express-session')
|
||||
|
||||
const OAuthClient = require('../models/oauth_client')
|
||||
const OAuthToken = require('../models/oauth_token')
|
||||
const OAuthCode = require('../models/oauth_code')
|
||||
|
||||
const helpers = require('../../helpers.js')
|
||||
const User = require('../models/user')
|
||||
const passport = require('passport')
|
||||
|
||||
const get = require('lodash/get')
|
||||
|
||||
const BasicStrategy = require('passport-http').BasicStrategy
|
||||
const ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy
|
||||
const ClientPublicStrategy = require('passport-oauth2-client-public').Strategy
|
||||
const BearerStrategy = require('passport-http-bearer').Strategy
|
||||
const AnonymousStrategy = require('passport-anonymous').Strategy
|
||||
|
||||
const oauth2orize = require('oauth2orize')
|
||||
const log = require('../../log')
|
||||
const dayjs = require('dayjs')
|
||||
|
||||
async function randomString (len = 16) {
|
||||
const bytes = await randomBytes(len * 8)
|
||||
return crypto
|
||||
.createHash('sha1')
|
||||
.update(bytes)
|
||||
.digest('hex')
|
||||
passport.serializeUser((user, done) => done(null, user.id))
|
||||
|
||||
passport.deserializeUser(async (id, done) => {
|
||||
const user = await User.findByPk(id)
|
||||
done(null, user)
|
||||
})
|
||||
|
||||
/**
|
||||
* BasicStrategy & ClientPasswordStrategy
|
||||
*
|
||||
* These strategies are used to authenticate registered OAuth clients. They are
|
||||
* employed to protect the `token` endpoint, which consumers use to obtain
|
||||
* access tokens. The OAuth 2.0 specification suggests that clients use the
|
||||
* HTTP Basic scheme to authenticate. Use of the client password strategy
|
||||
* allows clients to send the same credentials in the request body (as opposed
|
||||
* to the `Authorization` header). While this approach is not recommended by
|
||||
* the specification, in practice it is quite common.
|
||||
*/
|
||||
async function verifyClient(client_id, client_secret, done) {
|
||||
const client = await OAuthClient.findByPk(client_id, { raw: true })
|
||||
if (!client) {
|
||||
return done(null, false)
|
||||
}
|
||||
if (client.client_secret && client_secret !== client.client_secret) {
|
||||
return done(null, false)
|
||||
}
|
||||
|
||||
if (client) { client.grants = ['authorization_code', 'password'] } //sure ?
|
||||
|
||||
return done(null, client)
|
||||
}
|
||||
|
||||
const oauthController = {
|
||||
async function verifyPublicClient (client_id, done) {
|
||||
if (client_id !== 'self') {
|
||||
return done(null, false)
|
||||
}
|
||||
try {
|
||||
|
||||
// create client => http:///gancio.org/oauth#create-client
|
||||
const client = await OAuthClient.findByPk(client_id, { raw: true })
|
||||
done(null, client)
|
||||
} catch (e) {
|
||||
done(null, { message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
passport.use(new AnonymousStrategy())
|
||||
passport.use(new BasicStrategy(verifyClient))
|
||||
passport.use(new ClientPasswordStrategy(verifyClient))
|
||||
passport.use(new ClientPublicStrategy(verifyPublicClient))
|
||||
|
||||
/**
|
||||
* BearerStrategy
|
||||
*
|
||||
* This strategy is used to authenticate either users or clients based on an access token
|
||||
* (aka a bearer token). If a user, they must have previously authorized a client
|
||||
* application, which is issued an access token to make requests on behalf of
|
||||
* the authorizing user.
|
||||
*/
|
||||
passport.use(new BearerStrategy({ passReqToCallback: true }, verifyToken))
|
||||
|
||||
async function verifyToken (req, accessToken, done) {
|
||||
const token = await OAuthToken.findByPk(accessToken,
|
||||
{ include: [{ model: User, attributes: { exclude: ['password'] } }, { model: OAuthClient, as: 'client' }] })
|
||||
|
||||
if (!token) return done(null, false)
|
||||
if (token.userId) {
|
||||
if (!token.user) {
|
||||
return done(null, false)
|
||||
}
|
||||
// To keep this example simple, restricted scopes are not implemented,
|
||||
// and this is just for illustrative purposes.
|
||||
done(null, token.user, { scope: '*' })
|
||||
} else {
|
||||
|
||||
// The request came from a client only since userId is null,
|
||||
// therefore the client is passed back instead of a user.
|
||||
if (!token.client) {
|
||||
return done(null, false)
|
||||
}
|
||||
// To keep this example simple, restricted scopes are not implemented,
|
||||
// and this is just for illustrative purposes.
|
||||
done(null, client, { scope: '*' })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const oauthServer = oauth2orize.createServer()
|
||||
|
||||
|
||||
// Register serialization and deserialization functions.
|
||||
//
|
||||
// When a client redirects a user to user authorization endpoint, an
|
||||
// authorization transaction is initiated. To complete the transaction, the
|
||||
// user must authenticate and approve the authorization request. Because this
|
||||
// may involve multiple HTTP request/response exchanges, the transaction is
|
||||
// stored in the session.
|
||||
//
|
||||
// An application must supply serialization functions, which determine how the
|
||||
// client object is serialized into the session. Typically this will be a
|
||||
// simple matter of serializing the client's ID, and deserializing by finding
|
||||
// the client by ID from the database.
|
||||
oauthServer.serializeClient((client, done) => {
|
||||
done(null, client.id)
|
||||
})
|
||||
|
||||
oauthServer.deserializeClient(async (id, done) => {
|
||||
const client = await OAuthClient.findByPk(id)
|
||||
done(null, client)
|
||||
})
|
||||
|
||||
// Register supported grant types.
|
||||
//
|
||||
// OAuth 2.0 specifies a framework that allows users to grant client
|
||||
// applications limited access to their protected resources. It does this
|
||||
// through a process of the user granting access, and the client exchanging
|
||||
// the grant for an access token.
|
||||
|
||||
// Grant authorization codes. The callback takes the `client` requesting
|
||||
// authorization, the `redirectUri` (which is used as a verifier in the
|
||||
// subsequent exchange), the authenticated `user` granting access, and
|
||||
// their response, which contains approved scope, duration, etc. as parsed by
|
||||
// the application. The application issues a code, which is bound to these
|
||||
// values, and will be exchanged for an access token.
|
||||
|
||||
oauthServer.grant(oauth2orize.grant.code(async (client, redirect_uri, user, ares, done) => {
|
||||
const authorizationCode = helpers.randomString(16);
|
||||
await OAuthCode.create({
|
||||
redirect_uri,
|
||||
authorizationCode,
|
||||
clientId: client.id,
|
||||
userId: user.id,
|
||||
})
|
||||
return done(null, authorizationCode)
|
||||
}))
|
||||
|
||||
|
||||
// Grant implicit authorization. The callback takes the `client` requesting
|
||||
// authorization, the authenticated `user` granting access, and
|
||||
// their response, which contains approved scope, duration, etc. as parsed by
|
||||
// the application. The application issues a token, which is bound to these
|
||||
// values.
|
||||
|
||||
oauthServer.grant(oauth2orize.grant.token((client, user, ares, done) => {
|
||||
return oauthController.issueTokens(user.id, client.clientId, done)
|
||||
}))
|
||||
|
||||
|
||||
// Exchange authorization codes for access tokens. The callback accepts the
|
||||
// `client`, which is exchanging `code` and any `redirectUri` from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the user who authorized the
|
||||
// code. The issued access token response can include a refresh token and
|
||||
// custom parameters by adding these to the `done()` call
|
||||
|
||||
oauthServer.exchange(oauth2orize.exchange.code(async (client, code, redirect_uri, done) => {
|
||||
const oauthCode = await OAuthCode.findByPk(code)
|
||||
if (!oauthCode || client.id !== oauthCode.clientId || client.redirectUris !== oauthCode.redirect_uri) {
|
||||
return done(null, false)
|
||||
}
|
||||
return oauthController.issueTokens(oauthCode.userId, oauthCode.clientId, done)
|
||||
}))
|
||||
|
||||
|
||||
|
||||
// Exchange user id and password for access tokens. The callback accepts the
|
||||
// `client`, which is exchanging the user's name and password from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the user who authorized the code.
|
||||
oauthServer.exchange(oauth2orize.exchange.password(async (client, username, password, scope, done) => {
|
||||
// Validate the client
|
||||
const oauthClient = await OAuthClient.findByPk(client.id)
|
||||
if (!oauthClient) { // || oauthClient.client_secret !== client.clientSecret) {
|
||||
return done(null, false)
|
||||
}
|
||||
const user = await User.findOne({ where: { email: username, is_active: true } })
|
||||
if (!user) {
|
||||
return done(null, false)
|
||||
}
|
||||
// check if password matches
|
||||
if (await user.comparePassword(password)) {
|
||||
return oauthController.issueTokens(user.id, oauthClient.id, done)
|
||||
}
|
||||
return done(null, false)
|
||||
}))
|
||||
|
||||
|
||||
// Exchange the client id and password/secret for an access token. The callback accepts the
|
||||
// `client`, which is exchanging the client's id and password/secret from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the client who authorized the code.
|
||||
oauthServer.exchange(oauth2orize.exchange.clientCredentials(async (client, scope, done) => {
|
||||
// Validate the client
|
||||
const oauthClient = await OAuthClient.findByPk(client.clientId)
|
||||
if (!oauthClient || oauthClient.client_secret !== client.clientSecret) {
|
||||
return done(null, false)
|
||||
}
|
||||
|
||||
return oauthController.issueTokens(null, oauthClient.id, done)
|
||||
}))
|
||||
|
||||
// issue new tokens and remove the old ones
|
||||
oauthServer.exchange(oauth2orize.exchange.refreshToken(async (client, refreshToken, scope, done) => {
|
||||
// db.refreshTokens.find(refreshToken, (error, token) => {
|
||||
// if (error) return done(error)
|
||||
// issueTokens(token.id, client.id, (err, accessToken, refreshToken) => {
|
||||
// if (err) {
|
||||
// done(err, null, null)
|
||||
// }
|
||||
// db.accessTokens.removeByUserIdAndClientId(token.userId, token.clientId, (err) => {
|
||||
// if (err) {
|
||||
// done(err, null, null)
|
||||
// }
|
||||
// db.refreshTokens.removeByUserIdAndClientId(token.userId, token.clientId, (err) => {
|
||||
// if (err) {
|
||||
// done(err, null, null)
|
||||
// }
|
||||
// done(null, accessToken, refreshToken)
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
}))
|
||||
|
||||
|
||||
const oauthController = {
|
||||
|
||||
// this is a middleware to authenticate a request
|
||||
authenticate: [
|
||||
passport.initialize(), // initialize passport
|
||||
cookieParser(), // parse cookies
|
||||
session({ secret: 'secret', resave: true, saveUninitialized: true }),
|
||||
passport.session(),
|
||||
(req, res, next) => { // retrocompatibility
|
||||
const token = get(req.cookies, 'auth._token.local', null)
|
||||
const authorization = get(req.headers, 'authorization', null)
|
||||
if (!authorization && token) {
|
||||
req.headers.authorization = token
|
||||
}
|
||||
next()
|
||||
},
|
||||
passport.authenticate(['bearer', 'oauth2-client-password', 'anonymous'], { session: false })
|
||||
],
|
||||
|
||||
login: [
|
||||
bodyParser.urlencoded({ extended: true }), // login is done via application/x-www-form-urlencoded form
|
||||
passport.authenticate(['oauth2-client-public'], { session: false }),
|
||||
oauthServer.token(),
|
||||
oauthServer.errorHandler()
|
||||
],
|
||||
|
||||
token: [
|
||||
bodyParser.urlencoded({ extended: true }), // login is done via application/x-www-form-urlencoded form
|
||||
passport.authenticate(['bearer', 'oauth2-client-password'], { session: false }),
|
||||
oauthServer.token(),
|
||||
oauthServer.errorHandler()
|
||||
],
|
||||
|
||||
authorization: [
|
||||
oauthServer.authorization(async (clientId, redirectUri, done) => {
|
||||
const oauthClient = await OAuthClient.findByPk(clientId)
|
||||
if (!oauthClient) {
|
||||
return done(null, false)
|
||||
}
|
||||
|
||||
// WARNING: For security purposes, it is highly advisable to check that
|
||||
// redirectUri provided by the client matches one registered with
|
||||
// the server. For simplicity, this example does not. You have
|
||||
// been warned.
|
||||
return done(null, oauthClient, redirectUri);
|
||||
}, async (client, user, done) => {
|
||||
// Check if grant request qualifies for immediate approval
|
||||
|
||||
// Auto-approve
|
||||
if (client.isTrusted) return done(null, true);
|
||||
if (!user) {
|
||||
return done(null, false)
|
||||
}
|
||||
const token = await OAuthToken.findOne({ where: { clientId: client.id, userId: user.id }})
|
||||
// Auto-approve
|
||||
if (token) {
|
||||
return done(null, true)
|
||||
}
|
||||
// Otherwise ask user
|
||||
return done(null, false)
|
||||
|
||||
}),
|
||||
(req, res, next) => {
|
||||
//clean old transactionID
|
||||
if(req.session.authorize){
|
||||
for(const key in req.session.authorize){
|
||||
if(key !== req.oauth2.transactionID){
|
||||
delete req.session.authorize[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
const query = new URLSearchParams({
|
||||
transactionID: req.oauth2.transactionID,
|
||||
client: req.oauth2.client.name,
|
||||
scope: req.oauth2.client.scopes,
|
||||
redirect_uri: req.oauth2.client.redirectUris
|
||||
})
|
||||
return res.redirect(`/authorize?${query.toString()}`)
|
||||
}
|
||||
],
|
||||
|
||||
decision: [
|
||||
bodyParser.urlencoded({ extended: true }),
|
||||
oauthServer.decision()
|
||||
],
|
||||
|
||||
async issueTokens(userId, clientId, done) {
|
||||
const user = await User.findByPk(userId)
|
||||
if (!user) {
|
||||
return done(null, false)
|
||||
}
|
||||
|
||||
const refreshToken = helpers.randomString(32)
|
||||
const accessToken = helpers.randomString(32)
|
||||
|
||||
const token = {
|
||||
refreshToken,
|
||||
accessToken,
|
||||
userId,
|
||||
clientId
|
||||
}
|
||||
|
||||
await OAuthToken.create(token)
|
||||
return done(null, accessToken, refreshToken, { username: user.email })
|
||||
},
|
||||
|
||||
// create client => http:///gancio.org/dev/oauth#create-client
|
||||
async createClient (req, res) {
|
||||
// only write scope is supported
|
||||
if (req.body.scopes && req.body.scopes !== 'event:write') {
|
||||
@@ -28,12 +359,12 @@ const oauthController = {
|
||||
}
|
||||
|
||||
const client = {
|
||||
id: await randomString(256),
|
||||
id: helpers.randomString(32),
|
||||
name: req.body.client_name,
|
||||
redirectUris: req.body.redirect_uris,
|
||||
scopes: req.body.scopes || 'event:write',
|
||||
website: req.body.website,
|
||||
client_secret: await randomString(256)
|
||||
client_secret: helpers.randomString(32)
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -63,99 +394,11 @@ const oauthController = {
|
||||
|
||||
async getClients (req, res) {
|
||||
const tokens = await OAuthToken.findAll({
|
||||
include: [{ model: User, where: { id: res.locals.user.id } }, { model: OAuthClient, as: 'client' }],
|
||||
include: [{ model: User, where: { id: req.user.id } }, { model: OAuthClient, as: 'client' }],
|
||||
raw: true,
|
||||
nest: true
|
||||
})
|
||||
res.json(tokens)
|
||||
},
|
||||
|
||||
model: {
|
||||
|
||||
/**
|
||||
* Invoked to retrieve an existing access token previously saved through #saveToken().
|
||||
* https://oauth2-server.readthedocs.io/en/latest/model/spec.html#getaccesstoken-accesstoken-callback
|
||||
* */
|
||||
async getAccessToken (accessToken) {
|
||||
const oauth_token = await OAuthToken.findByPk(accessToken,
|
||||
{ include: [{ model: User, attributes: { exclude: ['password'] } }, { model: OAuthClient, as: 'client' }] })
|
||||
return oauth_token
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked to retrieve a client using a client id or a client id/client secret combination, depend on the grant type.
|
||||
*/
|
||||
async getClient (client_id, client_secret) {
|
||||
const client = await OAuthClient.findByPk(client_id, { raw: true })
|
||||
if (!client || (client_secret && client_secret !== client.client_secret)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (client) { client.grants = ['authorization_code', 'password'] }
|
||||
|
||||
return client
|
||||
},
|
||||
|
||||
async getRefreshToken (refresh_token) {
|
||||
const oauth_token = await OAuthToken.findOne({ where: { refresh_token }, raw: true })
|
||||
return oauth_token
|
||||
},
|
||||
|
||||
async getAuthorizationCode (code) {
|
||||
const oauth_code = await OAuthCode.findByPk(code,
|
||||
{ include: [User, { model: OAuthClient, as: 'client' }] })
|
||||
return oauth_code
|
||||
},
|
||||
|
||||
async saveToken (token, client, user) {
|
||||
token.userId = user.id
|
||||
token.clientId = client.id
|
||||
const oauth_token = await OAuthToken.create(token)
|
||||
oauth_token.client = client
|
||||
oauth_token.user = user
|
||||
return oauth_token
|
||||
},
|
||||
|
||||
async revokeAuthorizationCode (code) {
|
||||
const oauth_code = await OAuthCode.findByPk(code.authorizationCode)
|
||||
return oauth_code.destroy()
|
||||
},
|
||||
|
||||
async getUser (username, password) {
|
||||
const user = await User.findOne({ where: { email: username } })
|
||||
if (!user || !user.is_active) {
|
||||
return false
|
||||
}
|
||||
// check if password matches
|
||||
if (await user.comparePassword(password)) {
|
||||
return user
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
async saveAuthorizationCode (code, client, user) {
|
||||
code.userId = user.id
|
||||
code.clientId = client.id
|
||||
code.expiresAt = dayjs(code.expiresAt).toDate()
|
||||
return OAuthCode.create(code)
|
||||
},
|
||||
|
||||
// TODO
|
||||
verifyScope (token, scope) {
|
||||
// const userScope = [
|
||||
// 'user:remove',
|
||||
// 'user:update',
|
||||
// 'event:write',
|
||||
// 'event:remove'
|
||||
// ]
|
||||
log.debug(`VERIFY SCOPE ${scope} ${token.user.email}`)
|
||||
if (token.user.is_admin && token.user.is_active) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,13 +44,13 @@ const userController = {
|
||||
},
|
||||
|
||||
async current (req, res) {
|
||||
if (!res.locals.user) { return res.status(400).send('Not logged') }
|
||||
const user = await User.scope('withoutPassword').findByPk(res.locals.user.id)
|
||||
if (!req.user) { return res.status(400).send('Not logged') }
|
||||
const user = await User.scope('withoutPassword').findByPk(req.user.id)
|
||||
res.json(user)
|
||||
},
|
||||
|
||||
async getAll (req, res) {
|
||||
const users = await User.scope(res.locals.user.is_admin ? 'withRecover' : 'withoutPassword').findAll({
|
||||
const users = await User.scope(req.user.is_admin ? 'withRecover' : 'withoutPassword').findAll({
|
||||
order: [['is_admin', 'DESC'], ['createdAt', 'DESC']]
|
||||
})
|
||||
res.json(users)
|
||||
@@ -62,7 +62,7 @@ const userController = {
|
||||
|
||||
if (!user) { return res.status(404).json({ success: false, message: 'User not found!' }) }
|
||||
|
||||
if (req.body.id !== res.locals.user.id && !res.locals.user.is_admin) {
|
||||
if (req.body.id !== req.user.id && !req.user.is_admin) {
|
||||
return res.status(400).json({ succes: false, message: 'Not allowed' })
|
||||
}
|
||||
|
||||
@@ -123,10 +123,10 @@ const userController = {
|
||||
async remove (req, res) {
|
||||
try {
|
||||
let user
|
||||
if (res.locals.user.is_admin && req.params.id) {
|
||||
if (req.user.is_admin && req.params.id) {
|
||||
user = await User.findByPk(req.params.id)
|
||||
} else {
|
||||
user = await User.findByPk(res.locals.user.id)
|
||||
user = await User.findByPk(req.user.id)
|
||||
}
|
||||
await user.destroy()
|
||||
log.warn(`User ${user.email} removed!`)
|
||||
|
||||
Reference in New Issue
Block a user