From c23145f3389d7953c2a2d73f5d30d2740b7753ad Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Thu, 11 Dec 2025 21:00:13 +0530 Subject: [PATCH 1/4] feat(auth): separate auth and blog API clients and integrate author auto-creation ## Summary Refactored the authentication flow to correctly separate traffic between the Auth service and Blog service. Added post-registration author creation and switched all `/auth/*` calls to the dedicated `auth` Axios client. ## Changes ### AuthProvider - Replaced `api.post('/auth/register')` with `auth.post('/register')` - Replaced `api.post('/auth/login')` with `auth.post('/login')` - Added automatic author creation after user registration (`POST /authors`) - Switched user identity lookup from `api.get('/auth/me')` to `auth.get('/me')` - Replaced `/authors/{id}` lookup with `/authors/me` - Updated imports to use `{ api, auth }` ### Axios Client Layer - Introduced a new `auth` Axios instance using `VITE_AUTH_BASE_URL` - Added shared token attachment and 401 handling logic - Applied interceptors to both `auth` and `api` clients - Removed inline auth logic from `api.ts` ### Types - Added `VITE_AUTH_BASE_URL` to `vite-env.d.ts` ## Impact - Correctly routes authentication traffic to the Auth microservice - Ensures an Author document is created automatically after registration - Simplifies identity loading via `/authors/me` - Improves token handling consistency across both services --- src/blog/providers/Author.tsx | 17 +++++++--- src/blog/utils/api.ts | 60 +++++++++++++++++++++++------------ src/vite-env.d.ts | 1 + 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/blog/providers/Author.tsx b/src/blog/providers/Author.tsx index 1df7c07..a42de49 100644 --- a/src/blog/providers/Author.tsx +++ b/src/blog/providers/Author.tsx @@ -1,5 +1,5 @@ import React, { createContext, useState, useEffect, useContext } from 'react'; -import { api } from '../utils/api'; +import { api, auth } from '../utils/api'; import { AuthorModel } from '../types/models'; import { AuthContextModel } from '../types/contexts'; @@ -18,7 +18,14 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children setLoading(true); setError(null); - const res = await api.post('/auth/register', { username, password }); + const res = await auth.post('/register', { username, password }); + + // auto-login + // await login(username, password); + + // now create author + await api.post('/authors', { name: null, avatar: null }); + return res.data; } catch (err: any) { console.error('Registration failed:', err); @@ -34,7 +41,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children setLoading(true); setError(null); - const res = await api.post('/auth/login', { username, password }); + const res = await auth.post('/login', { username, password }); const { access_token, user } = res.data; if (access_token) { @@ -99,9 +106,9 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const fetchCurrentUser = async () => { if (!token) return; try { - const me = await api.get<{ _id: string; username: string; email: string }>('/auth/me'); + const me = await auth.get('/me'); - const author = await api.get(`/authors/${me.data._id}`); + const author = await api.get(`/authors/me`); const fullUser = { ...me.data, ...author.data }; diff --git a/src/blog/utils/api.ts b/src/blog/utils/api.ts index 671417f..e6d29f4 100644 --- a/src/blog/utils/api.ts +++ b/src/blog/utils/api.ts @@ -1,8 +1,42 @@ // src/utils/api.ts import axios from 'axios'; +const AUTH_BASE = import.meta.env.VITE_AUTH_BASE_URL; const API_BASE = import.meta.env.VITE_API_BASE_URL; +//------------------------------------------------------ +// COMMON TOKEN ATTACHMENT LOGIC +//------------------------------------------------------ +const attachToken = (config: any) => { + const token = localStorage.getItem('token'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}; + +const handleAuthError = (error: any) => { + if (error.response?.status === 401) { + console.warn('Token expired or invalid. Logging out...'); + localStorage.removeItem('token'); + // Optional: eventBus, redirect, logout callback + } + return Promise.reject(error); +}; + +//------------------------------------------------------ +// AUTH SERVICE CLIENT +//------------------------------------------------------ +export const auth = axios.create({ + baseURL: AUTH_BASE, + headers: { + 'Content-Type': 'application/json', + }, +}); + +//------------------------------------------------------ +// BLOG SERVICE CLIENT +//------------------------------------------------------ export const api = axios.create({ baseURL: API_BASE, headers: { @@ -10,24 +44,10 @@ export const api = axios.create({ }, }); -// 🔹 Attach token from localStorage before each request -api.interceptors.request.use((config) => { - const token = localStorage.getItem('token'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; -}); +// Attach token + 401 handling +api.interceptors.request.use(attachToken); +api.interceptors.response.use((res) => res, handleAuthError); -// 🔹 Handle expired or invalid tokens globally -api.interceptors.response.use( - (response) => response, - (error) => { - if (error.response?.status === 401) { - console.warn('Token expired or invalid. Logging out...'); - localStorage.removeItem('token'); - // Optionally: trigger a redirect or event - } - return Promise.reject(error); - } -); +// Auth service ALSO needs token for /me, /logout, /introspect +auth.interceptors.request.use(attachToken); +auth.interceptors.response.use((res) => res, handleAuthError); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 8304c33..9ce06ff 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -2,6 +2,7 @@ interface ImportMetaEnv { readonly VITE_API_BASE_URL: string; + readonly VITE_AUTH_BASE_URL: string; } interface ImportMeta { -- 2.49.1 From 8fe75b161b366a64d68cfb4b5d375eac54f5f9df Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 13 Dec 2025 18:11:55 +0530 Subject: [PATCH 2/4] disabled changing username --- src/blog/components/Profile.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blog/components/Profile.tsx b/src/blog/components/Profile.tsx index 21b7e10..a5710c1 100644 --- a/src/blog/components/Profile.tsx +++ b/src/blog/components/Profile.tsx @@ -133,6 +133,7 @@ export default function Profile({ label="Username" name="username" margin="normal" + disabled={true} value={formData.username} onChange={handleChange} /> -- 2.49.1 From 80992f89ad3bd4a47772e3158f2c4f15cc3fbd85 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 13 Dec 2025 18:38:28 +0530 Subject: [PATCH 3/4] added AUTH_BASE_URL in .drone.yml --- .drone.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.drone.yml b/.drone.yml index 678f7c4..98b2a5f 100644 --- a/.drone.yml +++ b/.drone.yml @@ -66,6 +66,8 @@ steps: environment: API_BASE_URL: from_secret: API_BASE_URL + AUTH_BASE_URL: + from_secret: AUTH_BASE_URL volumes: - name: dockersock path: /var/run/docker.sock @@ -76,6 +78,7 @@ steps: - | docker build --network=host \ --build-arg VITE_API_BASE_URL="$API_BASE_URL" \ + --build-arg VITE_AUTH_BASE_URL="$AUTH_BASE_URL" \ -t apps/blog:$IMAGE_TAG \ -t apps/blog:latest \ /drone/src -- 2.49.1 From d61415236a4c19faa84577c2ad43820d19060149 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 13 Dec 2025 18:42:58 +0530 Subject: [PATCH 4/4] bumped up version to 0.3.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e0205f5..b2649f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "aetoskia-blog-app", - "version": "0.2.1", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index e82d80d..11d7745 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aetoskia-blog-app", - "version": "0.2.5", + "version": "0.3.0", "private": true, "scripts": { "dev": "vite", -- 2.49.1