Add more services; Version 0.3.3

This commit is contained in:
Aslan 2025-12-29 02:02:56 +01:00
parent 50348cc494
commit ddcc591d12
26 changed files with 887 additions and 38 deletions

View file

@ -6,10 +6,19 @@ import type {
IPostCreateChannelRequest,
IPostCreateChannelResponseError,
IPostCreateChannelResponseSuccess,
IPatchChannelParams,
IPatchChannelRequest,
IPatchChannelResponseError,
IPatchChannelResponseSuccess,
IDeleteChannelParams,
IDeleteChannelResponseError,
IDeleteChannelResponseSuccess,
} from "./types.js";
import {
createChannelAuth,
deleteChannelByIdAuth,
getChannelByIdAuth,
updateChannelByIdAuth,
} from "../../services/channel/channel.js";
import { API_ERROR } from "../errors.js";
@ -63,4 +72,62 @@ const postCreateChannel = async (
} as IPostCreateChannelResponseSuccess;
};
export { getChannel, postCreateChannel };
const patchChannel = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IPatchChannelParams;
const patchChannelRequest = request.body as IPatchChannelRequest;
const authHeader = request.headers["authorization"];
const channel = await updateChannelByIdAuth(
id,
patchChannelRequest,
authHeader,
);
if (!channel) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IPatchChannelResponseError;
}
if (channel === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IPatchChannelResponseError;
}
return {
id: channel.id,
name: channel.name,
communityId: channel.communityId,
} as IPatchChannelResponseSuccess;
};
const deleteChannel = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IDeleteChannelParams;
const authHeader = request.headers["authorization"];
const channel = await deleteChannelByIdAuth(id, authHeader);
if (!channel) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IDeleteChannelResponseError;
}
if (channel === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IDeleteChannelResponseError;
}
return {
id: channel.id,
communityId: channel.communityId,
} as IDeleteChannelResponseSuccess;
};
export { getChannel, postCreateChannel, patchChannel, deleteChannel };

View file

@ -4,6 +4,8 @@ import * as controller from "./channel.js";
const channelRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id`, controller.getChannel);
fastify.post(`/`, controller.postCreateChannel);
fastify.patch(`/:id`, controller.patchChannel);
fastify.delete(`/:id`, controller.deleteChannel);
};
export { channelRoutes };

View file

@ -32,6 +32,39 @@ interface IPostCreateChannelResponseSuccess {
communityId: string;
}
interface IPatchChannelParams {
id: string;
}
interface IPatchChannelRequest {
name?: string;
}
interface IPatchChannelResponseError {
id: string;
error: API_ERROR;
}
interface IPatchChannelResponseSuccess {
id: string;
name: string;
communityId: string;
}
interface IDeleteChannelParams {
id: string;
}
interface IDeleteChannelResponseError {
id: string;
error: API_ERROR;
}
interface IDeleteChannelResponseSuccess {
id: string;
communityId: string;
}
export {
type IGetChannelParams,
type IGetChannelResponseError,
@ -39,4 +72,11 @@ export {
type IPostCreateChannelRequest,
type IPostCreateChannelResponseError,
type IPostCreateChannelResponseSuccess,
type IPatchChannelParams,
type IPatchChannelRequest,
type IPatchChannelResponseError,
type IPatchChannelResponseSuccess,
type IDeleteChannelParams,
type IDeleteChannelResponseError,
type IDeleteChannelResponseSuccess,
};

View file

@ -10,6 +10,9 @@ import type {
IPatchCommunityRequest,
IPatchCommunityResponseError,
IPatchCommunityResponseSuccess,
IDeleteCommunityParams,
IDeleteCommunityResponseError,
IDeleteCommunityResponseSuccess,
IGetMembersParams,
IGetMembersResponseError,
IGetMembersResponseSuccess,
@ -32,6 +35,7 @@ import {
getCommunityMembersByIdAuth,
getCommunityRolesByIdAuth,
createInviteAuth,
deleteCommunityByIdAuth,
} from "../../services/community/community.js";
import { API_ERROR } from "../errors.js";
import type { ICreateInvite } from "../../services/community/types.js";
@ -115,6 +119,34 @@ const patchCommunity = async (request: FastifyRequest, reply: FastifyReply) => {
} as IPatchCommunityResponseSuccess;
};
const deleteCommunity = async (
request: FastifyRequest,
reply: FastifyReply,
) => {
const { id } = request.params as IDeleteCommunityParams;
const authHeader = request.headers["authorization"];
const community = await deleteCommunityByIdAuth(id, authHeader);
if (!community) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IDeleteCommunityResponseError;
}
if (community === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IDeleteCommunityResponseError;
}
return {
id: community.id,
} as IDeleteCommunityResponseSuccess;
};
const getMembers = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IGetMembersParams;
const authHeader = request.headers["authorization"];
@ -253,6 +285,7 @@ export {
getCommunity,
postCreateCommunity,
patchCommunity,
deleteCommunity,
getMembers,
getChannels,
getRoles,

View file

@ -5,6 +5,7 @@ const communityRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id`, controller.getCommunity);
fastify.post(`/`, controller.postCreateCommunity);
fastify.patch(`/:id`, controller.patchCommunity);
fastify.delete(`/:id`, controller.deleteCommunity);
fastify.get(`/:id/members`, controller.getMembers);
fastify.get(`/:id/channels`, controller.getChannels);
fastify.get(`/:id/roles`, controller.getRoles);

