Files
GitOcean-Old/internal/app/cli_admin.go
T
2026-06-08 13:34:53 -05:00

124 lines
3.4 KiB
Go

package app
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
func cliToken(args []string) error {
if len(args) < 1 {
return errors.New("usage: gitocean token <list|revoke|prune>")
}
cfg, err := loadConfig()
if err != nil {
return err
}
switch args[0] {
case "list":
jsonOut := len(args) > 1 && args[1] == "--json"
if len(args) > 2 || (len(args) == 2 && !jsonOut) {
return errors.New("usage: gitocean token list [--json]")
}
var out []TokenInfo
if err := apiRequest(context.Background(), cfg.Server, http.MethodGet, "/api/tokens", cfg.Token, nil, &out); err != nil {
return err
}
if jsonOut {
printJSON(out)
return nil
}
for _, t := range out {
status := "revoked/expired"
if t.Active {
status = "active"
}
fmt.Printf("%-6d %-15s created=%s expires=%s\n", t.ID, status, t.CreatedAt.Format(time.RFC3339), t.ExpiresAt.Format(time.RFC3339))
}
return nil
case "revoke":
if len(args) != 2 {
return errors.New("usage: gitocean token revoke TOKEN_ID")
}
return apiRequest(context.Background(), cfg.Server, http.MethodDelete, "/api/tokens/"+args[1], cfg.Token, nil, nil)
case "prune":
return apiRequest(context.Background(), cfg.Server, http.MethodPost, "/api/tokens/prune", cfg.Token, nil, nil)
default:
return fmt.Errorf("unknown token command %q", args[0])
}
}
func cliAdmin(args []string) error {
if len(args) < 2 {
return errors.New("usage: gitocean admin users list | repos list | storage check | tokens prune")
}
cfg, err := loadConfig()
if err != nil {
return err
}
switch args[0] + " " + args[1] {
case "users list":
var out []User
if err := apiRequest(context.Background(), cfg.Server, http.MethodGet, "/api/admin/users", cfg.Token, nil, &out); err != nil {
return err
}
for _, u := range out {
fmt.Printf("%-20s %-30s admin=%v\n", u.Username, u.Email, u.IsAdmin)
}
return nil
case "users delete":
if len(args) != 3 {
return errors.New("usage: gitocean admin users delete USER")
}
return apiRequest(context.Background(), cfg.Server, http.MethodDelete, "/api/admin/users/"+strings.ToLower(args[2]), cfg.Token, nil, nil)
case "repos list":
var out []Repository
if err := apiRequest(context.Background(), cfg.Server, http.MethodGet, "/api/admin/repos", cfg.Token, nil, &out); err != nil {
return err
}
printRepoTable(out)
return nil
case "storage check":
serverCfg, err := loadServerConfig(defaultServerConfigPath())
if err != nil {
return err
}
return filepath.Walk(filepath.Join(serverCfg.Storage, "repos"), func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info != nil && info.IsDir() && strings.HasSuffix(path, ".git") {
fmt.Println(path)
}
return nil
})
case "tokens prune":
return apiRequest(context.Background(), cfg.Server, http.MethodPost, "/api/admin/tokens/prune", cfg.Token, nil, nil)
default:
return errors.New("usage: gitocean admin users list | repos list | storage check | tokens prune")
}
}
func cliBackup(args []string) error {
if len(args) != 2 {
return errors.New("usage: gitocean backup create FILE | restore FILE")
}
cfg, err := loadServerConfig(defaultServerConfigPath())
if err != nil {
return err
}
switch args[0] {
case "create":
return createBackup(cfg, args[1])
case "restore":
return restoreBackup(cfg, args[1])
default:
return errors.New("usage: gitocean backup create FILE | restore FILE")
}
}