mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-19 00:01:16 -04:00
Compare commits
10 Commits
5ef5a0ade6
...
15fa0383fb
Author | SHA1 | Date | |
---|---|---|---|
|
15fa0383fb | ||
|
98f02203f9 | ||
|
673cf6af76 | ||
|
e74a3b18af | ||
|
e5e1d842c0 | ||
|
70f8d10fc5 | ||
|
5600504eed | ||
|
9e446dbf04 | ||
|
3b2da7e4ae | ||
|
ee27b94b2c |
@ -18,6 +18,7 @@ plugins:
|
||||
- eslint-plugin-regexp
|
||||
- eslint-plugin-sonarjs
|
||||
- eslint-plugin-unicorn
|
||||
- eslint-plugin-vitest-globals
|
||||
- eslint-plugin-wc
|
||||
|
||||
env:
|
||||
@ -45,6 +46,9 @@ overrides:
|
||||
- files: ["*.config.*"]
|
||||
rules:
|
||||
import/no-unused-modules: [0]
|
||||
- files: ["**/*.test.*", "web_src/js/test/setup.js"]
|
||||
env:
|
||||
vitest-globals/env: true
|
||||
- files: ["web_src/js/modules/fetch.js", "web_src/js/standalone/**/*"]
|
||||
rules:
|
||||
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement, SequenceExpression]
|
||||
|
617
cmd/admin.go
617
cmd/admin.go
@ -6,26 +6,13 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
auth_service "code.gitea.io/gitea/services/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@ -59,28 +46,16 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
microcmdRegenHooks = &cli.Command{
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
}
|
||||
|
||||
microcmdRegenKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
}
|
||||
|
||||
subcmdAuth = &cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Modify external auth providers",
|
||||
Subcommands: []*cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
cmdAuthAddLdapBindDn,
|
||||
cmdAuthUpdateLdapBindDn,
|
||||
cmdAuthAddLdapSimpleAuth,
|
||||
cmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthAddLdapBindDn,
|
||||
microcmdAuthUpdateLdapBindDn,
|
||||
microcmdAuthAddLdapSimpleAuth,
|
||||
microcmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthAddSMTP,
|
||||
microcmdAuthUpdateSMTP,
|
||||
microcmdAuthList,
|
||||
@ -88,170 +63,6 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthList = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "min-width",
|
||||
Usage: "Minimal cell width including any padding for the formatted table",
|
||||
Value: 0,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "tab-width",
|
||||
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
||||
Value: 8,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "padding",
|
||||
Usage: "padding added to a cell before computing its width",
|
||||
Value: 1,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pad-char",
|
||||
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
||||
Value: "\t",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "vertical-bars",
|
||||
Usage: "Set to true to print vertical bars between columns",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
idFlag = &cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}
|
||||
|
||||
microcmdAuthDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-tenant-id",
|
||||
Value: "",
|
||||
Usage: "Use custom Tenant ID for OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "icon-url",
|
||||
Value: "",
|
||||
Usage: "Custom icon URL for OAuth2 login source",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "scopes",
|
||||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-value",
|
||||
Value: "",
|
||||
Usage: "Claim value that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name providing group names for this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "admin-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for administrator users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "restricted-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for restricted users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-team-map",
|
||||
Value: "",
|
||||
Usage: "JSON mapping between groups and org teams",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "group-team-map-removal",
|
||||
Usage: "Activate automatic team membership removal depending on groups",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
|
||||
subcmdSendMail = &cli.Command{
|
||||
Name: "sendmail",
|
||||
Usage: "Send a message to all users",
|
||||
@ -275,75 +86,9 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
smtpCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth-type",
|
||||
Value: "PLAIN",
|
||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "",
|
||||
Usage: "SMTP Host",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "SMTP Port",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
Value: "",
|
||||
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
Value: "",
|
||||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
Usage: "This Authentication Source is Activated.",
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddSMTP = &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: runAddSMTP,
|
||||
Flags: smtpCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateSMTP = &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: runUpdateSMTP,
|
||||
Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
|
||||
idFlag = &cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}
|
||||
)
|
||||
|
||||
@ -420,351 +165,3 @@ func getReleaseCount(ctx context.Context, id int64) (int64, error) {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func runRegenerateHooks(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||
}
|
||||
|
||||
func runRegenerateKeys(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return asymkey_model.RewriteAllPublicKeys(ctx)
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
Tenant: c.String("custom-tenant-id"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &oauth2.Source{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
GroupClaimName: c.String("group-claim-name"),
|
||||
AdminGroup: c.String("admin-group"),
|
||||
RestrictedGroup: c.String("restricted-group"),
|
||||
GroupTeamMap: c.String("group-team-map"),
|
||||
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := parseOAuth2Config(c)
|
||||
if config.Provider == "openidConnect" {
|
||||
discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
|
||||
if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
|
||||
return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
|
||||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.Cfg.(*oauth2.Source)
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
if c.IsSet("icon-url") {
|
||||
oAuth2Config.IconURL = c.String("icon-url")
|
||||
}
|
||||
|
||||
if c.IsSet("scopes") {
|
||||
oAuth2Config.Scopes = c.StringSlice("scopes")
|
||||
}
|
||||
|
||||
if c.IsSet("required-claim-name") {
|
||||
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
|
||||
}
|
||||
if c.IsSet("required-claim-value") {
|
||||
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
|
||||
}
|
||||
|
||||
if c.IsSet("group-claim-name") {
|
||||
oAuth2Config.GroupClaimName = c.String("group-claim-name")
|
||||
}
|
||||
if c.IsSet("admin-group") {
|
||||
oAuth2Config.AdminGroup = c.String("admin-group")
|
||||
}
|
||||
if c.IsSet("restricted-group") {
|
||||
oAuth2Config.RestrictedGroup = c.String("restricted-group")
|
||||
}
|
||||
if c.IsSet("group-team-map") {
|
||||
oAuth2Config.GroupTeamMap = c.String("group-team-map")
|
||||
}
|
||||
if c.IsSet("group-team-map-removal") {
|
||||
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
customURLMapping := &oauth2.CustomURLMapping{}
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
customURLMapping.Tenant = oAuth2Config.CustomURLMapping.Tenant
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-tenant-id") {
|
||||
customURLMapping.Tenant = c.String("custom-tenant-id")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
||||
|
||||
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
if c.IsSet("auth-type") {
|
||||
conf.Auth = c.String("auth-type")
|
||||
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
|
||||
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
|
||||
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
|
||||
}
|
||||
conf.Auth = c.String("auth-type")
|
||||
}
|
||||
if c.IsSet("host") {
|
||||
conf.Host = c.String("host")
|
||||
}
|
||||
if c.IsSet("port") {
|
||||
conf.Port = c.Int("port")
|
||||
}
|
||||
if c.IsSet("allowed-domains") {
|
||||
conf.AllowedDomains = c.String("allowed-domains")
|
||||
}
|
||||
if c.IsSet("force-smtps") {
|
||||
conf.ForceSMTPS = c.Bool("force-smtps")
|
||||
}
|
||||
if c.IsSet("skip-verify") {
|
||||
conf.SkipVerify = c.Bool("skip-verify")
|
||||
}
|
||||
if c.IsSet("helo-hostname") {
|
||||
conf.HeloHostname = c.String("helo-hostname")
|
||||
}
|
||||
if c.IsSet("disable-helo") {
|
||||
conf.DisableHelo = c.Bool("disable-helo")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTP(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.IsSet("name") || len(c.String("name")) == 0 {
|
||||
return errors.New("name must be set")
|
||||
}
|
||||
if !c.IsSet("host") || len(c.String("host")) == 0 {
|
||||
return errors.New("host must be set")
|
||||
}
|
||||
if !c.IsSet("port") {
|
||||
return errors.New("port must be set")
|
||||
}
|
||||
active := true
|
||||
if c.IsSet("active") {
|
||||
active = c.Bool("active")
|
||||
}
|
||||
|
||||
var smtpConfig smtp.Source
|
||||
if err := parseSMTPConfig(c, &smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not set default to PLAIN
|
||||
if len(smtpConfig.Auth) == 0 {
|
||||
smtpConfig.Auth = "PLAIN"
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateSMTP(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smtpConfig := source.Cfg.(*smtp.Source)
|
||||
|
||||
if err := parseSMTPConfig(c, smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("active") {
|
||||
source.IsActive = c.Bool("active")
|
||||
}
|
||||
|
||||
source.Cfg = smtpConfig
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authSources, err := auth_model.Sources()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags := tabwriter.AlignRight
|
||||
if c.Bool("vertical-bars") {
|
||||
flags |= tabwriter.Debug
|
||||
}
|
||||
|
||||
padChar := byte('\t')
|
||||
if len(c.String("pad-char")) > 0 {
|
||||
padChar = c.String("pad-char")[0]
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, c.Int("min-width"), c.Int("tab-width"), c.Int("padding"), padChar, flags)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
for _, source := range authSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", source.ID, source.Name, source.Type.String(), source.IsActive)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return auth_service.DeleteSource(source)
|
||||
}
|
||||
|
109
cmd/admin_auth.go
Normal file
109
cmd/admin_auth.go
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
auth_service "code.gitea.io/gitea/services/auth"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
microcmdAuthDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
microcmdAuthList = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "min-width",
|
||||
Usage: "Minimal cell width including any padding for the formatted table",
|
||||
Value: 0,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "tab-width",
|
||||
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
||||
Value: 8,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "padding",
|
||||
Usage: "padding added to a cell before computing its width",
|
||||
Value: 1,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pad-char",
|
||||
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
||||
Value: "\t",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "vertical-bars",
|
||||
Usage: "Set to true to print vertical bars between columns",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authSources, err := auth_model.Sources()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags := tabwriter.AlignRight
|
||||
if c.Bool("vertical-bars") {
|
||||
flags |= tabwriter.Debug
|
||||
}
|
||||
|
||||
padChar := byte('\t')
|
||||
if len(c.String("pad-char")) > 0 {
|
||||
padChar = c.String("pad-char")[0]
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, c.Int("min-width"), c.Int("tab-width"), c.Int("padding"), padChar, flags)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
for _, source := range authSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", source.ID, source.Name, source.Type.String(), source.IsActive)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return auth_service.DeleteSource(source)
|
||||
}
|
@ -132,10 +132,10 @@ var (
|
||||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
||||
&cli.StringFlag{
|
||||
Name: "user-dn",
|
||||
Usage: "The user’s DN.",
|
||||
Usage: "The user's DN.",
|
||||
})
|
||||
|
||||
cmdAuthAddLdapBindDn = &cli.Command{
|
||||
microcmdAuthAddLdapBindDn = &cli.Command{
|
||||
Name: "add-ldap",
|
||||
Usage: "Add new LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@ -144,7 +144,7 @@ var (
|
||||
Flags: ldapBindDnCLIFlags,
|
||||
}
|
||||
|
||||
cmdAuthUpdateLdapBindDn = &cli.Command{
|
||||
microcmdAuthUpdateLdapBindDn = &cli.Command{
|
||||
Name: "update-ldap",
|
||||
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@ -153,7 +153,7 @@ var (
|
||||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
||||
}
|
||||
|
||||
cmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||
microcmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||
Name: "add-ldap-simple",
|
||||
Usage: "Add new LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@ -162,7 +162,7 @@ var (
|
||||
Flags: ldapSimpleAuthCLIFlags,
|
||||
}
|
||||
|
||||
cmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||
microcmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||
Name: "update-ldap-simple",
|
||||
Usage: "Update existing LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
|
@ -226,7 +226,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = cmdAuthAddLdapBindDn.Flags
|
||||
app.Flags = microcmdAuthAddLdapBindDn.Flags
|
||||
app.Action = service.addLdapBindDn
|
||||
|
||||
// Run it
|
||||
@ -457,7 +457,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = cmdAuthAddLdapSimpleAuth.Flags
|
||||
app.Flags = microcmdAuthAddLdapSimpleAuth.Flags
|
||||
app.Action = service.addLdapSimpleAuth
|
||||
|
||||
// Run it
|
||||
@ -920,7 +920,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = cmdAuthUpdateLdapBindDn.Flags
|
||||
app.Flags = microcmdAuthUpdateLdapBindDn.Flags
|
||||
app.Action = service.updateLdapBindDn
|
||||
|
||||
// Run it
|
||||
@ -1310,7 +1310,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = cmdAuthUpdateLdapSimpleAuth.Flags
|
||||
app.Flags = microcmdAuthUpdateLdapSimpleAuth.Flags
|
||||
app.Action = service.updateLdapSimpleAuth
|
||||
|
||||
// Run it
|
||||
|
298
cmd/admin_auth_oauth.go
Normal file
298
cmd/admin_auth_oauth.go
Normal file
@ -0,0 +1,298 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-tenant-id",
|
||||
Value: "",
|
||||
Usage: "Use custom Tenant ID for OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "icon-url",
|
||||
Value: "",
|
||||
Usage: "Custom icon URL for OAuth2 login source",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "scopes",
|
||||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-value",
|
||||
Value: "",
|
||||
Usage: "Claim value that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name providing group names for this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "admin-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for administrator users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "restricted-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for restricted users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-team-map",
|
||||
Value: "",
|
||||
Usage: "JSON mapping between groups and org teams",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "group-team-map-removal",
|
||||
Usage: "Activate automatic team membership removal depending on groups",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
)
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
Tenant: c.String("custom-tenant-id"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &oauth2.Source{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
GroupClaimName: c.String("group-claim-name"),
|
||||
AdminGroup: c.String("admin-group"),
|
||||
RestrictedGroup: c.String("restricted-group"),
|
||||
GroupTeamMap: c.String("group-team-map"),
|
||||
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := parseOAuth2Config(c)
|
||||
if config.Provider == "openidConnect" {
|
||||
discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
|
||||
if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
|
||||
return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
|
||||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.Cfg.(*oauth2.Source)
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
if c.IsSet("icon-url") {
|
||||
oAuth2Config.IconURL = c.String("icon-url")
|
||||
}
|
||||
|
||||
if c.IsSet("scopes") {
|
||||
oAuth2Config.Scopes = c.StringSlice("scopes")
|
||||
}
|
||||
|
||||
if c.IsSet("required-claim-name") {
|
||||
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
|
||||
}
|
||||
if c.IsSet("required-claim-value") {
|
||||
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
|
||||
}
|
||||
|
||||
if c.IsSet("group-claim-name") {
|
||||
oAuth2Config.GroupClaimName = c.String("group-claim-name")
|
||||
}
|
||||
if c.IsSet("admin-group") {
|
||||
oAuth2Config.AdminGroup = c.String("admin-group")
|
||||
}
|
||||
if c.IsSet("restricted-group") {
|
||||
oAuth2Config.RestrictedGroup = c.String("restricted-group")
|
||||
}
|
||||
if c.IsSet("group-team-map") {
|
||||
oAuth2Config.GroupTeamMap = c.String("group-team-map")
|
||||
}
|
||||
if c.IsSet("group-team-map-removal") {
|
||||
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
customURLMapping := &oauth2.CustomURLMapping{}
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
customURLMapping.Tenant = oAuth2Config.CustomURLMapping.Tenant
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-tenant-id") {
|
||||
customURLMapping.Tenant = c.String("custom-tenant-id")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
201
cmd/admin_auth_stmp.go
Normal file
201
cmd/admin_auth_stmp.go
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
smtpCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth-type",
|
||||
Value: "PLAIN",
|
||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "",
|
||||
Usage: "SMTP Host",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "SMTP Port",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
Value: "",
|
||||
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
Value: "",
|
||||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
Usage: "This Authentication Source is Activated.",
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddSMTP = &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: runAddSMTP,
|
||||
Flags: smtpCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateSMTP = &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: runUpdateSMTP,
|
||||
Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
|
||||
}
|
||||
)
|
||||
|
||||
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
if c.IsSet("auth-type") {
|
||||
conf.Auth = c.String("auth-type")
|
||||
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
|
||||
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
|
||||
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
|
||||
}
|
||||
conf.Auth = c.String("auth-type")
|
||||
}
|
||||
if c.IsSet("host") {
|
||||
conf.Host = c.String("host")
|
||||
}
|
||||
if c.IsSet("port") {
|
||||
conf.Port = c.Int("port")
|
||||
}
|
||||
if c.IsSet("allowed-domains") {
|
||||
conf.AllowedDomains = c.String("allowed-domains")
|
||||
}
|
||||
if c.IsSet("force-smtps") {
|
||||
conf.ForceSMTPS = c.Bool("force-smtps")
|
||||
}
|
||||
if c.IsSet("skip-verify") {
|
||||
conf.SkipVerify = c.Bool("skip-verify")
|
||||
}
|
||||
if c.IsSet("helo-hostname") {
|
||||
conf.HeloHostname = c.String("helo-hostname")
|
||||
}
|
||||
if c.IsSet("disable-helo") {
|
||||
conf.DisableHelo = c.Bool("disable-helo")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTP(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.IsSet("name") || len(c.String("name")) == 0 {
|
||||
return errors.New("name must be set")
|
||||
}
|
||||
if !c.IsSet("host") || len(c.String("host")) == 0 {
|
||||
return errors.New("host must be set")
|
||||
}
|
||||
if !c.IsSet("port") {
|
||||
return errors.New("port must be set")
|
||||
}
|
||||
active := true
|
||||
if c.IsSet("active") {
|
||||
active = c.Bool("active")
|
||||
}
|
||||
|
||||
var smtpConfig smtp.Source
|
||||
if err := parseSMTPConfig(c, &smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not set default to PLAIN
|
||||
if len(smtpConfig.Auth) == 0 {
|
||||
smtpConfig.Auth = "PLAIN"
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateSMTP(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smtpConfig := source.Cfg.(*smtp.Source)
|
||||
|
||||
if err := parseSMTPConfig(c, smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("active") {
|
||||
source.IsActive = c.Bool("active")
|
||||
}
|
||||
|
||||
source.Cfg = smtpConfig
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
46
cmd/admin_regenerate.go
Normal file
46
cmd/admin_regenerate.go
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
microcmdRegenHooks = &cli.Command{
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
}
|
||||
|
||||
microcmdRegenKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
}
|
||||
)
|
||||
|
||||
func runRegenerateHooks(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||
}
|
||||
|
||||
func runRegenerateKeys(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return asymkey_model.RewriteAllPublicKeys(ctx)
|
||||
}
|
@ -20,9 +20,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: "..",
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func makePathOutput(workPath, customPath, customConf string) string {
|
||||
|
@ -220,10 +220,10 @@ TAGS="bindata sqlite sqlite_unlock_notify" \
|
||||
make build
|
||||
```
|
||||
|
||||
## 源映射
|
||||
## Source Map
|
||||
|
||||
默认情况下,gitea 会为前端文件生成精简的源映射以节省空间。 这可以通过“ENABLE_SOURCEMAP”环境变量进行控制:
|
||||
默认情况下,gitea 会为前端文件生成精简的 Source Map 以节省空间。 这可以通过“ENABLE_SOURCEMAP”环境变量进行控制:
|
||||
|
||||
- `ENABLE_SOURCEMAP=true` 生成所有源映射,这是开发版本的默认设置
|
||||
- `ENABLE_SOURCEMAP=reduced` 生成有限的源映射,这是生产版本的默认设置
|
||||
- `ENABLE_SOURCEMAP=false` 不生成源映射
|
||||
- `ENABLE_SOURCEMAP=true` 生成所有Source Map,这是开发版本的默认设置
|
||||
- `ENABLE_SOURCEMAP=reduced` 生成有限的Source Map,这是生产版本的默认设置
|
||||
- `ENABLE_SOURCEMAP=false` 不生成Source Map
|
||||
|
20
go.mod
20
go.mod
@ -19,7 +19,7 @@ require (
|
||||
github.com/PuerkitoBio/goquery v1.8.1
|
||||
github.com/alecthomas/chroma/v2 v2.9.1
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.3.9
|
||||
github.com/blevesearch/bleve/v2 v2.3.10
|
||||
github.com/bufbuild/connect-go v1.10.0
|
||||
github.com/buildkite/terminal-to-html/v3 v3.9.1
|
||||
github.com/caddyserver/certmagic v0.19.2
|
||||
@ -145,22 +145,22 @@ require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.8.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.0.5 // indirect
|
||||
github.com/blevesearch/geo v0.1.17 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.9.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.0.6 // indirect
|
||||
github.com/blevesearch/geo v0.1.18 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.5 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.6 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
github.com/blevesearch/vellum v1.0.10 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.9 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.9 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.9 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.9 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.12 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230611145640-acc696258285 // indirect
|
||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||
|
40
go.sum
40
go.sum
@ -149,18 +149,18 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.1.10/go.mod h1:w0XsmFg8qg6cmpTtJ0z3pKgjTDBMMnI/+I2syrE6XBE=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
|
||||
github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.9.0 h1:g1YivPG8jOtrN013Fe8OBXubkiTwvm7/vG2vXz03ANU=
|
||||
github.com/bits-and-blooms/bitset v1.9.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/blevesearch/bleve/v2 v2.0.5/go.mod h1:ZjWibgnbRX33c+vBRgla9QhPb4QOjD6fdVJ+R1Bk8LM=
|
||||
github.com/blevesearch/bleve/v2 v2.3.9 h1:pUMvK0mxAexqasZcVj8lazmWnEW5XiV0tASIqANiNTQ=
|
||||
github.com/blevesearch/bleve/v2 v2.3.9/go.mod h1:1PibElcjlQMQHF9uS9mRv58ODQgj4pCWHA1Wfd+qagU=
|
||||
github.com/blevesearch/bleve/v2 v2.3.10 h1:z8V0wwGoL4rp7nG/O3qVVLYxUqCbEwskMt4iRJsPLgg=
|
||||
github.com/blevesearch/bleve/v2 v2.3.10/go.mod h1:RJzeoeHC+vNHsoLR54+crS1HmOWpnH87fL70HAUCzIA=
|
||||
github.com/blevesearch/bleve_index_api v1.0.0/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/bleve_index_api v1.0.5 h1:Lc986kpC4Z0/n1g3gg8ul7H+lxgOQPcXb9SxvQGu+tw=
|
||||
github.com/blevesearch/bleve_index_api v1.0.5/go.mod h1:YXMDwaXFFXwncRS8UobWs7nvo0DmusriM1nztTlj1ms=
|
||||
github.com/blevesearch/geo v0.1.17 h1:AguzI6/5mHXapzB0gE9IKWo+wWPHZmXZoscHcjFgAFA=
|
||||
github.com/blevesearch/geo v0.1.17/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM=
|
||||
github.com/blevesearch/bleve_index_api v1.0.6 h1:gyUUxdsrvmW3jVhhYdCVL6h9dCjNT/geNU7PxGn37p8=
|
||||
github.com/blevesearch/bleve_index_api v1.0.6/go.mod h1:YXMDwaXFFXwncRS8UobWs7nvo0DmusriM1nztTlj1ms=
|
||||
github.com/blevesearch/geo v0.1.18 h1:Np8jycHTZ5scFe7VEPLrDoHnnb9C4j636ue/CGrhtDw=
|
||||
github.com/blevesearch/geo v0.1.18/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
@ -169,8 +169,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+
|
||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.0.1/go.mod h1:lq7yK2jQy1yQjtjTfU931aVqz7pYxEudHaDwOt1tXfU=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.5 h1:1g713kpCQZ8u4a3stRGBfrwVOuGRnmxOVU5MQkUPrHU=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.5/go.mod h1:f2nOkKS1HcjgIWZgDAErgBdxmr2eyt0Kn7IY+FU1Xe4=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.6 h1:CdekX/Ob6YCYmeHzD72cKpwzBjvkOGegHOqhAkXp6yA=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.6/go.mod h1:nQQYlp51XvoSVxcciBjtvuHPIVjlWrN1hX4qwK2cqdc=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
@ -184,20 +184,20 @@ github.com/blevesearch/vellum v1.0.4/go.mod h1:cMhywHI0de50f7Nj42YgvyD6bFJ2WkNRv
|
||||
github.com/blevesearch/vellum v1.0.10 h1:HGPJDT2bTva12hrHepVT3rOyIKFFF4t7Gf6yMxyMIPI=
|
||||
github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k=
|
||||
github.com/blevesearch/zapx/v11 v11.2.0/go.mod h1:gN/a0alGw1FZt/YGTo1G6Z6XpDkeOfujX5exY9sCQQM=
|
||||
github.com/blevesearch/zapx/v11 v11.3.9 h1:y3ijS4h4MJdmQ07MHASxat4owAixreK2xdo76w9ncrw=
|
||||
github.com/blevesearch/zapx/v11 v11.3.9/go.mod h1:jcAYnQwlr+LqD2vLjDWjWiZDXDXGFqPbpPDRTd3XmS4=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 h1:hvjgj9tZ9DeIqBCxKhi70TtSZYMdcFn7gDb71Xo/fvk=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ=
|
||||
github.com/blevesearch/zapx/v12 v12.2.0/go.mod h1:fdjwvCwWWwJW/EYTYGtAp3gBA0geCYGLcVTtJEZnY6A=
|
||||
github.com/blevesearch/zapx/v12 v12.3.9 h1:MXGLlZ03oxXH3DMJTZaBaRj2xb6t4wQVZeZK/wu1M6w=
|
||||
github.com/blevesearch/zapx/v12 v12.3.9/go.mod h1:QXCMwmOkdLnMDgTN1P4CcuX5F851iUOtOwXbw0HMBYs=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 h1:yHfj3vXLSYmmsBleJFROXuO08mS3L1qDCdDK81jDl8s=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs=
|
||||
github.com/blevesearch/zapx/v13 v13.2.0/go.mod h1:o5rAy/lRS5JpAbITdrOHBS/TugWYbkcYZTz6VfEinAQ=
|
||||
github.com/blevesearch/zapx/v13 v13.3.9 h1:+VAz9V0VmllHXlZV4DCvfYj0nqaZHgF3MeEHwOyRBwQ=
|
||||
github.com/blevesearch/zapx/v13 v13.3.9/go.mod h1:s+WjNp4WSDtrBVBpa37DUOd7S/Gr/jTZ7ST/MbCVj/0=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIqMGahDE8=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
|
||||
github.com/blevesearch/zapx/v14 v14.2.0/go.mod h1:GNgZusc1p4ot040cBQMRGEZobvwjCquiEKYh1xLFK9g=
|
||||
github.com/blevesearch/zapx/v14 v14.3.9 h1:wuqxATgsTCNHM9xsOFOeFp8H2heZ/gMX/tsl9lRK8U4=
|
||||
github.com/blevesearch/zapx/v14 v14.3.9/go.mod h1:MWZ4v8AzFBRurhDzkLvokFW8ljcq9Evm27mkWe8OGbM=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
||||
github.com/blevesearch/zapx/v15 v15.2.0/go.mod h1:MmQceLpWfME4n1WrBFIwplhWmaQbQqLQARpaKUEOs/A=
|
||||
github.com/blevesearch/zapx/v15 v15.3.12 h1:w/kU9aHyfMDEdwHGZzCiakC3HZ9z5gYlXaALDC4Dct8=
|
||||
github.com/blevesearch/zapx/v15 v15.3.12/go.mod h1:tx53gDJS/7Oa3Je820cmVurqCuJ4dqdAy1kiDMV/IUo=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
|
@ -22,7 +22,7 @@ type ActionRunnerToken struct {
|
||||
Owner *user_model.User `xorm:"-"`
|
||||
RepoID int64 `xorm:"index"` // repo level runner, if orgid also is zero, then it's a global
|
||||
Repo *repo_model.Repository `xorm:"-"`
|
||||
IsActive bool
|
||||
IsActive bool // true means it can be used
|
||||
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||
@ -57,7 +57,7 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
|
||||
return err
|
||||
}
|
||||
|
||||
// NewRunnerToken creates a new runner token
|
||||
// NewRunnerToken creates a new active runner token and invalidate all old tokens
|
||||
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||
token, err := util.CryptoRandomString(40)
|
||||
if err != nil {
|
||||
@ -66,17 +66,27 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
|
||||
runnerToken := &ActionRunnerToken{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
IsActive: false,
|
||||
IsActive: true,
|
||||
Token: token,
|
||||
}
|
||||
_, err = db.GetEngine(ctx).Insert(runnerToken)
|
||||
return runnerToken, err
|
||||
|
||||
return runnerToken, db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if _, err := db.GetEngine(ctx).Where("owner_id =? AND repo_id = ?", ownerID, repoID).Cols("is_active").Update(&ActionRunnerToken{
|
||||
IsActive: false,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.GetEngine(ctx).Insert(runnerToken)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// GetUnactivatedRunnerToken returns a unactivated runner token
|
||||
func GetUnactivatedRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||
// GetLastestRunnerToken returns the latest runner token
|
||||
func GetLastestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||
var runnerToken ActionRunnerToken
|
||||
has, err := db.GetEngine(ctx).Where("owner_id=? AND repo_id=? AND is_active=?", ownerID, repoID, false).OrderBy("id DESC").Get(&runnerToken)
|
||||
has, err := db.GetEngine(ctx).Where("owner_id=? AND repo_id=?", ownerID, repoID).
|
||||
OrderBy("id DESC").Get(&runnerToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package activities_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -12,7 +11,6 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{
|
||||
"gpg_key.yml",
|
||||
"public_key.yml",
|
||||
|
@ -4,7 +4,6 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -17,7 +16,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package avatars_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -15,7 +14,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package db_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package paginator
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package dbfs
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -15,7 +14,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package issues_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
@ -30,7 +29,5 @@ func TestFixturesAreConsistent(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -29,7 +29,5 @@ func TestFixturesAreConsistent(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: "..",
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package organization_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -18,7 +17,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package packages_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@ -20,9 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestHasOwnerPackages(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package access_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -17,7 +16,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,6 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{
|
||||
"project.yml",
|
||||
"project_board.yml",
|
||||
|
@ -4,7 +4,6 @@
|
||||
package repo_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -18,7 +17,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package system_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -16,7 +15,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -62,35 +62,46 @@ func InitSettings(extraConfigs ...string) {
|
||||
|
||||
// TestOptions represents test options
|
||||
type TestOptions struct {
|
||||
GiteaRootPath string
|
||||
FixtureFiles []string
|
||||
SetUp func() error // SetUp will be executed before all tests in this package
|
||||
TearDown func() error // TearDown will be executed after all tests in this package
|
||||
FixtureFiles []string
|
||||
SetUp func() error // SetUp will be executed before all tests in this package
|
||||
TearDown func() error // TearDown will be executed after all tests in this package
|
||||
}
|
||||
|
||||
// MainTest a reusable TestMain(..) function for unit tests that need to use a
|
||||
// test database. Creates the test database, and sets necessary settings.
|
||||
func MainTest(m *testing.M, testOpts *TestOptions) {
|
||||
setting.CustomPath = filepath.Join(testOpts.GiteaRootPath, "custom")
|
||||
func MainTest(m *testing.M, testOpts ...*TestOptions) {
|
||||
searchDir, _ := os.Getwd()
|
||||
for searchDir != "" {
|
||||
if _, err := os.Stat(filepath.Join(searchDir, "go.mod")); err == nil {
|
||||
break // The "go.mod" should be the one for Gitea repository
|
||||
}
|
||||
if dir := filepath.Dir(searchDir); dir == searchDir {
|
||||
searchDir = "" // reaches the root of filesystem
|
||||
} else {
|
||||
searchDir = dir
|
||||
}
|
||||
}
|
||||
if searchDir == "" {
|
||||
panic("The tests should run in a Gitea repository, there should be a 'go.mod' in the root")
|
||||
}
|
||||
|
||||
giteaRoot = searchDir
|
||||
setting.CustomPath = filepath.Join(giteaRoot, "custom")
|
||||
InitSettings()
|
||||
|
||||
var err error
|
||||
|
||||
giteaRoot = testOpts.GiteaRootPath
|
||||
fixturesDir = filepath.Join(testOpts.GiteaRootPath, "models", "fixtures")
|
||||
|
||||
fixturesDir = filepath.Join(giteaRoot, "models", "fixtures")
|
||||
var opts FixturesOptions
|
||||
if len(testOpts.FixtureFiles) == 0 {
|
||||
if len(testOpts) == 0 || len(testOpts[0].FixtureFiles) == 0 {
|
||||
opts.Dir = fixturesDir
|
||||
} else {
|
||||
for _, f := range testOpts.FixtureFiles {
|
||||
for _, f := range testOpts[0].FixtureFiles {
|
||||
if len(f) != 0 {
|
||||
opts.Files = append(opts.Files, filepath.Join(fixturesDir, f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = CreateTestEngine(opts); err != nil {
|
||||
if err := CreateTestEngine(opts); err != nil {
|
||||
fatalTestError("Error creating test engine: %v\n", err)
|
||||
}
|
||||
|
||||
@ -112,8 +123,8 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
|
||||
fatalTestError("TempDir: %v\n", err)
|
||||
}
|
||||
setting.AppDataPath = appDataPath
|
||||
setting.AppWorkPath = testOpts.GiteaRootPath
|
||||
setting.StaticRootPath = testOpts.GiteaRootPath
|
||||
setting.AppWorkPath = giteaRoot
|
||||
setting.StaticRootPath = giteaRoot
|
||||
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
|
||||
|
||||
setting.Attachment.Storage.Path = filepath.Join(setting.AppDataPath, "attachments")
|
||||
@ -144,7 +155,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
|
||||
if err = util.RemoveAll(repoRootPath); err != nil {
|
||||
fatalTestError("util.RemoveAll: %v\n", err)
|
||||
}
|
||||
if err = CopyDir(filepath.Join(testOpts.GiteaRootPath, "tests", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
|
||||
if err = CopyDir(filepath.Join(giteaRoot, "tests", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
|
||||
fatalTestError("util.CopyDir: %v\n", err)
|
||||
}
|
||||
|
||||
@ -171,16 +182,16 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
if testOpts.SetUp != nil {
|
||||
if err := testOpts.SetUp(); err != nil {
|
||||
if len(testOpts) > 0 && testOpts[0].SetUp != nil {
|
||||
if err := testOpts[0].SetUp(); err != nil {
|
||||
fatalTestError("set up failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
exitStatus := m.Run()
|
||||
|
||||
if testOpts.TearDown != nil {
|
||||
if err := testOpts.TearDown(); err != nil {
|
||||
if len(testOpts) > 0 && testOpts[0].TearDown != nil {
|
||||
if err := testOpts[0].TearDown(); err != nil {
|
||||
fatalTestError("tear down failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package user_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -16,7 +15,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -12,7 +11,6 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{
|
||||
"webhook.yml",
|
||||
"hook_task.yml",
|
||||
|
@ -4,7 +4,6 @@
|
||||
package activitypub
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -15,7 +14,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -168,9 +168,9 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
// find protected branches without existing repository
|
||||
genericOrphanCheck("Protected Branches without existing repository",
|
||||
"protected_branch", "repository", "protected_branch.repo_id=repository.id"),
|
||||
// find deleted branches without existing repository
|
||||
genericOrphanCheck("Deleted Branches without existing repository",
|
||||
"deleted_branch", "repository", "deleted_branch.repo_id=repository.id"),
|
||||
// find branches without existing repository
|
||||
genericOrphanCheck("Branches without existing repository",
|
||||
"branch", "repository", "branch.repo_id=repository.id"),
|
||||
// find LFS locks without existing repository
|
||||
genericOrphanCheck("LFS locks without existing repository",
|
||||
"lfs_lock", "repository", "lfs_lock.repo_id=repository.id"),
|
||||
@ -189,6 +189,9 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
// find action without repository
|
||||
genericOrphanCheck("Action entries without existing repository",
|
||||
"action", "repository", "action.repo_id=repository.id"),
|
||||
// find action without user
|
||||
genericOrphanCheck("Action entries without existing user",
|
||||
"action", "user", "action.act_user_id=`user`.id"),
|
||||
// find OAuth2Grant without existing user
|
||||
genericOrphanCheck("Orphaned OAuth2Grant without existing User",
|
||||
"oauth2_grant", "user", "oauth2_grant.user_id=`user`.id"),
|
||||
|
@ -6,7 +6,6 @@ package code
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -23,9 +22,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
||||
|
@ -5,7 +5,6 @@ package issues
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@ -22,9 +21,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestDBSearchIssues(t *testing.T) {
|
||||
|
@ -5,7 +5,6 @@ package stats
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -23,9 +22,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestRepoStatsIndex(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -13,7 +12,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,8 +13,7 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{""}, // load nothing
|
||||
FixtureFiles: []string{""}, // load nothing
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ milestones=マイルストーン
|
||||
|
||||
ok=OK
|
||||
cancel=キャンセル
|
||||
retry=再試行
|
||||
rerun=再実行
|
||||
rerun_all=すべてのジョブを再実行
|
||||
save=保存
|
||||
|
7
package-lock.json
generated
7
package-lock.json
generated
@ -67,6 +67,7 @@
|
||||
"eslint-plugin-regexp": "1.15.0",
|
||||
"eslint-plugin-sonarjs": "0.21.0",
|
||||
"eslint-plugin-unicorn": "48.0.1",
|
||||
"eslint-plugin-vitest-globals": "1.4.0",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.5.0",
|
||||
"eslint-plugin-wc": "2.0.3",
|
||||
@ -4963,6 +4964,12 @@
|
||||
"eslint": ">=8.44.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest-globals": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vitest-globals/-/eslint-plugin-vitest-globals-1.4.0.tgz",
|
||||
"integrity": "sha512-WE+YlK9X9s4vf5EaYRU0Scw7WItDZStm+PapFSYlg2ABNtaQ4zIG7wEqpoUB3SlfM+SgkhgmzR0TeJOO5k3/Nw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint-plugin-vue": {
|
||||
"version": "9.17.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"eslint-plugin-regexp": "1.15.0",
|
||||
"eslint-plugin-sonarjs": "0.21.0",
|
||||
"eslint-plugin-unicorn": "48.0.1",
|
||||
"eslint-plugin-vitest-globals": "1.4.0",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.5.0",
|
||||
"eslint-plugin-wc": "2.0.3",
|
||||
|
@ -47,11 +47,11 @@ func (s *Service) Register(
|
||||
|
||||
runnerToken, err := actions_model.GetRunnerToken(ctx, req.Msg.Token)
|
||||
if err != nil {
|
||||
return nil, errors.New("runner token not found")
|
||||
return nil, errors.New("runner registration token not found")
|
||||
}
|
||||
|
||||
if runnerToken.IsActive {
|
||||
return nil, errors.New("runner token has already been activated")
|
||||
if !runnerToken.IsActive {
|
||||
return nil, errors.New("runner registration token has been invalidated, please use the latest one")
|
||||
}
|
||||
|
||||
labels := req.Msg.Labels
|
||||
|
@ -4,7 +4,6 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,6 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", "..", ".."),
|
||||
SetUp: func() error {
|
||||
setting.LoadQueueSettings()
|
||||
return webhook_service.Init()
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -35,7 +34,5 @@ func TestRenderPanicErrorPage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ package install
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -35,7 +34,5 @@ func TestRoutes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
|
||||
})
|
||||
}
|
||||
|
||||
token, err := actions_model.GetUnactivatedRunnerToken(ctx, owner, repo)
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
token, err := actions_model.GetLastestRunnerToken(ctx, owner, repo)
|
||||
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
|
||||
token, err = actions_model.NewRunnerToken(ctx, owner, repo)
|
||||
if err != nil {
|
||||
err := fmt.Sprintf("error while creating runner token: %v", err)
|
||||
|
@ -4,14 +4,11 @@
|
||||
package private
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package org_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package setting
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -35,15 +35,15 @@ func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
|
||||
|
||||
// ownid=0,repo_id=0,means this token is used for global
|
||||
var token *actions_model.ActionRunnerToken
|
||||
token, err = actions_model.GetUnactivatedRunnerToken(ctx, opts.OwnerID, opts.RepoID)
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
token, err = actions_model.GetLastestRunnerToken(ctx, opts.OwnerID, opts.RepoID)
|
||||
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
|
||||
token, err = actions_model.NewRunnerToken(ctx, opts.OwnerID, opts.RepoID)
|
||||
if err != nil {
|
||||
ctx.ServerError("CreateRunnerToken", err)
|
||||
return
|
||||
}
|
||||
} else if err != nil {
|
||||
ctx.ServerError("GetUnactivatedRunnerToken", err)
|
||||
ctx.ServerError("GetLastestRunnerToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,11 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,14 +4,11 @@
|
||||
package setting
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -19,9 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestUploadAttachment(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -13,7 +12,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -20,9 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestRenameRepoAction(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package gitdiff
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -15,7 +14,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package issue
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -13,7 +12,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package mailer
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -13,7 +12,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package markup
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -12,7 +11,6 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{"user.yml"},
|
||||
FixtureFiles: []string{"user.yml"},
|
||||
})
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -16,9 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func timePtr(t time.Time) *time.Time {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
@ -16,9 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestDeleteOrganization(t *testing.T) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
package pull
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -14,7 +13,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package release
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@ -22,9 +21,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestRelease_Create(t *testing.T) {
|
||||
|
@ -5,7 +5,6 @@ package archiver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -18,9 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestArchive_Basic(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -19,9 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", "..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func getExpectedReadmeContentsResponse() *api.ContentsResponse {
|
||||
|
@ -4,14 +4,11 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -22,9 +21,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@ -19,7 +18,6 @@ func TestMain(m *testing.M) {
|
||||
// for tests, allow only loopback IPs
|
||||
setting.Webhook.AllowedHostList = hostmatcher.MatchBuiltinLoopback
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
SetUp: func() error {
|
||||
setting.LoadQueueSettings()
|
||||
return Init()
|
||||
|
@ -5,7 +5,6 @@ package wiki
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -20,9 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
|
||||
func TestWebPathSegments(t *testing.T) {
|
||||
|
@ -19,12 +19,12 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
{{if .DefaultBranchBranch.IsProtected}}
|
||||
{{svg "octicon-shield-lock"}}
|
||||
{{end}}
|
||||
<div class="gt-df gt-ac">
|
||||
{{if .DefaultBranchBranch.IsProtected}}
|
||||
<span class="gt-df gt-pr-2">{{svg "octicon-shield-lock"}}</span>
|
||||
{{end}}
|
||||
<a class="gt-ellipsis" href="{{.RepoLink}}/src/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}">{{.DefaultBranchBranch.DBBranch.Name}}</a>
|
||||
<button class="btn interact-fg gt-p-3" data-clipboard-text="{{.DefaultBranchBranch.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
<button class="btn interact-fg gt-df gt-p-3" data-clipboard-text="{{.DefaultBranchBranch.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}}
|
||||
</div>
|
||||
<p class="info gt-df gt-ac gt-my-2">{{svg "octicon-git-commit" 16 "gt-mr-2"}}<a href="{{.RepoLink}}/commit/{{PathEscape .DefaultBranchBranch.DBBranch.CommitID}}">{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DefaultBranchBranch.DBBranch.CommitMessage .RepoLink .Repository.ComposeMetas}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DefaultBranchBranch.DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DefaultBranchBranch.DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}</p>
|
||||
@ -97,12 +97,12 @@
|
||||
</div>
|
||||
<p class="info">{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{TimeSinceUnix .DBBranch.DeletedUnix ctx.Locale}}</p>
|
||||
{{else}}
|
||||
{{if .IsProtected}}
|
||||
{{svg "octicon-shield-lock"}}
|
||||
{{end}}
|
||||
<div class="gt-df gt-ac">
|
||||
{{if .IsProtected}}
|
||||
<span class="gt-df gt-pr-2">{{svg "octicon-shield-lock"}}</span>
|
||||
{{end}}
|
||||
<a class="gt-ellipsis" href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .DBBranch.Name}}">{{.DBBranch.Name}}</a>
|
||||
<button class="btn interact-fg gt-p-3" data-clipboard-text="{{.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
<button class="btn interact-fg gt-df gt-p-3" data-clipboard-text="{{.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DBBranch.CommitID)}}
|
||||
</div>
|
||||
<p class="info gt-df gt-ac gt-my-2">{{svg "octicon-git-commit" 16 "gt-mr-2"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .DBBranch.CommitID}}">{{ShortSha .DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DBBranch.CommitMessage $.RepoLink $.Repository.ComposeMetas}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}</p>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- make sure this matches the color logic in web_src/js/components/DashboardRepoList.vue -->
|
||||
<span class="gt-df">
|
||||
{{if eq .State "pending"}}
|
||||
{{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}}
|
||||
{{end}}
|
||||
@ -11,3 +12,4 @@
|
||||
{{if eq .State "failure"}}
|
||||
{{svg "octicon-x" 18 "commit-status icon text red"}}
|
||||
{{end}}
|
||||
</span>
|
||||
|
@ -11,6 +11,7 @@ export default defineConfig({
|
||||
open: false,
|
||||
allowOnly: true,
|
||||
passWithNoTests: true,
|
||||
globals: true,
|
||||
watch: false,
|
||||
},
|
||||
plugins: [
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {parseIssueListQuickGotoLink} from './common-issue-list.js';
|
||||
|
||||
test('parseIssueListQuickGotoLink', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {singleAnchorRegex, rangeAnchorRegex} from './repo-code.js';
|
||||
|
||||
test('singleAnchorRegex', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import {strSubMatch, calcMatchedWeight, filterRepoFilesWeighted} from './repo-findfile.js';
|
||||
|
||||
describe('Repo Find Files', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {GET, POST, PATCH, PUT, DELETE} from './fetch.js';
|
||||
|
||||
// tests here are only to satisfy the linter for unused functions
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {showInfoToast, showErrorToast, showWarningToast} from './toast.js';
|
||||
|
||||
test('showInfoToast', async () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {expect, test} from 'vitest';
|
||||
import {renderAnsi} from './ansi.js';
|
||||
|
||||
test('renderAnsi', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {expect, test} from 'vitest';
|
||||
import {svg, SvgIcon, svgParseOuterInner} from './svg.js';
|
||||
import {createApp, h} from 'vue';
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {expect, test} from 'vitest';
|
||||
import {
|
||||
basename, extname, isObject, stripTags, parseIssueHref,
|
||||
parseUrl, translateMonth, translateDay, blobToDataURI,
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {useLightTextOnBackground} from './color.js';
|
||||
|
||||
test('useLightTextOnBackground', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {test, expect} from 'vitest';
|
||||
import {matchEmoji, matchMention} from './match.js';
|
||||
|
||||
test('matchEmoji', () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {expect, test} from 'vitest';
|
||||
import {pathEscapeSegments} from './url.js';
|
||||
|
||||
test('pathEscapeSegments', () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user