aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--prisma/schema.prisma4
-rw-r--r--src/controller/friend.ts44
-rw-r--r--src/controller/transaction.ts19
-rw-r--r--src/route/friend.ts3
-rw-r--r--src/route/transaction.ts4
-rw-r--r--src/service/friend.ts52
-rw-r--r--src/service/transaction.ts16
8 files changed, 123 insertions, 21 deletions
diff --git a/package.json b/package.json
index fc5203c..c49b152 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "financer",
- "version": "0.1.1",
+ "version": "0.5.0",
"description": "Pocket Money Tracker",
"main": "dist/index.js",
"scripts": {
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 7c99fed..4e2dbbc 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -65,13 +65,11 @@ model MonthlyBudget {
}
model Friend {
- id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
userId Int
friend User @relation(name: "friend", fields: [friendId], references: [id])
friendId Int
-
- @@unique([userId, friendId])
+ @@id([userId, friendId])
}
enum TransactionType {
diff --git a/src/controller/friend.ts b/src/controller/friend.ts
index a73d3d1..4690f39 100644
--- a/src/controller/friend.ts
+++ b/src/controller/friend.ts
@@ -17,8 +17,9 @@
import { Request, Response } from "express";
import { getFriendToken } from "../util/auth";
-import { friend, unfriend, list } from "../service/friend";
+import { friend, unfriend, list, get } from "../service/friend";
import jwt from "jsonwebtoken";
+import {readById} from "../service/user";
const friendRequest = async (req: Request, res: Response) => {
try {
@@ -55,12 +56,21 @@ const addFriend = async (req: Request, res: Response) => {
} else {
try {
// @ts-ignore
- const _ = await friend(claims.userId, req.userId);
- res.status(200).json({ message: "success" });
+ const f = await friend(claims.userId, req.userId);
+ // @ts-ignore
+ delete f["password"];
+ // @ts-ignore
+ delete f["refreshTokenVersion"];
+ // @ts-ignore
+ delete f["createdAt"];
+ // @ts-ignore
+ delete f["updatedAt"];
+
+ res.status(200).json({ friend: f });
} catch (error) {
// @ts-ignore
if (error.code == "P2002") {
- res.status(409).json({ error: "Already friends" });
+ res.status(409).json({error: "Already friends"});
} else {
res.status(500).json({ error: "Internal Server Error" });
console.error(error);
@@ -77,9 +87,11 @@ const addFriend = async (req: Request, res: Response) => {
const removeFriend = async (req: Request, res: Response) => {
try {
+ if (req.body.friendId === undefined || req.body.friendId === null || !Number.isInteger(req.body.friendId)) {
+ res.status(400).json({ message: "Invalid Friend ID" });
// @ts-ignore
- if (req.userId == req.body.friendId) {
- res.status(400).json({ message: "Attempted to unfriend self" });
+ } else if (req.userId == req.body.friendId) {
+ res.status(400).json({message: "Attempted to unfriend self"});
} else {
// @ts-ignore
const { count } = await unfriend(req.userId, req.body.friendId)
@@ -107,9 +119,27 @@ const listFriends = async (req: Request, res: Response) => {
}
}
+const getFriend = async (req: Request, res: Response) => {
+ try {
+ // @ts-ignore
+ const friend = await get(req.userId, parseInt(req.params.friendId)) // TODO: handle non int value passed (bad req)
+ // @ts-ignore
+ res.status(200).json({ friend: friend });
+ } catch(error) {
+ // @ts-ignore
+ if (error.message == "forbidden") {
+ res.status(403).json({ error: "You are not allowed to view this profile." });
+ } else {
+ res.status(500).json({ error: "Internal Server Error" });
+ console.error(error);
+ }
+ }
+}
+
export {
friendRequest,
addFriend,
removeFriend,
- listFriends
+ listFriends,
+ getFriend
}
diff --git a/src/controller/transaction.ts b/src/controller/transaction.ts
index 6c818d6..9d4d6da 100644
--- a/src/controller/transaction.ts
+++ b/src/controller/transaction.ts
@@ -16,7 +16,7 @@
*/
import { Request, Response } from "express";
-import { create, read, del } from "../service/transaction";
+import { create, read, readOne, del } from "../service/transaction";
const addNew = async (req: Request, res: Response) => {
try {
@@ -40,6 +40,22 @@ const get = async (req: Request, res: Response) => {
}
}
+const getOne = async (req: Request, res: Response) => {
+ try {
+ // @ts-ignore
+ const transaction = await readOne(req.userId, parseInt(req.params.transactionId)); // TODO: handle non int value passed (bad req)
+ res.status(200).json({ transaction: transaction });
+ } catch(error) {
+ // @ts-ignore
+ if (error.message == "forbidden") {
+ res.status(403).json({ error: "You are not allowed to view this transaction." });
+ } else {
+ res.status(500).json({ error: "Internal Server Error" });
+ console.error(error);
+ }
+ }
+}
+
const remove = async (req: Request, res: Response) => {
try {
// @ts-ignore
@@ -65,5 +81,6 @@ const remove = async (req: Request, res: Response) => {
export {
addNew,
get,
+ getOne,
remove
}
diff --git a/src/route/friend.ts b/src/route/friend.ts
index f477c23..e52226a 100644
--- a/src/route/friend.ts
+++ b/src/route/friend.ts
@@ -16,12 +16,13 @@
*/
import { Router } from "express";
-import { listFriends, friendRequest, addFriend, removeFriend } from "../controller/friend";
+import { listFriends, getFriend, friendRequest, addFriend, removeFriend } from "../controller/friend";
const router: Router = Router();
router.get("/", listFriends);
router.get("/code", friendRequest);
+router.get("/:friendId", getFriend);
router.post("/", addFriend);
router.delete("/", removeFriend);
diff --git a/src/route/transaction.ts b/src/route/transaction.ts
index d42f94b..c0893fc 100644
--- a/src/route/transaction.ts
+++ b/src/route/transaction.ts
@@ -16,11 +16,13 @@
*/
import { Router } from "express";
-import { get, addNew, remove } from "../controller/transaction";
+import { get, getOne, addNew, remove } from "../controller/transaction";
+import {getFriend} from "../controller/friend";
const router: Router = Router();
router.get("/", get);
+router.get("/:transactionId", getOne);
router.post("/", addNew);
router.delete("/", remove);
diff --git a/src/service/friend.ts b/src/service/friend.ts
index 6986858..1f30760 100644
--- a/src/service/friend.ts
+++ b/src/service/friend.ts
@@ -16,10 +16,11 @@
*/
import prisma from "../util/prisma";
+import { readById } from "./user";
const friend = async (userId: Number, friendId: Number) => {
- // will return error P2002 if already friends
- return prisma.friend.createMany({
+ // will throw error P2002 if already friends
+ await prisma.friend.createMany({
data: [
// @ts-ignore
{ userId: userId, friendId: friendId },
@@ -28,17 +29,18 @@ const friend = async (userId: Number, friendId: Number) => {
{ userId: friendId, friendId: userId }
]
})
+
+ return readById(userId);
}
-const unfriend = async (userId: Number, friendId: Number) => {
+const unfriend = (userId: Number, friendId: Number) => {
return prisma.friend.deleteMany({
where: {
OR: [
// @ts-ignore
- { userId: userId },
-
+ { userId: userId, friendId: friendId },
// @ts-ignore
- { userId: friendId },
+ { userId: friendId, friendId: userId }
]
}
})
@@ -63,8 +65,44 @@ const list = async (userId: Number) => {
})
}
+const get = async (userId: Number, friendId: Number) => {
+ // Verify that users are friends. Seeing a non-friend's profile isn't allowed
+ const friendship = await prisma.friend.findFirst({
+ // @ts-ignore
+ where: {
+ AND: [
+ // @ts-ignore
+ { userId: userId },
+ // @ts-ignore
+ { friendId: friendId },
+ ]
+ }
+ })
+
+ if (friendship == null) {
+ // user isn't friends with them
+ throw new Error("forbidden");
+ }
+
+ const friend = await prisma.user.findUnique({
+ // @ts-ignore
+ where: { id: friendId }
+ })
+ // @ts-ignore
+ delete friend["password"];
+ // @ts-ignore
+ delete friend["refreshTokenVersion"];
+ // @ts-ignore
+ delete friend["createdAt"];
+ // @ts-ignore
+ delete friend["updatedAt"];
+
+ return friend;
+}
+
export {
friend,
unfriend,
- list
+ list,
+ get
} \ No newline at end of file
diff --git a/src/service/transaction.ts b/src/service/transaction.ts
index 8f1c99d..c3a2408 100644
--- a/src/service/transaction.ts
+++ b/src/service/transaction.ts
@@ -42,6 +42,21 @@ const read = async (userId: Number, type: String) => {
})
}
+const readOne = async (userId: Number, id: Number) => {
+ const transaction = await prisma.transaction.findUnique({
+ // @ts-ignore
+ where: { id: id },
+ })
+
+ // NOTE: this gon change a bit when there are also collaborators
+ // @ts-ignore
+ if (transaction.userId !== userId) {
+ throw new Error("forbidden")
+ }
+
+ return transaction
+}
+
// TODO: ig collaborated transactions would need more logic
const del = async (userId: Number, transactionId: String) => {
const t = await prisma.transaction.findUnique({
@@ -66,5 +81,6 @@ const del = async (userId: Number, transactionId: String) => {
export {
create,
read,
+ readOne,
del
}