Add role assign/unassign

This commit is contained in:
Aslan 2025-12-28 13:35:12 +01:00
parent 1f3a94cf38
commit 50348cc494
6 changed files with 235 additions and 10 deletions

View file

@ -1,6 +1,6 @@
{
"name": "tether",
"version": "0.3.0",
"version": "0.3.1",
"description": "Communication server using the Nexlink protocol",
"repository": {
"type": "git",

View file

@ -6,8 +6,21 @@ import type {
IPostCreateRoleRequest,
IPostCreateRoleResponseError,
IPostCreateRoleResponseSuccess,
IPostAssignRoleParams,
IPostAssignRoleRequest,
IPostAssignRoleResponseError,
IPostAssignRoleResponseSuccess,
IPostUnassignRoleParams,
IPostUnassignRoleRequest,
IPostUnassignRoleResponseError,
IPostUnassignRoleResponseSuccess,
} from "./types.js";
import { createRoleAuth, getRoleByIdAuth } from "../../services/role/role.js";
import {
assignRoleByIdAuth,
createRoleAuth,
getRoleByIdAuth,
unassignRoleByIdAuth,
} from "../../services/role/role.js";
import { API_ERROR } from "../errors.js";
const getRole = async (request: FastifyRequest, reply: FastifyReply) => {
@ -57,4 +70,49 @@ const postCreateRole = async (request: FastifyRequest, reply: FastifyReply) => {
} as IPostCreateRoleResponseSuccess;
};
export { getRole, postCreateRole };
const postAssignRole = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IPostAssignRoleParams;
const { userId } = request.body as IPostAssignRoleRequest;
const authHeader = request.headers["authorization"];
const role = await assignRoleByIdAuth(id, userId, authHeader);
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
error: API_ERROR.ACCESS_DENIED,
} as IPostAssignRoleResponseError;
}
return {
id: role.id,
name: role.name,
communityId: role.communityId,
userId: userId,
} as IPostAssignRoleResponseSuccess;
};
const postUnassignRole = async (
request: FastifyRequest,
reply: FastifyReply,
) => {
const { id } = request.params as IPostUnassignRoleParams;
const { userId } = request.body as IPostUnassignRoleRequest;
const authHeader = request.headers["authorization"];
const role = await unassignRoleByIdAuth(id, userId, authHeader);
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
error: API_ERROR.ACCESS_DENIED,
} as IPostUnassignRoleResponseError;
}
return {
id: role.id,
name: role.name,
communityId: role.communityId,
userId: userId,
} as IPostUnassignRoleResponseSuccess;
};
export { getRole, postCreateRole, postAssignRole, postUnassignRole };

View file

@ -4,6 +4,8 @@ import * as controller from "./role.js";
const roleRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id`, controller.getRole);
fastify.post(`/`, controller.postCreateRole);
fastify.post(`/:id/assign`, controller.postAssignRole);
fastify.post(`/:id/unassign`, controller.postUnassignRole);
};
export { roleRoutes };

View file

@ -34,6 +34,46 @@ interface IPostCreateRoleResponseSuccess {
communityId: string;
}
interface IPostAssignRoleParams {
id: string;
}
interface IPostAssignRoleRequest {
userId: string;
}
interface IPostAssignRoleResponseError {
id: string;
error: API_ERROR;
}
interface IPostAssignRoleResponseSuccess {
id: string;
name: string;
communityId: string;
userId: string;
}
interface IPostUnassignRoleParams {
id: string;
}
interface IPostUnassignRoleRequest {
userId: string;
}
interface IPostUnassignRoleResponseError {
id: string;
error: API_ERROR;
}
interface IPostUnassignRoleResponseSuccess {
id: string;
name: string;
communityId: string;
userId: string;
}
export {
type IGetRoleParams,
type IGetRoleResponseError,
@ -41,4 +81,12 @@ export {
type IPostCreateRoleRequest,
type IPostCreateRoleResponseError,
type IPostCreateRoleResponseSuccess,
type IPostAssignRoleParams,
type IPostAssignRoleRequest,
type IPostAssignRoleResponseError,
type IPostAssignRoleResponseSuccess,
type IPostUnassignRoleParams,
type IPostUnassignRoleRequest,
type IPostUnassignRoleResponseError,
type IPostUnassignRoleResponseSuccess,
};

View file

@ -67,4 +67,93 @@ const createRoleAuth = async (
return await createRole(create);
};
export { getRoleById, getRoleByIdAuth, createRole, createRoleAuth };
const assignRoleById = async (id: string, userId: string): Promise<Role> => {
return await getDB().role.update({
where: {
id: id,
},
data: {
users: {
connect: {
id: userId,
},
},
},
});
};
const assignRoleByIdAuth = async (
id: string,
userId: string,
authHeader: string | undefined,
): Promise<Role | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const role = await getRoleById(id);
const community = await getCommunityById(role?.communityId ?? "");
if (
!(await isUserAllowed(
authUser,
{
community: community,
},
community,
[PERMISSION.ROLES_MANAGE],
))
) {
return API_ERROR.ACCESS_DENIED;
}
return await assignRoleById(id, userId);
};
const unassignRoleById = async (id: string, userId: string): Promise<Role> => {
return await getDB().role.update({
where: {
id: id,
},
data: {
users: {
disconnect: {
id: userId,
},
},
},
});
};
const unassignRoleByIdAuth = async (
id: string,
userId: string,
authHeader: string | undefined,
): Promise<Role | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const role = await getRoleById(id);
const community = await getCommunityById(role?.communityId ?? "");
if (
!(await isUserAllowed(
authUser,
{
community: community,
},
community,
[PERMISSION.ROLES_MANAGE],
))
) {
return API_ERROR.ACCESS_DENIED;
}
return await unassignRoleById(id, userId);
};
export {
getRoleById,
getRoleByIdAuth,
createRole,
createRoleAuth,
assignRoleById,
assignRoleByIdAuth,
unassignRoleById,
unassignRoleByIdAuth,
};

View file

@ -200,14 +200,18 @@ test("can create role", async () => {
});
test("can assign role to user", async () => {
const response = await apiGet(
`community/${state.communityId}/members`,
state.token2,
const response = await apiPost(
`role/${state.roleId}/assign`,
{
userId: state.userId2,
},
state.token1,
);
assert.equal(response.id, state.communityId);
assert.equal(response.name, state.communityName);
assert.equal(response.members.length === 2, true);
assert.equal(response.id, state.roleId);
assert.equal(response.name, state.roleName);
assert.equal(response.communityId, state.communityId);
assert.equal(response.userId, state.userId2);
});
test("can get members", async () => {
@ -242,3 +246,27 @@ test("can get roles", async () => {
assert.equal(response.name, state.communityName);
assert.equal(response.roles.length === 1, true);
});
test("can unassign role from user", async () => {
const response = await apiPost(
`role/${state.roleId}/unassign`,
{
userId: state.userId2,
},
state.token1,
);
assert.equal(response.id, state.roleId);
assert.equal(response.name, state.roleName);
assert.equal(response.communityId, state.communityId);
assert.equal(response.userId, state.userId2);
});
test("shouldn't be able to get channels 2", async () => {
const response = await apiGet(
`community/${state.communityId}/channels`,
state.token2,
);
assert.equal(response.error, "ACCESS_DENIED");
});