import legacy frontend & fix dependency issues
This commit is contained in:
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}\\dist\\index.js",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/**/*.js"
|
||||
],
|
||||
"env": {
|
||||
"TKD_DB_USER": "webapi",
|
||||
"TKD_DB_PASSWORD": "devpassword",
|
||||
"TKD_DB_HOST": "localhost",
|
||||
"TKD_COOKIE_SECRET": "devsecret"
|
||||
},
|
||||
"runtimeExecutable": "C:\\Users\\Toni\\AppData\\Roaming\\fnm\\aliases\\default\\node"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,3 +21,5 @@ CREATE DATABASE keycloak
|
||||
-- replace Frontend redirect URLS in realm-export.json
|
||||
-- SET NODE_ENV=production when running on server
|
||||
-- SET DEFAULT_PERSISSIONS for webapi user
|
||||
-- add backend to allowed redirect urls in forntenc kc-client
|
||||
-- fix web origins for kc-clients
|
||||
|
||||
+14
-18
@@ -3,38 +3,34 @@
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "node dist/index.js",
|
||||
"build": "tsc -p .",
|
||||
"dev": "run-script-os",
|
||||
"dev:win32": "wsl -- bash -ic 'pnpm run dev:linux'",
|
||||
"dev:linux": "./scripts/dev.sh"
|
||||
"build": "tsc -p ."
|
||||
},
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/connect-pg-simple": "^7.0.3",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/connect-pg-simple": "^7.0.3",
|
||||
"@types/express": "^5.0.5",
|
||||
"@types/express-session": "^1.18.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/node": "^24.9.2",
|
||||
"@types/pg": "^8.15.6",
|
||||
"dotenv": "^17.2.3",
|
||||
"prisma": "^7.1.0",
|
||||
"run-script-os": "^1.1.6",
|
||||
"tsx": "^4.21.0",
|
||||
"prisma": "^7.0.1",
|
||||
"tsx": "^4.20.6",
|
||||
"typescript": "~5.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keycloak/keycloak-admin-client": "^26.4.7",
|
||||
"@prisma/adapter-pg": "^7.1.0",
|
||||
"@prisma/client": "^7.1.0",
|
||||
"cors": "^2.8.5",
|
||||
"rxjs": "~7.8.2",
|
||||
"@keycloak/keycloak-admin-client": "^26.4.4",
|
||||
"@prisma/adapter-pg": "^7.0.1",
|
||||
"@prisma/client": "^7.0.1",
|
||||
"@tsoa/runtime": "^6.6.0",
|
||||
"connect-pg-simple": "^10.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^5.2.1",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^5.1.0",
|
||||
"express-session": "^1.18.2",
|
||||
"keycloak-connect": "^26.1.1",
|
||||
"pg": "^8.16.3",
|
||||
"rxjs": "~7.8.2"
|
||||
"pg": "^8.16.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import {
|
||||
SuccessResponse,
|
||||
} from "@tsoa/runtime";
|
||||
import express from "express";
|
||||
import { Claim } from "../dtos/claim.js";
|
||||
import type { Member, MemberCreateArgs } from "../dtos/member.js";
|
||||
import { inject } from "../infrastructure/di/index.js";
|
||||
import { ErrorStates } from "../infrastructure/errorStates.js";
|
||||
import { Claim } from "../models/claim.js";
|
||||
import type { Member, MemberCreateArgs } from "../models/member.js";
|
||||
import { KC_SECURITY_NAME } from "../services/keycloak/user/index.js";
|
||||
import { MembersService } from "../services/membersService.js";
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
Security,
|
||||
SuccessResponse,
|
||||
} from "@tsoa/runtime";
|
||||
import { Claim } from "../dtos/claim.js";
|
||||
import { type User } from "../dtos/user.js";
|
||||
import { inject } from "../infrastructure/di/index.js";
|
||||
import { Claim } from "../models/claim.js";
|
||||
import { type User } from "../models/user.js";
|
||||
import { KC_SECURITY_NAME } from "../services/keycloak/user/index.js";
|
||||
import { UserService } from "../services/userService.js";
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { type MemberModel as DbMember } from "../generated/prisma/models.js";
|
||||
|
||||
export interface Member {
|
||||
id?: string | null;
|
||||
vorname?: string | null;
|
||||
nachname?: string | null;
|
||||
geburtsdatum?: Date | null;
|
||||
geburtsort?: string | null;
|
||||
geschlecht?: string | null;
|
||||
passnummer?: string | null;
|
||||
uvertrag?: boolean | null;
|
||||
verein?: boolean | null;
|
||||
graduierung?: string | null;
|
||||
letztePruefung?: Date | null;
|
||||
kontakt?: string | null;
|
||||
kuendigungzum?: Date | null;
|
||||
loeschenam?: string | null;
|
||||
id: string | null;
|
||||
vorname: string | null;
|
||||
nachname: string | null;
|
||||
geburtsdatum: Date | null;
|
||||
geburtsort: string | null;
|
||||
geschlecht: string | null;
|
||||
passnummer: string | null;
|
||||
uvertrag: boolean | null;
|
||||
verein: boolean | null;
|
||||
graduierung: string | null;
|
||||
letztePruefung: Date | null;
|
||||
kontakt: string | null;
|
||||
kuendigungzum: Date | null;
|
||||
loeschenam: Date | null;
|
||||
}
|
||||
|
||||
export type MemberCreateArgs = Omit<Member, "id" | "loeschenam">;
|
||||
@@ -34,5 +34,6 @@ export function mapDbMemberToMember(dbMember: DbMember): Member {
|
||||
passnummer: dbMember.passnummer,
|
||||
uvertrag: dbMember.uvertrag,
|
||||
verein: dbMember.verein,
|
||||
loeschenam: new Date(), //TODO
|
||||
};
|
||||
}
|
||||
@@ -14,7 +14,6 @@ const app = express();
|
||||
|
||||
app.use(sessionHandler);
|
||||
app.use(keycloak.middleware());
|
||||
// console.log("not using", keycloak.middleware);
|
||||
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
@@ -25,6 +24,8 @@ app.use(
|
||||
"https://tcc-1-ev-intern.web.app",
|
||||
"http://localhost:4200",
|
||||
"https://localhost:4200",
|
||||
"http://localhost:3000",
|
||||
"http://localhost:8080",
|
||||
],
|
||||
//TODO reevaluate
|
||||
}),
|
||||
|
||||
@@ -8,8 +8,11 @@ function promisifyMiddleware(
|
||||
response?: Response,
|
||||
): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
middleware(request, response || ({} as any), (result: any) => {
|
||||
result instanceof Error ? reject(result) : resolve(result);
|
||||
middleware(request, response || ({} as any), (next_result: any) => {
|
||||
console.dir(next_result);
|
||||
next_result instanceof Error
|
||||
? reject(next_result)
|
||||
: resolve(next_result);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -20,10 +23,15 @@ async function doKeycloakAuth(
|
||||
response?: Response,
|
||||
): Promise<any> {
|
||||
if (roles && roles.length > 0) {
|
||||
return await promisifyMiddleware(
|
||||
request,
|
||||
keycloak.enforcer(roles?.map(role => `realm:${role}`)),
|
||||
const grant = await keycloak.getGrant(request, response ?? ({} as any));
|
||||
const allowed = roles.every(role =>
|
||||
grant.access_token?.hasRealmRole(role),
|
||||
);
|
||||
if (allowed) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(httpError(403, "Forbidden"));
|
||||
}
|
||||
} else {
|
||||
return await promisifyMiddleware(request, keycloak.protect(), response);
|
||||
}
|
||||
@@ -35,12 +43,21 @@ export async function expressAuthentication(
|
||||
roles?: string[],
|
||||
response?: Response,
|
||||
): Promise<any> {
|
||||
if (request.method === "OPTIONS") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
switch (securityName) {
|
||||
case KC_SECURITY_NAME:
|
||||
return doKeycloakAuth(request, roles, response);
|
||||
return await doKeycloakAuth(request, roles, response);
|
||||
case undefined:
|
||||
return Promise.resolve();
|
||||
default:
|
||||
return Promise.reject("Unknown security name");
|
||||
return Promise.reject(httpError(400, "Unknown security name"));
|
||||
}
|
||||
}
|
||||
|
||||
function httpError(status: number, message: string) {
|
||||
const err: any = new Error(message);
|
||||
err.status = status;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import { PrismaClient } from "../../generated/prisma/client.js";
|
||||
import { Injectable } from "../../infrastructure/di/injectable-decorator.js";
|
||||
|
||||
type ExtendedClient = ReturnType<typeof createExtendedClient>;
|
||||
type TransactionClient = Omit<
|
||||
ExtendedClient,
|
||||
"$connect" | "$disconnect" | "$on" | "$transaction" | "$extends"
|
||||
>;
|
||||
// type TransactionClient = Omit<
|
||||
// ExtendedClient,
|
||||
// "$connect" | "$disconnect" | "$on" | "$transaction" | "$extends"
|
||||
// >;
|
||||
|
||||
export type SafeClient = Omit<
|
||||
ExtendedClient,
|
||||
@@ -58,13 +58,8 @@ export class DatabaseService {
|
||||
command: (prisma: SafeClient) => Promise<T>,
|
||||
request: Request,
|
||||
): Promise<T> {
|
||||
const transaction = (request as any).transaction as SafeClient;
|
||||
const transaction =
|
||||
(request as any).transaction ?? (this.prismaClient as SafeClient);
|
||||
return await command(transaction);
|
||||
}
|
||||
|
||||
public async createTransaction(
|
||||
action: (prisma: TransactionClient) => Promise<void>,
|
||||
) {
|
||||
await this.prismaClient.$transaction(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import kcClientConfig from "./nodejs-api.json" with { type: "json" };
|
||||
|
||||
import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation.js";
|
||||
import { Claim } from "../../../models/claim.js";
|
||||
import { type User } from "../../../models/user.js";
|
||||
import { Claim } from "../../../dtos/claim.js";
|
||||
import { type User } from "../../../dtos/user.js";
|
||||
|
||||
@Injectable()
|
||||
export class KeycloakAdmin {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"realm": "taekwondo",
|
||||
"auth-server-url": "https://localhost:8080",
|
||||
"ssl-required": "external",
|
||||
"resource": "nodejs-api",
|
||||
"credentials": {
|
||||
"secret": "devsecret"
|
||||
},
|
||||
"confidential-port": 0
|
||||
"realm": "taekwondo",
|
||||
"auth-server-url": "http://localhost:8080/",
|
||||
"ssl-required": "external",
|
||||
"resource": "angular-frontend",
|
||||
"public-client": true,
|
||||
"confidential-port": 0
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import express from "express";
|
||||
import { inject, Injectable } from "../infrastructure/di/index.js";
|
||||
import { ErrorStates } from "../infrastructure/errorStates.js";
|
||||
import {
|
||||
type Member,
|
||||
type MemberCreateArgs,
|
||||
mapDbMemberToMember,
|
||||
} from "../models/member.js";
|
||||
} from "../dtos/member.js";
|
||||
import { inject, Injectable } from "../infrastructure/di/index.js";
|
||||
import { ErrorStates } from "../infrastructure/errorStates.js";
|
||||
import { DatabaseService } from "./db/prisma.js";
|
||||
|
||||
@Injectable()
|
||||
@@ -43,6 +43,10 @@ export class MembersService {
|
||||
createArgs: MemberCreateArgs,
|
||||
request: express.Request,
|
||||
): Promise<Member> {
|
||||
const x: MemberCreateArgs = {
|
||||
...createArgs,
|
||||
geburtsdatum: createArgs.geburtsdatum ?? null,
|
||||
};
|
||||
const newMember = await this.database.doRequest(
|
||||
async prisma => await prisma.member.create({ data: createArgs }),
|
||||
request,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Claim } from "../dtos/claim.js";
|
||||
import { type User } from "../dtos/user.js";
|
||||
import { inject } from "../infrastructure/di/index.js";
|
||||
import { Claim } from "../models/claim.js";
|
||||
import { type User } from "../models/user.js";
|
||||
import { KeycloakAdmin } from "./keycloak/admin/index.js";
|
||||
|
||||
export class UserService {
|
||||
|
||||
Reference in New Issue
Block a user