You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudreve/service/admin/oauth_client.go

192 lines
5.1 KiB

package admin
import (
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/inventory"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
)
// System OAuth client GUIDs that cannot be deleted
var systemOAuthClientGUIDs = []string{
inventory.OAuthClientDesktopGUID,
inventory.OAuthClientiOSGUID,
}
type (
SingleOAuthClientService struct {
ID int `uri:"id" json:"id" binding:"required"`
}
SingleOAuthClientParamCtx struct{}
)
type (
UpsertOAuthClientService struct {
Client *ent.OAuthClient `json:"client" binding:"required"`
}
UpsertOAuthClientParamCtx struct{}
)
type (
BatchOAuthClientService struct {
IDs []int `json:"ids" binding:"required"`
}
BatchOAuthClientParamCtx struct{}
)
// OAuthClients lists OAuth clients with pagination
func (s *AdminListService) OAuthClients(c *gin.Context) (*ListOAuthClientResponse, error) {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
var isEnabled *bool
if enabledStr, ok := s.Conditions["is_enabled"]; ok {
enabled := enabledStr == "true"
isEnabled = &enabled
}
res, err := oauthClient.List(c, &inventory.ListOAuthClientArgs{
PaginationArgs: &inventory.PaginationArgs{
Page: s.Page - 1,
PageSize: s.PageSize,
OrderBy: s.OrderBy,
Order: inventory.OrderDirection(s.OrderDirection),
},
Name: s.Searches["name"],
IsEnabled: isEnabled,
})
if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list OAuth clients", err)
}
clients := lo.Map(res.Clients, func(client *ent.OAuthClient, _ int) GetOAuthClientResponse {
return GetOAuthClientResponse{
OAuthClient: client,
IsSystem: lo.Contains(systemOAuthClientGUIDs, client.GUID),
}
})
return &ListOAuthClientResponse{
Pagination: res.PaginationResults,
Clients: clients,
}, nil
}
func (s *SingleOAuthClientService) Get(c *gin.Context) (*GetOAuthClientResponse, error) {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
client, err := oauthClient.GetByID(c, s.ID)
if err != nil {
return nil, serializer.NewError(serializer.CodeNotFound, "OAuth client not found", err)
}
res := &GetOAuthClientResponse{
OAuthClient: client,
IsSystem: lo.Contains(systemOAuthClientGUIDs, client.GUID),
}
// Count grants
grants, err := oauthClient.CountGrants(c, s.ID)
if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to count grants", err)
}
res.TotalGrants = grants
return res, nil
}
func (s *UpsertOAuthClientService) Create(c *gin.Context) (*GetOAuthClientResponse, error) {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
if s.Client.ID > 0 {
return nil, serializer.NewError(serializer.CodeParamErr, "ID must be 0 for creating new OAuth client", nil)
}
client, err := oauthClient.Create(c, s.Client)
if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to create OAuth client", err)
}
service := &SingleOAuthClientService{ID: client.ID}
return service.Get(c)
}
func (s *UpsertOAuthClientService) Update(c *gin.Context) (*GetOAuthClientResponse, error) {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
if s.Client.ID == 0 {
return nil, serializer.NewError(serializer.CodeParamErr, "ID is required", nil)
}
// Check if this is a system client
existing, err := oauthClient.GetByID(c, s.Client.ID)
if err != nil {
return nil, serializer.NewError(serializer.CodeNotFound, "OAuth client not found", err)
}
// System clients cannot change GUID
if lo.Contains(systemOAuthClientGUIDs, existing.GUID) {
s.Client.GUID = existing.GUID
}
_, err = oauthClient.Update(c, s.Client)
if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to update OAuth client", err)
}
service := &SingleOAuthClientService{ID: s.Client.ID}
return service.Get(c)
}
func (s *SingleOAuthClientService) Delete(c *gin.Context) error {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
// Check if client exists
client, err := oauthClient.GetByID(c, s.ID)
if err != nil {
return serializer.NewError(serializer.CodeNotFound, "OAuth client not found", err)
}
// Check if this is a system client
if lo.Contains(systemOAuthClientGUIDs, client.GUID) {
return serializer.NewError(serializer.CodeInvalidActionOnSystemGroup, "Cannot delete system OAuth client", nil)
}
err = oauthClient.Delete(c, s.ID)
if err != nil {
return serializer.NewError(serializer.CodeDBError, "Failed to delete OAuth client", err)
}
return nil
}
func (s *BatchOAuthClientService) Delete(c *gin.Context) error {
dep := dependency.FromContext(c)
oauthClient := dep.OAuthClientClient()
for _, id := range s.IDs {
// Check if client exists
client, err := oauthClient.GetByID(c, id)
if err != nil {
continue // Skip non-existent clients
}
// Check if this is a system client
if lo.Contains(systemOAuthClientGUIDs, client.GUID) {
continue // Skip system clients
}
// Delete the client (including grants)
oauthClient.Delete(c, id)
}
return nil
}