some updates

This commit is contained in:
2024-04-05 18:04:29 +02:00
parent 45decc60a7
commit e82b753dfb
19 changed files with 5343 additions and 17922 deletions

8124
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@
},
"license": "MIT",
"dependencies": {
"@koa/cors": "^4.0.0",
"@koa/cors": "^5",
"@koa/router": "^12.0.0",
"bcrypt": "^5.1.0",
"class-validator": "^0.14.0",
@@ -43,16 +43,17 @@
"@types/deasync": "^0.1.2",
"@types/eslint": "^8.44.1",
"@types/eslint-config-prettier": "^6.11.0",
"@types/eslint-plugin-mocha": "^10.4.0",
"@types/eslint-plugin-prettier": "^3.1.0",
"@types/hasha": "^3.0.1",
"@types/jsonwebtoken": "^9.0.2",
"@types/koa": "^2.13.7",
"@types/koa__cors": "^4.0.0",
"@types/koa__router": "^12.0.0",
"@types/koa-logger": "^3.1.2",
"@types/koa-send": "^4.1.3",
"@types/koa-sslify": "^4.0.3",
"@types/koa-static": "^4.0.2",
"@types/koa__cors": "^4.0.0",
"@types/koa__router": "^12.0.0",
"@types/mime-types": "^2.1.1",
"@types/mocha": "^10.0.1",
"@types/mysql": "^2.15.21",

View File

@@ -52,7 +52,7 @@ export async function getConfigValue(key: ConfigKey): Promise<string> {
}
try {
const pair = await Config.findOneOrFail({ key });
const pair = await Config.findOneOrFail({ key }, {});
return pair.value;
} catch (e) {
return defaultValues[key];
@@ -67,7 +67,7 @@ export async function setConfigValue(
throw new Error(`${key} is not valid config key`);
}
let pair = await Config.findOne({ key });
let pair = await Config.findOne({ key }, {});
if (!pair) {
pair = new Config(key, val);
} else {

View File

@@ -1,26 +1,26 @@
import * as Router from "@koa/router";
import { Photo } from "~entity/Photo";
import {
TPhotoReqJSON,
TPhotosNewRespBody,
TPhotoByIDDeleteRespBody,
TPhotosUploadRespBody,
TPhotosListRespBody,
TPhotosByIDGetRespBody,
TPhotosDeleteRespBody,
PhotoJSON,
PhotosDeleteBody,
PhotosListPagination,
PhotosNewPostBody,
PhotoJSON,
TPhotoByIDDeleteRespBody,
TPhotoReqJSON,
TPhotosByIDGetRespBody,
TPhotosDeleteRespBody,
TPhotosGetShowTokenByIDRespBody,
PhotosDeleteBody,
TPhotosListRespBody,
TPhotosNewRespBody,
TPhotosUploadRespBody,
} from "~/shared/types";
import send = require("koa-send");
import { getHash, getSize } from "~util";
import * as jwt from "jsonwebtoken";
import { config } from "~config";
import { ValidationError } from "class-validator";
import { In } from "typeorm";
import { IAppContext, IAppState } from "~app";
import send = require("koa-send");
export const photosRouter = new Router<IAppState, IAppContext>();
@@ -44,7 +44,7 @@ photosRouter.post("/photos/new", async (ctx: ContextType) => {
await photo.save();
} catch (e) {
if (e.code === "ER_DUP_ENTRY") {
const photo = await Photo.findOne({ hash, size, user });
const photo = await Photo.findOne({ hash, size, user }, {});
if (!photo) {
ctx.throw(404);
}
@@ -85,7 +85,7 @@ photosRouter.post("/photos/upload/:id", async (ctx: ContextType) => {
}
const { user } = ctx.state;
const photo = await Photo.findOne({ id: parseInt(id), user });
const photo = await Photo.findOne({ id: parseInt(id), user }, {});
if (!photo) {
ctx.throw(404);
}
@@ -131,47 +131,47 @@ photosRouter.post("/photos/upload/:id", async (ctx: ContextType) => {
});
/**
export interface TPhotosByIDPatchBody {
}
export type TPhotosByIDPatchRespBody = IAPIResponse<TPhotoReqJSON>;
photosRouter.patch("/photos/byID/:id", async (ctx: ContextType) => {
if (!ctx.state.user) {
ctx.throw(401);
return;
}
const { user } = ctx.state;
const { id } = ctx.params as {
id: number | undefined;
};
if (!id) {
ctx.throw(400);
return;
}
const photo = await Photo.findOne({ id, user });
if (!photo) {
ctx.throw(404);
return;
}
// TODO: Some actual editing
try {
photo.editedAt = new Date();
await photo.save();
} catch (e) {
ctx.throw(400);
}
ctx.body = {
error: false,
data: photo.toReqJSON(),
};
});
*/
export interface TPhotosByIDPatchBody {
}
export type TPhotosByIDPatchRespBody = IAPIResponse<TPhotoReqJSON>;
photosRouter.patch("/photos/byID/:id", async (ctx: ContextType) => {
if (!ctx.state.user) {
ctx.throw(401);
return;
}
const { user } = ctx.state;
const { id } = ctx.params as {
id: number | undefined;
};
if (!id) {
ctx.throw(400);
return;
}
const photo = await Photo.findOne({ id, user },{});
if (!photo) {
ctx.throw(404);
return;
}
// TODO: Some actual editing
try {
photo.editedAt = new Date();
await photo.save();
} catch (e) {
ctx.throw(400);
}
ctx.body = {
error: false,
data: photo.toReqJSON(),
};
});
*/
photosRouter.get("/photos/list", async (ctx: ContextType) => {
if (!ctx.state.user) {
@@ -229,7 +229,7 @@ photosRouter.get("/photos/byID/:id", async (ctx: ContextType) => {
const { user } = ctx.state;
const photo = await Photo.findOne({ id: parseInt(id), user });
const photo = await Photo.findOne({ id: parseInt(id), user }, {});
if (!photo) {
ctx.throw(404);
@@ -260,10 +260,13 @@ photosRouter.get("/photos/showByID/:id/:token", async (ctx: ContextType) => {
const photoReqJSON = PhotoJSON.parse(jwt.decode(token));
const { user } = photoReqJSON;
const photo = await Photo.findOne({
id: parseInt(id),
user: { id: user },
});
const photo = await Photo.findOne(
{
id: parseInt(id),
user: { id: user },
},
{},
);
if (!photo) {
ctx.throw(404);
@@ -296,7 +299,7 @@ photosRouter.get("/photos/showByID/:id", async (ctx: ContextType) => {
const { user } = ctx.state;
const photo = await Photo.findOne({ id: parseInt(id), user });
const photo = await Photo.findOne({ id: parseInt(id), user }, {});
if (!photo) {
ctx.throw(404);
@@ -329,7 +332,7 @@ photosRouter.get("/photos/getShowByIDToken/:id", async (ctx: ContextType) => {
const { user } = ctx.state;
const photo = await Photo.findOne({ id: parseInt(id), user });
const photo = await Photo.findOne({ id: parseInt(id), user }, {});
if (!photo) {
ctx.throw(404);
}
@@ -354,7 +357,7 @@ photosRouter.delete("/photos/byID/:id", async (ctx: ContextType) => {
const { user } = ctx.state;
const photo = await Photo.findOne({ id: parseInt(id), user });
const photo = await Photo.findOne({ id: parseInt(id), user }, {});
if (!photo) {
ctx.throw(404);

View File

@@ -1,18 +1,14 @@
import * as Router from "@koa/router";
import { getConfigValue, ConfigKey } from "~entity/Config";
import { ConfigKey, getConfigValue } from "~entity/Config";
import { User } from "~entity/User";
import {
TUserJWT,
TUserGetRespBody,
TUserEditRespBody,
TUserSignupBody,
TUserSignupRespBody,
TUserGetRespBody,
TUserLoginRespBody,
TUserEditBody,
TUserLoginBody,
TUserSignupRespBody,
UserEditBody,
UserLoginBody,
UserSignupBody,
UserEditBody,
} from "~/shared/types";
import { IAppContext, IAppState } from "~app";
@@ -28,7 +24,7 @@ userRouter.get("/users/user", async (ctx: ContextType) => {
}
const jwt = ctx.state.user;
const user = await User.findOne(jwt.id);
const user = await User.findOne(jwt.id, {});
if (!user) {
ctx.throw(401);
@@ -45,7 +41,7 @@ userRouter.post("/users/login", async (ctx: ContextType) => {
}
const { username, password } = UserLoginBody.parse(request.body);
const user = await User.findOne({ username });
const user = await User.findOne({ username }, {});
if (!user || !(await user.verifyPassword(password))) {
ctx.throw(404, "User not found");
}
@@ -95,7 +91,7 @@ userRouter.post("/users/edit", async (ctx: ContextType) => {
}
const jwt = ctx.state.user;
const user = await User.findOne(jwt.id);
const user = await User.findOne(jwt.id, {});
const request = ctx.request;
if (!user) {

View File

@@ -86,7 +86,9 @@ describe("photos", function () {
Authorization: `Bearer ${seed.user2.toJWT()}`,
})
.expect(200);
expect(parseInt(response.get("content-length"))).to.equal(dogFileSize);
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogFileSize,
);
});
it("should delete a photo after file has been deleted", async function () {
@@ -96,7 +98,9 @@ describe("photos", function () {
Authorization: `Bearer ${seed.user2.toJWT()}`,
})
.expect(200);
expect(parseInt(response.get("content-length"))).to.equal(dogFileSize);
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogFileSize,
);
await fs.unlink(await seed.dogPhoto.getReadyPath("original"));
await request(callback)
@@ -119,7 +123,7 @@ describe("photos", function () {
const dogSmallThumbSize = (
await fs.stat(seed.dogPhoto.getThumbPath("512"))
).size;
expect(parseInt(response.get("content-length"))).to.equal(
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogSmallThumbSize,
);
@@ -143,7 +147,7 @@ describe("photos", function () {
Authorization: `Bearer ${seed.user2.toJWT()}`,
})
.expect(200);
expect(parseInt(response.get("content-length"))).to.be.lessThan(
expect(parseInt(response.get("content-length") ?? "")).to.be.lessThan(
dogFileSize,
);
});
@@ -158,7 +162,7 @@ describe("photos", function () {
const dogSmallThumbSize = (
await fs.stat(seed.dogPhoto.getThumbPath("512"))
).size;
expect(parseInt(response.get("content-length"))).to.equal(
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogSmallThumbSize,
);
@@ -172,7 +176,7 @@ describe("photos", function () {
const dogSmallThumbSize2 = (
await fs.stat(seed.dogPhoto.getThumbPath("512"))
).size;
expect(parseInt(response.get("content-length"))).to.equal(
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogSmallThumbSize2,
);
});
@@ -198,7 +202,7 @@ describe("photos", function () {
const listAnyResp = await request(callback)
.get(`/photos/showByID/${photos[0].id}/${photos[0].accessToken}`)
.expect(200);
expect(parseInt(listAnyResp.get("content-length"))).to.be.oneOf([
expect(parseInt(listAnyResp.get("content-length") ?? "")).to.be.oneOf([
dogFileSize,
catFileSize,
]);
@@ -216,7 +220,9 @@ describe("photos", function () {
const response = await request(callback)
.get(`/photos/showByID/${seed.dogPhoto.id}/${token}`)
.expect(200);
expect(parseInt(response.get("content-length"))).to.equal(dogFileSize);
expect(parseInt(response.get("content-length") ?? "")).to.equal(
dogFileSize,
);
const tokenSelfSigned = jwt.sign(
await seed.dogPhoto.toReqJSON(),
@@ -229,7 +235,7 @@ describe("photos", function () {
const responseSS = await request(callback)
.get(`/photos/showByID/${seed.dogPhoto.id}/${tokenSelfSigned}`)
.expect(200);
expect(parseInt(responseSS.get("content-length"))).to.equal(
expect(parseInt(responseSS.get("content-length") ?? "")).to.equal(
dogFileSize,
);
});
@@ -312,7 +318,9 @@ describe("photos", function () {
})
.expect(200);
expect(parseInt(showResp.get("content-length"))).to.equal(dogFileSize);
expect(parseInt(showResp.get("content-length") ?? "")).to.equal(
dogFileSize,
);
});
it("should create, upload and show a png file", async function () {
@@ -370,7 +378,9 @@ describe("photos", function () {
})
.expect(200);
expect(parseInt(showResp.get("content-length"))).to.equal(pngFileSize);
expect(parseInt(showResp.get("content-length") ?? "")).to.equal(
pngFileSize,
);
});
it("should not create a photo twice", async function () {
@@ -464,7 +474,9 @@ describe("photos", function () {
})
.expect(200);
expect(parseInt(showResp.get("content-length"))).to.equal(dogFileSize);
expect(parseInt(showResp.get("content-length") ?? "")).to.equal(
dogFileSize,
);
});
it("should not upload a wrong photo", async function () {