Skip to content
Snippets Groups Projects
task.ts 12.8 KiB
Newer Older
import { v4 as uuid, validate } from 'uuid';

import database from '../database';
import { requireVerification, Token } from './auth';
import { isOfType } from '../util';

const task = express();

task.use(requireVerification);

task.get('/:uuid', async (req, res) => {
    try {
        const id = req.params.uuid;
        if (validate(id)) {
            const task = await database('users')
                .innerJoin('team_members', 'users.id', 'team_members.user_id')
                .innerJoin('team_projects', 'team_members.team_id', 'team_projects.team_id')
                .innerJoin('tasks', 'team_projects.project_id', 'tasks.project_id')
                .select({
                    id: 'tasks.id',
                    project: 'tasks.project_id',
                    name: 'tasks.name',
                    text: 'tasks.text',
                    status: 'tasks.status',
                    priority: 'tasks.priority',
                    created: 'tasks.created',
                    edited: 'tasks.edited',
                })
                .where({
                    'users.id': req.body.token.id,
                    'tasks.id': id,
                });
            if (task.length >= 1) {
                const assigned = await database('task_assignees')
                    .select({
                        id: 'task_assignees.user_id',
                    })
                    .where({
                        'task_assignees.task_id': id,
                    });
                const dependentcies = await database('task_dependencies')
                    .select({
                        id: 'task_dependencies.requires_id',
                    })
                    .where({
                        'task_dependencies.task_id': id,
                    });
                const requirements = await database('task_requirements')
                    .select({
                        role: 'task_requirements.role_id',
                        time: 'task_requirements.time'
                    })
                    .where({
                        'task_requirements.task_id': id,
                    });
                res.status(200).json({
                    status: 'success',
                    task: {
                        ...task[0],
                        assigned: assigned.map(row => row.id),
                        dependentcies: dependentcies.map(row => row.id),
                        requirements: requirements.map(row => ({
                            role: row.role,
                            time: row.time,
                        })),
                    },
                });
            } else {
                res.status(404).json({
                    status: 'error',
                    message: 'task not found',
                });
            }
        } else {
            res.status(400).json({
                status: 'error',
                message: 'malformed uuid',
            });
        }
    } catch (e) {
        res.status(400).json({
            status: 'error',
            message: 'failed get task',
interface TaskRequirement {
    role: string;
    time: number;
}

interface AddTaskBody {
    project: string;
    name: string;
    text: string;
    priority: string;
    dependentcies: Array<string>;
    requirements: Array<TaskRequirement>;
    token: Token;
}

task.post('/', async (req, res) => {
    if (isOfType<AddTaskBody>(req.body, [
        ['project', 'string'], ['name', 'string'], ['text', 'string'], ['icon', 'string'],
        ['priority', 'string'], ['dependentcies', 'object'], ['requirements', 'object'],
    ])) {
        try {
            const project_id = req.body.project;
            const dependentcy_ids = req.body.dependentcies;
            const assigned_ids = req.body.assigned;
            const requirements = req.body.requirements;
            const requirement_ids = requirements.map(req => req.role);
            for (const team_id of [ ...dependentcy_ids, ...requirement_ids, ...assigned_ids, project_id ]) {
                if (!validate(team_id)) {
                    res.status(400).json({
                        status: 'error',
                        message: 'malformed uuid',
                    });
                    return;
                }
            }
            const task_id = uuid();
            const project = await database('users')
                .innerJoin('team_members', 'users.id', 'team_members.user_id')
                .innerJoin('team_projects', 'team_members.team_id', 'team_projects.team_id')
                .innerJoin('projects', 'team_projects.project_id', 'projects.id')
                .select({ id: 'projects.id' })
                .where({
                    'users.id': req.body.token.id,
                    'projects.id': project_id,
            if (project.length >= 1) {
                await database.transaction(async transaction => {
                    await transaction('tasks').insert({
                        id: task_id,
                        project_id: project_id,
                        name: req.body.name,
                        text: req.body.text,
                        priority: req.body.priority,
                        status: 'open',
                        created: new Date(),
                        edited: new Date(),
                    });
                    if (requirements.length !== 0) {
                        await transaction('task_requirements').insert(
                            requirements.map(requirement => ({
                                task_id: task_id,
                                role_id: requirement.role,
                                time: requirement.time,
                            }))
                        );
                    }
                    if (dependentcy_ids.length !== 0) {
                        await transaction('task_dependencies').insert(
                            dependentcy_ids.map(dependentcy_id => ({
                                task_id: task_id,
                                requires_id: dependentcy_id,
                            }))
                        );
                    }
                    if (assigned_ids.length !== 0) {
                        await transaction('task_assignees').insert(
                            assigned_ids.map(user_id => ({
                                task_id: task_id,
                                user_id: user_id,
                            }))
                        );
                    }
                });
                res.status(200).json({
                    status: 'success',
                    id: task_id,
                });
            } else {
                res.status(404).json({
                    status: 'error',
                    message: 'project not found',
                });
            }
        } catch (e) {
            res.status(400).json({
                status: 'error',
                message: 'failed to create task',
            });
        }
    } else {
        res.status(400).json({
            status: 'error',
            message: 'missing request fields',
        });
    }
});
interface UpdateTaskBody {
    name?: string;
    text?: string;
    icon?: string;
    priority?: string;
    status?: string;
    remove_dependentcies?: Array<string>;
    remove_requirements?: Array<string>;
    remove_assigned?: Array<string>;
    add_dependentcies?: Array<string>;
    add_requirements?: Array<TaskRequirement>;
    add_assigned?: Array<string>;
    token: Token;
}

task.put('/:uuid', async (req, res) => {
    if (isOfType<UpdateTaskBody>(req.body, [])) {
        try {
            const task_id = req.params.uuid;
            const remove_dependentcy_ids = req.body.remove_dependentcies ?? [];
            const remove_assigned_ids = req.body.remove_assigned ?? [];
            const remove_requirement_ids = req.body.remove_requirements ?? [];
            const add_dependentcy_ids = req.body.add_dependentcies ?? [];
            const add_assigned_ids = req.body.add_assigned ?? [];
            const add_requirements = req.body.add_requirements ?? [];
            const add_requirement_ids = add_requirements.map(req => req.role);
            const all_ids = [
                ...remove_requirement_ids,
                ...remove_assigned_ids,
                ...remove_dependentcy_ids,
                ...add_requirement_ids,
                ...add_assigned_ids,
                ...add_dependentcy_ids,
                task_id,
            ];
            for (const team_id of all_ids) {
                if (!validate(team_id)) {
                    res.status(400).json({
                        status: 'error',
                        message: 'malformed uuid',
                    });
                    return;
                }
            }
            const task = await database('users')
                .innerJoin('team_members', 'users.id', 'team_members.user_id')
                .innerJoin('team_projects', 'team_members.team_id', 'team_projects.team_id')
                .innerJoin('tasks', 'team_projects.project_id', 'tasks.project_id')
                .select({ id: 'tasks.id' })
                .where({
                    'users.id': req.body.token.id,
                    'tasks.id': task_id,
                });
            if (task.length >= 1) {
                await database.transaction(async transaction => {
                    await transaction('tasks')
                        .update({
                            name: req.body.name,
                            text: req.body.text,
                            icon: req.body.icon,
                            priority: req.body.priority,
                            status: req.body.status,
                            edited: new Date(),
                        })
                        .where({
                            'tasks.id': task_id,
                        });
                    if (remove_requirement_ids.length !== 0) {
                        await transaction('task_requirements')
                            .delete()
                            .where({
                                'task_id': task_id,
                            })
                            .whereIn('role_id', remove_requirement_ids);
                    }
                    if (remove_dependentcy_ids.length !== 0) {
                        await transaction('task_dependencies')
                            .delete()
                            .where({
                                'task_id': task_id,
                            })
                            .whereIn('requires_id', remove_dependentcy_ids);
                    }
                    if (remove_assigned_ids.length !== 0) {
                        await transaction('task_assignees')
                            .delete()
                            .where({
                                'task_id': task_id,
                            })
                            .whereIn('user_id', remove_assigned_ids);
                    }
                    if (add_requirements.length !== 0) {
                        await transaction('task_requirements').insert(
                            add_requirements.map(requirement => ({
                                task_id: task_id,
                                role_id: requirement.role,
                                time: requirement.time,
                            }))
                        );
                    }
                    if (add_dependentcy_ids.length !== 0) {
                        await transaction('task_dependencies').insert(
                            add_dependentcy_ids.map(dependentcy_id => ({
                                task_id: task_id,
                                requires_id: dependentcy_id,
                            }))
                        );
                    }
                    if (add_assigned_ids.length !== 0) {
                        await transaction('task_assignees').insert(
                            add_assigned_ids.map(user_id => ({
                                task_id: task_id,
                                user_id: user_id,
                            }))
                        );
                    }
                });
                res.status(200).json({
                    status: 'success',
                });
            } else {
                res.status(404).json({
                    status: 'error',
                    message: 'task not found',
                });
            }
        } catch (e) {
            res.status(400).json({
                status: 'error',
                message: 'failed to update task',
            });
        }
    } else {
        res.status(400).json({
            status: 'error',
            message: 'missing request fields',
        });
    }
});