View file

@ -54,6 +54,19 @@ interface IPatchCommunityResponseSuccess {
description: string;
}
interface IDeleteCommunityParams {
id: string;
}
interface IDeleteCommunityResponseError {
id: string;
error: API_ERROR;
}
interface IDeleteCommunityResponseSuccess {
id: string;
}
interface IGetMembersParams {
id: string;
}
@ -144,6 +157,9 @@ export {
type IPatchCommunityRequest,
type IPatchCommunityResponseError,
type IPatchCommunityResponseSuccess,
type IDeleteCommunityParams,
type IDeleteCommunityResponseError,
type IDeleteCommunityResponseSuccess,
type IGetMembersParams,
type IGetMembersResponseError,
type IGetMembersResponseSuccess,

View file

@ -3,9 +3,19 @@ import type {
IGetRoleParams,
IGetRoleResponseError,
IGetRoleResponseSuccess,
IGetRolePermissionsParams,
IGetRolePermissionsResponseError,
IGetRolePermissionsResponseSuccess,
IPostCreateRoleRequest,
IPostCreateRoleResponseError,
IPostCreateRoleResponseSuccess,
IPatchRoleParams,
IPatchRoleRequest,
IPatchRoleResponseError,
IPatchRoleResponseSuccess,
IDeleteRoleParams,
IDeleteRoleResponseError,
IDeleteRoleResponseSuccess,
IPostAssignRoleParams,
IPostAssignRoleRequest,
IPostAssignRoleResponseError,
@ -18,8 +28,10 @@ import type {
import {
assignRoleByIdAuth,
createRoleAuth,
deleteRoleByIdAuth,
getRoleByIdAuth,
unassignRoleByIdAuth,
updateRoleByIdAuth,
} from "../../services/role/role.js";
import { API_ERROR } from "../errors.js";
@ -51,6 +63,38 @@ const getRole = async (request: FastifyRequest, reply: FastifyReply) => {
} as IGetRoleResponseSuccess;
};
const getRolePermissions = async (
request: FastifyRequest,
reply: FastifyReply,
) => {
const { id } = request.params as IGetRolePermissionsParams;
const authHeader = request.headers["authorization"];
const role = await getRoleByIdAuth(id, authHeader);
if (!role) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IGetRolePermissionsResponseError;
}
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IGetRolePermissionsResponseError;
}
return {
id: role.id,
name: role.name,
communityId: role.communityId,
permissions: role.permissions,
creationDate: role.creationDate.getTime(),
} as IGetRolePermissionsResponseSuccess;
};
const postCreateRole = async (request: FastifyRequest, reply: FastifyReply) => {
const createRoleRequest = request.body as IPostCreateRoleRequest;
const authHeader = request.headers["authorization"];
@ -70,12 +114,73 @@ const postCreateRole = async (request: FastifyRequest, reply: FastifyReply) => {
} as IPostCreateRoleResponseSuccess;
};
const patchRole = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IPatchRoleParams;
const patchRoleRequest = request.body as IPatchRoleRequest;
const authHeader = request.headers["authorization"];
const role = await updateRoleByIdAuth(id, patchRoleRequest, authHeader);
if (!role) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IPatchRoleResponseError;
}
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IPatchRoleResponseError;
}
return {
id: role.id,
name: role.name,
communityId: role.communityId,
permissions: role.permissions,
} as IPatchRoleResponseSuccess;
};
const deleteRole = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IDeleteRoleParams;
const authHeader = request.headers["authorization"];
const role = await deleteRoleByIdAuth(id, authHeader);
if (!role) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IDeleteRoleResponseError;
}
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IDeleteRoleResponseError;
}
return {
id: role.id,
communityId: role.communityId,
} as IDeleteRoleResponseSuccess;
};
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) {
reply.status(404);
return {
error: API_ERROR.NOT_FOUND,
} as IPostAssignRoleResponseError;
}
if (role === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
@ -106,6 +211,12 @@ const postUnassignRole = async (
error: API_ERROR.ACCESS_DENIED,
} as IPostUnassignRoleResponseError;
}
if (!role) {
reply.status(404);
return {
error: API_ERROR.NOT_FOUND,
} as IPostUnassignRoleResponseError;
}
return {
id: role.id,
@ -115,4 +226,12 @@ const postUnassignRole = async (
} as IPostUnassignRoleResponseSuccess;
};
export { getRole, postCreateRole, postAssignRole, postUnassignRole };
export {
getRole,
getRolePermissions,
patchRole,
deleteRole,
postCreateRole,
postAssignRole,
postUnassignRole,
};

