From ab9191985d2603fe507d19089f57ca5266b924ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Domonkos?= <144695310+IvnDmnks@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:39:40 +0100 Subject: [PATCH] Feat/authentication (#21) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed gitignore * added docker * half done * Filter by userId * single period, dynamic reporting periods * added jwt on frontend --------- Co-authored-by: Bujdosó Gergő --- apps/backend/.env.example | 1 + .../backend/src/tasks/entities/task.entity.ts | 3 +- apps/frontend/.env | 2 +- .../app/(with-layout)/adminoverview/page.tsx | 9 ++ .../frontend/src/app/(with-layout)/layout.tsx | 2 +- .../app/(with-layout)/singleperiod/page.tsx | 9 ++ apps/frontend/src/app/auth/callback/route.tsx | 16 +++ apps/frontend/src/app/auth/logout/route.tsx | 10 ++ .../frontend/src/components/AdminOverview.tsx | 115 ++++++++++++++++++ apps/frontend/src/components/AfterLogin.tsx | 6 +- apps/frontend/src/components/Navbar.tsx | 10 +- apps/frontend/src/components/NewProject.tsx | 5 +- .../src/components/ReportingPeriod.tsx | 81 ++++++++---- apps/frontend/src/components/SinglePeriod.tsx | 101 +++++++++++++++ apps/frontend/src/components/footer.tsx | 2 +- apps/frontend/src/lib/axiosConfig.ts | 2 +- 16 files changed, 332 insertions(+), 42 deletions(-) create mode 100644 apps/frontend/src/app/(with-layout)/adminoverview/page.tsx create mode 100644 apps/frontend/src/app/(with-layout)/singleperiod/page.tsx create mode 100644 apps/frontend/src/app/auth/callback/route.tsx create mode 100644 apps/frontend/src/app/auth/logout/route.tsx create mode 100644 apps/frontend/src/components/AdminOverview.tsx create mode 100644 apps/frontend/src/components/SinglePeriod.tsx diff --git a/apps/backend/.env.example b/apps/backend/.env.example index 28fb2e2..70ee7c0 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -4,3 +4,4 @@ JWT_EXPIRATION="1d" AUTHSCH_CLIENT_ID="" AUTHSCH_CLIENT_SECRET="" BACKEND_PORT=3001 +FRONTEND_AUTHORIZED_URL="http://localhost:3000/auth/callback" diff --git a/apps/backend/src/tasks/entities/task.entity.ts b/apps/backend/src/tasks/entities/task.entity.ts index b627cb2..1e541d4 100644 --- a/apps/backend/src/tasks/entities/task.entity.ts +++ b/apps/backend/src/tasks/entities/task.entity.ts @@ -11,8 +11,7 @@ export class Tasks { @IsInt() sprintId: number; - @IsInt() - userId: number; + userId: string; @IsInt() projectId: number; diff --git a/apps/frontend/.env b/apps/frontend/.env index 9bdee49..8ec9f7c 100644 --- a/apps/frontend/.env +++ b/apps/frontend/.env @@ -1 +1 @@ -BACKEND_URL= https://localhost:3001 +NEXT_PUBLIC_BACKEND_URL= http://localhost:3001 diff --git a/apps/frontend/src/app/(with-layout)/adminoverview/page.tsx b/apps/frontend/src/app/(with-layout)/adminoverview/page.tsx new file mode 100644 index 0000000..ab38acd --- /dev/null +++ b/apps/frontend/src/app/(with-layout)/adminoverview/page.tsx @@ -0,0 +1,9 @@ +import AdminOverview from '../../../components/AdminOverview'; + +export default function Home() { + return ( +
+ +
+ ); +} diff --git a/apps/frontend/src/app/(with-layout)/layout.tsx b/apps/frontend/src/app/(with-layout)/layout.tsx index 1ab979d..3a4b893 100644 --- a/apps/frontend/src/app/(with-layout)/layout.tsx +++ b/apps/frontend/src/app/(with-layout)/layout.tsx @@ -1,4 +1,4 @@ -import { Footer } from '../../components/Footer'; +import { Footer } from '../../components/footer'; import Navbar from '../../components/Navbar'; import Section from '../../components/section'; diff --git a/apps/frontend/src/app/(with-layout)/singleperiod/page.tsx b/apps/frontend/src/app/(with-layout)/singleperiod/page.tsx new file mode 100644 index 0000000..f9ae5b3 --- /dev/null +++ b/apps/frontend/src/app/(with-layout)/singleperiod/page.tsx @@ -0,0 +1,9 @@ +import SinglePeriod from '../../../components/SinglePeriod'; + +export default function Home() { + return ( +
+ +
+ ); +} diff --git a/apps/frontend/src/app/auth/callback/route.tsx b/apps/frontend/src/app/auth/callback/route.tsx new file mode 100644 index 0000000..1de7770 --- /dev/null +++ b/apps/frontend/src/app/auth/callback/route.tsx @@ -0,0 +1,16 @@ +import { cookies } from 'next/headers'; +import { NextRequest, NextResponse } from 'next/server'; + +export const dynamic = 'force-dynamic'; + +export async function GET(request: NextRequest) { + const jwt = request.nextUrl.searchParams.get('jwt'); + + if (!jwt) { + return new Response('Unauthorized', { status: 401 }); + } + + cookies().set('jwt', jwt, { path: '/' }); + + return NextResponse.redirect(new URL('/profile', request.url)); +} diff --git a/apps/frontend/src/app/auth/logout/route.tsx b/apps/frontend/src/app/auth/logout/route.tsx new file mode 100644 index 0000000..5185cce --- /dev/null +++ b/apps/frontend/src/app/auth/logout/route.tsx @@ -0,0 +1,10 @@ +import { cookies } from 'next/headers'; +import { NextRequest, NextResponse } from 'next/server'; + +export const dynamic = 'force-dynamic'; + +export async function GET(request: NextRequest) { + cookies().delete('jwt'); + + return NextResponse.redirect(new URL('/', request.url)); +} diff --git a/apps/frontend/src/components/AdminOverview.tsx b/apps/frontend/src/components/AdminOverview.tsx new file mode 100644 index 0000000..fd6d9c5 --- /dev/null +++ b/apps/frontend/src/components/AdminOverview.tsx @@ -0,0 +1,115 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +import api from '../lib/axiosConfig'; + +export default function AdminOverview() { + interface Task { + id: number; + description: string; + createdAt: string; + projectId: number; + userId: string; + } + + const [tasks, setTasks] = useState([]); + const [sort, setSort] = useState([]); + const [filter, setFilter] = useState(''); + const [selectedUserId, setSelectedUserId] = useState(''); + + console.log(sort); + + useEffect(() => { + api.get('/tasks').then((res) => { + setTasks(res.data); + setSort(res.data); + console.log(res.data); + }); + }, []); + + useEffect(() => { + let filteredTasks = [...tasks]; + + if (filter === 'name') { + setSort([...tasks].sort((a, b) => a.userId.localeCompare(b.userId))); + } else if (filter === 'date') { + setSort([...tasks].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())); + } else if (filter === 'project') { + setSort([...tasks].sort((a, b) => a.projectId - b.projectId)); + } else { + setSort(tasks); + } + + if (selectedUserId) { + filteredTasks = filteredTasks.filter((task) => task.userId === selectedUserId); + } + setSort(filteredTasks); + }, [filter, tasks, selectedUserId]); + + const uniqueUserIds = Array.from(new Set(tasks.map((task) => task.userId))); + return ( +
+
+

+ Áttekintés +

+
+ + +
+
+ + + + + + + + + + + {sort.map((task) => ( + + + + + + + ))} + +
NévProjektIdőszakLeírás
{task.userId}{task.projectId}{task.createdAt}{task.description}
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/AfterLogin.tsx b/apps/frontend/src/components/AfterLogin.tsx index 509e7cc..7ba76c4 100644 --- a/apps/frontend/src/components/AfterLogin.tsx +++ b/apps/frontend/src/components/AfterLogin.tsx @@ -18,7 +18,7 @@ export default function GreetingsPage() {
Beszámolási időszakok @@ -30,7 +30,7 @@ export default function GreetingsPage() {
Munkák

Láthatod a jelenleg zajló

@@ -46,7 +46,7 @@ export default function GreetingsPage() {
Új Projekt

Itt tudsz új projeket nyitni.

diff --git a/apps/frontend/src/components/Navbar.tsx b/apps/frontend/src/components/Navbar.tsx index 67470b7..756ac02 100644 --- a/apps/frontend/src/components/Navbar.tsx +++ b/apps/frontend/src/components/Navbar.tsx @@ -1,28 +1,28 @@ export default function Navbar() { return ( -
+