Add authentication system and admin panel

- Implement JWT-based authentication with login/logout
- Add user management routes and middleware
- Create admin panel for managing words and categories
- Add authentication store and API client
- Update database schema with User model
- Configure CORS and authentication middleware
- Add login page and protected routes
This commit is contained in:
2026-01-17 14:30:22 +01:00
parent a11e2acb23
commit 3275bc4a4f
24 changed files with 1551 additions and 73 deletions

View File

@@ -23,7 +23,7 @@ This document provides a complete implementation plan for a 1:1 functional and v
### Backend
- **Runtime**: Node.js 20 LTS
- **Framework**: Express.js with TypeScript
- **Authentication**: Passport.js (Google OAuth, Microsoft OAuth, local email/password)
- **Authentication**: Simple admin user + local user management (OAuth deferred to later phases)
- **Session**: express-session with MySQL session store
- **Validation**: Zod (shared with frontend)
- **File Upload**: Multer (for video/image uploads)
@@ -83,7 +83,9 @@ turkshop/
│ │ │ │ ├── Help.tsx
│ │ │ │ ├── Community.tsx
│ │ │ │ ├── Comments.tsx
│ │ │ │ ── BugReport.tsx
│ │ │ │ ── BugReport.tsx
│ │ │ │ └── admin/
│ │ │ │ └── UserManagement.tsx
│ │ │ ├── stores/ # Zustand stores
│ │ │ │ ├── authStore.ts
│ │ │ │ ├── sentenceStore.ts
@@ -107,6 +109,7 @@ turkshop/
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ │ ├── auth.ts
│ │ │ ├── admin.ts
│ │ │ ├── terms.ts
│ │ │ ├── documents.ts
│ │ │ ├── sentences.ts
@@ -115,6 +118,7 @@ turkshop/
│ │ │ └── index.ts
│ │ ├── controllers/ # Business logic
│ │ │ ├── authController.ts
│ │ │ ├── adminController.ts
│ │ │ ├── termController.ts
│ │ │ ├── documentController.ts
│ │ │ └── sentenceController.ts
@@ -129,7 +133,7 @@ turkshop/
│ │ │ └── playlistService.ts
│ │ ├── lib/ # Utilities
│ │ │ ├── prisma.ts # Prisma client
│ │ │ └── passport.ts # Passport config
│ │ │ └── auth.ts # Auth utilities (bcrypt, session)
│ │ ├── types/ # TypeScript types
│ │ │ └── index.ts
│ │ ├── config/ # Configuration
@@ -183,9 +187,9 @@ model User {
id String @id @default(uuid())
email String @unique
displayName String? @map("display_name")
passwordHash String? @map("password_hash")
authProvider String @default("local") @map("auth_provider") // local, google, microsoft
providerId String? @map("provider_id")
passwordHash String @map("password_hash")
role UserRole @default(USER)
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@ -196,6 +200,11 @@ model User {
@@map("users")
}
enum UserRole {
ADMIN
USER
}
// ============================================
// DICTIONARY / TERMS
// ============================================
@@ -408,16 +417,22 @@ enum BugStatus {
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| POST | `/auth/register` | Register new user with email/password | No |
| POST | `/auth/login` | Login with email/password | No |
| POST | `/auth/logout` | Logout current user | Yes |
| GET | `/auth/me` | Get current user info | Yes |
| GET | `/auth/google` | Initiate Google OAuth flow | No |
| GET | `/auth/google/callback` | Google OAuth callback | No |
| GET | `/auth/microsoft` | Initiate Microsoft OAuth flow | No |
| GET | `/auth/microsoft/callback` | Microsoft OAuth callback | No |
### 4.2 Dictionary/Terms Routes (`/api/terms`)
### 4.2 Admin User Management Routes (`/api/admin/users`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| GET | `/admin/users` | List all users | Yes (Admin) |
| POST | `/admin/users` | Create new user | Yes (Admin) |
| PUT | `/admin/users/:id` | Update user | Yes (Admin) |
| DELETE | `/admin/users/:id` | Delete user | Yes (Admin) |
| PUT | `/admin/users/:id/password` | Reset user password | Yes (Admin) |
| PUT | `/admin/users/:id/activate` | Activate/deactivate user | Yes (Admin) |
### 4.3 Dictionary/Terms Routes (`/api/terms`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -438,7 +453,7 @@ enum BugStatus {
- `sortBy` (string): Sort field (default: wordText)
- `sortOrder` (asc|desc): Sort direction (default: asc)
### 4.3 Document Routes (`/api/documents`)
### 4.4 Document Routes (`/api/documents`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -450,7 +465,7 @@ enum BugStatus {
| PUT | `/documents/:id/content` | Update document content (pages/sentences) | Yes |
| POST | `/documents/:id/share` | Generate share link | Yes |
### 4.4 Sentence Routes (`/api/sentences`)
### 4.5 Sentence Routes (`/api/sentences`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -463,7 +478,7 @@ enum BugStatus {
| DELETE | `/sentences/:id/tokens/:tokenId` | Remove token | Yes |
| PUT | `/sentences/:id/reorder` | Reorder tokens | Yes |
### 4.5 Playlist Routes (`/api/playlists`)
### 4.6 Playlist Routes (`/api/playlists`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -494,7 +509,7 @@ enum BugStatus {
}
```
### 4.6 Community Routes (`/api/community`)
### 4.7 Community Routes (`/api/community`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -502,7 +517,7 @@ enum BugStatus {
| POST | `/community/comments` | Create comment | Yes |
| DELETE | `/community/comments/:id` | Delete own comment | Yes |
### 4.7 Bug Report Routes (`/api/bugs`)
### 4.8 Bug Report Routes (`/api/bugs`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
@@ -511,14 +526,14 @@ enum BugStatus {
| POST | `/bugs` | Submit bug report | Yes |
| PUT | `/bugs/:id` | Update bug status (admin) | Yes (Admin) |
### 4.8 Upload Routes (`/api/uploads`)
### 4.9 Upload Routes (`/api/uploads`)
| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| POST | `/uploads/video` | Upload video file | Yes (Admin) |
| POST | `/uploads/icon` | Upload icon/image | Yes (Admin) |
### 4.9 Static File Serving
### 4.10 Static File Serving
| Path | Description |
|------|-------------|
@@ -653,6 +668,7 @@ Components to install:
- Zajednica (Community)
- Komentari (Comments)
- Prijavi grešku (Bug Report)
- Admin Panel (Admin only - User Management)
**Dictionary Page:**
- Riječ (Word) - search input label
@@ -674,14 +690,26 @@ Components to install:
**Auth:**
- Prijavi se (Sign In)
- Odjavi se (Sign Out)
- Registriraj se (Sign Up)
- Email adresa (Email Address)
- Lozinka (Password)
**Admin Panel:**
- Korisnici (Users)
- Dodaj korisnika (Add User)
- Uredi korisnika (Edit User)
- Obriši korisnika (Delete User)
- Resetiraj lozinku (Reset Password)
- Aktiviraj/Deaktiviraj (Activate/Deactivate)
- Uloga (Role)
- Aktivan (Active)
---
## 6. Implementation Milestones
**Note on Authentication Strategy:**
For the initial phases, we will implement a simple admin user with local user management. OAuth integration (Google, Microsoft) will be deferred to later phases (Phase 8+) to focus on core functionality first. The admin user will be able to create and manage local users through an admin panel.
### Phase 0: Project Setup (Week 1)
**Goal:** Initialize project structure and development environment
@@ -704,34 +732,36 @@ Components to install:
---
### Phase 1: Core Infrastructure (Week 2)
**Goal:** Build authentication and basic layout
**Goal:** Build basic authentication and layout with admin user
**Backend Tasks:**
1. Implement Prisma schema (User model)
1. Implement Prisma schema (User model with role and isActive fields)
2. Run initial migration
3. Set up Passport.js with local strategy
4. Implement session management
5. Create auth routes (register, login, logout, me)
6. Set up Google OAuth
7. Set up Microsoft OAuth
8. Create auth middleware
9. Set up CORS and security headers
3. Create seed script with default admin user
4. Implement simple session-based authentication
5. Create auth routes (login, logout, me)
6. Create auth middleware (isAuthenticated, isAdmin)
7. Set up CORS and security headers
8. Create admin user management routes (CRUD)
**Frontend Tasks:**
1. Create layout components (Sidebar, Header, Layout)
2. Set up React Router with routes
3. Create auth pages (Login, Register)
3. Create login page (simple email/password)
4. Implement auth store (Zustand)
5. Create auth API client
6. Implement protected routes
7. Add OAuth buttons
7. Create admin panel page for user management
8. Build user list, create, edit, delete components
**Deliverables:**
-Users can register and login
- ✅ OAuth works (Google + Microsoft)
-Admin can login with default credentials
- ✅ Session persists across page reloads
- ✅ Sidebar navigation works
- ✅ Protected routes redirect to login
- ✅ Admin can create/edit/delete local users
- ✅ Admin can reset user passwords
- ✅ Admin can activate/deactivate users
---
@@ -918,6 +948,31 @@ Components to install:
---
### Phase 8: OAuth Integration (Future Phase)
**Goal:** Add OAuth authentication providers (deferred from Phase 1)
**Backend Tasks:**
1. Set up Passport.js with Google OAuth strategy
2. Set up Passport.js with Microsoft OAuth strategy
3. Update User model to support authProvider and providerId fields
4. Create OAuth callback routes
5. Implement account linking (OAuth to existing local accounts)
6. Update auth middleware to support OAuth sessions
**Frontend Tasks:**
1. Add OAuth buttons to login page
2. Create OAuth callback handling
3. Add account linking UI
4. Update user profile to show auth provider
**Deliverables:**
- ✅ Users can sign in with Google
- ✅ Users can sign in with Microsoft
- ✅ OAuth accounts can be linked to existing local accounts
- ✅ Session management works with OAuth
---
## 7. Environment Configuration
### Backend `.env` (packages/backend/.env)
@@ -934,15 +989,9 @@ DATABASE_URL="mysql://user:password@localhost:3306/znakovni"
# Session
SESSION_SECRET=your-super-secret-session-key-change-in-production
# OAuth - Google
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:3000/api/auth/google/callback
# OAuth - Microsoft
MICROSOFT_CLIENT_ID=your-microsoft-client-id
MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret
MICROSOFT_CALLBACK_URL=http://localhost:3000/api/auth/microsoft/callback
# Default Admin User (created on first run)
ADMIN_EMAIL=admin@znakovni.hr
ADMIN_PASSWORD=change-this-password-immediately
# File Upload
UPLOAD_DIR=./uploads
@@ -1290,7 +1339,11 @@ npx shadcn-ui@latest add card
- [ ] Sentences can be saved to documents
- [ ] Documents can be loaded from cloud
- [ ] Video sentence player works with sequential playback
- [ ] Authentication works (email + Google + Microsoft)
- [ ] Admin can login with credentials
- [ ] Admin can create/edit/delete local users
- [ ] Admin can reset user passwords
- [ ] Admin can activate/deactivate users
- [ ] Regular users can login with their credentials
- [ ] Cloud document management works
- [ ] Comments and bug reports can be submitted
@@ -1321,12 +1374,12 @@ npx shadcn-ui@latest add card
## 13. Next Steps
1. **Review and approve this plan**
2. **Set up OAuth credentials** (Google Cloud Console, Microsoft Azure)
3. **Prepare MySQL database** (local or cloud)
4. **Begin Phase 0: Project Setup**
5. **Iterate through phases sequentially**
6. **Test continuously during development**
7. **Deploy to production server**
2. **Prepare MySQL database** (local or cloud)
3. **Begin Phase 0: Project Setup**
4. **Iterate through phases sequentially**
5. **Test continuously during development**
6. **Deploy to production server**
7. **Phase 8+ (Future): Set up OAuth credentials** (Google Cloud Console, Microsoft Azure) when ready to add OAuth
---