View file

@ -3,7 +3,10 @@ import * as controller from "./role.js";
const roleRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id`, controller.getRole);
fastify.get(`/:id/permissions`, controller.getRolePermissions);
fastify.post(`/`, controller.postCreateRole);
fastify.patch(`/:id`, controller.patchRole);
fastify.delete(`/:id`, controller.deleteRole);
fastify.post(`/:id/assign`, controller.postAssignRole);
fastify.post(`/:id/unassign`, controller.postUnassignRole);
};

View file

@ -17,6 +17,23 @@ interface IGetRoleResponseSuccess {
creationDate: number;
}
interface IGetRolePermissionsParams {
id: string;
}
interface IGetRolePermissionsResponseError {
id: string;
error: API_ERROR;
}
interface IGetRolePermissionsResponseSuccess {
id: string;
name: string;
communityId: string;
permissions: PERMISSION[];
creationDate: number;
}
interface IPostCreateRoleRequest {
name: string;
communityId: string;
@ -34,6 +51,40 @@ interface IPostCreateRoleResponseSuccess {
communityId: string;
}
interface IPatchRoleParams {
id: string;
}
interface IPatchRoleRequest {
name?: string;
}
interface IPatchRoleResponseError {
id: string;
error: API_ERROR;
}
interface IPatchRoleResponseSuccess {
id: string;
name: string;
communityId: string;
permissions: PERMISSION[];
}
interface IDeleteRoleParams {
id: string;
}
interface IDeleteRoleResponseError {
id: string;
error: API_ERROR;
}
interface IDeleteRoleResponseSuccess {
id: string;
communityId: string;
}
interface IPostAssignRoleParams {
id: string;
}
@ -78,9 +129,19 @@ export {
type IGetRoleParams,
type IGetRoleResponseError,
type IGetRoleResponseSuccess,
type IGetRolePermissionsParams,
type IGetRolePermissionsResponseError,
type IGetRolePermissionsResponseSuccess,
type IPostCreateRoleRequest,
type IPostCreateRoleResponseError,
type IPostCreateRoleResponseSuccess,
type IPatchRoleParams,
type IPatchRoleRequest,
type IPatchRoleResponseError,
type IPatchRoleResponseSuccess,
type IDeleteRoleParams,
type IDeleteRoleResponseError,
type IDeleteRoleResponseSuccess,
type IPostAssignRoleParams,
type IPostAssignRoleRequest,
type IPostAssignRoleResponseError,

View file

@ -3,7 +3,9 @@ import * as controller from "./user.js";
const userRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id`, controller.getUser);
fastify.post(`/`, controller.postCreateUser);
fastify.patch(`/:id`, controller.patchUser);
fastify.delete(`/:id`, controller.deleteUser);
fastify.get(`/:id/sessions`, controller.getSessions);
};

View file

