mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-03-11 18:27:57 +08:00
### What problem does this PR solve? As title ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Signed-off-by: Jin Hai <haijin.chn@gmail.com>
997 lines
23 KiB
Go
997 lines
23 KiB
Go
//
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package admin
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"ragflow/internal/common"
|
|
"ragflow/internal/server"
|
|
"ragflow/internal/service"
|
|
"ragflow/internal/utility"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// Common errors
|
|
var (
|
|
ErrInvalidCredentials = errors.New("invalid credentials")
|
|
ErrUserNotFound = errors.New("user not found")
|
|
ErrInvalidToken = errors.New("invalid token")
|
|
)
|
|
|
|
// Handler admin handler
|
|
type Handler struct {
|
|
service *Service
|
|
userService *service.UserService
|
|
}
|
|
|
|
// NewHandler create admin handler
|
|
func NewHandler(service *Service, userService *service.UserService) *Handler {
|
|
return &Handler{service: service, userService: userService}
|
|
}
|
|
|
|
// SuccessResponse success response
|
|
type SuccessResponse struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data"`
|
|
}
|
|
|
|
// ErrorResponse error response
|
|
type ErrorResponse struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// success returns success response
|
|
func success(c *gin.Context, data interface{}, message string) {
|
|
c.JSON(200, SuccessResponse{
|
|
Code: 0,
|
|
Message: message,
|
|
Data: data,
|
|
})
|
|
}
|
|
|
|
// successNoData returns success response without data
|
|
func successNoData(c *gin.Context, message string) {
|
|
c.JSON(200, SuccessResponse{
|
|
Code: 0,
|
|
Message: message,
|
|
Data: nil,
|
|
})
|
|
}
|
|
|
|
// error returns error response
|
|
func errorResponse(c *gin.Context, message string, code int) {
|
|
c.JSON(code, ErrorResponse{
|
|
Code: code,
|
|
Message: message,
|
|
})
|
|
}
|
|
|
|
// Health health check
|
|
func (h *Handler) Health(c *gin.Context) {
|
|
c.JSON(200, gin.H{"status": "ok"})
|
|
}
|
|
|
|
// Ping ping endpoint
|
|
func (h *Handler) Ping(c *gin.Context) {
|
|
successNoData(c, "PONG")
|
|
}
|
|
|
|
// LoginHTTPRequest login request body
|
|
type LoginHTTPRequest struct {
|
|
Email string `json:"email" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
}
|
|
|
|
// Login handle admin login
|
|
func (h *Handler) Login(c *gin.Context) {
|
|
var req service.EmailLoginRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": 400,
|
|
"message": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
user, code, err := h.userService.LoginByEmail(&req, true)
|
|
if err != nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{
|
|
"code": code,
|
|
"message": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
variables := server.GetVariables()
|
|
secretKey := variables.SecretKey
|
|
authToken, err := utility.DumpAccessToken(*user.AccessToken, secretKey)
|
|
|
|
// Set Authorization header with access_token
|
|
if user.AccessToken != nil {
|
|
c.Header("Authorization", authToken)
|
|
}
|
|
// Set CORS headers
|
|
c.Header("Access-Control-Allow-Origin", "*")
|
|
c.Header("Access-Control-Allow-Methods", "*")
|
|
c.Header("Access-Control-Allow-Headers", "*")
|
|
c.Header("Access-Control-Expose-Headers", "Authorization")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": common.CodeSuccess,
|
|
"message": "Welcome back!",
|
|
"data": user,
|
|
})
|
|
}
|
|
|
|
// Logout handle logout
|
|
func (h *Handler) Logout(c *gin.Context) {
|
|
user, exists := c.Get("user")
|
|
if !exists {
|
|
errorResponse(c, "Not authenticated", 401)
|
|
return
|
|
}
|
|
|
|
if err := h.service.Logout(user); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Logout successful")
|
|
}
|
|
|
|
// AuthCheck check admin auth
|
|
func (h *Handler) AuthCheck(c *gin.Context) {
|
|
successNoData(c, "Admin is authorized")
|
|
}
|
|
|
|
// ListUsers handle list users
|
|
func (h *Handler) ListUsers(c *gin.Context) {
|
|
users, err := h.service.ListUsers()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, users, "Get all users")
|
|
}
|
|
|
|
// CreateUserHTTPRequest create user request
|
|
type CreateUserHTTPRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
// CreateUser handle create user
|
|
func (h *Handler) CreateUser(c *gin.Context) {
|
|
var req CreateUserHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Username and password are required", 400)
|
|
return
|
|
}
|
|
|
|
if req.Role == "" {
|
|
req.Role = "user"
|
|
}
|
|
|
|
userInfo, err := h.service.CreateUser(req.Username, req.Password, req.Role)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, userInfo, "User created successfully")
|
|
}
|
|
|
|
// GetUser handle get user
|
|
func (h *Handler) GetUser(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
userDetails, err := h.service.GetUserDetails(username)
|
|
if err != nil {
|
|
if errors.Is(err, ErrUserNotFound) {
|
|
errorResponse(c, "User not found", 404)
|
|
return
|
|
}
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, userDetails, "")
|
|
}
|
|
|
|
// DeleteUser handle delete user
|
|
func (h *Handler) DeleteUser(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.DeleteUser(username); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "User deleted successfully")
|
|
}
|
|
|
|
// ChangePasswordHTTPRequest change password request
|
|
type ChangePasswordHTTPRequest struct {
|
|
NewPassword string `json:"new_password" binding:"required"`
|
|
}
|
|
|
|
// ChangePassword handle change password
|
|
func (h *Handler) ChangePassword(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
var req ChangePasswordHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "New password is required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.ChangePassword(username, req.NewPassword); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Password updated successfully")
|
|
}
|
|
|
|
// UpdateActivateStatusHTTPRequest update activate status request
|
|
type UpdateActivateStatusHTTPRequest struct {
|
|
ActivateStatus bool `json:"activate_status" binding:"required"`
|
|
}
|
|
|
|
// UpdateUserActivateStatus handle update user activate status
|
|
func (h *Handler) UpdateUserActivateStatus(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
var req UpdateActivateStatusHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Activation status is required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.UpdateUserActivateStatus(username, req.ActivateStatus); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Activation status updated")
|
|
}
|
|
|
|
// GrantAdmin handle grant admin role
|
|
func (h *Handler) GrantAdmin(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
// Get current user from context
|
|
currentUser, _ := c.Get("user")
|
|
if currentUser != nil && currentUser.(string) == username {
|
|
errorResponse(c, "can't grant current user: "+username, 409)
|
|
return
|
|
}
|
|
|
|
if err := h.service.GrantAdmin(username); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Admin role granted")
|
|
}
|
|
|
|
// RevokeAdmin handle revoke admin role
|
|
func (h *Handler) RevokeAdmin(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
// Get current user from context
|
|
currentUser, _ := c.Get("user")
|
|
if currentUser != nil && currentUser.(string) == username {
|
|
errorResponse(c, "can't revoke current user: "+username, 409)
|
|
return
|
|
}
|
|
|
|
if err := h.service.RevokeAdmin(username); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Admin role revoked")
|
|
}
|
|
|
|
// GetUserDatasets handle get user datasets
|
|
func (h *Handler) GetUserDatasets(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
datasets, err := h.service.GetUserDatasets(username)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, datasets, "")
|
|
}
|
|
|
|
// GetUserAgents handle get user agents
|
|
func (h *Handler) GetUserAgents(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
agents, err := h.service.GetUserAgents(username)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, agents, "")
|
|
}
|
|
|
|
// GetUserAPIKeys handle get user API keys
|
|
func (h *Handler) GetUserAPIKeys(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
apiKeys, err := h.service.GetUserAPIKeys(username)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, apiKeys, "Get user API keys")
|
|
}
|
|
|
|
// GenerateUserAPIKey handle generate user API key
|
|
func (h *Handler) GenerateUserAPIKey(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
apiKey, err := h.service.GenerateUserAPIKey(username)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, apiKey, "API key generated successfully")
|
|
}
|
|
|
|
// DeleteUserAPIKey handle delete user API key
|
|
func (h *Handler) DeleteUserAPIKey(c *gin.Context) {
|
|
username := c.Param("username")
|
|
key := c.Param("key")
|
|
if username == "" || key == "" {
|
|
errorResponse(c, "Username and key are required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.DeleteUserAPIKey(username, key); err != nil {
|
|
errorResponse(c, err.Error(), 404)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "API key deleted successfully")
|
|
}
|
|
|
|
// ListRoles handle list roles
|
|
func (h *Handler) ListRoles(c *gin.Context) {
|
|
roles, err := h.service.ListRoles()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, roles, "")
|
|
}
|
|
|
|
// CreateRoleHTTPRequest create role request
|
|
type CreateRoleHTTPRequest struct {
|
|
RoleName string `json:"role_name" binding:"required"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
// CreateRole handle create role
|
|
func (h *Handler) CreateRole(c *gin.Context) {
|
|
var req CreateRoleHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
role, err := h.service.CreateRole(req.RoleName, req.Description)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, role, "")
|
|
}
|
|
|
|
// GetRole handle get role
|
|
func (h *Handler) GetRole(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
role, err := h.service.GetRole(roleName)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, role, "")
|
|
}
|
|
|
|
// UpdateRoleHTTPRequest update role request
|
|
type UpdateRoleHTTPRequest struct {
|
|
Description string `json:"description" binding:"required"`
|
|
}
|
|
|
|
// UpdateRole handle update role
|
|
func (h *Handler) UpdateRole(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
var req UpdateRoleHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Role description is required", 400)
|
|
return
|
|
}
|
|
|
|
role, err := h.service.UpdateRole(roleName, req.Description)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, role, "")
|
|
}
|
|
|
|
// DeleteRole handle delete role
|
|
func (h *Handler) DeleteRole(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.DeleteRole(roleName); err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "")
|
|
}
|
|
|
|
// GetRolePermission handle get role permission
|
|
func (h *Handler) GetRolePermission(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
permissions, err := h.service.GetRolePermission(roleName)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, permissions, "")
|
|
}
|
|
|
|
// GrantRolePermissionHTTPRequest grant role permission request
|
|
type GrantRolePermissionHTTPRequest struct {
|
|
Actions []string `json:"actions" binding:"required"`
|
|
Resource string `json:"resource" binding:"required"`
|
|
}
|
|
|
|
// GrantRolePermission handle grant role permission
|
|
func (h *Handler) GrantRolePermission(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
var req GrantRolePermissionHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Permission is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.GrantRolePermission(roleName, req.Actions, req.Resource)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// RevokeRolePermissionHTTPRequest revoke role permission request
|
|
type RevokeRolePermissionHTTPRequest struct {
|
|
Actions []string `json:"actions" binding:"required"`
|
|
Resource string `json:"resource" binding:"required"`
|
|
}
|
|
|
|
// RevokeRolePermission handle revoke role permission
|
|
func (h *Handler) RevokeRolePermission(c *gin.Context) {
|
|
roleName := c.Param("role_name")
|
|
if roleName == "" {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
var req RevokeRolePermissionHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Permission is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.RevokeRolePermission(roleName, req.Actions, req.Resource)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// UpdateUserRoleHTTPRequest update user role request
|
|
type UpdateUserRoleHTTPRequest struct {
|
|
RoleName string `json:"role_name" binding:"required"`
|
|
}
|
|
|
|
// UpdateUserRole handle update user role
|
|
func (h *Handler) UpdateUserRole(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
var req UpdateUserRoleHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Role name is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.UpdateUserRole(username, req.RoleName)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// GetUserPermission handle get user permission
|
|
func (h *Handler) GetUserPermission(c *gin.Context) {
|
|
username := c.Param("username")
|
|
if username == "" {
|
|
errorResponse(c, "Username is required", 400)
|
|
return
|
|
}
|
|
|
|
permissions, err := h.service.GetUserPermission(username)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, permissions, "")
|
|
}
|
|
|
|
// GetServices handle get all services
|
|
func (h *Handler) GetServices(c *gin.Context) {
|
|
services, err := h.service.ListServices()
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": common.CodeServerError,
|
|
"message": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
success(c, services, "Get all services")
|
|
}
|
|
|
|
// GetServicesByType handle get services by type
|
|
func (h *Handler) GetServicesByType(c *gin.Context) {
|
|
serviceType := c.Param("service_type")
|
|
if serviceType == "" {
|
|
errorResponse(c, "Service type is required", 400)
|
|
return
|
|
}
|
|
|
|
services, err := h.service.GetServicesByType(serviceType)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, services, "")
|
|
}
|
|
|
|
// GetService handle get service details
|
|
func (h *Handler) GetService(c *gin.Context) {
|
|
serviceID := c.Param("service_id")
|
|
if serviceID == "" {
|
|
errorResponse(c, "Service ID is required", 400)
|
|
return
|
|
}
|
|
|
|
// Get all services and find the one with matching ID
|
|
allConfigs := server.GetAllConfigs()
|
|
|
|
var targetService map[string]interface{}
|
|
for _, config := range allConfigs {
|
|
if id, ok := config["id"]; ok {
|
|
if strconv.Itoa(id.(int)) == serviceID {
|
|
targetService = config
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if targetService == nil {
|
|
errorResponse(c, "Service not found", 404)
|
|
return
|
|
}
|
|
|
|
serviceStatus, err := h.service.GetServiceDetails(targetService)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, serviceStatus, "")
|
|
}
|
|
|
|
// ShutdownService handle shutdown service
|
|
func (h *Handler) ShutdownService(c *gin.Context) {
|
|
serviceID := c.Param("service_id")
|
|
if serviceID == "" {
|
|
errorResponse(c, "Service ID is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.ShutdownService(serviceID)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// RestartService handle restart service
|
|
func (h *Handler) RestartService(c *gin.Context) {
|
|
serviceID := c.Param("service_id")
|
|
if serviceID == "" {
|
|
errorResponse(c, "Service ID is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.RestartService(serviceID)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// GetVariables handle get variables
|
|
func (h *Handler) GetVariables(c *gin.Context) {
|
|
varName := c.Query("var_name")
|
|
|
|
if varName != "" {
|
|
// Get single variable
|
|
variable, err := h.service.GetVariable(varName)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
success(c, variable, "")
|
|
return
|
|
}
|
|
|
|
// List all variables
|
|
variables, err := h.service.GetAllVariables()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
success(c, variables, "")
|
|
}
|
|
|
|
// SetVariableHTTPRequest set variable request
|
|
type SetVariableHTTPRequest struct {
|
|
VarName string `json:"var_name" binding:"required"`
|
|
VarValue string `json:"var_value" binding:"required"`
|
|
}
|
|
|
|
// SetVariable handle set variable
|
|
func (h *Handler) SetVariable(c *gin.Context) {
|
|
var req SetVariableHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Var name and value are required", 400)
|
|
return
|
|
}
|
|
|
|
if err := h.service.SetVariable(req.VarName, req.VarValue); err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Set variable successfully")
|
|
}
|
|
|
|
// GetConfigs handle get configs
|
|
func (h *Handler) GetConfigs(c *gin.Context) {
|
|
configs, err := h.service.GetAllConfigs()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, configs, "")
|
|
}
|
|
|
|
// GetEnvironments handle get environments
|
|
func (h *Handler) GetEnvironments(c *gin.Context) {
|
|
environments, err := h.service.GetAllEnvironments()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, environments, "")
|
|
}
|
|
|
|
// GetVersion handle get version
|
|
func (h *Handler) GetVersion(c *gin.Context) {
|
|
version := h.service.GetVersion()
|
|
success(c, gin.H{"version": version}, "")
|
|
}
|
|
|
|
// ListSandboxProviders handle list sandbox providers
|
|
func (h *Handler) ListSandboxProviders(c *gin.Context) {
|
|
providers, err := h.service.ListSandboxProviders()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, providers, "")
|
|
}
|
|
|
|
// GetSandboxProviderSchema handle get sandbox provider schema
|
|
func (h *Handler) GetSandboxProviderSchema(c *gin.Context) {
|
|
providerID := c.Param("provider_id")
|
|
if providerID == "" {
|
|
errorResponse(c, "Provider ID is required", 400)
|
|
return
|
|
}
|
|
|
|
schema, err := h.service.GetSandboxProviderSchema(providerID)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, schema, "")
|
|
}
|
|
|
|
// GetSandboxConfig handle get sandbox config
|
|
func (h *Handler) GetSandboxConfig(c *gin.Context) {
|
|
config, err := h.service.GetSandboxConfig()
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, config, "")
|
|
}
|
|
|
|
// SetSandboxConfigHTTPRequest set sandbox config request
|
|
type SetSandboxConfigHTTPRequest struct {
|
|
ProviderType string `json:"provider_type" binding:"required"`
|
|
Config map[string]interface{} `json:"config"`
|
|
SetActive bool `json:"set_active"`
|
|
}
|
|
|
|
// SetSandboxConfig handle set sandbox config
|
|
func (h *Handler) SetSandboxConfig(c *gin.Context) {
|
|
var req SetSandboxConfigHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Request body is required", 400)
|
|
return
|
|
}
|
|
|
|
if req.ProviderType == "" {
|
|
errorResponse(c, "provider_type is required", 400)
|
|
return
|
|
}
|
|
|
|
// Default to true for backward compatibility
|
|
_ = c.Request.Body.Close()
|
|
req.SetActive = true
|
|
|
|
result, err := h.service.SetSandboxConfig(req.ProviderType, req.Config, req.SetActive)
|
|
if err != nil {
|
|
errorResponse(c, err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
success(c, result, "Sandbox configuration updated successfully")
|
|
}
|
|
|
|
// TestSandboxConnectionHTTPRequest test sandbox connection request
|
|
type TestSandboxConnectionHTTPRequest struct {
|
|
ProviderType string `json:"provider_type" binding:"required"`
|
|
Config map[string]interface{} `json:"config"`
|
|
}
|
|
|
|
// TestSandboxConnection handle test sandbox connection
|
|
func (h *Handler) TestSandboxConnection(c *gin.Context) {
|
|
var req TestSandboxConnectionHTTPRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
errorResponse(c, "Request body is required", 400)
|
|
return
|
|
}
|
|
|
|
if req.ProviderType == "" {
|
|
errorResponse(c, "provider_type is required", 400)
|
|
return
|
|
}
|
|
|
|
result, err := h.service.TestSandboxConnection(req.ProviderType, req.Config)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": common.CodeBadRequest,
|
|
"message": "Invalid access token",
|
|
})
|
|
return
|
|
}
|
|
|
|
success(c, result, "")
|
|
}
|
|
|
|
// AuthMiddleware JWT auth middleware
|
|
func (h *Handler) AuthMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
token := c.GetHeader("Authorization")
|
|
if token == "" {
|
|
errorResponse(c, "missing authorization header", 401)
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
// Get user by access token
|
|
user, code, err := h.userService.GetUserByToken(token)
|
|
if err != nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{
|
|
"code": code,
|
|
"message": "Invalid access token",
|
|
})
|
|
return
|
|
}
|
|
|
|
if !*user.IsSuperuser {
|
|
c.JSON(http.StatusForbidden, gin.H{
|
|
"code": common.CodeForbidden,
|
|
"message": "Permission denied",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.Set("user", user)
|
|
c.Set("user_id", user.ID)
|
|
c.Set("email", user.Email)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// HandleNoRoute handle undefined routes
|
|
func (h *Handler) HandleNoRoute(c *gin.Context) {
|
|
c.JSON(http.StatusNotFound, ErrorResponse{
|
|
Code: 404,
|
|
Message: "The requested resource was not found",
|
|
})
|
|
}
|
|
|
|
// Reports handle heartbeat reports from servers
|
|
func (h *Handler) Reports(c *gin.Context) {
|
|
var req common.BaseMessage
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": common.CodeBadRequest,
|
|
"message": "Invalid request body: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Set default timestamp if not provided
|
|
if req.Timestamp.IsZero() {
|
|
req.Timestamp = time.Now()
|
|
}
|
|
|
|
// Only process heartbeat messages for now
|
|
if req.MessageType != common.MessageHeartbeat {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": common.CodeBadRequest,
|
|
"message": "Unsupported report type: " + string(req.MessageType),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Handle the heartbeat
|
|
if err := h.service.HandleHeartbeat(&req); err != nil {
|
|
errorResponse(c, "Failed to process heartbeat: "+err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
successNoData(c, "Heartbeat received successfully")
|
|
}
|