Move user authentication handlers to userAct.go and frpc instance handlers to frpAct.go Remove handlers from handlers.go and clean up file structure
170 lines
4.2 KiB
Go
170 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"super-frpc/postLog"
|
|
"time"
|
|
)
|
|
|
|
type Response struct {
|
|
Success bool `json:"success"`
|
|
Message string `json:"message,omitempty"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
}
|
|
|
|
func SendErrorResponse(w http.ResponseWriter, statusCode int, message string) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(statusCode)
|
|
resp := Response{
|
|
Success: false,
|
|
Message: message,
|
|
}
|
|
jsonResp, err := json.Marshal(resp)
|
|
if err != nil {
|
|
postLog.Error(fmt.Sprintf("Failed to marshal error response: %v", err))
|
|
return
|
|
}
|
|
w.Write(jsonResp)
|
|
}
|
|
|
|
func SendSuccessResponse(w http.ResponseWriter, message string, data interface{}) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
resp := Response{
|
|
Success: true,
|
|
Message: message,
|
|
Data: data,
|
|
}
|
|
jsonResp, err := json.Marshal(resp)
|
|
if err != nil {
|
|
postLog.Error(fmt.Sprintf("Failed to marshal success response: %v", err))
|
|
return
|
|
}
|
|
w.Write(jsonResp)
|
|
}
|
|
|
|
func ValidateRequest(w http.ResponseWriter, r *http.Request, requiredFields ...string) (int, string, error) { // ValidateRequest validates the request body and header
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("Failed to read request body: %w", err)
|
|
}
|
|
defer r.Body.Close()
|
|
|
|
return ValidateRequestWithBody(w, r, body, requiredFields...)
|
|
}
|
|
|
|
func ValidateRequestWithBody(w http.ResponseWriter, r *http.Request, body []byte, requiredFields ...string) (int, string, error) {
|
|
var reqMap map[string]interface{}
|
|
if err := json.Unmarshal(body, &reqMap); err != nil {
|
|
return 0, "", fmt.Errorf("Invalid request format: %w", err)
|
|
}
|
|
|
|
token := r.Header.Get("X-Token")
|
|
if token == "" {
|
|
return 0, "", fmt.Errorf("Token is required in header: %s", token)
|
|
}
|
|
|
|
if !isDebug {
|
|
if !ValidateTimeStamp(r.Header) {
|
|
return 0, "", fmt.Errorf("Invalid or missing X-Timestamp in header")
|
|
}
|
|
}
|
|
|
|
userID, err := extractUserIDFromToken(token)
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("Invalid token format: %w", err)
|
|
}
|
|
|
|
if err := ValidateToken(userID, token); err != nil {
|
|
return 0, "", fmt.Errorf("Token validation failed: %w", err)
|
|
}
|
|
|
|
for _, field := range requiredFields {
|
|
if _, ok := reqMap[field]; !ok {
|
|
return 0, "", fmt.Errorf("required field %s is missing: %s", field, reqMap[field])
|
|
}
|
|
}
|
|
|
|
return userID, token, nil
|
|
}
|
|
|
|
func ValidateRequestWithHeader(w http.ResponseWriter, r *http.Request, requiredFields ...string) (int, string, error) {
|
|
token := r.Header.Get("X-Token")
|
|
if token == "" {
|
|
return 0, "", fmt.Errorf("Token is required in header: %s", token)
|
|
}
|
|
|
|
if !isDebug {
|
|
if !ValidateTimeStamp(r.Header) {
|
|
return 0, "", fmt.Errorf("Invalid or missing X-Timestamp in header")
|
|
}
|
|
}
|
|
|
|
userID, err := extractUserIDFromToken(token)
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("Invalid token format in header: %w", err)
|
|
}
|
|
|
|
if err := ValidateToken(userID, token); err != nil {
|
|
return 0, "", fmt.Errorf("Token validation failed in header: %w", err)
|
|
}
|
|
|
|
for _, field := range requiredFields {
|
|
headerValue := r.Header.Get(fmt.Sprintf("X-%s", field))
|
|
if headerValue == "" {
|
|
return 0, "", fmt.Errorf("required field %s is missing in header: %s", field, headerValue)
|
|
}
|
|
}
|
|
|
|
return userID, token, nil
|
|
}
|
|
|
|
func GetUserType(userID int) (string, error) {
|
|
user, err := GetUserByID(userID)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Failed to get user type: %w", err)
|
|
}
|
|
return user.Type, nil
|
|
}
|
|
|
|
func CheckPermission(userID int, requiredTypes ...string) error {
|
|
userType, err := GetUserType(userID)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to check permission: %w", err)
|
|
}
|
|
|
|
for _, t := range requiredTypes {
|
|
if userType == t {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("Permission denied for user type %s", userType)
|
|
}
|
|
|
|
func GetClientIP(r *http.Request) string {
|
|
forwarded := r.Header.Get("X-Forwarded-For")
|
|
if forwarded != "" {
|
|
return forwarded
|
|
}
|
|
return r.RemoteAddr
|
|
}
|
|
|
|
func LogRequest(r *http.Request, userID int) {
|
|
postLog.Info(fmt.Sprintf("[%s] %s %s - UserID: %d - IP: %s",
|
|
time.Now().Format("2006-01-02 15:04:05"),
|
|
r.Method,
|
|
r.URL.Path,
|
|
userID,
|
|
GetClientIP(r),
|
|
))
|
|
}
|
|
|
|
func IntToString(i int) string {
|
|
return strconv.Itoa(i)
|
|
}
|