@ -19,6 +19,27 @@ interface IGetUserResponseSuccess {
lastLogin: number;
}
interface IPostCreateUserRequest {
username: string;
password: string;
email?: string;
description?: string;
admin?: boolean;
}
interface IPostCreateUserResponseError {
id: string;
error: API_ERROR;
}
interface IPostCreateUserResponseSuccess {
id: string;
username: string;
email: string;
description: string;
admin: boolean;
}
interface IPatchUserParams {
id: string;
}
@ -39,6 +60,19 @@ interface IPatchUserResponseSuccess {
description: string;
}
interface IDeleteUserParams {
id: string;
}
interface IDeleteUserResponseError {
id: string;
error: API_ERROR;
}
interface IDeleteUserResponseSuccess {
id: string;
}
interface IGetSessionsParams {
id: string;
}
@ -62,10 +96,16 @@ export {
type IGetUserParams,
type IGetUserResponseError,
type IGetUserResponseSuccess,
type IPostCreateUserRequest,
type IPostCreateUserResponseError,
type IPostCreateUserResponseSuccess,
type IPatchUserParams,
type IPatchUserRequest,
type IPatchUserResponseError,
type IPatchUserResponseSuccess,
type IDeleteUserParams,
type IDeleteUserResponseError,
type IDeleteUserResponseSuccess,
type IGetSessionsParams,
type IGetSessionsResponseError,
type IGetSessionsResponseSuccess,

View file

@ -3,10 +3,16 @@ import type {
IGetUserParams,
IGetUserResponseError,
IGetUserResponseSuccess,
IPostCreateUserRequest,
IPostCreateUserResponseError,
IPostCreateUserResponseSuccess,
IPatchUserParams,
IPatchUserRequest,
IPatchUserResponseError,
IPatchUserResponseSuccess,
IDeleteUserParams,
IDeleteUserResponseError,
IDeleteUserResponseSuccess,
IGetSessionsParams,
IGetSessionsResponseError,
IGetSessionsResponseSuccess,
@ -15,6 +21,8 @@ import {
getUserByIdAuth,
updateUserByIdAuth,
getUserSessionsByIdAuth,
deleteUserByIdAuth,
createUserAuth,
} from "../../services/user/user.js";
import { API_ERROR } from "../errors.js";
@ -49,6 +57,27 @@ const getUser = async (request: FastifyRequest, reply: FastifyReply) => {
} as IGetUserResponseSuccess;
};
const postCreateUser = async (request: FastifyRequest, reply: FastifyReply) => {
const createUserRequest = request.body as IPostCreateUserRequest;
const authHeader = request.headers["authorization"];
const user = await createUserAuth(createUserRequest, authHeader);
if (user === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
error: API_ERROR.ACCESS_DENIED,
} as IPostCreateUserResponseError;
}
return {
id: user.id,
username: user.username,
email: user.email,
description: user.description,
admin: user.admin,
} as IPostCreateUserResponseSuccess;
};
const patchUser = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IPatchUserParams;
const patchUserRequest = request.body as IPatchUserRequest;
@ -77,6 +106,31 @@ const patchUser = async (request: FastifyRequest, reply: FastifyReply) => {
} as IPatchUserResponseSuccess;
};
const deleteUser = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IDeleteUserParams;
const authHeader = request.headers["authorization"];
const user = await deleteUserByIdAuth(id, authHeader);
if (!user) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IDeleteUserResponseError;
}
if (user === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IDeleteUserResponseError;
}
return {
id: user.id,
} as IDeleteUserResponseSuccess;
};
const getSessions = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IGetSessionsParams;
const authHeader = request.headers["authorization"];
@ -106,4 +160,4 @@ const getSessions = async (request: FastifyRequest, reply: FastifyReply) => {
} as IGetSessionsResponseSuccess;
};
export { getUser, patchUser, getSessions };
export { getUser, postCreateUser, patchUser, deleteUser, getSessions };

View file

@ -4,7 +4,7 @@ import { getDB } from "../../store/store.js";
import { getUserFromAuth, isUserAllowed } from "../auth/helpers.js";
import { PERMISSION } from "../auth/permission.js";
import { getCommunityById } from "../community/community.js";
import type { ICreateChannel } from "./types.js";
import type { ICreateChannel, IUpdateChannel } from "./types.js";
const getChannelById = async (id: string): Promise<Channel | null> => {
return await getDB().channel.findUnique({
@ -24,7 +24,7 @@ const getChannelByIdAuth = async (
!(await isUserAllowed(
authUser,
{
channel: channel,
community: community,
},
community,
[PERMISSION.CHANNELS_READ],
@ -67,4 +67,82 @@ const createChannelAuth = async (
return await createChannel(create);
};
export { getChannelById, getChannelByIdAuth, createChannel, createChannelAuth };
const updateChannelById = async (
id: string,
update: IUpdateChannel,
): Promise<Channel | null> => {
return await getDB().channel.update({
where: {
id: id,
},
data: {
...update,
},
});
};
const updateChannelByIdAuth = async (
id: string,
update: IUpdateChannel,
authHeader: string | undefined,
): Promise<Channel | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const channel = await getChannelById(id);
const community = await getCommunityById(channel?.communityId ?? "");
if (
!(await isUserAllowed(
authUser,
{
community: community,
},
community,
[PERMISSION.CHANNELS_MANAGE],
))
) {
return API_ERROR.ACCESS_DENIED;
}
return await updateChannelById(id, update);
};
const deleteChannelById = async (id: string): Promise<Channel | null> => {
return await getDB().channel.delete({
where: { id: id },
});
};
const deleteChannelByIdAuth = async (
id: string,
authHeader: string | undefined,
): Promise<Channel | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const channel = await getChannelById(id);
const community = await getCommunityById(channel?.communityId ?? "");
if (
!(await isUserAllowed(
authUser,
{
community: community,
},
community,
[PERMISSION.CHANNELS_MANAGE],
))
) {
return API_ERROR.ACCESS_DENIED;
}
return await deleteChannelById(id);
};
export {
getChannelById,
getChannelByIdAuth,
createChannel,
createChannelAuth,
updateChannelById,
updateChannelByIdAuth,
deleteChannelById,
deleteChannelByIdAuth,
};

View file

@ -3,4 +3,8 @@ interface ICreateChannel {
communityId: string;
}
export { type ICreateChannel };
interface IUpdateChannel {
name?: string;
}
export { type ICreateChannel, type IUpdateChannel };

View file

@ -1,7 +1,11 @@
import { API_ERROR } from "../../controllers/errors.js";
import type { Community, Invite, User } from "../../generated/prisma/client.js";
import { getDB } from "../../store/store.js";
import { getUserFromAuth, isUserAllowed } from "../auth/helpers.js";
import {
getUserFromAuth,
isUserAllowed,
isUserOwnerOrAdmin,
} from "../auth/helpers.js";
import { PERMISSION } from "../auth/permission.js";
import type {
ICreateCommunity,
@ -86,6 +90,30 @@ const updateCommunityByIdAuth = async (
return await updateCommunityById(id, update);
};
const deleteCommunityById = async (id: string): Promise<Community | null> => {
return await getDB().community.delete({
where: { id: id },
});
};
const deleteCommunityByIdAuth = async (
id: string,
authHeader: string | undefined,
): Promise<Community | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const community = await getCommunityById(id);
if (
!(await isUserOwnerOrAdmin(authUser, {
community: community,
}))
) {
return API_ERROR.ACCESS_DENIED;
}
return await deleteCommunityById(id);
};
const getCommunityMembersById = async (
id: string,
): Promise<ICommunityMember[]> => {
@ -244,6 +272,8 @@ export {
createCommunityAuth,
updateCommunityById,
updateCommunityByIdAuth,
deleteCommunityById,
deleteCommunityByIdAuth,
getCommunityMembersById,
getCommunityMembersByIdAuth,
getCommunityChannelsById,

View file

@ -26,7 +26,7 @@ const deleteInviteByIdAuth = async (
authHeader: string | undefined,
): Promise<Invite | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const invite = await deleteInviteById(id);
const invite = await getInviteById(id);
const community = await getCommunityById(invite?.communityId ?? "");
if (
@ -42,7 +42,7 @@ const deleteInviteByIdAuth = async (
return API_ERROR.ACCESS_DENIED;
}
return invite;
return await deleteInviteById(id);
};
const acceptInviteById = async (

View file

@ -4,7 +4,7 @@ import { getDB } from "../../store/store.js";
import { getUserFromAuth, isUserAllowed } from "../auth/helpers.js";
import { PERMISSION } from "../auth/permission.js";
import { getCommunityById } from "../community/community.js";
import type { ICreateRole } from "./types.js";
import type { ICreateRole, IUpdateRole } from "./types.js";
const getRoleById = async (id: string): Promise<Role | null> => {
return await getDB().role.findUnique({
@ -24,7 +24,7 @@ const getRoleByIdAuth = async (
!(await isUserAllowed(
authUser,
{
role: role,
community: community,
},
community,
[PERMISSION.ROLES_READ],
@ -67,7 +67,79 @@ const createRoleAuth = async (
return await createRole(create);
};
const assignRoleById = async (id: string, userId: string): Promise<Role> => {
const updateRoleById = async (
id: string,
update: IUpdateRole,
): Promise<Role | null> => {
return await getDB().role.update({
where: {
id: id,
},
data: {
...update,
},
});
};
const updateRoleByIdAuth = async (
id: string,
update: IUpdateRole,
authHeader: string | undefined,
): Promise<Role | null | 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 updateRoleById(id, update);
};
const deleteRoleById = async (id: string): Promise<Role | null> => {
return await getDB().role.delete({
where: { id: id },
});
};
const deleteRoleByIdAuth = async (
id: string,
authHeader: string | undefined,
): Promise<Role | null | 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 deleteRoleById(id);
};
const assignRoleById = async (
id: string,
userId: string,
): Promise<Role | null> => {
return await getDB().role.update({
where: {
id: id,
@ -86,7 +158,7 @@ const assignRoleByIdAuth = async (
id: string,
userId: string,
authHeader: string | undefined,
): Promise<Role | API_ERROR.ACCESS_DENIED> => {
): Promise<Role | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const role = await getRoleById(id);
const community = await getCommunityById(role?.communityId ?? "");
@ -107,7 +179,10 @@ const assignRoleByIdAuth = async (
return await assignRoleById(id, userId);
};
const unassignRoleById = async (id: string, userId: string): Promise<Role> => {
const unassignRoleById = async (
id: string,
userId: string,
): Promise<Role | null> => {
return await getDB().role.update({
where: {
id: id,
@ -126,7 +201,7 @@ const unassignRoleByIdAuth = async (
id: string,
userId: string,
authHeader: string | undefined,
): Promise<Role | API_ERROR.ACCESS_DENIED> => {
): Promise<Role | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const role = await getRoleById(id);
const community = await getCommunityById(role?.communityId ?? "");
@ -152,6 +227,10 @@ export {
getRoleByIdAuth,
createRole,
createRoleAuth,
updateRoleById,
updateRoleByIdAuth,
deleteRoleById,
deleteRoleByIdAuth,
assignRoleById,
assignRoleByIdAuth,
unassignRoleById,

View file

@ -6,4 +6,9 @@ interface ICreateRole {
permissions: PERMISSION[];
}
export { type ICreateRole };
interface IUpdateRole {
name?: string;
permissions?: PERMISSION[];
}
export { type ICreateRole, type IUpdateRole };

View file

@ -1,6 +1,14 @@
interface ICreateUser {
username: string;
password: string;
email?: string;
description?: string;
admin?: boolean;
}
interface IUpdateUser {
email?: string;
description?: string;
}
export { type IUpdateUser };
export { type ICreateUser, type IUpdateUser };

View file

@ -2,7 +2,7 @@ import type { User, Session } from "../../generated/prisma/client.js";
import { getUserFromAuth, isUserOwnerOrAdmin } from "../auth/helpers.js";
import { getDB } from "../../store/store.js";
import { API_ERROR } from "../../controllers/errors.js";
import type { IUpdateUser } from "./types.js";
import type { ICreateUser, IUpdateUser } from "./types.js";
const getUserById = async (id: string): Promise<User | null> => {
return await getDB().user.findUnique({
@ -28,6 +28,27 @@ const getUserByIdAuth = async (
return user;
};
const createUser = async (create: ICreateUser): Promise<User> => {
return await getDB().user.create({
data: {
...create,
},
});
};
const createUserAuth = async (
create: ICreateUser,
authHeader: string | undefined,
): Promise<User | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
if (!authUser?.admin) {
return API_ERROR.ACCESS_DENIED;
}
return await createUser(create);
};
const updateUserById = async (
id: string,
update: IUpdateUser,
@ -61,6 +82,30 @@ const updateUserByIdAuth = async (
return await updateUserById(id, update);
};
const deleteUserById = async (id: string): Promise<User | null> => {
return await getDB().user.delete({
where: { id: id },
});
};
const deleteUserByIdAuth = async (
id: string,
authHeader: string | undefined,
): Promise<User | null | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const user = await getUserById(id);
if (
!(await isUserOwnerOrAdmin(authUser, {
user: user,
}))
) {
return API_ERROR.ACCESS_DENIED;
}
return await deleteUserById(id);
};
const getUserSessionsById = async (id: string): Promise<Session[] | null> => {
return await getDB().session.findMany({
where: {
@ -91,8 +136,12 @@ const getUserSessionsByIdAuth = async (
export {
getUserById,
getUserByIdAuth,
createUser,
createUserAuth,
updateUserById,
updateUserByIdAuth,
deleteUserById,
deleteUserByIdAuth,
getUserSessionsById,
getUserSessionsByIdAuth,
};