From 4e251de2c3a18a347c3ef50bb597127e01d89507 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 00:07:29 +0000 Subject: [PATCH] feat(misc): add instance settings endpoints Co-Authored-By: Virgil --- docs/api-contract.md | 4 ++ misc.go | 36 ++++++++++++++ misc_test.go | 110 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/docs/api-contract.md b/docs/api-contract.md index a09d8cc..7225ea1 100644 --- a/docs/api-contract.md +++ b/docs/api-contract.md @@ -140,9 +140,13 @@ Coverage notes: rows list direct tests when a symbol is named in test names or r | method | MilestoneService.Get | `func (s *MilestoneService) Get(ctx context.Context, owner, repo string, id int64) (*types.Milestone, error)` | Get returns a single milestone by ID. | No direct tests. | | method | MilestoneService.ListAll | `func (s *MilestoneService) ListAll(ctx context.Context, params Params) ([]types.Milestone, error)` | ListAll returns all milestones for a repository. | No direct tests. | | method | MiscService.GetGitignoreTemplate | `func (s *MiscService) GetGitignoreTemplate(ctx context.Context, name string) (*types.GitignoreTemplateInfo, error)` | GetGitignoreTemplate returns a single gitignore template by name. | `TestMiscService_Good_GetGitignoreTemplate` | +| method | MiscService.GetAPISettings | `func (s *MiscService) GetAPISettings(ctx context.Context) (*types.GeneralAPISettings, error)` | GetAPISettings returns the instance's global API settings. | `TestMiscService_GetAPISettings_Good` | +| method | MiscService.GetAttachmentSettings | `func (s *MiscService) GetAttachmentSettings(ctx context.Context) (*types.GeneralAttachmentSettings, error)` | GetAttachmentSettings returns the instance's global attachment settings. | `TestMiscService_GetAttachmentSettings_Good` | | method | MiscService.GetLicense | `func (s *MiscService) GetLicense(ctx context.Context, name string) (*types.LicenseTemplateInfo, error)` | GetLicense returns a single licence template by name. | `TestMiscService_Bad_NotFound`, `TestMiscService_Good_GetLicense` | | method | MiscService.GetNodeInfo | `func (s *MiscService) GetNodeInfo(ctx context.Context) (*types.NodeInfo, error)` | GetNodeInfo returns the NodeInfo metadata for the Forgejo instance. | `TestMiscService_Good_GetNodeInfo` | +| method | MiscService.GetRepositorySettings | `func (s *MiscService) GetRepositorySettings(ctx context.Context) (*types.GeneralRepoSettings, error)` | GetRepositorySettings returns the instance's global repository settings. | `TestMiscService_GetRepositorySettings_Good` | | method | MiscService.GetVersion | `func (s *MiscService) GetVersion(ctx context.Context) (*types.ServerVersion, error)` | GetVersion returns the server version. | `TestMiscService_Good_GetVersion` | +| method | MiscService.GetUISettings | `func (s *MiscService) GetUISettings(ctx context.Context) (*types.GeneralUISettings, error)` | GetUISettings returns the instance's global UI settings. | `TestMiscService_GetUISettings_Good` | | method | MiscService.ListGitignoreTemplates | `func (s *MiscService) ListGitignoreTemplates(ctx context.Context) ([]string, error)` | ListGitignoreTemplates returns all available gitignore template names. | `TestMiscService_Good_ListGitignoreTemplates` | | method | MiscService.ListLicenses | `func (s *MiscService) ListLicenses(ctx context.Context) ([]types.LicensesTemplateListEntry, error)` | ListLicenses returns all available licence templates. | `TestMiscService_Good_ListLicenses` | | method | MiscService.RenderMarkdown | `func (s *MiscService) RenderMarkdown(ctx context.Context, text, mode string) (string, error)` | RenderMarkdown renders markdown text to HTML. The response is raw HTML text, not JSON. | `TestMiscService_Good_RenderMarkdown` | diff --git a/misc.go b/misc.go index a2ebda4..85e23d3 100644 --- a/misc.go +++ b/misc.go @@ -135,6 +135,42 @@ func (s *MiscService) GetNodeInfo(ctx context.Context) (*types.NodeInfo, error) return &out, nil } +// GetAPISettings returns the instance's global API settings. +func (s *MiscService) GetAPISettings(ctx context.Context) (*types.GeneralAPISettings, error) { + var out types.GeneralAPISettings + if err := s.client.Get(ctx, "/api/v1/settings/api", &out); err != nil { + return nil, err + } + return &out, nil +} + +// GetAttachmentSettings returns the instance's global attachment settings. +func (s *MiscService) GetAttachmentSettings(ctx context.Context) (*types.GeneralAttachmentSettings, error) { + var out types.GeneralAttachmentSettings + if err := s.client.Get(ctx, "/api/v1/settings/attachment", &out); err != nil { + return nil, err + } + return &out, nil +} + +// GetRepositorySettings returns the instance's global repository settings. +func (s *MiscService) GetRepositorySettings(ctx context.Context) (*types.GeneralRepoSettings, error) { + var out types.GeneralRepoSettings + if err := s.client.Get(ctx, "/api/v1/settings/repository", &out); err != nil { + return nil, err + } + return &out, nil +} + +// GetUISettings returns the instance's global UI settings. +func (s *MiscService) GetUISettings(ctx context.Context) (*types.GeneralUISettings, error) { + var out types.GeneralUISettings + if err := s.client.Get(ctx, "/api/v1/settings/ui", &out); err != nil { + return nil, err + } + return &out, nil +} + // GetVersion returns the server version. func (s *MiscService) GetVersion(ctx context.Context) (*types.ServerVersion, error) { var out types.ServerVersion diff --git a/misc_test.go b/misc_test.go index bf2fe2b..14f5c98 100644 --- a/misc_test.go +++ b/misc_test.go @@ -141,6 +141,116 @@ func TestMiscService_GetVersion_Good(t *testing.T) { } } +func TestMiscService_GetAPISettings_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/settings/api" { + t.Errorf("wrong path: %s", r.URL.Path) + } + json.NewEncoder(w).Encode(types.GeneralAPISettings{ + DefaultGitTreesPerPage: 25, + DefaultMaxBlobSize: 4096, + DefaultPagingNum: 1, + MaxResponseItems: 500, + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + settings, err := f.Misc.GetAPISettings(context.Background()) + if err != nil { + t.Fatal(err) + } + if settings.DefaultPagingNum != 1 || settings.MaxResponseItems != 500 { + t.Fatalf("unexpected api settings: %+v", settings) + } +} + +func TestMiscService_GetAttachmentSettings_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/settings/attachment" { + t.Errorf("wrong path: %s", r.URL.Path) + } + json.NewEncoder(w).Encode(types.GeneralAttachmentSettings{ + AllowedTypes: "image/*", + Enabled: true, + MaxFiles: 10, + MaxSize: 1048576, + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + settings, err := f.Misc.GetAttachmentSettings(context.Background()) + if err != nil { + t.Fatal(err) + } + if !settings.Enabled || settings.MaxFiles != 10 { + t.Fatalf("unexpected attachment settings: %+v", settings) + } +} + +func TestMiscService_GetRepositorySettings_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/settings/repository" { + t.Errorf("wrong path: %s", r.URL.Path) + } + json.NewEncoder(w).Encode(types.GeneralRepoSettings{ + ForksDisabled: true, + HTTPGitDisabled: true, + LFSDisabled: true, + MigrationsDisabled: true, + MirrorsDisabled: false, + StarsDisabled: true, + TimeTrackingDisabled: false, + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + settings, err := f.Misc.GetRepositorySettings(context.Background()) + if err != nil { + t.Fatal(err) + } + if !settings.ForksDisabled || !settings.HTTPGitDisabled { + t.Fatalf("unexpected repository settings: %+v", settings) + } +} + +func TestMiscService_GetUISettings_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/settings/ui" { + t.Errorf("wrong path: %s", r.URL.Path) + } + json.NewEncoder(w).Encode(types.GeneralUISettings{ + AllowedReactions: []string{"+1", "-1"}, + CustomEmojis: []string{":forgejo:"}, + DefaultTheme: "forgejo-auto", + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + settings, err := f.Misc.GetUISettings(context.Background()) + if err != nil { + t.Fatal(err) + } + if settings.DefaultTheme != "forgejo-auto" || len(settings.AllowedReactions) != 2 { + t.Fatalf("unexpected ui settings: %+v", settings) + } +} + func TestMiscService_ListLicenses_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet {