diff --git a/server/src/v1/auth.ts b/server/src/v1/auth.ts index fc0c9fbb48369aa51fe21ea1f673c967e01eb3bb..2e9b9233d30d8d0a92a96bc55b269862cd5aa2d5 100644 --- a/server/src/v1/auth.ts +++ b/server/src/v1/auth.ts @@ -50,7 +50,7 @@ export function requireVerification(req: Request, res: Response, next: NextFunct } async function generateToken(token: Token) { - return asyncify(sign, token, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 }); + return asyncify(sign, token, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 * 10000000000000 }); } interface RegisterBody { diff --git a/server/src/v1/index.ts b/server/src/v1/index.ts index f059f876622f0d3ff67eb52c3ad630b0f185848e..bf965e6e39768fa7d2815b9e30be6e496ff6a7ec 100644 --- a/server/src/v1/index.ts +++ b/server/src/v1/index.ts @@ -4,7 +4,6 @@ import express from 'express'; import auth, { tokenVerification } from './auth'; import user from './user'; import team from './team'; -import role from './role'; import project from './project'; import task from './task'; import comment from './comment'; @@ -15,7 +14,6 @@ v1.use(tokenVerification); v1.use('/auth', auth); v1.use('/user', user); v1.use('/team', team); -v1.use('/role', role); v1.use('/project', project); v1.use('/task', task); v1.use('/comment', comment); diff --git a/server/src/v1/role.ts b/server/src/v1/role.ts deleted file mode 100644 index f0c5da998285013e12b827ff97bd893463a2f7ff..0000000000000000000000000000000000000000 --- a/server/src/v1/role.ts +++ /dev/null @@ -1,13 +0,0 @@ - -import express from 'express'; - -import { requireVerification } from './auth'; - -const role = express(); - -role.use(requireVerification); - - - -export default role; - diff --git a/server/src/v1/team.ts b/server/src/v1/team.ts index 56d99ed63ccdfcec995800df65c9f1cd354b1ef6..8bced9365680486a0dcddf58a8900a4bffd4f426 100644 --- a/server/src/v1/team.ts +++ b/server/src/v1/team.ts @@ -62,6 +62,30 @@ team.post('/', async (req, res) => { } }); +team.get('/', async (req, res) => { + try { + const teams = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .innerJoin('teams', 'team_members.team_id', 'teams.id') + .select({ + id: 'teams.id', + name: 'teams.name', + }) + .where({ + 'users.id': req.body.token.id + }); + res.status(200).json({ + status: 'success', + teams: teams, + }); + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to get teams', + }); + } +}); + team.get('/:uuid/', async (req, res) => { try { const id = req.params.uuid; @@ -110,11 +134,14 @@ team.get('/:uuid/members', async (req, res) => { .innerJoin({ ut: 'team_members'}, 'user.id', 'ut.user_id') .innerJoin({ tm: 'team_members'}, 'ut.team_id', 'tm.team_id') .innerJoin({ members: 'users'}, 'tm.user_id', 'members.id') + .innerJoin('roles', 'tm.role_id', 'roles.id') .select({ id: 'members.id', name: 'members.user_name', email: 'members.email', realname: 'members.real_name', + role_id: 'roles.id', + role_name: 'roles.name', }) .where({ 'user.id': req.body.token.id, @@ -123,9 +150,19 @@ team.get('/:uuid/members', async (req, res) => { if (members.length >= 1) { res.status(200).json({ status: 'success', - members: members, + members: members.map(member => ({ + id: member.id, + name: member.name, + email: member.email, + realname: member.realname, + role: { + id: member.role_id, + name: member.role_name, + }, + })), }); } else { + // All teams have members res.status(404).json({ status: 'error', message: 'team not found', @@ -140,7 +177,306 @@ team.get('/:uuid/members', async (req, res) => { } catch (e) { res.status(400).json({ status: 'error', - message: 'failed get team', + message: 'failed get members', + }); + } +}); + +team.get('/:uuid/roles', async (req, res) => { + try { + const id = req.params.uuid; + if (validate(id)) { + const roles = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .innerJoin('roles', 'team_members.team_id', 'roles.team_id') + .select({ + id: 'roles.id', + name: 'roles.name', + }) + .where({ + 'users.id': req.body.token.id, + 'team_members.team_id': id, + }); + if (roles.length >= 1) { + res.status(200).json({ + status: 'success', + roles: roles, + }); + } else { + // All teams have at least one role + res.status(404).json({ + status: 'error', + message: 'team not found', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed get roles', + }); + } +}); + +interface AddRoleBody { + name: string; + token: Token; +} + +team.post('/:uuid/roles', async (req, res) => { + if (isOfType<AddRoleBody>(req.body, [['name', 'string']])) { + try { + const team_id = req.params.uuid; + if (validate(team_id)) { + const team = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .select({ id: 'team_members.team_id' }) + .where({ + 'users.id': req.body.token.id, + 'team_members.team_id': team_id, + }); + if (team.length === 1) { + const role_id = uuid(); + const role_name = req.body.name; + await database('roles').insert({ + id: role_id, + name: role_name, + team_id: team_id, + }); + res.status(200).json({ + status: 'success', + role: { + id: role_id, + name: role_name, + }, + }); + } else { + res.status(404).json({ + status: 'error', + message: 'team not found', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to add role', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'missing request fields', + }); + } +}); + +team.delete('/:teamid/roles/:roleid', async (req, res) => { + try { + const team_id = req.params.teamid; + const role_id = req.params.roleid; + if (validate(team_id) && validate(role_id)) { + const team = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .select({ id: 'team_members.team_id' }) + .where({ + 'users.id': req.body.token.id, + 'team_members.team_id': team_id, + }); + if (team.length === 1) { + const deleted = await database('roles') + .delete() + .where({ + id: role_id, + team_id: team_id, + }); + if (deleted >= 1) { + res.status(200).json({ + status: 'success', + }); + } else { + res.status(404).json({ + status: 'error', + message: 'role not found', + }); + } + } else { + res.status(404).json({ + status: 'error', + message: 'team not found', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to add role', + }); + } +}); + +interface AddMemberBody { + user: string; + role: string; + token: Token; +} + +team.post('/:uuid/members', async (req, res) => { + if (isOfType<AddMemberBody>(req.body, [['user', 'string'], ['role', 'string']])) { + try { + const team_id = req.params.uuid; + const user_id = req.body.user; + const role_id = req.body.role; + if (validate(team_id) && validate(user_id) && validate(role_id)) { + const role = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .innerJoin('roles', 'team_members.team_id', 'roles.team_id') + .select({ id: 'roles.id' }) + .where({ + 'users.id': req.body.token.id, + 'team_members.team_id': team_id, + 'roles.id': role_id, + }); + if (role.length === 1) { + await database('team_members').insert({ + user_id: user_id, + team_id: team_id, + role_id: role_id, + }); + res.status(200).json({ + status: 'success', + }); + } else { + res.status(404).json({ + status: 'error', + message: 'role not found', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to add member', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'missing request fields', + }); + } +}); + +interface UpdateMemberBody { + user: string; + role: string; + token: Token; +} + +team.put('/:uuid/members', async (req, res) => { + if (isOfType<UpdateMemberBody>(req.body, [['user', 'string'], ['role', 'string']])) { + try { + const team_id = req.params.uuid; + const user_id = req.body.user; + const role_id = req.body.role; + if (validate(team_id) && validate(user_id) && validate(role_id)) { + const role = await database('users') + .innerJoin('team_members', 'users.id', 'team_members.user_id') + .innerJoin('roles', 'team_members.team_id', 'roles.team_id') + .select({ id: 'roles.id' }) + .where({ + 'users.id': req.body.token.id, + 'team_members.team_id': team_id, + 'roles.id': role_id, + }); + if (role.length === 1) { + await database('team_members') + .update({ role_id: role_id }) + .where({ + user_id: user_id, + team_id: team_id, + }); + res.status(200).json({ + status: 'success', + }); + } else { + res.status(404).json({ + status: 'error', + message: 'role not found', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to update member', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'missing request fields', + }); + } +}); + +team.delete('/:uuid/', async (req, res) => { + try { + const id = req.params.uuid; + if (validate(id)) { + await database.transaction(async transaction => { + const deleted = await transaction('team_members') + .delete() + .where({ + 'team_members.user_id': req.body.token.id, + 'team_members.team_id': id, + }); + if (deleted >= 1) { + res.status(200).json({ + status: 'success', + }); + } else { + res.status(404).json({ + status: 'error', + message: 'team not found', + }); + } + }); + } else { + res.status(400).json({ + status: 'error', + message: 'malformed uuid', + }); + } + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed leave team', }); } });