1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-18 12:49:43 +02:00

feat: Add INTERNAL_ACCESS_TOKEN to support internal user configuration

This commit is contained in:
Maksim Eltyshev 2025-07-07 21:35:37 +02:00
parent b61b4e658f
commit 4346b7040a
8 changed files with 55 additions and 20 deletions

View file

@ -38,6 +38,7 @@ services:
# - DEFAULT_ADMIN_NAME=Demo Demo # - DEFAULT_ADMIN_NAME=Demo Demo
# - DEFAULT_ADMIN_USERNAME=demo # - DEFAULT_ADMIN_USERNAME=demo
# - INTERNAL_ACCESS_TOKEN=
# - ACTIVE_USERS_LIMIT= # - ACTIVE_USERS_LIMIT=
# Set to true to show more detailed authentication error messages. # Set to true to show more detailed authentication error messages.

View file

@ -52,6 +52,7 @@ services:
# - DEFAULT_ADMIN_NAME=Demo Demo # - DEFAULT_ADMIN_NAME=Demo Demo
# - DEFAULT_ADMIN_USERNAME=demo # - DEFAULT_ADMIN_USERNAME=demo
# - INTERNAL_ACCESS_TOKEN=
# - ACTIVE_USERS_LIMIT= # - ACTIVE_USERS_LIMIT=
# Set to true to show more detailed authentication error messages. # Set to true to show more detailed authentication error messages.

View file

@ -29,6 +29,7 @@ SECRET_KEY=notsecretkey
# DEFAULT_ADMIN_NAME=Demo Demo # DEFAULT_ADMIN_NAME=Demo Demo
# DEFAULT_ADMIN_USERNAME=demo # DEFAULT_ADMIN_USERNAME=demo
# INTERNAL_ACCESS_TOKEN=
# ACTIVE_USERS_LIMIT= # ACTIVE_USERS_LIMIT=
# Set to true to show more detailed authentication error messages. # Set to true to show more detailed authentication error messages.

View file

@ -67,25 +67,30 @@ module.exports = function defineCurrentUserHook(sails) {
if (authorizationHeader && TOKEN_PATTERN.test(authorizationHeader)) { if (authorizationHeader && TOKEN_PATTERN.test(authorizationHeader)) {
const accessToken = authorizationHeader.replace(TOKEN_PATTERN, ''); const accessToken = authorizationHeader.replace(TOKEN_PATTERN, '');
const { httpOnlyToken } = req.cookies; const { internalAccessToken } = sails.config.custom;
const sessionAndUser = await getSessionAndUser(accessToken, httpOnlyToken); if (internalAccessToken && accessToken === internalAccessToken) {
req.currentUser = User.INTERNAL;
} else {
const { httpOnlyToken } = req.cookies;
const sessionAndUser = await getSessionAndUser(accessToken, httpOnlyToken);
if (sessionAndUser) { if (sessionAndUser) {
const { session, user } = sessionAndUser; const { session, user } = sessionAndUser;
if (user.language) { if (user.language) {
req.setLocale(user.language); req.setLocale(user.language);
} }
Object.assign(req, { Object.assign(req, {
currentSession: session, currentSession: session,
currentUser: user, currentUser: user,
}); });
if (req.isSocket) { if (req.isSocket) {
sails.sockets.join(req, `@accessToken:${session.accessToken}`); sails.sockets.join(req, `@accessToken:${session.accessToken}`);
sails.sockets.join(req, `@user:${user.id}`); sails.sockets.join(req, `@user:${user.id}`);
}
} }
} }
} }

View file

@ -81,8 +81,14 @@ const PERSONAL_FIELD_NAMES = [
'defaultProjectsOrder', 'defaultProjectsOrder',
]; ];
const INTERNAL = {
id: '_internal',
role: Roles.ADMIN,
};
const OIDC = { const OIDC = {
id: '_oidc', id: '_oidc',
role: Roles.ADMIN,
}; };
module.exports = { module.exports = {
@ -93,6 +99,7 @@ module.exports = {
LANGUAGES, LANGUAGES,
PRIVATE_FIELD_NAMES, PRIVATE_FIELD_NAMES,
PERSONAL_FIELD_NAMES, PERSONAL_FIELD_NAMES,
INTERNAL,
OIDC, OIDC,
attributes: { attributes: {

View file

@ -0,0 +1,12 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
module.exports = async function isExternal(req, res, proceed) {
if (req.currentUser.id === User.INTERNAL.id) {
return res.notFound(); // Forbidden
}
return proceed();
};

View file

@ -50,6 +50,7 @@ module.exports.custom = {
defaultAdminEmail: defaultAdminEmail:
process.env.DEFAULT_ADMIN_EMAIL && process.env.DEFAULT_ADMIN_EMAIL.toLowerCase(), process.env.DEFAULT_ADMIN_EMAIL && process.env.DEFAULT_ADMIN_EMAIL.toLowerCase(),
internalAccessToken: process.env.INTERNAL_ACCESS_TOKEN,
activeUsersLimit: envToNumber(process.env.ACTIVE_USERS_LIMIT), activeUsersLimit: envToNumber(process.env.ACTIVE_USERS_LIMIT),
showDetailedAuthErrors: process.env.SHOW_DETAILED_AUTH_ERRORS === 'true', showDetailedAuthErrors: process.env.SHOW_DETAILED_AUTH_ERRORS === 'true',

View file

@ -16,17 +16,24 @@ module.exports.policies = {
* *
*/ */
'*': 'is-authenticated', '*': ['is-authenticated', 'is-external'],
'webhooks/index': ['is-admin'], 'webhooks/index': ['is-authenticated', 'is-external', 'is-admin'],
'webhooks/create': ['is-admin'], 'webhooks/create': ['is-authenticated', 'is-external', 'is-admin'],
'webhooks/update': ['is-admin'], 'webhooks/update': ['is-authenticated', 'is-external', 'is-admin'],
'webhooks/delete': ['is-admin'], 'webhooks/delete': ['is-authenticated', 'is-external', 'is-admin'],
'users/index': 'is-authenticated',
'users/create': ['is-authenticated', 'is-admin'], 'users/create': ['is-authenticated', 'is-admin'],
'users/show': 'is-authenticated',
'users/update': 'is-authenticated',
'users/update-email': 'is-authenticated',
'users/update-password': 'is-authenticated',
'users/update-username': 'is-authenticated',
'users/update-avatar': 'is-authenticated',
'users/delete': ['is-authenticated', 'is-admin'], 'users/delete': ['is-authenticated', 'is-admin'],
'projects/create': ['is-authenticated', 'is-admin-or-project-owner'], 'projects/create': ['is-authenticated', 'is-external', 'is-admin-or-project-owner'],
'config/show': true, 'config/show': true,
'access-tokens/create': true, 'access-tokens/create': true,