mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-07-22 16:00:03 +02:00
Compare commits
67 commits
4e8e3fafe7
...
702896a512
Author | SHA1 | Date | |
---|---|---|---|
![]() |
702896a512 | ||
![]() |
0b74ecebe0 | ||
![]() |
dc6626453a | ||
![]() |
74f7250259 | ||
![]() |
316073a925 | ||
![]() |
a8d8a4c106 | ||
![]() |
51b42e3a84 | ||
![]() |
049899b56b | ||
![]() |
2c01097315 | ||
![]() |
b332d1c2e4 | ||
![]() |
7c06db89e3 | ||
![]() |
7cd313951a | ||
![]() |
3f1ed6dde4 | ||
![]() |
86a13589fa | ||
![]() |
ddc9240a14 | ||
![]() |
3c7e3ec9e2 | ||
![]() |
ba42ebf1ae | ||
![]() |
8ac572682b | ||
![]() |
13b560c191 | ||
![]() |
24d6972f6b | ||
![]() |
f324ee73c5 | ||
![]() |
48035bbd4e | ||
![]() |
32e8610b20 | ||
![]() |
11934670ec | ||
![]() |
0636b3087f | ||
![]() |
34b77270e8 | ||
![]() |
f8d6a61157 | ||
![]() |
eb8ed7e5e9 | ||
![]() |
cee2aae4ca | ||
![]() |
c69e8cde7a | ||
![]() |
63236ed693 | ||
![]() |
1d310e6df5 | ||
![]() |
da1c0f7f18 | ||
![]() |
f5cbb9604d | ||
![]() |
ff5ef8fe8b | ||
![]() |
466e7bfcb8 | ||
![]() |
288c56f5d3 | ||
![]() |
74981d9e97 | ||
![]() |
212e8ac348 | ||
![]() |
6e239a7f65 | ||
![]() |
5f514a6e4d | ||
![]() |
d8c5083c6f | ||
![]() |
d4873965c8 | ||
![]() |
a789dd76d5 | ||
![]() |
72620db8df | ||
![]() |
b669564f39 | ||
![]() |
aca7e8a9af | ||
![]() |
b580c830e0 | ||
![]() |
4935e6e1a3 | ||
![]() |
bc2e4942fc | ||
![]() |
8cc2086402 | ||
![]() |
c0eeb75322 | ||
![]() |
bcde3aea4f | ||
![]() |
abb95c8c92 | ||
![]() |
0ecd9d9682 | ||
![]() |
1ed750a33a | ||
![]() |
6f501b1fdf | ||
![]() |
7a8ff20bf3 | ||
![]() |
8f28942233 | ||
![]() |
2b5123a90f | ||
![]() |
0730e5481f | ||
![]() |
2f0a993a33 | ||
![]() |
0ecb25fdcb | ||
![]() |
6e58d285c7 | ||
![]() |
6e66380408 | ||
![]() |
76b3f4cd6a | ||
![]() |
1b9ac27578 |
551 changed files with 5386 additions and 2823 deletions
|
@ -27,15 +27,13 @@ forgejo.org/models/db
|
|||
TruncateBeans
|
||||
InTransaction
|
||||
DumpTables
|
||||
GetTableNames
|
||||
|
||||
forgejo.org/models/dbfs
|
||||
file.renameTo
|
||||
Create
|
||||
Rename
|
||||
|
||||
forgejo.org/models/forgefed
|
||||
GetFederationHost
|
||||
|
||||
forgejo.org/models/forgejo/semver
|
||||
GetVersion
|
||||
SetVersionString
|
||||
|
@ -67,7 +65,6 @@ forgejo.org/models/user
|
|||
DeleteUserSetting
|
||||
GetFederatedUser
|
||||
GetFederatedUserByUserID
|
||||
UpdateFederatedUser
|
||||
GetFollowersForUser
|
||||
AddFollower
|
||||
RemoveFollower
|
||||
|
@ -248,6 +245,9 @@ forgejo.org/routers/web/org
|
|||
forgejo.org/services/context
|
||||
GetPrivateContext
|
||||
|
||||
forgejo.org/services/federation
|
||||
Init
|
||||
|
||||
forgejo.org/services/repository
|
||||
IsErrForkAlreadyExist
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "22"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.2.4": {},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.2.5": {},
|
||||
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:41.17.2
|
||||
image: data.forgejo.org/renovate/renovate:41.23.2
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
|
@ -79,6 +79,10 @@ linters:
|
|||
- name: unreachable-code
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
arguments:
|
||||
- []
|
||||
- []
|
||||
- - skip-package-name-checks: true
|
||||
- name: redefines-builtin-id
|
||||
disabled: true
|
||||
staticcheck:
|
||||
|
|
4
Makefile
4
Makefile
|
@ -39,7 +39,7 @@ XGO_VERSION := go-1.21.x
|
|||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.3.0 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
|
@ -47,7 +47,7 @@ GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasour
|
|||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
|
||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.34.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@41.17.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@41.23.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
|
|
@ -17,6 +17,15 @@ import (
|
|||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
type (
|
||||
authService struct {
|
||||
initDB func(ctx context.Context) error
|
||||
createAuthSource func(context.Context, *auth_model.Source) error
|
||||
updateAuthSource func(context.Context, *auth_model.Source) error
|
||||
getAuthSourceByID func(ctx context.Context, id int64) (*auth_model.Source, error)
|
||||
}
|
||||
)
|
||||
|
||||
func microcmdAuthDelete() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "delete",
|
||||
|
@ -60,6 +69,16 @@ func microcmdAuthList() *cli.Command {
|
|||
}
|
||||
}
|
||||
|
||||
// newAuthService creates a service with default functions.
|
||||
func newAuthService() *authService {
|
||||
return &authService{
|
||||
initDB: initDB,
|
||||
createAuthSource: auth_model.CreateSource,
|
||||
updateAuthSource: auth_model.UpdateSource,
|
||||
getAuthSourceByID: auth_model.GetSourceByID,
|
||||
}
|
||||
}
|
||||
|
||||
func runListAuth(ctx context.Context, c *cli.Command) error {
|
||||
ctx, cancel := installSignals(ctx)
|
||||
defer cancel()
|
||||
|
|
|
@ -14,15 +14,6 @@ import (
|
|||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
type (
|
||||
authService struct {
|
||||
initDB func(ctx context.Context) error
|
||||
createAuthSource func(context.Context, *auth.Source) error
|
||||
updateAuthSource func(context.Context, *auth.Source) error
|
||||
getAuthSourceByID func(ctx context.Context, id int64) (*auth.Source, error)
|
||||
}
|
||||
)
|
||||
|
||||
func commonLdapCLIFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
|
@ -184,16 +175,6 @@ func microcmdAuthUpdateLdapSimpleAuth() *cli.Command {
|
|||
}
|
||||
}
|
||||
|
||||
// newAuthService creates a service with default functions.
|
||||
func newAuthService() *authService {
|
||||
return &authService{
|
||||
initDB: initDB,
|
||||
createAuthSource: auth.CreateSource,
|
||||
updateAuthSource: auth.UpdateSource,
|
||||
getAuthSourceByID: auth.GetSourceByID,
|
||||
}
|
||||
}
|
||||
|
||||
// parseAuthSource assigns values on authSource according to command line flags.
|
||||
func parseAuthSource(c *cli.Command, authSource *auth.Source) {
|
||||
if c.IsSet("name") {
|
||||
|
|
|
@ -86,6 +86,11 @@ func oauthCLIFlags() []cli.Flag {
|
|||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "attribute-ssh-public-key",
|
||||
Value: "",
|
||||
Usage: "Claim name providing SSH public keys for this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
|
@ -127,7 +132,7 @@ func microcmdAuthAddOauth() *cli.Command {
|
|||
return &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Action: newAuthService().addOauth,
|
||||
Flags: oauthCLIFlags(),
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +141,7 @@ func microcmdAuthUpdateOauth() *cli.Command {
|
|||
return &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Action: newAuthService().updateOauth,
|
||||
Flags: append(oauthCLIFlags()[:1], append([]cli.Flag{idFlag()}, oauthCLIFlags()[1:]...)...),
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +168,7 @@ func parseOAuth2Config(_ context.Context, c *cli.Command) *oauth2.Source {
|
|||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
AttributeSSHPublicKey: c.String("attribute-ssh-public-key"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
GroupClaimName: c.String("group-claim-name"),
|
||||
|
@ -173,11 +179,11 @@ func parseOAuth2Config(_ context.Context, c *cli.Command) *oauth2.Source {
|
|||
}
|
||||
}
|
||||
|
||||
func runAddOauth(ctx context.Context, c *cli.Command) error {
|
||||
func (a *authService) addOauth(ctx context.Context, c *cli.Command) error {
|
||||
ctx, cancel := installSignals(ctx)
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -189,7 +195,7 @@ func runAddOauth(ctx context.Context, c *cli.Command) error {
|
|||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(ctx, &auth_model.Source{
|
||||
return a.createAuthSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
|
@ -197,7 +203,7 @@ func runAddOauth(ctx context.Context, c *cli.Command) error {
|
|||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(ctx context.Context, c *cli.Command) error {
|
||||
func (a *authService) updateOauth(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
@ -205,11 +211,11 @@ func runUpdateOauth(ctx context.Context, c *cli.Command) error {
|
|||
ctx, cancel := installSignals(ctx)
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
source, err := a.getAuthSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -244,6 +250,10 @@ func runUpdateOauth(ctx context.Context, c *cli.Command) error {
|
|||
oAuth2Config.Scopes = c.StringSlice("scopes")
|
||||
}
|
||||
|
||||
if c.IsSet("attribute-ssh-public-key") {
|
||||
oAuth2Config.AttributeSSHPublicKey = c.String("attribute-ssh-public-key")
|
||||
}
|
||||
|
||||
if c.IsSet("required-claim-name") {
|
||||
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
|
||||
}
|
||||
|
@ -300,5 +310,5 @@ func runUpdateOauth(ctx context.Context, c *cli.Command) error {
|
|||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(ctx, source)
|
||||
return a.updateAuthSource(ctx, source)
|
||||
}
|
||||
|
|
704
cmd/admin_auth_oauth_test.go
Normal file
704
cmd/admin_auth_oauth_test.go
Normal file
|
@ -0,0 +1,704 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"forgejo.org/models/auth"
|
||||
"forgejo.org/modules/test"
|
||||
"forgejo.org/services/auth/source/oauth2"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestAddOauth(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
args []string
|
||||
source *auth.Source
|
||||
errMsg string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source full",
|
||||
"--provider", "openidConnect",
|
||||
"--key", "client id",
|
||||
"--secret", "client secret",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
"--use-custom-urls", "",
|
||||
"--custom-tenant-id", "tenant id",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
"--icon-url", "https://example.com/icon.svg",
|
||||
"--skip-local-2fa",
|
||||
"--scopes", "address",
|
||||
"--scopes", "email",
|
||||
"--scopes", "phone",
|
||||
"--scopes", "profile",
|
||||
"--attribute-ssh-public-key", "ssh_public_key",
|
||||
"--required-claim-name", "can_access",
|
||||
"--required-claim-value", "yes",
|
||||
"--group-claim-name", "groups",
|
||||
"--admin-group", "admin",
|
||||
"--restricted-group", "restricted",
|
||||
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
"--group-team-map-removal",
|
||||
},
|
||||
source: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source full",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
ClientID: "client id",
|
||||
ClientSecret: "client secret",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
AuthURL: "https://example.com/auth",
|
||||
TokenURL: "https://example.com/token",
|
||||
ProfileURL: "https://example.com/profile",
|
||||
EmailURL: "https://example.com/email",
|
||||
Tenant: "tenant id",
|
||||
},
|
||||
IconURL: "https://example.com/icon.svg",
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
AttributeSSHPublicKey: "ssh_public_key",
|
||||
RequiredClaimName: "can_access",
|
||||
RequiredClaimValue: "yes",
|
||||
GroupClaimName: "groups",
|
||||
AdminGroup: "admin",
|
||||
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
GroupTeamMapRemoval: true,
|
||||
RestrictedGroup: "restricted",
|
||||
SkipLocalTwoFA: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source min",
|
||||
"--provider", "openidConnect",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
},
|
||||
source: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source min",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
Scopes: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 2
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||||
"--custom-tenant-id", "tenant id",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
},
|
||||
source: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Scopes: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||||
"--provider", "openidConnect",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
"--scopes", "address",
|
||||
"--scopes", "email",
|
||||
"--scopes", "phone",
|
||||
"--scopes", "profile",
|
||||
},
|
||||
source: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 4
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||||
"--provider", "openidConnect",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
"--scopes", "address,email,phone,profile",
|
||||
},
|
||||
source: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 5
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source",
|
||||
"--provider", "openidConnect",
|
||||
},
|
||||
errMsg: "invalid Auto Discovery URL: (this must be a valid URL starting with http:// or https://)",
|
||||
},
|
||||
// case 6
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--name", "oauth2 (via openidConnect) source",
|
||||
"--provider", "openidConnect",
|
||||
"--auto-discover-url", "example.com",
|
||||
},
|
||||
errMsg: "invalid Auto Discovery URL: example.com (this must be a valid URL starting with http:// or https://)",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
// Mock functions.
|
||||
var createdAuthSource *auth.Source
|
||||
service := &authService{
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
createdAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "should not call updateAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
assert.FailNow(t, "should not call getAuthSourceByID", "case: %d", n)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.Command{}
|
||||
app.Flags = microcmdAuthAddOauth().Flags
|
||||
app.Action = service.addOauth
|
||||
|
||||
// Run it
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
require.NoError(t, err, "case %d: should have no errors", n)
|
||||
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOauth(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
args []string
|
||||
id int64
|
||||
existingAuthSource *auth.Source
|
||||
authSource *auth.Source
|
||||
errMsg string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "23",
|
||||
"--name", "oauth2 (via openidConnect) source full",
|
||||
"--provider", "openidConnect",
|
||||
"--key", "client id",
|
||||
"--secret", "client secret",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
"--use-custom-urls", "",
|
||||
"--custom-tenant-id", "tenant id",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
"--icon-url", "https://example.com/icon.svg",
|
||||
"--skip-local-2fa",
|
||||
"--scopes", "address",
|
||||
"--scopes", "email",
|
||||
"--scopes", "phone",
|
||||
"--scopes", "profile",
|
||||
"--attribute-ssh-public-key", "ssh_public_key",
|
||||
"--required-claim-name", "can_access",
|
||||
"--required-claim-value", "yes",
|
||||
"--group-claim-name", "groups",
|
||||
"--admin-group", "admin",
|
||||
"--restricted-group", "restricted",
|
||||
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
"--group-team-map-removal",
|
||||
},
|
||||
id: 23,
|
||||
existingAuthSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{},
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source full",
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
ClientID: "client id",
|
||||
ClientSecret: "client secret",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
AuthURL: "https://example.com/auth",
|
||||
TokenURL: "https://example.com/token",
|
||||
ProfileURL: "https://example.com/profile",
|
||||
EmailURL: "https://example.com/email",
|
||||
Tenant: "tenant id",
|
||||
},
|
||||
IconURL: "https://example.com/icon.svg",
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
AttributeSSHPublicKey: "ssh_public_key",
|
||||
RequiredClaimName: "can_access",
|
||||
RequiredClaimValue: "yes",
|
||||
GroupClaimName: "groups",
|
||||
AdminGroup: "admin",
|
||||
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
GroupTeamMapRemoval: true,
|
||||
RestrictedGroup: "restricted",
|
||||
// `--skip-local-2fa` is currently ignored.
|
||||
// SkipLocalTwoFA: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 2
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--name", "oauth2 (via openidConnect) source full",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source full",
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--provider", "openidConnect",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "openidConnect",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 4
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--key", "client id",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
ClientID: "client id",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 5
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--secret", "client secret",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
ClientSecret: "client secret",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 6
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 7
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--use-custom-urls", "",
|
||||
"--custom-tenant-id", "tenant id",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
AuthURL: "https://example.com/auth",
|
||||
TokenURL: "https://example.com/token",
|
||||
ProfileURL: "https://example.com/profile",
|
||||
EmailURL: "https://example.com/email",
|
||||
Tenant: "tenant id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 8
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--name", "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||||
"--custom-tenant-id", "tenant id",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 9
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--icon-url", "https://example.com/icon.svg",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
IconURL: "https://example.com/icon.svg",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 10
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--name", "oauth2 (via openidConnect) source `--skip-local-2fa` is currently ignored",
|
||||
"--skip-local-2fa",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--skip-local-2fa` is currently ignored",
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
// `--skip-local-2fa` is currently ignored.
|
||||
// SkipLocalTwoFA: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 11
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--name", "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||||
"--scopes", "address",
|
||||
"--scopes", "email",
|
||||
"--scopes", "phone",
|
||||
"--scopes", "profile",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 12
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--name", "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||||
"--scopes", "address,email,phone,profile",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Name: "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
Scopes: []string{"address", "email", "phone", "profile"},
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 13
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--attribute-ssh-public-key", "ssh_public_key",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
AttributeSSHPublicKey: "ssh_public_key",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 14
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--required-claim-name", "can_access",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
RequiredClaimName: "can_access",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 15
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--required-claim-value", "yes",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
RequiredClaimValue: "yes",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 16
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--group-claim-name", "groups",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
GroupClaimName: "groups",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 17
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--admin-group", "admin",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
AdminGroup: "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 18
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--restricted-group", "restricted",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
RestrictedGroup: "restricted",
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 19
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 20
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "1",
|
||||
"--group-team-map-removal",
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
GroupTeamMapRemoval: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 21
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
"--id", "23",
|
||||
"--group-team-map-removal=false",
|
||||
},
|
||||
id: 23,
|
||||
existingAuthSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
GroupTeamMapRemoval: true,
|
||||
},
|
||||
},
|
||||
authSource: &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
GroupTeamMapRemoval: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
// case 22
|
||||
{
|
||||
args: []string{
|
||||
"oauth-test",
|
||||
},
|
||||
errMsg: "--id flag is missing",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
// Mock functions.
|
||||
var updatedAuthSource *auth.Source
|
||||
service := &authService{
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "should not call createAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
updatedAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
if c.id != 0 {
|
||||
assert.Equal(t, c.id, id, "case %d: wrong id", n)
|
||||
}
|
||||
if c.existingAuthSource != nil {
|
||||
return c.existingAuthSource, nil
|
||||
}
|
||||
return &auth.Source{
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &oauth2.Source{},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.Command{}
|
||||
app.Flags = microcmdAuthUpdateOauth().Flags
|
||||
app.Action = service.updateOauth
|
||||
|
||||
// Run it
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
require.NoError(t, err, "case %d: should have no errors", n)
|
||||
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,6 +44,11 @@ func defaultLoggingFlags() []cli.Flag {
|
|||
Aliases: []string{"e"},
|
||||
Usage: "Matching expression for the logger",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "exclusion",
|
||||
Aliases: []string{"x"},
|
||||
Usage: "Exclusion for the logger",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "prefix",
|
||||
Aliases: []string{"p"},
|
||||
|
@ -286,6 +291,9 @@ func commonAddLogger(ctx context.Context, c *cli.Command, mode string, vals map[
|
|||
if len(c.String("expression")) > 0 {
|
||||
vals["expression"] = c.String("expression")
|
||||
}
|
||||
if len(c.String("exclusion")) > 0 {
|
||||
vals["exclusion"] = c.String("exclusion")
|
||||
}
|
||||
if len(c.String("prefix")) > 0 {
|
||||
vals["prefix"] = c.String("prefix")
|
||||
}
|
||||
|
|
|
@ -631,6 +631,7 @@ LEVEL = Info
|
|||
;LEVEL=
|
||||
;FLAGS = stdflags or journald
|
||||
;EXPRESSION =
|
||||
;EXCLUSION =
|
||||
;PREFIX =
|
||||
;COLORIZE = false
|
||||
;;
|
||||
|
@ -1767,6 +1768,9 @@ LEVEL = Info
|
|||
;; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
;PASSWD =
|
||||
;;
|
||||
;; Alternative location to specify mailer password. You cannot specify both this and PASSWD, and must pick one
|
||||
;PASSWD_URI = file:/etc/forgejo/mailer_passwd
|
||||
;;
|
||||
;; Send mails only in plain text, without HTML alternative
|
||||
;SEND_AS_PLAIN_TEXT = false
|
||||
;;
|
||||
|
@ -1819,6 +1823,9 @@ LEVEL = Info
|
|||
;; Password of the receiving account
|
||||
;PASSWORD =
|
||||
;;
|
||||
;; Alternative location to specify password of the receiving account. You cannot specify both this and PASSWORD, and must pick one
|
||||
;PASSWORD_URI = file:/etc/forgejo/email_incoming_password
|
||||
;;
|
||||
;; Whether the IMAP server uses TLS.
|
||||
;USE_TLS = false
|
||||
;;
|
||||
|
|
24
go.mod
24
go.mod
|
@ -2,7 +2,7 @@ module forgejo.org
|
|||
|
||||
go 1.24
|
||||
|
||||
toolchain go1.24.4
|
||||
toolchain go1.24.5
|
||||
|
||||
require (
|
||||
code.forgejo.org/f3/gof3/v3 v3.11.0
|
||||
|
@ -24,7 +24,7 @@ require (
|
|||
github.com/ProtonMail/go-crypto v1.3.0
|
||||
github.com/PuerkitoBio/goquery v1.10.3
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||
github.com/alecthomas/chroma/v2 v2.18.0
|
||||
github.com/alecthomas/chroma/v2 v2.19.0
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.5.2
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
||||
|
@ -42,21 +42,21 @@ require (
|
|||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||
github.com/go-chi/chi/v5 v5.2.2
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/cors v1.2.2
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-enry/go-enry/v2 v2.9.2
|
||||
github.com/go-git/go-git/v5 v5.13.2
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/go-openapi/spec v0.21.0
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
github.com/go-webauthn/webauthn v0.13.0
|
||||
github.com/go-webauthn/webauthn v0.13.1
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/google/go-github/v64 v64.0.0
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.2.0
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
|
@ -99,13 +99,13 @@ require (
|
|||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
gitlab.com/gitlab-org/api/client-go v0.130.1
|
||||
go.uber.org/mock v0.5.2
|
||||
golang.org/x/crypto v0.39.0
|
||||
golang.org/x/crypto v0.40.0
|
||||
golang.org/x/image v0.27.0
|
||||
golang.org/x/net v0.41.0
|
||||
golang.org/x/net v0.42.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.15.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/text v0.26.0
|
||||
golang.org/x/sync v0.16.0
|
||||
golang.org/x/sys v0.34.0
|
||||
golang.org/x/text v0.27.0
|
||||
google.golang.org/protobuf v1.36.4
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
|
@ -170,7 +170,7 @@ require (
|
|||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-webauthn/x v0.1.21 // indirect
|
||||
github.com/go-webauthn/x v0.1.22 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
|
@ -244,7 +244,7 @@ require (
|
|||
|
||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.28.0
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.29.0
|
||||
|
||||
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
||||
|
||||
|
|
48
go.sum
48
go.sum
|
@ -4,8 +4,8 @@ code.forgejo.org/f3/gof3/v3 v3.11.0 h1:f/xToKwqTgxG6PYxvewywjDQyCcyHEEJ6sZqUitFs
|
|||
code.forgejo.org/f3/gof3/v3 v3.11.0/go.mod h1:4FaRUNSQGBiD1M0DuB0yNv+Z2wMtlOeckgygHSSq4KQ=
|
||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
|
||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
|
||||
code.forgejo.org/forgejo/act v1.28.0 h1:96njNC7C1YNyjWq5OWvLZMF/nw0PMthzIA8Nwbnn7jo=
|
||||
code.forgejo.org/forgejo/act v1.28.0/go.mod h1:dFuiwAmD5vyrzecysHB2kL/GM3wRpoVPl+WdbCTC8Bs=
|
||||
code.forgejo.org/forgejo/act v1.29.0 h1:CPiI0LRPU0f6gUdQj1ZVax0ySc8CfegY4hiRsymdZU0=
|
||||
code.forgejo.org/forgejo/act v1.29.0/go.mod h1:RPqtuaI2FkC1SVOaYCRODo5jIfoMTBVgEOOP3Sdiuh4=
|
||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
|
||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
code.forgejo.org/forgejo/go-rpmutils v1.0.0 h1:RZGGeKt70p/WaIEL97pyT6uiiEIoN8/aLmS5Z6WmX0M=
|
||||
|
@ -62,8 +62,8 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2/go.mod h1:JitQWJ8JuV4Y
|
|||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.18.0 h1:6h53Q4hW83SuF+jcsp7CVhLsMozzvQvO8HBbKQW+gn4=
|
||||
github.com/alecthomas/chroma/v2 v2.18.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
|
||||
github.com/alecthomas/chroma/v2 v2.19.0 h1:Im+SLRgT8maArxv81mULDWN8oKxkzboH07CHesxElq4=
|
||||
github.com/alecthomas/chroma/v2 v2.19.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
|
@ -215,8 +215,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro
|
|||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
|
||||
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
|
||||
github.com/go-enry/go-enry/v2 v2.9.2 h1:giOQAtCgBX08kosrX818DCQJTCNtKwoPBGu0qb6nKTY=
|
||||
|
@ -250,10 +250,10 @@ github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI6
|
|||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-webauthn/webauthn v0.13.0 h1:cJIL1/1l+22UekVhipziAaSgESJxokYkowUqAIsWs0Y=
|
||||
github.com/go-webauthn/webauthn v0.13.0/go.mod h1:Oy9o2o79dbLKRPZWWgRIOdtBGAhKnDIaBp2PFkICRHs=
|
||||
github.com/go-webauthn/x v0.1.21 h1:nFbckQxudvHEJn2uy1VEi713MeSpApoAv9eRqsb9AdQ=
|
||||
github.com/go-webauthn/x v0.1.21/go.mod h1:sEYohtg1zL4An1TXIUIQ5csdmoO+WO0R4R2pGKaHYKA=
|
||||
github.com/go-webauthn/webauthn v0.13.1 h1:Q3/GLXsckVJUPE+BGR6ex26yRIiZ/X2ITaMeSkOftuc=
|
||||
github.com/go-webauthn/webauthn v0.13.1/go.mod h1:HeaBromTjgMg1sHZOzyjEiqcrk4Og7mxafDTWDepaXI=
|
||||
github.com/go-webauthn/x v0.1.22 h1:rHilV/rYXawarI0uA3uZ5nhLb30Ex8RgbVAsOSt/57o=
|
||||
github.com/go-webauthn/x v0.1.22/go.mod h1:+iV9BF4OsvLYzETdc0lmQO2webTos10oH6QydSoWxDM=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
|
@ -307,8 +307,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
|
@ -585,8 +585,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
|||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
|
@ -614,8 +614,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -627,8 +627,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -654,8 +654,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -665,8 +665,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -677,8 +677,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
@ -284,16 +284,10 @@ func GetLatestRun(ctx context.Context, repoID int64) (*ActionRun, error) {
|
|||
return &run, nil
|
||||
}
|
||||
|
||||
// GetRunBefore returns the last run that completed a given timestamp (not inclusive).
|
||||
func GetRunBefore(ctx context.Context, repoID int64, timestamp timeutil.TimeStamp) (*ActionRun, error) {
|
||||
var run ActionRun
|
||||
has, err := db.GetEngine(ctx).Where("repo_id=? AND stopped IS NOT NULL AND stopped<?", repoID, timestamp).OrderBy("stopped DESC").Limit(1).Get(&run)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, fmt.Errorf("run before: %w", util.ErrNotExist)
|
||||
}
|
||||
return &run, nil
|
||||
func GetRunBefore(ctx context.Context, _ *ActionRun) (*ActionRun, error) {
|
||||
// TODO return the most recent run related to the run given in argument
|
||||
// see https://codeberg.org/forgejo/user-research/issues/63 for context
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func GetLatestRunForBranchAndWorkflow(ctx context.Context, repoID int64, branch, workflowFile, event string) (*ActionRun, error) {
|
||||
|
|
|
@ -5,92 +5,7 @@ package actions
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/models/unittest"
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetRunBefore(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// this repo is part of the test database requiring loading "repository.yml" in main_test.go
|
||||
var repoID int64 = 1
|
||||
|
||||
workflowID := "test_workflow"
|
||||
|
||||
// third completed run
|
||||
time1, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
|
||||
require.NoError(t, err)
|
||||
timeutil.MockSet(time1)
|
||||
run1 := ActionRun{
|
||||
ID: 1,
|
||||
Index: 1,
|
||||
RepoID: repoID,
|
||||
Stopped: timeutil.TimeStampNow(),
|
||||
WorkflowID: workflowID,
|
||||
}
|
||||
|
||||
// fourth completed run
|
||||
time2, err := time.Parse(time.RFC3339, "2024-08-31T15:47:55+08:00")
|
||||
require.NoError(t, err)
|
||||
timeutil.MockSet(time2)
|
||||
run2 := ActionRun{
|
||||
ID: 2,
|
||||
Index: 2,
|
||||
RepoID: repoID,
|
||||
Stopped: timeutil.TimeStampNow(),
|
||||
WorkflowID: workflowID,
|
||||
}
|
||||
|
||||
// second completed run
|
||||
time3, err := time.Parse(time.RFC3339, "2024-07-31T15:47:54+08:00")
|
||||
require.NoError(t, err)
|
||||
timeutil.MockSet(time3)
|
||||
run3 := ActionRun{
|
||||
ID: 3,
|
||||
Index: 3,
|
||||
RepoID: repoID,
|
||||
Stopped: timeutil.TimeStampNow(),
|
||||
WorkflowID: workflowID,
|
||||
}
|
||||
|
||||
// first completed run
|
||||
time4, err := time.Parse(time.RFC3339, "2024-06-30T15:47:54+08:00")
|
||||
require.NoError(t, err)
|
||||
timeutil.MockSet(time4)
|
||||
run4 := ActionRun{
|
||||
ID: 4,
|
||||
Index: 4,
|
||||
RepoID: repoID,
|
||||
Stopped: timeutil.TimeStampNow(),
|
||||
WorkflowID: workflowID,
|
||||
}
|
||||
require.NoError(t, db.Insert(db.DefaultContext, &run1))
|
||||
runBefore, err := GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
|
||||
// there is no run before run1
|
||||
require.Error(t, err)
|
||||
require.Nil(t, runBefore)
|
||||
|
||||
// now there is only run3 before run1
|
||||
require.NoError(t, db.Insert(db.DefaultContext, &run3))
|
||||
runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, run3.ID, runBefore.ID)
|
||||
|
||||
// there still is only run3 before run1
|
||||
require.NoError(t, db.Insert(db.DefaultContext, &run2))
|
||||
runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, run3.ID, runBefore.ID)
|
||||
|
||||
// run4 is further away from run1
|
||||
require.NoError(t, db.Insert(db.DefaultContext, &run4))
|
||||
runBefore, err = GetRunBefore(db.DefaultContext, repoID, run1.Stopped)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, run3.ID, runBefore.ID)
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ func TestMain(m *testing.M) {
|
|||
"gpg_key.yml",
|
||||
"public_key.yml",
|
||||
"TestParseCommitWithSSHSignature/public_key.yml",
|
||||
"deploy_key.yml",
|
||||
"gpg_key_import.yml",
|
||||
"user.yml",
|
||||
"email_address.yml",
|
||||
},
|
||||
|
|
|
@ -141,7 +141,7 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) {
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
return newContext(DefaultContext, sess, true), sess, nil
|
||||
return newContext(parentCtx, sess, true), sess, nil
|
||||
}
|
||||
|
||||
// WithTx represents executing database operations on a transaction, if the transaction exist,
|
||||
|
|
|
@ -84,4 +84,16 @@ func TestTxContext(t *testing.T) {
|
|||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
t.Run("Reuses parent context", func(t *testing.T) {
|
||||
type unique struct{}
|
||||
|
||||
ctx := context.WithValue(db.DefaultContext, unique{}, "yes!")
|
||||
assert.False(t, db.InTransaction(ctx))
|
||||
|
||||
require.NoError(t, db.WithTx(ctx, func(ctx context.Context) error {
|
||||
assert.Equal(t, "yes!", ctx.Value(unique{}))
|
||||
return nil
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"forgejo.org/modules/container"
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/setting"
|
||||
|
||||
|
@ -438,3 +439,12 @@ func GetMasterEngine(x Engine) (*xorm.Engine, error) {
|
|||
|
||||
return engine, nil
|
||||
}
|
||||
|
||||
// GetTableNames returns the table name of all registered models.
|
||||
func GetTableNames() container.Set[string] {
|
||||
names := make(container.Set[string])
|
||||
for _, table := range tables {
|
||||
names.Add(x.TableName(table))
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
|
40
models/db/table_names_test.go
Normal file
40
models/db/table_names_test.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"forgejo.org/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetTableNames(t *testing.T) {
|
||||
t.Run("Simple", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&tables, []any{new(GPGKey)})()
|
||||
|
||||
assert.Equal(t, []string{"gpg_key"}, GetTableNames().Values())
|
||||
})
|
||||
|
||||
t.Run("Multiple tables", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&tables, []any{new(GPGKey), new(User), new(BlockedUser)})()
|
||||
|
||||
tableNames := GetTableNames().Values()
|
||||
slices.Sort(tableNames)
|
||||
|
||||
assert.Equal(t, []string{"forgejo_blocked_user", "gpg_key", "user"}, tableNames)
|
||||
})
|
||||
}
|
||||
|
||||
type GPGKey struct{}
|
||||
|
||||
type User struct{}
|
||||
|
||||
type BlockedUser struct{}
|
||||
|
||||
func (*BlockedUser) TableName() string {
|
||||
return "forgejo_blocked_user"
|
||||
}
|
7
models/fixtures/TestActivateUserEmail/email_address.yml
Normal file
7
models/fixtures/TestActivateUserEmail/email_address.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
-
|
||||
id: 1001
|
||||
uid: 1001
|
||||
email: AnotherTestUserWithUpperCaseEmail@otto.splvs.net
|
||||
lower_email: anothertestuserwithuppercaseemail@otto.splvs.net
|
||||
is_activated: false
|
||||
is_primary: true
|
12
models/fixtures/TestActivateUserEmail/user.yml
Normal file
12
models/fixtures/TestActivateUserEmail/user.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
-
|
||||
id: 1001
|
||||
lower_name: user1001
|
||||
name: user1001
|
||||
full_name: User That loves Upper Cases
|
||||
email: AnotherTestUserWithUpperCaseEmail@otto.splvs.net
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
avatar: ''
|
||||
avatar_email: anothertestuserwithuppercaseemail@otto.splvs.net
|
||||
login_name: user1
|
||||
created_unix: 1672578000
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -3,6 +3,7 @@
|
|||
repo_id: 1
|
||||
org_id: 0
|
||||
name: label1
|
||||
description: 'First label'
|
||||
color: '#abcdef'
|
||||
exclusive: false
|
||||
num_issues: 2
|
||||
|
@ -107,3 +108,26 @@
|
|||
num_issues: 0
|
||||
num_closed_issues: 0
|
||||
archived_unix: 0
|
||||
|
||||
-
|
||||
id: 11
|
||||
repo_id: 3
|
||||
org_id: 0
|
||||
name: " <script>malicious</script> /'?&"
|
||||
description: "Malicious label ' <script>malicious</script>"
|
||||
color: '#000000'
|
||||
exclusive: true
|
||||
num_issues: 0
|
||||
num_closed_issues: 0
|
||||
archived_unix: 0
|
||||
|
||||
-
|
||||
id: 12
|
||||
repo_id: 3
|
||||
org_id: 0
|
||||
name: 'archived label<>'
|
||||
color: '#000000'
|
||||
exclusive: false
|
||||
num_issues: 0
|
||||
num_closed_issues: 0
|
||||
archived_unix: 2991092130
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1 +0,0 @@
|
|||
[] # empty
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -108,7 +108,9 @@ var migrations = []*Migration{
|
|||
// v33 -> v34
|
||||
NewMigration("Add `notify-email` column to `action_run` table", AddNotifyEmailToActionRun),
|
||||
// v34 -> v35
|
||||
NewMigration("Add index to `stopped` column in `action_run` table", AddIndexToActionRunStopped),
|
||||
NewMigration("Noop because of https://codeberg.org/forgejo/forgejo/issues/8373", NoopAddIndexToActionRunStopped),
|
||||
// v35 -> v36
|
||||
NewMigration("Fix wiki unit default permission", FixWikiUnitDefaultPermission),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"forgejo.org/models/migrations/base"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_v1_20 //nolint:revive
|
||||
package forgejo_v1_20
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_v1_20 //nolint:revive
|
||||
package forgejo_v1_20
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_v1_20 //nolint:revive
|
||||
package forgejo_v1_20
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
package v1_22
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddIndexToActionRunStopped(x *xorm.Engine) error {
|
||||
type ActionRun struct {
|
||||
ID int64
|
||||
Stopped timeutil.TimeStamp `xorm:"index"`
|
||||
}
|
||||
|
||||
return x.Sync(&ActionRun{})
|
||||
// see https://codeberg.org/forgejo/forgejo/issues/8373
|
||||
func NoopAddIndexToActionRunStopped(x *xorm.Engine) error {
|
||||
return nil
|
||||
}
|
||||
|
|
55
models/forgejo_migrations/v36.go
Normal file
55
models/forgejo_migrations/v36.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func FixWikiUnitDefaultPermission(x *xorm.Engine) error {
|
||||
// Type is Unit's Type
|
||||
type Type int
|
||||
|
||||
// Enumerate all the unit types
|
||||
const (
|
||||
TypeInvalid Type = iota // 0 invalid
|
||||
TypeCode // 1 code
|
||||
TypeIssues // 2 issues
|
||||
TypePullRequests // 3 PRs
|
||||
TypeReleases // 4 Releases
|
||||
TypeWiki // 5 Wiki
|
||||
TypeExternalWiki // 6 ExternalWiki
|
||||
TypeExternalTracker // 7 ExternalTracker
|
||||
TypeProjects // 8 Projects
|
||||
TypePackages // 9 Packages
|
||||
TypeActions // 10 Actions
|
||||
)
|
||||
|
||||
// RepoUnitAccessMode specifies the users access mode to a repo unit
|
||||
type UnitAccessMode int
|
||||
|
||||
const (
|
||||
// UnitAccessModeUnset - no unit mode set
|
||||
UnitAccessModeUnset UnitAccessMode = iota // 0
|
||||
// UnitAccessModeNone no access
|
||||
UnitAccessModeNone // 1
|
||||
// UnitAccessModeRead read access
|
||||
UnitAccessModeRead // 2
|
||||
// UnitAccessModeWrite write access
|
||||
UnitAccessModeWrite // 3
|
||||
)
|
||||
_ = UnitAccessModeNone
|
||||
_ = UnitAccessModeWrite
|
||||
|
||||
type RepoUnit struct {
|
||||
DefaultPermissions UnitAccessMode `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
_, err := x.Where("type = ?", TypeWiki).
|
||||
Where("default_permissions = ?", UnitAccessModeRead).
|
||||
Cols("default_permissions").
|
||||
Update(RepoUnit{
|
||||
DefaultPermissions: UnitAccessModeUnset,
|
||||
})
|
||||
return err
|
||||
}
|
|
@ -95,7 +95,8 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu
|
|||
t.Logf("initializing fixtures from: %s", fixturesDir)
|
||||
if err := unittest.InitFixtures(
|
||||
unittest.FixturesOptions{
|
||||
Dir: fixturesDir,
|
||||
Dir: fixturesDir,
|
||||
SkipCleanRegistedModels: true,
|
||||
}, x); err != nil {
|
||||
t.Errorf("error whilst initializing fixtures from %s: %v", fixturesDir, err)
|
||||
return x, deferFn
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"xorm.io/builder"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_10 //nolint
|
||||
package v1_10
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_11 //nolint
|
||||
package v1_11
|
||||
|
||||
import (
|
||||
"forgejo.org/models/migrations/base"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_11 //nolint
|
||||
package v1_11
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_11 //nolint
|
||||
package v1_11
|
||||
|
||||
import (
|
||||
"forgejo.org/models/migrations/base"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue