Add more services and auth
This commit is contained in:
parent
d17f37749d
commit
cae53fab61
13 changed files with 331 additions and 57 deletions
|
|
@ -1,20 +1,29 @@
|
|||
import { type FastifyReply, type FastifyRequest } from "fastify";
|
||||
import type {
|
||||
ICommunityParams,
|
||||
ICommunityResponseError,
|
||||
ICommunityResponseSuccess,
|
||||
IGetCommunityParams,
|
||||
IGetCommunityResponseError,
|
||||
IGetCommunityResponseSuccess,
|
||||
IPatchCommunityParams,
|
||||
IPatchCommunityRequest,
|
||||
IPatchCommunityResponseError,
|
||||
IPatchCommunityResponseSuccess,
|
||||
} from "./types.js";
|
||||
import { getCommunityById } from "../../services/community/community.js";
|
||||
import {
|
||||
getCommunityById,
|
||||
updateCommunityByIdAuth,
|
||||
} from "../../services/community/community.js";
|
||||
import { API_ERROR } from "../errors.js";
|
||||
|
||||
const getCommunity = async (request: FastifyRequest, _reply: FastifyReply) => {
|
||||
const { id } = request.params as ICommunityParams;
|
||||
const getCommunity = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const { id } = request.params as IGetCommunityParams;
|
||||
|
||||
const community = await getCommunityById(id);
|
||||
if (!community) {
|
||||
reply.status(404);
|
||||
return {
|
||||
id: id,
|
||||
error: "community does not exist",
|
||||
} as ICommunityResponseError;
|
||||
error: API_ERROR.NOT_FOUND,
|
||||
} as IGetCommunityResponseError;
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -22,7 +31,39 @@ const getCommunity = async (request: FastifyRequest, _reply: FastifyReply) => {
|
|||
name: community.name,
|
||||
description: community.description,
|
||||
creationDate: community.creationDate.getTime(),
|
||||
} as ICommunityResponseSuccess;
|
||||
} as IGetCommunityResponseSuccess;
|
||||
};
|
||||
|
||||
export { getCommunity };
|
||||
const patchCommunity = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const { id } = request.params as IPatchCommunityParams;
|
||||
const patchCommunityRequest = request.body as IPatchCommunityRequest;
|
||||
const authHeader = request.headers["authorization"];
|
||||
|
||||
const community = await updateCommunityByIdAuth(
|
||||
id,
|
||||
patchCommunityRequest,
|
||||
authHeader,
|
||||
);
|
||||
if (!community) {
|
||||
reply.status(404);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.NOT_FOUND,
|
||||
} as IPatchCommunityResponseError;
|
||||
}
|
||||
if (community === API_ERROR.ACCESS_DENIED) {
|
||||
reply.status(403);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.ACCESS_DENIED,
|
||||
} as IPatchCommunityResponseError;
|
||||
}
|
||||
|
||||
return {
|
||||
id: community.id,
|
||||
name: community.name,
|
||||
description: community.description,
|
||||
} as IPatchCommunityResponseSuccess;
|
||||
};
|
||||
|
||||
export { getCommunity, patchCommunity };
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import * as controller from "./community.js";
|
|||
|
||||
const communityRoutes = async (fastify: FastifyInstance) => {
|
||||
fastify.get(`/:id`, controller.getCommunity);
|
||||
fastify.patch(`/:id`, controller.patchCommunity);
|
||||
};
|
||||
|
||||
export { communityRoutes };
|
||||
|
|
|
|||
|
|
@ -1,21 +1,45 @@
|
|||
interface ICommunityParams {
|
||||
interface IGetCommunityParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface ICommunityResponseError {
|
||||
interface IGetCommunityResponseError {
|
||||
id: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface ICommunityResponseSuccess {
|
||||
interface IGetCommunityResponseSuccess {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
creationDate: number;
|
||||
}
|
||||
|
||||
interface IPatchCommunityParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface IPatchCommunityRequest {
|
||||
name?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface IPatchCommunityResponseError {
|
||||
id: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface IPatchCommunityResponseSuccess {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export {
|
||||
type ICommunityParams,
|
||||
type ICommunityResponseError,
|
||||
type ICommunityResponseSuccess,
|
||||
type IGetCommunityParams,
|
||||
type IGetCommunityResponseError,
|
||||
type IGetCommunityResponseSuccess,
|
||||
type IPatchCommunityParams,
|
||||
type IPatchCommunityRequest,
|
||||
type IPatchCommunityResponseError,
|
||||
type IPatchCommunityResponseSuccess,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import * as controller from "./user.js";
|
|||
|
||||
const userRoutes = async (fastify: FastifyInstance) => {
|
||||
fastify.get(`/:id`, controller.getUser);
|
||||
fastify.patch(`/:id`, controller.patchUser);
|
||||
fastify.get(`/:id/sessions`, controller.getSessions);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
interface IUserParams {
|
||||
interface IGetUserParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface IUserResponseError {
|
||||
interface IGetUserResponseError {
|
||||
id: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface IUserResponseSuccess {
|
||||
interface IGetUserResponseSuccess {
|
||||
id: string;
|
||||
username: string;
|
||||
email: string;
|
||||
|
|
@ -17,25 +17,54 @@ interface IUserResponseSuccess {
|
|||
lastLogin: number;
|
||||
}
|
||||
|
||||
interface ISessionsResponseError {
|
||||
interface IPatchUserParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface IPatchUserRequest {
|
||||
email?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface IPatchUserResponseError {
|
||||
id: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface ISessionsResponseSuccess {
|
||||
sessions: ISessionsResponseSession[];
|
||||
interface IPatchUserResponseSuccess {
|
||||
id: string;
|
||||
email: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface ISessionsResponseSession {
|
||||
interface IGetSessionsParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface IGetSessionsResponseError {
|
||||
id: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface IGetSessionsResponseSuccess {
|
||||
sessions: IGetSessionsResponseSession[];
|
||||
}
|
||||
|
||||
interface IGetSessionsResponseSession {
|
||||
id: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export {
|
||||
type IUserParams,
|
||||
type IUserResponseError,
|
||||
type IUserResponseSuccess,
|
||||
type ISessionsResponseError,
|
||||
type ISessionsResponseSuccess,
|
||||
type ISessionsResponseSession,
|
||||
type IGetUserParams,
|
||||
type IGetUserResponseError,
|
||||
type IGetUserResponseSuccess,
|
||||
type IPatchUserParams,
|
||||
type IPatchUserRequest,
|
||||
type IPatchUserResponseError,
|
||||
type IPatchUserResponseSuccess,
|
||||
type IGetSessionsParams,
|
||||
type IGetSessionsResponseError,
|
||||
type IGetSessionsResponseSuccess,
|
||||
type IGetSessionsResponseSession,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,22 +1,41 @@
|
|||
import { type FastifyReply, type FastifyRequest } from "fastify";
|
||||
import type {
|
||||
IUserParams,
|
||||
IUserResponseError,
|
||||
IUserResponseSuccess,
|
||||
ISessionsResponseError,
|
||||
ISessionsResponseSuccess,
|
||||
IGetUserParams,
|
||||
IGetUserResponseError,
|
||||
IGetUserResponseSuccess,
|
||||
IPatchUserParams,
|
||||
IPatchUserRequest,
|
||||
IPatchUserResponseError,
|
||||
IPatchUserResponseSuccess,
|
||||
IGetSessionsParams,
|
||||
IGetSessionsResponseError,
|
||||
IGetSessionsResponseSuccess,
|
||||
} from "./types.js";
|
||||
import { getUserById, getUserSessionsById } from "../../services/user/user.js";
|
||||
import {
|
||||
getUserByIdAuth,
|
||||
updateUserByIdAuth,
|
||||
getUserSessionsByIdAuth,
|
||||
} from "../../services/user/user.js";
|
||||
import { API_ERROR } from "../errors.js";
|
||||
|
||||
const getUser = async (request: FastifyRequest, _reply: FastifyReply) => {
|
||||
const { id } = request.params as IUserParams;
|
||||
const getUser = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const { id } = request.params as IGetUserParams;
|
||||
const authHeader = request.headers["authorization"];
|
||||
|
||||
const user = await getUserById(id);
|
||||
const user = await getUserByIdAuth(id, authHeader);
|
||||
if (!user) {
|
||||
reply.status(404);
|
||||
return {
|
||||
id: id,
|
||||
error: "user does not exist",
|
||||
} as IUserResponseError;
|
||||
error: API_ERROR.NOT_FOUND,
|
||||
} as IGetUserResponseError;
|
||||
}
|
||||
if (user === API_ERROR.ACCESS_DENIED) {
|
||||
reply.status(403);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.ACCESS_DENIED,
|
||||
} as IGetUserResponseError;
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -27,19 +46,55 @@ const getUser = async (request: FastifyRequest, _reply: FastifyReply) => {
|
|||
admin: user.admin,
|
||||
registerDate: user.registerDate.getTime(),
|
||||
lastLogin: user.lastLogin?.getTime() ?? 0,
|
||||
} as IUserResponseSuccess;
|
||||
} as IGetUserResponseSuccess;
|
||||
};
|
||||
|
||||
const getSessions = async (request: FastifyRequest, _reply: FastifyReply) => {
|
||||
const { id } = request.params as IUserParams;
|
||||
const patchUser = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const { id } = request.params as IPatchUserParams;
|
||||
const patchUserRequest = request.body as IPatchUserRequest;
|
||||
const authHeader = request.headers["authorization"];
|
||||
|
||||
const sessions = await getUserSessionsById(id, authHeader);
|
||||
if (!sessions) {
|
||||
const user = await updateUserByIdAuth(id, patchUserRequest, authHeader);
|
||||
if (!user) {
|
||||
reply.status(404);
|
||||
return {
|
||||
id: id,
|
||||
error: "user does not exist or you have no access",
|
||||
} as ISessionsResponseError;
|
||||
error: API_ERROR.NOT_FOUND,
|
||||
} as IPatchUserResponseError;
|
||||
}
|
||||
if (user === API_ERROR.ACCESS_DENIED) {
|
||||
reply.status(403);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.ACCESS_DENIED,
|
||||
} as IPatchUserResponseError;
|
||||
}
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
description: user.description,
|
||||
} as IPatchUserResponseSuccess;
|
||||
};
|
||||
|
||||
const getSessions = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const { id } = request.params as IGetSessionsParams;
|
||||
const authHeader = request.headers["authorization"];
|
||||
|
||||
const sessions = await getUserSessionsByIdAuth(id, authHeader);
|
||||
if (!sessions) {
|
||||
reply.status(404);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.NOT_FOUND,
|
||||
} as IGetSessionsResponseError;
|
||||
}
|
||||
if (sessions === API_ERROR.ACCESS_DENIED) {
|
||||
reply.status(403);
|
||||
return {
|
||||
id: id,
|
||||
error: API_ERROR.ACCESS_DENIED,
|
||||
} as IGetSessionsResponseError;
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -47,7 +102,7 @@ const getSessions = async (request: FastifyRequest, _reply: FastifyReply) => {
|
|||
id: session.id,
|
||||
userId: session.userId,
|
||||
})),
|
||||
} as ISessionsResponseSuccess;
|
||||
} as IGetSessionsResponseSuccess;
|
||||
};
|
||||
|
||||
export { getUser, getSessions };
|
||||
export { getUser, patchUser, getSessions };
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { API_ERROR } from "../../controllers/errors.js";
|
||||
import type { Community } from "../../generated/prisma/client.js";
|
||||
import { getDB } from "../../store/store.js";
|
||||
import { getUserFromAuth, isUserAllowed } from "../auth/helpers.js";
|
||||
import { PERMISSION } from "../auth/permission.js";
|
||||
import type { IUpdateCommunity } from "./types.js";
|
||||
|
||||
const getCommunityById = async (id: string): Promise<Community | null> => {
|
||||
return await getDB().community.findUnique({
|
||||
|
|
@ -7,4 +11,42 @@ const getCommunityById = async (id: string): Promise<Community | null> => {
|
|||
});
|
||||
};
|
||||
|
||||
export { getCommunityById };
|
||||
const updateCommunityById = async (
|
||||
id: string,
|
||||
update: IUpdateCommunity,
|
||||
): Promise<Community | null> => {
|
||||
return await getDB().community.update({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
data: {
|
||||
...update,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const updateCommunityByIdAuth = async (
|
||||
id: string,
|
||||
update: IUpdateCommunity,
|
||||
authHeader: string | undefined,
|
||||
): Promise<Community | null | API_ERROR.ACCESS_DENIED> => {
|
||||
const authUser = await getUserFromAuth(authHeader);
|
||||
const community = await getCommunityById(id);
|
||||
|
||||
if (
|
||||
!(await isUserAllowed(
|
||||
authUser,
|
||||
{
|
||||
community: community,
|
||||
},
|
||||
community,
|
||||
[PERMISSION.COMMUNITY_MANAGE],
|
||||
))
|
||||
) {
|
||||
return API_ERROR.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return await updateCommunityById(id, update);
|
||||
};
|
||||
|
||||
export { getCommunityById, updateCommunityById, updateCommunityByIdAuth };
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
export * from "./community.js";
|
||||
export * from "./types.js";
|
||||
|
|
|
|||
6
src/services/community/types.ts
Normal file
6
src/services/community/types.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
interface IUpdateCommunity {
|
||||
name?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export { type IUpdateCommunity };
|
||||
|
|
@ -38,7 +38,7 @@ const deleteSessionByIdAuth = async (
|
|||
authHeader: string | undefined,
|
||||
): Promise<Session | null | API_ERROR.ACCESS_DENIED> => {
|
||||
const authUser = await getUserFromAuth(authHeader);
|
||||
const session = await deleteSessionById(id);
|
||||
const session = await getSessionById(id);
|
||||
|
||||
if (
|
||||
!(await isUserOwnerOrAdmin(authUser, {
|
||||
|
|
@ -48,7 +48,7 @@ const deleteSessionByIdAuth = async (
|
|||
return API_ERROR.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return session;
|
||||
return await deleteSessionById(id);
|
||||
};
|
||||
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
export * from "./user.js";
|
||||
export * from "./types.js";
|
||||
|
|
|
|||
6
src/services/user/types.ts
Normal file
6
src/services/user/types.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
interface IUpdateUser {
|
||||
email?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export { type IUpdateUser };
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
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";
|
||||
|
||||
const getUserById = async (id: string): Promise<User | null> => {
|
||||
return await getDB().user.findUnique({
|
||||
|
|
@ -8,19 +10,58 @@ const getUserById = async (id: string): Promise<User | null> => {
|
|||
});
|
||||
};
|
||||
|
||||
const getUserSessionsById = async (
|
||||
const getUserByIdAuth = async (
|
||||
id: string,
|
||||
authHeader: string | undefined,
|
||||
): Promise<Session[] | null> => {
|
||||
): Promise<User | null | API_ERROR.ACCESS_DENIED> => {
|
||||
const authUser = await getUserFromAuth(authHeader);
|
||||
const user = await getUserById(id);
|
||||
|
||||
if (
|
||||
!(await isUserOwnerOrAdmin(authUser, {
|
||||
user: await getUserById(id),
|
||||
user: user,
|
||||
}))
|
||||
) {
|
||||
return null;
|
||||
return API_ERROR.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
const updateUserById = async (
|
||||
id: string,
|
||||
update: IUpdateUser,
|
||||
): Promise<User | null> => {
|
||||
return await getDB().user.update({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
data: {
|
||||
...update,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const updateUserByIdAuth = async (
|
||||
id: string,
|
||||
update: IUpdateUser,
|
||||
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 updateUserById(id, update);
|
||||
};
|
||||
|
||||
const getUserSessionsById = async (id: string): Promise<Session[] | null> => {
|
||||
return await getDB().session.findMany({
|
||||
where: {
|
||||
userId: id,
|
||||
|
|
@ -28,4 +69,30 @@ const getUserSessionsById = async (
|
|||
});
|
||||
};
|
||||
|
||||
export { getUserById, getUserSessionsById };
|
||||
const getUserSessionsByIdAuth = async (
|
||||
id: string,
|
||||
authHeader: string | undefined,
|
||||
): Promise<Session[] | null | API_ERROR.ACCESS_DENIED> => {
|
||||
const authUser = await getUserFromAuth(authHeader);
|
||||
const user = await getUserById(id);
|
||||
const sessions = await getUserSessionsById(id);
|
||||
|
||||
if (
|
||||
!(await isUserOwnerOrAdmin(authUser, {
|
||||
user: user,
|
||||
}))
|
||||
) {
|
||||
return API_ERROR.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return sessions;
|
||||
};
|
||||
|
||||
export {
|
||||
getUserById,
|
||||
getUserByIdAuth,
|
||||
updateUserById,
|
||||
updateUserByIdAuth,
|
||||
getUserSessionsById,
|
||||
getUserSessionsByIdAuth,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue