feat: pagination tariff

This commit is contained in:
Kirill 2023-06-01 22:07:43 +00:00
parent 67ed2131a0
commit e90cbf763b
12 changed files with 208 additions and 116 deletions

@ -6,7 +6,7 @@ import { PermissionModule } from "@/services/permission/permission.module";
import { getUser } from "@/clients/auth"; import { getUser } from "@/clients/auth";
import { validateEmptyFields } from "@/utils/validate-empty-fields"; import { validateEmptyFields } from "@/utils/validate-empty-fields";
import { determinePaginationParameters } from "./helpers"; import { determinePaginationParameters } from "@/utils/determine-pagination-parameters";
import type { FastifyReply, FastifyRequest } from "fastify"; import type { FastifyReply, FastifyRequest } from "fastify";
import type { Account } from "@/types/models/account.type"; import type { Account } from "@/types/models/account.type";
@ -27,21 +27,21 @@ export const getAccounts = async (request: GetAccountsRequest): Promise<GetAccou
export const createAccount = async (request: FastifyRequest, reply: FastifyReply) => { export const createAccount = async (request: FastifyRequest, reply: FastifyReply) => {
if (!Types.ObjectId.isValid(request.user.id)) { if (!Types.ObjectId.isValid(request.user.id)) {
reply.status(400); void reply.status(400);
return new Error("invalid user id"); return new Error("invalid user id");
} }
const account = await AccountModel.findOne({ userId: request.user.id }).lean(); const account = await AccountModel.findOne({ userId: request.user.id }).lean();
if (account) { if (account) {
reply.status(409); void reply.status(409);
return new Error("account already exist"); return new Error("account already exist");
} }
const user = await getUser({ id: request.user.id }); const user = await getUser({ id: request.user.id });
if (!user) { if (!user) {
reply.status(404); void reply.status(404);
return new Error("user not found"); return new Error("user not found");
} }
@ -56,19 +56,19 @@ export const getAccountByID = async (request: GetAccountRequest, reply: FastifyR
const [getAccountRequestParams, error] = validateEmptyFields(request.params || {}, ["userId"]); const [getAccountRequestParams, error] = validateEmptyFields(request.params || {}, ["userId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
throw error; throw error;
} }
if (!Types.ObjectId.isValid(getAccountRequestParams.userId)) { if (!Types.ObjectId.isValid(getAccountRequestParams.userId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
const account = await AccountModel.findOne({ userId: getAccountRequestParams.userId }).lean(); const account = await AccountModel.findOne({ userId: getAccountRequestParams.userId }).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -77,14 +77,14 @@ export const getAccountByID = async (request: GetAccountRequest, reply: FastifyR
export const getAccount = async (request: GetAccountRequest, reply: FastifyReply): Promise<Account> => { export const getAccount = async (request: GetAccountRequest, reply: FastifyReply): Promise<Account> => {
if (!Types.ObjectId.isValid(request.user.id)) { if (!Types.ObjectId.isValid(request.user.id)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
const account = await AccountModel.findOne({ userId: request.user.id }).lean(); const account = await AccountModel.findOne({ userId: request.user.id }).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -95,14 +95,14 @@ export const setAccountRole = async (request: SetAccountRoleRequest, reply: Fast
const [setAccountRoleBody, error] = validateEmptyFields(request.body || {}, ["userId", "role"]); const [setAccountRoleBody, error] = validateEmptyFields(request.body || {}, ["userId", "role"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
const role = await RoleModel.findOne({ name: setAccountRoleBody.role }).lean(); const role = await RoleModel.findOne({ name: setAccountRoleBody.role }).lean();
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -112,7 +112,7 @@ export const setAccountRole = async (request: SetAccountRoleRequest, reply: Fast
); );
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
return new Error("account not found"); return new Error("account not found");
} }
@ -121,7 +121,7 @@ export const setAccountRole = async (request: SetAccountRoleRequest, reply: Fast
export const removeAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => { export const removeAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => {
if (!Types.ObjectId.isValid(request.user.id)) { if (!Types.ObjectId.isValid(request.user.id)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
@ -131,7 +131,7 @@ export const removeAccount = async (request: FastifyRequest, reply: FastifyReply
).lean(); ).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -142,19 +142,19 @@ export const removeAccountById = async (request: GetAccountRequest, reply: Fasti
const [{ userId }, error] = validateEmptyFields(request.params || {}, ["userId"]); const [{ userId }, error] = validateEmptyFields(request.params || {}, ["userId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
throw error; throw error;
} }
if (!Types.ObjectId.isValid(userId)) { if (!Types.ObjectId.isValid(userId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
const account = await AccountModel.findOne({ userId: request.user.id }); const account = await AccountModel.findOne({ userId: request.user.id });
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -171,14 +171,14 @@ export const removeAccountById = async (request: GetAccountRequest, reply: Fasti
export const deleteAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => { export const deleteAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => {
if (!Types.ObjectId.isValid(request.user.id)) { if (!Types.ObjectId.isValid(request.user.id)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
const account = await AccountModel.findByIdAndDelete({ userId: request.user.id }).lean(); const account = await AccountModel.findByIdAndDelete({ userId: request.user.id }).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -189,19 +189,19 @@ export const deleteAccountById = async (request: GetAccountRequest, reply: Fasti
const [{ userId }, error] = validateEmptyFields(request.params || {}, ["userId"]); const [{ userId }, error] = validateEmptyFields(request.params || {}, ["userId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
throw error; throw error;
} }
if (!Types.ObjectId.isValid(userId)) { if (!Types.ObjectId.isValid(userId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
const account = await AccountModel.findByIdAndDelete({ userId: request.user.id }).lean(); const account = await AccountModel.findByIdAndDelete({ userId: request.user.id }).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }
@ -216,7 +216,7 @@ export const deleteAccountById = async (request: GetAccountRequest, reply: Fasti
export const restoreAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => { export const restoreAccount = async (request: FastifyRequest, reply: FastifyReply): Promise<Account> => {
if (!Types.ObjectId.isValid(request.user.id)) { if (!Types.ObjectId.isValid(request.user.id)) {
reply.status(400); void reply.status(400);
throw new Error("invalid user id"); throw new Error("invalid user id");
} }
@ -226,7 +226,7 @@ export const restoreAccount = async (request: FastifyRequest, reply: FastifyRepl
).lean(); ).lean();
if (!account) { if (!account) {
reply.status(404); void reply.status(404);
throw new Error("account not found"); throw new Error("account not found");
} }

@ -1,5 +1,6 @@
import type { FastifyRequest } from "fastify"; import type { FastifyRequest } from "fastify";
import type { Account } from "@/types/models/account.type"; import type { Account } from "@/types/models/account.type";
import type { PaginationParams } from "@/types/messages/pagination.type";
export type GetAccountRequest = FastifyRequest<{ export type GetAccountRequest = FastifyRequest<{
Params?: { Params?: {
@ -22,8 +23,3 @@ export type GetAccountsResponse = {
accounts: Account[]; accounts: Account[];
totalPages: number; totalPages: number;
}; };
export type PaginationParams = {
page?: number;
limit?: number;
};

@ -1,20 +1,17 @@
import type { FastifyRequest, FastifyReply, HookHandlerDoneFunction as Done } from "fastify"; import type { FastifyRequest, FastifyReply, HookHandlerDoneFunction as Done } from "fastify";
export const verifyUser = async (request: FastifyRequest, reply: FastifyReply, done: Done) => { export const verifyUser = async (request: FastifyRequest, reply: FastifyReply, done: Done) => {
console.info("---------------------------verifyUser------------------------------");
try { try {
const { id } = await request.jwtVerify<{ id?: string }>(); const { id } = await request.jwtVerify<{ id?: string }>();
if (!id) { if (!id) {
reply.status(401); void reply.status(401);
return reply.send("user id is empty"); return reply.send("user id is empty");
} }
request.user = { id }; request.user = { id };
} catch (nativeError) { } catch (nativeError) {
reply.status(401); void reply.status(401);
console.info("---------------------------verifyUser error------------------------------", nativeError);
return reply.send(nativeError); return reply.send(nativeError);
} }

@ -18,12 +18,12 @@ export const getPermissionById = async (
const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]); const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]);
if (validateParamsError) { if (validateParamsError) {
reply.status(400); void reply.status(400);
throw validateParamsError; throw validateParamsError;
} }
if (!Types.ObjectId.isValid(permissionId)) { if (!Types.ObjectId.isValid(permissionId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid permission id"); throw new Error("invalid permission id");
} }
@ -33,7 +33,7 @@ export const getPermissionById = async (
}); });
if (!permission) { if (!permission) {
reply.status(404); void reply.status(404);
throw new Error("permission not found"); throw new Error("permission not found");
} }
@ -44,7 +44,7 @@ export const createPermission = async (request: CreatePermissionRequest, reply:
const [permission, error] = validateEmptyFields(request.body || {}, ["name", "description"]); const [permission, error] = validateEmptyFields(request.body || {}, ["name", "description"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
throw error; throw error;
} }
@ -61,17 +61,17 @@ export const updatePermission = async (
const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]); const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]);
if (validateBodyError) { if (validateBodyError) {
reply.status(400); void reply.status(400);
throw validateBodyError; throw validateBodyError;
} }
if (validateParamsError) { if (validateParamsError) {
reply.status(400); void reply.status(400);
throw validateParamsError; throw validateParamsError;
} }
if (!Types.ObjectId.isValid(permissionId)) { if (!Types.ObjectId.isValid(permissionId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid permission id"); throw new Error("invalid permission id");
} }
@ -83,7 +83,7 @@ export const updatePermission = async (
}); });
if (!findedPermission) { if (!findedPermission) {
reply.status(404); void reply.status(404);
throw new Error("permission not found"); throw new Error("permission not found");
} }
@ -97,12 +97,12 @@ export const removePermission = async (
const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]); const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]);
if (validateParamsError) { if (validateParamsError) {
reply.status(400); void reply.status(400);
throw validateParamsError; throw validateParamsError;
} }
if (!Types.ObjectId.isValid(permissionId)) { if (!Types.ObjectId.isValid(permissionId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid permission id"); throw new Error("invalid permission id");
} }
@ -120,7 +120,7 @@ export const removePermission = async (
); );
if (!permission) { if (!permission) {
reply.status(404); void reply.status(404);
throw new Error("permission not found"); throw new Error("permission not found");
} }
@ -134,12 +134,12 @@ export const restorePermission = async (
const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]); const [{ permissionId }, validateParamsError] = validateEmptyFields(request.params || {}, ["permissionId"]);
if (validateParamsError) { if (validateParamsError) {
reply.status(400); void reply.status(400);
throw validateParamsError; throw validateParamsError;
} }
if (!Types.ObjectId.isValid(permissionId)) { if (!Types.ObjectId.isValid(permissionId)) {
reply.status(400); void reply.status(400);
throw new Error("invalid permission id"); throw new Error("invalid permission id");
} }
@ -158,7 +158,7 @@ export const restorePermission = async (
); );
if (!permission) { if (!permission) {
reply.status(404); void reply.status(404);
throw new Error("permission not found"); throw new Error("permission not found");
} }

@ -18,12 +18,12 @@ export const registerPrivilegies = async (request: RegisterPrivilegiesRequest, r
const [requestBody, errorEmpty] = validateEmptyFields(request.body ?? {}, ["privilegies"]); const [requestBody, errorEmpty] = validateEmptyFields(request.body ?? {}, ["privilegies"]);
if (errorEmpty) { if (errorEmpty) {
reply.status(400); void reply.status(400);
return errorEmpty; return errorEmpty;
} }
if (!requestBody.privilegies.length) { if (!requestBody.privilegies.length) {
reply.status(400); void reply.status(400);
return new Error("empty privilege array"); return new Error("empty privilege array");
} }
@ -31,7 +31,7 @@ export const registerPrivilegies = async (request: RegisterPrivilegiesRequest, r
const errorInvalid = validatePrivilege(rawPrivilege); const errorInvalid = validatePrivilege(rawPrivilege);
if (errorInvalid) { if (errorInvalid) {
reply.status(400); void reply.status(400);
return errorInvalid; return errorInvalid;
} }
} }
@ -69,21 +69,21 @@ export const registerPrivilege = async (request: RegisterPrivilegeRequest, reply
); );
if (errorEmpty) { if (errorEmpty) {
reply.status(400); void reply.status(400);
return errorEmpty; return errorEmpty;
} }
const errorInvalid = validatePrivilege(requestBody); const errorInvalid = validatePrivilege(requestBody);
if (errorInvalid) { if (errorInvalid) {
reply.status(400); void reply.status(400);
return errorInvalid; return errorInvalid;
} }
const privilege = await PrivilegeModel.findOne({ privilegeId: requestBody.privilegeId }).lean(); const privilege = await PrivilegeModel.findOne({ privilegeId: requestBody.privilegeId }).lean();
if (privilege) { if (privilege) {
reply.status(409); void reply.status(409);
return new Error("privilege already exist"); return new Error("privilege already exist");
} }
@ -116,7 +116,7 @@ export const getServicePrivilegies = async (request: GetServicePrivilegiesReques
const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["serviceKey"]); const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["serviceKey"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
@ -127,19 +127,19 @@ export const getPrivilege = async (request: GetPrivilegeRequest, reply: FastifyR
const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["privilegeId"]); const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["privilegeId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(requestParams.privilegeId)) { if (!Types.ObjectId.isValid(requestParams.privilegeId)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const privilege = await PrivilegeModel.findOne({ privilegeId: requestParams.privilegeId, isDeleted: false }).lean(); const privilege = await PrivilegeModel.findOne({ privilegeId: requestParams.privilegeId, isDeleted: false }).lean();
if (!privilege) { if (!privilege) {
reply.status(404); void reply.status(404);
return new Error("privilege not found"); return new Error("privilege not found");
} }
@ -154,21 +154,21 @@ export const replacePrivilege = async (request: RegisterPrivilegeRequest, reply:
); );
if (errorEmpty) { if (errorEmpty) {
reply.status(400); void reply.status(400);
return errorEmpty; return errorEmpty;
} }
const errorInvalid = validatePrivilege(requestBody); const errorInvalid = validatePrivilege(requestBody);
if (errorInvalid) { if (errorInvalid) {
reply.status(400); void reply.status(400);
return errorInvalid; return errorInvalid;
} }
const privilege = await PrivilegeModel.findOne({ privilegeId: requestBody.privilegeId }); const privilege = await PrivilegeModel.findOne({ privilegeId: requestBody.privilegeId });
if (!privilege) { if (!privilege) {
reply.status(404); void reply.status(404);
return new Error("privilege not found"); return new Error("privilege not found");
} }
@ -190,12 +190,12 @@ export const removePrivilege = async (request: RemovePrivilegeRequest, reply: Fa
const [{ privilegeId }, error] = validateEmptyFields(request.body ?? {}, ["privilegeId"]); const [{ privilegeId }, error] = validateEmptyFields(request.body ?? {}, ["privilegeId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(privilegeId)) { if (!Types.ObjectId.isValid(privilegeId)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
@ -205,7 +205,7 @@ export const removePrivilege = async (request: RemovePrivilegeRequest, reply: Fa
); );
if (!privilege) { if (!privilege) {
reply.status(404); void reply.status(404);
return new Error("privilege not found"); return new Error("privilege not found");
} }
@ -216,12 +216,12 @@ export const replacePrivilegies = async (request: RegisterPrivilegiesRequest, re
const [requestBody, errorEmpty] = validateEmptyFields(request.body ?? {}, ["privilegies"]); const [requestBody, errorEmpty] = validateEmptyFields(request.body ?? {}, ["privilegies"]);
if (errorEmpty) { if (errorEmpty) {
reply.status(400); void reply.status(400);
return errorEmpty; return errorEmpty;
} }
if (!requestBody.privilegies.length) { if (!requestBody.privilegies.length) {
reply.status(400); void reply.status(400);
return new Error("empty privilege array"); return new Error("empty privilege array");
} }
@ -229,7 +229,7 @@ export const replacePrivilegies = async (request: RegisterPrivilegiesRequest, re
const errorInvalid = validatePrivilege(rawPrivilege); const errorInvalid = validatePrivilege(rawPrivilege);
if (errorInvalid) { if (errorInvalid) {
reply.status(400); void reply.status(400);
return errorInvalid; return errorInvalid;
} }
} }
@ -260,19 +260,19 @@ export const restorePrivilege = async (request: RemovePrivilegeRequest, reply: F
const [{ privilegeId }, error] = validateEmptyFields(request.body ?? {}, ["privilegeId"]); const [{ privilegeId }, error] = validateEmptyFields(request.body ?? {}, ["privilegeId"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(privilegeId)) { if (!Types.ObjectId.isValid(privilegeId)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const privilege = await PrivilegeModel.findOneAndUpdate({ privilegeId }, { $set: { isDeleted: false } }); const privilege = await PrivilegeModel.findOneAndUpdate({ privilegeId }, { $set: { isDeleted: false } });
if (!privilege) { if (!privilege) {
reply.status(404); void reply.status(404);
return new Error("privilege not found"); return new Error("privilege not found");
} }

@ -14,14 +14,14 @@ export const createRole = async (request: CreateRoleRequest, reply: FastifyReply
const [createRoleRequest, error] = validateEmptyFields(request.body, ["name", "permissions"]); const [createRoleRequest, error] = validateEmptyFields(request.body, ["name", "permissions"]);
if (error || !createRoleRequest) { if (error || !createRoleRequest) {
reply.status(400); void reply.status(400);
return error; return error;
} }
const isRoleExist = await RoleModel.exists({ name: createRoleRequest.name }).lean(); const isRoleExist = await RoleModel.exists({ name: createRoleRequest.name }).lean();
if (isRoleExist) { if (isRoleExist) {
reply.status(409); void reply.status(409);
return new Error("role already exist"); return new Error("role already exist");
} }
@ -34,14 +34,14 @@ export const deleteRole = async (request: RemoveRoleRequest, reply: FastifyReply
const { id } = request.body || {}; const { id } = request.body || {};
if (!id || !Types.ObjectId.isValid(id)) { if (!id || !Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("wrong id"); return new Error("wrong id");
} }
const deletedRole = await RoleModel.findByIdAndDelete(id); const deletedRole = await RoleModel.findByIdAndDelete(id);
if (!deletedRole) { if (!deletedRole) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -52,18 +52,19 @@ export const removeRole = async (request: RemoveRoleRequest, reply: FastifyReply
const { id } = request.body || {}; const { id } = request.body || {};
if (!id || !Types.ObjectId.isValid(id)) { if (!id || !Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("wrong id"); return new Error("wrong id");
} }
const role = await RoleModel.findById(id); const role = await RoleModel.findById(id);
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role by id not found"); return new Error("role by id not found");
} }
if (role.isDeleted) { if (role.isDeleted) {
reply.status(409); void reply.status(409);
return new Error("role already deleted"); return new Error("role already deleted");
} }
@ -76,7 +77,7 @@ export const getRole = async (request: GetRoleRequest, reply: FastifyReply) => {
const { query } = request.params || {}; const { query } = request.params || {};
if (!query) { if (!query) {
reply.status(400); void reply.status(400);
return new Error("query is empty"); return new Error("query is empty");
} }
@ -84,7 +85,7 @@ export const getRole = async (request: GetRoleRequest, reply: FastifyReply) => {
const role = await RoleModel.findOne({ _id: new Types.ObjectId(query), isDeleted: false }).lean(); const role = await RoleModel.findOne({ _id: new Types.ObjectId(query), isDeleted: false }).lean();
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -94,7 +95,7 @@ export const getRole = async (request: GetRoleRequest, reply: FastifyReply) => {
const role = await RoleModel.findOne({ name: query, isDeleted: false }).lean(); const role = await RoleModel.findOne({ name: query, isDeleted: false }).lean();
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -106,19 +107,20 @@ export const replaceRole = async (request: UpdateRoleRequest, reply: FastifyRepl
const { query } = request.params || {}; const { query } = request.params || {};
if (error || !replaceRoleRequest) { if (error || !replaceRoleRequest) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!query) { if (!query) {
reply.status(400); void reply.status(400);
return new Error("either name or id must be filled"); return new Error("either name or id must be filled");
} }
if (Types.ObjectId.isValid(query)) { if (Types.ObjectId.isValid(query)) {
const role = RoleModel.findById(query); const role = await RoleModel.findById(query);
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role by id not found"); return new Error("role by id not found");
} }
@ -134,7 +136,7 @@ export const replaceRole = async (request: UpdateRoleRequest, reply: FastifyRepl
const role = await RoleModel.findOne({ name: query }); const role = await RoleModel.findOne({ name: query });
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -151,11 +153,12 @@ export const updateRole = async (request: UpdateRoleRequest, reply: FastifyReply
const { query } = request.params; const { query } = request.params;
if (!query) { if (!query) {
reply.status(400); void reply.status(400);
return new Error("query is empty"); return new Error("query is empty");
} }
if (!request.body?.name && !request.body?.permissions) { if (!request.body?.name && !request.body?.permissions) {
reply.status(400); void reply.status(400);
return new Error("either name or permissions must be filled"); return new Error("either name or permissions must be filled");
} }
@ -163,7 +166,7 @@ export const updateRole = async (request: UpdateRoleRequest, reply: FastifyReply
const role = await RoleModel.findById(query); const role = await RoleModel.findById(query);
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role by id not found"); return new Error("role by id not found");
} }
@ -181,7 +184,7 @@ export const updateRole = async (request: UpdateRoleRequest, reply: FastifyReply
const role = await RoleModel.findOne({ name: query }); const role = await RoleModel.findOne({ name: query });
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role not found"); return new Error("role not found");
} }
@ -200,18 +203,19 @@ export const restoreRole = async (request: RemoveRoleRequest, reply: FastifyRepl
const { id } = request.body || {}; const { id } = request.body || {};
if (!id || !Types.ObjectId.isValid(id)) { if (!id || !Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("wrong id"); return new Error("wrong id");
} }
const role = await RoleModel.findById(id); const role = await RoleModel.findById(id);
if (!role) { if (!role) {
reply.status(404); void reply.status(404);
return new Error("role by id not found"); return new Error("role by id not found");
} }
if (!role.isDeleted) { if (!role.isDeleted) {
reply.status(409); void reply.status(409);
return new Error("role not removed"); return new Error("role not removed");
} }

@ -4,33 +4,51 @@ import { TariffModel } from "@/models/tariff.model";
import { PrivilegeModel } from "@/models/privilege.model"; import { PrivilegeModel } from "@/models/privilege.model";
import { validateEmptyFields } from "@/utils/validate-empty-fields"; import { validateEmptyFields } from "@/utils/validate-empty-fields";
import { determinePaginationParameters } from "@/utils/determine-pagination-parameters";
import { validateTariff } from "./helpers"; import { validateTariff } from "./helpers";
import type { FastifyReply } from "fastify"; import type { FastifyReply } from "fastify";
import type { Privilege } from "@/types/models/privilege.type"; import type { Privilege } from "@/types/models/privilege.type";
import type { Eloquent } from "@/types/models/eloquent.type"; import type { Eloquent } from "@/types/models/eloquent.type";
import type { CreateTariffRequest, GetTariffRequest, ReplaceTariffRequest, RemoveTariffRequest } from "./types"; import type {
CreateTariffRequest,
GetTariffRequest,
ReplaceTariffRequest,
RemoveTariffRequest,
GetTariffsResponse,
GetTariffsRequest,
} from "./types";
export const getTariffs = async () => TariffModel.find({}).lean(); export const getTariffs = async (request: GetTariffsRequest): Promise<GetTariffsResponse> => {
const { page, limit } = determinePaginationParameters(request?.query ?? {});
const tariffsCount = await TariffModel.countDocuments();
const totalPages = Math.ceil(tariffsCount / limit);
const offset = (page - 1) * limit;
const tariffs = await TariffModel.find({}).sort({ createdAt: "desc" }).skip(offset).limit(limit).lean();
return { tariffs, totalPages };
};
export const getTariff = async (request: GetTariffRequest, reply: FastifyReply) => { export const getTariff = async (request: GetTariffRequest, reply: FastifyReply) => {
const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["id"]); const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["id"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(requestParams.id)) { if (!Types.ObjectId.isValid(requestParams.id)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const tariff = await TariffModel.findById(requestParams.id).lean(); const tariff = await TariffModel.findById(requestParams.id).lean();
if (!tariff) { if (!tariff) {
reply.status(404); void reply.status(404);
return new Error("tariff not found"); return new Error("tariff not found");
} }
@ -41,13 +59,13 @@ export const createTariff = async (request: CreateTariffRequest, reply: FastifyR
const [requestBody, error] = validateTariff(request.body); const [requestBody, error] = validateTariff(request.body);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
for (const privilege of requestBody.privilegies) { for (const privilege of requestBody.privilegies) {
if (!Types.ObjectId.isValid(privilege.privilegeId)) { if (!Types.ObjectId.isValid(privilege.privilegeId)) {
reply.status(404); void reply.status(404);
return new Error(`privilege id <${privilege.privilegeId}> invalid`); return new Error(`privilege id <${privilege.privilegeId}> invalid`);
} }
} }
@ -82,25 +100,25 @@ export const replaceTariff = async (request: ReplaceTariffRequest, reply: Fastif
const [requestBody, error] = validateTariff(request.body ?? {}); const [requestBody, error] = validateTariff(request.body ?? {});
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(request.params?.id || "")) { if (!Types.ObjectId.isValid(request.params?.id || "")) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const tariff = await TariffModel.findById(request.params?.id); const tariff = await TariffModel.findById(request.params?.id);
if (!tariff) { if (!tariff) {
reply.status(404); void reply.status(404);
return new Error("tariff not found"); return new Error("tariff not found");
} }
for (const privilege of requestBody.privilegies) { for (const privilege of requestBody.privilegies) {
if (!Types.ObjectId.isValid(privilege.privilegeId)) { if (!Types.ObjectId.isValid(privilege.privilegeId)) {
reply.status(404); void reply.status(404);
return new Error(`privilege id <${privilege.privilegeId}> invalid`); return new Error(`privilege id <${privilege.privilegeId}> invalid`);
} }
} }
@ -133,12 +151,12 @@ export const removeTariff = async (request: RemoveTariffRequest, reply: FastifyR
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(id)) { if (!Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
@ -147,7 +165,7 @@ export const removeTariff = async (request: RemoveTariffRequest, reply: FastifyR
}).lean(); }).lean();
if (!tariff) { if (!tariff) {
reply.status(404); void reply.status(404);
return new Error("tariff not found"); return new Error("tariff not found");
} }
@ -158,19 +176,19 @@ export const deleteTariff = async (request: RemoveTariffRequest, reply: FastifyR
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(id)) { if (!Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const tariff = await TariffModel.findByIdAndDelete(id).lean(); const tariff = await TariffModel.findByIdAndDelete(id).lean();
if (!tariff) { if (!tariff) {
reply.status(404); void reply.status(404);
return new Error("tariff not found"); return new Error("tariff not found");
} }
@ -181,19 +199,19 @@ export const restoreTariff = async (request: RemoveTariffRequest, reply: Fastify
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) { if (error) {
reply.status(400); void reply.status(400);
return error; return error;
} }
if (!Types.ObjectId.isValid(id)) { if (!Types.ObjectId.isValid(id)) {
reply.status(400); void reply.status(400);
return new Error("invalid id"); return new Error("invalid id");
} }
const tariff = await TariffModel.findByIdAndUpdate(id, { $set: { isDeleted: false } }).lean(); const tariff = await TariffModel.findByIdAndUpdate(id, { $set: { isDeleted: false } }).lean();
if (!tariff) { if (!tariff) {
reply.status(404); void reply.status(404);
return new Error("tariff not found"); return new Error("tariff not found");
} }

@ -1,5 +1,7 @@
import type { FastifyRequest } from "fastify"; import type { FastifyRequest } from "fastify";
import type { TariffMessage } from "@/types/messages/tariff-message.type"; import type { TariffMessage } from "@/types/messages/tariff-message.type";
import type { Tariff } from "@/types/models/tariff.type";
import type { PaginationParams } from "@/types/messages/pagination.type";
export type GetTariffRequest = FastifyRequest<{ export type GetTariffRequest = FastifyRequest<{
Params?: { Params?: {
@ -21,3 +23,12 @@ export type ReplaceTariffRequest = FastifyRequest<{
Body?: TariffMessage; Body?: TariffMessage;
Params?: { id?: string }; Params?: { id?: string };
}>; }>;
export type GetTariffsRequest = FastifyRequest<{
Querystring?: PaginationParams;
}>;
export type GetTariffsResponse = {
tariffs: Tariff[];
totalPages: number;
};

@ -82,3 +82,65 @@ export const tariff: SwaggerMessage = {
}, },
], ],
}; };
export const tariffs: SwaggerMessage = {
description: "Список тарифов",
type: "object",
required: ["tariffs", "totalPages"],
properties: {
tariffs: {
type: "array",
description: "Массив тарифов",
items: tariff,
},
totalPages: { type: "number" },
},
examples: [
{
totalPages: 10,
tariffs: [
{
name: "Использование сервисов",
price: 14000,
isCustom: false,
privilegies: [
{
name: "name",
privilegeId: "507f1f77bcf86cd799439011",
serviceKey: "docx-templater-service",
description: "Количество попыток использования",
type: "count",
value: "200",
price: 12300,
amount: 300,
},
],
isDeleted: false,
createdAt: "2017-07-21T17:32:28Z",
updatedAt: "2017-07-21T17:32:28Z",
},
{
name: "user",
price: 14000,
isCustom: false,
privilegies: [
{
name: "507f1f77bcf86cd799439011",
privilegeId: "507f1f77bcf86cd799439011",
serviceKey: "docx-templater-service",
description: "Количество попыток использования",
type: "count",
value: "200",
price: 12300,
amount: 100,
},
],
isDeleted: true,
createdAt: "2017-07-21T17:32:28Z",
updatedAt: "2019-04-14T15:32:15Z",
deletedAt: "2021-08-17T13:23:44Z",
},
],
},
],
};

@ -0,0 +1,4 @@
export type PaginationParams = {
page?: number;
limit?: number;
};

@ -1,6 +1,6 @@
import { determinePaginationParameters } from "./helpers"; import { determinePaginationParameters } from "./determine-pagination-parameters";
import type { PaginationParams } from "./types"; import type { PaginationParams } from "@/types/messages/pagination.type";
describe("determinePaginationParameters", () => { describe("determinePaginationParameters", () => {
const testCases: Array<{ const testCases: Array<{

@ -1,5 +1,5 @@
import type { ObjectWithRequiredFields } from "@/types/object-with-required-fields"; import type { ObjectWithRequiredFields } from "@/types/object-with-required-fields";
import type { PaginationParams } from "./types"; import type { PaginationParams } from "@/types/messages/pagination.type";
const DEFAULT_PAGE = 1; const DEFAULT_PAGE = 1;
const DEFAULT_LIMIT = 100; const DEFAULT_LIMIT = 100;