Authentication with firebase, Landing Page 1.Teil
This commit is contained in:
5
api/.env
5
api/.env
@@ -1,2 +1,5 @@
|
||||
DB_FILE_NAME=file:local.db
|
||||
PORT=3000
|
||||
PORT=3000
|
||||
FIREBASE_PROJECT_ID=haiki-452bd
|
||||
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-fbsvc@haiki-452bd.iam.gserviceaccount.com
|
||||
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDyCsRhtPYwozBy\n60A4LguqsFzJG0WwCMhvi7PIxoh1kVenwxXBBQHvgssF/jPTkqbK6orL9r15gdRc\nZK2S73OdESYlO9xCE+gq/pop1F432DrHBA6ftQIl2NHSQfkKgTKFM6Pt85e6s5mb\neIxxHr7AzGMlqu7UJbnw8Vk2+8LP3NZXwsyCEi5vg4+8UgPFVxhLnB4HYZIM8JOj\nM3q1N/KqKgl2qGl5ekZLN7QLPs6+znlVZVIeHo1vuX9xTUaa6XUA0xeZfFO3pNUd\nKLlQNAy7OFQ6GlTFTWWHnShecLPHLQdWP15rkwBPv1q7qDmtLMy4E2XLvsoErhJM\niFsbEczxAgMBAAECggEAJqGJTn7vfDvPk8fwbAcNXaTgakisCricJRGLFFR7mygj\ncWc1paUC9hNODBrScsZJUMG2fW9YNnh+SHDZM0Z8kWkXSYIQWYuL1rDkMiDvGMKu\nPu1q2BqvyRKeCoz1DrQoOBJR67yhTu8zaRkIcVWS5Hq6qFxr2fhbgRVEQ/5SzZIG\nPh+Npxdp62Xe66MB0OzmF/A5qSrXTpOOk4/Lmpoqf6PtmrOD+SetE+Aa6ELYX3pK\n30XPLiUyDS+EFPjHLA1U7frOawLRpMP6Iobu7hUzu9ASzgLKxpzbcGRsPtbVRuAQ\nzP+iV+Nyn/wMFbnnjrjlwk/jqE+NLGJnf7Jrc9vwQQKBgQD5lfRWR6MKDezty5Qu\nPGrSlKXOM+aOoTmZiaPTutYzwWHeqzfUfYsghbgR3jl7I0BTqMaGrOnYU60IDWZi\nJeK6iu68pUe8Mme3vXm15Go55UhZD9U5/4W+x0/+AVivBPUBwKUXFdgmPFkb2jBY\np1LJmXaelx2jvPM3yMXQN+5flQKBgQD4Qy6aF3V7DIVxo/F88KCGNUpEobyXsxv6\nakSV+7WEtuSf6amXHxZyiJPtjCIwzCUL458gUd6mwiQgWRy7awdKreU6BCHgqNVf\nAE5ahjeeiLOc1uu0ocNLL+g35DbBXSgSlB+hUE0+bxAxU9xjNc9UZKqIi/kGRP/G\nlxi2ZUIQ7QKBgQDUH5Ku0evL29IGuQOT2F2h5ByXiJznlDd0Ovs2NJFhI3ae3T5y\nJtFcLsomxYxtD6TYdZVlWQjWhyeEtH7T5AczLGmDg6XYWa61ByCuaxetZSV8LGy5\nAmcVoihmZZaOCdSCTM0DNdmjhZ7mgSad8nf2R6v9VconI6xDOSyGr0K1kQKBgQCp\nuhxxIpqhzlSo9aFSfpvwRRyKQVzTBZOaJu7O7zARFIzHOxNDivBoyzD/FXAGlnq5\nXxvaF761mULjjqjTBQAOMUbm3A5hLmv5sBbhUqNR0jmhf1nTu0ft7km/dFlu5wZP\ndU8OlPzKM1oJr0Cb3xzooI3qHm/YtnF7Tq+Jez6onQKBgQCfbqG5dyTAduhPZzmp\n6m4ndzzdYVoh8KiM3fUApo/u9zF3GixUFgcKKFzP1/zmD6A6UfbVT+JVmUfIVtor\nAA42lqJyOaNH9ttQjZeDXfPpbAyAoZzH0l7/U9KSOkh+2I8tMscjWFqyQ1/DGNcY\nptIRECjQrk5jL0yea0+tbpMmJQ==\n-----END PRIVATE KEY-----\n
|
||||
|
||||
@@ -1,28 +1,18 @@
|
||||
// decks.controller.ts
|
||||
import express from 'express';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
Put,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Res,
|
||||
} from '@nestjs/common';
|
||||
import { Body, Controller, Delete, Get, HttpException, HttpStatus, Param, Post, Put, Request, UseGuards } from '@nestjs/common';
|
||||
import { User } from '../db/schema';
|
||||
import { AuthGuard } from '../service/auth.guard';
|
||||
import { DrizzleService } from './drizzle.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@Controller('decks')
|
||||
@UseGuards(AuthGuard)
|
||||
export class DecksController {
|
||||
constructor(private readonly drizzleService: DrizzleService) {}
|
||||
|
||||
@Get()
|
||||
async getDecks() {
|
||||
const entries = await this.drizzleService.getDecks();
|
||||
async getDecks(@Request() req) {
|
||||
const user: User = req['user'];
|
||||
const entries = await this.drizzleService.getDecks(user);
|
||||
const decks = {};
|
||||
for (const entry of entries) {
|
||||
const deckname = entry.deckname!!;
|
||||
@@ -55,16 +45,18 @@ export class DecksController {
|
||||
}
|
||||
|
||||
@Post()
|
||||
async createDeck(@Body() data: { deckname: string }) {
|
||||
async createDeck(@Request() req, @Body() data: { deckname: string }) {
|
||||
if (!data.deckname) {
|
||||
throw new HttpException('No deckname provided', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return this.drizzleService.createDeck(data.deckname);
|
||||
const user: User = req['user'];
|
||||
return this.drizzleService.createDeck(data.deckname, user);
|
||||
}
|
||||
|
||||
@Get(':deckname')
|
||||
async getDeck(@Param('deckname') deckname: string) {
|
||||
const entries = await this.drizzleService.getDeckByName(deckname);
|
||||
async getDeck(@Request() req, @Param('deckname') deckname: string) {
|
||||
const user: User = req['user'];
|
||||
const entries = await this.drizzleService.getDeckByName(deckname, user);
|
||||
if (entries.length === 0) {
|
||||
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
@@ -98,40 +90,36 @@ export class DecksController {
|
||||
}
|
||||
|
||||
@Delete(':deckname')
|
||||
async deleteDeck(@Param('deckname') deckname: string) {
|
||||
return this.drizzleService.deleteDeck(deckname);
|
||||
async deleteDeck(@Request() req, @Param('deckname') deckname: string) {
|
||||
const user: User = req['user'];
|
||||
return this.drizzleService.deleteDeck(deckname, user);
|
||||
}
|
||||
|
||||
@Put(':oldDeckname/rename')
|
||||
async renameDeck(
|
||||
@Param('oldDeckname') oldDeckname: string,
|
||||
@Body() data: { newDeckName: string },
|
||||
) {
|
||||
async renameDeck(@Request() req, @Param('oldDeckname') oldDeckname: string, @Body() data: { newDeckName: string }) {
|
||||
if (!data.newDeckName) {
|
||||
throw new HttpException('New deck name is required', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return this.drizzleService.renameDeck(oldDeckname, data.newDeckName);
|
||||
const user: User = req['user'];
|
||||
return this.drizzleService.renameDeck(oldDeckname, data.newDeckName, user);
|
||||
}
|
||||
|
||||
@Post('image')
|
||||
async updateImage(@Body() data: any) {
|
||||
async updateImage(@Request() req, @Body() data: any) {
|
||||
if (!data) {
|
||||
throw new HttpException('No data provided', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
const user: User = req['user'];
|
||||
const requiredFields = ['deckname', 'bildname', 'bildid', 'boxes'];
|
||||
if (!requiredFields.every((field) => field in data)) {
|
||||
if (!requiredFields.every(field => field in data)) {
|
||||
throw new HttpException('Missing fields in data', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!Array.isArray(data.boxes) || data.boxes.length === 0) {
|
||||
throw new HttpException(
|
||||
"'boxes' must be a non-empty list",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
throw new HttpException("'boxes' must be a non-empty list", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
return this.drizzleService.updateImage(data);
|
||||
return this.drizzleService.updateImage(data, user);
|
||||
}
|
||||
|
||||
@Delete('image/:bildid')
|
||||
@@ -140,10 +128,7 @@ export class DecksController {
|
||||
}
|
||||
|
||||
@Post('images/:bildid/move')
|
||||
async moveImage(
|
||||
@Param('bildid') bildid: string,
|
||||
@Body() data: { targetDeckId: string },
|
||||
) {
|
||||
async moveImage(@Param('bildid') bildid: string, @Body() data: { targetDeckId: string }) {
|
||||
if (!data.targetDeckId) {
|
||||
throw new HttpException('No targetDeckId provided', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -165,6 +150,4 @@ export class DecksController {
|
||||
) {
|
||||
return this.drizzleService.updateBox(boxId, data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,63 @@
|
||||
// drizzle.service.ts
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { and, eq, isNull } from 'drizzle-orm';
|
||||
import { drizzle } from 'drizzle-orm/libsql';
|
||||
import { Deck, InsertDeck } from '../db/schema';
|
||||
import { eq, and, isNull } from 'drizzle-orm';
|
||||
import { Deck, User } from '../db/schema';
|
||||
|
||||
@Injectable()
|
||||
export class DrizzleService {
|
||||
private db = drizzle('file:local.db');
|
||||
|
||||
async getDecks() {
|
||||
return this.db.select().from(Deck).all();
|
||||
async getDecks(user: User) {
|
||||
return this.db.select().from(Deck).where(eq(Deck.user, user.email));
|
||||
}
|
||||
|
||||
async createDeck(deckname: string) {
|
||||
const result = await this.db.insert(Deck).values({ deckname }).returning();
|
||||
async createDeck(deckname: string, user: User) {
|
||||
const result = await this.db.insert(Deck).values({ deckname, user: user.email }).returning();
|
||||
return { status: 'success', deck: result };
|
||||
}
|
||||
|
||||
async getDeckByName(deckname: string) {
|
||||
return this.db.select().from(Deck).where(eq(Deck.deckname, deckname)).all();
|
||||
async getDeckByName(deckname: string, user: User) {
|
||||
return this.db
|
||||
.select()
|
||||
.from(Deck)
|
||||
.where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email)));
|
||||
}
|
||||
|
||||
async deleteDeck(deckname: string) {
|
||||
const existingDeck = await this.getDeckByName(deckname);
|
||||
async deleteDeck(deckname: string, user: User) {
|
||||
const existingDeck = await this.getDeckByName(deckname, user);
|
||||
if (existingDeck.length === 0) {
|
||||
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
await this.db.delete(Deck).where(eq(Deck.deckname, deckname));
|
||||
await this.db.delete(Deck).where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email)));
|
||||
return { status: 'success' };
|
||||
}
|
||||
|
||||
async renameDeck(oldDeckname: string, newDeckname: string) {
|
||||
const existingDeck = await this.getDeckByName(oldDeckname);
|
||||
async renameDeck(oldDeckname: string, newDeckname: string, user: User) {
|
||||
const existingDeck = await this.getDeckByName(oldDeckname, user);
|
||||
if (existingDeck.length === 0) {
|
||||
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
const existingNewDeck = await this.getDeckByName(newDeckname);
|
||||
const existingNewDeck = await this.getDeckByName(newDeckname, user);
|
||||
if (existingNewDeck.length > 0) {
|
||||
throw new HttpException(
|
||||
'Deck with the new name already exists',
|
||||
HttpStatus.CONFLICT,
|
||||
);
|
||||
throw new HttpException('Deck with the new name already exists', HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
await this.db
|
||||
.update(Deck)
|
||||
.set({ deckname: newDeckname })
|
||||
.where(eq(Deck.deckname, oldDeckname))
|
||||
await this.db.update(Deck).set({ deckname: newDeckname }).where(eq(Deck.deckname, oldDeckname));
|
||||
return { status: 'success', message: 'Deck renamed successfully' };
|
||||
}
|
||||
|
||||
async updateImage(data: {
|
||||
deckname: string;
|
||||
bildname: string;
|
||||
bildid: string;
|
||||
boxes: Array<{ x1: number; x2: number; y1: number; y2: number }>;
|
||||
}) {
|
||||
const existingDeck = await this.getDeckByName(data.deckname);
|
||||
async updateImage(data: { deckname: string; bildname: string; bildid: string; boxes: Array<{ x1: number; x2: number; y1: number; y2: number }> }, user: User) {
|
||||
const existingDeck = await this.getDeckByName(data.deckname, user);
|
||||
if (existingDeck.length === 0) {
|
||||
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
await this.db
|
||||
.delete(Deck)
|
||||
.where(
|
||||
and(eq(Deck.deckname, data.deckname), eq(Deck.bildid, data.bildid)),
|
||||
)
|
||||
await this.db.delete(Deck).where(and(eq(Deck.deckname, data.deckname), eq(Deck.bildid, data.bildid)));
|
||||
|
||||
const insertedImages:any = [];
|
||||
const insertedImages: any = [];
|
||||
for (let index = 0; index < data.boxes.length; index++) {
|
||||
const box = data.boxes[index];
|
||||
const result = await this.db
|
||||
@@ -83,7 +71,9 @@ export class DrizzleService {
|
||||
x2: box.x2,
|
||||
y1: box.y1,
|
||||
y2: box.y2,
|
||||
}).returning();
|
||||
user: 'andreas.knuth@gmail.com',
|
||||
})
|
||||
.returning();
|
||||
insertedImages.push(result);
|
||||
}
|
||||
|
||||
@@ -91,17 +81,10 @@ export class DrizzleService {
|
||||
}
|
||||
|
||||
async deleteImagesByBildId(bildid: string) {
|
||||
const affectedDecks = await this.db
|
||||
.select({ deckname: Deck.deckname })
|
||||
.from(Deck)
|
||||
.where(eq(Deck.bildid, bildid))
|
||||
.all();
|
||||
const affectedDecks = await this.db.select({ deckname: Deck.deckname }).from(Deck).where(eq(Deck.bildid, bildid)).all();
|
||||
|
||||
if (affectedDecks.length === 0) {
|
||||
throw new HttpException(
|
||||
'No entries found for the given image ID',
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
await this.db.delete(Deck).where(eq(Deck.bildid, bildid));
|
||||
@@ -110,22 +93,18 @@ export class DrizzleService {
|
||||
const remainingImages = await this.db
|
||||
.select()
|
||||
.from(Deck)
|
||||
.where(
|
||||
and(eq(Deck.deckname, deck.deckname), eq(Deck.bildid, bildid)),
|
||||
)
|
||||
.where(and(eq(Deck.deckname, deck.deckname), eq(Deck.bildid, bildid)))
|
||||
.all();
|
||||
|
||||
if (remainingImages.length === 0) {
|
||||
const emptyDeckEntry = await this.db
|
||||
.select()
|
||||
.from(Deck)
|
||||
.where(
|
||||
and(eq(Deck.deckname, deck.deckname), isNull(Deck.bildid)),
|
||||
)
|
||||
.where(and(eq(Deck.deckname, deck.deckname), isNull(Deck.bildid)))
|
||||
.all();
|
||||
|
||||
if (emptyDeckEntry.length === 0) {
|
||||
await this.db.insert(Deck).values({ deckname: deck.deckname });
|
||||
await this.db.insert(Deck).values({ deckname: deck.deckname, user: 'andreas.knuth@gmail.com' });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,23 +116,13 @@ export class DrizzleService {
|
||||
}
|
||||
|
||||
async moveImage(bildid: string, targetDeckId: string) {
|
||||
const existingImages = await this.db
|
||||
.select()
|
||||
.from(Deck)
|
||||
.where(eq(Deck.bildid, bildid))
|
||||
.all();
|
||||
const existingImages = await this.db.select().from(Deck).where(eq(Deck.bildid, bildid)).all();
|
||||
|
||||
if (existingImages.length === 0) {
|
||||
throw new HttpException(
|
||||
'No entries found for the given image ID',
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
await this.db
|
||||
.update(Deck)
|
||||
.set({ deckname: targetDeckId })
|
||||
.where(eq(Deck.bildid, bildid))
|
||||
await this.db.update(Deck).set({ deckname: targetDeckId }).where(eq(Deck.bildid, bildid));
|
||||
|
||||
return { status: 'success', moved_entries: existingImages.length };
|
||||
}
|
||||
@@ -174,10 +143,7 @@ export class DrizzleService {
|
||||
updateData.isGraduated = Number(data.isGraduated);
|
||||
}
|
||||
|
||||
const result = await this.db
|
||||
.update(Deck)
|
||||
.set(updateData)
|
||||
.where(eq(Deck.id, boxId))
|
||||
const result = await this.db.update(Deck).set(updateData).where(eq(Deck.id, boxId));
|
||||
|
||||
if (result.rowsAffected === 0) {
|
||||
throw new HttpException('Box not found', HttpStatus.NOT_FOUND);
|
||||
@@ -185,4 +151,4 @@ export class DrizzleService {
|
||||
|
||||
return { status: 'success' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +1,64 @@
|
||||
// decks.controller.ts
|
||||
import { Body, Controller, HttpException, HttpStatus, Post, Res, UseGuards } from '@nestjs/common';
|
||||
import express from 'express';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
Put,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Res,
|
||||
} from '@nestjs/common';
|
||||
import { DrizzleService } from './drizzle.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { AuthGuard } from '../service/auth.guard';
|
||||
|
||||
@Controller('')
|
||||
@UseGuards(AuthGuard)
|
||||
export class ProxyController {
|
||||
constructor() {}
|
||||
// --------------------
|
||||
// --------------------
|
||||
// Proxy Endpoints
|
||||
// --------------------
|
||||
// @Get('debug_image/:name/:filename')
|
||||
// async getDebugImage(
|
||||
// @Param('name') name: string,
|
||||
// @Param('filename') filename: string,
|
||||
// @Res() res: express.Response,
|
||||
// ) {
|
||||
// const url = `http://localhost:8080/api/debug_image/${name}/${filename}`;
|
||||
// //const url = `http://localhost:5000/api/debug_image/20250112_112306_9286e3bf/thumbnail.jpg`;
|
||||
// @Get('debug_image/:name/:filename')
|
||||
// async getDebugImage(
|
||||
// @Param('name') name: string,
|
||||
// @Param('filename') filename: string,
|
||||
// @Res() res: express.Response,
|
||||
// ) {
|
||||
// const url = `http://localhost:8080/api/debug_image/${name}/${filename}`;
|
||||
// //const url = `http://localhost:5000/api/debug_image/20250112_112306_9286e3bf/thumbnail.jpg`;
|
||||
|
||||
// try {
|
||||
// // Fetch the image from the external service
|
||||
// const response = await fetch(url);
|
||||
// try {
|
||||
// // Fetch the image from the external service
|
||||
// const response = await fetch(url);
|
||||
|
||||
// // Check if the response is OK (status code 200-299)
|
||||
// if (!response.ok) {
|
||||
// throw new Error(`Failed to retrieve image: ${response.statusText}`);
|
||||
// }
|
||||
// // Check if the response is OK (status code 200-299)
|
||||
// if (!response.ok) {
|
||||
// throw new Error(`Failed to retrieve image: ${response.statusText}`);
|
||||
// }
|
||||
|
||||
// // Get the image data as a buffer
|
||||
// const imageBuffer = await response.arrayBuffer();
|
||||
// // Get the image data as a buffer
|
||||
// const imageBuffer = await response.arrayBuffer();
|
||||
|
||||
// // Determine the Content-Type based on the file extension
|
||||
// let contentType = 'image/png'; // Default MIME type
|
||||
// if (filename.toLowerCase().endsWith('.jpg') || filename.toLowerCase().endsWith('.jpeg')) {
|
||||
// contentType = 'image/jpeg';
|
||||
// } else if (filename.toLowerCase().endsWith('.gif')) {
|
||||
// contentType = 'image/gif';
|
||||
// } else if (filename.toLowerCase().endsWith('.bmp')) {
|
||||
// contentType = 'image/bmp';
|
||||
// } else if (filename.toLowerCase().endsWith('.tiff') || filename.toLowerCase().endsWith('.tif')) {
|
||||
// contentType = 'image/tiff';
|
||||
// }
|
||||
// // Determine the Content-Type based on the file extension
|
||||
// let contentType = 'image/png'; // Default MIME type
|
||||
// if (filename.toLowerCase().endsWith('.jpg') || filename.toLowerCase().endsWith('.jpeg')) {
|
||||
// contentType = 'image/jpeg';
|
||||
// } else if (filename.toLowerCase().endsWith('.gif')) {
|
||||
// contentType = 'image/gif';
|
||||
// } else if (filename.toLowerCase().endsWith('.bmp')) {
|
||||
// contentType = 'image/bmp';
|
||||
// } else if (filename.toLowerCase().endsWith('.tiff') || filename.toLowerCase().endsWith('.tif')) {
|
||||
// contentType = 'image/tiff';
|
||||
// }
|
||||
|
||||
// // Set the Content-Type header and send the image data
|
||||
// res.set('Content-Type', contentType);
|
||||
// res.send(Buffer.from(imageBuffer));
|
||||
// } catch (error) {
|
||||
// // Handle errors
|
||||
// res.status(500).json({ error: error.message });
|
||||
// }
|
||||
// }
|
||||
// // Set the Content-Type header and send the image data
|
||||
// res.set('Content-Type', contentType);
|
||||
// res.send(Buffer.from(imageBuffer));
|
||||
// } catch (error) {
|
||||
// // Handle errors
|
||||
// res.status(500).json({ error: error.message });
|
||||
// }
|
||||
// }
|
||||
|
||||
@Post('ocr')
|
||||
async ocrEndpoint(
|
||||
@Body() data: { image: string },
|
||||
@Res() res: express.Response,
|
||||
) {
|
||||
async ocrEndpoint(@Body() data: { image: string }, @Res() res: express.Response) {
|
||||
try {
|
||||
if (!data || !data.image) {
|
||||
throw new HttpException('No image provided', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
const response = await fetch('http://localhost:5000/api/ocr', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -81,19 +66,16 @@ export class ProxyController {
|
||||
},
|
||||
body: JSON.stringify({ image: data.image }),
|
||||
});
|
||||
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 400) {
|
||||
throw new HttpException(result.error, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
throw new HttpException(
|
||||
result.error || 'OCR processing failed',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
throw new HttpException(result.error || 'OCR processing failed', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
|
||||
// Bei erfolgreicher Verarbeitung mit Warnung
|
||||
if (result.warning) {
|
||||
return res.status(HttpStatus.OK).json({
|
||||
@@ -101,21 +83,17 @@ export class ProxyController {
|
||||
debug_dir: result.debug_dir,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Bei vollständig erfolgreicher Verarbeitung
|
||||
return res.status(HttpStatus.OK).json({
|
||||
status: result.status,
|
||||
results: result.results,
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
'Internal server error',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
throw new HttpException('Internal server error', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,50 @@
|
||||
import { sqliteTable as table, text, integer, real } from 'drizzle-orm/sqlite-core';
|
||||
import * as t from "drizzle-orm/sqlite-core";
|
||||
import * as t from 'drizzle-orm/sqlite-core';
|
||||
import { integer, real, sqliteTable as table, text } from 'drizzle-orm/sqlite-core';
|
||||
|
||||
export const Deck = table('Deck', {
|
||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
||||
deckname: text('deckname').notNull(),
|
||||
bildname: text('bildname'),
|
||||
bildid: text('bildid'),
|
||||
iconindex: integer('iconindex'),
|
||||
x1: real('x1'),
|
||||
x2: real('x2'),
|
||||
y1: real('y1'),
|
||||
y2: real('y2'),
|
||||
due: integer('due'),
|
||||
ivl: real('ivl'),
|
||||
factor: real('factor'),
|
||||
reps: integer('reps'),
|
||||
lapses: integer('lapses'),
|
||||
isGraduated: integer('isGraduated'),
|
||||
},
|
||||
(table) => {
|
||||
return {
|
||||
index: t.uniqueIndex("email_idx").on(table.id),
|
||||
};
|
||||
}
|
||||
export const Deck = table(
|
||||
'Deck',
|
||||
{
|
||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
||||
deckname: text('deckname').notNull(),
|
||||
bildname: text('bildname'),
|
||||
bildid: text('bildid'),
|
||||
iconindex: integer('iconindex'),
|
||||
x1: real('x1'),
|
||||
x2: real('x2'),
|
||||
y1: real('y1'),
|
||||
y2: real('y2'),
|
||||
due: integer('due'),
|
||||
ivl: real('ivl'),
|
||||
factor: real('factor'),
|
||||
reps: integer('reps'),
|
||||
lapses: integer('lapses'),
|
||||
isGraduated: integer('isGraduated'),
|
||||
user: text('user').notNull(),
|
||||
},
|
||||
table => {
|
||||
return {
|
||||
index: t.uniqueIndex('email_idx').on(table.id),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export type InsertDeck = typeof Deck.$inferInsert;
|
||||
export type SelectDeck = typeof Deck.$inferSelect;
|
||||
|
||||
export interface User {
|
||||
name: string;
|
||||
picture: string;
|
||||
iss: string;
|
||||
aud: string;
|
||||
auth_time: number;
|
||||
user_id: string;
|
||||
sub: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
email: string;
|
||||
email_verified: boolean;
|
||||
firebase: {
|
||||
identities: any;
|
||||
sign_in_provider: string;
|
||||
};
|
||||
uid: string;
|
||||
}
|
||||
|
||||
27
api/src/service/auth.guard.ts
Normal file
27
api/src/service/auth.guard.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import admin from './firebase-admin';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest<Request>();
|
||||
const token = this.extractTokenFromHeader(request);
|
||||
|
||||
if (!token) {
|
||||
throw new UnauthorizedException('No token provided');
|
||||
}
|
||||
|
||||
try {
|
||||
const decodedToken = await admin.auth().verifyIdToken(token);
|
||||
request['user'] = decodedToken; // Fügen Sie die Benutzerdaten dem Request-Objekt hinzu
|
||||
return true;
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
const [type, token] = request.headers['authorization']?.split(' ') ?? [];
|
||||
return type === 'Bearer' ? token : undefined;
|
||||
}
|
||||
}
|
||||
16
api/src/service/firebase-admin.ts
Normal file
16
api/src/service/firebase-admin.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as admin from 'firebase-admin';
|
||||
import { ServiceAccount } from 'firebase-admin';
|
||||
|
||||
const serviceAccount: ServiceAccount = {
|
||||
projectId: process.env['FIREBASE_PROJECT_ID'],
|
||||
clientEmail: process.env['FIREBASE_CLIENT_EMAIL'],
|
||||
privateKey: process.env['FIREBASE_PRIVATE_KEY']?.replace(/\\n/g, '\n'), // Ersetzen Sie escaped newlines
|
||||
};
|
||||
|
||||
if (!admin.apps.length) {
|
||||
admin.initializeApp({
|
||||
credential: admin.credential.cert(serviceAccount),
|
||||
});
|
||||
}
|
||||
|
||||
export default admin;
|
||||
Reference in New Issue
Block a user