-
+
+
);
}
Static.propTypes = {
- cardId: PropTypes.string,
- boardId: PropTypes.string,
projectId: PropTypes.string,
+ cardId: PropTypes.string,
+ board: PropTypes.object, // eslint-disable-line react/forbid-prop-types
};
Static.defaultProps = {
- cardId: undefined,
- boardId: undefined,
projectId: undefined,
+ cardId: undefined,
+ board: undefined,
};
export default Static;
diff --git a/client/src/components/Static/Static.module.scss b/client/src/components/Static/Static.module.scss
index 19e83520..829ca3a0 100644
--- a/client/src/components/Static/Static.module.scss
+++ b/client/src/components/Static/Static.module.scss
@@ -1,13 +1,4 @@
:global(#app) {
- .board {
- margin-top: 174px;
- }
-
- .flex {
- display: flex;
- height: 100%;
- }
-
.message {
align-content: space-between;
align-items: center;
@@ -34,7 +25,24 @@
text-align: center;
}
- .root {
+ .wrapper {
+ height: 100%;
margin-top: 50px;
}
+
+ .wrapperBoard {
+ margin-top: 174px;
+ }
+
+ .wrapperFlex {
+ display: flex;
+ }
+
+ .wrapperLoader {
+ position: relative;
+ }
+
+ .wrapperProject {
+ margin-top: 98px;
+ }
}
diff --git a/client/src/components/UserEmailEditStep/UserEmailEditStep.jsx b/client/src/components/UserEmailEditStep/UserEmailEditStep.jsx
index 80b0d09d..eb7c35ca 100644
--- a/client/src/components/UserEmailEditStep/UserEmailEditStep.jsx
+++ b/client/src/components/UserEmailEditStep/UserEmailEditStep.jsx
@@ -1,4 +1,3 @@
-import omit from 'lodash/omit';
import isEmail from 'validator/lib/isEmail';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
@@ -78,12 +77,16 @@ const UserEmailEditStep = React.memo(
return;
}
- if (usePasswordConfirmation && !cleanData.currentPassword) {
- currentPasswordField.current.focus();
- return;
+ if (usePasswordConfirmation) {
+ if (!cleanData.currentPassword) {
+ currentPasswordField.current.focus();
+ return;
+ }
+ } else {
+ delete cleanData.currentPassword;
}
- onUpdate(usePasswordConfirmation ? cleanData : omit(cleanData, 'currentPassword'));
+ onUpdate(cleanData);
}, [email, usePasswordConfirmation, onUpdate, onClose, data]);
useEffect(() => {
diff --git a/client/src/components/UserUsernameEditStep/UserUsernameEditStep.jsx b/client/src/components/UserUsernameEditStep/UserUsernameEditStep.jsx
index 35c44583..0d29361d 100644
--- a/client/src/components/UserUsernameEditStep/UserUsernameEditStep.jsx
+++ b/client/src/components/UserUsernameEditStep/UserUsernameEditStep.jsx
@@ -1,4 +1,3 @@
-import omit from 'lodash/omit';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
@@ -78,12 +77,16 @@ const UserUsernameEditStep = React.memo(
return;
}
- if (usePasswordConfirmation && !cleanData.currentPassword) {
- currentPasswordField.current.focus();
- return;
+ if (usePasswordConfirmation) {
+ if (!cleanData.currentPassword) {
+ currentPasswordField.current.focus();
+ return;
+ }
+ } else {
+ delete cleanData.currentPassword;
}
- onUpdate(usePasswordConfirmation ? cleanData : omit(cleanData, 'currentPassword'));
+ onUpdate(cleanData);
}, [username, usePasswordConfirmation, onUpdate, onClose, data]);
useEffect(() => {
diff --git a/client/src/constants/Enums.js b/client/src/constants/Enums.js
index 09d98219..1fb5cdc7 100755
--- a/client/src/constants/Enums.js
+++ b/client/src/constants/Enums.js
@@ -3,10 +3,6 @@ export const ProjectBackgroundTypes = {
IMAGE: 'image',
};
-export const BoardTypes = {
- KANBAN: 'kanban',
-};
-
export const BoardMembershipRoles = {
EDITOR: 'editor',
VIEWER: 'viewer',
diff --git a/client/src/containers/BoardActionsContainer.js b/client/src/containers/BoardActionsContainer.js
index 0608cae6..b88b3491 100644
--- a/client/src/containers/BoardActionsContainer.js
+++ b/client/src/containers/BoardActionsContainer.js
@@ -15,13 +15,16 @@ const mapStateToProps = (state) => {
const filterLabels = selectors.selectFilterLabelsForCurrentBoard(state);
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
+ const isCurrentUserEditor =
+ !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
+
return {
memberships,
labels,
filterUsers,
filterLabels,
allUsers,
- canEdit: !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
+ canEdit: isCurrentUserEditor,
canEditMemberships: isCurrentUserManager,
};
};
diff --git a/client/src/containers/BoardKanbanContainer.js b/client/src/containers/BoardContainer.js
similarity index 80%
rename from client/src/containers/BoardKanbanContainer.js
rename to client/src/containers/BoardContainer.js
index 1201e59a..7c473754 100755
--- a/client/src/containers/BoardKanbanContainer.js
+++ b/client/src/containers/BoardContainer.js
@@ -4,17 +4,20 @@ import { connect } from 'react-redux';
import selectors from '../selectors';
import entryActions from '../entry-actions';
import { BoardMembershipRoles } from '../constants/Enums';
-import BoardKanban from '../components/BoardKanban';
+import Board from '../components/Board';
const mapStateToProps = (state) => {
const { cardId } = selectors.selectPath(state);
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
const listIds = selectors.selectListIdsForCurrentBoard(state);
+ const isCurrentUserEditor =
+ !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
+
return {
listIds,
isCardModalOpened: !!cardId,
- canEdit: !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
+ canEdit: isCurrentUserEditor,
};
};
@@ -28,4 +31,4 @@ const mapDispatchToProps = (dispatch) =>
dispatch,
);
-export default connect(mapStateToProps, mapDispatchToProps)(BoardKanban);
+export default connect(mapStateToProps, mapDispatchToProps)(Board);
diff --git a/client/src/containers/BoardWrapperContainer.js b/client/src/containers/BoardWrapperContainer.js
deleted file mode 100755
index a7fb0609..00000000
--- a/client/src/containers/BoardWrapperContainer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { connect } from 'react-redux';
-
-import selectors from '../selectors';
-import BoardWrapper from '../components/BoardWrapper';
-
-const mapStateToProps = (state) => {
- const { type, isFetching } = selectors.selectCurrentBoard(state);
-
- return {
- type,
- isFetching,
- };
-};
-
-export default connect(mapStateToProps)(BoardWrapper);
diff --git a/client/src/containers/CardContainer.js b/client/src/containers/CardContainer.js
index f44245dc..63ab6917 100755
--- a/client/src/containers/CardContainer.js
+++ b/client/src/containers/CardContainer.js
@@ -30,6 +30,9 @@ const makeMapStateToProps = () => {
const tasks = selectTasksByCardId(state, id);
const notificationsTotal = selectNotificationsTotalByCardId(state, id);
+ const isCurrentUserEditor =
+ !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
+
return {
id,
index,
@@ -48,8 +51,7 @@ const makeMapStateToProps = () => {
allProjectsToLists,
allBoardMemberships,
allLabels,
- canEdit:
- !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
+ canEdit: isCurrentUserEditor,
};
};
};
diff --git a/client/src/containers/CardModalContainer.js b/client/src/containers/CardModalContainer.js
index 49b993d3..5a44dcc9 100755
--- a/client/src/containers/CardModalContainer.js
+++ b/client/src/containers/CardModalContainer.js
@@ -37,6 +37,14 @@ const mapStateToProps = (state) => {
const attachments = selectors.selectAttachmentsForCurrentCard(state);
const activities = selectors.selectActivitiesForCurrentCard(state);
+ let isCurrentUserEditor = false;
+ let isCurrentUserEditorOrCanComment = false;
+
+ if (currentUserMembership) {
+ isCurrentUserEditor = currentUserMembership.role === BoardMembershipRoles.EDITOR;
+ isCurrentUserEditorOrCanComment = isCurrentUserEditor || currentUserMembership.canComment;
+ }
+
return {
name,
description,
@@ -58,11 +66,8 @@ const mapStateToProps = (state) => {
allProjectsToLists,
allBoardMemberships,
allLabels,
- canEdit: !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
- canEditCommentActivities:
- !!currentUserMembership &&
- (currentUserMembership.role === BoardMembershipRoles.EDITOR ||
- currentUserMembership.canComment),
+ canEdit: isCurrentUserEditor,
+ canEditCommentActivities: isCurrentUserEditorOrCanComment,
canEditAllCommentActivities: isCurrentUserManager,
};
};
diff --git a/client/src/containers/CoreContainer.js b/client/src/containers/CoreContainer.js
index d251927e..09ffc2c3 100755
--- a/client/src/containers/CoreContainer.js
+++ b/client/src/containers/CoreContainer.js
@@ -4,12 +4,16 @@ import selectors from '../selectors';
import Core from '../components/Core';
const mapStateToProps = (state) => {
+ const isCoreInitializing = selectors.selectIsCoreInitializing(state);
+ const isSocketDisconnected = selectors.selectIsSocketDisconnected(state);
const currentModal = selectors.selectCurrentModal(state);
const currentProject = selectors.selectCurrentProject(state);
return {
+ isSocketDisconnected,
currentModal,
currentProject,
+ isInitializing: isCoreInitializing,
};
};
diff --git a/client/src/containers/CoreWrapperContainer.js b/client/src/containers/CoreWrapperContainer.js
deleted file mode 100755
index f50ca642..00000000
--- a/client/src/containers/CoreWrapperContainer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { connect } from 'react-redux';
-
-import selectors from '../selectors';
-import CoreWrapper from '../components/CoreWrapper';
-
-const mapStateToProps = (state) => {
- const isCoreInitializing = selectors.selectIsCoreInitializing(state);
-
- return {
- isInitializing: isCoreInitializing,
- isSocketDisconnected: state.socket.isDisconnected,
- };
-};
-
-export default connect(mapStateToProps)(CoreWrapper);
diff --git a/client/src/containers/ListContainer.js b/client/src/containers/ListContainer.js
index 57e33621..95ee90c8 100755
--- a/client/src/containers/ListContainer.js
+++ b/client/src/containers/ListContainer.js
@@ -15,14 +15,16 @@ const makeMapStateToProps = () => {
const cardIds = selectCardIdsByListId(state, id);
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
+ const isCurrentUserEditor =
+ !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
+
return {
id,
index,
name,
isPersisted,
cardIds,
- canEdit:
- !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
+ canEdit: isCurrentUserEditor,
};
};
};
diff --git a/client/src/containers/StaticContainer.js b/client/src/containers/StaticContainer.js
index 01e10793..de59fffc 100644
--- a/client/src/containers/StaticContainer.js
+++ b/client/src/containers/StaticContainer.js
@@ -4,12 +4,13 @@ import selectors from '../selectors';
import Static from '../components/Static';
const mapStateToProps = (state) => {
- const { cardId, boardId, projectId } = selectors.selectPath(state);
+ const { cardId, projectId } = selectors.selectPath(state);
+ const currentBoard = selectors.selectCurrentBoard(state);
return {
- cardId,
- boardId,
projectId,
+ cardId,
+ board: currentBoard,
};
};
diff --git a/client/src/lib/popup/with-popup.jsx b/client/src/lib/popup/with-popup.jsx
index 02a0d0dc..6c561bf0 100755
--- a/client/src/lib/popup/with-popup.jsx
+++ b/client/src/lib/popup/with-popup.jsx
@@ -6,7 +6,7 @@ import { Button, Popup as SemanticUIPopup } from 'semantic-ui-react';
import styles from './Popup.module.css';
export default (WrappedComponent, defaultProps) => {
- const Popup = React.memo(({ children, ...props }) => {
+ const Popup = React.memo(({ children, onClose, ...props }) => {
const [isOpened, setIsOpened] = useState(false);
const wrapper = useRef(null);
@@ -18,7 +18,11 @@ export default (WrappedComponent, defaultProps) => {
const handleClose = useCallback(() => {
setIsOpened(false);
- }, []);
+
+ if (onClose) {
+ onClose();
+ }
+ }, [onClose]);
const handleMouseDown = useCallback((event) => {
event.stopPropagation();
@@ -105,6 +109,11 @@ export default (WrappedComponent, defaultProps) => {
Popup.propTypes = {
children: PropTypes.node.isRequired,
+ onClose: PropTypes.func,
+ };
+
+ Popup.defaultProps = {
+ onClose: undefined,
};
return Popup;
diff --git a/client/src/models/Activity.js b/client/src/models/Activity.js
index f387d04f..e30110b4 100755
--- a/client/src/models/Activity.js
+++ b/client/src/models/Activity.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Activity';
static fields = {
diff --git a/client/src/models/Attachment.js b/client/src/models/Attachment.js
index acd13b4c..64ea0116 100644
--- a/client/src/models/Attachment.js
+++ b/client/src/models/Attachment.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Attachment';
static fields = {
diff --git a/client/src/models/BaseModel.js b/client/src/models/BaseModel.js
new file mode 100644
index 00000000..17da5c52
--- /dev/null
+++ b/client/src/models/BaseModel.js
@@ -0,0 +1,6 @@
+import { Model } from 'redux-orm';
+
+export default class BaseModel extends Model {
+ // eslint-disable-next-line no-underscore-dangle, class-methods-use-this
+ _onDelete() {}
+}
diff --git a/client/src/models/Board.js b/client/src/models/Board.js
index 79c818bf..d048d606 100755
--- a/client/src/models/Board.js
+++ b/client/src/models/Board.js
@@ -1,13 +1,13 @@
-import { Model, attr, fk, many } from 'redux-orm';
+import { attr, fk, many } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Board';
static fields = {
id: attr(),
- type: attr(),
position: attr(),
name: attr(),
isFetching: attr({
@@ -179,7 +179,7 @@ export default class extends Model {
return this.lists.orderBy('position');
}
- getMembershipModel(userId) {
+ getMembershipModelForUser(userId) {
return this.memberships
.filter({
userId,
@@ -187,7 +187,7 @@ export default class extends Model {
.first();
}
- hasMemberUser(userId) {
+ hasMembershipForUser(userId) {
return this.memberships
.filter({
userId,
@@ -195,6 +195,12 @@ export default class extends Model {
.exists();
}
+ isAvailableForUser(userId) {
+ return (
+ this.project && (this.project.hasManagerForUser(userId) || this.hasMembershipForUser(userId))
+ );
+ }
+
deleteRelated(exceptMemberUserId) {
this.memberships.toModelArray().forEach((boardMembershipModel) => {
if (boardMembershipModel.userId !== exceptMemberUserId) {
diff --git a/client/src/models/BoardMembership.js b/client/src/models/BoardMembership.js
index f1d3ca1d..0bdd7044 100644
--- a/client/src/models/BoardMembership.js
+++ b/client/src/models/BoardMembership.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'BoardMembership';
static fields = {
diff --git a/client/src/models/Card.js b/client/src/models/Card.js
index c8712db1..5fbf0330 100755
--- a/client/src/models/Card.js
+++ b/client/src/models/Card.js
@@ -1,10 +1,11 @@
-import { Model, attr, fk, many, oneToOne } from 'redux-orm';
+import { attr, fk, many, oneToOne } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
import Config from '../constants/Config';
import { ActivityTypes } from '../constants/Enums';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Card';
static fields = {
@@ -74,7 +75,11 @@ export default class extends Model {
break;
case ActionTypes.SOCKET_RECONNECT_HANDLE:
- Card.all().delete();
+ Card.all()
+ .toModelArray()
+ .forEach((cardModel) => {
+ cardModel.deleteWithClearable();
+ });
if (payload.cards) {
payload.cards.forEach((card) => {
@@ -176,7 +181,7 @@ export default class extends Model {
break;
case ActionTypes.CARD_DELETE:
- Card.withId(payload.id).delete();
+ Card.withId(payload.id).deleteWithRelated();
break;
case ActionTypes.CARD_DELETE__SUCCESS:
@@ -220,15 +225,7 @@ export default class extends Model {
isActivitiesDetailsFetching: false,
});
- cardModel.activities.toModelArray().forEach((activityModel) => {
- if (activityModel.notification) {
- activityModel.update({
- isInCard: false,
- });
- } else {
- activityModel.delete();
- }
- });
+ cardModel.deleteActivities();
break;
}
@@ -268,10 +265,37 @@ export default class extends Model {
});
}
+ isAvailableForUser(userId) {
+ return this.board && this.board.isAvailableForUser(userId);
+ }
+
+ deleteClearable() {
+ this.users.clear();
+ this.labels.clear();
+ }
+
+ deleteActivities() {
+ this.activities.toModelArray().forEach((activityModel) => {
+ if (activityModel.notification) {
+ activityModel.update({
+ isInCard: false,
+ });
+ } else {
+ activityModel.delete();
+ }
+ });
+ }
+
deleteRelated() {
+ this.deleteClearable();
this.tasks.delete();
this.attachments.delete();
- this.activities.delete();
+ this.deleteActivities();
+ }
+
+ deleteWithClearable() {
+ this.deleteClearable();
+ this.delete();
}
deleteWithRelated() {
diff --git a/client/src/models/Label.js b/client/src/models/Label.js
index ef38393a..793e6734 100755
--- a/client/src/models/Label.js
+++ b/client/src/models/Label.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Label';
static fields = {
diff --git a/client/src/models/List.js b/client/src/models/List.js
index c78f84df..b634a666 100755
--- a/client/src/models/List.js
+++ b/client/src/models/List.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'List';
static fields = {
diff --git a/client/src/models/Notification.js b/client/src/models/Notification.js
index 4ace2873..fe6f4b14 100755
--- a/client/src/models/Notification.js
+++ b/client/src/models/Notification.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk, oneToOne } from 'redux-orm';
+import { attr, fk, oneToOne } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Notification';
static fields = {
diff --git a/client/src/models/Project.js b/client/src/models/Project.js
index 2ba703c3..df844734 100755
--- a/client/src/models/Project.js
+++ b/client/src/models/Project.js
@@ -1,9 +1,10 @@
-import { Model, attr, many } from 'redux-orm';
+import { attr, many } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
import { ProjectBackgroundTypes } from '../constants/Enums';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Project';
static fields = {
@@ -143,21 +144,21 @@ export default class extends Model {
return this.boards.orderBy('position');
}
- getOrderedMemberBoardsModelArray(userId) {
+ getOrderedBoardsModelArrayForUser(userId) {
return this.getOrderedBoardsQuerySet()
.toModelArray()
- .filter((boardModel) => boardModel.hasMemberUser(userId));
+ .filter((boardModel) => boardModel.hasMembershipForUser(userId));
}
- getOrderedAvailableBoardsModelArray(userId) {
- if (this.hasManagerUser(userId)) {
+ getOrderedBoardsModelArrayAvailableForUser(userId) {
+ if (this.hasManagerForUser(userId)) {
return this.getOrderedBoardsQuerySet().toModelArray();
}
- return this.getOrderedMemberBoardsModelArray(userId);
+ return this.getOrderedBoardsModelArrayForUser(userId);
}
- hasManagerUser(userId) {
+ hasManagerForUser(userId) {
return this.managers
.filter({
userId,
@@ -165,8 +166,12 @@ export default class extends Model {
.exists();
}
- hasMemberUserForAnyBoard(userId) {
- return this.boards.toModelArray().some((boardModel) => boardModel.hasMemberUser(userId));
+ hasMembershipInAnyBoardForUser(userId) {
+ return this.boards.toModelArray().some((boardModel) => boardModel.hasMembershipForUser(userId));
+ }
+
+ isAvailableForUser(userId) {
+ return this.hasManagerForUser(userId) || this.hasMembershipInAnyBoardForUser(userId);
}
deleteRelated() {
diff --git a/client/src/models/ProjectManager.js b/client/src/models/ProjectManager.js
index 7cae2cc4..6c68d5a0 100644
--- a/client/src/models/ProjectManager.js
+++ b/client/src/models/ProjectManager.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'ProjectManager';
static fields = {
diff --git a/client/src/models/Task.js b/client/src/models/Task.js
index c9a59777..1a472718 100755
--- a/client/src/models/Task.js
+++ b/client/src/models/Task.js
@@ -1,8 +1,9 @@
-import { Model, attr, fk } from 'redux-orm';
+import { attr, fk } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'Task';
static fields = {
diff --git a/client/src/models/User.js b/client/src/models/User.js
index 6bdf2753..fbc03d6c 100755
--- a/client/src/models/User.js
+++ b/client/src/models/User.js
@@ -1,5 +1,6 @@
-import { Model, attr } from 'redux-orm';
+import { attr } from 'redux-orm';
+import BaseModel from './BaseModel';
import ActionTypes from '../constants/ActionTypes';
const DEFAULT_EMAIL_UPDATE_FORM = {
@@ -29,7 +30,7 @@ const DEFAULT_USERNAME_UPDATE_FORM = {
error: null,
};
-export default class extends Model {
+export default class extends BaseModel {
static modelName = 'User';
static fields = {
diff --git a/client/src/sagas/core/services/cards.js b/client/src/sagas/core/services/cards.js
index 9af22a6f..a75844d2 100644
--- a/client/src/sagas/core/services/cards.js
+++ b/client/src/sagas/core/services/cards.js
@@ -12,7 +12,6 @@ export function* createCard(listId, data) {
const nextData = {
...data,
- listId,
position: yield select(selectors.selectNextCardPosition, listId),
};
@@ -22,13 +21,14 @@ export function* createCard(listId, data) {
actions.createCard({
...nextData,
boardId,
+ listId,
id: localId,
}),
);
let card;
try {
- ({ item: card } = yield call(request, api.createCard, boardId, nextData));
+ ({ item: card } = yield call(request, api.createCard, listId, nextData));
} catch (error) {
yield put(actions.createCard.failure(localId, error));
return;
@@ -61,8 +61,9 @@ export function* updateCurrentCard(data) {
yield call(updateCard, cardId, data);
}
+// TODO: handle card transfer
export function* handleCardUpdate(card) {
- yield put(actions.handleCardUpdate(card)); // TODO: handle card transfer
+ yield put(actions.handleCardUpdate(card));
}
export function* moveCard(id, listId, index) {
diff --git a/client/src/sagas/core/services/lists.js b/client/src/sagas/core/services/lists.js
index 670bc9a5..d9dd7182 100644
--- a/client/src/sagas/core/services/lists.js
+++ b/client/src/sagas/core/services/lists.js
@@ -39,8 +39,8 @@ export function* createListInCurrentBoard(data) {
yield call(createList, boardId, data);
}
-export function* handleListCreate(label) {
- yield put(actions.handleListCreate(label));
+export function* handleListCreate(list) {
+ yield put(actions.handleListCreate(list));
}
export function* updateList(id, data) {
@@ -57,8 +57,8 @@ export function* updateList(id, data) {
yield put(actions.updateList.success(list));
}
-export function* handleListUpdate(label) {
- yield put(actions.handleListUpdate(label));
+export function* handleListUpdate(list) {
+ yield put(actions.handleListUpdate(list));
}
export function* moveList(id, index) {
@@ -84,8 +84,8 @@ export function* deleteList(id) {
yield put(actions.deleteList.success(list));
}
-export function* handleListDelete(label) {
- yield put(actions.handleListDelete(label));
+export function* handleListDelete(list) {
+ yield put(actions.handleListDelete(list));
}
export default {
diff --git a/client/src/selectors/boards.js b/client/src/selectors/boards.js
index 52a653e5..7edf34ff 100644
--- a/client/src/selectors/boards.js
+++ b/client/src/selectors/boards.js
@@ -69,6 +69,31 @@ export const selectMembershipsForCurrentBoard = createSelector(
},
);
+export const selectCurrentUserMembershipForCurrentBoard = createSelector(
+ orm,
+ (state) => selectPath(state).boardId,
+ (state) => selectCurrentUserId(state),
+ ({ Board }, id, currentUserId) => {
+ if (!id) {
+ return id;
+ }
+
+ const boardModel = Board.withId(id);
+
+ if (!boardModel) {
+ return boardModel;
+ }
+
+ const boardMembershipModel = boardModel.getMembershipModelForUser(currentUserId);
+
+ if (!boardMembershipModel) {
+ return boardMembershipModel;
+ }
+
+ return boardMembershipModel.ref;
+ },
+);
+
export const selectLabelsForCurrentBoard = createSelector(
orm,
(state) => selectPath(state).boardId,
@@ -147,31 +172,6 @@ export const selectFilterLabelsForCurrentBoard = createSelector(
},
);
-export const selectCurrentUserMembershipForCurrentBoard = createSelector(
- orm,
- (state) => selectPath(state).boardId,
- (state) => selectCurrentUserId(state),
- ({ Board }, id, currentUserId) => {
- if (!id) {
- return id;
- }
-
- const boardModel = Board.withId(id);
-
- if (!boardModel) {
- return boardModel;
- }
-
- const boardMembershipModel = boardModel.getMembershipModel(currentUserId);
-
- if (!boardMembershipModel) {
- return boardMembershipModel;
- }
-
- return boardMembershipModel.ref;
- },
-);
-
export const selectIsBoardWithIdExists = createSelector(
orm,
(_, id) => id,
@@ -183,10 +183,10 @@ export default {
selectBoardById,
selectCurrentBoard,
selectMembershipsForCurrentBoard,
+ selectCurrentUserMembershipForCurrentBoard,
selectLabelsForCurrentBoard,
selectListIdsForCurrentBoard,
selectFilterUsersForCurrentBoard,
selectFilterLabelsForCurrentBoard,
- selectCurrentUserMembershipForCurrentBoard,
selectIsBoardWithIdExists,
};
diff --git a/client/src/selectors/index.js b/client/src/selectors/index.js
index 617b2b2c..9b636666 100755
--- a/client/src/selectors/index.js
+++ b/client/src/selectors/index.js
@@ -1,4 +1,5 @@
import router from './router';
+import socket from './socket';
import core from './core';
import modals from './modals';
import users from './users';
@@ -13,6 +14,7 @@ import attachments from './attachments';
export default {
...router,
+ ...socket,
...core,
...modals,
...users,
diff --git a/client/src/selectors/projects.js b/client/src/selectors/projects.js
index ddfe60e1..900f9c6a 100644
--- a/client/src/selectors/projects.js
+++ b/client/src/selectors/projects.js
@@ -67,10 +67,12 @@ export const selectBoardsForCurrentProject = createSelector(
return projectModel;
}
- return projectModel.getOrderedAvailableBoardsModelArray(currentUserId).map((boardModel) => ({
- ...boardModel.ref,
- isPersisted: !isLocalId(boardModel.id),
- }));
+ return projectModel
+ .getOrderedBoardsModelArrayAvailableForUser(currentUserId)
+ .map((boardModel) => ({
+ ...boardModel.ref,
+ isPersisted: !isLocalId(boardModel.id),
+ }));
},
);
@@ -89,7 +91,7 @@ export const selectIsCurrentUserManagerForCurrentProject = createSelector(
return false;
}
- return projectModel.hasManagerUser(currentUserId);
+ return projectModel.hasManagerForUser(currentUserId);
},
);
diff --git a/client/src/selectors/router.js b/client/src/selectors/router.js
index d0e42e71..d63d317c 100755
--- a/client/src/selectors/router.js
+++ b/client/src/selectors/router.js
@@ -26,55 +26,35 @@ export const selectPath = createReduxOrmSelector(
case Paths.PROJECTS: {
const projectModel = Project.withId(pathsMatch.params.id);
- if (!projectModel) {
+ if (!projectModel || !projectModel.isAvailableForUser(currentUserId)) {
return {
projectId: null,
};
}
- if (!projectModel.hasManagerUser(currentUserId)) {
- if (!projectModel.hasMemberUserForAnyBoard(currentUserId)) {
- return {
- projectId: null,
- };
- }
- }
-
return {
projectId: projectModel.id,
};
}
case Paths.BOARDS: {
const boardModel = Board.withId(pathsMatch.params.id);
- const projectModel = boardModel && boardModel.project;
- if (!projectModel) {
+ if (!boardModel || !boardModel.isAvailableForUser(currentUserId)) {
return {
boardId: null,
projectId: null,
};
}
- if (!projectModel.hasManagerUser(currentUserId)) {
- if (!boardModel.hasMemberUser(currentUserId)) {
- return {
- boardId: null,
- projectId: null,
- };
- }
- }
-
return {
boardId: boardModel.id,
- projectId: projectModel.id,
+ projectId: boardModel.projectId,
};
}
case Paths.CARDS: {
const cardModel = Card.withId(pathsMatch.params.id);
- const boardModel = cardModel && cardModel.board;
- const projectModel = boardModel && boardModel.project;
- if (!projectModel) {
+ if (!cardModel || !cardModel.isAvailableForUser(currentUserId)) {
return {
cardId: null,
boardId: null,
@@ -82,20 +62,10 @@ export const selectPath = createReduxOrmSelector(
};
}
- if (!projectModel.hasManagerUser(currentUserId)) {
- if (!boardModel.hasMemberUser(currentUserId)) {
- return {
- cardId: null,
- boardId: null,
- projectId: null,
- };
- }
- }
-
return {
cardId: cardModel.id,
- boardId: boardModel.id,
- projectId: projectModel.id,
+ boardId: cardModel.boardId,
+ projectId: cardModel.board.projectId,
};
}
default:
diff --git a/client/src/selectors/socket.js b/client/src/selectors/socket.js
new file mode 100644
index 00000000..e75a10dd
--- /dev/null
+++ b/client/src/selectors/socket.js
@@ -0,0 +1,5 @@
+export const selectIsSocketDisconnected = ({ socket: { isDisconnected } }) => isDisconnected;
+
+export default {
+ selectIsSocketDisconnected,
+};
diff --git a/client/src/selectors/users.js b/client/src/selectors/users.js
index c3b3bd4b..953e76de 100644
--- a/client/src/selectors/users.js
+++ b/client/src/selectors/users.js
@@ -52,7 +52,7 @@ export const selectProjectsForCurrentUser = createSelector(
}
return userModel.getOrderedAvailableProjectsModelArray().map((projectModel) => {
- const boardsModels = projectModel.getOrderedAvailableBoardsModelArray(userModel.id);
+ const boardsModels = projectModel.getOrderedBoardsModelArrayAvailableForUser(userModel.id);
let notificationsTotal = 0;
boardsModels.forEach((boardModel) => {
@@ -86,7 +86,7 @@ export const selectProjectsToListsForCurrentUser = createSelector(
return userModel.getOrderedAvailableProjectsModelArray().map((projectModel) => ({
...projectModel.ref,
- boards: projectModel.getOrderedMemberBoardsModelArray(id).map((boardModel) => ({
+ boards: projectModel.getOrderedBoardsModelArrayForUser(id).map((boardModel) => ({
...boardModel.ref,
lists: boardModel.getOrderedListsQuerySet().toRefArray(),
})),
diff --git a/server/api/controllers/access-tokens/create.js b/server/api/controllers/access-tokens/create.js
index cdb76243..f98add91 100755
--- a/server/api/controllers/access-tokens/create.js
+++ b/server/api/controllers/access-tokens/create.js
@@ -12,16 +12,16 @@ const Errors = {
},
};
+const emailOrUsernameValidator = (value) =>
+ value.includes('@')
+ ? validator.isEmail(value)
+ : value.length >= 3 && value.length <= 16 && /^[a-zA-Z0-9]+((_|\.)?[a-zA-Z0-9])*$/.test(value);
+
module.exports = {
inputs: {
emailOrUsername: {
type: 'string',
- custom: (value) =>
- value.includes('@')
- ? validator.isEmail(value)
- : value.length >= 3 &&
- value.length <= 16 &&
- /^[a-zA-Z0-9]+((_|\.)?[a-zA-Z0-9])*$/.test(value),
+ custom: emailOrUsernameValidator,
required: true,
},
password: {
diff --git a/server/api/controllers/attachments/create.js b/server/api/controllers/attachments/create.js
index e822e5e5..bab6e138 100644
--- a/server/api/controllers/attachments/create.js
+++ b/server/api/controllers/attachments/create.js
@@ -82,13 +82,15 @@ module.exports = {
const file = _.last(files);
const fileData = await sails.helpers.attachments.processUploadedFile(file);
- const attachment = await sails.helpers.attachments.createOne(
- fileData,
- currentUser,
- card,
- inputs.requestId,
- this.req,
- );
+ const attachment = await sails.helpers.attachments.createOne.with({
+ values: {
+ ...fileData,
+ card,
+ creatorUser: currentUser,
+ },
+ requestId: inputs.requestId,
+ request: this.req,
+ });
return exits.success({
item: attachment,
diff --git a/server/api/controllers/attachments/delete.js b/server/api/controllers/attachments/delete.js
index 85af351b..697f749d 100755
--- a/server/api/controllers/attachments/delete.js
+++ b/server/api/controllers/attachments/delete.js
@@ -48,7 +48,12 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- attachment = await sails.helpers.attachments.deleteOne(attachment, board, card, this.req);
+ attachment = await sails.helpers.attachments.deleteOne.with({
+ board,
+ card,
+ record: attachment,
+ request: this.req,
+ });
if (!attachment) {
throw Errors.ATTACHMENT_NOT_FOUND;
diff --git a/server/api/controllers/attachments/update.js b/server/api/controllers/attachments/update.js
index c1ac51d3..90e51bab 100755
--- a/server/api/controllers/attachments/update.js
+++ b/server/api/controllers/attachments/update.js
@@ -53,7 +53,13 @@ module.exports = {
}
const values = _.pick(inputs, ['name']);
- attachment = await sails.helpers.attachments.updateOne(attachment, values, board, this.req);
+
+ attachment = await sails.helpers.attachments.updateOne.with({
+ values,
+ board,
+ record: attachment,
+ request: this.req,
+ });
if (!attachment) {
throw Errors.ATTACHMENT_NOT_FOUND;
diff --git a/server/api/controllers/board-memberships/create.js b/server/api/controllers/board-memberships/create.js
index 611288fb..fa4ec899 100755
--- a/server/api/controllers/board-memberships/create.js
+++ b/server/api/controllers/board-memberships/create.js
@@ -68,8 +68,15 @@ module.exports = {
const values = _.pick(inputs, ['role', 'canComment']);
- const boardMembership = await sails.helpers.boardMemberships
- .createOne(values, user, board, this.req)
+ const boardMembership = await sails.helpers.boardMemberships.createOne
+ .with({
+ values: {
+ ...values,
+ board,
+ user,
+ },
+ request: this.req,
+ })
.intercept('userAlreadyBoardMember', () => Errors.USER_ALREADY_BOARD_MEMBER);
return {
diff --git a/server/api/controllers/board-memberships/delete.js b/server/api/controllers/board-memberships/delete.js
index f4aacf90..b9d6021c 100755
--- a/server/api/controllers/board-memberships/delete.js
+++ b/server/api/controllers/board-memberships/delete.js
@@ -36,15 +36,15 @@ module.exports = {
);
if (!isProjectManager) {
- throw Errors.BOARD_MEMBERSHIP_NOT_FOUND;
+ throw Errors.BOARD_MEMBERSHIP_NOT_FOUND; // Forbidden
}
}
- boardMembership = await sails.helpers.boardMemberships.deleteOne(
- boardMembership,
+ boardMembership = await sails.helpers.boardMemberships.deleteOne.with({
project,
- this.req,
- );
+ record: boardMembership,
+ request: this.req,
+ });
if (!boardMembership) {
throw Errors.BOARD_MEMBERSHIP_NOT_FOUND;
diff --git a/server/api/controllers/board-memberships/update.js b/server/api/controllers/board-memberships/update.js
index 2439ee01..ffbf2d5c 100644
--- a/server/api/controllers/board-memberships/update.js
+++ b/server/api/controllers/board-memberships/update.js
@@ -44,11 +44,11 @@ module.exports = {
const values = _.pick(inputs, ['role', 'canComment']);
- boardMembership = await sails.helpers.boardMemberships.updateOne(
- boardMembership,
+ boardMembership = await sails.helpers.boardMemberships.updateOne.with({
values,
- this.req,
- );
+ record: boardMembership,
+ request: this.req,
+ });
return {
item: boardMembership,
diff --git a/server/api/controllers/boards/create.js b/server/api/controllers/boards/create.js
index c825e911..f1d69b40 100755
--- a/server/api/controllers/boards/create.js
+++ b/server/api/controllers/boards/create.js
@@ -20,11 +20,6 @@ module.exports = {
regex: /^[0-9]+$/,
required: true,
},
- type: {
- type: 'string',
- isIn: Object.values(Board.Types),
- required: true,
- },
position: {
type: 'number',
required: true,
@@ -70,7 +65,7 @@ module.exports = {
throw Errors.PROJECT_NOT_FOUND; // Forbidden
}
- const values = _.pick(inputs, ['type', 'position', 'name']);
+ const values = _.pick(inputs, ['position', 'name']);
let boardImport;
if (inputs.importType && Object.values(Board.ImportTypes).includes(inputs.importType)) {
@@ -102,14 +97,16 @@ module.exports = {
}
}
- const { board, boardMembership } = await sails.helpers.boards.createOne(
- values,
- boardImport,
- currentUser,
- project,
- inputs.requestId,
- this.req,
- );
+ const { board, boardMembership } = await sails.helpers.boards.createOne.with({
+ values: {
+ ...values,
+ project,
+ },
+ import: boardImport,
+ user: currentUser,
+ requestId: inputs.requestId,
+ request: this.req,
+ });
if (this.req.isSocket) {
sails.sockets.join(this.req, `board:${board.id}`); // TODO: only when subscription needed
diff --git a/server/api/controllers/boards/delete.js b/server/api/controllers/boards/delete.js
index 1909b897..9d0fc5cd 100755
--- a/server/api/controllers/boards/delete.js
+++ b/server/api/controllers/boards/delete.js
@@ -39,7 +39,10 @@ module.exports = {
throw Errors.BOARD_NOT_FOUND; // Forbidden
}
- board = await sails.helpers.boards.deleteOne(board, this.req);
+ board = await sails.helpers.boards.deleteOne.with({
+ record: board,
+ request: this.req,
+ });
if (!board) {
throw Errors.BOARD_NOT_FOUND;
diff --git a/server/api/controllers/boards/show.js b/server/api/controllers/boards/show.js
index ac7fadc8..d7a5f871 100755
--- a/server/api/controllers/boards/show.js
+++ b/server/api/controllers/boards/show.js
@@ -47,7 +47,7 @@ module.exports = {
const labels = await sails.helpers.boards.getLabels(board.id);
const lists = await sails.helpers.boards.getLists(board.id);
- const cards = await sails.helpers.boards.getCards(board);
+ const cards = await sails.helpers.boards.getCards(board.id);
const cardIds = sails.helpers.utils.mapRecords(cards);
const cardSubscriptions = await sails.helpers.cardSubscriptions.getMany({
@@ -69,7 +69,8 @@ module.exports = {
);
cards.forEach((card) => {
- card.isSubscribed = isSubscribedByCardId[card.id] || false; // eslint-disable-line no-param-reassign
+ // eslint-disable-next-line no-param-reassign
+ card.isSubscribed = isSubscribedByCardId[card.id] || false;
});
if (this.req.isSocket) {
diff --git a/server/api/controllers/boards/update.js b/server/api/controllers/boards/update.js
index 745af6ca..85c2d01c 100755
--- a/server/api/controllers/boards/update.js
+++ b/server/api/controllers/boards/update.js
@@ -47,7 +47,12 @@ module.exports = {
}
const values = _.pick(inputs, ['position', 'name']);
- board = await sails.helpers.boards.updateOne(board, values, this.req);
+
+ board = await sails.helpers.boards.updateOne.with({
+ values,
+ record: board,
+ request: this.req,
+ });
if (!board) {
throw Errors.BOARD_NOT_FOUND;
diff --git a/server/api/controllers/card-labels/create.js b/server/api/controllers/card-labels/create.js
index 14caf017..207619af 100755
--- a/server/api/controllers/card-labels/create.js
+++ b/server/api/controllers/card-labels/create.js
@@ -71,8 +71,14 @@ module.exports = {
throw Errors.LABEL_NOT_FOUND;
}
- const cardLabel = await sails.helpers.cardLabels
- .createOne(label, card, this.req)
+ const cardLabel = await sails.helpers.cardLabels.createOne
+ .with({
+ values: {
+ card,
+ label,
+ },
+ request: this.req,
+ })
.intercept('labelAlreadyInCard', () => Errors.LABEL_ALREADY_IN_CARD);
return {
diff --git a/server/api/controllers/card-labels/delete.js b/server/api/controllers/card-labels/delete.js
index a54ae064..2911bce4 100755
--- a/server/api/controllers/card-labels/delete.js
+++ b/server/api/controllers/card-labels/delete.js
@@ -65,7 +65,11 @@ module.exports = {
throw Errors.LABEL_NOT_IN_CARD;
}
- cardLabel = await sails.helpers.cardLabels.deleteOne(cardLabel, board, this.req);
+ cardLabel = await sails.helpers.cardLabels.deleteOne.with({
+ board,
+ record: cardLabel,
+ request: this.req,
+ });
if (!cardLabel) {
throw Errors.LABEL_NOT_IN_CARD;
diff --git a/server/api/controllers/card-memberships/create.js b/server/api/controllers/card-memberships/create.js
index 9c2c9c8a..c5ee73f7 100755
--- a/server/api/controllers/card-memberships/create.js
+++ b/server/api/controllers/card-memberships/create.js
@@ -68,8 +68,14 @@ module.exports = {
throw Errors.USER_NOT_FOUND;
}
- const cardMembership = await sails.helpers.cardMemberships
- .createOne(inputs.userId, card, this.req)
+ const cardMembership = await sails.helpers.cardMemberships.createOne
+ .with({
+ values: {
+ card,
+ userId: inputs.userId,
+ },
+ request: this.req,
+ })
.intercept('userAlreadyCardMember', () => Errors.USER_ALREADY_CARD_MEMBER);
return {
diff --git a/server/api/controllers/card-memberships/delete.js b/server/api/controllers/card-memberships/delete.js
index 48d38569..d2107309 100755
--- a/server/api/controllers/card-memberships/delete.js
+++ b/server/api/controllers/card-memberships/delete.js
@@ -65,7 +65,11 @@ module.exports = {
throw Errors.USER_NOT_CARD_MEMBER;
}
- cardMembership = await sails.helpers.cardMemberships.deleteOne(cardMembership, board, this.req);
+ cardMembership = await sails.helpers.cardMemberships.deleteOne.with({
+ board,
+ record: cardMembership,
+ request: this.req,
+ });
if (!cardMembership) {
throw Errors.USER_NOT_CARD_MEMBER;
diff --git a/server/api/controllers/cards/create.js b/server/api/controllers/cards/create.js
index 580f67b6..0b2d2698 100755
--- a/server/api/controllers/cards/create.js
+++ b/server/api/controllers/cards/create.js
@@ -4,30 +4,42 @@ const Errors = {
NOT_ENOUGH_RIGHTS: {
notEnoughRights: 'Not enough rights',
},
- BOARD_NOT_FOUND: {
- boardNotFound: 'Board not found',
- },
LIST_NOT_FOUND: {
listNotFound: 'List not found',
},
- LIST_MUST_BE_PRESENT: {
- listMustBePresent: 'List must be present',
- },
POSITION_MUST_BE_PRESENT: {
positionMustBePresent: 'Position must be present',
},
};
+const dueDateValidator = (value) => moment(value, moment.ISO_8601, true).isValid();
+
+const timerValidator = (value) => {
+ if (!_.isPlainObject(value) || _.size(value) !== 2) {
+ return false;
+ }
+
+ if (
+ !_.isNull(value.startedAt) &&
+ _.isString(value.startedAt) &&
+ !moment(value.startedAt, moment.ISO_8601, true).isValid()
+ ) {
+ return false;
+ }
+
+ if (!_.isFinite(value.total)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
- boardId: {
- type: 'string',
- regex: /^[0-9]+$/,
- required: true,
- },
listId: {
type: 'string',
regex: /^[0-9]+$/,
+ required: true,
},
position: {
type: 'number',
@@ -43,29 +55,11 @@ module.exports = {
},
dueDate: {
type: 'string',
- custom: (value) => moment(value, moment.ISO_8601, true).isValid(),
+ custom: dueDateValidator,
},
timer: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value) || _.size(value) !== 2) {
- return false;
- }
-
- if (
- !_.isNull(value.startedAt) &&
- _.isString(value.startedAt) &&
- !moment(value.startedAt, moment.ISO_8601, true).isValid()
- ) {
- return false;
- }
-
- if (!_.isFinite(value.total)) {
- return false;
- }
-
- return true;
- },
+ custom: timerValidator,
},
},
@@ -73,15 +67,9 @@ module.exports = {
notEnoughRights: {
responseType: 'forbidden',
},
- boardNotFound: {
- responseType: 'notFound',
- },
listNotFound: {
responseType: 'notFound',
},
- listMustBePresent: {
- responseType: 'unprocessableEntity',
- },
positionMustBePresent: {
responseType: 'unprocessableEntity',
},
@@ -90,40 +78,34 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board } = await sails.helpers.boards
- .getProjectPath(inputs.boardId)
- .intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
+ const { list } = await sails.helpers.lists
+ .getProjectPath(inputs.listId)
+ .intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: board.id,
+ boardId: list.boardId,
userId: currentUser.id,
});
if (!boardMembership) {
- throw Errors.BOARD_NOT_FOUND; // Forbidden
+ throw Errors.LIST_NOT_FOUND; // Forbidden
}
if (boardMembership.role !== BoardMembership.Roles.EDITOR) {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- let list;
- if (!_.isUndefined(inputs.listId)) {
- list = await List.findOne({
- id: inputs.listId,
- boardId: board.id,
- });
-
- if (!list) {
- throw Errors.LIST_NOT_FOUND;
- }
- }
-
const values = _.pick(inputs, ['position', 'name', 'description', 'dueDate', 'timer']);
- const card = await sails.helpers.cards
- .createOne(values, currentUser, board, list, this.req)
- .intercept('listMustBePresent', () => Errors.LIST_MUST_BE_PRESENT)
+ const card = await sails.helpers.cards.createOne
+ .with({
+ values: {
+ ...values,
+ list,
+ creatorUser: currentUser,
+ },
+ request: this.req,
+ })
.intercept('positionMustBeInValues', () => Errors.POSITION_MUST_BE_PRESENT);
return {
diff --git a/server/api/controllers/cards/delete.js b/server/api/controllers/cards/delete.js
index 98c61e2c..e2b6d00b 100755
--- a/server/api/controllers/cards/delete.js
+++ b/server/api/controllers/cards/delete.js
@@ -45,7 +45,10 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- card = await sails.helpers.cards.deleteOne(card, this.req);
+ card = await sails.helpers.cards.deleteOne.with({
+ record: card,
+ request: this.req,
+ });
if (!card) {
throw Errors.CARD_NOT_FOUND;
diff --git a/server/api/controllers/cards/index.js b/server/api/controllers/cards/index.js
deleted file mode 100644
index 3bcd7ea0..00000000
--- a/server/api/controllers/cards/index.js
+++ /dev/null
@@ -1,74 +0,0 @@
-const Errors = {
- BOARD_NOT_FOUND: {
- boardNotFound: 'Board not found',
- },
-};
-
-module.exports = {
- inputs: {
- boardId: {
- type: 'string',
- regex: /^[0-9]+$/,
- required: true,
- },
- beforeId: {
- type: 'string',
- regex: /^[0-9]+$/,
- },
- },
-
- exits: {
- boardNotFound: {
- responseType: 'notFound',
- },
- },
-
- async fn(inputs) {
- const { currentUser } = this.req;
-
- const { board } = await sails.helpers.boards
- .getProjectPath(inputs.boardId)
- .intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
-
- const isBoardMember = await sails.helpers.users.isBoardMember(currentUser.id, board.id);
-
- if (!isBoardMember) {
- throw Errors.BOARD_NOT_FOUND; // Forbidden
- }
-
- const cards = await sails.helpers.boards.getCards(board, inputs.beforeId);
- const cardIds = sails.helpers.utils.mapRecords(cards);
-
- const cardSubscriptions = await sails.helpers.cardSubscriptions.getMany({
- cardId: cardIds,
- userId: currentUser.id,
- });
-
- const isSubscribedByCardId = cardSubscriptions.reduce(
- (result, cardSubscription) => ({
- ...result,
- [cardSubscription.cardId]: true,
- }),
- {},
- );
-
- cards.forEach((card) => {
- card.isSubscribed = isSubscribedByCardId[card.id] || false; // eslint-disable-line no-param-reassign
- });
-
- const cardMemberships = await sails.helpers.cards.getCardMemberships(cardIds);
- const cardLabels = await sails.helpers.cards.getCardLabels(cardIds);
- const tasks = await sails.helpers.cards.getTasks(cardIds);
- const attachments = await sails.helpers.cards.getAttachments(cardIds);
-
- return {
- items: cards,
- included: {
- cardMemberships,
- cardLabels,
- tasks,
- attachments,
- },
- };
- },
-};
diff --git a/server/api/controllers/cards/update.js b/server/api/controllers/cards/update.js
index 3fbe3ced..f87853e5 100755
--- a/server/api/controllers/cards/update.js
+++ b/server/api/controllers/cards/update.js
@@ -21,6 +21,28 @@ const Errors = {
},
};
+const dueDateValidator = (value) => moment(value, moment.ISO_8601, true).isValid();
+
+const timerValidator = (value) => {
+ if (!_.isPlainObject(value) || _.size(value) !== 2) {
+ return false;
+ }
+
+ if (
+ !_.isNull(value.startedAt) &&
+ _.isString(value.startedAt) &&
+ !moment(value.startedAt, moment.ISO_8601, true).isValid()
+ ) {
+ return false;
+ }
+
+ if (!_.isFinite(value.total)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
id: {
@@ -55,30 +77,12 @@ module.exports = {
},
dueDate: {
type: 'string',
- custom: (value) => moment(value, moment.ISO_8601, true).isValid(),
+ custom: dueDateValidator,
allowNull: true,
},
timer: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value) || _.size(value) !== 2) {
- return false;
- }
-
- if (
- !_.isNull(value.startedAt) &&
- _.isString(value.startedAt) &&
- !moment(value.startedAt, moment.ISO_8601, true).isValid()
- ) {
- return false;
- }
-
- if (!_.isFinite(value.total)) {
- return false;
- }
-
- return true;
- },
+ custom: timerValidator,
},
isSubscribed: {
type: 'boolean',
@@ -171,10 +175,21 @@ module.exports = {
'isSubscribed',
]);
- card = await sails.helpers.cards
- .updateOne(card, values, nextBoard, nextList, currentUser, board, list, this.req)
- .intercept('nextListMustBePresent', () => Errors.LIST_MUST_BE_PRESENT)
- .intercept('positionMustBeInValues', () => Errors.POSITION_MUST_BE_PRESENT);
+ card = await sails.helpers.cards.updateOne
+ .with({
+ board,
+ list,
+ record: card,
+ values: {
+ ...values,
+ board: nextBoard,
+ list: nextList,
+ },
+ user: currentUser,
+ request: this.req,
+ })
+ .intercept('positionMustBeInValues', () => Errors.POSITION_MUST_BE_PRESENT)
+ .intercept('listMustBeInValues', () => Errors.LIST_MUST_BE_PRESENT);
if (!card) {
throw Errors.CARD_NOT_FOUND;
diff --git a/server/api/controllers/comment-actions/create.js b/server/api/controllers/comment-actions/create.js
index cd60287e..ddf4b991 100755
--- a/server/api/controllers/comment-actions/create.js
+++ b/server/api/controllers/comment-actions/create.js
@@ -54,7 +54,14 @@ module.exports = {
data: _.pick(inputs, ['text']),
};
- const action = await sails.helpers.actions.createOne(values, currentUser, card, this.req);
+ const action = await sails.helpers.actions.createOne.with({
+ values: {
+ ...values,
+ card,
+ user: currentUser,
+ },
+ request: this.req,
+ });
return {
item: action,
diff --git a/server/api/controllers/comment-actions/delete.js b/server/api/controllers/comment-actions/delete.js
index a173635f..b09ce262 100755
--- a/server/api/controllers/comment-actions/delete.js
+++ b/server/api/controllers/comment-actions/delete.js
@@ -59,7 +59,11 @@ module.exports = {
}
}
- action = await sails.helpers.actions.deleteOne(action, board, this.req);
+ action = await sails.helpers.actions.deleteOne.with({
+ board,
+ record: action,
+ request: this.req,
+ });
if (!action) {
throw Errors.COMMENT_ACTION_NOT_FOUND;
diff --git a/server/api/controllers/comment-actions/update.js b/server/api/controllers/comment-actions/update.js
index 73e4bbe8..fc5dffb9 100755
--- a/server/api/controllers/comment-actions/update.js
+++ b/server/api/controllers/comment-actions/update.js
@@ -67,7 +67,12 @@ module.exports = {
data: _.pick(inputs, ['text']),
};
- action = await sails.helpers.actions.updateOne(action, values, board, this.req);
+ action = await sails.helpers.actions.updateOne.with({
+ values,
+ board,
+ record: action,
+ request: this.req,
+ });
if (!action) {
throw Errors.COMMENT_ACTION_NOT_FOUND;
diff --git a/server/api/controllers/labels/create.js b/server/api/controllers/labels/create.js
index 1af47b8b..086626e4 100755
--- a/server/api/controllers/labels/create.js
+++ b/server/api/controllers/labels/create.js
@@ -56,7 +56,14 @@ module.exports = {
}
const values = _.pick(inputs, ['name', 'color']);
- const label = await sails.helpers.labels.createOne(values, board, this.req);
+
+ const label = await sails.helpers.labels.createOne.with({
+ values: {
+ ...values,
+ board,
+ },
+ request: this.req,
+ });
return {
item: label,
diff --git a/server/api/controllers/labels/delete.js b/server/api/controllers/labels/delete.js
index 3c5c2ac2..e2f0a098 100755
--- a/server/api/controllers/labels/delete.js
+++ b/server/api/controllers/labels/delete.js
@@ -45,7 +45,10 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- label = await sails.helpers.labels.deleteOne(label, this.req);
+ label = await sails.helpers.labels.deleteOne.with({
+ record: label,
+ request: this.req,
+ });
if (!label) {
throw Errors.LABEL_NOT_FOUND;
diff --git a/server/api/controllers/labels/update.js b/server/api/controllers/labels/update.js
index 3e7ce24b..ee3646d7 100755
--- a/server/api/controllers/labels/update.js
+++ b/server/api/controllers/labels/update.js
@@ -56,7 +56,12 @@ module.exports = {
}
const values = _.pick(inputs, ['name', 'color']);
- label = await sails.helpers.labels.updateOne(label, values, this.req);
+
+ label = await sails.helpers.labels.updateOne.with({
+ values,
+ record: label,
+ request: this.req,
+ });
return {
item: label,
diff --git a/server/api/controllers/lists/create.js b/server/api/controllers/lists/create.js
index f1d45828..9383f5be 100755
--- a/server/api/controllers/lists/create.js
+++ b/server/api/controllers/lists/create.js
@@ -54,7 +54,14 @@ module.exports = {
}
const values = _.pick(inputs, ['position', 'name']);
- const list = await sails.helpers.lists.createOne(values, board, this.req);
+
+ const list = await sails.helpers.lists.createOne.with({
+ values: {
+ ...values,
+ board,
+ },
+ request: this.req,
+ });
return {
item: list,
diff --git a/server/api/controllers/lists/delete.js b/server/api/controllers/lists/delete.js
index 9c9a5d2d..44cb48b4 100755
--- a/server/api/controllers/lists/delete.js
+++ b/server/api/controllers/lists/delete.js
@@ -45,7 +45,10 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- list = await sails.helpers.lists.deleteOne(list, this.req);
+ list = await sails.helpers.lists.deleteOne.with({
+ record: list,
+ request: this.req,
+ });
if (!list) {
throw Errors.LIST_NOT_FOUND;
diff --git a/server/api/controllers/lists/update.js b/server/api/controllers/lists/update.js
index ea379855..2cb34e25 100755
--- a/server/api/controllers/lists/update.js
+++ b/server/api/controllers/lists/update.js
@@ -53,7 +53,12 @@ module.exports = {
}
const values = _.pick(inputs, ['position', 'name']);
- list = await sails.helpers.lists.updateOne(list, values, this.req);
+
+ list = await sails.helpers.lists.updateOne.with({
+ values,
+ record: list,
+ request: this.req,
+ });
if (!list) {
throw Errors.LIST_NOT_FOUND;
diff --git a/server/api/controllers/notifications/update.js b/server/api/controllers/notifications/update.js
index 6d73f616..f8a97a35 100755
--- a/server/api/controllers/notifications/update.js
+++ b/server/api/controllers/notifications/update.js
@@ -15,12 +15,12 @@ module.exports = {
const values = _.pick(inputs, ['isRead']);
- const notifications = await sails.helpers.notifications.updateMany(
- inputs.ids.split(','),
+ const notifications = await sails.helpers.notifications.updateMany.with({
values,
- currentUser,
- this.req,
- );
+ recordsOrIds: inputs.ids.split(','),
+ user: currentUser,
+ request: this.req,
+ });
return {
items: notifications,
diff --git a/server/api/controllers/project-managers/create.js b/server/api/controllers/project-managers/create.js
index 227980d9..a5751fdb 100755
--- a/server/api/controllers/project-managers/create.js
+++ b/server/api/controllers/project-managers/create.js
@@ -57,8 +57,14 @@ module.exports = {
throw Error.USER_NOT_FOUND;
}
- const projectManager = await sails.helpers.projectManagers
- .createOne(user, project, this.req)
+ const projectManager = await sails.helpers.projectManagers.createOne
+ .with({
+ values: {
+ project,
+ user,
+ },
+ request: this.req,
+ })
.intercept('userAlreadyProjectManager', () => Errors.USER_ALREADY_PROJECT_MANAGER);
return {
diff --git a/server/api/controllers/project-managers/delete.js b/server/api/controllers/project-managers/delete.js
index 141f11f4..5bd3f9af 100755
--- a/server/api/controllers/project-managers/delete.js
+++ b/server/api/controllers/project-managers/delete.js
@@ -38,7 +38,10 @@ module.exports = {
}
// TODO: check if the last one
- projectManager = await sails.helpers.projectManagers.deleteOne(projectManager, this.req);
+ projectManager = await sails.helpers.projectManagers.deleteOne.with({
+ record: projectManager,
+ request: this.req,
+ });
if (!projectManager) {
throw Errors.PROJECT_MANAGER_NOT_FOUND;
diff --git a/server/api/controllers/projects/create.js b/server/api/controllers/projects/create.js
index 62ef6f1a..1ce57ae8 100755
--- a/server/api/controllers/projects/create.js
+++ b/server/api/controllers/projects/create.js
@@ -11,11 +11,11 @@ module.exports = {
const values = _.pick(inputs, ['name']);
- const { project, projectManager } = await sails.helpers.projects.createOne(
+ const { project, projectManager } = await sails.helpers.projects.createOne.with({
values,
- currentUser,
- this.req,
- );
+ user: currentUser,
+ request: this.req,
+ });
return {
item: project,
diff --git a/server/api/controllers/projects/delete.js b/server/api/controllers/projects/delete.js
index 19d5de48..dedb9070 100755
--- a/server/api/controllers/projects/delete.js
+++ b/server/api/controllers/projects/delete.js
@@ -34,7 +34,10 @@ module.exports = {
throw Errors.PROJECT_NOT_FOUND; // Forbidden
}
- project = await sails.helpers.projects.deleteOne(project, this.req);
+ project = await sails.helpers.projects.deleteOne.with({
+ record: project,
+ request: this.req,
+ });
if (!project) {
throw Errors.PROJECT_NOT_FOUND;
diff --git a/server/api/controllers/projects/index.js b/server/api/controllers/projects/index.js
index b4f2123d..77843f57 100755
--- a/server/api/controllers/projects/index.js
+++ b/server/api/controllers/projects/index.js
@@ -6,7 +6,6 @@ module.exports = {
const managerProjects = await sails.helpers.projects.getMany(managerProjectIds);
let boardMemberships = await sails.helpers.users.getBoardMemberships(currentUser.id);
-
const membershipBoardIds = sails.helpers.utils.mapRecords(boardMemberships, 'boardId');
let membershipBoards = await sails.helpers.boards.getMany({
diff --git a/server/api/controllers/projects/update-background-image.js b/server/api/controllers/projects/update-background-image.js
index 5d3d7f60..85825e08 100755
--- a/server/api/controllers/projects/update-background-image.js
+++ b/server/api/controllers/projects/update-background-image.js
@@ -85,13 +85,13 @@ module.exports = {
return Errors.FILE_IS_NOT_IMAGE;
});
- project = await sails.helpers.projects.updateOne(
- project,
- {
+ project = await sails.helpers.projects.updateOne.with({
+ record: project,
+ values: {
backgroundImage: fileData,
},
- this.req,
- );
+ request: this.req,
+ });
if (!project) {
throw Errors.PROJECT_NOT_FOUND;
diff --git a/server/api/controllers/projects/update.js b/server/api/controllers/projects/update.js
index 9ca9b368..6d6e16e9 100755
--- a/server/api/controllers/projects/update.js
+++ b/server/api/controllers/projects/update.js
@@ -4,6 +4,36 @@ const Errors = {
},
};
+const backgroundValidator = (value) => {
+ if (_.isNull(value)) {
+ return true;
+ }
+
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!Object.values(Project.BackgroundTypes).includes(value.type)) {
+ return false;
+ }
+
+ if (
+ value.type === Project.BackgroundTypes.GRADIENT &&
+ _.size(value) === 2 &&
+ Project.BACKGROUND_GRADIENTS.includes(value.name)
+ ) {
+ return true;
+ }
+
+ if (value.type === Project.BackgroundTypes.IMAGE && _.size(value) === 1) {
+ return true;
+ }
+
+ return false;
+};
+
+const backgroundImageValidator = (value) => _.isNull(value);
+
module.exports = {
inputs: {
id: {
@@ -17,37 +47,11 @@ module.exports = {
},
background: {
type: 'json',
- custom: (value) => {
- if (_.isNull(value)) {
- return true;
- }
-
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!Object.values(Project.BackgroundTypes).includes(value.type)) {
- return false;
- }
-
- if (
- value.type === Project.BackgroundTypes.GRADIENT &&
- _.size(value) === 2 &&
- Project.BACKGROUND_GRADIENTS.includes(value.name)
- ) {
- return true;
- }
-
- if (value.type === Project.BackgroundTypes.IMAGE && _.size(value) === 1) {
- return true;
- }
-
- return false;
- },
+ custom: backgroundValidator,
},
backgroundImage: {
type: 'json',
- custom: (value) => _.isNull(value),
+ custom: backgroundImageValidator,
},
},
@@ -73,7 +77,12 @@ module.exports = {
}
const values = _.pick(inputs, ['name', 'background', 'backgroundImage']);
- project = await sails.helpers.projects.updateOne(project, values, this.req);
+
+ project = await sails.helpers.projects.updateOne.with({
+ values,
+ record: project,
+ request: this.req,
+ });
if (!project) {
throw Errors.PROJECT_NOT_FOUND;
diff --git a/server/api/controllers/tasks/create.js b/server/api/controllers/tasks/create.js
index d8ed009a..0d2b5a41 100755
--- a/server/api/controllers/tasks/create.js
+++ b/server/api/controllers/tasks/create.js
@@ -57,7 +57,14 @@ module.exports = {
}
const values = _.pick(inputs, ['position', 'name', 'isCompleted']);
- const task = await sails.helpers.tasks.createOne(values, card, this.req);
+
+ const task = await sails.helpers.tasks.createOne.with({
+ values: {
+ ...values,
+ card,
+ },
+ request: this.req,
+ });
return {
item: task,
diff --git a/server/api/controllers/tasks/delete.js b/server/api/controllers/tasks/delete.js
index 095173a4..c4ba0ed3 100755
--- a/server/api/controllers/tasks/delete.js
+++ b/server/api/controllers/tasks/delete.js
@@ -48,7 +48,11 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- task = await sails.helpers.tasks.deleteOne(task, board, this.req);
+ task = await sails.helpers.tasks.deleteOne.with({
+ board,
+ record: task,
+ request: this.req,
+ });
if (!task) {
throw Errors.TASK_NOT_FOUND;
diff --git a/server/api/controllers/tasks/update.js b/server/api/controllers/tasks/update.js
index 43aa7adf..9e08f76f 100755
--- a/server/api/controllers/tasks/update.js
+++ b/server/api/controllers/tasks/update.js
@@ -59,7 +59,13 @@ module.exports = {
}
const values = _.pick(inputs, ['position', 'name', 'isCompleted']);
- task = await sails.helpers.tasks.updateOne(task, values, board, this.req);
+
+ task = await sails.helpers.tasks.updateOne.with({
+ values,
+ board,
+ record: task,
+ request: this.req,
+ });
if (!task) {
throw Errors.TASK_NOT_FOUND;
diff --git a/server/api/controllers/users/create.js b/server/api/controllers/users/create.js
index 1fa0f1f5..5652ad5e 100755
--- a/server/api/controllers/users/create.js
+++ b/server/api/controllers/users/create.js
@@ -9,6 +9,8 @@ const Errors = {
},
};
+const passwordValidator = (value) => zxcvbn(value).score >= 2; // TODO: move to config
+
module.exports = {
inputs: {
email: {
@@ -18,7 +20,7 @@ module.exports = {
},
password: {
type: 'string',
- custom: (value) => zxcvbn(value).score >= 2, // TODO: move to config
+ custom: passwordValidator,
required: true,
},
name: {
@@ -74,8 +76,11 @@ module.exports = {
'subscribeToOwnCards',
]);
- const user = await sails.helpers.users
- .createOne(values, this.req)
+ const user = await sails.helpers.users.createOne
+ .with({
+ values,
+ request: this.req,
+ })
.intercept('emailAlreadyInUse', () => Errors.EMAIL_ALREADY_IN_USE)
.intercept('usernameAlreadyInUse', () => Errors.USERNAME_ALREADY_IN_USE);
diff --git a/server/api/controllers/users/delete.js b/server/api/controllers/users/delete.js
index 1353b2df..37df2d6f 100755
--- a/server/api/controllers/users/delete.js
+++ b/server/api/controllers/users/delete.js
@@ -26,7 +26,10 @@ module.exports = {
throw Errors.USER_NOT_FOUND;
}
- user = await sails.helpers.users.deleteOne(user, this.req);
+ user = await sails.helpers.users.deleteOne.with({
+ record: user,
+ request: this.req,
+ });
if (!user) {
throw Errors.USER_NOT_FOUND;
diff --git a/server/api/controllers/users/update-avatar.js b/server/api/controllers/users/update-avatar.js
index 367f6ae5..37b01f11 100755
--- a/server/api/controllers/users/update-avatar.js
+++ b/server/api/controllers/users/update-avatar.js
@@ -86,14 +86,14 @@ module.exports = {
return Errors.FILE_IS_NOT_IMAGE;
});
- user = await sails.helpers.users.updateOne(
- user,
- {
+ user = await sails.helpers.users.updateOne.with({
+ record: user,
+ values: {
avatar: fileData,
},
- currentUser,
- this.req,
- );
+ user: currentUser,
+ request: this.req,
+ });
if (!user) {
throw Errors.USER_NOT_FOUND;
diff --git a/server/api/controllers/users/update-email.js b/server/api/controllers/users/update-email.js
index 2d2cd522..a148099f 100644
--- a/server/api/controllers/users/update-email.js
+++ b/server/api/controllers/users/update-email.js
@@ -68,8 +68,13 @@ module.exports = {
const values = _.pick(inputs, ['email']);
- user = await sails.helpers.users
- .updateOne(user, values, currentUser, this.req)
+ user = await sails.helpers.users.updateOne
+ .with({
+ values,
+ record: user,
+ user: currentUser,
+ request: this.req,
+ })
.intercept('emailAlreadyInUse', () => Errors.EMAIL_ALREADY_IN_USE);
if (!user) {
diff --git a/server/api/controllers/users/update-password.js b/server/api/controllers/users/update-password.js
index 157ea16c..1cf27361 100644
--- a/server/api/controllers/users/update-password.js
+++ b/server/api/controllers/users/update-password.js
@@ -12,6 +12,8 @@ const Errors = {
},
};
+const passwordValidator = (value) => zxcvbn(value).score >= 2; // TODO: move to config
+
module.exports = {
inputs: {
id: {
@@ -21,7 +23,7 @@ module.exports = {
},
password: {
type: 'string',
- custom: (value) => zxcvbn(value).score >= 2, // TODO: move to config
+ custom: passwordValidator,
required: true,
},
currentPassword: {
@@ -64,7 +66,13 @@ module.exports = {
}
const values = _.pick(inputs, ['password']);
- user = await sails.helpers.users.updateOne(user, values, currentUser, this.req);
+
+ user = await sails.helpers.users.updateOne.with({
+ values,
+ record: user,
+ user: currentUser,
+ request: this.req,
+ });
if (!user) {
throw Errors.USER_NOT_FOUND;
diff --git a/server/api/controllers/users/update-username.js b/server/api/controllers/users/update-username.js
index f9961b3e..13fc4bc4 100644
--- a/server/api/controllers/users/update-username.js
+++ b/server/api/controllers/users/update-username.js
@@ -70,8 +70,13 @@ module.exports = {
const values = _.pick(inputs, ['username']);
- user = await sails.helpers.users
- .updateOne(user, values, currentUser, this.req)
+ user = await sails.helpers.users.updateOne
+ .with({
+ values,
+ record: user,
+ user: currentUser,
+ request: this.req,
+ })
.intercept('usernameAlreadyInUse', () => Errors.USERNAME_ALREADY_IN_USE);
if (!user) {
diff --git a/server/api/controllers/users/update.js b/server/api/controllers/users/update.js
index c1b92656..a6631027 100755
--- a/server/api/controllers/users/update.js
+++ b/server/api/controllers/users/update.js
@@ -4,6 +4,8 @@ const Errors = {
},
};
+const avatarUrlValidator = (value) => _.isNull(value);
+
module.exports = {
inputs: {
id: {
@@ -20,7 +22,7 @@ module.exports = {
},
avatarUrl: {
type: 'json',
- custom: (value) => _.isNull(value),
+ custom: avatarUrlValidator,
},
phone: {
type: 'string',
@@ -77,7 +79,12 @@ module.exports = {
avatar: inputs.avatarUrl,
};
- user = await sails.helpers.users.updateOne(user, values, currentUser, this.req);
+ user = await sails.helpers.users.updateOne.with({
+ values,
+ record: user,
+ user: currentUser,
+ request: this.req,
+ });
if (!user) {
throw Errors.USER_NOT_FOUND;
diff --git a/server/api/helpers/actions/create-one.js b/server/api/helpers/actions/create-one.js
index 66e4547f..e96df93f 100644
--- a/server/api/helpers/actions/create-one.js
+++ b/server/api/helpers/actions/create-one.js
@@ -1,15 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.card)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.user)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- required: true,
- },
- user: {
- type: 'ref',
- required: true,
- },
- card: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -18,14 +27,16 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const action = await Action.create({
- ...inputs.values,
- cardId: inputs.card.id,
- userId: inputs.user.id,
+ ...values,
+ cardId: values.card.id,
+ userId: values.user.id,
}).fetch();
sails.sockets.broadcast(
- `board:${inputs.card.boardId}`,
+ `board:${values.card.boardId}`,
'actionCreate',
{
item: action,
@@ -38,9 +49,16 @@ module.exports = {
action.userId,
);
- subscriptionUserIds.forEach(async (userId) => {
- await sails.helpers.notifications.createOne(userId, action);
- });
+ await Promise.all(
+ subscriptionUserIds.map(async (userId) =>
+ sails.helpers.notifications.createOne.with({
+ values: {
+ userId,
+ action,
+ },
+ }),
+ ),
+ );
return action;
},
diff --git a/server/api/helpers/actions/get-many.js b/server/api/helpers/actions/get-many.js
index fe9d5c09..cdf87748 100644
--- a/server/api/helpers/actions/get-many.js
+++ b/server/api/helpers/actions/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
limit: {
type: 'number',
diff --git a/server/api/helpers/actions/update-one.js b/server/api/helpers/actions/update-one.js
index 39e3a876..47d2f52e 100644
--- a/server/api/helpers/actions/update-one.js
+++ b/server/api/helpers/actions/update-one.js
@@ -18,7 +18,9 @@ module.exports = {
},
async fn(inputs) {
- const action = await Action.updateOne(inputs.record.id).set(inputs.values);
+ const { values } = inputs;
+
+ const action = await Action.updateOne(inputs.record.id).set({ ...values });
if (action) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/attachments/create-one.js b/server/api/helpers/attachments/create-one.js
index 70e19143..6ed6e6b7 100644
--- a/server/api/helpers/attachments/create-one.js
+++ b/server/api/helpers/attachments/create-one.js
@@ -1,15 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.card)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.creatorUser)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- required: true,
- },
- user: {
- type: 'ref',
- required: true,
- },
- card: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
requestId: {
@@ -22,14 +31,16 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const attachment = await Attachment.create({
- ...inputs.values,
- cardId: inputs.card.id,
- creatorUserId: inputs.user.id,
+ ...values,
+ cardId: values.card.id,
+ creatorUserId: values.creatorUser.id,
}).fetch();
sails.sockets.broadcast(
- `board:${inputs.card.boardId}`,
+ `board:${values.card.boardId}`,
'attachmentCreate',
{
item: attachment,
@@ -38,9 +49,12 @@ module.exports = {
inputs.request,
);
- if (!inputs.card.coverAttachmentId && attachment.image) {
- await sails.helpers.cards.updateOne(inputs.card, {
- coverAttachmentId: attachment.id,
+ if (!values.card.coverAttachmentId && attachment.image) {
+ await sails.helpers.cards.updateOne.with({
+ record: values.card,
+ values: {
+ coverAttachmentId: attachment.id,
+ },
});
}
diff --git a/server/api/helpers/attachments/get-many.js b/server/api/helpers/attachments/get-many.js
index 8360fbe8..8e686ce9 100644
--- a/server/api/helpers/attachments/get-many.js
+++ b/server/api/helpers/attachments/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/attachments/update-one.js b/server/api/helpers/attachments/update-one.js
index c8b7131f..ba9dd24f 100644
--- a/server/api/helpers/attachments/update-one.js
+++ b/server/api/helpers/attachments/update-one.js
@@ -18,7 +18,9 @@ module.exports = {
},
async fn(inputs) {
- const attachment = await Attachment.updateOne(inputs.record.id).set(inputs.values);
+ const { values } = inputs;
+
+ const attachment = await Attachment.updateOne(inputs.record.id).set({ ...values });
if (attachment) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/board-memberships/create-one.js b/server/api/helpers/board-memberships/create-one.js
index e43c48c5..5adf9eb2 100644
--- a/server/api/helpers/board-memberships/create-one.js
+++ b/server/api/helpers/board-memberships/create-one.js
@@ -1,15 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.board)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.user)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- required: true,
- },
- user: {
- type: 'ref',
- required: true,
- },
- board: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -22,18 +31,20 @@ module.exports = {
},
async fn(inputs) {
- if (inputs.values.role === BoardMembership.Roles.EDITOR) {
- delete inputs.values.canComment; // eslint-disable-line no-param-reassign
- } else if (inputs.values.role === BoardMembership.Roles.VIEWER) {
- if (_.isNil(inputs.values.canComment)) {
- inputs.values.canComment = false; // eslint-disable-line no-param-reassign
+ const { values } = inputs;
+
+ if (values.role === BoardMembership.Roles.EDITOR) {
+ delete values.canComment;
+ } else if (values.role === BoardMembership.Roles.VIEWER) {
+ if (_.isNil(values.canComment)) {
+ values.canComment = false;
}
}
const boardMembership = await BoardMembership.create({
- ...inputs.values,
- boardId: inputs.board.id,
- userId: inputs.user.id,
+ ...values,
+ boardId: values.board.id,
+ userId: values.user.id,
})
.intercept('E_UNIQUE', 'userAlreadyBoardMember')
.fetch();
diff --git a/server/api/helpers/board-memberships/get-many.js b/server/api/helpers/board-memberships/get-many.js
index 62194971..9c635203 100644
--- a/server/api/helpers/board-memberships/get-many.js
+++ b/server/api/helpers/board-memberships/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/board-memberships/update-one.js b/server/api/helpers/board-memberships/update-one.js
index 6b3be4e3..cb43adc8 100644
--- a/server/api/helpers/board-memberships/update-one.js
+++ b/server/api/helpers/board-memberships/update-one.js
@@ -14,21 +14,22 @@ module.exports = {
},
async fn(inputs) {
- const role = inputs.values.role || inputs.record.role;
+ const { values } = inputs;
+ const role = values.role || inputs.record.role;
if (role === BoardMembership.Roles.EDITOR) {
- inputs.values.canComment = null; // eslint-disable-line no-param-reassign
+ values.canComment = null;
} else if (role === BoardMembership.Roles.VIEWER) {
- const canComment = _.isUndefined(inputs.values.canComment)
+ const canComment = _.isUndefined(values.canComment)
? inputs.record.canComment
- : inputs.values.canComment;
+ : values.canComment;
if (_.isNull(canComment)) {
- inputs.values.canComment = false; // eslint-disable-line no-param-reassign
+ values.canComment = false;
}
}
- const boardMembership = await BoardMembership.updateOne(inputs.record.id).set(inputs.values);
+ const boardMembership = await BoardMembership.updateOne(inputs.record.id).set({ ...values });
if (boardMembership) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/boards/create-one.js b/server/api/helpers/boards/create-one.js
index 4f82ef1f..f9a43c43 100644
--- a/server/api/helpers/boards/create-one.js
+++ b/server/api/helpers/boards/create-one.js
@@ -1,25 +1,46 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isFinite(value.position)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.project)) {
+ return false;
+ }
+
+ return true;
+};
+
+const importValidator = (value) => {
+ if (!value.type || !Object.values(Board.ImportTypes).includes(value.type)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.board)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- custom: (value) => _.isPlainObject(value) && _.isFinite(value.position),
+ type: 'ref',
+ custom: valuesValidator,
required: true,
},
import: {
type: 'json',
- custom: (value) =>
- value.type &&
- Object.values(Board.ImportTypes).includes(value.type) &&
- _.isPlainObject(value.board),
+ custom: importValidator,
},
user: {
type: 'ref',
required: true,
},
- project: {
- type: 'ref',
- required: true,
- },
requestId: {
type: 'string',
isNotEmptyString: true,
@@ -30,26 +51,29 @@ module.exports = {
},
async fn(inputs) {
- const managerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.project.id);
- const boards = await sails.helpers.projects.getBoards(inputs.project.id);
+ const { values } = inputs;
+
+ const projectManagerUserIds = await sails.helpers.projects.getManagerUserIds(values.project.id);
+ const boards = await sails.helpers.projects.getBoards(values.project.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
boards,
);
repositions.forEach(async ({ id, position: nextPosition }) => {
await Board.update({
id,
- projectId: inputs.project.id,
+ projectId: values.project.id,
}).set({
position: nextPosition,
});
- const memberUserIds = await sails.helpers.boards.getMemberUserIds(id);
- const userIds = _.union(managerUserIds, memberUserIds);
+ // TODO: move out of loop
+ const boardMemberUserIds = await sails.helpers.boards.getMemberUserIds(id);
+ const boardRelatedUserIds = _.union(projectManagerUserIds, boardMemberUserIds);
- userIds.forEach((userId) => {
+ boardRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(`user:${userId}`, 'boardUpdate', {
item: {
id,
@@ -60,9 +84,9 @@ module.exports = {
});
const board = await Board.create({
- ...inputs.values,
+ ...values,
position,
- projectId: inputs.project.id,
+ projectId: values.project.id,
}).fetch();
if (inputs.import && inputs.import.type === Board.ImportTypes.TRELLO) {
@@ -75,7 +99,7 @@ module.exports = {
role: BoardMembership.Roles.EDITOR,
}).fetch();
- managerUserIds.forEach((userId) => {
+ projectManagerUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'boardCreate',
diff --git a/server/api/helpers/boards/delete-one.js b/server/api/helpers/boards/delete-one.js
index 8c61b823..4fdcc114 100644
--- a/server/api/helpers/boards/delete-one.js
+++ b/server/api/helpers/boards/delete-one.js
@@ -10,7 +10,7 @@ module.exports = {
},
async fn(inputs) {
- await BoardMembership.destroy({
+ const boardMemberships = await BoardMembership.destroy({
boardId: inputs.record.id,
}).fetch();
@@ -19,12 +19,11 @@ module.exports = {
if (board) {
sails.sockets.removeRoomMembersFromRooms(`board:${board.id}`, `board:${board.id}`);
- const managerUserIds = await sails.helpers.projects.getManagerUserIds(board.projectId);
- const memberUserIds = await sails.helpers.boards.getMemberUserIds(board.id);
+ const projectManagerUserIds = await sails.helpers.projects.getManagerUserIds(board.projectId);
+ const boardMemberUserIds = sails.helpers.utils.mapRecords(boardMemberships, 'userId');
+ const boardRelatedUserIds = _.union(projectManagerUserIds, boardMemberUserIds);
- const userIds = _.union(managerUserIds, memberUserIds);
-
- userIds.forEach((userId) => {
+ boardRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'boardDelete',
diff --git a/server/api/helpers/boards/get-board-memberships.js b/server/api/helpers/boards/get-board-memberships.js
index e57169c7..af0531d3 100644
--- a/server/api/helpers/boards/get-board-memberships.js
+++ b/server/api/helpers/boards/get-board-memberships.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/boards/get-card-ids.js b/server/api/helpers/boards/get-card-ids.js
index 27a6eaaa..28c9cb3f 100644
--- a/server/api/helpers/boards/get-card-ids.js
+++ b/server/api/helpers/boards/get-card-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/boards/get-cards.js b/server/api/helpers/boards/get-cards.js
index 6d9c77f4..e6824d20 100644
--- a/server/api/helpers/boards/get-cards.js
+++ b/server/api/helpers/boards/get-cards.js
@@ -1,41 +1,17 @@
-const LIMIT = 10;
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
module.exports = {
inputs: {
- recordOrIdOrIds: {
- type: 'ref',
- custom: (value) => _.isObjectLike(value) || _.isString(value) || _.every(value, _.isString),
+ idOrIds: {
+ type: 'json',
+ custom: idOrIdsValidator,
required: true,
},
- beforeId: {
- type: 'string',
- },
},
async fn(inputs) {
- const criteria = {};
-
- let sort;
- let limit;
-
- if (_.isObjectLike(inputs.recordOrIdOrIds)) {
- criteria.boardId = inputs.recordOrIdOrIds.id;
-
- if (inputs.recordOrIdOrIds.type === Board.Types.KANBAN) {
- sort = 'position';
- } else if (inputs.recordOrIdOrIds.type === Board.Types.COLLECTION) {
- if (inputs.beforeId) {
- criteria.id = {
- '<': inputs.beforeId,
- };
- }
-
- limit = LIMIT;
- }
- } else {
- criteria.boardId = inputs.recordOrIdOrIds;
- }
-
- return sails.helpers.cards.getMany(criteria, sort, limit);
+ return sails.helpers.cards.getMany({
+ boardId: inputs.idOrIds,
+ });
},
};
diff --git a/server/api/helpers/boards/get-labels.js b/server/api/helpers/boards/get-labels.js
index 03f97d9e..c11b75e8 100644
--- a/server/api/helpers/boards/get-labels.js
+++ b/server/api/helpers/boards/get-labels.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/boards/get-lists.js b/server/api/helpers/boards/get-lists.js
index bc74b391..b2643509 100644
--- a/server/api/helpers/boards/get-lists.js
+++ b/server/api/helpers/boards/get-lists.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptListIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
diff --git a/server/api/helpers/boards/get-many.js b/server/api/helpers/boards/get-many.js
index 251dbb49..d6600140 100644
--- a/server/api/helpers/boards/get-many.js
+++ b/server/api/helpers/boards/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/boards/get-member-user-ids.js b/server/api/helpers/boards/get-member-user-ids.js
index 3fa41516..3d11e717 100644
--- a/server/api/helpers/boards/get-member-user-ids.js
+++ b/server/api/helpers/boards/get-member-user-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/boards/update-one.js b/server/api/helpers/boards/update-one.js
index 873d5690..9b26733c 100644
--- a/server/api/helpers/boards/update-one.js
+++ b/server/api/helpers/boards/update-one.js
@@ -1,3 +1,15 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -6,17 +18,7 @@ module.exports = {
},
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
request: {
@@ -25,23 +27,27 @@ module.exports = {
},
async fn(inputs) {
- const managerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.record.projectId);
- const memberUserIds = await sails.helpers.boards.getMemberUserIds(inputs.record.id);
+ const { values } = inputs;
- const userIds = _.union(managerUserIds, memberUserIds);
+ const projectManagerUserIds = await sails.helpers.projects.getManagerUserIds(
+ inputs.record.projectId,
+ );
- if (!_.isUndefined(inputs.values.position)) {
+ const boardMemberUserIds = await sails.helpers.boards.getMemberUserIds(inputs.record.id);
+ const boardRelatedUserIds = _.union(projectManagerUserIds, boardMemberUserIds);
+
+ if (!_.isUndefined(values.position)) {
const boards = await sails.helpers.projects.getBoards(
inputs.record.projectId,
inputs.record.id,
);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
boards,
);
- inputs.values.position = position; // eslint-disable-line no-param-reassign
+ values.position = position;
repositions.forEach(async ({ id, position: nextPosition }) => {
await Board.update({
@@ -51,7 +57,7 @@ module.exports = {
position: nextPosition,
});
- userIds.forEach((userId) => {
+ boardRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(`user:${userId}`, 'boardUpdate', {
item: {
id,
@@ -62,10 +68,10 @@ module.exports = {
});
}
- const board = await Board.updateOne(inputs.record.id).set(inputs.values);
+ const board = await Board.updateOne(inputs.record.id).set({ ...values });
if (board) {
- userIds.forEach((userId) => {
+ boardRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'boardUpdate',
diff --git a/server/api/helpers/card-labels/create-one.js b/server/api/helpers/card-labels/create-one.js
index a90be460..f0cde82c 100644
--- a/server/api/helpers/card-labels/create-one.js
+++ b/server/api/helpers/card-labels/create-one.js
@@ -1,11 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.card)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.label)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
- label: {
- type: 'ref',
- required: true,
- },
- card: {
+ values: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -18,15 +31,18 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const cardLabel = await CardLabel.create({
- cardId: inputs.card.id,
- labelId: inputs.label.id,
+ ...values,
+ cardId: values.card.id,
+ labelId: values.label.id,
})
.intercept('E_UNIQUE', 'labelAlreadyInCard')
.fetch();
sails.sockets.broadcast(
- `board:${inputs.card.boardId}`,
+ `board:${values.card.boardId}`,
'cardLabelCreate',
{
item: cardLabel,
diff --git a/server/api/helpers/card-labels/get-many.js b/server/api/helpers/card-labels/get-many.js
index a63ce708..fca12713 100644
--- a/server/api/helpers/card-labels/get-many.js
+++ b/server/api/helpers/card-labels/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/card-memberships/create-one.js b/server/api/helpers/card-memberships/create-one.js
index 75371fc8..bb92b9fd 100644
--- a/server/api/helpers/card-memberships/create-one.js
+++ b/server/api/helpers/card-memberships/create-one.js
@@ -1,12 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.card)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.user) && !_.isString(value.userId)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
- userOrId: {
- type: 'ref',
- custom: (value) => _.isObjectLike(value) || _.isString(value),
- required: true,
- },
- card: {
+ values: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -19,17 +31,21 @@ module.exports = {
},
async fn(inputs) {
- const { userId = inputs.userOrId } = inputs.userOrId;
+ const { values } = inputs;
+
+ if (values.user) {
+ values.userId = values.user.id;
+ }
const cardMembership = await CardMembership.create({
- userId,
- cardId: inputs.card.id,
+ ...values,
+ cardId: values.card.id,
})
.intercept('E_UNIQUE', 'userAlreadyCardMember')
.fetch();
sails.sockets.broadcast(
- `board:${inputs.card.boardId}`,
+ `board:${values.card.boardId}`,
'cardMembershipCreate',
{
item: cardMembership,
diff --git a/server/api/helpers/card-memberships/get-many.js b/server/api/helpers/card-memberships/get-many.js
index 8faf648a..8edfe4df 100644
--- a/server/api/helpers/card-memberships/get-many.js
+++ b/server/api/helpers/card-memberships/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/card-subscriptions/get-many.js b/server/api/helpers/card-subscriptions/get-many.js
index 8272bad4..90cbf4ba 100644
--- a/server/api/helpers/card-subscriptions/get-many.js
+++ b/server/api/helpers/card-subscriptions/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/cards/create-one.js b/server/api/helpers/cards/create-one.js
index 141da13f..0999c27d 100644
--- a/server/api/helpers/cards/create-one.js
+++ b/server/api/helpers/cards/create-one.js
@@ -1,92 +1,75 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isFinite(value.position)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.list)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.creatorUser)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
- return false;
- }
-
- return true;
- },
- required: true,
- },
- user: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
- board: {
- type: 'ref',
- required: true,
- },
- list: {
- type: 'ref',
- },
request: {
type: 'ref',
},
},
exits: {
- listMustBePresent: {},
- listMustBelongToBoard: {},
positionMustBeInValues: {},
},
async fn(inputs) {
const { values } = inputs;
- if (inputs.board.type === Board.Types.KANBAN) {
- if (!inputs.list) {
- throw 'listMustBePresent';
- }
+ if (_.isUndefined(values.position)) {
+ throw 'positionMustBeInValues';
+ }
- if (inputs.list.boardId !== inputs.board.id) {
- throw 'listMustBelongToBoard';
- }
+ const cards = await sails.helpers.lists.getCards(values.list.id);
- values.listId = inputs.list.id;
+ const { position, repositions } = sails.helpers.utils.insertToPositionables(
+ values.position,
+ cards,
+ );
- if (_.isUndefined(values.position)) {
- throw 'positionMustBeInValues';
- }
-
- const cards = await sails.helpers.lists.getCards(inputs.list.id);
-
- const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
- cards,
- );
-
- repositions.forEach(async ({ id, position: nextPosition }) => {
- await Card.update({
- id,
- listId: inputs.list.id,
- }).set({
- position: nextPosition,
- });
-
- sails.sockets.broadcast(`board:${inputs.board.id}`, 'cardUpdate', {
- item: {
- id,
- position: nextPosition,
- },
- });
+ repositions.forEach(async ({ id, position: nextPosition }) => {
+ await Card.update({
+ id,
+ listId: values.list.id,
+ }).set({
+ position: nextPosition,
});
- values.position = position;
- } else if (inputs.board.type === Board.Types.COLLECTION) {
- delete values.position;
- }
+ sails.sockets.broadcast(`board:${values.list.boardId}`, 'cardUpdate', {
+ item: {
+ id,
+ position: nextPosition,
+ },
+ });
+ });
const card = await Card.create({
...values,
- boardId: inputs.board.id,
- creatorUserId: inputs.user.id,
+ position,
+ boardId: values.list.boardId,
+ listId: values.list.id,
+ creatorUserId: values.creatorUser.id,
}).fetch();
sails.sockets.broadcast(
@@ -98,13 +81,13 @@ module.exports = {
inputs.request,
);
- if (inputs.user.subscribeToOwnCards) {
+ if (values.creatorUser.subscribeToOwnCards) {
await CardSubscription.create({
cardId: card.id,
- userId: inputs.user.id,
+ userId: card.creatorUserId,
}).tolerate('E_UNIQUE');
- sails.sockets.broadcast(`user:${inputs.user.id}`, 'cardUpdate', {
+ sails.sockets.broadcast(`user:${card.creatorUserId}`, 'cardUpdate', {
item: {
id: card.id,
isSubscribed: true,
@@ -112,16 +95,16 @@ module.exports = {
});
}
- await sails.helpers.actions.createOne(
- {
+ await sails.helpers.actions.createOne.with({
+ values: {
+ card,
type: Action.Types.CREATE_CARD,
data: {
- list: _.pick(inputs.list, ['id', 'name']),
+ list: _.pick(values.list, ['id', 'name']),
},
+ user: values.creatorUser,
},
- inputs.user,
- card,
- );
+ });
return card;
},
diff --git a/server/api/helpers/cards/get-actions.js b/server/api/helpers/cards/get-actions.js
index 69c5dcbe..bd04bf76 100644
--- a/server/api/helpers/cards/get-actions.js
+++ b/server/api/helpers/cards/get-actions.js
@@ -1,10 +1,12 @@
const LIMIT = 50;
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
beforeId: {
diff --git a/server/api/helpers/cards/get-attachments.js b/server/api/helpers/cards/get-attachments.js
index 6ddbd471..93b17be7 100644
--- a/server/api/helpers/cards/get-attachments.js
+++ b/server/api/helpers/cards/get-attachments.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/cards/get-card-labels.js b/server/api/helpers/cards/get-card-labels.js
index 7fe7aab6..1e80447b 100644
--- a/server/api/helpers/cards/get-card-labels.js
+++ b/server/api/helpers/cards/get-card-labels.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/cards/get-card-memberships.js b/server/api/helpers/cards/get-card-memberships.js
index dd3e98bd..10b970f7 100644
--- a/server/api/helpers/cards/get-card-memberships.js
+++ b/server/api/helpers/cards/get-card-memberships.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/cards/get-card-subscriptions.js b/server/api/helpers/cards/get-card-subscriptions.js
index 3ba8960d..8a3d39e4 100644
--- a/server/api/helpers/cards/get-card-subscriptions.js
+++ b/server/api/helpers/cards/get-card-subscriptions.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptUserIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
diff --git a/server/api/helpers/cards/get-label-ids.js b/server/api/helpers/cards/get-label-ids.js
index 492ec031..a9a8fed6 100644
--- a/server/api/helpers/cards/get-label-ids.js
+++ b/server/api/helpers/cards/get-label-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/cards/get-labels.js b/server/api/helpers/cards/get-labels.js
index 517e629a..7fb4c66d 100644
--- a/server/api/helpers/cards/get-labels.js
+++ b/server/api/helpers/cards/get-labels.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/cards/get-many.js b/server/api/helpers/cards/get-many.js
index 76884f36..72009236 100644
--- a/server/api/helpers/cards/get-many.js
+++ b/server/api/helpers/cards/get-many.js
@@ -1,19 +1,14 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
- },
- sort: {
- type: 'json',
- defaultsTo: 'id DESC',
- },
- limit: {
- type: 'number',
+ custom: criteriaValidator,
},
},
async fn(inputs) {
- return Card.find(inputs.criteria).sort(inputs.sort).limit(inputs.limit);
+ return Card.find(inputs.criteria).sort('position');
},
};
diff --git a/server/api/helpers/cards/get-project-path.js b/server/api/helpers/cards/get-project-path.js
index b1652166..1b5d16cd 100644
--- a/server/api/helpers/cards/get-project-path.js
+++ b/server/api/helpers/cards/get-project-path.js
@@ -17,26 +17,14 @@ module.exports = {
throw 'pathNotFound';
}
- let path;
- if (card.listId) {
- path = await sails.helpers.lists
- .getProjectPath(card.listId)
- .intercept('pathNotFound', (nodes) => ({
- pathNotFound: {
- card,
- ...nodes,
- },
- }));
- } else {
- path = await sails.helpers.boards
- .getProjectPath(card.boardId)
- .intercept('pathNotFound', (nodes) => ({
- pathNotFound: {
- card,
- ...nodes,
- },
- }));
- }
+ const path = await sails.helpers.lists
+ .getProjectPath(card.listId)
+ .intercept('pathNotFound', (nodes) => ({
+ pathNotFound: {
+ card,
+ ...nodes,
+ },
+ }));
return {
card,
diff --git a/server/api/helpers/cards/get-subscription-user-ids.js b/server/api/helpers/cards/get-subscription-user-ids.js
index 493ca1a0..8ed4d8a5 100644
--- a/server/api/helpers/cards/get-subscription-user-ids.js
+++ b/server/api/helpers/cards/get-subscription-user-ids.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptUserIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
diff --git a/server/api/helpers/cards/get-tasks.js b/server/api/helpers/cards/get-tasks.js
index 10b921bf..51955876 100644
--- a/server/api/helpers/cards/get-tasks.js
+++ b/server/api/helpers/cards/get-tasks.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptTaskIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
diff --git a/server/api/helpers/cards/update-one.js b/server/api/helpers/cards/update-one.js
index 42e1b182..7f86892d 100644
--- a/server/api/helpers/cards/update-one.js
+++ b/server/api/helpers/cards/update-one.js
@@ -1,3 +1,23 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.board) && !_.isPlainObject(value.board)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.list) && !_.isPlainObject(value.list)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -5,25 +25,9 @@ module.exports = {
required: true,
},
values: {
- type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
- return false;
- }
-
- return true;
- },
- defaultsTo: {},
- },
- nextBoard: {
- type: 'ref',
- },
- nextList: {
type: 'ref',
+ custom: valuesValidator,
+ required: true,
},
user: {
type: 'ref',
@@ -40,68 +44,58 @@ module.exports = {
},
exits: {
+ positionMustBeInValues: {},
+ listMustBeInValues: {},
+ listInValuesMustBelongToBoard: {},
+ userMustBePresent: {},
boardMustBePresent: {},
listMustBePresent: {},
- nextListMustBelongToBoard: {},
- nextListMustBePresent: {},
- positionMustBeInValues: {},
- userMustBePresent: {},
},
async fn(inputs) {
const { isSubscribed, ...values } = inputs.values;
- if (inputs.nextBoard || inputs.nextList || !_.isUndefined(values.position)) {
+ if (values.board || values.list || !_.isUndefined(values.position)) {
if (!inputs.board) {
throw 'boardMustBePresent';
}
- if (inputs.nextBoard) {
- if (inputs.nextBoard.id === inputs.board.id) {
- delete inputs.nextBoard; // eslint-disable-line no-param-reassign
+ if (values.board) {
+ if (values.board.id === inputs.board.id) {
+ delete values.board;
} else {
- values.boardId = inputs.nextBoard.id;
+ values.boardId = values.board.id;
}
}
- const board = inputs.nextBoard || inputs.board;
+ const board = values.board || inputs.board;
- if (inputs.nextList) {
- if (inputs.board.type === Board.Types.KANBAN && !inputs.list) {
+ if (values.list) {
+ if (!inputs.list) {
throw 'listMustBePresent';
}
- if (inputs.nextList.boardId !== board.id) {
- throw 'nextListMustBelongToBoard';
+ if (values.list.boardId !== board.id) {
+ throw 'listInValuesMustBelongToBoard';
}
- if (
- board.type === Board.Types.COLLECTION ||
- (inputs.board.type === Board.Types.KANBAN && inputs.nextList.id === inputs.list.id)
- ) {
- delete inputs.nextList; // eslint-disable-line no-param-reassign
+ if (values.list.id === inputs.list.id) {
+ delete values.list;
} else {
- values.listId = inputs.nextList.id;
+ values.listId = values.list.id;
}
}
- if (inputs.nextList) {
+ if (values.list) {
if (_.isUndefined(values.position)) {
throw 'positionMustBeInValues';
}
- } else if (inputs.nextBoard) {
- if (inputs.nextBoard.type === Board.Types.KANBAN) {
- throw 'nextListMustBePresent';
- }
-
- if (inputs.board.type === Board.Types.KANBAN) {
- values.listId = null;
- values.position = null;
- }
+ } else if (values.board) {
+ throw 'listMustBeInValues';
}
}
- if ((!_.isUndefined(isSubscribed) || inputs.nextBoard || inputs.nextList) && !inputs.user) {
+ if ((!_.isUndefined(isSubscribed) || values.board || values.list) && !inputs.user) {
throw 'userMustBePresent';
}
@@ -116,6 +110,8 @@ module.exports = {
cards,
);
+ values.position = position;
+
repositions.forEach(async ({ id, position: nextPosition }) => {
await Card.update({
id,
@@ -131,31 +127,29 @@ module.exports = {
},
});
});
-
- values.position = position;
}
let card;
- if (!_.isEmpty(values)) {
+ if (_.isEmpty(values)) {
+ card = inputs.record;
+ } else {
let prevLabels;
- if (inputs.nextBoard) {
- if (inputs.nextBoard.projectId !== inputs.board.projectId) {
- const memberUserIds = await sails.helpers.boards.getMemberUserIds(inputs.nextBoard.id);
+ if (values.board) {
+ const boardMemberUserIds = await sails.helpers.boards.getMemberUserIds(values.board.id);
- await CardSubscription.destroy({
- cardId: inputs.record.id,
- userId: {
- '!=': memberUserIds,
- },
- });
+ await CardSubscription.destroy({
+ cardId: inputs.record.id,
+ userId: {
+ '!=': boardMemberUserIds,
+ },
+ });
- await CardMembership.destroy({
- cardId: inputs.record.id,
- userId: {
- '!=': memberUserIds,
- },
- });
- }
+ await CardMembership.destroy({
+ cardId: inputs.record.id,
+ userId: {
+ '!=': boardMemberUserIds,
+ },
+ });
prevLabels = await sails.helpers.cards.getLabels(inputs.record.id);
@@ -164,26 +158,28 @@ module.exports = {
});
}
- card = await Card.updateOne(inputs.record.id).set(values);
+ card = await Card.updateOne(inputs.record.id).set({ ...values });
if (!card) {
return card;
}
- if (inputs.nextBoard) {
+ if (values.board) {
const labels = await sails.helpers.boards.getLabels(card.boardId);
- const labelByNameMap = _.keyBy(labels, 'name');
+ const labelByName = _.keyBy(labels, 'name');
const labelIds = await Promise.all(
- prevLabels.map(async (prevLabel) => {
- if (labelByNameMap[prevLabel.name]) {
- return labelByNameMap[prevLabel.name].id;
+ prevLabels.map(async (label) => {
+ if (labelByName[label.name]) {
+ return labelByName[label.name].id;
}
- const { id } = await sails.helpers.labels.createOne(
- _.omit(prevLabel, ['id', 'boardId']),
- inputs.nextBoard,
- );
+ const { id } = await sails.helpers.labels.createOne.with({
+ values: {
+ ..._.omit(label, ['id', 'boardId']),
+ board: values.board,
+ },
+ });
return id;
}),
@@ -225,31 +221,27 @@ module.exports = {
);
}
- if (!inputs.nextBoard && inputs.nextList) {
- // TODO: add transfer action
- await sails.helpers.actions.createOne(
- {
+ if (!values.board && values.list) {
+ await sails.helpers.actions.createOne.with({
+ values: {
+ card,
+ user: inputs.user,
type: Action.Types.MOVE_CARD,
data: {
fromList: _.pick(inputs.list, ['id', 'name']),
- toList: _.pick(inputs.nextList, ['id', 'name']),
+ toList: _.pick(values.list, ['id', 'name']),
},
},
- inputs.user,
- card,
- );
+ });
}
- } else {
- card = inputs.record;
+
+ // TODO: add transfer action
}
if (!_.isUndefined(isSubscribed)) {
- const cardSubscription = await CardSubscription.findOne({
- cardId: card.id,
- userId: inputs.user.id,
- });
+ const prevIsSubscribed = await sails.helpers.users.isCardSubscriber(inputs.user.id, card.id);
- if (isSubscribed !== !!cardSubscription) {
+ if (isSubscribed !== prevIsSubscribed) {
if (isSubscribed) {
await CardSubscription.create({
cardId: card.id,
diff --git a/server/api/helpers/labels/create-one.js b/server/api/helpers/labels/create-one.js
index f6fd6414..564d31af 100644
--- a/server/api/helpers/labels/create-one.js
+++ b/server/api/helpers/labels/create-one.js
@@ -1,11 +1,20 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.board)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- required: true,
- },
- board: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -14,9 +23,11 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const label = await Label.create({
- ...inputs.values,
- boardId: inputs.board.id,
+ ...values,
+ boardId: values.board.id,
}).fetch();
sails.sockets.broadcast(
diff --git a/server/api/helpers/labels/get-many.js b/server/api/helpers/labels/get-many.js
index 9dd16454..35442998 100644
--- a/server/api/helpers/labels/get-many.js
+++ b/server/api/helpers/labels/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/labels/update-one.js b/server/api/helpers/labels/update-one.js
index 9eb7a143..b4a823a3 100644
--- a/server/api/helpers/labels/update-one.js
+++ b/server/api/helpers/labels/update-one.js
@@ -14,7 +14,9 @@ module.exports = {
},
async fn(inputs) {
- const label = await Label.updateOne(inputs.record.id).set(inputs.values);
+ const { values } = inputs;
+
+ const label = await Label.updateOne(inputs.record.id).set({ ...values });
if (label) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/lists/create-one.js b/server/api/helpers/lists/create-one.js
index bec9dcea..95c258b3 100644
--- a/server/api/helpers/lists/create-one.js
+++ b/server/api/helpers/lists/create-one.js
@@ -1,12 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isFinite(value.position)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.board)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- custom: (value) => _.isPlainObject(value) && _.isFinite(value.position),
- required: true,
- },
- board: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -15,22 +27,24 @@ module.exports = {
},
async fn(inputs) {
- const lists = await sails.helpers.boards.getLists(inputs.board.id);
+ const { values } = inputs;
+
+ const lists = await sails.helpers.boards.getLists(values.board.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
lists,
);
repositions.forEach(async ({ id, position: nextPosition }) => {
await List.update({
id,
- boardId: inputs.board.id,
+ boardId: values.board.id,
}).set({
position: nextPosition,
});
- sails.sockets.broadcast(`board:${inputs.board.id}`, 'listUpdate', {
+ sails.sockets.broadcast(`board:${values.board.id}`, 'listUpdate', {
item: {
id,
position: nextPosition,
@@ -39,9 +53,9 @@ module.exports = {
});
const list = await List.create({
- ...inputs.values,
+ ...values,
position,
- boardId: inputs.board.id,
+ boardId: values.board.id,
}).fetch();
sails.sockets.broadcast(
diff --git a/server/api/helpers/lists/get-cards.js b/server/api/helpers/lists/get-cards.js
index ea0e495c..5b396f9d 100644
--- a/server/api/helpers/lists/get-cards.js
+++ b/server/api/helpers/lists/get-cards.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptCardIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
@@ -22,6 +24,6 @@ module.exports = {
};
}
- return sails.helpers.cards.getMany(criteria, 'position');
+ return sails.helpers.cards.getMany(criteria);
},
};
diff --git a/server/api/helpers/lists/get-many.js b/server/api/helpers/lists/get-many.js
index be8161a7..e3e597a3 100644
--- a/server/api/helpers/lists/get-many.js
+++ b/server/api/helpers/lists/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/lists/update-one.js b/server/api/helpers/lists/update-one.js
index f55fabda..6b2b0e8f 100644
--- a/server/api/helpers/lists/update-one.js
+++ b/server/api/helpers/lists/update-one.js
@@ -1,3 +1,15 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -6,17 +18,7 @@ module.exports = {
},
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
request: {
@@ -25,15 +27,17 @@ module.exports = {
},
async fn(inputs) {
- if (!_.isUndefined(inputs.values.position)) {
+ const { values } = inputs;
+
+ if (!_.isUndefined(values.position)) {
const lists = await sails.helpers.boards.getLists(inputs.record.boardId, inputs.record.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
lists,
);
- inputs.values.position = position; // eslint-disable-line no-param-reassign
+ values.position = position;
repositions.forEach(async ({ id, position: nextPosition }) => {
await List.update({
@@ -52,7 +56,7 @@ module.exports = {
});
}
- const list = await List.updateOne(inputs.record.id).set(inputs.values);
+ const list = await List.updateOne(inputs.record.id).set({ ...values });
if (list) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/notifications/create-one.js b/server/api/helpers/notifications/create-one.js
index d86b5c50..cc6a0b63 100644
--- a/server/api/helpers/notifications/create-one.js
+++ b/server/api/helpers/notifications/create-one.js
@@ -1,26 +1,42 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.user) && !_.isString(value.userId)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.action)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
- userOrId: {
- type: 'ref',
- custom: (value) => _.isObjectLike(value) || _.isString(value),
- required: true,
- },
- action: {
+ values: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
},
async fn(inputs) {
- const { userId = inputs.userOrId } = inputs.userOrId;
+ const { values } = inputs;
+
+ if (values.user) {
+ values.userId = values.user.id;
+ }
const notification = await Notification.create({
- userId,
- actionId: inputs.action.id,
- cardId: inputs.action.cardId,
+ ...values,
+ actionId: values.action.id,
+ cardId: values.action.cardId,
}).fetch();
- sails.sockets.broadcast(`user:${userId}`, 'notificationCreate', {
+ sails.sockets.broadcast(`user:${notification.userId}`, 'notificationCreate', {
item: notification,
});
diff --git a/server/api/helpers/notifications/get-many.js b/server/api/helpers/notifications/get-many.js
index 5dd24dc1..c16e6614 100644
--- a/server/api/helpers/notifications/get-many.js
+++ b/server/api/helpers/notifications/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/notifications/update-many.js b/server/api/helpers/notifications/update-many.js
index 30b8bd7f..fee2c024 100644
--- a/server/api/helpers/notifications/update-many.js
+++ b/server/api/helpers/notifications/update-many.js
@@ -1,8 +1,11 @@
+const recordsOrIdsValidator = (value) =>
+ _.every(value, _.isPlainObject) || _.every(value, _.isString);
+
module.exports = {
inputs: {
recordsOrIds: {
type: 'json',
- custom: (value) => _.every(value, _.isObjectLike) || _.every(value, _.isString),
+ custom: recordsOrIdsValidator,
required: true,
},
values: {
@@ -18,9 +21,11 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const criteria = {};
- if (_.every(inputs.recordsOrIds, _.isObjectLike)) {
+ if (_.every(inputs.recordsOrIds, _.isPlainObject)) {
criteria.id = sails.helpers.utils.mapRecords(inputs.recordsOrIds);
} else if (_.every(inputs.recordsOrIds, _.isString)) {
criteria.id = inputs.recordsOrIds;
@@ -30,7 +35,9 @@ module.exports = {
criteria.userId = inputs.user.id;
}
- const notifications = await Notification.update(criteria).set(inputs.values).fetch();
+ const notifications = await Notification.update(criteria)
+ .set({ ...values })
+ .fetch();
notifications.forEach((notification) => {
sails.sockets.broadcast(
diff --git a/server/api/helpers/project-managers/create-one.js b/server/api/helpers/project-managers/create-one.js
index 40a12833..56929d18 100644
--- a/server/api/helpers/project-managers/create-one.js
+++ b/server/api/helpers/project-managers/create-one.js
@@ -1,11 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.project)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.user)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
- user: {
- type: 'ref',
- required: true,
- },
- project: {
+ values: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -18,18 +31,20 @@ module.exports = {
},
async fn(inputs) {
+ const { values } = inputs;
+
const projectManager = await ProjectManager.create({
- projectId: inputs.project.id,
- userId: inputs.user.id,
+ projectId: values.project.id,
+ userId: values.user.id,
})
.intercept('E_UNIQUE', 'userAlreadyProjectManager')
.fetch();
- const userIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
+ const projectRelatedUserIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
projectManager.projectId,
);
- userIds.forEach((userId) => {
+ projectRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'projectManagerCreate',
diff --git a/server/api/helpers/project-managers/delete-one.js b/server/api/helpers/project-managers/delete-one.js
index 1bfda99c..3677836d 100644
--- a/server/api/helpers/project-managers/delete-one.js
+++ b/server/api/helpers/project-managers/delete-one.js
@@ -10,14 +10,14 @@ module.exports = {
},
async fn(inputs) {
- const userIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
+ const projectRelatedUserIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
inputs.record.projectId,
);
const projectManager = await ProjectManager.destroyOne(inputs.record.id);
if (projectManager) {
- userIds.forEach((userId) => {
+ projectRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'projectManagerDelete',
diff --git a/server/api/helpers/project-managers/get-many.js b/server/api/helpers/project-managers/get-many.js
index 0f9b6f04..362b3046 100644
--- a/server/api/helpers/project-managers/get-many.js
+++ b/server/api/helpers/project-managers/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/projects/create-one.js b/server/api/helpers/projects/create-one.js
index 3887225a..fb97f007 100644
--- a/server/api/helpers/projects/create-one.js
+++ b/server/api/helpers/projects/create-one.js
@@ -14,7 +14,9 @@ module.exports = {
},
async fn(inputs) {
- const project = await Project.create(inputs.values).fetch();
+ const { values } = inputs;
+
+ const project = await Project.create({ ...values }).fetch();
const projectManager = await ProjectManager.create({
projectId: project.id,
diff --git a/server/api/helpers/projects/delete-one.js b/server/api/helpers/projects/delete-one.js
index a73ece27..3328f2f0 100644
--- a/server/api/helpers/projects/delete-one.js
+++ b/server/api/helpers/projects/delete-one.js
@@ -17,15 +17,15 @@ module.exports = {
const project = await Project.archiveOne(inputs.record.id);
if (project) {
- const managerUserIds = sails.helpers.utils.mapRecords(projectManagers, 'userId');
+ const projectManagerUserIds = sails.helpers.utils.mapRecords(projectManagers, 'userId');
const boardIds = await sails.helpers.projects.getBoardIds(project.id);
const boardRooms = boardIds.map((boardId) => `board:${boardId}`);
- const memberUserIds = await sails.helpers.boards.getMemberUserIds(boardIds);
- const userIds = _.union(managerUserIds, memberUserIds);
+ const boardMemberUserIds = await sails.helpers.boards.getMemberUserIds(boardIds);
+ const projectRelatedUserIds = _.union(projectManagerUserIds, boardMemberUserIds);
- userIds.forEach((userId) => {
+ projectRelatedUserIds.forEach((userId) => {
sails.sockets.removeRoomMembersFromRooms(`@user:${userId}`, boardRooms);
sails.sockets.broadcast(
diff --git a/server/api/helpers/projects/get-board-ids.js b/server/api/helpers/projects/get-board-ids.js
index 70de411b..a00595c6 100644
--- a/server/api/helpers/projects/get-board-ids.js
+++ b/server/api/helpers/projects/get-board-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/projects/get-board-member-user-ids.js b/server/api/helpers/projects/get-board-member-user-ids.js
index 3be02071..adabeaf4 100644
--- a/server/api/helpers/projects/get-board-member-user-ids.js
+++ b/server/api/helpers/projects/get-board-member-user-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/projects/get-boards.js b/server/api/helpers/projects/get-boards.js
index 641dfe87..b5084f4a 100644
--- a/server/api/helpers/projects/get-boards.js
+++ b/server/api/helpers/projects/get-boards.js
@@ -1,13 +1,15 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
exceptBoardIdOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
},
},
diff --git a/server/api/helpers/projects/get-manager-and-board-member-user-ids.js b/server/api/helpers/projects/get-manager-and-board-member-user-ids.js
index 86b207dd..560d8b86 100644
--- a/server/api/helpers/projects/get-manager-and-board-member-user-ids.js
+++ b/server/api/helpers/projects/get-manager-and-board-member-user-ids.js
@@ -1,16 +1,18 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
async fn(inputs) {
- const managerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.idOrIds);
- const memberUserIds = await sails.helpers.projects.getBoardMemberUserIds(inputs.idOrIds);
+ const projectManagerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.idOrIds);
+ const boardMemberUserIds = await sails.helpers.projects.getBoardMemberUserIds(inputs.idOrIds);
- return _.union(managerUserIds, memberUserIds);
+ return _.union(projectManagerUserIds, boardMemberUserIds);
},
};
diff --git a/server/api/helpers/projects/get-manager-user-ids.js b/server/api/helpers/projects/get-manager-user-ids.js
index 46d7a3e8..677f5183 100644
--- a/server/api/helpers/projects/get-manager-user-ids.js
+++ b/server/api/helpers/projects/get-manager-user-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/projects/get-many.js b/server/api/helpers/projects/get-many.js
index be28e289..6cb951f1 100644
--- a/server/api/helpers/projects/get-many.js
+++ b/server/api/helpers/projects/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/projects/get-project-managers.js b/server/api/helpers/projects/get-project-managers.js
index 75cf93b1..ccf2e64e 100644
--- a/server/api/helpers/projects/get-project-managers.js
+++ b/server/api/helpers/projects/get-project-managers.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/projects/update-one.js b/server/api/helpers/projects/update-one.js
index 6b4f8ef7..e14c8a40 100644
--- a/server/api/helpers/projects/update-one.js
+++ b/server/api/helpers/projects/update-one.js
@@ -1,6 +1,22 @@
const path = require('path');
const rimraf = require('rimraf');
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (value.background && !_.isPlainObject(value.background)) {
+ return false;
+ }
+
+ if (value.backgroundImage && !_.isPlainObject(value.backgroundImage)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -9,21 +25,7 @@ module.exports = {
},
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (value.background && !_.isPlainObject(value.background)) {
- return false;
- }
-
- if (value.backgroundImage && !_.isPlainObject(value.backgroundImage)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
request: {
@@ -32,45 +34,46 @@ module.exports = {
},
exits: {
- backgroundImageMustBeNotNullInValues: {},
+ backgroundImageInValuesMustNotBeNull: {},
},
async fn(inputs) {
- if (inputs.values.backgroundImage) {
- // eslint-disable-next-line no-param-reassign
- inputs.values.background = {
+ const { values } = inputs;
+
+ if (values.backgroundImage) {
+ values.background = {
type: 'image',
};
} else if (
- _.isNull(inputs.values.backgroundImage) &&
+ _.isNull(values.backgroundImage) &&
inputs.record.background &&
inputs.record.background.type === 'image'
) {
- inputs.values.background = null; // eslint-disable-line no-param-reassign
+ values.background = null;
}
let project;
- if (inputs.values.background && inputs.values.background.type === 'image') {
- if (_.isNull(inputs.values.backgroundImage)) {
- throw 'backgroundImageMustBeNotNullInValues';
+ if (values.background && values.background.type === 'image') {
+ if (_.isNull(values.backgroundImage)) {
+ throw 'backgroundImageInValuesMustNotBeNull';
}
- if (_.isUndefined(inputs.values.backgroundImage)) {
+ if (_.isUndefined(values.backgroundImage)) {
project = await Project.updateOne({
id: inputs.record.id,
backgroundImage: {
'!=': null,
},
- }).set(inputs.values);
+ }).set({ ...values });
if (!project) {
- delete inputs.values.background; // eslint-disable-line no-param-reassign
+ delete values.background;
}
}
}
if (!project) {
- project = await Project.updateOne(inputs.record.id).set(inputs.values);
+ project = await Project.updateOne(inputs.record.id).set({ ...values });
}
if (project) {
@@ -91,9 +94,11 @@ module.exports = {
}
}
- const userIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(project.id);
+ const projectRelatedUserIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
+ project.id,
+ );
- userIds.forEach((userId) => {
+ projectRelatedUserIds.forEach((userId) => {
sails.sockets.broadcast(
`user:${userId}`,
'projectUpdate',
diff --git a/server/api/helpers/tasks/create-one.js b/server/api/helpers/tasks/create-one.js
index bed7c900..c42b0077 100644
--- a/server/api/helpers/tasks/create-one.js
+++ b/server/api/helpers/tasks/create-one.js
@@ -1,12 +1,24 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isFinite(value.position)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.card)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
- type: 'json',
- custom: (value) => _.isPlainObject(value) && _.isFinite(value.position),
- required: true,
- },
- card: {
type: 'ref',
+ custom: valuesValidator,
required: true,
},
request: {
@@ -15,22 +27,24 @@ module.exports = {
},
async fn(inputs) {
- const tasks = await sails.helpers.cards.getTasks(inputs.card.id);
+ const { values } = inputs;
+
+ const tasks = await sails.helpers.cards.getTasks(values.card.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
tasks,
);
repositions.forEach(async ({ id, position: nextPosition }) => {
await Task.update({
id,
- cardId: inputs.card.id,
+ cardId: values.card.id,
}).set({
position: nextPosition,
});
- sails.sockets.broadcast(`board:${inputs.card.boardId}`, 'taskUpdate', {
+ sails.sockets.broadcast(`board:${values.card.boardId}`, 'taskUpdate', {
item: {
id,
position: nextPosition,
@@ -39,13 +53,13 @@ module.exports = {
});
const task = await Task.create({
- ...inputs.values,
+ ...values,
position,
- cardId: inputs.card.id,
+ cardId: values.card.id,
}).fetch();
sails.sockets.broadcast(
- `board:${inputs.card.boardId}`,
+ `board:${values.card.boardId}`,
'taskCreate',
{
item: task,
diff --git a/server/api/helpers/tasks/get-many.js b/server/api/helpers/tasks/get-many.js
index 17ac1406..c64247ff 100644
--- a/server/api/helpers/tasks/get-many.js
+++ b/server/api/helpers/tasks/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
},
diff --git a/server/api/helpers/tasks/update-one.js b/server/api/helpers/tasks/update-one.js
index 17aac814..69958afd 100644
--- a/server/api/helpers/tasks/update-one.js
+++ b/server/api/helpers/tasks/update-one.js
@@ -1,3 +1,15 @@
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -6,17 +18,7 @@ module.exports = {
},
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
board: {
@@ -29,15 +31,17 @@ module.exports = {
},
async fn(inputs) {
- if (!_.isUndefined(inputs.values.position)) {
+ const { values } = inputs;
+
+ if (!_.isUndefined(values.position)) {
const tasks = await sails.helpers.cards.getTasks(inputs.record.cardId, inputs.record.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
- inputs.values.position,
+ values.position,
tasks,
);
- inputs.values.position = position; // eslint-disable-line no-param-reassign
+ values.position = position;
repositions.forEach(async ({ id, position: nextPosition }) => {
await Task.update({
@@ -56,7 +60,7 @@ module.exports = {
});
}
- const task = await Task.updateOne(inputs.record.id).set(inputs.values);
+ const task = await Task.updateOne(inputs.record.id).set({ ...values });
if (task) {
sails.sockets.broadcast(
diff --git a/server/api/helpers/users/create-one.js b/server/api/helpers/users/create-one.js
index 3094c705..4c628869 100644
--- a/server/api/helpers/users/create-one.js
+++ b/server/api/helpers/users/create-one.js
@@ -1,28 +1,30 @@
const bcrypt = require('bcrypt');
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isString(value.email)) {
+ return false;
+ }
+
+ if (!_.isString(value.password)) {
+ return false;
+ }
+
+ if (value.username && !_.isString(value.username)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isString(value.email)) {
- return false;
- }
-
- if (!_.isString(value.password)) {
- return false;
- }
-
- if (value.username && !_.isString(value.username)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
request: {
@@ -36,15 +38,16 @@ module.exports = {
},
async fn(inputs) {
- if (inputs.values.username) {
- // eslint-disable-next-line no-param-reassign
- inputs.values.username = inputs.values.username.toLowerCase();
+ const { values } = inputs;
+
+ if (values.username) {
+ values.username = values.username.toLowerCase();
}
const user = await User.create({
- ...inputs.values,
- email: inputs.values.email.toLowerCase(),
- password: bcrypt.hashSync(inputs.values.password, 10),
+ ...values,
+ email: values.email.toLowerCase(),
+ password: bcrypt.hashSync(values.password, 10),
})
.intercept(
{
diff --git a/server/api/helpers/users/get-board-memberships.js b/server/api/helpers/users/get-board-memberships.js
index 4cb23ff5..ee7f66e3 100644
--- a/server/api/helpers/users/get-board-memberships.js
+++ b/server/api/helpers/users/get-board-memberships.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/users/get-manager-project-ids.js b/server/api/helpers/users/get-manager-project-ids.js
index efe62e57..a34bf213 100644
--- a/server/api/helpers/users/get-manager-project-ids.js
+++ b/server/api/helpers/users/get-manager-project-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/users/get-many.js b/server/api/helpers/users/get-many.js
index 2afb12f6..b8077e2f 100644
--- a/server/api/helpers/users/get-many.js
+++ b/server/api/helpers/users/get-many.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isArray(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isArray(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
},
withDeleted: {
type: 'boolean',
diff --git a/server/api/helpers/users/get-membership-board-ids.js b/server/api/helpers/users/get-membership-board-ids.js
index 46a30420..cc1787a7 100644
--- a/server/api/helpers/users/get-membership-board-ids.js
+++ b/server/api/helpers/users/get-membership-board-ids.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/users/get-notifications.js b/server/api/helpers/users/get-notifications.js
index 2ea49f48..74194f77 100644
--- a/server/api/helpers/users/get-notifications.js
+++ b/server/api/helpers/users/get-notifications.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/users/get-one.js b/server/api/helpers/users/get-one.js
index 2287a4e4..19cb5d5b 100644
--- a/server/api/helpers/users/get-one.js
+++ b/server/api/helpers/users/get-one.js
@@ -1,8 +1,10 @@
+const criteriaValidator = (value) => _.isString(value) || _.isPlainObject(value);
+
module.exports = {
inputs: {
criteria: {
type: 'json',
- custom: (value) => _.isString(value) || _.isPlainObject(value),
+ custom: criteriaValidator,
required: true,
},
withDeleted: {
diff --git a/server/api/helpers/users/get-project-managers.js b/server/api/helpers/users/get-project-managers.js
index 7e7f258f..25202ed1 100644
--- a/server/api/helpers/users/get-project-managers.js
+++ b/server/api/helpers/users/get-project-managers.js
@@ -1,8 +1,10 @@
+const idOrIdsValidator = (value) => _.isString(value) || _.every(value, _.isString);
+
module.exports = {
inputs: {
idOrIds: {
type: 'json',
- custom: (value) => _.isString(value) || _.every(value, _.isString),
+ custom: idOrIdsValidator,
required: true,
},
},
diff --git a/server/api/helpers/users/update-one.js b/server/api/helpers/users/update-one.js
index 4ea8d990..314b9d7e 100644
--- a/server/api/helpers/users/update-one.js
+++ b/server/api/helpers/users/update-one.js
@@ -3,6 +3,30 @@ const bcrypt = require('bcrypt');
const rimraf = require('rimraf');
const { v4: uuid } = require('uuid');
+const valuesValidator = (value) => {
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.email) && !_.isString(value.email)) {
+ return false;
+ }
+
+ if (!_.isUndefined(value.password) && !_.isString(value.password)) {
+ return false;
+ }
+
+ if (value.username && !_.isString(value.username)) {
+ return false;
+ }
+
+ if (value.avatar && !_.isPlainObject(value.avatar)) {
+ return false;
+ }
+
+ return true;
+};
+
module.exports = {
inputs: {
record: {
@@ -11,29 +35,7 @@ module.exports = {
},
values: {
type: 'json',
- custom: (value) => {
- if (!_.isPlainObject(value)) {
- return false;
- }
-
- if (!_.isUndefined(value.email) && !_.isString(value.email)) {
- return false;
- }
-
- if (!_.isUndefined(value.password) && !_.isString(value.password)) {
- return false;
- }
-
- if (value.username && !_.isString(value.username)) {
- return false;
- }
-
- if (value.avatar && !_.isPlainObject(value.avatar)) {
- return false;
- }
-
- return true;
- },
+ custom: valuesValidator,
required: true,
},
user: {
@@ -51,34 +53,34 @@ module.exports = {
},
async fn(inputs) {
- if (!_.isUndefined(inputs.values.email)) {
- // eslint-disable-next-line no-param-reassign
- inputs.values.email = inputs.values.email.toLowerCase();
+ const { values } = inputs;
+
+ if (!_.isUndefined(values.email)) {
+ values.email = values.email.toLowerCase();
}
let isOnlyPasswordChange = false;
- if (!_.isUndefined(inputs.values.password)) {
- Object.assign(inputs.values, {
- password: bcrypt.hashSync(inputs.values.password, 10),
+ if (!_.isUndefined(values.password)) {
+ Object.assign(values, {
+ password: bcrypt.hashSync(values.password, 10),
passwordChangedAt: new Date().toUTCString(),
});
- if (Object.keys(inputs.values).length === 1) {
+ if (Object.keys(values).length === 1) {
isOnlyPasswordChange = true;
}
}
- if (inputs.values.username) {
- // eslint-disable-next-line no-param-reassign
- inputs.values.username = inputs.values.username.toLowerCase();
+ if (values.username) {
+ values.username = values.username.toLowerCase();
}
const user = await User.updateOne({
id: inputs.record.id,
deletedAt: null,
})
- .set(inputs.values)
+ .set({ ...values })
.intercept(
{
message:
@@ -106,7 +108,7 @@ module.exports = {
}
}
- if (!_.isUndefined(inputs.values.password)) {
+ if (!_.isUndefined(values.password)) {
sails.sockets.broadcast(
`user:${user.id}`,
'userDelete', // TODO: introduce separate event
diff --git a/server/api/helpers/utils/map-records.js b/server/api/helpers/utils/map-records.js
index 5a96605d..93979d76 100644
--- a/server/api/helpers/utils/map-records.js
+++ b/server/api/helpers/utils/map-records.js
@@ -1,10 +1,12 @@
+const recordsValidator = (value) => _.isArray(value);
+
module.exports = {
sync: true,
inputs: {
records: {
type: 'ref',
- custom: (value) => _.isArray(value),
+ custom: recordsValidator,
required: true,
},
attribute: {
diff --git a/server/api/models/Board.js b/server/api/models/Board.js
index 6541769b..c5924e2f 100755
--- a/server/api/models/Board.js
+++ b/server/api/models/Board.js
@@ -5,17 +5,11 @@
* @docs :: https://sailsjs.com/docs/concepts/models-and-orm/models
*/
-const Types = {
- KANBAN: 'kanban',
- COLLECTION: 'collection',
-};
-
const ImportTypes = {
TRELLO: 'trello',
};
module.exports = {
- Types,
ImportTypes,
attributes: {
@@ -23,11 +17,6 @@ module.exports = {
// ╠═╝╠╦╝║║║║║ ║ ║╚╗╔╝║╣ ╚═╗
// ╩ ╩╚═╩╩ ╩╩ ╩ ╩ ╚╝ ╚═╝╚═╝
- type: {
- type: 'string',
- isIn: Object.values(Types),
- required: true,
- },
position: {
type: 'number',
required: true,
diff --git a/server/api/models/Card.js b/server/api/models/Card.js
index d32516b8..933201f9 100755
--- a/server/api/models/Card.js
+++ b/server/api/models/Card.js
@@ -13,7 +13,7 @@ module.exports = {
position: {
type: 'number',
- allowNull: true,
+ required: true,
},
name: {
type: 'string',
@@ -47,6 +47,7 @@ module.exports = {
},
listId: {
model: 'List',
+ required: true,
columnName: 'list_id',
},
creatorUserId: {
diff --git a/server/config/routes.js b/server/config/routes.js
index ae5c5e2d..2453f918 100644
--- a/server/config/routes.js
+++ b/server/config/routes.js
@@ -49,8 +49,7 @@ module.exports.routes = {
'PATCH /api/lists/:id': 'lists/update',
'DELETE /api/lists/:id': 'lists/delete',
- 'GET /api/boards/:boardId/cards': 'cards/index',
- 'POST /api/boards/:boardId/cards': 'cards/create',
+ 'POST /api/lists/:listId/cards': 'cards/create',
'GET /api/cards/:id': 'cards/show',
'PATCH /api/cards/:id': 'cards/update',
'DELETE /api/cards/:id': 'cards/delete',
diff --git a/server/db/migrations/20221225224651_remove_board_types.js.js b/server/db/migrations/20221225224651_remove_board_types.js.js
new file mode 100644
index 00000000..56a67d90
--- /dev/null
+++ b/server/db/migrations/20221225224651_remove_board_types.js.js
@@ -0,0 +1,21 @@
+module.exports.up = async (knex) => {
+ await knex.schema.table('board', (table) => {
+ table.dropColumn('type');
+ });
+
+ return knex.schema.alterTable('card', (table) => {
+ table.bigInteger('list_id').notNullable().alter();
+ });
+};
+
+module.exports.down = async (knex) => {
+ await knex.schema.table('board', (table) => {
+ /* Columns */
+
+ table.text('type').notNullable().defaultTo('kanban');
+ });
+
+ return knex.schema.alterTable('card', (table) => {
+ table.bigInteger('list_id').alter();
+ });
+};