api maintenance
This commit is contained in:
@@ -50,9 +50,12 @@ function App() {
|
|||||||
<div className="App">
|
<div className="App">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<Routes>
|
<Routes>
|
||||||
|
{/* Base access privileges */}
|
||||||
<Route path="/" element={<Welcome />} />
|
<Route path="/" element={<Welcome />} />
|
||||||
<Route path="/register" element={<Register />} />
|
<Route path="/register" element={<Register />} />
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
|
|
||||||
|
{/* Protected routes */}
|
||||||
<Route path="/profile" element={<Profile />} />
|
<Route path="/profile" element={<Profile />} />
|
||||||
<Route path="/collections" element={<CollectionBrowser />} />
|
<Route path="/collections" element={<CollectionBrowser />} />
|
||||||
<Route path="/collections/:id" element={<Collection />} />
|
<Route path="/collections/:id" element={<Collection />} />
|
||||||
@@ -61,10 +64,11 @@ function App() {
|
|||||||
<Route path="/recipe/:id" element={<Recipe />} />
|
<Route path="/recipe/:id" element={<Recipe />} />
|
||||||
<Route path="/subscriptions" element={<Subscriptions />} />
|
<Route path="/subscriptions" element={<Subscriptions />} />
|
||||||
<Route path="/subscriptions/:id" element={<Collection />} />
|
<Route path="/subscriptions/:id" element={<Collection />} />
|
||||||
|
|
||||||
<Route path="/add-recipe" element={<AddRecipe />} />
|
<Route path="/add-recipe" element={<AddRecipe />} />
|
||||||
<Route path="/grocery-list" element={<GroceryListCollection />} />
|
<Route path="/grocery-list" element={<GroceryListCollection />} />
|
||||||
<Route path="/grocery-list/:id" element={<GroceryList />} />
|
<Route path="/grocery-list/:id" element={<GroceryList />} />
|
||||||
|
|
||||||
|
{/* For dev use */}
|
||||||
<Route path="/sandbox" element={<Sandbox />} />
|
<Route path="/sandbox" element={<Sandbox />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import FriendSearchWidget from "../ui/Widgets/NewFriendWidget"
|
|||||||
|
|
||||||
const AddFriends = () => {
|
const AddFriends = () => {
|
||||||
return (
|
return (
|
||||||
<Protect>
|
<Protect redirect="/add-friends">
|
||||||
<h1>Search for New Friends</h1>
|
<h1>Search for New Friends</h1>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import API from "../../util/API";
|
|||||||
import { useSelectorContext } from "../../context/SelectorContext";
|
import { useSelectorContext } from "../../context/SelectorContext";
|
||||||
import IngredientSelector from "../derived/IngredientSelector";
|
import IngredientSelector from "../derived/IngredientSelector";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
import Protect from "../../util/Protect";
|
||||||
|
|
||||||
const AddRecipe = () => {
|
const AddRecipe = () => {
|
||||||
const { user, token } = useAuthContext();
|
const { user, token } = useAuthContext();
|
||||||
@@ -99,7 +100,7 @@ const AddRecipe = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Protect redirect="/add-recipe">
|
||||||
<h1>Add a New Recipe</h1>
|
<h1>Add a New Recipe</h1>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ const AddRecipe = () => {
|
|||||||
|
|
||||||
<div id="toast">{ toast }</div>
|
<div id="toast">{ toast }</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
</Page>
|
</Protect>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const Collection = () => {
|
|||||||
}, [data, recipes])
|
}, [data, recipes])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Protect>
|
<Protect redirect={`/collections/${id}`}>
|
||||||
{ content }
|
{ content }
|
||||||
</Protect>
|
</Protect>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { v4 } from "uuid";
|
|||||||
import { useAuthContext } from "../../context/AuthContext";
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
import { ICollection } from "../../schemas";
|
import { ICollection } from "../../schemas";
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
|
import Protect from "../../util/Protect";
|
||||||
import { Page, Panel } from "../ui";
|
import { Page, Panel } from "../ui";
|
||||||
|
|
||||||
const CollectionBrowser = () => {
|
const CollectionBrowser = () => {
|
||||||
@@ -47,7 +48,7 @@ const CollectionBrowser = () => {
|
|||||||
}, [list])
|
}, [list])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Protect redirect="/collections">
|
||||||
{ list && (
|
{ list && (
|
||||||
<>
|
<>
|
||||||
<h1>Browsing your {list.length} collection{ (list.length !== 1) && "s" }:</h1>
|
<h1>Browsing your {list.length} collection{ (list.length !== 1) && "s" }:</h1>
|
||||||
@@ -62,7 +63,7 @@ const CollectionBrowser = () => {
|
|||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Page>
|
</Protect>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function Login() {
|
|||||||
setToken(result.token);
|
setToken(result.token);
|
||||||
|
|
||||||
// if there is a redirect, go there, else go home
|
// if there is a redirect, go there, else go home
|
||||||
navigate(`/${redirect ?? ''}`);
|
navigate(redirect ?? '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for logged in user and mount form
|
// check for logged in user and mount form
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ export default function Profile() {
|
|||||||
|
|
||||||
// if this is the current user's profile
|
// if this is the current user's profile
|
||||||
setContents(
|
setContents(
|
||||||
<Protect redirect="profile">
|
<Protect redirect="/profile">
|
||||||
<div className="profile-authenticated">
|
<div className="profile-authenticated">
|
||||||
<h1>{user!.firstname}'s Profile</h1>
|
<h1>{user!.firstname}'s Profile</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useParams } from "react-router-dom";
|
|||||||
import { Page, Panel } from "../ui";
|
import { Page, Panel } from "../ui";
|
||||||
import { IRecipe } from "../../schemas";
|
import { IRecipe } from "../../schemas";
|
||||||
import { getRecipeByID } from "../../util/apiUtils";
|
import { getRecipeByID } from "../../util/apiUtils";
|
||||||
|
import Protect from "../../util/Protect";
|
||||||
|
|
||||||
export default function Recipe() {
|
export default function Recipe() {
|
||||||
const [recipe, setRecipe] = useState<IRecipe>();
|
const [recipe, setRecipe] = useState<IRecipe>();
|
||||||
@@ -23,7 +24,7 @@ export default function Recipe() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Protect redirect={`/recipe/${id}`}>
|
||||||
{ recipe && (
|
{ recipe && (
|
||||||
<Panel>
|
<Panel>
|
||||||
<h1>{recipe.name}</h1>
|
<h1>{recipe.name}</h1>
|
||||||
@@ -31,6 +32,6 @@ export default function Recipe() {
|
|||||||
<p>{recipe.preptime}</p>
|
<p>{recipe.preptime}</p>
|
||||||
</Panel>
|
</Panel>
|
||||||
)}
|
)}
|
||||||
</Page>
|
</Protect>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
16
client/src/components/pages/StatusPages/403.tsx
Normal file
16
client/src/components/pages/StatusPages/403.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { Button, Divider, Page } from "../../ui";
|
||||||
|
|
||||||
|
export default function AccessForbidden({ children = <></> }) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<h1>403: Unauthorized</h1>
|
||||||
|
{ children }
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<Button onClick={() => navigate('/')}>Home</Button>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
||||||
16
client/src/components/pages/StatusPages/404.tsx
Normal file
16
client/src/components/pages/StatusPages/404.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { Button, Divider, Page } from "../../ui";
|
||||||
|
|
||||||
|
export default function ResourceNotFound({ children = <></> }) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<h1>404: We didn't find what you are looking for</h1>
|
||||||
|
{ children }
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<Button onClick={() => navigate('/')}>Home</Button>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ const Browser: FC<BrowserProps> = ({ children, header, searchFunction }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Protect>
|
<Protect redirect="/explore">
|
||||||
<h1>{header}</h1>
|
<h1>{header}</h1>
|
||||||
</Protect>
|
</Protect>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ module API {
|
|||||||
return Promise.resolve(response.data);
|
return Promise.resolve(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getActiveFriends() {
|
||||||
|
const response = await this.instance.get(this.endpoint + "?accepted=true", this.headers);
|
||||||
|
return Promise.resolve(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
async addFriend(id: string | number) {
|
async addFriend(id: string | number) {
|
||||||
const response = await this.instance.post(this.endpoint + `/${id}`, this.headers);
|
const response = await this.instance.post(this.endpoint + `/${id}`, this.headers);
|
||||||
return Promise.resolve(response.data);
|
return Promise.resolve(response.data);
|
||||||
|
|||||||
@@ -1,31 +1,47 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import AccessForbidden from "../components/pages/StatusPages/403";
|
||||||
import { Button, Page } from "../components/ui";
|
import { Button, Page } from "../components/ui";
|
||||||
import Divider from "../components/ui/Divider";
|
|
||||||
import { useAuthContext } from "../context/AuthContext";
|
import { useAuthContext } from "../context/AuthContext";
|
||||||
|
import API from "./API";
|
||||||
import { ProtectPortal } from "./types";
|
import { ProtectPortal } from "./types";
|
||||||
|
|
||||||
const Protect: ProtectPortal = ({ children, redirect = '' }) => {
|
const Protect: ProtectPortal = ({ children, redirect = '', accessRules = null }) => {
|
||||||
const { user } = useAuthContext();
|
const [view, setView] = useState(<Page><h1>Loading...</h1></Page>);
|
||||||
|
const { user, token } = useAuthContext();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
if (!user) {
|
useEffect(() => {
|
||||||
return (
|
if (!user || !token) {
|
||||||
<Page>
|
setView(
|
||||||
<div className="content-unauthorized">
|
<AccessForbidden>
|
||||||
<h1>Hi there! You don't look too familiar.</h1>
|
<>
|
||||||
|
<h2>Hi there! You don't look too familiar.</h2>
|
||||||
<p>To view the content on this page, please log in below:</p>
|
<p>To view the content on this page, please log in below:</p>
|
||||||
<Divider />
|
|
||||||
<Button onClick={() => navigate(redirect ? `/login?redirect=${redirect}` : '/login')}>Log In</Button>
|
<Button onClick={() => navigate(redirect ? `/login?redirect=${redirect}` : '/login')}>Log In</Button>
|
||||||
</div>
|
</>
|
||||||
</Page>
|
</AccessForbidden>
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
return (
|
return;
|
||||||
<Page>
|
}
|
||||||
{ children || <></> }
|
|
||||||
</Page>
|
if (accessRules !== null) {
|
||||||
|
if (accessRules.mustBeRecipinAdmin && !(user.isadmin)) {
|
||||||
|
setView(
|
||||||
|
<AccessForbidden>
|
||||||
|
<>
|
||||||
|
<h2>This page requires administrator access.</h2>
|
||||||
|
<p>If you believe you are receiving this message in error, please contact Recipin support.</p>
|
||||||
|
</>
|
||||||
|
</AccessForbidden>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, [user, token])
|
||||||
|
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
export default Protect;
|
export default Protect;
|
||||||
@@ -15,8 +15,15 @@ interface ButtonParams extends PortalBase {
|
|||||||
disabledText?: string
|
disabledText?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AccessRules {
|
||||||
|
mustBeRecipinAdmin: boolean
|
||||||
|
mustBeFriend: boolean
|
||||||
|
mustBeSubscribed: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProtectParams extends PortalBase {
|
export interface ProtectParams extends PortalBase {
|
||||||
redirect?: string
|
redirect?: string
|
||||||
|
accessRules?: AccessRules | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserCardProps extends PortalBase {
|
interface UserCardProps extends PortalBase {
|
||||||
|
|||||||
4
server/controllers/UserCtl.d.ts
vendored
Normal file
4
server/controllers/UserCtl.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @method getAll
|
||||||
|
* @returns { ControllerResponse<IUser[] | string> }
|
||||||
|
*/
|
||||||
@@ -5,6 +5,18 @@ import { StatusCode } from '../util/types';
|
|||||||
const UserInstance = new User();
|
const UserInstance = new User();
|
||||||
|
|
||||||
export default class UserCtl {
|
export default class UserCtl {
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* FIRST SECTION:
|
||||||
|
* METHODS SPECIFIC TO USERS AND USER DATA
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method getAll
|
||||||
|
* returns all available user entries
|
||||||
|
*
|
||||||
|
* @params (none)
|
||||||
|
* @returns list of users, or an explanatory string if no response is received
|
||||||
|
*/
|
||||||
async getAll() {
|
async getAll() {
|
||||||
try {
|
try {
|
||||||
// attempt to get users from database
|
// attempt to get users from database
|
||||||
@@ -22,6 +34,11 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method post
|
||||||
|
* @param body - serialized user data as { IUser }
|
||||||
|
* @returns the newly inserted user entry, or an explanatory string
|
||||||
|
*/
|
||||||
async post(body: IUser) {
|
async post(body: IUser) {
|
||||||
try {
|
try {
|
||||||
const response = await UserInstance.post(body);
|
const response = await UserInstance.post(body);
|
||||||
@@ -34,6 +51,11 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method getOne
|
||||||
|
* @param id - user id to query
|
||||||
|
* @returns the user entry, if found, or an explanatory string if none was found
|
||||||
|
*/
|
||||||
async getOne(id: number | string) {
|
async getOne(id: number | string) {
|
||||||
try {
|
try {
|
||||||
const user = await UserInstance.getOneByID(id);
|
const user = await UserInstance.getOneByID(id);
|
||||||
@@ -46,6 +68,12 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method updateOne
|
||||||
|
* @param id - user id to update
|
||||||
|
* @param body - the new user body to update with
|
||||||
|
* @returns the updated user body, or an explanatory string
|
||||||
|
*/
|
||||||
async updateOne(id: number | string, body: IUser) {
|
async updateOne(id: number | string, body: IUser) {
|
||||||
try {
|
try {
|
||||||
const result = await UserInstance.updateOneByID(id, body);
|
const result = await UserInstance.updateOneByID(id, body);
|
||||||
@@ -58,6 +86,16 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* SECOND SECTION:
|
||||||
|
* METHODS SPECIFIC TO FRIENDSHIPS BETWEEN USERS
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method getFriends
|
||||||
|
* @param id - get all friendship entries for a user, regardless of status
|
||||||
|
* @returns a list of friendship entries, or an explanatory string if none are found
|
||||||
|
*/
|
||||||
async getFriends(id: number | string) {
|
async getFriends(id: number | string) {
|
||||||
try {
|
try {
|
||||||
const result = await UserInstance.getFriends(id);
|
const result = await UserInstance.getFriends(id);
|
||||||
@@ -70,6 +108,12 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method getFriendshipByID
|
||||||
|
* @param id - the ID of the friendship in question
|
||||||
|
* @param userid - the user ID of the logged in user, to verify permissions
|
||||||
|
* @returns a friendship entry, or an explanatory string
|
||||||
|
*/
|
||||||
async getFriendshipByID(id: number | string, userid: number | string) {
|
async getFriendshipByID(id: number | string, userid: number | string) {
|
||||||
try {
|
try {
|
||||||
const { ok, code, result } = await UserInstance.getFriendshipByID(id, userid);
|
const { ok, code, result } = await UserInstance.getFriendshipByID(id, userid);
|
||||||
@@ -79,6 +123,11 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### @method getPendingFriendRequests
|
||||||
|
*
|
||||||
|
* *IMPORTANT*: I don't think this one works the way I think it does
|
||||||
|
*/
|
||||||
async getPendingFriendRequests(recipient: string | number) {
|
async getPendingFriendRequests(recipient: string | number) {
|
||||||
try {
|
try {
|
||||||
const { ok, code, result } = await UserInstance.getPendingFriendRequests(recipient);
|
const { ok, code, result } = await UserInstance.getPendingFriendRequests(recipient);
|
||||||
@@ -88,6 +137,15 @@ export default class UserCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAcceptedFriends(userid: number | string) {
|
||||||
|
try {
|
||||||
|
const { code, result } = await UserInstance.getAcceptedFriends(userid);
|
||||||
|
return new ControllerResponse(code, result);
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async addFriendship(userid: number | string, targetid: number | string) {
|
async addFriendship(userid: number | string, targetid: number | string) {
|
||||||
try {
|
try {
|
||||||
const result = await UserInstance.addFriendship(userid, targetid);
|
const result = await UserInstance.addFriendship(userid, targetid);
|
||||||
|
|||||||
@@ -140,6 +140,18 @@ export class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAcceptedFriends(userid: number | string) {
|
||||||
|
try {
|
||||||
|
const statement = `SELECT * FROM recipin.cmp_userfriendships WHERE active = true AND (senderid = $1) OR (targetid = $1);`
|
||||||
|
const result = await pool.query(statement, [userid]);
|
||||||
|
|
||||||
|
if (result.rows.length) return { ok: true, code: StatusCode.OK, result: result.rows }
|
||||||
|
return { ok: true, code: StatusCode.NotFound, result: "No pending friend requests found" }
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async addFriendship(userid: number | string, targetid: number | string) {
|
async addFriendship(userid: number | string, targetid: number | string) {
|
||||||
try {
|
try {
|
||||||
const statement = `
|
const statement = `
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Express, Router } from 'express';
|
|||||||
import { restrictAccess } from '../auth/middlewares';
|
import { restrictAccess } from '../auth/middlewares';
|
||||||
import { UserCtl } from '../controllers';
|
import { UserCtl } from '../controllers';
|
||||||
import { IUser } from '../schemas';
|
import { IUser } from '../schemas';
|
||||||
|
import { StatusCode } from '../util/types';
|
||||||
|
|
||||||
const UserInstance = new UserCtl();
|
const UserInstance = new UserCtl();
|
||||||
const router = Router();
|
const router = Router();
|
||||||
@@ -24,12 +25,15 @@ export const friendRouter = (app: Express) => {
|
|||||||
// get all friendships for a user
|
// get all friendships for a user
|
||||||
router.get('/', async (req, res, next) => {
|
router.get('/', async (req, res, next) => {
|
||||||
const user = req.user as IUser;
|
const user = req.user as IUser;
|
||||||
const { pending, targetUser } = req.query;
|
const { pending, accepted, targetUser } = req.query;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (pending) {
|
if (pending) {
|
||||||
const { code, data } = await UserInstance.getPendingFriendRequests(user.id as number);
|
const { code, data } = await UserInstance.getPendingFriendRequests(user.id as number);
|
||||||
res.status(code).send(data);
|
res.status(code).send(data);
|
||||||
|
} else if (accepted) {
|
||||||
|
const { code, data } = await UserInstance.getAcceptedFriends(user.id as number);
|
||||||
|
res.status(code).send(data);
|
||||||
} else {
|
} else {
|
||||||
if (targetUser) {
|
if (targetUser) {
|
||||||
const { code, data } = await UserInstance.getFriends(parseInt(targetUser as string));
|
const { code, data } = await UserInstance.getFriends(parseInt(targetUser as string));
|
||||||
@@ -39,6 +43,9 @@ export const friendRouter = (app: Express) => {
|
|||||||
res.status(code).send(data);
|
res.status(code).send(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send server error in case any of these conditions not landing
|
||||||
|
res.status(StatusCode.ServerError).json({ message: "An unexpected error occurred." });
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
next(e);
|
next(e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user