mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 12:49:43 +02:00
parent
7273b33768
commit
4fe77c305c
15 changed files with 130 additions and 42 deletions
|
@ -47,9 +47,11 @@ initializeCore.fetchConfig = (config) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const logout = () => ({
|
||||
const logout = (invalidateAccessToken) => ({
|
||||
type: ActionTypes.LOGOUT,
|
||||
payload: {},
|
||||
payload: {
|
||||
invalidateAccessToken,
|
||||
},
|
||||
});
|
||||
|
||||
logout.invalidateAccessToken = () => ({
|
||||
|
|
|
@ -38,7 +38,7 @@ const handleCardUpdate = (card) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const moveCard = (id, listId, index = 0) => ({
|
||||
const moveCard = (id, listId, index) => ({
|
||||
type: EntryActionTypes.CARD_MOVE,
|
||||
payload: {
|
||||
id,
|
||||
|
@ -47,7 +47,7 @@ const moveCard = (id, listId, index = 0) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const moveCurrentCard = (listId, index = 0) => ({
|
||||
const moveCurrentCard = (listId, index) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_MOVE,
|
||||
payload: {
|
||||
listId,
|
||||
|
@ -55,7 +55,7 @@ const moveCurrentCard = (listId, index = 0) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const transferCard = (id, boardId, listId, index = 0) => ({
|
||||
const transferCard = (id, boardId, listId, index) => ({
|
||||
type: EntryActionTypes.CARD_TRANSFER,
|
||||
payload: {
|
||||
id,
|
||||
|
@ -65,7 +65,7 @@ const transferCard = (id, boardId, listId, index = 0) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const transferCurrentCard = (boardId, listId, index = 0) => ({
|
||||
const transferCurrentCard = (boardId, listId, index) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_TRANSFER,
|
||||
payload: {
|
||||
boardId,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import EntryActionTypes from '../constants/EntryActionTypes';
|
||||
|
||||
const logout = () => ({
|
||||
const logout = (invalidateAccessToken) => ({
|
||||
type: EntryActionTypes.LOGOUT,
|
||||
payload: {},
|
||||
payload: {
|
||||
invalidateAccessToken,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { call, fork, join, put, select, take } from 'redux-saga/effects';
|
||||
|
||||
import selectors from '../../selectors';
|
||||
import actions from '../../actions';
|
||||
import { removeAccessToken } from '../../utils/access-token-storage';
|
||||
import entryActions from '../../entry-actions';
|
||||
import ErrorCodes from '../../constants/ErrorCodes';
|
||||
|
||||
let lastRequestTask;
|
||||
|
@ -22,8 +21,7 @@ function* queueRequest(method, ...args) {
|
|||
});
|
||||
} catch (error) {
|
||||
if (error.code === ErrorCodes.UNAUTHORIZED) {
|
||||
yield call(removeAccessToken);
|
||||
yield put(actions.logout()); // TODO: next url
|
||||
yield put(entryActions.logout(false));
|
||||
yield take();
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export function* handleCardUpdate(card) {
|
|||
yield put(actions.handleCardUpdate(card));
|
||||
}
|
||||
|
||||
export function* moveCard(id, listId, index) {
|
||||
export function* moveCard(id, listId, index = 0) {
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
yield call(updateCard, id, {
|
||||
|
@ -101,7 +101,7 @@ export function* moveCurrentCard(listId, index) {
|
|||
yield call(moveCard, cardId, listId, index);
|
||||
}
|
||||
|
||||
export function* transferCard(id, boardId, listId, index) {
|
||||
export function* transferCard(id, boardId, listId, index = 0) {
|
||||
const { cardId: currentCardId, boardId: currentBoardId } = yield select(selectors.selectPath);
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { call, put, select, take } from 'redux-saga/effects';
|
||||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import request from '../request';
|
||||
import requests from '../requests';
|
||||
|
@ -84,8 +84,7 @@ export function* logout(invalidateAccessToken = true) {
|
|||
} catch (error) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
yield put(actions.logout());
|
||||
yield take();
|
||||
yield put(actions.logout()); // TODO: next url
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import { call, put, select, take } from 'redux-saga/effects';
|
||||
import { push } from '../../../lib/redux-router';
|
||||
|
||||
import { logout } from './core';
|
||||
import request from '../request';
|
||||
import selectors from '../../../selectors';
|
||||
import actions from '../../../actions';
|
||||
import api from '../../../api';
|
||||
import { getAccessToken } from '../../../utils/access-token-storage';
|
||||
import ActionTypes from '../../../constants/ActionTypes';
|
||||
import Paths from '../../../constants/Paths';
|
||||
|
||||
|
@ -25,6 +27,13 @@ export function* goToCard(cardId) {
|
|||
}
|
||||
|
||||
export function* handleLocationChange() {
|
||||
const accessToken = yield call(getAccessToken);
|
||||
|
||||
if (!accessToken) {
|
||||
yield call(logout, false);
|
||||
return;
|
||||
}
|
||||
|
||||
const pathsMatch = yield select(selectors.selectPathsMatch);
|
||||
|
||||
if (!pathsMatch) {
|
||||
|
|
|
@ -218,6 +218,7 @@ export function* handleUserDelete(user) {
|
|||
|
||||
if (user.id === currentUserId) {
|
||||
yield call(logout, false);
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.handleUserDelete(user));
|
||||
|
|
|
@ -4,5 +4,9 @@ import services from '../services';
|
|||
import EntryActionTypes from '../../../constants/EntryActionTypes';
|
||||
|
||||
export default function* coreWatchers() {
|
||||
yield all([takeEvery(EntryActionTypes.LOGOUT, () => services.logout())]);
|
||||
yield all([
|
||||
takeEvery(EntryActionTypes.LOGOUT, ({ payload: { invalidateAccessToken } }) =>
|
||||
services.logout(invalidateAccessToken),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ const createSocketEventsChannel = () =>
|
|||
emit(entryActions.handleSocketReconnect());
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
emit(entryActions.logout(false));
|
||||
};
|
||||
|
||||
const handleUserCreate = api.makeHandleUserCreate(({ item }) => {
|
||||
emit(entryActions.handleUserCreate(item));
|
||||
});
|
||||
|
@ -171,6 +175,8 @@ const createSocketEventsChannel = () =>
|
|||
socket.on('disconnect', handleDisconnect);
|
||||
socket.on('reconnect', handleReconnect);
|
||||
|
||||
socket.on('logout', handleLogout);
|
||||
|
||||
socket.on('userCreate', handleUserCreate);
|
||||
socket.on('userUpdate', handleUserUpdate);
|
||||
socket.on('userDelete', handleUserDelete);
|
||||
|
@ -227,6 +233,8 @@ const createSocketEventsChannel = () =>
|
|||
socket.off('disconnect', handleDisconnect);
|
||||
socket.off('reconnect', handleReconnect);
|
||||
|
||||
socket.off('logout', handleLogout);
|
||||
|
||||
socket.off('userCreate', handleUserCreate);
|
||||
socket.off('userUpdate', handleUserUpdate);
|
||||
socket.off('userDelete', handleUserDelete);
|
||||
|
|
|
@ -9,6 +9,10 @@ module.exports = {
|
|||
deletedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
if (this.req.isSocket) {
|
||||
sails.sockets.leaveAll(`@accessToken:${accessToken}`);
|
||||
}
|
||||
|
||||
return {
|
||||
item: accessToken,
|
||||
};
|
||||
|
|
|
@ -61,6 +61,7 @@ module.exports = function defineCurrentUserHook(sails) {
|
|||
});
|
||||
|
||||
if (req.isSocket) {
|
||||
sails.sockets.join(req, `@accessToken:${accessToken}`);
|
||||
sails.sockets.join(req, `@user:${currentUser.id}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
const openidClient = require('openid-client');
|
||||
|
||||
module.exports = function oidcServiceHook(sails) {
|
||||
/**
|
||||
* oidc hook
|
||||
*
|
||||
* @description :: A hook definition. Extends Sails by adding shadow routes, implicit actions,
|
||||
* and/or initialization logic.
|
||||
* @docs :: https://sailsjs.com/docs/concepts/extending-sails/hooks
|
||||
*/
|
||||
|
||||
module.exports = function defineOidcHook(sails) {
|
||||
let client = null;
|
||||
|
||||
return {
|
||||
|
@ -9,17 +17,20 @@ module.exports = function oidcServiceHook(sails) {
|
|||
*/
|
||||
|
||||
async initialize() {
|
||||
if (sails.config.custom.oidcIssuer) {
|
||||
const issuer = await openidClient.Issuer.discover(sails.config.custom.oidcIssuer);
|
||||
|
||||
client = new issuer.Client({
|
||||
client_id: sails.config.custom.oidcClientId,
|
||||
client_secret: sails.config.custom.oidcClientSecret,
|
||||
redirect_uris: [sails.config.custom.oidcRedirectUri],
|
||||
response_types: ['code'],
|
||||
});
|
||||
sails.log.info('OIDC hook has been loaded successfully');
|
||||
if (!sails.config.custom.oidcIssuer) {
|
||||
return;
|
||||
}
|
||||
|
||||
sails.log.info('Initializing custom hook (`oidc`)');
|
||||
|
||||
const issuer = await openidClient.Issuer.discover(sails.config.custom.oidcIssuer);
|
||||
|
||||
client = new issuer.Client({
|
||||
client_id: sails.config.custom.oidcClientId,
|
||||
client_secret: sails.config.custom.oidcClientSecret,
|
||||
redirect_uris: [sails.config.custom.oidcRedirectUri],
|
||||
response_types: ['code'],
|
||||
});
|
||||
},
|
||||
|
||||
getClient() {
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
const nodemailer = require('nodemailer');
|
||||
|
||||
module.exports = function smtpServiceHook(sails) {
|
||||
/**
|
||||
* smtp hook
|
||||
*
|
||||
* @description :: A hook definition. Extends Sails by adding shadow routes, implicit actions,
|
||||
* and/or initialization logic.
|
||||
* @docs :: https://sailsjs.com/docs/concepts/extending-sails/hooks
|
||||
*/
|
||||
|
||||
module.exports = function defineSmtpHook(sails) {
|
||||
let transporter = null;
|
||||
|
||||
return {
|
||||
|
@ -9,19 +17,22 @@ module.exports = function smtpServiceHook(sails) {
|
|||
*/
|
||||
|
||||
async initialize() {
|
||||
if (sails.config.custom.smtpHost) {
|
||||
transporter = nodemailer.createTransport({
|
||||
pool: true,
|
||||
host: sails.config.custom.smtpHost,
|
||||
port: sails.config.custom.smtpPort,
|
||||
secure: sails.config.custom.smtpSecure,
|
||||
auth: sails.config.custom.smtpUser && {
|
||||
user: sails.config.custom.smtpUser,
|
||||
pass: sails.config.custom.smtpPassword,
|
||||
},
|
||||
});
|
||||
sails.log.info('SMTP hook has been loaded successfully');
|
||||
if (!sails.config.custom.smtpHost) {
|
||||
return;
|
||||
}
|
||||
|
||||
sails.log.info('Initializing custom hook (`smtp`)');
|
||||
|
||||
transporter = nodemailer.createTransport({
|
||||
pool: true,
|
||||
host: sails.config.custom.smtpHost,
|
||||
port: sails.config.custom.smtpPort,
|
||||
secure: sails.config.custom.smtpSecure,
|
||||
auth: sails.config.custom.smtpUser && {
|
||||
user: sails.config.custom.smtpUser,
|
||||
pass: sails.config.custom.smtpPassword,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
getTransporter() {
|
||||
|
|
38
server/api/hooks/watcher/index.js
Normal file
38
server/api/hooks/watcher/index.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* watcher hook
|
||||
*
|
||||
* @description :: A hook definition. Extends Sails by adding shadow routes, implicit actions,
|
||||
* and/or initialization logic.
|
||||
* @docs :: https://sailsjs.com/docs/concepts/extending-sails/hooks
|
||||
*/
|
||||
|
||||
module.exports = function defineWatcherHook(sails) {
|
||||
const checkSocketConnectionsToLogout = () => {
|
||||
Object.keys(sails.io.sockets.adapter.rooms).forEach((room) => {
|
||||
if (!room.startsWith('@accessToken:')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const accessToken = room.split(':')[1];
|
||||
|
||||
try {
|
||||
sails.helpers.utils.verifyToken(accessToken);
|
||||
} catch (error) {
|
||||
sails.sockets.broadcast(room, 'logout');
|
||||
sails.sockets.leaveAll(room);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Runs when this Sails app loads/lifts.
|
||||
*/
|
||||
|
||||
async initialize() {
|
||||
sails.log.info('Initializing custom hook (`watcher`)');
|
||||
|
||||
setInterval(checkSocketConnectionsToLogout, 60 * 1000);
|
||||
},
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue