package main import ( "context" "encoding/json" "io" "log" "net/http" "strings" "time" "github.com/golang-jwt/jwt/v5" ) type APIResponse[T any] struct { Timestamp int64 `json:"timestamp"` Status string `json:"status"` // "success" or "fail" Message string `json:"message"` Response T `json:"response"` } // Custom claims struct type MyClaims struct { Sub string `json:"sub"` Purpose string `json:"purpose"` Account string `json:"account"` jwt.RegisteredClaims } type RoleCreateType struct { Rolename string `json:"rolename"` Description string `json:"description"` } func createRole(w http.ResponseWriter, r *http.Request) { var response APIResponse[string] // Only allow POST if r.Method != http.MethodPost { response.Timestamp = time.Now().Unix() response.Status = "error" response.Message = "HTTP POST method not allowed" //response.Response: "Testing" w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusMethodNotAllowed) json.NewEncoder(w).Encode(response) return } // Get JWT from Authorization header authHeader := r.Header.Get("Authorization") if authHeader == "" { response.Timestamp = time.Now().Unix() response.Status = "error" response.Message = "HTTP POST method not allowed" //response.Response: "Testing" w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) json.NewEncoder(w).Encode(response) return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { http.Error(w, "Invalid Authorization format", http.StatusUnauthorized) return } tokenString := parts[1] // Replace with your actual secret or keyfunc secret := []byte("super-secret-key") claims := &MyClaims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { // Validate signing method if needed return secret, nil }) if err != nil || !token.Valid { http.Error(w, "Invalid token", http.StatusUnauthorized) return } // Access parsed values log.Println("sub:", claims.Sub) log.Println("purpose:", claims.Purpose) log.Println("account:", claims.Account) // exp and iat come from RegisteredClaims log.Println("exp:", claims.ExpiresAt) log.Println("iat:", claims.IssuedAt) if claims.ExpiresAt == nil || time.Now().After(claims.ExpiresAt.Time) { http.Error(w, "Token expired", http.StatusUnauthorized) return } // Read the raw request body body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Failed to read body", http.StatusBadRequest) return } defer r.Body.Close() // Parse JSON into Role struct var role RoleCreateType if err := json.Unmarshal(body, &role); err != nil { http.Error(w, "Invalid JSON", http.StatusBadRequest) return } if role.Rolename == "" { http.Error(w, "Rolename is required", http.StatusBadRequest) return } // Print the parsed values to terminal log.Println("Rolename:", role.Rolename) log.Println("Description:", role.Description) // Prevent duplication of roles with the same name for the same account checkExisting := pool.QueryRow(context.Background(), "SELECT FROM roles WHERE accountid = $1 AND rolename = $2", claims.Account, role.Rolename) err = checkExisting.Scan() if err == nil { log.Println("Already exists") w.WriteHeader(http.StatusConflict) return } _, err = pool.Exec( context.Background(), "INSERT INTO roles (accountid, rolename, description) VALUES ($1, $2, $3)", claims.Account, role.Rolename, role.Description) if err != nil { log.Println("Error inserting role into database:", err) http.Error(w, "Failed to create role", http.StatusInternalServerError) return } w.Write([]byte("JWT parsed successfully")) }