- Add GetMetrics method to MetricsClient interface and implement cluster metrics API - Add QuotaPrecheck service for validating resource quotas before deployment - Add auth DTO with role/permission models and auth handler tests - Add instance diagnostics: mounted NFS volumes, labels, annotations in pod diagnostics - Update workspace handler with GetWorkspace endpoint and shared-user list - Fix monitoring handler to use correct service method name - Add tail_lines fallback in instance handler for snake_case query params - Update nginx config for SSE log streaming support (no buffering) - Add comprehensive test coverage: auth_service_test, auth_handler_test, auth_dto_test, metrics_client_test, quota_precheck_test - Update error messages for quota validation and instance operations - ModifyModal: fix YAML lineWidth:0, modified keys summary, delta-only submit - InstanceCard: correctly disable scale-minus when replicas <= 0 - SidebarLayout: add hover transition for sidebar items - Update todo.md and lessons.md with latest fixes
143 lines
5.9 KiB
Go
143 lines
5.9 KiB
Go
package dto
|
|
|
|
import "strings"
|
|
|
|
// RegisterRequest 用户注册请求
|
|
type RegisterRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required,min=6"`
|
|
Role string `json:"role,omitempty"`
|
|
WorkspaceID string `json:"workspaceId,omitempty"`
|
|
WorkspaceIDSnake string `json:"workspace_id,omitempty"`
|
|
Namespace string `json:"namespace,omitempty"`
|
|
DefaultClusterID string `json:"defaultClusterId,omitempty"`
|
|
DefaultClusterIDSnake string `json:"default_cluster_id,omitempty"`
|
|
QuotaCPU string `json:"quotaCpu,omitempty"`
|
|
QuotaCPUSnake string `json:"quota_cpu,omitempty"`
|
|
QuotaMemory string `json:"quotaMemory,omitempty"`
|
|
QuotaMemorySnake string `json:"quota_memory,omitempty"`
|
|
QuotaGPU string `json:"quotaGpu,omitempty"`
|
|
QuotaGPUSnake string `json:"quota_gpu,omitempty"`
|
|
QuotaGPUMem string `json:"quotaGpuMemory,omitempty"`
|
|
QuotaGPUMemSnake string `json:"quota_gpu_memory,omitempty"`
|
|
IsActive *bool `json:"isActive,omitempty"`
|
|
IsActiveSnake *bool `json:"is_active,omitempty"`
|
|
MustChangePassword *bool `json:"mustChangePassword,omitempty"`
|
|
MustChangePasswordSnake *bool `json:"must_change_password,omitempty"`
|
|
}
|
|
|
|
func (r *RegisterRequest) Normalize() {
|
|
if r == nil {
|
|
return
|
|
}
|
|
r.WorkspaceID = firstNonBlank(r.WorkspaceID, r.WorkspaceIDSnake)
|
|
r.DefaultClusterID = firstNonBlank(r.DefaultClusterID, r.DefaultClusterIDSnake)
|
|
r.QuotaCPU = firstNonBlank(r.QuotaCPU, r.QuotaCPUSnake)
|
|
r.QuotaMemory = firstNonBlank(r.QuotaMemory, r.QuotaMemorySnake)
|
|
r.QuotaGPU = firstNonBlank(r.QuotaGPU, r.QuotaGPUSnake)
|
|
r.QuotaGPUMem = firstNonBlank(r.QuotaGPUMem, r.QuotaGPUMemSnake)
|
|
if r.IsActive == nil {
|
|
r.IsActive = r.IsActiveSnake
|
|
}
|
|
if r.MustChangePassword == nil {
|
|
r.MustChangePassword = r.MustChangePasswordSnake
|
|
}
|
|
}
|
|
|
|
// LoginRequest 用户登录请求
|
|
type LoginRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
}
|
|
|
|
// RefreshTokenRequest 刷新 Token 请求
|
|
type RefreshTokenRequest struct {
|
|
RefreshToken string `json:"refreshToken" binding:"required"`
|
|
}
|
|
|
|
// AuthResponse 认证响应
|
|
type AuthResponse struct {
|
|
AccessToken string `json:"accessToken"`
|
|
RefreshToken string `json:"refreshToken"`
|
|
UserID string `json:"userId"`
|
|
Username string `json:"username"`
|
|
Role string `json:"role"`
|
|
WorkspaceID string `json:"workspaceId"`
|
|
WorkspaceName string `json:"workspaceName,omitempty"`
|
|
Namespace string `json:"namespace,omitempty"`
|
|
DefaultClusterID string `json:"defaultClusterId,omitempty"`
|
|
QuotaCPU string `json:"quotaCpu,omitempty"`
|
|
QuotaMemory string `json:"quotaMemory,omitempty"`
|
|
QuotaGPU string `json:"quotaGpu,omitempty"`
|
|
QuotaGPUMem string `json:"quotaGpuMemory,omitempty"`
|
|
Permissions []string `json:"permissions,omitempty"`
|
|
PermissionVersion int `json:"permissionVersion"`
|
|
}
|
|
|
|
// UserResponse 用户信息响应
|
|
type UserResponse struct {
|
|
ID string `json:"id"`
|
|
Username string `json:"username"`
|
|
Email string `json:"email"`
|
|
Role string `json:"role"`
|
|
WorkspaceID string `json:"workspaceId"`
|
|
WorkspaceName string `json:"workspaceName,omitempty"`
|
|
Namespace string `json:"namespace,omitempty"`
|
|
DefaultClusterID string `json:"defaultClusterId,omitempty"`
|
|
QuotaCPU string `json:"quotaCpu,omitempty"`
|
|
QuotaMemory string `json:"quotaMemory,omitempty"`
|
|
QuotaGPU string `json:"quotaGpu,omitempty"`
|
|
QuotaGPUMem string `json:"quotaGpuMemory,omitempty"`
|
|
IsActive bool `json:"isActive"`
|
|
MustChangePassword bool `json:"mustChangePassword"`
|
|
CreatedAt string `json:"createdAt"`
|
|
UpdatedAt string `json:"updatedAt"`
|
|
}
|
|
|
|
// UpdateUserRequest 管理员更新用户状态/角色请求
|
|
type UpdateUserRequest struct {
|
|
Role string `json:"role,omitempty"`
|
|
WorkspaceID string `json:"workspaceId,omitempty"`
|
|
WorkspaceIDSnake string `json:"workspace_id,omitempty"`
|
|
Namespace string `json:"namespace,omitempty"`
|
|
DefaultClusterID string `json:"defaultClusterId,omitempty"`
|
|
DefaultClusterIDSnake string `json:"default_cluster_id,omitempty"`
|
|
QuotaCPU string `json:"quotaCpu,omitempty"`
|
|
QuotaCPUSnake string `json:"quota_cpu,omitempty"`
|
|
QuotaMemory string `json:"quotaMemory,omitempty"`
|
|
QuotaMemorySnake string `json:"quota_memory,omitempty"`
|
|
QuotaGPU string `json:"quotaGpu,omitempty"`
|
|
QuotaGPUSnake string `json:"quota_gpu,omitempty"`
|
|
QuotaGPUMem string `json:"quotaGpuMemory,omitempty"`
|
|
QuotaGPUMemSnake string `json:"quota_gpu_memory,omitempty"`
|
|
IsActive *bool `json:"isActive,omitempty"`
|
|
IsActiveSnake *bool `json:"is_active,omitempty"`
|
|
MustChangePassword *bool `json:"mustChangePassword,omitempty"`
|
|
MustChangePasswordSnake *bool `json:"must_change_password,omitempty"`
|
|
}
|
|
|
|
func (r *UpdateUserRequest) Normalize() {
|
|
if r == nil {
|
|
return
|
|
}
|
|
r.WorkspaceID = firstNonBlank(r.WorkspaceID, r.WorkspaceIDSnake)
|
|
r.DefaultClusterID = firstNonBlank(r.DefaultClusterID, r.DefaultClusterIDSnake)
|
|
r.QuotaCPU = firstNonBlank(r.QuotaCPU, r.QuotaCPUSnake)
|
|
r.QuotaMemory = firstNonBlank(r.QuotaMemory, r.QuotaMemorySnake)
|
|
r.QuotaGPU = firstNonBlank(r.QuotaGPU, r.QuotaGPUSnake)
|
|
r.QuotaGPUMem = firstNonBlank(r.QuotaGPUMem, r.QuotaGPUMemSnake)
|
|
if r.IsActive == nil {
|
|
r.IsActive = r.IsActiveSnake
|
|
}
|
|
if r.MustChangePassword == nil {
|
|
r.MustChangePassword = r.MustChangePasswordSnake
|
|
}
|
|
}
|
|
|
|
func firstNonBlank(primary, alternate string) string {
|
|
if strings.TrimSpace(primary) != "" {
|
|
return primary
|
|
}
|
|
return alternate
|
|
}
|