Gt

Client (Angular) <-> API Gateway (Go) <-> Database (PostgreSQL) ↑ JWT Auth - /cmd/api - /internal - /handlers - /models - /middleware - /config - /migrations - /pkg - /auth CREATE TABLE users ( id UUID PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(20) CHECK (role IN ('admin', 'user', 'company')) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE vehicles ( id UUID PRIMARY KEY, user_id UUID REFERENCES users(id), make VARCHAR(255) NOT NULL, model VARCHAR(255) NOT NULL, year INTEGER NOT NULL, vin VARCHAR(17) UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); package middleware import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" ) func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { tokenString := c.GetHeader("Authorization") if tokenString == "" { c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"}) return } token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return []byte(config.JWTSecret), nil }) if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { c.Set("userID", claims["sub"]) c.Set("userRole", claims["role"]) c.Next() } else { c.AbortWithStatusJSON(401, gin.H{"error": "Invalid token", "details": err.Error()}) } } } func RoleMiddleware(allowedRoles []string) gin.HandlerFunc { return func(c *gin.Context) { userRole, _ := c.Get("userRole") for _, role := range allowedRoles { if role == userRole { c.Next() return } } c.AbortWithStatusJSON(403, gin.H{"error": "Forbidden"}) } } package handlers func RegisterUser(c *gin.Context) { var user models.User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } // Validate role if !isValidRole(user.Role) { c.JSON(400, gin.H{"error": "Invalid role"}) return } // Hash password hashedPassword, err := auth.HashPassword(user.Password) if err != nil { c.JSON(500, gin.H{"error": "Could not create user"}) return } // Save to database newUser := models.User{ ID: uuid.New(), Email: user.Email, PasswordHash: hashedPassword, Role: user.Role, } if err := config.DB.Create(&newUser).Error; err != nil { c.JSON(500, gin.H{"error": "Could not create user"}) return } c.JSON(201, gin.H{"message": "User created successfully"}) } // auth.service.ts @Injectable({ providedIn: 'root' }) export class AuthService { private apiUrl = environment.apiUrl; constructor(private http: HttpClient) {} login(credentials: { email: string, password: string }): Observable { return this.http.post(`${this.apiUrl}/login`, credentials).pipe( tap((res: any) => { localStorage.setItem('access_token', res.token); }) ); } register(user: { email: string, password: string, role: string }): Observable { return this.http.post(`${this.apiUrl}/register`, user); } } // auth.guard.ts @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { if (this.authService.isLoggedIn()) { const requiredRoles = next.data['roles'] as Array; const userRole = this.authService.getUserRole(); if (requiredRoles && !requiredRoles.includes(userRole)) { this.router.navigate(['/forbidden']); return false; } return true; } this.router.navigate(['/login']); return false; } } // jwt.interceptor.ts @Injectable() export class JwtInterceptor implements HttpInterceptor { intercept(request: HttpRequest, next: HttpHandler): Observable> { const token = localStorage.getItem('access_token'); if (token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next.handle(request); } } JWT_SECRET=your_strong_secret_here DB_HOST=your_db_host DB_USER=your_db_user DB_PASSWORD=your_db_password func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "http://your-angular-app:4200") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization") c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) return } c.Next() } }

Comments

Popular posts from this blog

Explore the techniques and tips for achieving the ideal texture in cooking, such as crispy, tender, or creamy.

Share your favorite tips for balancing flavors and creating well-seasoned dishes.