Move user authentication handlers to userAct.go and frpc instance handlers to frpAct.go Remove handlers from handlers.go and clean up file structure
162 lines
5.6 KiB
Go
162 lines
5.6 KiB
Go
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))
|
|
}
|