bismillah
This commit is contained in:
106
create-local-identity.go
Normal file
106
create-local-identity.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type CreateIdentityRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
}
|
||||
|
||||
func createLocalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var hashText string
|
||||
var salt []byte
|
||||
var err error
|
||||
var checkExisting pgx.Row
|
||||
var req CreateIdentityRequest
|
||||
var accountid string
|
||||
|
||||
response := map[string]interface{}{}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Only allow POST method
|
||||
if r.Method != http.MethodPost {
|
||||
//http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
response["status"] = "error"
|
||||
response["message"] = "HTTP POST Method not allowed"
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
// XXX Temporary Account Handler
|
||||
accountid = r.Header.Get("Account")
|
||||
if accountid == "" {
|
||||
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Missing Authentication header"
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
// Optional: enforce content type
|
||||
if r.Header.Get("Content-Type") != "application/json" {
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Content-Type must be application/json"
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
// Read body with size limit (protect against huge requests)
|
||||
const maxBodyBytes = 1 << 20 // 1 MB
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxBodyBytes)
|
||||
|
||||
// Decode JSON from request body directly into struct
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Invalid JSON: " + err.Error()
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
log.Println("Received Identity Request: AccountID:", accountid, "Username:", req.Username, "Password:", req.Password, "First Name:", req.FirstName, "LastName:", req.LastName)
|
||||
|
||||
// Check if policy with the same name already exists for the account
|
||||
checkExisting = pool.QueryRow(context.Background(),
|
||||
"SELECT FROM identities WHERE accountid = $1 AND provider_user_id = $2",
|
||||
accountid, req.Username)
|
||||
err = checkExisting.Scan()
|
||||
if err == nil {
|
||||
response["status"] = "fail"
|
||||
response["message"] = "Identity " + req.Username + " already exists: "
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
salt, _ = generateSalt()
|
||||
hashText = hashPassword(req.Password, salt)
|
||||
|
||||
_, err = pool.Exec(context.Background(),
|
||||
"INSERT INTO identities (accountid, provider, provider_user_id, password_hash) VALUES($1, $2, $3, $4) ON CONFLICT DO NOTHING",
|
||||
accountid, "local", req.Username, hashText)
|
||||
if err != nil {
|
||||
response["status"] = "fail"
|
||||
response["message"] = "Internal Server Error: " + err.Error()
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
goto ExitAPICall
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response["status"] = "success"
|
||||
ExitAPICall:
|
||||
response["timestamp"] = fmt.Sprintf("%d", time.Now().Unix())
|
||||
json.NewEncoder(w).Encode(response)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user