package handler import ( "encoding/json" "log" "net/http" "aws-sts-mock/internal/kvdb" ) // UserHandler handles user management operations type UserHandler struct { db kvdb.KVDB } // NewUserHandler creates a new user handler func NewUserHandler(db kvdb.KVDB) *UserHandler { return &UserHandler{ db: db, } } // CreateUser creates a new user func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var user kvdb.User if err := json.NewDecoder(r.Body).Decode(&user); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return } // Validate required fields if user.AccessKeyID == "" || user.SecretAccessKey == "" || user.AccountID == "" { http.Error(w, "Missing required fields: access_key_id, secret_access_key, account_id", http.StatusBadRequest) return } if err := h.db.CreateUser(&user); err != nil { if err == kvdb.ErrUserAlreadyExists { http.Error(w, "User already exists", http.StatusConflict) return } log.Printf("Error creating user: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } log.Printf("Created user: %s (Account: %s)", user.Username, user.AccountID) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(map[string]string{ "message": "User created successfully", "access_key_id": user.AccessKeyID, "account_id": user.AccountID, }) } // GetUser retrieves a user by access key ID func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } accessKeyID := r.URL.Query().Get("access_key_id") if accessKeyID == "" { http.Error(w, "Missing access_key_id query parameter", http.StatusBadRequest) return } user, err := h.db.GetUser(accessKeyID) if err != nil { if err == kvdb.ErrUserNotFound { http.Error(w, "User not found", http.StatusNotFound) return } log.Printf("Error getting user: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } // Don't send secret key in response response := map[string]string{ "access_key_id": user.AccessKeyID, "account_id": user.AccountID, "username": user.Username, "email": user.Email, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } // ListUsers lists all users func (h *UserHandler) ListUsers(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } users, err := h.db.ListUsers() if err != nil { log.Printf("Error listing users: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } // Don't send secret keys in response var response []map[string]string for _, user := range users { response = append(response, map[string]string{ "access_key_id": user.AccessKeyID, "account_id": user.AccountID, "username": user.Username, "email": user.Email, }) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } // DeleteUser deletes a user func (h *UserHandler) DeleteUser(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } accessKeyID := r.URL.Query().Get("access_key_id") if accessKeyID == "" { http.Error(w, "Missing access_key_id query parameter", http.StatusBadRequest) return } if err := h.db.DeleteUser(accessKeyID); err != nil { if err == kvdb.ErrUserNotFound { http.Error(w, "User not found", http.StatusNotFound) return } log.Printf("Error deleting user: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } log.Printf("Deleted user: %s", accessKeyID) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "message": "User deleted successfully", }) } // UpdateUser updates a user func (h *UserHandler) UpdateUser(w http.ResponseWriter, r *http.Request) { if r.Method != "PUT" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var user kvdb.User if err := json.NewDecoder(r.Body).Decode(&user); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return } if user.AccessKeyID == "" { http.Error(w, "Missing access_key_id", http.StatusBadRequest) return } if err := h.db.UpdateUser(&user); err != nil { if err == kvdb.ErrUserNotFound { http.Error(w, "User not found", http.StatusNotFound) return } log.Printf("Error updating user: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } log.Printf("Updated user: %s", user.AccessKeyID) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "message": "User updated successfully", }) }