Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend fixes #172

Merged
merged 29 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
67dbe9f
Move uuid from devDependencies to dependencies
gf-rog Apr 26, 2024
dfe2ab3
Remove data folder
gf-rog Apr 27, 2024
5594671
Rename db.ts to importDb.ts
gf-rog Apr 27, 2024
12034e6
Move driver.ts to /src
gf-rog Apr 27, 2024
1f8b978
Move server setup code to correct places
gf-rog Apr 27, 2024
084b29f
Apply formatting
gf-rog May 2, 2024
7ee6403
Merge branch 'tests' into backend-fixes
gf-rog May 14, 2024
f96b203
Don't restart backend if tests changed
gf-rog May 14, 2024
a041f3a
Add token parameter
gf-rog May 14, 2024
4b26923
Add authorization to user CRUD
gf-rog May 14, 2024
b8f852b
Use token introspection endpoint instead of userinfo
gf-rog May 15, 2024
40203cb
Print response if request failed
gf-rog May 15, 2024
fb92fdc
Add authorization to user friend requests
gf-rog May 15, 2024
e26477e
Add authorization to chat requests
gf-rog May 15, 2024
28dfced
Remove unused meeting endpoints
gf-rog May 15, 2024
b630f27
Add token parameter to frontend fetchData
gf-rog May 15, 2024
32f4229
Fix frontend authorization
gf-rog May 15, 2024
2a3f212
Merge pull request #171 from Karol-2/frontend-auth-fix
Piterson25 May 15, 2024
4548737
Refactor tests for more readability
Piterson25 May 15, 2024
165317d
Add authorization to user friends
gf-rog May 15, 2024
fa21c27
Fix endpoints not checking the token user ID
gf-rog May 16, 2024
8973b0b
Add authorization to user friend suggestions
gf-rog May 16, 2024
5b4c87b
Fix issuers not exported
gf-rog May 16, 2024
2ccd6d9
Add @ianvs/prettier-plugin-sort-imports
gf-rog May 16, 2024
c25cce2
Ignore non-code folders when formatting code
gf-rog May 16, 2024
8ce797c
Add blank lines between import groups
gf-rog May 16, 2024
e99a597
Merge remote-tracking branch 'origin/dev' into backend-fixes
gf-rog May 16, 2024
4428e05
Apply formatting
gf-rog May 16, 2024
2b32909
Remove debug console.log
gf-rog May 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
node_modules/
coverage/
coverage/
frontend/.vite/
keycloak/
db/
4 changes: 3 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
"endOfLine": "lf",
"semi": true,
"bracketSpacing": true,
"quoteProps": "preserve"
"quoteProps": "preserve",
"plugins": ["@ianvs/prettier-plugin-sort-imports"],
"importOrder": ["<BUILTIN_MODULES>", "", "<THIRD_PARTY_MODULES>", "", "^[.]"]
}
6 changes: 2 additions & 4 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"neo4j-driver": "^5.13.0",
"socket.io": "^4.7.2",
"unidecode": "^0.1.8",
"uuid": "^9.0.1",
"vite": "^5.2.6",
"zod": "^3.22.4"
},
Expand All @@ -42,7 +43,6 @@
"tsc-watch": "^6.0.4",
"tsx": "^4.7.1",
"typescript": "^5.2.2",
"uuid": "^9.0.1",
"vitest": "^0.34.6"
}
}
File renamed without changes.
37 changes: 29 additions & 8 deletions backend/src/httpServer.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
import dotenv from "dotenv";
import servers from "./server.js";
import usersRouter from "./routes/usersRoute.js";
import { createServer } from "node:http";

import cookieParser from "cookie-parser";
import cors from "cors";
import express from "express";

import authRouter from "./routes/authRoute.js";
import chatRouter from "./routes/chatRoute.js";
import { cleanUpData, importInitialData } from "./db.js";
import usersRouter from "./routes/usersRoute.js";

const { app } = servers;
const app = express();
const port: number = 5000;

dotenv.config();
const corsOptions = {
origin: ["http://localhost:5000", "http://localhost:5173"],
optionsSuccessStatus: 200,
};

cleanUpData();
importInitialData().then((res) => console.log(res));
app.use(cors(corsOptions));
app.use((_req, res, next) => {
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
app.use(cookieParser());
app.use(express.json({ limit: "10mb" }));

const expressServer = createServer(app);

expressServer.listen(port, () => {
console.log(`HTTP server running on port ${port}`);
});

app.use("/users", usersRouter);
app.use("/auth", authRouter);
app.use("/chat", chatRouter);

export { expressServer };
7 changes: 3 additions & 4 deletions backend/src/db.ts → backend/src/importDb.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import driver from "./driver/driver.js";

import userData from "./data/users.js";
import { registerUser, registerUserSchema } from "./users.js";
import driver from "./driver.js";
import userData from "./userData.js";
import { addFriend } from "./userFriends.js";
import { registerUser, registerUserSchema } from "./users.js";

export async function isDatabaseEmpty() {
const session = driver.session();
Expand Down
16 changes: 16 additions & 0 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
import "dotenv/config";
import "./httpServer.js";
import "./socketServer.js";
import "./kcAdminClient.js";

import { connect } from "mongoose";

import { cleanUpData, importInitialData } from "./importDb.js";

cleanUpData();
importInitialData().then((res) => console.log(res));

try {
const uri = process.env.MONGODB_URI || "mongodb://localhost:27017";
await connect(`${uri}/chats`);
console.log("Chat database started");
} catch (err) {
console.error(err);
}
3 changes: 3 additions & 0 deletions backend/src/kcAdminClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import KeycloakAdminClient from "@keycloak/keycloak-admin-client";

export const keycloakUri = process.env.KEYCLOAK_URI || "http://localhost:3000";
export const keycloakIssuer = process.env.KEYCLOAK_ISSUER || keycloakUri;
export const keycloakCredentials = Buffer.from(
`mercury-backend:${process.env.CLIENT_SECRET}`,
).toString("base64");

const kcAdminClient = new KeycloakAdminClient({
baseUrl: keycloakUri,
Expand Down
1 change: 1 addition & 0 deletions backend/src/meetings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Session } from "neo4j-driver";
import { v4 as uuidv4 } from "uuid";

import Meeting from "./models/Meeting.js";

export async function isInMeeting(session: Session, userId: string) {
Expand Down
14 changes: 13 additions & 1 deletion backend/src/misc/fetchData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
export const fetchData = async (url: string, method: string, options = {}) => {
export const fetchData = async (
url: string,
method: string,
options: RequestInit = {},
token?: string,
) => {
if (token) {
options.headers = {
...options.headers,
"Authorization": `Bearer ${token}`,
};
}

try {
const response = await fetch(url, { ...options, method });
const data = await response.json();
Expand Down
1 change: 1 addition & 0 deletions backend/src/misc/formatError.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ZodError } from "zod";

import { Errors } from "../models/Response.js";

export function formatError<T>(error: ZodError<T>): Errors {
Expand Down
21 changes: 14 additions & 7 deletions backend/src/misc/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { Request, Response, NextFunction } from "express";
import { NextFunction, Request, Response } from "express";
import jwt from "jsonwebtoken";
import { AuthResponse, CustomResponse } from "../models/Response.js";

import {
keycloakCredentials,
keycloakIssuer,
keycloakUri,
} from "../kcAdminClient.js";
import DecodedData from "../models/DecodedData.js";
import Issuer from "../models/Issuer.js";
import { AuthResponse, CustomResponse } from "../models/Response.js";
import TokenPayload from "../models/TokenPayload.js";
import { keycloakIssuer, keycloakUri } from "../kcAdminClient.js";

export interface JWTRequest extends Request {
token?: TokenPayload;
tokenStr?: string;
}

const issuers: Record<Issuer, string> = {
export const issuers: Record<Issuer, string> = {
mercury: `${keycloakIssuer}/realms/mercury`,
rest: "http://localhost:5000",
};
Expand All @@ -37,12 +42,14 @@ function tokenIssuerToName(issuer: string): Issuer | "unknown" {

export async function verifyKeycloakToken(tokenStr: string): Promise<boolean> {
const response = await fetch(
`${keycloakUri}/realms/mercury/protocol/openid-connect/userinfo`,
`${keycloakUri}/realms/mercury/protocol/openid-connect/token/introspect`,
{
method: "GET",
method: "POST",
headers: {
"Authorization": `Bearer ${tokenStr}`,
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${keycloakCredentials}`,
},
body: `token=${tokenStr}`,
},
);

Expand Down
1 change: 1 addition & 0 deletions backend/src/models/ChangePasswordReq.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from "zod";

import { userPasswordSchema } from "./User.js";

type ChangePasswordReq =
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/NativeUser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZodType, z } from "zod";
import { z, ZodType } from "zod";

type NativeUser = {
password: string;
Expand Down
10 changes: 8 additions & 2 deletions backend/src/models/Response.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import User from "./User.js";

import { Response } from "express";

import Message from "./Message.js";
import User from "./User.js";

type Send<J, T = Response> = (body?: J) => T;

export interface CustomResponse<J> extends Response {
Expand Down Expand Up @@ -60,6 +61,11 @@ export interface UsersSearchResponse {
users: User[];
}

export interface MessagesResponse {
status: "ok";
messages: Message[];
}

export interface JWTResponse extends OkResponse {
token: string;
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/User.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZodType, z } from "zod";
import { z, ZodType } from "zod";

export default interface User {
id: string;
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/routes/Page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZodType, z } from "zod";
import { z, ZodType } from "zod";

interface Page {
page: string | number;
Expand Down
5 changes: 3 additions & 2 deletions backend/src/models/routes/Search.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ZodType, z } from "zod";
import Page, { pageSchema } from "./Page.js";
import { z, ZodType } from "zod";

import { userCountrySchema } from "../User.js";
import Page, { pageSchema } from "./Page.js";

interface Search extends Page {
q: string;
Expand Down
1 change: 1 addition & 0 deletions backend/src/mongoDB/MessageModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { model, Schema } from "mongoose";

import Message from "../models/Message.js";

const chatSchema = new Schema<Message>({
Expand Down
14 changes: 6 additions & 8 deletions backend/src/routes/authRoute.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { Router, Request } from "express";

import bcrypt from "bcrypt";
import { Request, Router } from "express";
import jwt, { JwtPayload } from "jsonwebtoken";

import driver from "../driver/driver.js";
import driver from "../driver.js";
import { leaveMeeting } from "../meetings.js";
import {
JWTRequest,
authenticateToken,
generateAccessToken,
generateRefreshToken,
JWTRequest,
} from "../misc/jwt.js";

import jwt, { JwtPayload } from "jsonwebtoken";
import { Errors } from "../models/Response.js";
import { TokenErrorResponse } from "../types/authResponse.js";
import { OkErrorResponse } from "../types/userResponse.js";
import { leaveMeeting } from "../meetings.js";
import { getDbUser } from "../users.js";
import { Errors } from "../models/Response.js";

const authRouter = Router();

Expand Down
Loading
Loading