From 1c347d14b649fc0c4b5b612e66f3a3d6b1617ff7 Mon Sep 17 00:00:00 2001 From: NanamiAdmin Date: Tue, 3 Mar 2026 22:43:27 +0800 Subject: [PATCH] refactor: reorganize handler files and rename frpc.go to frpAct.go Move user authentication handlers to userAct.go and frpc instance handlers to frpAct.go Remove handlers from handlers.go and clean up file structure --- frpc.go => frpAct.go | 0 handlers.go | 152 ---------------------------------------- userAct.go | 161 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 152 deletions(-) rename frpc.go => frpAct.go (100%) create mode 100644 userAct.go diff --git a/frpc.go b/frpAct.go similarity index 100% rename from frpc.go rename to frpAct.go diff --git a/handlers.go b/handlers.go index 751b8dd..a914686 100644 --- a/handlers.go +++ b/handlers.go @@ -10,164 +10,12 @@ import ( "time" ) -type RegisterRequest struct { - Username string `json:"username"` - Passwd string `json:"passwd"` -} - -type LoginRequest struct { - Username string `json:"username"` - Passwd string `json:"passwd"` -} - type Response struct { Success bool `json:"success"` Message string `json:"message,omitempty"` Data interface{} `json:"data,omitempty"` } -func RegisterHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") - postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request method: %s", r.Method)) - return - } - - if !ValidateTimeStamp(r.Header) { - SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") - postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid or missing X-Timestamp in header: %s", r.Header.Get("X-Timestamp"))) - return - } - - body, err := io.ReadAll(r.Body) - if err != nil { - SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") - postLog.Warning(fmt.Sprintf("[RegisterHandler] Failed to read request body: %v", err)) - return - } - defer r.Body.Close() - - var req RegisterRequest - if err := json.Unmarshal(body, &req); err != nil { - SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") - postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request format: %v", err)) - return - } - - if req.Username == "" || req.Passwd == "" { - SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") - postLog.Warning("[RegisterHandler] New user registration failed: username or password is empty") - return - } - - if !isValidInput(req.Username) || !isValidInput(req.Passwd) { - SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") - postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) - return - } - - if !isValidPassword(req.Passwd) { - SendErrorResponse(w, http.StatusBadRequest, "Password does not meet complexity requirements (must contain uppercase, lowercase, digit, and special character)") - postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: password \"%s\" does not meet complexity requirements", req.Passwd)) - return - } - - userID, err := AddUser(req.Username, req.Passwd) - if err != nil { - SendErrorResponse(w, http.StatusInternalServerError, err.Error()) - postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err)) - return - } - - user, err := GetUserByID(userID) - if err != nil { - SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after registration") - postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to retrieve user \"%s\" after registration: %v", req.Username, err)) - return - } - - SendSuccessResponse(w, "user registered successfully", map[string]interface{}{ - "userID": user.UserID, - "username": user.Username, - "type": user.Type, - }) -} - -func LoginHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") - postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request method: %s", r.Method)) - return - } - - if !ValidateTimeStamp(r.Header) { - SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") - return - } - - body, err := io.ReadAll(r.Body) - if err != nil { - SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") - postLog.Warning(fmt.Sprintf("[LoginHandler] Failed to read request body: %v", err)) - return - } - defer r.Body.Close() - - var req LoginRequest - if err := json.Unmarshal(body, &req); err != nil { - SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") - postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request format: %v", err)) - return - } - - if req.Username == "" || req.Passwd == "" { - SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") - postLog.Warning("[LoginHandler] Login failed: username or password is empty") - return - } - - if !isValidInput(req.Username) || !isValidInput(req.Passwd) { - SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") - postLog.Debug(fmt.Sprintf("[LoginHandler] Login failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) - return - } - - user, err := GetUserByUsername(req.Username) - if err != nil { - SendErrorResponse(w, http.StatusUnauthorized, "User not exist") - postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: User not exist \"%s\"", req.Username)) - return - } - - if !verifyPassword(req.Passwd, user.Passwd) { - SendErrorResponse(w, http.StatusUnauthorized, "Invalid password") - postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: invalid password for user \"%s\"", req.Username)) - return - } - - existingTokenInfo, err := GetTokenInfo(user.UserID) - if err == nil && existingTokenInfo != nil { - SendErrorResponse(w, http.StatusConflict, "User is already logged in") - postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: user \"%s\" is already logged in", req.Username)) - return - } - - token, err := GenerateToken(user.UserID) - if err != nil { - SendErrorResponse(w, http.StatusInternalServerError, "Failed to generate token") - postLog.Error(fmt.Sprintf("[LoginHandler] Failed to generate token for user \"%s\": %v", req.Username, err)) - return - } - - SendSuccessResponse(w, "Login successful", map[string]interface{}{ - "token": token, - "userID": user.UserID, - "username": user.Username, - "type": user.Type, - }) - postLog.Info(fmt.Sprintf("[LoginHandler] User \"%s\" Login successful", req.Username)) -} - func SendErrorResponse(w http.ResponseWriter, statusCode int, message string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) diff --git a/userAct.go b/userAct.go new file mode 100644 index 0000000..cc5d28f --- /dev/null +++ b/userAct.go @@ -0,0 +1,161 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "super-frpc/postLog" +) + +type RegisterRequest struct { + Username string `json:"username"` + Passwd string `json:"passwd"` +} + +type LoginRequest struct { + Username string `json:"username"` + Passwd string `json:"passwd"` +} + +func RegisterHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") + postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request method: %s", r.Method)) + return + } + + if !ValidateTimeStamp(r.Header) { + SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") + postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid or missing X-Timestamp in header: %s", r.Header.Get("X-Timestamp"))) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + postLog.Warning(fmt.Sprintf("[RegisterHandler] Failed to read request body: %v", err)) + return + } + defer r.Body.Close() + + var req RegisterRequest + if err := json.Unmarshal(body, &req); err != nil { + SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + postLog.Warning(fmt.Sprintf("[RegisterHandler] Invalid request format: %v", err)) + return + } + + if req.Username == "" || req.Passwd == "" { + SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") + postLog.Warning("[RegisterHandler] New user registration failed: username or password is empty") + return + } + + if !isValidInput(req.Username) || !isValidInput(req.Passwd) { + SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") + postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) + return + } + + if !isValidPassword(req.Passwd) { + SendErrorResponse(w, http.StatusBadRequest, "Password does not meet complexity requirements (must contain uppercase, lowercase, digit, and special character)") + postLog.Debug(fmt.Sprintf("[RegisterHandler] New user registration failed: password \"%s\" does not meet complexity requirements", req.Passwd)) + return + } + + userID, err := AddUser(req.Username, req.Passwd) + if err != nil { + SendErrorResponse(w, http.StatusInternalServerError, err.Error()) + postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to register user \"%s\": %v", req.Username, err)) + return + } + + user, err := GetUserByID(userID) + if err != nil { + SendErrorResponse(w, http.StatusInternalServerError, "Failed to retrieve user after registration") + postLog.Error(fmt.Sprintf("[RegisterHandler] Failed to retrieve user \"%s\" after registration: %v", req.Username, err)) + return + } + + SendSuccessResponse(w, "user registered successfully", map[string]interface{}{ + "userID": user.UserID, + "username": user.Username, + "type": user.Type, + }) +} + +func LoginHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") + postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request method: %s", r.Method)) + return + } + + if !ValidateTimeStamp(r.Header) { + SendErrorResponse(w, http.StatusBadRequest, "Invalid or missing X-Timestamp in header") + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body") + postLog.Warning(fmt.Sprintf("[LoginHandler] Failed to read request body: %v", err)) + return + } + defer r.Body.Close() + + var req LoginRequest + if err := json.Unmarshal(body, &req); err != nil { + SendErrorResponse(w, http.StatusBadRequest, "Invalid request format") + postLog.Warning(fmt.Sprintf("[LoginHandler] Invalid request format: %v", err)) + return + } + + if req.Username == "" || req.Passwd == "" { + SendErrorResponse(w, http.StatusBadRequest, "Username and password are required") + postLog.Warning("[LoginHandler] Login failed: username or password is empty") + return + } + + if !isValidInput(req.Username) || !isValidInput(req.Passwd) { + SendErrorResponse(w, http.StatusBadRequest, "Invalid input: contains illegal characters") + postLog.Debug(fmt.Sprintf("[LoginHandler] Login failed: username or password contains illegal characters \"%s\":\"%s\"", req.Username, req.Passwd)) + return + } + + user, err := GetUserByUsername(req.Username) + if err != nil { + SendErrorResponse(w, http.StatusUnauthorized, "User not exist") + postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: User not exist \"%s\"", req.Username)) + return + } + + if !verifyPassword(req.Passwd, user.Passwd) { + SendErrorResponse(w, http.StatusUnauthorized, "Invalid password") + postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: invalid password for user \"%s\"", req.Username)) + return + } + + existingTokenInfo, err := GetTokenInfo(user.UserID) + if err == nil && existingTokenInfo != nil { + SendErrorResponse(w, http.StatusConflict, "User is already logged in") + postLog.Warning(fmt.Sprintf("[LoginHandler] Login failed: user \"%s\" is already logged in", req.Username)) + return + } + + token, err := GenerateToken(user.UserID) + if err != nil { + SendErrorResponse(w, http.StatusInternalServerError, "Failed to generate token") + postLog.Error(fmt.Sprintf("[LoginHandler] Failed to generate token for user \"%s\": %v", req.Username, err)) + return + } + + SendSuccessResponse(w, "Login successful", map[string]interface{}{ + "token": token, + "userID": user.UserID, + "username": user.Username, + "type": user.Type, + }) + postLog.Info(fmt.Sprintf("[LoginHandler] User \"%s\" Login successful", req.Username)) +}