From 65f38d68c528a7e53b93882d9629908cacdd7fb8 Mon Sep 17 00:00:00 2001 From: Krrish Ghimire Date: Tue, 30 Jun 2026 11:13:55 +0545 Subject: [PATCH] register, login, create and manage sites and pages --- .gitignore | 63 + PLAN.md | 293 + README.md | 233 + backend/build.gradle | 73 + .../gradle/wrapper/gradle-wrapper.properties | 9 + backend/gradlew | 248 + backend/gradlew.bat | 82 + backend/settings.gradle | 1 + .../main/java/com/indie/IndieApplication.java | 12 + .../main/java/com/indie/config/GitConfig.java | 47 + .../indie/config/GlobalExceptionHandler.java | 33 + .../indie/config/JwtAuthenticationToken.java | 28 + .../main/java/com/indie/config/JwtConfig.java | 128 + .../java/com/indie/config/SecurityConfig.java | 138 + .../java/com/indie/config/TokenService.java | 13 + .../java/com/indie/config/UserPrincipal.java | 47 + .../com/indie/controller/AuthController.java | 48 + .../com/indie/controller/PageController.java | 124 + .../com/indie/controller/SiteController.java | 114 + .../main/java/com/indie/dto/AuthResponse.java | 37 + .../main/java/com/indie/dto/LoginRequest.java | 16 + .../main/java/com/indie/dto/PageRequest.java | 22 + .../main/java/com/indie/dto/PageResponse.java | 36 + .../com/indie/dto/RefreshTokenRequest.java | 11 + .../java/com/indie/dto/RegisterRequest.java | 21 + .../main/java/com/indie/dto/SiteRequest.java | 19 + .../main/java/com/indie/dto/SiteResponse.java | 42 + .../java/com/indie/model/AuthProvider.java | 5 + .../main/java/com/indie/model/Component.java | 47 + .../java/com/indie/model/ComponentType.java | 5 + .../src/main/java/com/indie/model/Page.java | 50 + .../src/main/java/com/indie/model/Site.java | 67 + .../main/java/com/indie/model/SiteStatus.java | 5 + .../src/main/java/com/indie/model/User.java | 61 + .../indie/repository/ComponentRepository.java | 14 + .../com/indie/repository/PageRepository.java | 17 + .../com/indie/repository/SiteRepository.java | 17 + .../com/indie/repository/UserRepository.java | 17 + .../java/com/indie/service/AuthService.java | 96 + .../com/indie/service/CustomOAuth2User.java | 40 + .../indie/service/OAuth2SuccessHandler.java | 42 + .../com/indie/service/OAuth2UserService.java | 110 + backend/src/main/resources/application.yml | 43 + .../config/GlobalExceptionHandlerTest.java | 45 + .../com/indie/config/UserPrincipalTest.java | 45 + .../indie/controller/AuthControllerTest.java | 141 + .../indie/controller/PageControllerTest.java | 201 + .../indie/controller/SiteControllerTest.java | 195 + .../java/com/indie/dto/PageResponseTest.java | 57 + .../java/com/indie/dto/SiteResponseTest.java | 65 + .../java/com/indie/model/ComponentTest.java | 39 + .../test/java/com/indie/model/PageTest.java | 57 + .../test/java/com/indie/model/SiteTest.java | 68 + .../test/java/com/indie/model/UserTest.java | 71 + .../repository/ComponentRepositoryTest.java | 92 + .../indie/repository/PageRepositoryTest.java | 101 + .../indie/repository/SiteRepositoryTest.java | 89 + .../indie/repository/UserRepositoryTest.java | 89 + .../com/indie/service/AuthServiceTest.java | 190 + .../indie/service/OAuth2UserServiceTest.java | 129 + .../support/FakeComponentRepository.java | 40 + .../java/com/indie/support/FakeJwtConfig.java | 49 + .../com/indie/support/FakePageRepository.java | 49 + .../com/indie/support/FakeSiteRepository.java | 49 + .../com/indie/support/FakeUserRepository.java | 47 + .../com/indie/support/InMemoryRepository.java | 209 + .../indie/support/StubPasswordEncoder.java | 18 + .../com/indie/support/TestOAuth2User.java | 38 + .../com/indie/support/TestSecurityConfig.java | 21 + backend/src/test/resources/application.yml | 16 + docker-compose.yml | 38 + frontend/.editorconfig | 16 + frontend/.gitignore | 42 + frontend/Dockerfile | 12 + frontend/README.md | 27 + frontend/angular.json | 128 + frontend/nginx.conf | 22 + frontend/package-lock.json | 13609 ++++++++++++++++ frontend/package.json | 43 + frontend/pnpm-lock.yaml | 8446 ++++++++++ frontend/postcss.config.js | 6 + frontend/proxy.conf.json | 14 + frontend/src/app/app.component.css | 0 frontend/src/app/app.component.html | 1 + frontend/src/app/app.component.ts | 10 + frontend/src/app/app.config.ts | 16 + frontend/src/app/app.routes.ts | 24 + .../src/app/auth/login/login.component.ts | 99 + .../oauth-callback.component.ts | 37 + .../app/auth/register/register.component.ts | 93 + frontend/src/app/core/guards/auth.guard.ts | 15 + .../app/core/interceptors/jwt.interceptor.ts | 19 + frontend/src/app/core/models/auth-response.ts | 14 + frontend/src/app/core/models/page.ts | 18 + frontend/src/app/core/models/site.ts | 19 + .../src/app/core/services/auth.service.ts | 101 + .../src/app/core/services/page.service.ts | 25 + .../src/app/core/services/site.service.ts | 29 + .../create-site-dialog/create-site-dialog.ts | 72 + .../src/app/dashboard/dashboard.component.ts | 142 + .../delete-site-dialog/delete-site-dialog.ts | 24 + frontend/src/assets/.gitkeep | 0 frontend/src/favicon.ico | Bin 0 -> 15086 bytes frontend/src/index.html | 15 + frontend/src/main.ts | 6 + frontend/src/styles.css | 10 + frontend/tailwind.config.js | 13 + frontend/tsconfig.app.json | 14 + frontend/tsconfig.json | 32 + frontend/tsconfig.spec.json | 14 + 110 files changed, 28049 insertions(+) create mode 100644 .gitignore create mode 100644 PLAN.md create mode 100644 README.md create mode 100644 backend/build.gradle create mode 100644 backend/gradle/wrapper/gradle-wrapper.properties create mode 100755 backend/gradlew create mode 100644 backend/gradlew.bat create mode 100644 backend/settings.gradle create mode 100644 backend/src/main/java/com/indie/IndieApplication.java create mode 100644 backend/src/main/java/com/indie/config/GitConfig.java create mode 100644 backend/src/main/java/com/indie/config/GlobalExceptionHandler.java create mode 100644 backend/src/main/java/com/indie/config/JwtAuthenticationToken.java create mode 100644 backend/src/main/java/com/indie/config/JwtConfig.java create mode 100644 backend/src/main/java/com/indie/config/SecurityConfig.java create mode 100644 backend/src/main/java/com/indie/config/TokenService.java create mode 100644 backend/src/main/java/com/indie/config/UserPrincipal.java create mode 100644 backend/src/main/java/com/indie/controller/AuthController.java create mode 100644 backend/src/main/java/com/indie/controller/PageController.java create mode 100644 backend/src/main/java/com/indie/controller/SiteController.java create mode 100644 backend/src/main/java/com/indie/dto/AuthResponse.java create mode 100644 backend/src/main/java/com/indie/dto/LoginRequest.java create mode 100644 backend/src/main/java/com/indie/dto/PageRequest.java create mode 100644 backend/src/main/java/com/indie/dto/PageResponse.java create mode 100644 backend/src/main/java/com/indie/dto/RefreshTokenRequest.java create mode 100644 backend/src/main/java/com/indie/dto/RegisterRequest.java create mode 100644 backend/src/main/java/com/indie/dto/SiteRequest.java create mode 100644 backend/src/main/java/com/indie/dto/SiteResponse.java create mode 100644 backend/src/main/java/com/indie/model/AuthProvider.java create mode 100644 backend/src/main/java/com/indie/model/Component.java create mode 100644 backend/src/main/java/com/indie/model/ComponentType.java create mode 100644 backend/src/main/java/com/indie/model/Page.java create mode 100644 backend/src/main/java/com/indie/model/Site.java create mode 100644 backend/src/main/java/com/indie/model/SiteStatus.java create mode 100644 backend/src/main/java/com/indie/model/User.java create mode 100644 backend/src/main/java/com/indie/repository/ComponentRepository.java create mode 100644 backend/src/main/java/com/indie/repository/PageRepository.java create mode 100644 backend/src/main/java/com/indie/repository/SiteRepository.java create mode 100644 backend/src/main/java/com/indie/repository/UserRepository.java create mode 100644 backend/src/main/java/com/indie/service/AuthService.java create mode 100644 backend/src/main/java/com/indie/service/CustomOAuth2User.java create mode 100644 backend/src/main/java/com/indie/service/OAuth2SuccessHandler.java create mode 100644 backend/src/main/java/com/indie/service/OAuth2UserService.java create mode 100644 backend/src/main/resources/application.yml create mode 100644 backend/src/test/java/com/indie/config/GlobalExceptionHandlerTest.java create mode 100644 backend/src/test/java/com/indie/config/UserPrincipalTest.java create mode 100644 backend/src/test/java/com/indie/controller/AuthControllerTest.java create mode 100644 backend/src/test/java/com/indie/controller/PageControllerTest.java create mode 100644 backend/src/test/java/com/indie/controller/SiteControllerTest.java create mode 100644 backend/src/test/java/com/indie/dto/PageResponseTest.java create mode 100644 backend/src/test/java/com/indie/dto/SiteResponseTest.java create mode 100644 backend/src/test/java/com/indie/model/ComponentTest.java create mode 100644 backend/src/test/java/com/indie/model/PageTest.java create mode 100644 backend/src/test/java/com/indie/model/SiteTest.java create mode 100644 backend/src/test/java/com/indie/model/UserTest.java create mode 100644 backend/src/test/java/com/indie/repository/ComponentRepositoryTest.java create mode 100644 backend/src/test/java/com/indie/repository/PageRepositoryTest.java create mode 100644 backend/src/test/java/com/indie/repository/SiteRepositoryTest.java create mode 100644 backend/src/test/java/com/indie/repository/UserRepositoryTest.java create mode 100644 backend/src/test/java/com/indie/service/AuthServiceTest.java create mode 100644 backend/src/test/java/com/indie/service/OAuth2UserServiceTest.java create mode 100644 backend/src/test/java/com/indie/support/FakeComponentRepository.java create mode 100644 backend/src/test/java/com/indie/support/FakeJwtConfig.java create mode 100644 backend/src/test/java/com/indie/support/FakePageRepository.java create mode 100644 backend/src/test/java/com/indie/support/FakeSiteRepository.java create mode 100644 backend/src/test/java/com/indie/support/FakeUserRepository.java create mode 100644 backend/src/test/java/com/indie/support/InMemoryRepository.java create mode 100644 backend/src/test/java/com/indie/support/StubPasswordEncoder.java create mode 100644 backend/src/test/java/com/indie/support/TestOAuth2User.java create mode 100644 backend/src/test/java/com/indie/support/TestSecurityConfig.java create mode 100644 backend/src/test/resources/application.yml create mode 100644 docker-compose.yml create mode 100644 frontend/.editorconfig create mode 100644 frontend/.gitignore create mode 100644 frontend/Dockerfile create mode 100644 frontend/README.md create mode 100644 frontend/angular.json create mode 100644 frontend/nginx.conf create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/pnpm-lock.yaml create mode 100644 frontend/postcss.config.js create mode 100644 frontend/proxy.conf.json create mode 100644 frontend/src/app/app.component.css create mode 100644 frontend/src/app/app.component.html create mode 100644 frontend/src/app/app.component.ts create mode 100644 frontend/src/app/app.config.ts create mode 100644 frontend/src/app/app.routes.ts create mode 100644 frontend/src/app/auth/login/login.component.ts create mode 100644 frontend/src/app/auth/oauth-callback/oauth-callback.component.ts create mode 100644 frontend/src/app/auth/register/register.component.ts create mode 100644 frontend/src/app/core/guards/auth.guard.ts create mode 100644 frontend/src/app/core/interceptors/jwt.interceptor.ts create mode 100644 frontend/src/app/core/models/auth-response.ts create mode 100644 frontend/src/app/core/models/page.ts create mode 100644 frontend/src/app/core/models/site.ts create mode 100644 frontend/src/app/core/services/auth.service.ts create mode 100644 frontend/src/app/core/services/page.service.ts create mode 100644 frontend/src/app/core/services/site.service.ts create mode 100644 frontend/src/app/dashboard/create-site-dialog/create-site-dialog.ts create mode 100644 frontend/src/app/dashboard/dashboard.component.ts create mode 100644 frontend/src/app/dashboard/delete-site-dialog/delete-site-dialog.ts create mode 100644 frontend/src/assets/.gitkeep create mode 100644 frontend/src/favicon.ico create mode 100644 frontend/src/index.html create mode 100644 frontend/src/main.ts create mode 100644 frontend/src/styles.css create mode 100644 frontend/tailwind.config.js create mode 100644 frontend/tsconfig.app.json create mode 100644 frontend/tsconfig.json create mode 100644 frontend/tsconfig.spec.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1a65c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Java / Gradle (Backend) +backend/.gradle/ +backend/build/ +backend/bin/ +backend/out/ + +# Node / Angular (Frontend) +frontend/node_modules/ +frontend/dist/ +frontend/tmp/ +frontend/out-tsc/ +frontend/.angular/cache/ +frontend/coverage/ + +# Environment files +.env +.env.* +backend/src/main/resources/application-local.yml +backend/src/main/resources/application-dev.yml + +# IDE +.idea/ +.vscode/ +*.iml +*.ipr +*.iws +.project +.classpath +.settings/ +*.sublime-workspace + +# OS +.DS_Store +Thumbs.db +*.swp +*.swo +*~ + +# Logs +*.log + +# Docker +docker-data/ + +# Secrets / keys / certificates +backend/config/ +*.key +*.pem +*.p8 +*.p12 +*.pfx +*.crt +*.cert +*.jks +*.keystore +*.secret + +# Misc +*.jar +*.war +*.ear +*.tar.gz +*.zip diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..53b0a38 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,293 @@ +# Indie — Independent Website Platform + +A platform that lets anyone create, own, and publish their own static website without social media gatekeeping. Built with a drag-and-drop builder and LLM prompt-to-site generation. Every site is backed by a git repository. Users self-host or use free subdomain hosting. + +--- + +## Tech Stack + +| Layer | Technology | +|-------|-----------| +| Backend | Java 17, Spring Boot 3.x, Gradle (Groovy) | +| Frontend | Angular 17, Angular Material, Angular CDK (drag-drop) | +| Relational DB | PostgreSQL | +| Document DB | MongoDB (LLM sessions) | +| Object Storage | Cloudflare R2 (S3-compatible) | +| LLM | Gemini (primary), OpenAI (fallback), provider-abstraction for future | +| Auth | Spring Security + OAuth2 Client — email/password, Google OAuth, GitHub OAuth, OpenID Connect | +| Git | JGit — local repo per site, optional GitHub/GitLab remote push | +| Infra | Docker Compose (dev), R2 + Cloudflare (hosting), Caddy/nginx (prod reverse proxy) | + +--- + +## Build Phases + +### v0.1 — Auth & Foundation (Target: Weeks 1-3) + +**Goal:** User can register, log in via email or OAuth, and create/manage sites and pages. + +#### Backend + +| File | Action | Details | +|------|--------|---------| +| `backend/build.gradle` | Add | Spring Boot 3.x, deps: web, jpa, security, oauth2-client, oauth2-resource-server, validation, lombok, postgresql, testcontainers, aws-java-sdk-s3 (R2), springdoc-openapi, jgit | +| `backend/settings.gradle` | Add | Project name, plugin management | +| `backend/src/main/resources/application.yml` | Add | DB configs, JWT keys, OAuth client IDs/secrets, LLM keys, R2 credentials, git config | +| `com/indie/IndieApplication.java` | Add | Main class | +| `com/indie/config/SecurityConfig.java` | Add | SecurityFilterChain with JWT filter + OAuth2 login + OpenID Connect. Route permissions: `/api/auth/**` public, `/api/**` authenticated | +| `com/indie/config/JwtConfig.java` | Add | RS256 signing, access token 15min, refresh token 7d | +| `com/indie/config/GitConfig.java` | Add | Repos root path (`/var/git/sites/`), author name/email | +| `com/indie/model/User.java` | Add | id(UUID), email, password(bcrypt, nullable), name, avatarUrl, provider(LOCAL/GOOGLE/GITHUB/OPENID), providerId, emailVerified, createdAt, updatedAt | +| `com/indie/model/Site.java` | Add | id, userId, name, description, subdomain(unique), themeConfig(JSONB), status(DRAFT/PUBLISHED), publishedAt, createdAt, updatedAt | +| `com/indie/model/Page.java` | Add | id, siteId(FK), title, slug, seoTitle, seoDescription, orderIndex, createdAt | +| `com/indie/model/Component.java` | Add | id, pageId(FK), type(enum), config(JSONB), styles(JSONB), orderIndex | +| `com/indie/repository/*.java` | Add | JPA repositories for User, Site, Page, Component | +| `com/indie/service/AuthService.java` | Add | register, login, refreshToken, oauthLogin | +| `com/indie/service/OAuth2UserService.java` | Add | Maps Google/GitHub/OpenID user info to User entity | +| `com/indie/controller/AuthController.java` | Add | `POST /api/auth/register`, `/login`, `/refresh`, `/logout` | +| `com/indie/controller/SiteController.java` | Add | Full CRUD: `GET/POST /api/sites`, `GET/PUT/DELETE /api/sites/{id}` | +| `com/indie/controller/PageController.java` | Add | CRUD for pages within a site | + +#### Frontend + +| File | Action | Details | +|------|--------|---------| +| `frontend/` | Init | Angular 17 standalone, Angular Material, lazy routes, Tailwind CSS | +| `src/app/auth/` | Add | LoginComponent, RegisterComponent, OAuth callback handler, AuthService, AuthGuard, JWT interceptor | +| `src/app/dashboard/` | Add | DashboardComponent (list site cards), CreateSiteDialog, DeleteSiteDialog | + +#### Infrastructure + +| File | Action | Details | +|------|--------|---------| +| `docker-compose.yml` | Add | PostgreSQL, MongoDB, MinIO (local R2 mock), backend (8080), frontend (4200) | + +--- + +### v0.2 — Drag-and-Drop Builder (Target: Weeks 4-6) + +**Goal:** User can visually build a website by dragging components onto a canvas, editing their properties, styling via theme editor, and previewing live. + +#### Backend + +| File | Action | Details | +|------|--------|---------| +| `com/indie/controller/BuilderController.java` | Add | `GET /api/sites/{id}/pages` (with nested components), `PUT /api/sites/{id}/pages/{pageId}/components` (batch save), `GET/PUT /api/sites/{id}/theme` | +| `com/indie/service/BuilderService.java` | Add | Validate component tree (type enum, config schema, max 50/page), save in transaction | + +#### Frontend + +| File | Action | Details | +|------|--------|---------| +| `src/app/builder/builder.component.ts` | Add | 3-panel layout (palette 250px, canvas flex, properties 320px) via CSS Grid or mat-sidenav | +| `src/app/builder/services/builder-state.service.ts` | Add | BehaviorSubject store: `components$`, `selectedComponentId$`, `themeConfig$`, `pages$`. Methods: add, remove, update, reorder. Undo/redo stack (50 snapshots) | +| `src/app/builder/services/auto-save.service.ts` | Add | 2s debounce → `PUT` batch save. "Saving..."/"Saved" indicator | +| `src/app/builder/component-palette/` | Add | PaletteComponent — Material list of 10 draggable component types, organized by category | +| `src/app/builder/canvas/` | Add | CanvasComponent — `cdkDropList` accepting drops, renders components in order, highlight on select, delete on hover | +| `src/app/builder/property-panel/` | Add | PropertyPanelComponent — dynamic form per type (config + styles sections). Material expansion panels | +| `src/app/builder/renderer/` | Add | Render components per type (heading, text, image, button, divider, gallery, video, contact_form, map, custom_html) — each takes `config` + `styles` as `@Input()` | +| `src/app/builder/theme-editor/` | Add | ThemeEditorComponent — color pickers, font selectors, spacing slider. Live preview updates | +| `src/app/builder/preview/` | Add | PreviewComponent — sandboxed `