144 lines
4.6 KiB
JavaScript
144 lines
4.6 KiB
JavaScript
import express from 'express';
|
|
const router = express.Router();
|
|
import { DataTypes, Op } from 'sequelize';
|
|
import defineProject from '../../models/projects.js';
|
|
import defineFolder from '../../models/folders.js';
|
|
import defineCase from '../../models/cases.js';
|
|
import defineTag from '../../models/tags.js';
|
|
import defineRunCase from '../../models/runCases.js';
|
|
import authMiddleware from '../../middleware/auth.js';
|
|
import visibilityMiddleware from '../../middleware/verifyVisible.js';
|
|
|
|
export default function (sequelize) {
|
|
const Project = defineProject(sequelize, DataTypes);
|
|
const Folder = defineFolder(sequelize, DataTypes);
|
|
const Case = defineCase(sequelize, DataTypes);
|
|
const RunCase = defineRunCase(sequelize, DataTypes);
|
|
const Tags = defineTag(sequelize, DataTypes);
|
|
Project.hasMany(Folder, { foreignKey: 'projectId' });
|
|
Folder.hasMany(Case, { foreignKey: 'folderId' });
|
|
Folder.belongsTo(Project, { foreignKey: 'projectId' });
|
|
Case.belongsTo(Folder, { foreignKey: 'folderId' });
|
|
Case.hasMany(RunCase, { foreignKey: 'caseId' });
|
|
Case.belongsToMany(Tags, { through: 'caseTags', foreignKey: 'caseId', otherKey: 'tagId' });
|
|
Tags.belongsToMany(Case, { through: 'caseTags', foreignKey: 'tagId', otherKey: 'caseId' });
|
|
RunCase.belongsTo(Case, { foreignKey: 'caseId' });
|
|
const { verifySignedIn } = authMiddleware(sequelize);
|
|
const { verifyProjectVisibleFromProjectId } = visibilityMiddleware(sequelize);
|
|
const { verifyProjectVisibleFromRunId } = visibilityMiddleware(sequelize);
|
|
|
|
router.get(
|
|
'/byproject',
|
|
verifySignedIn,
|
|
verifyProjectVisibleFromProjectId,
|
|
verifyProjectVisibleFromRunId,
|
|
async (req, res) => {
|
|
const { projectId, runId, status, tag, search } = req.query;
|
|
|
|
if (!projectId) {
|
|
return res.status(400).json({ error: 'projectId is required' });
|
|
}
|
|
|
|
if (!runId) {
|
|
return res.status(400).json({ error: 'runId is required' });
|
|
}
|
|
|
|
try {
|
|
// Build where clause for Case model
|
|
const caseWhereClause = {};
|
|
|
|
// Handle search parameter
|
|
if (search) {
|
|
const searchTerm = search.trim();
|
|
|
|
if (searchTerm.length > 100) {
|
|
return res.status(400).json({ error: 'too long search param' });
|
|
}
|
|
|
|
if (searchTerm.length >= 1) {
|
|
caseWhereClause[Op.or] = [
|
|
{ title: { [Op.like]: `%${searchTerm}%` } },
|
|
{ description: { [Op.like]: `%${searchTerm}%` } },
|
|
];
|
|
}
|
|
}
|
|
|
|
// Handle status filter for RunCase
|
|
let statusFilter = undefined;
|
|
let runCaseRequired = false;
|
|
if (status) {
|
|
const statusValues = status
|
|
.split(',')
|
|
.map((t) => parseInt(t.trim(), 10))
|
|
.filter((t) => !isNaN(t));
|
|
|
|
if (statusValues.length > 0) {
|
|
statusFilter = { status: { [Op.in]: statusValues } };
|
|
runCaseRequired = true;
|
|
}
|
|
}
|
|
|
|
// Handle tag filter
|
|
const tagInclude = {
|
|
model: Tags,
|
|
attributes: ['id', 'name'],
|
|
through: { attributes: [] },
|
|
};
|
|
|
|
if (tag) {
|
|
const tagIds = tag
|
|
.split(',')
|
|
.map((t) => parseInt(t.trim(), 10))
|
|
.filter((t) => !isNaN(t));
|
|
|
|
if (tagIds.length > 0) {
|
|
tagInclude.where = { id: { [Op.in]: tagIds } };
|
|
tagInclude.required = true;
|
|
}
|
|
}
|
|
|
|
const cases = await Case.findAll({
|
|
where: caseWhereClause,
|
|
include: [
|
|
{
|
|
model: Folder,
|
|
where: {
|
|
projectId: projectId,
|
|
},
|
|
attributes: [],
|
|
},
|
|
{
|
|
model: RunCase,
|
|
attributes: [
|
|
'id',
|
|
'runId',
|
|
'status',
|
|
[
|
|
sequelize.literal(
|
|
'(SELECT COUNT(*) FROM `comments` WHERE `comments`.`commentableType` = ' +
|
|
sequelize.escape('RunCase') +
|
|
' AND `comments`.`commentableId` = `RunCases`.`id`)'
|
|
),
|
|
'commentCount',
|
|
],
|
|
],
|
|
// Must be 'true' when filtering by status, otherwise all cases are returned.
|
|
required: runCaseRequired,
|
|
where: {
|
|
[Op.and]: [{ runId: runId }, statusFilter],
|
|
},
|
|
},
|
|
tagInclude,
|
|
],
|
|
});
|
|
res.json(cases);
|
|
} catch (error) {
|
|
console.error(error);
|
|
res.status(500).send('Internal Server Error');
|
|
}
|
|
}
|
|
);
|
|
|
|
return router;
|
|
}
|