mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-04-08 02:31:36 +02:00
Merge branch 'report_abuse' into combine-multiple-reports-in-database
This commit is contained in:
commit
27fb9a0bfe
638 changed files with 7215 additions and 5225 deletions
|
@ -192,6 +192,9 @@ forgejo.org/modules/translation
|
|||
MockLocale.HasKey
|
||||
MockLocale.PrettyNumber
|
||||
|
||||
forgejo.org/modules/translation/localeiter
|
||||
IterateMessagesContent
|
||||
|
||||
forgejo.org/modules/util
|
||||
OptionalArg
|
||||
|
||||
|
@ -210,9 +213,6 @@ forgejo.org/modules/zstd
|
|||
Writer.Write
|
||||
Writer.Close
|
||||
|
||||
forgejo.org/routers/web
|
||||
NotFound
|
||||
|
||||
forgejo.org/routers/web/org
|
||||
MustEnableProjects
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ insert_final_newline = true
|
|||
[{*.{go,tmpl,html},Makefile,go.mod}]
|
||||
indent_style = tab
|
||||
|
||||
[go.*]
|
||||
indent_style = tab
|
||||
|
||||
[templates/custom/*.tmpl]
|
||||
insert_final_newline = false
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:39.212.0
|
||||
image: data.forgejo.org/renovate/renovate:39.222.1
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
- uses: ./.forgejo/workflows-composite/build-backend
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: https://data.forgejo.org/tj-actions/changed-files@v45
|
||||
uses: https://data.forgejo.org/tj-actions/changed-files@v46
|
||||
with:
|
||||
separator: '\n'
|
||||
- run: |
|
||||
|
|
269
.golangci.yml
269
.golangci.yml
|
@ -1,7 +1,9 @@
|
|||
version: "2"
|
||||
output:
|
||||
sort-order:
|
||||
- file
|
||||
linters:
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
fast: false
|
||||
default: none
|
||||
enable:
|
||||
- bidichk
|
||||
- depguard
|
||||
|
@ -9,142 +11,155 @@ linters:
|
|||
- errcheck
|
||||
- forbidigo
|
||||
- gocritic
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- testifylint
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unused
|
||||
- unparam
|
||||
- unused
|
||||
- usetesting
|
||||
- wastedassign
|
||||
|
||||
run:
|
||||
timeout: 10m
|
||||
|
||||
output:
|
||||
sort-results: true
|
||||
sort-order: [file]
|
||||
show-stats: true
|
||||
|
||||
linters-settings:
|
||||
stylecheck:
|
||||
checks: ["all", "-ST1005", "-ST1003"]
|
||||
nakedret:
|
||||
max-func-lines: 0
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
revive:
|
||||
severity: error
|
||||
settings:
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: encoding/json
|
||||
desc: use gitea's modules/json instead of encoding/json
|
||||
- pkg: github.com/unknwon/com
|
||||
desc: use gitea's util and replacements
|
||||
- pkg: io/ioutil
|
||||
desc: use os or io instead
|
||||
- pkg: golang.org/x/exp
|
||||
desc: it's experimental and unreliable
|
||||
- pkg: forgejo.org/modules/git/internal
|
||||
desc: do not use the internal package, use AddXxx function instead
|
||||
- pkg: gopkg.in/ini.v1
|
||||
desc: do not use the ini package, use gitea's config system instead
|
||||
- pkg: github.com/minio/sha256-simd
|
||||
desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
revive:
|
||||
severity: error
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: bare-return
|
||||
- name: blank-imports
|
||||
- name: constant-logical-expr
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: duplicated-imports
|
||||
- name: empty-lines
|
||||
- name: error-naming
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: errorf
|
||||
- name: exported
|
||||
- name: identical-branches
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: indent-error-flow
|
||||
- name: modifies-value-receiver
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: redefines-builtin-id
|
||||
- name: string-of-int
|
||||
- name: superfluous-else
|
||||
- name: time-naming
|
||||
- name: unconditional-recursion
|
||||
- name: unexported-return
|
||||
- name: unreachable-code
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
- name: redefines-builtin-id
|
||||
disabled: true
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
testifylint:
|
||||
disable:
|
||||
- go-require
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: bare-return
|
||||
- name: blank-imports
|
||||
- name: constant-logical-expr
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: duplicated-imports
|
||||
- name: empty-lines
|
||||
- name: error-naming
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: errorf
|
||||
- name: exported
|
||||
- name: identical-branches
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: indent-error-flow
|
||||
- name: modifies-value-receiver
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: redefines-builtin-id
|
||||
- name: string-of-int
|
||||
- name: superfluous-else
|
||||
- name: time-naming
|
||||
- name: unconditional-recursion
|
||||
- name: unexported-return
|
||||
- name: unreachable-code
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
- name: redefines-builtin-id
|
||||
disabled: true
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: encoding/json
|
||||
desc: use gitea's modules/json instead of encoding/json
|
||||
- pkg: github.com/unknwon/com
|
||||
desc: use gitea's util and replacements
|
||||
- pkg: io/ioutil
|
||||
desc: use os or io instead
|
||||
- pkg: golang.org/x/exp
|
||||
desc: it's experimental and unreliable
|
||||
- pkg: forgejo.org/modules/git/internal
|
||||
desc: do not use the internal package, use AddXxx function instead
|
||||
- pkg: gopkg.in/ini.v1
|
||||
desc: do not use the ini package, use gitea's config system instead
|
||||
- pkg: github.com/minio/sha256-simd
|
||||
desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528
|
||||
testifylint:
|
||||
disable:
|
||||
- go-require
|
||||
|
||||
- linters:
|
||||
- nolintlint
|
||||
path: models/db/sql_postgres_with_schema.go
|
||||
- linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- gocyclo
|
||||
- gosec
|
||||
- staticcheck
|
||||
- unparam
|
||||
path: _test\.go
|
||||
- linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- gocyclo
|
||||
- gosec
|
||||
path: models/migrations/v
|
||||
- linters:
|
||||
- forbidigo
|
||||
path: cmd
|
||||
- linters:
|
||||
- dupl
|
||||
text: (?i)webhook
|
||||
- linters:
|
||||
- gocritic
|
||||
text: (?i)`ID' should not be capitalized
|
||||
- linters:
|
||||
- deadcode
|
||||
- unused
|
||||
text: (?i)swagger
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: (?i)argument x is overwritten before first use
|
||||
- linters:
|
||||
- gocritic
|
||||
text: '(?i)commentFormatting: put a space between `//` and comment text'
|
||||
- linters:
|
||||
- gocritic
|
||||
text: '(?i)exitAfterDefer:'
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "(ST1005|ST1003|QF1001):"
|
||||
paths:
|
||||
- node_modules
|
||||
- public
|
||||
- web_src
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-dirs: [node_modules, public, web_src]
|
||||
exclude-case-sensitive: true
|
||||
exclude-rules:
|
||||
- path: models/db/sql_postgres_with_schema.go
|
||||
linters:
|
||||
- nolintlint
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- unparam
|
||||
- staticcheck
|
||||
- path: models/migrations/v
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- path: cmd
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: "webhook"
|
||||
linters:
|
||||
- dupl
|
||||
- text: "`ID' should not be capitalized"
|
||||
linters:
|
||||
- gocritic
|
||||
- text: "swagger"
|
||||
linters:
|
||||
- unused
|
||||
- deadcode
|
||||
- text: "argument x is overwritten before first use"
|
||||
linters:
|
||||
- staticcheck
|
||||
- text: "commentFormatting: put a space between `//` and comment text"
|
||||
linters:
|
||||
- gocritic
|
||||
- text: "exitAfterDefer:"
|
||||
linters:
|
||||
- gocritic
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- gofumpt
|
||||
settings:
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- node_modules
|
||||
- public
|
||||
- web_src
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
|
8
Makefile
8
Makefile
|
@ -39,7 +39,7 @@ XGO_VERSION := go-1.21.x
|
|||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.7 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.2 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
|||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.31.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.212.0 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.222.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
@ -462,7 +462,7 @@ lint-locale:
|
|||
|
||||
.PHONY: lint-locale-usage
|
||||
lint-locale-usage:
|
||||
$(GO) run build/lint-locale-usage/lint-locale-usage.go --allow-missing-msgids
|
||||
$(GO) run build/lint-locale-usage/lint-locale-usage.go
|
||||
|
||||
.PHONY: lint-md
|
||||
lint-md: node_modules
|
||||
|
@ -523,7 +523,7 @@ lint-yaml: .venv
|
|||
|
||||
.PHONY: security-check
|
||||
security-check:
|
||||
go run $(GOVULNCHECK_PACKAGE) ./...
|
||||
go run $(GOVULNCHECK_PACKAGE) -show color ./...
|
||||
|
||||
###
|
||||
# Development and testing targets
|
||||
|
|
|
@ -18,8 +18,8 @@ import (
|
|||
tmplParser "text/template/parse"
|
||||
|
||||
"forgejo.org/modules/container"
|
||||
"forgejo.org/modules/locale"
|
||||
fjTemplates "forgejo.org/modules/templates"
|
||||
"forgejo.org/modules/translation/localeiter"
|
||||
"forgejo.org/modules/util"
|
||||
)
|
||||
|
||||
|
@ -264,7 +264,7 @@ func (handler Handler) HandleTemplateFile(fname string, src any) error {
|
|||
Err: err,
|
||||
}
|
||||
}
|
||||
handler.handleTemplateFileNodes(fset, tmplParsed.Tree.Root.Nodes)
|
||||
handler.handleTemplateFileNodes(fset, tmplParsed.Root.Nodes)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -300,10 +300,6 @@ func main() {
|
|||
}
|
||||
|
||||
msgids := make(container.Set[string])
|
||||
onMsgid := func(trKey, trValue string) error {
|
||||
msgids[trKey] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
localeFile := filepath.Join(filepath.Join("options", "locale"), "locale_en-US.ini")
|
||||
localeContent, err := os.ReadFile(localeFile)
|
||||
|
@ -312,7 +308,10 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
if err = locale.IterateMessagesContent(localeContent, onMsgid); err != nil {
|
||||
if err = localeiter.IterateMessagesContent(localeContent, func(trKey, trValue string) error {
|
||||
msgids[trKey] = struct{}{}
|
||||
return nil
|
||||
}); err != nil {
|
||||
fmt.Printf("%s:\tERROR: %s\n", localeFile, err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
|
@ -324,7 +323,11 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
if err := locale.IterateMessagesNextContent(localeContent, onMsgid); err != nil {
|
||||
if err := localeiter.IterateMessagesNextContent(localeContent, func(trKey, pluralForm, trValue string) error {
|
||||
// ignore plural form
|
||||
msgids[trKey] = struct{}{}
|
||||
return nil
|
||||
}); err != nil {
|
||||
fmt.Printf("%s:\tERROR: %s\n", localeFile, err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
|
|
|
@ -37,13 +37,13 @@ func HandleTemplateFileWrapped(t *testing.T, fname, src string) []string {
|
|||
|
||||
func TestUsagesParser(t *testing.T) {
|
||||
t.Run("go, simple", func(t *testing.T) {
|
||||
assert.EqualValues(t,
|
||||
assert.Equal(t,
|
||||
[]string{"what.an.example"},
|
||||
HandleGoFileWrapped(t, "<g1>", "package main\nfunc Render(ctx *context.Context) string { return ctx.Tr(\"what.an.example\"); }\n"))
|
||||
})
|
||||
|
||||
t.Run("template, simple", func(t *testing.T) {
|
||||
assert.EqualValues(t,
|
||||
assert.Equal(t,
|
||||
[]string{"what.an.example"},
|
||||
HandleTemplateFileWrapped(t, "<t1>", "{{ ctx.Locale.Tr \"what.an.example\" }}\n"))
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"slices"
|
||||
"strings"
|
||||
|
||||
"forgejo.org/modules/locale"
|
||||
"forgejo.org/modules/translation/localeiter"
|
||||
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
"github.com/sergi/go-diff/diffmatchpatch"
|
||||
|
@ -100,7 +100,7 @@ func checkValue(trKey, value string) []string {
|
|||
func checkLocaleContent(localeContent []byte) []string {
|
||||
errors := []string{}
|
||||
|
||||
if err := locale.IterateMessagesContent(localeContent, func(trKey, trValue string) error {
|
||||
if err := localeiter.IterateMessagesContent(localeContent, func(trKey, trValue string) error {
|
||||
errors = append(errors, checkValue(trKey, trValue)...)
|
||||
return nil
|
||||
}); err != nil {
|
||||
|
@ -113,8 +113,12 @@ func checkLocaleContent(localeContent []byte) []string {
|
|||
func checkLocaleNextContent(localeContent []byte) []string {
|
||||
errors := []string{}
|
||||
|
||||
if err := locale.IterateMessagesNextContent(localeContent, func(trKey, trValue string) error {
|
||||
errors = append(errors, checkValue(trKey, trValue)...)
|
||||
if err := localeiter.IterateMessagesNextContent(localeContent, func(trKey, pluralForm, trValue string) error {
|
||||
fullKey := trKey
|
||||
if pluralForm != "" {
|
||||
fullKey = trKey + "." + pluralForm
|
||||
}
|
||||
errors = append(errors, checkValue(fullKey, trValue)...)
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -15,9 +15,9 @@ func TestLocalizationPolicy(t *testing.T) {
|
|||
t.Run("Remove tags", func(t *testing.T) {
|
||||
assert.Empty(t, checkLocaleContent([]byte(`hidden_comment_types_description = Comment types checked here will not be shown inside issue pages. Checking "Label" for example removes all "<user> added/removed <label>" comments.`)))
|
||||
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<not-an-allowed-key> <label>"`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<user@example.com>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<user@example.com> <email@example.com>"`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<tag>\x1b[0m REPLACED-TAG \x1b[31m</tag>\x1b[0m"}, checkLocaleContent([]byte(`key = "<tag> <email@example.com> </tag>"`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<not-an-allowed-key> <label>"`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<user@example.com>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<user@example.com> <email@example.com>"`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<tag>\x1b[0m REPLACED-TAG \x1b[31m</tag>\x1b[0m"}, checkLocaleContent([]byte(`key = "<tag> <email@example.com> </tag>"`)))
|
||||
})
|
||||
|
||||
t.Run("Specific exception", func(t *testing.T) {
|
||||
|
@ -25,11 +25,11 @@ func TestLocalizationPolicy(t *testing.T) {
|
|||
assert.Empty(t, checkLocaleContent([]byte(`pulls.title_desc_one = wants to merge %[1]d commit from <code>%[2]s</code> into <code id="%[4]s">%[3]s</code>`)))
|
||||
assert.Empty(t, checkLocaleContent([]byte(`editor.commit_directly_to_this_branch = Commit directly to the <strong class="%[2]s">%[1]s</strong> branch.`)))
|
||||
|
||||
assert.EqualValues(t, []string{"workflow.dispatch.trigger_found: This workflow has a \x1b[31m<d>\x1b[0mworkflow_dispatch\x1b[31m</d>\x1b[0m event trigger."}, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <d>workflow_dispatch</d> event trigger.`)))
|
||||
assert.EqualValues(t, []string{"key: <code\x1b[31m id=\"branch_targe\"\x1b[0m>%[3]s</code>"}, checkLocaleContent([]byte(`key = <code id="branch_targe">%[3]s</code>`)))
|
||||
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"ui sh\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="ui sh" href="%[3]s">`)))
|
||||
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"js-click-me\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="js-click-me" href="%[3]s">`)))
|
||||
assert.EqualValues(t, []string{"key: <strong\x1b[31m class=\"branch-target\"\x1b[0m>%[1]s</strong>"}, checkLocaleContent([]byte(`key = <strong class="branch-target">%[1]s</strong>`)))
|
||||
assert.Equal(t, []string{"workflow.dispatch.trigger_found: This workflow has a \x1b[31m<d>\x1b[0mworkflow_dispatch\x1b[31m</d>\x1b[0m event trigger."}, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <d>workflow_dispatch</d> event trigger.`)))
|
||||
assert.Equal(t, []string{"key: <code\x1b[31m id=\"branch_targe\"\x1b[0m>%[3]s</code>"}, checkLocaleContent([]byte(`key = <code id="branch_targe">%[3]s</code>`)))
|
||||
assert.Equal(t, []string{"key: <a\x1b[31m class=\"ui sh\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="ui sh" href="%[3]s">`)))
|
||||
assert.Equal(t, []string{"key: <a\x1b[31m class=\"js-click-me\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="js-click-me" href="%[3]s">`)))
|
||||
assert.Equal(t, []string{"key: <strong\x1b[31m class=\"branch-target\"\x1b[0m>%[1]s</strong>"}, checkLocaleContent([]byte(`key = <strong class="branch-target">%[1]s</strong>`)))
|
||||
})
|
||||
|
||||
t.Run("General safe tags", func(t *testing.T) {
|
||||
|
@ -38,7 +38,7 @@ func TestLocalizationPolicy(t *testing.T) {
|
|||
assert.Empty(t, checkLocaleContent([]byte("sqlite_helper = File path for the SQLite3 database.<br>Enter an absolute path if you run Forgejo as a service.")))
|
||||
assert.Empty(t, checkLocaleContent([]byte("hi_user_x = Hi <b>%s</b>,")))
|
||||
|
||||
assert.EqualValues(t, []string{"error404: The page you are trying to reach either <strong\x1b[31m title='aaa'\x1b[0m>does not exist</strong> or <strong>you are not authorized</strong> to view it."}, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong title='aaa'>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
|
||||
assert.Equal(t, []string{"error404: The page you are trying to reach either <strong\x1b[31m title='aaa'\x1b[0m>does not exist</strong> or <strong>you are not authorized</strong> to view it."}, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong title='aaa'>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
|
||||
})
|
||||
|
||||
t.Run("<a>", func(t *testing.T) {
|
||||
|
@ -47,20 +47,20 @@ func TestLocalizationPolicy(t *testing.T) {
|
|||
assert.Empty(t, checkLocaleContent([]byte(`webauthn_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a> standard.`)))
|
||||
assert.Empty(t, checkLocaleContent([]byte("issues.closed_at = `closed this issue <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>`")))
|
||||
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com">`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"javascript:alert('1')\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="javascript:alert('1')">`)))
|
||||
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m download\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" download>`)))
|
||||
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m target=\"_self\"\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" target="_self">`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/%s">`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/?q=%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/?q=%s">`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s/open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s/open-redirect">`)))
|
||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s?q=open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s?q=open-redirect">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"javascript:alert('1')\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="javascript:alert('1')">`)))
|
||||
assert.Equal(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m download\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" download>`)))
|
||||
assert.Equal(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m target=\"_self\"\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" target="_self">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"https://example.com/%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/%s">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"https://example.com/?q=%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/?q=%s">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"%s/open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s/open-redirect">`)))
|
||||
assert.Equal(t, []string{"key: \x1b[31m<a href=\"%s?q=open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s?q=open-redirect">`)))
|
||||
})
|
||||
|
||||
t.Run("Escaped HTML characters", func(t *testing.T) {
|
||||
assert.Empty(t, checkLocaleContent([]byte("activity.git_stats_push_to_branch = `إلى %s و\"`")))
|
||||
|
||||
assert.EqualValues(t, []string{"key: و\x1b[31m \x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و `)))
|
||||
assert.Equal(t, []string{"key: و\x1b[31m \x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و `)))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ func TestNextLocalizationPolicy(t *testing.T) {
|
|||
}
|
||||
}`)))
|
||||
|
||||
assert.EqualValues(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent([]byte(`{
|
||||
assert.Equal(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent([]byte(`{
|
||||
"settings": {
|
||||
"hidden_comment_types_description": "\"<not-an-allowed-key> <label>\""
|
||||
}
|
||||
|
@ -87,8 +87,20 @@ func TestNextLocalizationPolicy(t *testing.T) {
|
|||
"settings.hidden_comment_types_description": "Comment types checked here will not be shown inside issue pages. Checking \"Label\" for example removes all \"<user> added/removed <label>\" comments."
|
||||
}`)))
|
||||
|
||||
assert.EqualValues(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent([]byte(`{
|
||||
assert.Equal(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent([]byte(`{
|
||||
"settings.hidden_comment_types_description": "\"<not-an-allowed-key> <label>\""
|
||||
}`)))
|
||||
})
|
||||
|
||||
t.Run("Plural form", func(t *testing.T) {
|
||||
assert.Equal(t, []string{"repo.pulls.title_desc: key = \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleNextContent([]byte(`{"repo.pulls.title_desc": {
|
||||
"few": "key = <a href=\"%s\">",
|
||||
"other": "key = <a href=\"https://example.com\">"
|
||||
}}`)))
|
||||
|
||||
assert.Equal(t, []string{"repo.pulls.title_desc.few: key = \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleNextContent([]byte(`{"repo.pulls.title_desc": {
|
||||
"few": "key = <a href=\"https://example.com\">",
|
||||
"other": "key = <a href=\"%s\">"
|
||||
}}`)))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -216,11 +216,11 @@ func TestAddLdapBindDn(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call updateAuthSource", n)
|
||||
assert.FailNow(t, "should not call updateAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
|
||||
assert.FailNow(t, "should not call getAuthSourceByID", "case: %d", n)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
@ -447,11 +447,11 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call updateAuthSource", n)
|
||||
assert.FailNow(t, "should not call updateAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
|
||||
assert.FailNow(t, "should not call getAuthSourceByID", "case: %d", n)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
@ -898,7 +898,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call createAuthSource", n)
|
||||
assert.FailNow(t, "should not call createAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
|
@ -1288,7 +1288,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call createAuthSource", n)
|
||||
assert.FailNow(t, "should not call createAuthSource", "case: %d", n)
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"forgejo.org/services/doctor"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// CmdDoctor represents the available doctor sub-command.
|
||||
|
@ -120,7 +119,7 @@ func runRecreateTable(ctx *cli.Context) error {
|
|||
|
||||
args := ctx.Args()
|
||||
names := make([]string, 0, ctx.NArg())
|
||||
for i := 0; i < ctx.NArg(); i++ {
|
||||
for i := range ctx.NArg() {
|
||||
names = append(names, args.Get(i))
|
||||
}
|
||||
|
||||
|
@ -130,11 +129,17 @@ func runRecreateTable(ctx *cli.Context) error {
|
|||
}
|
||||
recreateTables := migrate_base.RecreateTables(beans...)
|
||||
|
||||
return db.InitEngineWithMigration(stdCtx, func(x *xorm.Engine) error {
|
||||
if err := migrations.EnsureUpToDate(x); err != nil {
|
||||
return db.InitEngineWithMigration(stdCtx, func(x db.Engine) error {
|
||||
engine, err := db.GetMasterEngine(x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return recreateTables(x)
|
||||
|
||||
if err := migrations.EnsureUpToDate(engine); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return recreateTables(engine)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -143,11 +148,12 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
|||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
||||
|
||||
logFile := ctx.String("log-file")
|
||||
if logFile == "" {
|
||||
switch logFile {
|
||||
case "":
|
||||
return // if no doctor log-file is set, do not show any log from default logger
|
||||
} else if logFile == "-" {
|
||||
case "-":
|
||||
setupConsoleLogger(log.TRACE, colorize, os.Stdout)
|
||||
} else {
|
||||
default:
|
||||
logFile, _ = filepath.Abs(logFile)
|
||||
writeMode := log.WriterMode{Level: log.TRACE, WriterOption: log.WriterFileOption{FileName: logFile}}
|
||||
writer, err := log.NewEventWriter("console-to-file", "file", writeMode)
|
||||
|
|
18
cmd/dump.go
18
cmd/dump.go
|
@ -122,7 +122,6 @@ It can be used for backup and capture Forgejo server image to send to maintainer
|
|||
&cli.StringFlag{
|
||||
Name: "tempdir",
|
||||
Aliases: []string{"t"},
|
||||
Value: os.TempDir(),
|
||||
Usage: "Temporary dir path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
|
@ -288,18 +287,31 @@ func runDump(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
tmpDir := ctx.String("tempdir")
|
||||
if tmpDir == "" {
|
||||
tmpDir, err = os.MkdirTemp("", "forgejo-dump-*")
|
||||
if err != nil {
|
||||
fatal("Failed to create temporary directory: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := util.Remove(tmpDir); err != nil {
|
||||
log.Warn("Failed to remove temporary directory: %s: Error: %v", tmpDir, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
fatal("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
|
||||
dbDump, err := os.CreateTemp(tmpDir, "forgejo-db.sql")
|
||||
if err != nil {
|
||||
fatal("Failed to create tmp file: %v", err)
|
||||
fatal("Failed to create temporary file: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = dbDump.Close()
|
||||
if err := util.Remove(dbDump.Name()); err != nil {
|
||||
log.Warn("Failed to remove temporary file: %s: Error: %v", dbDump.Name(), err)
|
||||
log.Warn("Failed to remove temporary database file: %s: Error: %v", dbDump.Name(), err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -70,10 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
_, jwtSecretBase64, err := generate.NewJwtSecret()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, jwtSecretBase64 := generate.NewJwtSecret()
|
||||
|
||||
fmt.Printf("%s", jwtSecretBase64)
|
||||
|
||||
|
|
11
cmd/hook.go
11
cmd/hook.go
|
@ -168,7 +168,7 @@ func runHookPreReceive(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), true)
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
|
@ -220,10 +220,7 @@ Forgejo or set your environment appropriately.`, "")
|
|||
}
|
||||
}
|
||||
|
||||
supportProcReceive := false
|
||||
if git.CheckGitVersionAtLeast("2.29") == nil {
|
||||
supportProcReceive = true
|
||||
}
|
||||
supportProcReceive := git.CheckGitVersionAtLeast("2.29") == nil
|
||||
|
||||
for scanner.Scan() {
|
||||
// TODO: support news feeds for wiki
|
||||
|
@ -330,7 +327,7 @@ func runHookPostReceive(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), true)
|
||||
|
||||
// First of all run update-server-info no matter what
|
||||
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
|
||||
|
@ -494,7 +491,7 @@ func runHookProcReceive(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), true)
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
|
|
|
@ -71,7 +71,7 @@ func runKeys(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), true)
|
||||
|
||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
||||
|
|
|
@ -122,9 +122,9 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
|||
}
|
||||
executable := filepath.Base(path)
|
||||
|
||||
var subCmdsStandalone []*cli.Command = make([]*cli.Command, 0, 10)
|
||||
var subCmdWithConfig []*cli.Command = make([]*cli.Command, 0, 10)
|
||||
var globalFlags []cli.Flag = make([]cli.Flag, 0, 10)
|
||||
subCmdsStandalone := make([]*cli.Command, 0, 10)
|
||||
subCmdWithConfig := make([]*cli.Command, 0, 10)
|
||||
globalFlags := make([]cli.Flag, 0, 10)
|
||||
|
||||
//
|
||||
// If the executable is forgejo-cli, provide a Forgejo specific CLI
|
||||
|
|
|
@ -132,14 +132,14 @@ func TestCliCmdError(t *testing.T) {
|
|||
r, err := runTestApp(app, "./gitea", "test-cmd")
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, 1, r.ExitCode)
|
||||
assert.Equal(t, "", r.Stdout)
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, 2, r.ExitCode)
|
||||
assert.Equal(t, "", r.Stdout)
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Equal(t, "exit error\n", r.Stderr)
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||
|
@ -147,12 +147,12 @@ func TestCliCmdError(t *testing.T) {
|
|||
require.Error(t, err)
|
||||
assert.Equal(t, 1, r.ExitCode)
|
||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
||||
assert.Equal(t, "", r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
||||
assert.Empty(t, r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
||||
assert.Equal(t, "", r.Stdout)
|
||||
assert.Equal(t, "", r.Stderr)
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Empty(t, r.Stderr)
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ func runShutdown(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
extra := private.Shutdown(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ func runRestart(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
extra := private.Restart(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func runReloadTemplates(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
extra := private.ReloadTemplates(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ func runFlushQueues(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
extra := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ func runProcesses(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
extra := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ func runRemoveLogger(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
logger := c.String("logger")
|
||||
if len(logger) == 0 {
|
||||
logger = log.DEFAULT
|
||||
|
@ -214,7 +214,7 @@ func runAddConnLogger(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
vals := map[string]any{}
|
||||
mode := "conn"
|
||||
vals["net"] = "tcp"
|
||||
|
@ -244,7 +244,7 @@ func runAddFileLogger(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
vals := map[string]any{}
|
||||
mode := "file"
|
||||
if c.IsSet("filename") {
|
||||
|
@ -311,7 +311,7 @@ func runPauseLogging(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
userMsg := private.PauseLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
|
@ -321,7 +321,7 @@ func runResumeLogging(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
userMsg := private.ResumeLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
|
@ -331,7 +331,7 @@ func runReleaseReopenLogging(c *cli.Context) error {
|
|||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
userMsg := private.ReleaseReopenLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
|
@ -340,7 +340,7 @@ func runReleaseReopenLogging(c *cli.Context) error {
|
|||
func runSetLogSQL(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), false)
|
||||
|
||||
extra := private.SetLogSQL(ctx, !c.Bool("off"))
|
||||
return handleCliResponseExtra(extra)
|
||||
|
|
|
@ -36,7 +36,13 @@ func runMigrate(ctx *cli.Context) error {
|
|||
log.Info("Log path: %s", setting.Log.RootPath)
|
||||
log.Info("Configuration file: %s", setting.CustomConf)
|
||||
|
||||
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {
|
||||
if err := db.InitEngineWithMigration(context.Background(), func(dbEngine db.Engine) error {
|
||||
masterEngine, err := db.GetMasterEngine(dbEngine)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return migrations.Migrate(masterEngine)
|
||||
}); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"forgejo.org/modules/storage"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// CmdMigrateStorage represents the available migrate storage sub-command.
|
||||
|
@ -195,7 +196,9 @@ func runMigrateStorage(ctx *cli.Context) error {
|
|||
log.Info("Log path: %s", setting.Log.RootPath)
|
||||
log.Info("Configuration file: %s", setting.CustomConf)
|
||||
|
||||
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {
|
||||
if err := db.InitEngineWithMigration(context.Background(), func(e db.Engine) error {
|
||||
return migrations.Migrate(e.(*xorm.Engine))
|
||||
}); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ func TestMigratePackages(t *testing.T) {
|
|||
entries, err := os.ReadDir(p)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, entries, 2)
|
||||
assert.EqualValues(t, "01", entries[0].Name())
|
||||
assert.EqualValues(t, "tmp", entries[1].Name())
|
||||
assert.Equal(t, "01", entries[0].Name())
|
||||
assert.Equal(t, "tmp", entries[1].Name())
|
||||
}
|
||||
|
||||
func TestMigrateActionsArtifacts(t *testing.T) {
|
||||
|
|
18
cmd/serv.go
18
cmd/serv.go
|
@ -57,19 +57,22 @@ var CmdServ = &cli.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func setup(ctx context.Context, debug bool) {
|
||||
func setup(ctx context.Context, debug, gitNeeded bool) {
|
||||
if debug {
|
||||
setupConsoleLogger(log.TRACE, false, os.Stderr)
|
||||
} else {
|
||||
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
||||
}
|
||||
setting.MustInstalled()
|
||||
// Sanity check to ensure path is not relative, see: https://github.com/go-gitea/gitea/pull/19317
|
||||
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
||||
_ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, err: %v", setting.RepoRootPath, err)
|
||||
return
|
||||
}
|
||||
if err := git.InitSimple(context.Background()); err != nil {
|
||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
||||
if gitNeeded {
|
||||
if err := git.InitSimple(context.Background()); err != nil {
|
||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +136,7 @@ func runServ(c *cli.Context) error {
|
|||
defer cancel()
|
||||
|
||||
// FIXME: This needs to internationalised
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, c.Bool("debug"), true)
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
fmt.Println("Forgejo: SSH has been disabled")
|
||||
|
@ -253,11 +256,12 @@ func runServ(c *cli.Context) error {
|
|||
}
|
||||
|
||||
if verb == lfsAuthenticateVerb {
|
||||
if lfsVerb == "upload" {
|
||||
switch lfsVerb {
|
||||
case "upload":
|
||||
requestedMode = perm.AccessModeWrite
|
||||
} else if lfsVerb == "download" {
|
||||
case "download":
|
||||
requestedMode = perm.AccessModeRead
|
||||
} else {
|
||||
default:
|
||||
return fail(ctx, "Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,9 +198,6 @@ func serveInstalled(ctx *cli.Context) error {
|
|||
for fn := range publicFilesSet.Seq() {
|
||||
log.Error("Found legacy public asset %q in CustomPath. Please move it to %s/public/assets/%s", fn, setting.CustomPath, fn)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(setting.CustomPath, "robots.txt")); err == nil {
|
||||
log.Error(`Found legacy public asset "robots.txt" in CustomPath. Please move it to %s/public/robots.txt`, setting.CustomPath)
|
||||
}
|
||||
|
||||
routers.InitWebInstalled(graceful.GetManager().HammerContext())
|
||||
|
||||
|
|
|
@ -318,8 +318,9 @@ export default tseslint.config(
|
|||
'no-jquery/no-data': [0],
|
||||
'no-jquery/no-deferred': [2],
|
||||
'no-jquery/no-delegate': [2],
|
||||
'no-jquery/no-done-fail': [2],
|
||||
'no-jquery/no-each-collection': [0],
|
||||
'no-jquery/no-each-util': [0],
|
||||
'no-jquery/no-each-util': [2],
|
||||
'no-jquery/no-each': [0],
|
||||
'no-jquery/no-error-shorthand': [2],
|
||||
'no-jquery/no-error': [2],
|
||||
|
@ -331,6 +332,7 @@ export default tseslint.config(
|
|||
'no-jquery/no-find-collection': [0],
|
||||
'no-jquery/no-find-util': [2],
|
||||
'no-jquery/no-find': [0],
|
||||
'no-jquery/no-fx': [2],
|
||||
'no-jquery/no-fx-interval': [2],
|
||||
'no-jquery/no-global-eval': [2],
|
||||
'no-jquery/no-global-selector': [0],
|
||||
|
@ -350,7 +352,7 @@ export default tseslint.config(
|
|||
'no-jquery/no-live': [2],
|
||||
'no-jquery/no-load-shorthand': [2],
|
||||
'no-jquery/no-load': [2],
|
||||
'no-jquery/no-map-collection': [0],
|
||||
'no-jquery/no-map-collection': [2],
|
||||
'no-jquery/no-map-util': [2],
|
||||
'no-jquery/no-map': [2],
|
||||
'no-jquery/no-merge': [2],
|
||||
|
@ -374,12 +376,12 @@ export default tseslint.config(
|
|||
'no-jquery/no-selector-prop': [2],
|
||||
'no-jquery/no-serialize': [2],
|
||||
'no-jquery/no-size': [2],
|
||||
'no-jquery/no-sizzle': [0],
|
||||
'no-jquery/no-sizzle': [2],
|
||||
'no-jquery/no-slide': [2],
|
||||
'no-jquery/no-sub': [2],
|
||||
'no-jquery/no-support': [2],
|
||||
'no-jquery/no-text': [0],
|
||||
'no-jquery/no-trigger': [0],
|
||||
'no-jquery/no-trigger': [2],
|
||||
'no-jquery/no-trim': [2],
|
||||
'no-jquery/no-type': [2],
|
||||
'no-jquery/no-unique': [2],
|
||||
|
|
20
go.mod
20
go.mod
|
@ -2,7 +2,7 @@ module forgejo.org
|
|||
|
||||
go 1.24
|
||||
|
||||
toolchain go1.24.1
|
||||
toolchain go1.24.2
|
||||
|
||||
require (
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.6
|
||||
|
@ -14,7 +14,7 @@ require (
|
|||
code.forgejo.org/go-chi/captcha v1.0.1
|
||||
code.forgejo.org/go-chi/session v1.0.1
|
||||
code.gitea.io/actions-proto-go v0.4.0
|
||||
code.gitea.io/sdk/gitea v0.20.0
|
||||
code.gitea.io/sdk/gitea v0.21.0
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.17.0
|
||||
github.com/42wim/httpsig v1.2.2
|
||||
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/ProtonMail/go-crypto v1.1.6
|
||||
github.com/PuerkitoBio/goquery v1.10.2
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||
github.com/alecthomas/chroma/v2 v2.15.0
|
||||
github.com/alecthomas/chroma/v2 v2.16.0
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.4.4
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
||||
|
@ -49,14 +49,14 @@ require (
|
|||
github.com/go-openapi/spec v0.20.14
|
||||
github.com/go-sql-driver/mysql v1.9.1
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0
|
||||
github.com/go-webauthn/webauthn v0.12.2
|
||||
github.com/go-webauthn/webauthn v0.12.3
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/google/go-github/v64 v64.0.0
|
||||
github.com/google/pprof v0.0.0-20241017200806-017d972448fc
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.2.0
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
|
@ -72,7 +72,7 @@ require (
|
|||
github.com/lib/pq v1.10.9
|
||||
github.com/markbates/goth v1.80.0
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/mattn/go-sqlite3 v1.14.27
|
||||
github.com/meilisearch/meilisearch-go v0.31.0
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
|
@ -103,7 +103,7 @@ require (
|
|||
go.uber.org/mock v0.5.0
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/image v0.25.0
|
||||
golang.org/x/net v0.37.0
|
||||
golang.org/x/net v0.38.0
|
||||
golang.org/x/oauth2 v0.28.0
|
||||
golang.org/x/sync v0.12.0
|
||||
golang.org/x/sys v0.31.0
|
||||
|
@ -170,14 +170,14 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||
|
@ -190,7 +190,7 @@ require (
|
|||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.22.7 // indirect
|
||||
github.com/go-webauthn/x v0.1.19 // indirect
|
||||
github.com/go-webauthn/x v0.1.20 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
||||
|
|
36
go.sum
36
go.sum
|
@ -636,8 +636,8 @@ code.forgejo.org/go-chi/session v1.0.1 h1:RNkcJQZJBqlvJoIFXSth87b3kMFZLDBA18Vcit
|
|||
code.forgejo.org/go-chi/session v1.0.1/go.mod h1:y69sjS984wc7k4xyu77yNE5HKeSlBoQW8VSGdsK7RAs=
|
||||
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||
code.gitea.io/sdk/gitea v0.20.0 h1:Zm/QDwwZK1awoM4AxdjeAQbxolzx2rIP8dDfmKu+KoU=
|
||||
code.gitea.io/sdk/gitea v0.20.0/go.mod h1:faouBHC/zyx5wLgjmRKR62ydyvMzwWf3QnU0bH7Cw6U=
|
||||
code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
|
||||
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
||||
|
@ -691,8 +691,8 @@ github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGW
|
|||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc=
|
||||
github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio=
|
||||
github.com/alecthomas/chroma/v2 v2.16.0 h1:QC5ZMizk67+HzxFDjQ4ASjni5kWBTGiigRG1u23IGvA=
|
||||
github.com/alecthomas/chroma/v2 v2.16.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
|
@ -835,8 +835,8 @@ github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmW
|
|||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||
|
@ -895,8 +895,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
|
||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI=
|
||||
|
@ -967,10 +967,10 @@ github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
|||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0 h1:aRt5qyH2XjzFgCC5NizNs6QrzjO7rC4pQZ1oJpPIdo8=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0/go.mod h1:HHb6Yd8spzm6aFZU6jwBj9qFvVUNNkx5nGbjG4UHeOE=
|
||||
github.com/go-webauthn/webauthn v0.12.2 h1:yLaNPgBUEXDQtWnOjhsGhMMCEWbXwjg/aNkC8riJQI8=
|
||||
github.com/go-webauthn/webauthn v0.12.2/go.mod h1:Q8SZPPj4sZ469fNTcQXxRpzJOdb30jQrn/36FX8jilA=
|
||||
github.com/go-webauthn/x v0.1.19 h1:IUfdHiBRoTdujpBA/14qbrMXQ3LGzYe/PRGWdZcmudg=
|
||||
github.com/go-webauthn/x v0.1.19/go.mod h1:C5arLuTQ3pVHKPw89v7CDGnqAZSZJj+4Jnr40dsn7tk=
|
||||
github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
|
||||
github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY=
|
||||
github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw=
|
||||
github.com/go-webauthn/x v0.1.20/go.mod h1:n/gAc8ssZJGATM0qThE+W+vfgXiMedsWi3wf/C4lld0=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
|
@ -1091,8 +1091,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
|
|||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs=
|
||||
github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
|
@ -1252,8 +1252,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
|||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
|
||||
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/meilisearch/meilisearch-go v0.31.0 h1:yZRhY1qJqdH8h6GFZALGtkDLyj8f9v5aJpsNMyrUmnY=
|
||||
github.com/meilisearch/meilisearch-go v0.31.0/go.mod h1:aNtyuwurDg/ggxQIcKqWH6G9g2ptc8GyY7PLY4zMn/g=
|
||||
github.com/mholt/acmez/v3 v3.1.1 h1:Jh+9uKHkPxUJdxM16q5mOr+G2V0aqkuFtNA28ihCxhQ=
|
||||
|
@ -1647,8 +1647,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
|
@ -24,9 +24,9 @@ func TestActions_RegisterRunner_Token(t *testing.T) {
|
|||
version := "v1.2.3"
|
||||
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, name, runner.Name)
|
||||
assert.Equal(t, name, runner.Name)
|
||||
|
||||
assert.EqualValues(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
|
||||
assert.Equal(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
|
||||
}
|
||||
|
||||
// TestActions_RegisterRunner_TokenUpdate tests that a token's secret is updated
|
||||
|
@ -73,19 +73,19 @@ func TestActions_RegisterRunner_CreateWithLabels(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Check that the returned record has been updated, except for the labels
|
||||
assert.EqualValues(t, ownerID, runner.OwnerID)
|
||||
assert.EqualValues(t, repoID, runner.RepoID)
|
||||
assert.EqualValues(t, name, runner.Name)
|
||||
assert.EqualValues(t, version, runner.Version)
|
||||
assert.EqualValues(t, labelsCopy, runner.AgentLabels)
|
||||
assert.Equal(t, ownerID, runner.OwnerID)
|
||||
assert.Equal(t, repoID, runner.RepoID)
|
||||
assert.Equal(t, name, runner.Name)
|
||||
assert.Equal(t, version, runner.Version)
|
||||
assert.Equal(t, labelsCopy, runner.AgentLabels)
|
||||
|
||||
// Check that whatever is in the DB has been updated, except for the labels
|
||||
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
|
||||
assert.EqualValues(t, ownerID, after.OwnerID)
|
||||
assert.EqualValues(t, repoID, after.RepoID)
|
||||
assert.EqualValues(t, name, after.Name)
|
||||
assert.EqualValues(t, version, after.Version)
|
||||
assert.EqualValues(t, labelsCopy, after.AgentLabels)
|
||||
assert.Equal(t, ownerID, after.OwnerID)
|
||||
assert.Equal(t, repoID, after.RepoID)
|
||||
assert.Equal(t, name, after.Name)
|
||||
assert.Equal(t, version, after.Version)
|
||||
assert.Equal(t, labelsCopy, after.AgentLabels)
|
||||
}
|
||||
|
||||
func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
|
||||
|
@ -100,19 +100,19 @@ func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Check that the returned record has been updated, except for the labels
|
||||
assert.EqualValues(t, ownerID, runner.OwnerID)
|
||||
assert.EqualValues(t, repoID, runner.RepoID)
|
||||
assert.EqualValues(t, name, runner.Name)
|
||||
assert.EqualValues(t, version, runner.Version)
|
||||
assert.EqualValues(t, []string{}, runner.AgentLabels)
|
||||
assert.Equal(t, ownerID, runner.OwnerID)
|
||||
assert.Equal(t, repoID, runner.RepoID)
|
||||
assert.Equal(t, name, runner.Name)
|
||||
assert.Equal(t, version, runner.Version)
|
||||
assert.Equal(t, []string{}, runner.AgentLabels)
|
||||
|
||||
// Check that whatever is in the DB has been updated, except for the labels
|
||||
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
|
||||
assert.EqualValues(t, ownerID, after.OwnerID)
|
||||
assert.EqualValues(t, repoID, after.RepoID)
|
||||
assert.EqualValues(t, name, after.Name)
|
||||
assert.EqualValues(t, version, after.Version)
|
||||
assert.EqualValues(t, []string{}, after.AgentLabels)
|
||||
assert.Equal(t, ownerID, after.OwnerID)
|
||||
assert.Equal(t, repoID, after.RepoID)
|
||||
assert.Equal(t, name, after.Name)
|
||||
assert.Equal(t, version, after.Version)
|
||||
assert.Equal(t, []string{}, after.AgentLabels)
|
||||
}
|
||||
|
||||
func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
|
||||
|
@ -132,19 +132,19 @@ func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Check that the returned record has been updated
|
||||
assert.EqualValues(t, newOwnerID, runner.OwnerID)
|
||||
assert.EqualValues(t, newRepoID, runner.RepoID)
|
||||
assert.EqualValues(t, newName, runner.Name)
|
||||
assert.EqualValues(t, newVersion, runner.Version)
|
||||
assert.EqualValues(t, labelsCopy, runner.AgentLabels)
|
||||
assert.Equal(t, newOwnerID, runner.OwnerID)
|
||||
assert.Equal(t, newRepoID, runner.RepoID)
|
||||
assert.Equal(t, newName, runner.Name)
|
||||
assert.Equal(t, newVersion, runner.Version)
|
||||
assert.Equal(t, labelsCopy, runner.AgentLabels)
|
||||
|
||||
// Check that whatever is in the DB has been updated
|
||||
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||
assert.EqualValues(t, newOwnerID, after.OwnerID)
|
||||
assert.EqualValues(t, newRepoID, after.RepoID)
|
||||
assert.EqualValues(t, newName, after.Name)
|
||||
assert.EqualValues(t, newVersion, after.Version)
|
||||
assert.EqualValues(t, labelsCopy, after.AgentLabels)
|
||||
assert.Equal(t, newOwnerID, after.OwnerID)
|
||||
assert.Equal(t, newRepoID, after.RepoID)
|
||||
assert.Equal(t, newName, after.Name)
|
||||
assert.Equal(t, newVersion, after.Version)
|
||||
assert.Equal(t, labelsCopy, after.AgentLabels)
|
||||
}
|
||||
|
||||
func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
|
||||
|
@ -162,17 +162,17 @@ func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Check that the returned record has been updated, except for the labels
|
||||
assert.EqualValues(t, newOwnerID, runner.OwnerID)
|
||||
assert.EqualValues(t, newRepoID, runner.RepoID)
|
||||
assert.EqualValues(t, newName, runner.Name)
|
||||
assert.EqualValues(t, newVersion, runner.Version)
|
||||
assert.EqualValues(t, before.AgentLabels, runner.AgentLabels)
|
||||
assert.Equal(t, newOwnerID, runner.OwnerID)
|
||||
assert.Equal(t, newRepoID, runner.RepoID)
|
||||
assert.Equal(t, newName, runner.Name)
|
||||
assert.Equal(t, newVersion, runner.Version)
|
||||
assert.Equal(t, before.AgentLabels, runner.AgentLabels)
|
||||
|
||||
// Check that whatever is in the DB has been updated, except for the labels
|
||||
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||
assert.EqualValues(t, newOwnerID, after.OwnerID)
|
||||
assert.EqualValues(t, newRepoID, after.RepoID)
|
||||
assert.EqualValues(t, newName, after.Name)
|
||||
assert.EqualValues(t, newVersion, after.Version)
|
||||
assert.EqualValues(t, before.AgentLabels, after.AgentLabels)
|
||||
assert.Equal(t, newOwnerID, after.OwnerID)
|
||||
assert.Equal(t, newRepoID, after.RepoID)
|
||||
assert.Equal(t, newName, after.Name)
|
||||
assert.Equal(t, newVersion, after.Version)
|
||||
assert.Equal(t, before.AgentLabels, after.AgentLabels)
|
||||
}
|
||||
|
|
|
@ -87,9 +87,10 @@ func (r *ActionRunner) BelongsToOwnerType() types.OwnerType {
|
|||
return types.OwnerTypeRepository
|
||||
}
|
||||
if r.OwnerID != 0 {
|
||||
if r.Owner.Type == user_model.UserTypeOrganization {
|
||||
switch r.Owner.Type {
|
||||
case user_model.UserTypeOrganization:
|
||||
return types.OwnerTypeOrganization
|
||||
} else if r.Owner.Type == user_model.UserTypeIndividual {
|
||||
case user_model.UserTypeIndividual:
|
||||
return types.OwnerTypeIndividual
|
||||
}
|
||||
}
|
||||
|
@ -167,12 +168,7 @@ func (r *ActionRunner) GenerateToken() (err error) {
|
|||
// UpdateSecret updates the hash based on the specified token. It does not
|
||||
// ensure that the runner's UUID matches the first 16 bytes of the token.
|
||||
func (r *ActionRunner) UpdateSecret(token string) error {
|
||||
saltBytes, err := util.CryptoRandomBytes(16)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CryptoRandomBytes %v", err)
|
||||
}
|
||||
|
||||
salt := hex.EncodeToString(saltBytes)
|
||||
salt := hex.EncodeToString(util.CryptoRandomBytes(16))
|
||||
|
||||
r.Token = token
|
||||
r.TokenSalt = salt
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestGetLatestRunnerToken(t *testing.T) {
|
|||
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
|
||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedToken, token)
|
||||
assert.Equal(t, expectedToken, token)
|
||||
}
|
||||
|
||||
func TestNewRunnerToken(t *testing.T) {
|
||||
|
@ -27,7 +27,7 @@ func TestNewRunnerToken(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedToken, token)
|
||||
assert.Equal(t, expectedToken, token)
|
||||
}
|
||||
|
||||
func TestUpdateRunnerToken(t *testing.T) {
|
||||
|
@ -37,5 +37,5 @@ func TestUpdateRunnerToken(t *testing.T) {
|
|||
require.NoError(t, UpdateRunnerToken(db.DefaultContext, token))
|
||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedToken, token)
|
||||
assert.Equal(t, expectedToken, token)
|
||||
}
|
||||
|
|
|
@ -22,11 +22,7 @@ func generateSaltedToken() (string, string, string, string, error) {
|
|||
if err != nil {
|
||||
return "", "", "", "", err
|
||||
}
|
||||
buf, err := util.CryptoRandomBytes(20)
|
||||
if err != nil {
|
||||
return "", "", "", "", err
|
||||
}
|
||||
token := hex.EncodeToString(buf)
|
||||
token := hex.EncodeToString(util.CryptoRandomBytes(20))
|
||||
hash := auth_model.HashToken(token, salt)
|
||||
return token, salt, hash, token[len(token)-8:], nil
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestGetFeeds(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
if assert.Len(t, actions, 1) {
|
||||
assert.EqualValues(t, 1, actions[0].ID)
|
||||
assert.EqualValues(t, user.ID, actions[0].UserID)
|
||||
assert.Equal(t, user.ID, actions[0].UserID)
|
||||
}
|
||||
assert.Equal(t, int64(1), count)
|
||||
|
||||
|
@ -133,7 +133,7 @@ func TestGetFeeds2(t *testing.T) {
|
|||
assert.Len(t, actions, 1)
|
||||
if assert.Len(t, actions, 1) {
|
||||
assert.EqualValues(t, 2, actions[0].ID)
|
||||
assert.EqualValues(t, org.ID, actions[0].UserID)
|
||||
assert.Equal(t, org.ID, actions[0].UserID)
|
||||
}
|
||||
assert.Equal(t, int64(1), count)
|
||||
|
||||
|
@ -291,7 +291,7 @@ func TestDeleteIssueActions(t *testing.T) {
|
|||
|
||||
// load an issue
|
||||
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 4})
|
||||
assert.NotEqualValues(t, issue.ID, issue.Index) // it needs to use different ID/Index to test the DeleteIssueActions to delete some actions by IssueIndex
|
||||
assert.NotEqual(t, issue.ID, issue.Index) // it needs to use different ID/Index to test the DeleteIssueActions to delete some actions by IssueIndex
|
||||
|
||||
// insert a comment
|
||||
err := db.Insert(db.DefaultContext, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
|
||||
|
|
|
@ -107,7 +107,7 @@ func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, n
|
|||
return err
|
||||
}
|
||||
toNotify.AddMultiple(issueWatches...)
|
||||
if !(issue.IsPull && issues_model.HasWorkInProgressPrefix(issue.Title)) {
|
||||
if !issue.IsPull || !issues_model.HasWorkInProgressPrefix(issue.Title) {
|
||||
repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -45,11 +45,11 @@ func TestNotificationsForUser(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
if assert.Len(t, notfs, 3) {
|
||||
assert.EqualValues(t, 5, notfs[0].ID)
|
||||
assert.EqualValues(t, user.ID, notfs[0].UserID)
|
||||
assert.Equal(t, user.ID, notfs[0].UserID)
|
||||
assert.EqualValues(t, 4, notfs[1].ID)
|
||||
assert.EqualValues(t, user.ID, notfs[1].UserID)
|
||||
assert.Equal(t, user.ID, notfs[1].UserID)
|
||||
assert.EqualValues(t, 2, notfs[2].ID)
|
||||
assert.EqualValues(t, user.ID, notfs[2].UserID)
|
||||
assert.Equal(t, user.ID, notfs[2].UserID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ func TestNotification_GetRepo(t *testing.T) {
|
|||
repo, err := notf.GetRepo(db.DefaultContext)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, repo, notf.Repository)
|
||||
assert.EqualValues(t, notf.RepoID, repo.ID)
|
||||
assert.Equal(t, notf.RepoID, repo.ID)
|
||||
}
|
||||
|
||||
func TestNotification_GetIssue(t *testing.T) {
|
||||
|
@ -68,7 +68,7 @@ func TestNotification_GetIssue(t *testing.T) {
|
|||
issue, err := notf.GetIssue(db.DefaultContext)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, issue, notf.Issue)
|
||||
assert.EqualValues(t, notf.IssueID, issue.ID)
|
||||
assert.Equal(t, notf.IssueID, issue.ID)
|
||||
}
|
||||
|
||||
func TestGetNotificationCount(t *testing.T) {
|
||||
|
@ -137,5 +137,5 @@ func TestSetIssueReadBy(t *testing.T) {
|
|||
|
||||
nt, err := activities_model.GetIssueNotification(db.DefaultContext, user.ID, issue.ID)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, activities_model.NotificationStatusRead, nt.Status)
|
||||
assert.Equal(t, activities_model.NotificationStatusRead, nt.Status)
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ func TestGetActivityStats(t *testing.T) {
|
|||
stats, err := GetActivityStats(db.DefaultContext, repo, time.Unix(0, 0), true, true, true, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, 2, stats.ActiveIssueCount())
|
||||
assert.EqualValues(t, 2, stats.OpenedIssueCount())
|
||||
assert.EqualValues(t, 0, stats.ClosedIssueCount())
|
||||
assert.EqualValues(t, 3, stats.ActivePRCount())
|
||||
assert.Equal(t, 2, stats.ActiveIssueCount())
|
||||
assert.Equal(t, 2, stats.OpenedIssueCount())
|
||||
assert.Equal(t, 0, stats.ClosedIssueCount())
|
||||
assert.Equal(t, 3, stats.ActivePRCount())
|
||||
}
|
||||
|
|
|
@ -293,7 +293,7 @@ heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, keys, 1)
|
||||
assert.Len(t, keys[0].Emails, 1)
|
||||
assert.EqualValues(t, "no-reply@golang.com", keys[0].Emails[0].Email)
|
||||
assert.Equal(t, "no-reply@golang.com", keys[0].Emails[0].Email)
|
||||
|
||||
primaryKeyID := "D68172F48E9C5283"
|
||||
// Assert primary key
|
||||
|
|
|
@ -44,7 +44,7 @@ func Test_SSHParsePublicKey(t *testing.T) {
|
|||
keyTypeN, lengthN, err := SSHNativeParsePublicKey(tc.content)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.keyType, keyTypeN)
|
||||
assert.EqualValues(t, tc.length, lengthN)
|
||||
assert.Equal(t, tc.length, lengthN)
|
||||
})
|
||||
if tc.skipSSHKeygen {
|
||||
return
|
||||
|
@ -54,19 +54,19 @@ func Test_SSHParsePublicKey(t *testing.T) {
|
|||
if err != nil {
|
||||
// Some servers do not support ecdsa format.
|
||||
if !strings.Contains(err.Error(), "line 1 too long:") {
|
||||
assert.FailNow(t, "%v", err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, tc.keyType, keyTypeK)
|
||||
assert.EqualValues(t, tc.length, lengthK)
|
||||
assert.Equal(t, tc.length, lengthK)
|
||||
})
|
||||
t.Run("SSHParseKeyNative", func(t *testing.T) {
|
||||
keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content)
|
||||
if err != nil {
|
||||
assert.FailNow(t, "%v", err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tc.keyType, keyTypeK)
|
||||
assert.EqualValues(t, tc.length, lengthK)
|
||||
assert.Equal(t, tc.length, lengthK)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -111,12 +111,8 @@ func generateAccessToken(t *AccessToken) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
token, err := util.CryptoRandomBytes(20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.TokenSalt = salt
|
||||
t.Token = hex.EncodeToString(token)
|
||||
t.Token = hex.EncodeToString(util.CryptoRandomBytes(20))
|
||||
t.TokenHash = HashToken(t.Token, t.TokenSalt)
|
||||
t.TokenLastEight = t.Token[len(t.Token)-8:]
|
||||
return nil
|
||||
|
|
|
@ -63,10 +63,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
|
|||
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp, purpose AuthorizationPurpose) (lookupKey, validator string, err error) {
|
||||
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
|
||||
// and the other 32 bytes will be used for the validator.
|
||||
rBytes, err := util.CryptoRandomBytes(64)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
rBytes := util.CryptoRandomBytes(64)
|
||||
hexEncoded := hex.EncodeToString(rBytes)
|
||||
validator, lookupKey = hexEncoded[64:], hexEncoded[:64]
|
||||
|
||||
|
|
|
@ -184,13 +184,9 @@ var base32Lower = base32.NewEncoding(lowerBase32Chars).WithPadding(base32.NoPadd
|
|||
|
||||
// GenerateClientSecret will generate the client secret and returns the plaintext and saves the hash at the database
|
||||
func (app *OAuth2Application) GenerateClientSecret(ctx context.Context) (string, error) {
|
||||
rBytes, err := util.CryptoRandomBytes(32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Add a prefix to the base32, this is in order to make it easier
|
||||
// for code scanners to grab sensitive tokens.
|
||||
clientSecret := "gto_" + base32Lower.EncodeToString(rBytes)
|
||||
clientSecret := "gto_" + base32Lower.EncodeToString(util.CryptoRandomBytes(32))
|
||||
|
||||
hashedSecret, err := bcrypt.GenerateFromPassword([]byte(clientSecret), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
|
@ -475,13 +471,9 @@ func (grant *OAuth2Grant) TableName() string {
|
|||
|
||||
// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database
|
||||
func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) {
|
||||
rBytes, err := util.CryptoRandomBytes(32)
|
||||
if err != nil {
|
||||
return &OAuth2AuthorizationCode{}, err
|
||||
}
|
||||
// Add a prefix to the base32, this is in order to make it easier
|
||||
// for code scanners to grab sensitive tokens.
|
||||
codeSecret := "gta_" + base32Lower.EncodeToString(rBytes)
|
||||
codeSecret := "gta_" + base32Lower.EncodeToString(util.CryptoRandomBytes(32))
|
||||
|
||||
code = &OAuth2AuthorizationCode{
|
||||
Grant: grant,
|
||||
|
|
|
@ -130,7 +130,7 @@ func TestOAuth2Application_CreateGrant(t *testing.T) {
|
|||
assert.NotNil(t, grant)
|
||||
assert.Equal(t, int64(2), grant.UserID)
|
||||
assert.Equal(t, int64(1), grant.ApplicationID)
|
||||
assert.Equal(t, "", grant.Scope)
|
||||
assert.Empty(t, grant.Scope)
|
||||
}
|
||||
|
||||
//////////////////// Grant
|
||||
|
@ -271,7 +271,7 @@ func TestOAuth2AuthorizationCode_TableName(t *testing.T) {
|
|||
func TestBuiltinApplicationsClientIDs(t *testing.T) {
|
||||
clientIDs := auth_model.BuiltinApplicationsClientIDs()
|
||||
slices.Sort(clientIDs)
|
||||
assert.EqualValues(t, []string{"a4792ccc-144e-407e-86c9-5e7d8d9c3269", "d57cb8c4-630c-4168-8324-ec79935e18d4", "e90ee53c-94e2-48ac-9358-a874fb9e0662"}, clientIDs)
|
||||
assert.Equal(t, []string{"a4792ccc-144e-407e-86c9-5e7d8d9c3269", "d57cb8c4-630c-4168-8324-ec79935e18d4", "e90ee53c-94e2-48ac-9358-a874fb9e0662"}, clientIDs)
|
||||
}
|
||||
|
||||
func TestOrphanedOAuth2Applications(t *testing.T) {
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestAuthSession(t *testing.T) {
|
|||
// New session is created.
|
||||
sess, err := auth.ReadSession(db.DefaultContext, key)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, key, sess.Key)
|
||||
assert.Equal(t, key, sess.Key)
|
||||
assert.Empty(t, sess.Data)
|
||||
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
||||
|
||||
|
@ -67,8 +67,8 @@ func TestAuthSession(t *testing.T) {
|
|||
// Ensure data is updated and expiry is set from the update session call.
|
||||
sess, err := auth.ReadSession(db.DefaultContext, key)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, key, sess.Key)
|
||||
assert.EqualValues(t, data, sess.Data)
|
||||
assert.Equal(t, key, sess.Key)
|
||||
assert.Equal(t, data, sess.Data)
|
||||
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
||||
|
||||
timeutil.MockSet(now)
|
||||
|
|
|
@ -61,17 +61,13 @@ func init() {
|
|||
}
|
||||
|
||||
// GenerateScratchToken recreates the scratch token the user is using.
|
||||
func (t *TwoFactor) GenerateScratchToken() (string, error) {
|
||||
tokenBytes, err := util.CryptoRandomBytes(6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
func (t *TwoFactor) GenerateScratchToken() string {
|
||||
// these chars are specially chosen, avoid ambiguous chars like `0`, `O`, `1`, `I`.
|
||||
const base32Chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
||||
token := base32.NewEncoding(base32Chars).WithPadding(base32.NoPadding).EncodeToString(tokenBytes)
|
||||
token := base32.NewEncoding(base32Chars).WithPadding(base32.NoPadding).EncodeToString(util.CryptoRandomBytes(6))
|
||||
t.ScratchSalt, _ = util.CryptoRandomString(10)
|
||||
t.ScratchHash = HashToken(token, t.ScratchSalt)
|
||||
return token, nil
|
||||
return token
|
||||
}
|
||||
|
||||
// HashToken return the hashable salt
|
||||
|
|
|
@ -95,34 +95,70 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// newXORMEngine returns a new XORM engine from the configuration
|
||||
func newXORMEngine() (*xorm.Engine, error) {
|
||||
connStr, err := setting.DBConnStr()
|
||||
// newXORMEngineGroup creates an xorm.EngineGroup (with one master and one or more slaves).
|
||||
// It assumes you have separate master and slave DSNs defined via the settings package.
|
||||
func newXORMEngineGroup() (Engine, error) {
|
||||
// Retrieve master DSN from settings.
|
||||
masterConnStr, err := setting.DBMasterConnStr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to determine master DSN: %w", err)
|
||||
}
|
||||
|
||||
var engine *xorm.Engine
|
||||
|
||||
var masterEngine *xorm.Engine
|
||||
// For PostgreSQL: if a schema is provided, we use the special "postgresschema" driver.
|
||||
if setting.Database.Type.IsPostgreSQL() && len(setting.Database.Schema) > 0 {
|
||||
// OK whilst we sort out our schema issues - create a schema aware postgres
|
||||
registerPostgresSchemaDriver()
|
||||
engine, err = xorm.NewEngine("postgresschema", connStr)
|
||||
masterEngine, err = xorm.NewEngine("postgresschema", masterConnStr)
|
||||
} else {
|
||||
engine, err = xorm.NewEngine(setting.Database.Type.String(), connStr)
|
||||
masterEngine, err = xorm.NewEngine(setting.Database.Type.String(), masterConnStr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to create master engine: %w", err)
|
||||
}
|
||||
if setting.Database.Type.IsMySQL() {
|
||||
engine.Dialect().SetParams(map[string]string{"rowFormat": "DYNAMIC"})
|
||||
masterEngine.Dialect().SetParams(map[string]string{"rowFormat": "DYNAMIC"})
|
||||
}
|
||||
engine.SetSchema(setting.Database.Schema)
|
||||
return engine, nil
|
||||
masterEngine.SetSchema(setting.Database.Schema)
|
||||
|
||||
slaveConnStrs, err := setting.DBSlaveConnStrs()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load slave DSNs: %w", err)
|
||||
}
|
||||
|
||||
var slaveEngines []*xorm.Engine
|
||||
// Iterate over all slave DSNs and create engines
|
||||
for _, dsn := range slaveConnStrs {
|
||||
slaveEngine, err := xorm.NewEngine(setting.Database.Type.String(), dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create slave engine for dsn %q: %w", dsn, err)
|
||||
}
|
||||
if setting.Database.Type.IsMySQL() {
|
||||
slaveEngine.Dialect().SetParams(map[string]string{"rowFormat": "DYNAMIC"})
|
||||
}
|
||||
slaveEngine.SetSchema(setting.Database.Schema)
|
||||
slaveEngines = append(slaveEngines, slaveEngine)
|
||||
}
|
||||
|
||||
policy := setting.BuildLoadBalancePolicy(&setting.Database, slaveEngines)
|
||||
|
||||
// Create the EngineGroup using the selected policy
|
||||
group, err := xorm.NewEngineGroup(masterEngine, slaveEngines, policy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create engine group: %w", err)
|
||||
}
|
||||
return engineGroupWrapper{group}, nil
|
||||
}
|
||||
|
||||
// SyncAllTables sync the schemas of all tables, is required by unit test code
|
||||
type engineGroupWrapper struct {
|
||||
*xorm.EngineGroup
|
||||
}
|
||||
|
||||
func (w engineGroupWrapper) AddHook(hook contexts.Hook) bool {
|
||||
w.EngineGroup.AddHook(hook)
|
||||
return true
|
||||
}
|
||||
|
||||
// SyncAllTables sync the schemas of all tables
|
||||
func SyncAllTables() error {
|
||||
_, err := x.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
|
||||
WarnIfDatabaseColumnMissed: true,
|
||||
|
@ -130,52 +166,61 @@ func SyncAllTables() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
|
||||
// InitEngine initializes the xorm EngineGroup and sets it as db.DefaultContext
|
||||
func InitEngine(ctx context.Context) error {
|
||||
xormEngine, err := newXORMEngine()
|
||||
xormEngine, err := newXORMEngineGroup()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to database: %w", err)
|
||||
}
|
||||
// Try to cast to the concrete type to access diagnostic methods
|
||||
if eng, ok := xormEngine.(engineGroupWrapper); ok {
|
||||
eng.SetMapper(names.GonicMapper{})
|
||||
// WARNING: for serv command, MUST remove the output to os.Stdout,
|
||||
// so use a log file instead of printing to stdout.
|
||||
eng.SetLogger(NewXORMLogger(setting.Database.LogSQL))
|
||||
eng.ShowSQL(setting.Database.LogSQL)
|
||||
eng.SetMaxOpenConns(setting.Database.MaxOpenConns)
|
||||
eng.SetMaxIdleConns(setting.Database.MaxIdleConns)
|
||||
eng.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
|
||||
eng.SetConnMaxIdleTime(setting.Database.ConnMaxIdleTime)
|
||||
eng.SetDefaultContext(ctx)
|
||||
|
||||
xormEngine.SetMapper(names.GonicMapper{})
|
||||
// WARNING: for serv command, MUST remove the output to os.stdout,
|
||||
// so use log file to instead print to stdout.
|
||||
xormEngine.SetLogger(NewXORMLogger(setting.Database.LogSQL))
|
||||
xormEngine.ShowSQL(setting.Database.LogSQL)
|
||||
xormEngine.SetMaxOpenConns(setting.Database.MaxOpenConns)
|
||||
xormEngine.SetMaxIdleConns(setting.Database.MaxIdleConns)
|
||||
xormEngine.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
|
||||
xormEngine.SetConnMaxIdleTime(setting.Database.ConnMaxIdleTime)
|
||||
xormEngine.SetDefaultContext(ctx)
|
||||
if setting.Database.SlowQueryThreshold > 0 {
|
||||
eng.AddHook(&SlowQueryHook{
|
||||
Treshold: setting.Database.SlowQueryThreshold,
|
||||
Logger: log.GetLogger("xorm"),
|
||||
})
|
||||
}
|
||||
|
||||
if setting.Database.SlowQueryThreshold > 0 {
|
||||
xormEngine.AddHook(&SlowQueryHook{
|
||||
Treshold: setting.Database.SlowQueryThreshold,
|
||||
Logger: log.GetLogger("xorm"),
|
||||
errorLogger := log.GetLogger("xorm")
|
||||
if setting.IsInTesting {
|
||||
errorLogger = log.GetLogger(log.DEFAULT)
|
||||
}
|
||||
|
||||
eng.AddHook(&ErrorQueryHook{
|
||||
Logger: errorLogger,
|
||||
})
|
||||
|
||||
eng.AddHook(&TracingHook{})
|
||||
|
||||
SetDefaultEngine(ctx, eng)
|
||||
} else {
|
||||
// Fallback: if type assertion fails, set default engine without extended diagnostics
|
||||
SetDefaultEngine(ctx, xormEngine)
|
||||
}
|
||||
|
||||
errorLogger := log.GetLogger("xorm")
|
||||
if setting.IsInTesting {
|
||||
errorLogger = log.GetLogger(log.DEFAULT)
|
||||
}
|
||||
|
||||
xormEngine.AddHook(&ErrorQueryHook{
|
||||
Logger: errorLogger,
|
||||
})
|
||||
|
||||
xormEngine.AddHook(&TracingHook{})
|
||||
|
||||
SetDefaultEngine(ctx, xormEngine)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDefaultEngine sets the default engine for db
|
||||
func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) {
|
||||
x = eng
|
||||
// SetDefaultEngine sets the default engine for db.
|
||||
func SetDefaultEngine(ctx context.Context, eng Engine) {
|
||||
masterEngine, err := GetMasterEngine(eng)
|
||||
if err == nil {
|
||||
x = masterEngine
|
||||
}
|
||||
|
||||
DefaultContext = &Context{
|
||||
Context: ctx,
|
||||
e: x,
|
||||
e: eng,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,12 +236,12 @@ func UnsetDefaultEngine() {
|
|||
DefaultContext = nil
|
||||
}
|
||||
|
||||
// InitEngineWithMigration initializes a new xorm.Engine and sets it as the db.DefaultContext
|
||||
// InitEngineWithMigration initializes a new xorm EngineGroup, runs migrations, and sets it as db.DefaultContext
|
||||
// This function must never call .Sync() if the provided migration function fails.
|
||||
// When called from the "doctor" command, the migration function is a version check
|
||||
// that prevents the doctor from fixing anything in the database if the migration level
|
||||
// is different from the expected value.
|
||||
func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
|
||||
func InitEngineWithMigration(ctx context.Context, migrateFunc func(Engine) error) (err error) {
|
||||
if err = InitEngine(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -230,14 +275,14 @@ func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine)
|
|||
return nil
|
||||
}
|
||||
|
||||
// NamesToBean return a list of beans or an error
|
||||
// NamesToBean returns a list of beans given names
|
||||
func NamesToBean(names ...string) ([]any, error) {
|
||||
beans := []any{}
|
||||
if len(names) == 0 {
|
||||
beans = append(beans, tables...)
|
||||
return beans, nil
|
||||
}
|
||||
// Need to map provided names to beans...
|
||||
// Map provided names to beans
|
||||
beanMap := make(map[string]any)
|
||||
for _, bean := range tables {
|
||||
beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean
|
||||
|
@ -259,7 +304,7 @@ func NamesToBean(names ...string) ([]any, error) {
|
|||
return beans, nil
|
||||
}
|
||||
|
||||
// DumpDatabase dumps all data from database according the special database SQL syntax to file system.
|
||||
// DumpDatabase dumps all data from database using special SQL syntax to the file system.
|
||||
func DumpDatabase(filePath, dbType string) error {
|
||||
var tbs []*schemas.Table
|
||||
for _, t := range tables {
|
||||
|
@ -295,29 +340,33 @@ func MaxBatchInsertSize(bean any) int {
|
|||
return 999 / len(t.ColumnsSeq())
|
||||
}
|
||||
|
||||
// IsTableNotEmpty returns true if table has at least one record
|
||||
// IsTableNotEmpty returns true if the table has at least one record
|
||||
func IsTableNotEmpty(beanOrTableName any) (bool, error) {
|
||||
return x.Table(beanOrTableName).Exist()
|
||||
}
|
||||
|
||||
// DeleteAllRecords will delete all the records of this table
|
||||
// DeleteAllRecords deletes all records in the given table.
|
||||
func DeleteAllRecords(tableName string) error {
|
||||
_, err := x.Exec(fmt.Sprintf("DELETE FROM %s", tableName))
|
||||
return err
|
||||
}
|
||||
|
||||
// GetMaxID will return max id of the table
|
||||
// GetMaxID returns the maximum id in the table
|
||||
func GetMaxID(beanOrTableName any) (maxID int64, err error) {
|
||||
_, err = x.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
|
||||
return maxID, err
|
||||
}
|
||||
|
||||
func SetLogSQL(ctx context.Context, on bool) {
|
||||
e := GetEngine(ctx)
|
||||
if x, ok := e.(*xorm.Engine); ok {
|
||||
x.ShowSQL(on)
|
||||
} else if sess, ok := e.(*xorm.Session); ok {
|
||||
ctxEngine := GetEngine(ctx)
|
||||
|
||||
if sess, ok := ctxEngine.(*xorm.Session); ok {
|
||||
sess.Engine().ShowSQL(on)
|
||||
} else if wrapper, ok := ctxEngine.(engineGroupWrapper); ok {
|
||||
// Handle engineGroupWrapper directly
|
||||
wrapper.ShowSQL(on)
|
||||
} else if masterEngine, err := GetMasterEngine(ctxEngine); err == nil {
|
||||
masterEngine.ShowSQL(on)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,3 +423,18 @@ func (h *ErrorQueryHook) AfterProcess(c *contexts.ContextHook) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMasterEngine extracts the master xorm.Engine from the provided xorm.Engine.
|
||||
// This handles both direct xorm.Engine cases and engines that implement a Master() method.
|
||||
func GetMasterEngine(x Engine) (*xorm.Engine, error) {
|
||||
if getter, ok := x.(interface{ Master() *xorm.Engine }); ok {
|
||||
return getter.Master(), nil
|
||||
}
|
||||
|
||||
engine, ok := x.(*xorm.Engine)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported engine type: %T", x)
|
||||
}
|
||||
|
||||
return engine, nil
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestDeleteOrphanedObjects(t *testing.T) {
|
|||
|
||||
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, countBefore, countAfter)
|
||||
assert.Equal(t, countBefore, countAfter)
|
||||
}
|
||||
|
||||
func TestPrimaryKeys(t *testing.T) {
|
||||
|
|
|
@ -33,10 +33,11 @@ func getCurrentResourceIndex(ctx context.Context, tableName string, groupID int6
|
|||
|
||||
func TestSyncMaxResourceIndex(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
xe := unittest.GetXORMEngine()
|
||||
xe, err := unittest.GetXORMEngine()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, xe.Sync(&TestIndex{}))
|
||||
|
||||
err := db.SyncMaxResourceIndex(db.DefaultContext, "test_index", 10, 51)
|
||||
err = db.SyncMaxResourceIndex(db.DefaultContext, "test_index", 10, 51)
|
||||
require.NoError(t, err)
|
||||
|
||||
// sync new max index
|
||||
|
@ -88,7 +89,8 @@ func TestSyncMaxResourceIndex(t *testing.T) {
|
|||
|
||||
func TestGetNextResourceIndex(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
xe := unittest.GetXORMEngine()
|
||||
xe, err := unittest.GetXORMEngine()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, xe.Sync(&TestIndex{}))
|
||||
|
||||
// create a new record
|
||||
|
|
|
@ -6,12 +6,10 @@ package install
|
|||
import (
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/modules/setting"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func getXORMEngine() *xorm.Engine {
|
||||
return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine)
|
||||
func getXORMEngine() db.Engine {
|
||||
return db.DefaultContext.(*db.Context).Engine()
|
||||
}
|
||||
|
||||
// CheckDatabaseConnection checks the database connection
|
||||
|
|
|
@ -17,7 +17,8 @@ import (
|
|||
|
||||
func TestIterate(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
xe := unittest.GetXORMEngine()
|
||||
xe, err := unittest.GetXORMEngine()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
|
||||
|
||||
cnt, err := db.GetEngine(db.DefaultContext).Count(&repo_model.RepoUnit{})
|
||||
|
|
|
@ -29,11 +29,12 @@ func (opts mockListOptions) ToConds() builder.Cond {
|
|||
|
||||
func TestFind(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
xe := unittest.GetXORMEngine()
|
||||
xe, err := unittest.GetXORMEngine()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
|
||||
|
||||
var repoUnitCount int
|
||||
_, err := db.GetEngine(db.DefaultContext).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount)
|
||||
_, err = db.GetEngine(db.DefaultContext).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, repoUnitCount)
|
||||
|
||||
|
@ -48,6 +49,6 @@ func TestFind(t *testing.T) {
|
|||
|
||||
repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, opts)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, cnt, newCnt)
|
||||
assert.Equal(t, cnt, newCnt)
|
||||
assert.Len(t, repoUnits, repoUnitCount)
|
||||
}
|
||||
|
|
|
@ -32,15 +32,15 @@ func TestDbfsBasic(t *testing.T) {
|
|||
|
||||
n, err := f.Write([]byte("0123456789")) // blocks: 0123 4567 89
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 10, n)
|
||||
assert.Equal(t, 10, n)
|
||||
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
require.NoError(t, err)
|
||||
|
||||
buf, err := io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 10, n)
|
||||
assert.EqualValues(t, "0123456789", string(buf))
|
||||
assert.Equal(t, 10, n)
|
||||
assert.Equal(t, "0123456789", string(buf))
|
||||
|
||||
// write some new data
|
||||
_, err = f.Seek(1, io.SeekStart)
|
||||
|
@ -51,14 +51,14 @@ func TestDbfsBasic(t *testing.T) {
|
|||
// read from offset
|
||||
buf, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "9", string(buf))
|
||||
assert.Equal(t, "9", string(buf))
|
||||
|
||||
// read all
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
require.NoError(t, err)
|
||||
buf, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "0bcdefghi9", string(buf))
|
||||
assert.Equal(t, "0bcdefghi9", string(buf))
|
||||
|
||||
// write to new size
|
||||
_, err = f.Seek(-1, io.SeekEnd)
|
||||
|
@ -69,7 +69,7 @@ func TestDbfsBasic(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
buf, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "0bcdefghiJKLMNOP", string(buf))
|
||||
assert.Equal(t, "0bcdefghiJKLMNOP", string(buf))
|
||||
|
||||
// write beyond EOF and fill with zero
|
||||
_, err = f.Seek(5, io.SeekCurrent)
|
||||
|
@ -80,7 +80,7 @@ func TestDbfsBasic(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
buf, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "0bcdefghiJKLMNOP\x00\x00\x00\x00\x00xyzu", string(buf))
|
||||
assert.Equal(t, "0bcdefghiJKLMNOP\x00\x00\x00\x00\x00xyzu", string(buf))
|
||||
|
||||
// write to the block with zeros
|
||||
_, err = f.Seek(-6, io.SeekCurrent)
|
||||
|
@ -91,7 +91,7 @@ func TestDbfsBasic(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
buf, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "0bcdefghiJKLMNOP\x00\x00\x00ABCDzu", string(buf))
|
||||
assert.Equal(t, "0bcdefghiJKLMNOP\x00\x00\x00ABCDzu", string(buf))
|
||||
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
|
@ -118,7 +118,7 @@ func TestDbfsBasic(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
stat, err := f.Stat()
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "test.txt", stat.Name())
|
||||
assert.Equal(t, "test.txt", stat.Name())
|
||||
assert.EqualValues(t, 0, stat.Size())
|
||||
_, err = f.Write([]byte("0123456789"))
|
||||
require.NoError(t, err)
|
||||
|
@ -145,7 +145,7 @@ func TestDbfsReadWrite(t *testing.T) {
|
|||
|
||||
line, err := f2r.ReadString('\n')
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "line 1\n", line)
|
||||
assert.Equal(t, "line 1\n", line)
|
||||
_, err = f2r.ReadString('\n')
|
||||
require.ErrorIs(t, err, io.EOF)
|
||||
|
||||
|
@ -154,7 +154,7 @@ func TestDbfsReadWrite(t *testing.T) {
|
|||
|
||||
line, err = f2r.ReadString('\n')
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "line 2\n", line)
|
||||
assert.Equal(t, "line 2\n", line)
|
||||
_, err = f2r.ReadString('\n')
|
||||
require.ErrorIs(t, err, io.EOF)
|
||||
}
|
||||
|
@ -187,5 +187,5 @@ func TestDbfsSeekWrite(t *testing.T) {
|
|||
|
||||
buf, err := io.ReadAll(fr)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "111333", string(buf))
|
||||
assert.Equal(t, "111333", string(buf))
|
||||
}
|
||||
|
|
1
models/fixtures/action_variable.yml
Normal file
1
models/fixtures/action_variable.yml
Normal file
|
@ -0,0 +1 @@
|
|||
[] # empty
|
|
@ -4,6 +4,7 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -15,12 +16,14 @@ import (
|
|||
// FederationHost data type
|
||||
// swagger:model
|
||||
type FederationHost struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
HostFqdn string `xorm:"host_fqdn UNIQUE INDEX VARCHAR(255) NOT NULL"`
|
||||
NodeInfo NodeInfo `xorm:"extends NOT NULL"`
|
||||
LatestActivity time.Time `xorm:"NOT NULL"`
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
HostFqdn string `xorm:"host_fqdn UNIQUE INDEX VARCHAR(255) NOT NULL"`
|
||||
NodeInfo NodeInfo `xorm:"extends NOT NULL"`
|
||||
LatestActivity time.Time `xorm:"NOT NULL"`
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||
KeyID sql.NullString `xorm:"key_id UNIQUE"`
|
||||
PublicKey sql.Null[sql.RawBytes] `xorm:"BLOB"`
|
||||
}
|
||||
|
||||
// Factory function for FederationHost. Created struct is asserted to be valid.
|
||||
|
|
|
@ -30,9 +30,9 @@ func GetFederationHost(ctx context.Context, ID int64) (*FederationHost, error) {
|
|||
return host, nil
|
||||
}
|
||||
|
||||
func FindFederationHostByFqdn(ctx context.Context, fqdn string) (*FederationHost, error) {
|
||||
func findFederationHostFromDB(ctx context.Context, searchKey, searchValue string) (*FederationHost, error) {
|
||||
host := new(FederationHost)
|
||||
has, err := db.GetEngine(ctx).Where("host_fqdn=?", strings.ToLower(fqdn)).Get(host)
|
||||
has, err := db.GetEngine(ctx).Where(searchKey, searchValue).Get(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
|
@ -44,6 +44,14 @@ func FindFederationHostByFqdn(ctx context.Context, fqdn string) (*FederationHost
|
|||
return host, nil
|
||||
}
|
||||
|
||||
func FindFederationHostByFqdn(ctx context.Context, fqdn string) (*FederationHost, error) {
|
||||
return findFederationHostFromDB(ctx, "host_fqdn=?", strings.ToLower(fqdn))
|
||||
}
|
||||
|
||||
func FindFederationHostByKeyID(ctx context.Context, keyID string) (*FederationHost, error) {
|
||||
return findFederationHostFromDB(ctx, "key_id=?", keyID)
|
||||
}
|
||||
|
||||
func CreateFederationHost(ctx context.Context, host *FederationHost) error {
|
||||
if res, err := validation.IsValid(host); !res {
|
||||
return err
|
||||
|
|
|
@ -22,7 +22,7 @@ func TestForgejoSemVerSetGet(t *testing.T) {
|
|||
require.NoError(t, SetVersionString(ctx, newVersion.String()))
|
||||
databaseVersion, err := GetVersion(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, newVersion.String(), databaseVersion.String())
|
||||
assert.Equal(t, newVersion.String(), databaseVersion.String())
|
||||
assert.True(t, newVersion.Equal(databaseVersion))
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,12 @@ func TestForgejoSemVerMissing(t *testing.T) {
|
|||
|
||||
v, err := GetVersion(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "1.0.0", v.String())
|
||||
assert.Equal(t, "1.0.0", v.String())
|
||||
|
||||
_, err = e.Exec("drop table forgejo_sem_ver")
|
||||
require.NoError(t, err)
|
||||
|
||||
v, err = GetVersion(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, "1.0.0", v.String())
|
||||
assert.Equal(t, "1.0.0", v.String())
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ var migrations = []*Migration{
|
|||
NewMigration("Add `created_unix` column to `user_redirect` table", AddCreatedUnixToRedirect),
|
||||
// v27 -> v28
|
||||
NewMigration("Add pronoun privacy settings to user", AddHidePronounsOptionToUser),
|
||||
// v28 -> v29
|
||||
NewMigration("Add public key information to `FederatedUser` and `FederationHost`", AddPublicKeyInformationForFederation),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
|
@ -29,7 +29,7 @@ func Test_RemoveSSHSignaturesFromReleaseNotes(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, releases, 3)
|
||||
|
||||
assert.Equal(t, "", releases[0].Note)
|
||||
assert.Empty(t, releases[0].Note)
|
||||
assert.Equal(t, "A message.\n", releases[1].Note)
|
||||
assert.Equal(t, "no signature present here", releases[2].Note)
|
||||
}
|
||||
|
|
29
models/forgejo_migrations/v29.go
Normal file
29
models/forgejo_migrations/v29.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddPublicKeyInformationForFederation(x *xorm.Engine) error {
|
||||
type FederationHost struct {
|
||||
KeyID sql.NullString `xorm:"key_id UNIQUE"`
|
||||
PublicKey sql.Null[sql.RawBytes] `xorm:"BLOB"`
|
||||
}
|
||||
|
||||
err := x.Sync(&FederationHost{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type FederatedUser struct {
|
||||
KeyID sql.NullString `xorm:"key_id UNIQUE"`
|
||||
PublicKey sql.Null[sql.RawBytes] `xorm:"BLOB"`
|
||||
}
|
||||
|
||||
return x.Sync(&FederatedUser{})
|
||||
}
|
|
@ -22,7 +22,7 @@ import (
|
|||
func TestAddDeletedBranch(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
assert.EqualValues(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
|
||||
assert.Equal(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
|
||||
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
|
||||
|
||||
assert.True(t, firstBranch.IsDeleted)
|
||||
|
|
|
@ -42,7 +42,7 @@ func TestIterateRepositoryIDsWithLFSMetaObjects(t *testing.T) {
|
|||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expected, cases)
|
||||
assert.Equal(t, expected, cases)
|
||||
})
|
||||
|
||||
t.Run("Low batch size", func(t *testing.T) {
|
||||
|
@ -54,7 +54,7 @@ func TestIterateRepositoryIDsWithLFSMetaObjects(t *testing.T) {
|
|||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expected, cases)
|
||||
assert.Equal(t, expected, cases)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ func TestIterateLFSMetaObjectsForRepo(t *testing.T) {
|
|||
return nil
|
||||
}, &IterateLFSMetaObjectsForRepoOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedIDs, actualIDs)
|
||||
assert.Equal(t, expectedIDs, actualIDs)
|
||||
})
|
||||
|
||||
t.Run("Low batch size", func(t *testing.T) {
|
||||
|
@ -84,7 +84,7 @@ func TestIterateLFSMetaObjectsForRepo(t *testing.T) {
|
|||
return nil
|
||||
}, &IterateLFSMetaObjectsForRepoOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedIDs, actualIDs)
|
||||
assert.Equal(t, expectedIDs, actualIDs)
|
||||
|
||||
t.Run("Batch handles updates", func(t *testing.T) {
|
||||
actualIDs := []int64{}
|
||||
|
@ -96,7 +96,7 @@ func TestIterateLFSMetaObjectsForRepo(t *testing.T) {
|
|||
return nil
|
||||
}, &IterateLFSMetaObjectsForRepoOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedIDs, actualIDs)
|
||||
assert.Equal(t, expectedIDs, actualIDs)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ func TestBranchRuleMatchPriority(t *testing.T) {
|
|||
require.Error(t, fmt.Errorf("no matched rules but expected %s[%d]", kase.Rules[kase.ExpectedMatchIdx], kase.ExpectedMatchIdx))
|
||||
}
|
||||
} else {
|
||||
assert.EqualValues(t, kase.Rules[kase.ExpectedMatchIdx], matchedPB.RuleName)
|
||||
assert.Equal(t, kase.Rules[kase.ExpectedMatchIdx], matchedPB.RuleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,6 @@ func TestBranchRuleMatch(t *testing.T) {
|
|||
|
||||
for _, kase := range kases {
|
||||
pb := ProtectedBranch{RuleName: kase.Rule}
|
||||
assert.EqualValues(t, kase.ExpectedMatch, pb.Match(kase.BranchName), "%s - %s", kase.BranchName, kase.Rule)
|
||||
assert.Equal(t, kase.ExpectedMatch, pb.Match(kase.BranchName), "%s - %s", kase.BranchName, kase.Rule)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,12 @@ func (agg *ActionAggregator) aggregateAction(c *Comment, index int) {
|
|||
}
|
||||
agg.EndInd = index
|
||||
|
||||
if c.Type == CommentTypeClose {
|
||||
switch c.Type {
|
||||
case CommentTypeClose:
|
||||
agg.IsClosed = true
|
||||
} else if c.Type == CommentTypeReopen {
|
||||
case CommentTypeReopen:
|
||||
agg.IsClosed = false
|
||||
} else if c.Type == CommentTypeReviewRequest {
|
||||
case CommentTypeReviewRequest:
|
||||
if c.AssigneeID > 0 {
|
||||
req := RequestReviewTarget{User: c.Assignee}
|
||||
if c.RemovedAssignee {
|
||||
|
@ -78,13 +79,13 @@ func (agg *ActionAggregator) aggregateAction(c *Comment, index int) {
|
|||
for _, r := range c.AddedRequestReview {
|
||||
agg.addReviewRequest(r)
|
||||
}
|
||||
} else if c.Type == CommentTypeLabel {
|
||||
case CommentTypeLabel:
|
||||
if c.Content == "1" {
|
||||
agg.addLabel(c.Label)
|
||||
} else {
|
||||
agg.delLabel(c.Label)
|
||||
}
|
||||
} else if c.Type == CommentTypeAggregator {
|
||||
case CommentTypeAggregator:
|
||||
agg.Merge(c.Aggregator)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ func TestCreateComment(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
then := time.Now().Unix()
|
||||
|
||||
assert.EqualValues(t, issues_model.CommentTypeComment, comment.Type)
|
||||
assert.EqualValues(t, "Hello", comment.Content)
|
||||
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||
assert.EqualValues(t, doer.ID, comment.PosterID)
|
||||
assert.Equal(t, issues_model.CommentTypeComment, comment.Type)
|
||||
assert.Equal(t, "Hello", comment.Content)
|
||||
assert.Equal(t, issue.ID, comment.IssueID)
|
||||
assert.Equal(t, doer.ID, comment.PosterID)
|
||||
unittest.AssertInt64InRange(t, now, then, int64(comment.CreatedUnix))
|
||||
unittest.AssertExistsAndLoadBean(t, comment) // assert actually added to DB
|
||||
|
||||
|
@ -95,7 +95,7 @@ func TestMigrate_InsertIssueComments(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
issueModified := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
|
||||
assert.EqualValues(t, issue.NumComments+1, issueModified.NumComments)
|
||||
assert.Equal(t, issue.NumComments+1, issueModified.NumComments)
|
||||
|
||||
unittest.CheckConsistencyFor(t, &issues_model.Issue{})
|
||||
}
|
||||
|
@ -132,5 +132,5 @@ func Test_UpdateIssueNumComments(t *testing.T) {
|
|||
|
||||
require.NoError(t, issues_model.UpdateIssueNumComments(db.DefaultContext, issue2.ID))
|
||||
issue2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||
assert.EqualValues(t, 1, issue2.NumComments)
|
||||
assert.Equal(t, 1, issue2.NumComments)
|
||||
}
|
||||
|
|
|
@ -646,7 +646,7 @@ func (issue *Issue) BlockedByDependencies(ctx context.Context, opts db.ListOptio
|
|||
err = sess.Find(&issueDeps)
|
||||
|
||||
for _, depInfo := range issueDeps {
|
||||
depInfo.Issue.Repo = &depInfo.Repository
|
||||
depInfo.Repo = &depInfo.Repository
|
||||
}
|
||||
|
||||
return issueDeps, err
|
||||
|
@ -664,7 +664,7 @@ func (issue *Issue) BlockingDependencies(ctx context.Context) (issueDeps []*Depe
|
|||
Find(&issueDeps)
|
||||
|
||||
for _, depInfo := range issueDeps {
|
||||
depInfo.Issue.Repo = &depInfo.Repository
|
||||
depInfo.Repo = &depInfo.Repository
|
||||
}
|
||||
|
||||
return issueDeps, err
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestIssueList_LoadRepositories(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, repos, 2)
|
||||
for _, issue := range issueList {
|
||||
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||
assert.Equal(t, issue.RepoID, issue.Repo.ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,28 +43,28 @@ func TestIssueList_LoadAttributes(t *testing.T) {
|
|||
|
||||
require.NoError(t, issueList.LoadAttributes(db.DefaultContext))
|
||||
for _, issue := range issueList {
|
||||
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||
assert.Equal(t, issue.RepoID, issue.Repo.ID)
|
||||
for _, label := range issue.Labels {
|
||||
assert.EqualValues(t, issue.RepoID, label.RepoID)
|
||||
assert.Equal(t, issue.RepoID, label.RepoID)
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
|
||||
}
|
||||
if issue.PosterID > 0 {
|
||||
assert.EqualValues(t, issue.PosterID, issue.Poster.ID)
|
||||
assert.Equal(t, issue.PosterID, issue.Poster.ID)
|
||||
}
|
||||
if issue.AssigneeID > 0 {
|
||||
assert.EqualValues(t, issue.AssigneeID, issue.Assignee.ID)
|
||||
assert.Equal(t, issue.AssigneeID, issue.Assignee.ID)
|
||||
}
|
||||
if issue.MilestoneID > 0 {
|
||||
assert.EqualValues(t, issue.MilestoneID, issue.Milestone.ID)
|
||||
assert.Equal(t, issue.MilestoneID, issue.Milestone.ID)
|
||||
}
|
||||
if issue.IsPull {
|
||||
assert.EqualValues(t, issue.ID, issue.PullRequest.IssueID)
|
||||
assert.Equal(t, issue.ID, issue.PullRequest.IssueID)
|
||||
}
|
||||
for _, attachment := range issue.Attachments {
|
||||
assert.EqualValues(t, issue.ID, attachment.IssueID)
|
||||
assert.Equal(t, issue.ID, attachment.IssueID)
|
||||
}
|
||||
for _, comment := range issue.Comments {
|
||||
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||
assert.Equal(t, issue.ID, comment.IssueID)
|
||||
}
|
||||
if issue.ID == int64(1) {
|
||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||
|
|
|
@ -39,15 +39,15 @@ func TestPrivateIssueProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
})
|
||||
|
||||
t.Run("Anonymous user", func(t *testing.T) {
|
||||
|
@ -59,15 +59,15 @@ func TestPrivateIssueProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, nil, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, nil, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, nil, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -85,15 +85,15 @@ func TestPrivateIssueProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, userProject, user2, nil, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, userProject, user2, nil, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, userProject, user2, nil, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
})
|
||||
|
||||
t.Run("Anonymous user", func(t *testing.T) {
|
||||
|
@ -105,15 +105,15 @@ func TestPrivateIssueProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, userProject, nil, nil, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, userProject, nil, nil, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, userProject, nil, nil, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -137,15 +137,15 @@ func TestPrivateRepoProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
assert.Equal(t, 1, issuesNum)
|
||||
})
|
||||
|
||||
t.Run("Full access", func(t *testing.T) {
|
||||
|
@ -160,14 +160,14 @@ func TestPrivateRepoProjects(t *testing.T) {
|
|||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
assert.Equal(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
assert.Equal(t, 2, issuesNum)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -143,8 +143,8 @@ func TestUpdateIssueCols(t *testing.T) {
|
|||
then := time.Now().Unix()
|
||||
|
||||
updatedIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID})
|
||||
assert.EqualValues(t, newTitle, updatedIssue.Title)
|
||||
assert.EqualValues(t, prevContent, updatedIssue.Content)
|
||||
assert.Equal(t, newTitle, updatedIssue.Title)
|
||||
assert.Equal(t, prevContent, updatedIssue.Content)
|
||||
unittest.AssertInt64InRange(t, now, then, int64(updatedIssue.UpdatedUnix))
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ func TestIssues(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
if assert.Len(t, issues, len(test.ExpectedIssueIDs)) {
|
||||
for i, issue := range issues {
|
||||
assert.EqualValues(t, test.ExpectedIssueIDs[i], issue.ID)
|
||||
assert.Equal(t, test.ExpectedIssueIDs[i], issue.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,10 +249,10 @@ func testInsertIssue(t *testing.T, title, content string, expectIndex int64) *is
|
|||
has, err := db.GetEngine(db.DefaultContext).ID(issue.ID).Get(&newIssue)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, issue.Title, newIssue.Title)
|
||||
assert.EqualValues(t, issue.Content, newIssue.Content)
|
||||
assert.Equal(t, issue.Title, newIssue.Title)
|
||||
assert.Equal(t, issue.Content, newIssue.Content)
|
||||
if expectIndex > 0 {
|
||||
assert.EqualValues(t, expectIndex, newIssue.Index)
|
||||
assert.Equal(t, expectIndex, newIssue.Index)
|
||||
}
|
||||
})
|
||||
return &newIssue
|
||||
|
@ -286,7 +286,7 @@ func TestIssue_ResolveMentions(t *testing.T) {
|
|||
ids[i] = user.ID
|
||||
}
|
||||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||||
assert.EqualValues(t, expected, ids)
|
||||
assert.Equal(t, expected, ids)
|
||||
}
|
||||
|
||||
// Public repo, existing user
|
||||
|
@ -421,28 +421,28 @@ func TestIssueLoadAttributes(t *testing.T) {
|
|||
|
||||
for _, issue := range issueList {
|
||||
require.NoError(t, issue.LoadAttributes(db.DefaultContext))
|
||||
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||
assert.Equal(t, issue.RepoID, issue.Repo.ID)
|
||||
for _, label := range issue.Labels {
|
||||
assert.EqualValues(t, issue.RepoID, label.RepoID)
|
||||
assert.Equal(t, issue.RepoID, label.RepoID)
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
|
||||
}
|
||||
if issue.PosterID > 0 {
|
||||
assert.EqualValues(t, issue.PosterID, issue.Poster.ID)
|
||||
assert.Equal(t, issue.PosterID, issue.Poster.ID)
|
||||
}
|
||||
if issue.AssigneeID > 0 {
|
||||
assert.EqualValues(t, issue.AssigneeID, issue.Assignee.ID)
|
||||
assert.Equal(t, issue.AssigneeID, issue.Assignee.ID)
|
||||
}
|
||||
if issue.MilestoneID > 0 {
|
||||
assert.EqualValues(t, issue.MilestoneID, issue.Milestone.ID)
|
||||
assert.Equal(t, issue.MilestoneID, issue.Milestone.ID)
|
||||
}
|
||||
if issue.IsPull {
|
||||
assert.EqualValues(t, issue.ID, issue.PullRequest.IssueID)
|
||||
assert.Equal(t, issue.ID, issue.PullRequest.IssueID)
|
||||
}
|
||||
for _, attachment := range issue.Attachments {
|
||||
assert.EqualValues(t, issue.ID, attachment.IssueID)
|
||||
assert.Equal(t, issue.ID, attachment.IssueID)
|
||||
}
|
||||
for _, comment := range issue.Comments {
|
||||
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||
assert.Equal(t, issue.ID, comment.IssueID)
|
||||
}
|
||||
if issue.ID == int64(1) {
|
||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||
|
|
|
@ -275,6 +275,11 @@ func ChangeIssueContent(ctx context.Context, issue *Issue, doer *user_model.User
|
|||
}
|
||||
}
|
||||
|
||||
// If the issue was reported as abusive, a shadow copy should be created before first update.
|
||||
if err := IfNeededCreateShadowCopyForIssue(ctx, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
issue.Content = content
|
||||
issue.ContentVersion = contentVersion + 1
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ func TestLabel_CalOpenIssues(t *testing.T) {
|
|||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||
label.CalOpenIssues()
|
||||
assert.EqualValues(t, 2, label.NumOpenIssues)
|
||||
assert.Equal(t, 2, label.NumOpenIssues)
|
||||
}
|
||||
|
||||
func TestLabel_LoadSelectedLabelsAfterClick(t *testing.T) {
|
||||
|
@ -156,7 +156,7 @@ func TestGetLabelsByRepoID(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, labels, len(expectedIssueIDs))
|
||||
for i, label := range labels {
|
||||
assert.EqualValues(t, expectedIssueIDs[i], label.ID)
|
||||
assert.Equal(t, expectedIssueIDs[i], label.ID)
|
||||
}
|
||||
}
|
||||
testSuccess(1, "leastissues", []int64{2, 1})
|
||||
|
@ -223,7 +223,7 @@ func TestGetLabelsByOrgID(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, labels, len(expectedIssueIDs))
|
||||
for i, label := range labels {
|
||||
assert.EqualValues(t, expectedIssueIDs[i], label.ID)
|
||||
assert.Equal(t, expectedIssueIDs[i], label.ID)
|
||||
}
|
||||
}
|
||||
testSuccess(3, "leastissues", []int64{3, 4})
|
||||
|
@ -269,10 +269,10 @@ func TestUpdateLabel(t *testing.T) {
|
|||
label.Name = update.Name
|
||||
require.NoError(t, issues_model.UpdateLabel(db.DefaultContext, update))
|
||||
newLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||
assert.EqualValues(t, label.ID, newLabel.ID)
|
||||
assert.EqualValues(t, label.Color, newLabel.Color)
|
||||
assert.EqualValues(t, label.Name, newLabel.Name)
|
||||
assert.EqualValues(t, label.Description, newLabel.Description)
|
||||
assert.Equal(t, label.ID, newLabel.ID)
|
||||
assert.Equal(t, label.Color, newLabel.Color)
|
||||
assert.Equal(t, label.Name, newLabel.Name)
|
||||
assert.Equal(t, label.Description, newLabel.Description)
|
||||
assert.EqualValues(t, 0, newLabel.ArchivedUnix)
|
||||
unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{})
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ func TestNewIssueLabel(t *testing.T) {
|
|||
Content: "1",
|
||||
})
|
||||
label = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2})
|
||||
assert.EqualValues(t, prevNumIssues+1, label.NumIssues)
|
||||
assert.Equal(t, prevNumIssues+1, label.NumIssues)
|
||||
|
||||
// re-add existing IssueLabel
|
||||
require.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
|
||||
|
@ -368,11 +368,11 @@ func TestNewIssueLabels(t *testing.T) {
|
|||
})
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID})
|
||||
label1 = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||
assert.EqualValues(t, 3, label1.NumIssues)
|
||||
assert.EqualValues(t, 1, label1.NumClosedIssues)
|
||||
assert.Equal(t, 3, label1.NumIssues)
|
||||
assert.Equal(t, 1, label1.NumClosedIssues)
|
||||
label2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2})
|
||||
assert.EqualValues(t, 1, label2.NumIssues)
|
||||
assert.EqualValues(t, 1, label2.NumClosedIssues)
|
||||
assert.Equal(t, 1, label2.NumIssues)
|
||||
assert.Equal(t, 1, label2.NumClosedIssues)
|
||||
|
||||
// corner case: test empty slice
|
||||
require.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{}, doer))
|
||||
|
@ -410,8 +410,8 @@ func TestDeleteIssueLabel(t *testing.T) {
|
|||
LabelID: labelID,
|
||||
}, `content=""`)
|
||||
label = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID})
|
||||
assert.EqualValues(t, expectedNumIssues, label.NumIssues)
|
||||
assert.EqualValues(t, expectedNumClosedIssues, label.NumClosedIssues)
|
||||
assert.Equal(t, expectedNumIssues, label.NumIssues)
|
||||
assert.Equal(t, expectedNumClosedIssues, label.NumClosedIssues)
|
||||
}
|
||||
testSuccess(1, 1, 2)
|
||||
testSuccess(2, 5, 2)
|
||||
|
|
|
@ -70,7 +70,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
|
|||
|
||||
assert.Len(t, milestones, n)
|
||||
for _, milestone := range milestones {
|
||||
assert.EqualValues(t, repoID, milestone.RepoID)
|
||||
assert.Equal(t, repoID, milestone.RepoID)
|
||||
}
|
||||
}
|
||||
test(1, api.StateOpen)
|
||||
|
@ -327,7 +327,7 @@ func TestUpdateMilestone(t *testing.T) {
|
|||
milestone.Content = "newMilestoneContent"
|
||||
require.NoError(t, issues_model.UpdateMilestone(db.DefaultContext, milestone, milestone.IsClosed))
|
||||
milestone = unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1})
|
||||
assert.EqualValues(t, "newMilestoneName", milestone.Name)
|
||||
assert.Equal(t, "newMilestoneName", milestone.Name)
|
||||
unittest.CheckConsistencyFor(t, &issues_model.Milestone{})
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ func TestMigrate_InsertMilestones(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
unittest.AssertExistsAndLoadBean(t, ms)
|
||||
repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID})
|
||||
assert.EqualValues(t, repo.NumMilestones+1, repoModified.NumMilestones)
|
||||
assert.Equal(t, repo.NumMilestones+1, repoModified.NumMilestones)
|
||||
|
||||
unittest.CheckConsistencyFor(t, &issues_model.Milestone{})
|
||||
}
|
||||
|
|
|
@ -11,9 +11,39 @@ import (
|
|||
"forgejo.org/modules/timeutil"
|
||||
)
|
||||
|
||||
// IssueData represents a trimmed down issue that is used for preserving
|
||||
// only the fields needed for abusive content reports (mainly string fields).
|
||||
type IssueData struct {
|
||||
RepoID int64
|
||||
Index int64
|
||||
PosterID int64
|
||||
Title string
|
||||
Content string
|
||||
ContentVersion int
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
// newIssueData creates a trimmed down issue to be used just to create a JSON structure
|
||||
// (keeping only the fields relevant for moderation purposes)
|
||||
func newIssueData(issue *Issue) IssueData {
|
||||
return IssueData{
|
||||
RepoID: issue.RepoID,
|
||||
Index: issue.Index,
|
||||
PosterID: issue.PosterID,
|
||||
Content: issue.Content,
|
||||
Title: issue.Title,
|
||||
ContentVersion: issue.ContentVersion,
|
||||
CreatedUnix: issue.CreatedUnix,
|
||||
UpdatedUnix: issue.UpdatedUnix,
|
||||
}
|
||||
}
|
||||
|
||||
// CommentData represents a trimmed down comment that is used for preserving
|
||||
// only the fields needed for abusive content reports (mainly string fields).
|
||||
type CommentData struct {
|
||||
PosterID int64
|
||||
IssueID int64
|
||||
Content string
|
||||
ContentVersion int
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
|
@ -24,6 +54,8 @@ type CommentData struct {
|
|||
// (keeping only the fields relevant for moderation purposes)
|
||||
func newCommentData(comment *Comment) CommentData {
|
||||
return CommentData{
|
||||
PosterID: comment.PosterID,
|
||||
IssueID: comment.IssueID,
|
||||
Content: comment.Content,
|
||||
ContentVersion: comment.ContentVersion,
|
||||
CreatedUnix: comment.CreatedUnix,
|
||||
|
@ -31,12 +63,37 @@ func newCommentData(comment *Comment) CommentData {
|
|||
}
|
||||
}
|
||||
|
||||
// IfNeededCreateShadowCopyForIssue checks if for the given issue there are any reports of abusive content submitted
|
||||
// and if found a shadow copy of relevant issue fields will be stored into DB and linked to the above report(s).
|
||||
// This function should be called before a issue is deleted or updated.
|
||||
func IfNeededCreateShadowCopyForIssue(ctx context.Context, issue *Issue) error {
|
||||
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeIssue, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if shadowCopyNeeded {
|
||||
issueData := newIssueData(issue)
|
||||
content, err := json.Marshal(issueData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return moderation.CreateShadowCopyForIssue(ctx, issue.ID, string(content))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IfNeededCreateShadowCopyForComment checks if for the given comment there are any reports of abusive content submitted
|
||||
// and if found a shadow copy of relevant comment fields will be stored into DB and linked to the above report(s).
|
||||
// This function should be called when a comment is deleted or updated.
|
||||
// This function should be called before a comment is deleted or updated.
|
||||
func IfNeededCreateShadowCopyForComment(ctx context.Context, comment *Comment) error {
|
||||
// TODO check comment.Type?
|
||||
if moderation.IsReported(ctx, moderation.ReportedContentTypeComment, comment.ID) {
|
||||
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeComment, comment.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if shadowCopyNeeded {
|
||||
commentData := newCommentData(comment)
|
||||
content, err := json.Marshal(commentData)
|
||||
if err != nil {
|
||||
|
|
|
@ -399,7 +399,7 @@ func TestDeleteOrphanedObjects(t *testing.T) {
|
|||
|
||||
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, countBefore, countAfter)
|
||||
assert.Equal(t, countBefore, countAfter)
|
||||
}
|
||||
|
||||
func TestParseCodeOwnersLine(t *testing.T) {
|
||||
|
@ -432,7 +432,7 @@ func TestGetApprovers(t *testing.T) {
|
|||
setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly = false
|
||||
approvers := pr.GetApprovers(db.DefaultContext)
|
||||
expected := "Reviewed-by: User Five <user5@example.com>\nReviewed-by: Org Six <org6@example.com>\n"
|
||||
assert.EqualValues(t, expected, approvers)
|
||||
assert.Equal(t, expected, approvers)
|
||||
}
|
||||
|
||||
func TestGetPullRequestByMergedCommit(t *testing.T) {
|
||||
|
|
|
@ -92,7 +92,7 @@ func TestGetUIDsAndStopwatch(t *testing.T) {
|
|||
|
||||
uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, map[int64][]*issues_model.Stopwatch{
|
||||
assert.Equal(t, map[int64][]*issues_model.Stopwatch{
|
||||
1: {
|
||||
{
|
||||
ID: 1,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/models/forgejo_migrations"
|
||||
"forgejo.org/models/migrations/v1_10"
|
||||
"forgejo.org/models/migrations/v1_11"
|
||||
|
@ -510,3 +511,12 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
|
|||
// Execute Forgejo specific migrations.
|
||||
return forgejo_migrations.Migrate(x)
|
||||
}
|
||||
|
||||
// WrapperMigrate is a wrapper for Migrate to be called in diagnostics
|
||||
func WrapperMigrate(e db.Engine) error {
|
||||
engine, err := db.GetMasterEngine(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return Migrate(engine)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func TestMigrations(t *testing.T) {
|
|||
|
||||
assert.EqualValues(t, 71, migrationIDNumberToDBVersion(70))
|
||||
|
||||
assert.EqualValues(t, []*migration{{idNumber: 70}, {idNumber: 71}}, getPendingMigrations(70, preparedMigrations))
|
||||
assert.EqualValues(t, []*migration{{idNumber: 71}}, getPendingMigrations(71, preparedMigrations))
|
||||
assert.EqualValues(t, []*migration{}, getPendingMigrations(72, preparedMigrations))
|
||||
assert.Equal(t, []*migration{{idNumber: 70}, {idNumber: 71}}, getPendingMigrations(70, preparedMigrations))
|
||||
assert.Equal(t, []*migration{{idNumber: 71}}, getPendingMigrations(71, preparedMigrations))
|
||||
assert.Equal(t, []*migration{}, getPendingMigrations(72, preparedMigrations))
|
||||
}
|
||||
|
|
|
@ -175,7 +175,10 @@ func newXORMEngine() (*xorm.Engine, error) {
|
|||
if err := db.InitEngine(context.Background()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := unittest.GetXORMEngine()
|
||||
x, err := unittest.GetXORMEngine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ func Test_AddPrimaryEmail2EmailAddress(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.True(t, emailAddress.IsPrimary)
|
||||
assert.EqualValues(t, user.IsActive, emailAddress.IsActivated)
|
||||
assert.EqualValues(t, user.ID, emailAddress.UID)
|
||||
assert.Equal(t, user.IsActive, emailAddress.IsActivated)
|
||||
assert.Equal(t, user.ID, emailAddress.UID)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,8 +76,8 @@ func Test_UnwrapLDAPSourceCfg(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
assert.EqualValues(t, expected, converted, "UnwrapLDAPSourceCfg failed for %d", source.ID)
|
||||
assert.EqualValues(t, source.ID%2 == 0, source.IsActive, "UnwrapLDAPSourceCfg failed for %d", source.ID)
|
||||
assert.Equal(t, expected, converted, "UnwrapLDAPSourceCfg failed for %d", source.ID)
|
||||
assert.Equal(t, source.ID%2 == 0, source.IsActive, "UnwrapLDAPSourceCfg failed for %d", source.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func Test_AddRepoIDForAttachment(t *testing.T) {
|
|||
has, err := x.ID(attach.IssueID).Get(&issue)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, attach.RepoID, issue.RepoID)
|
||||
assert.Equal(t, attach.RepoID, issue.RepoID)
|
||||
}
|
||||
|
||||
var releaseAttachments []*NewAttachment
|
||||
|
@ -76,6 +76,6 @@ func Test_AddRepoIDForAttachment(t *testing.T) {
|
|||
has, err := x.ID(attach.ReleaseID).Get(&release)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, attach.RepoID, release.RepoID)
|
||||
assert.Equal(t, attach.RepoID, release.RepoID)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,5 +84,5 @@ func Test_RemigrateU2FCredentials(t *testing.T) {
|
|||
err = x.Table("webauthn_credential").Select("id, credential_id").Asc("id").Find(&got)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, expected, got)
|
||||
assert.Equal(t, expected, got)
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func Test_AddHeaderAuthorizationEncryptedColWebhook(t *testing.T) {
|
|||
assert.Equal(t, e.Meta, got[i].Meta)
|
||||
|
||||
if e.HeaderAuthorization == "" {
|
||||
assert.Equal(t, "", got[i].HeaderAuthorizationEncrypted)
|
||||
assert.Empty(t, got[i].HeaderAuthorizationEncrypted)
|
||||
} else {
|
||||
cipherhex := got[i].HeaderAuthorizationEncrypted
|
||||
cleartext, err := secret.DecryptSecret(setting.SecretKey, cipherhex)
|
||||
|
|
|
@ -97,7 +97,7 @@ func Test_ConvertScopedAccessTokens(t *testing.T) {
|
|||
tokens := make([]AccessToken, 0)
|
||||
err = x.Find(&tokens)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(tests), len(tokens))
|
||||
assert.Len(t, tokens, len(tests))
|
||||
|
||||
// sort the tokens (insertion order by auto-incrementing primary key)
|
||||
sort.Slice(tokens, func(i, j int) bool {
|
||||
|
|
|
@ -109,11 +109,11 @@ func Test_RepositoryFormat(t *testing.T) {
|
|||
ok, err := x.ID(2).Get(repo)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
assert.EqualValues(t, "sha1", repo.ObjectFormatName)
|
||||
assert.Equal(t, "sha1", repo.ObjectFormatName)
|
||||
|
||||
repo = new(Repository)
|
||||
ok, err = x.ID(id).Get(repo)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
assert.EqualValues(t, "sha256", repo.ObjectFormatName)
|
||||
assert.Equal(t, "sha256", repo.ObjectFormatName)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
// ReportStatusType defines the statuses a report (of abusive content) can have.
|
||||
type ReportStatusType int //revive:disable-line:exported
|
||||
type ReportStatusType int
|
||||
|
||||
const (
|
||||
// ReportStatusTypeOpen represents the status of open reports that were not yet handled in any way.
|
||||
|
@ -30,7 +30,7 @@ const (
|
|||
|
||||
type (
|
||||
// AbuseCategoryType defines the categories in which a user can include the reported content.
|
||||
AbuseCategoryType int //revive:disable-line:exported
|
||||
AbuseCategoryType int
|
||||
|
||||
// AbuseCategoryItem defines a pair of value and it's corresponding translation key
|
||||
// (used to add options within the dropdown shown when new reports are submitted).
|
||||
|
@ -60,7 +60,7 @@ func GetAbuseCategoriesList() []AbuseCategoryItem {
|
|||
|
||||
// ReportedContentType defines the types of content that can be reported
|
||||
// (i.e. user/organization profile, repository, issue/pull, comment).
|
||||
type ReportedContentType int //revive:disable-line:exported
|
||||
type ReportedContentType int
|
||||
|
||||
const (
|
||||
// ReportedContentTypeUser should be used when reporting abusive users or organizations.
|
||||
|
@ -90,7 +90,7 @@ func (t ReportedContentType) IsValid() bool {
|
|||
// AbuseReport represents a report of abusive content.
|
||||
type AbuseReport struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Status ReportStatusType `xorm:"NOT NULL DEFAULT 1"`
|
||||
Status ReportStatusType `xorm:"INDEX NOT NULL DEFAULT 1"`
|
||||
// The ID of the user who submitted the report.
|
||||
ReporterID int64 `xorm:"NOT NULL"`
|
||||
// Reported content type: user/organization profile, repository, issue/pull or comment.
|
||||
|
@ -115,12 +115,12 @@ func init() {
|
|||
db.RegisterModel(new(AbuseReport))
|
||||
}
|
||||
|
||||
// IsReported reports whether one or more reports were already submitted for contentType and contentID
|
||||
// (regardless the status of the reports).
|
||||
func IsReported(ctx context.Context, contentType ReportedContentType, contentID int64) bool {
|
||||
// TODO: only consider the reports with 'New' status (and adjust the function name)?!
|
||||
reported, _ := db.GetEngine(ctx).Exist(&AbuseReport{ContentType: contentType, ContentID: contentID})
|
||||
return reported
|
||||
// IsShadowCopyNeeded reports whether one or more reports were already submitted
|
||||
// for contentType and contentID and not yet linked to a shadow copy (regardless their status).
|
||||
func IsShadowCopyNeeded(ctx context.Context, contentType ReportedContentType, contentID int64) (bool, error) {
|
||||
return db.GetEngine(ctx).Cols("id").Where(builder.IsNull{"shadow_copy_id"}).Exist(
|
||||
&AbuseReport{ContentType: contentType, ContentID: contentID},
|
||||
)
|
||||
}
|
||||
|
||||
// AlreadyReportedByAndOpen returns if doerID has already submitted a report for contentType and contentID that is still Open.
|
||||
|
|
|
@ -53,16 +53,6 @@ func createShadowCopy(ctx context.Context, contentType ReportedContentType, cont
|
|||
err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
notLinkedFound, err := sess.Cols("id").Where(builder.IsNull{"shadow_copy_id"}).Exist(
|
||||
&AbuseReport{ContentType: contentType, ContentID: contentID},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !notLinkedFound {
|
||||
log.Warn("Requested to create a shadow copy for reported content with type %d and ID %d but there is no such report without a shadow copy ID.", contentType, contentID)
|
||||
return nil
|
||||
}
|
||||
|
||||
shadowCopy := &AbuseReportShadowCopy{RawValue: content}
|
||||
affected, err := sess.Insert(shadowCopy)
|
||||
if err != nil {
|
||||
|
|
|
@ -82,7 +82,7 @@ func TestUpdateTeam(t *testing.T) {
|
|||
assert.True(t, strings.HasPrefix(team.Description, "A long description!"))
|
||||
|
||||
access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: 3})
|
||||
assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
|
||||
assert.Equal(t, perm.AccessModeAdmin, access.Mode)
|
||||
|
||||
unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID})
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ func TestRemoveOrgUser(t *testing.T) {
|
|||
require.NoError(t, RemoveOrgUser(db.DefaultContext, orgID, userID))
|
||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: orgID, UID: userID})
|
||||
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID})
|
||||
assert.EqualValues(t, expectedNumMembers, org.NumMembers)
|
||||
assert.Equal(t, expectedNumMembers, org.NumMembers)
|
||||
}
|
||||
testSuccess(3, 4)
|
||||
testSuccess(3, 4)
|
||||
|
|
|
@ -195,7 +195,7 @@ type FindOrgMembersOpts struct {
|
|||
}
|
||||
|
||||
func (opts FindOrgMembersOpts) PublicOnly() bool {
|
||||
return opts.Doer == nil || !(opts.IsDoerMember || opts.Doer.IsAdmin)
|
||||
return opts.Doer == nil || (!opts.IsDoerMember && !opts.Doer.IsAdmin)
|
||||
}
|
||||
|
||||
// CountOrgMembers counts the organization's members
|
||||
|
@ -289,12 +289,8 @@ func CreateOrganization(ctx context.Context, org *Organization, owner *user_mode
|
|||
}
|
||||
|
||||
org.LowerName = strings.ToLower(org.Name)
|
||||
if org.Rands, err = user_model.GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
if org.Salt, err = user_model.GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
org.Rands = user_model.GetUserSalt()
|
||||
org.Salt = user_model.GetUserSalt()
|
||||
org.UseCustomAvatar = true
|
||||
org.MaxRepoCreation = -1
|
||||
org.NumTeams = 1
|
||||
|
@ -478,7 +474,7 @@ func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUs
|
|||
sess.And("is_public = ?", true)
|
||||
}
|
||||
|
||||
if opts.ListOptions.PageSize > 0 {
|
||||
if opts.PageSize > 0 {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
||||
|
||||
ous := make([]*OrgUser, 0, opts.PageSize)
|
||||
|
|
|
@ -73,7 +73,7 @@ func TestGetUserOrgsList(t *testing.T) {
|
|||
if assert.Len(t, orgs, 1) {
|
||||
assert.EqualValues(t, 3, orgs[0].ID)
|
||||
// repo_id: 3 is in the team, 32 is public, 5 is private with no team
|
||||
assert.EqualValues(t, 2, orgs[0].NumRepos)
|
||||
assert.Equal(t, 2, orgs[0].NumRepos)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ func TestIsOrganizationOwner(t *testing.T) {
|
|||
test := func(orgID, userID int64, expected bool) {
|
||||
isOwner, err := organization.IsOrganizationOwner(db.DefaultContext, orgID, userID)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expected, isOwner)
|
||||
assert.Equal(t, expected, isOwner)
|
||||
}
|
||||
test(3, 2, true)
|
||||
test(3, 3, false)
|
||||
|
@ -150,7 +150,7 @@ func TestIsOrganizationMember(t *testing.T) {
|
|||
test := func(orgID, userID int64, expected bool) {
|
||||
isMember, err := organization.IsOrganizationMember(db.DefaultContext, orgID, userID)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expected, isMember)
|
||||
assert.Equal(t, expected, isMember)
|
||||
}
|
||||
test(3, 2, true)
|
||||
test(3, 3, false)
|
||||
|
@ -165,7 +165,7 @@ func TestIsPublicMembership(t *testing.T) {
|
|||
test := func(orgID, userID int64, expected bool) {
|
||||
isMember, err := organization.IsPublicMembership(db.DefaultContext, orgID, userID)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expected, isMember)
|
||||
assert.Equal(t, expected, isMember)
|
||||
}
|
||||
test(3, 2, true)
|
||||
test(3, 3, false)
|
||||
|
@ -188,7 +188,7 @@ func TestGetOrgUsersByOrgID(t *testing.T) {
|
|||
sort.Slice(orgUsers, func(i, j int) bool {
|
||||
return orgUsers[i].ID < orgUsers[j].ID
|
||||
})
|
||||
assert.EqualValues(t, []*organization.OrgUser{{
|
||||
assert.Equal(t, []*organization.OrgUser{{
|
||||
ID: 1,
|
||||
OrgID: 3,
|
||||
UID: 2,
|
||||
|
@ -255,7 +255,7 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
count, err := env.CountRepos()
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, expectedCount, count)
|
||||
assert.Equal(t, expectedCount, count)
|
||||
}
|
||||
testSuccess(2, 3)
|
||||
testSuccess(4, 2)
|
||||
|
@ -494,25 +494,25 @@ func TestUnitPermission(t *testing.T) {
|
|||
user := &user_model.User{ID: 1001}
|
||||
t.Run("Anonymous", func(t *testing.T) {
|
||||
t.Run("Public", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
})
|
||||
t.Run("Limited", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeNone, limitedOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeNone, limitedOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
})
|
||||
t.Run("Private", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Logged in", func(t *testing.T) {
|
||||
t.Run("Public", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
})
|
||||
t.Run("Limited", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeRead, limitedOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeRead, limitedOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
})
|
||||
t.Run("Private", func(t *testing.T) {
|
||||
assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
assert.Equal(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ func TestAddOrgUser(t *testing.T) {
|
|||
unittest.AssertExistsAndLoadBean(t, ou)
|
||||
assert.Equal(t, isPublic, ou.IsPublic)
|
||||
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID})
|
||||
assert.EqualValues(t, expectedNumMembers, org.NumMembers)
|
||||
assert.Equal(t, expectedNumMembers, org.NumMembers)
|
||||
}
|
||||
|
||||
setting.Service.DefaultOrgMemberVisible = false
|
||||
|
|
|
@ -77,7 +77,7 @@ func TestGetTeam(t *testing.T) {
|
|||
testSuccess := func(orgID int64, name string) {
|
||||
team, err := organization.GetTeam(db.DefaultContext, orgID, name)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, orgID, team.OrgID)
|
||||
assert.Equal(t, orgID, team.OrgID)
|
||||
assert.Equal(t, name, team.Name)
|
||||
}
|
||||
testSuccess(3, "Owners")
|
||||
|
@ -95,7 +95,7 @@ func TestGetTeamByID(t *testing.T) {
|
|||
testSuccess := func(teamID int64) {
|
||||
team, err := organization.GetTeamByID(db.DefaultContext, teamID)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, teamID, team.ID)
|
||||
assert.Equal(t, teamID, team.ID)
|
||||
}
|
||||
testSuccess(1)
|
||||
testSuccess(2)
|
||||
|
@ -163,7 +163,7 @@ func TestGetUserOrgTeams(t *testing.T) {
|
|||
teams, err := organization.GetUserOrgTeams(db.DefaultContext, orgID, userID)
|
||||
require.NoError(t, err)
|
||||
for _, team := range teams {
|
||||
assert.EqualValues(t, orgID, team.OrgID)
|
||||
assert.Equal(t, orgID, team.OrgID)
|
||||
unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{TeamID: team.ID, UID: userID})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ func refreshCollaboratorAccesses(ctx context.Context, repoID int64, accessMap ma
|
|||
return fmt.Errorf("getCollaborations: %w", err)
|
||||
}
|
||||
for _, c := range collaborators {
|
||||
if c.User.IsGhost() {
|
||||
if c.IsGhost() {
|
||||
continue
|
||||
}
|
||||
updateUserAccess(accessMap, c.User, c.Collaboration.Mode)
|
||||
|
|
|
@ -98,9 +98,9 @@ func Test_MoveColumnsOnProject(t *testing.T) {
|
|||
columnsAfter, err := project1.GetColumns(db.DefaultContext)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, columnsAfter, 3)
|
||||
assert.EqualValues(t, columns[1].ID, columnsAfter[0].ID)
|
||||
assert.EqualValues(t, columns[2].ID, columnsAfter[1].ID)
|
||||
assert.EqualValues(t, columns[0].ID, columnsAfter[2].ID)
|
||||
assert.Equal(t, columns[1].ID, columnsAfter[0].ID)
|
||||
assert.Equal(t, columns[2].ID, columnsAfter[1].ID)
|
||||
assert.Equal(t, columns[0].ID, columnsAfter[2].ID)
|
||||
}
|
||||
|
||||
func Test_NewColumn(t *testing.T) {
|
||||
|
|
|
@ -114,10 +114,10 @@ func TestProjectsSort(t *testing.T) {
|
|||
OrderBy: GetSearchOrderByBySortType(tt.sortType),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, int64(6), count)
|
||||
assert.Equal(t, int64(6), count)
|
||||
if assert.Len(t, projects, 6) {
|
||||
for i := range projects {
|
||||
assert.EqualValues(t, tt.wants[i], projects[i].ID)
|
||||
assert.Equal(t, tt.wants[i], projects[i].ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ func TestRepository_GetCollaborators(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, collaborators, int(expectedLen))
|
||||
for _, collaborator := range collaborators {
|
||||
assert.EqualValues(t, collaborator.User.ID, collaborator.Collaboration.UserID)
|
||||
assert.EqualValues(t, repoID, collaborator.Collaboration.RepoID)
|
||||
assert.Equal(t, collaborator.User.ID, collaborator.Collaboration.UserID)
|
||||
assert.Equal(t, repoID, collaborator.Collaboration.RepoID)
|
||||
}
|
||||
}
|
||||
test(1)
|
||||
|
@ -47,7 +47,7 @@ func TestRepository_GetCollaborators(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Len(t, collaborators2, 1)
|
||||
|
||||
assert.NotEqualValues(t, collaborators1[0].ID, collaborators2[0].ID)
|
||||
assert.NotEqual(t, collaborators1[0].ID, collaborators2[0].ID)
|
||||
}
|
||||
|
||||
func TestRepository_IsCollaborator(t *testing.T) {
|
||||
|
@ -72,10 +72,10 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
|
|||
require.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
|
||||
|
||||
collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4})
|
||||
assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode)
|
||||
assert.Equal(t, perm.AccessModeAdmin, collaboration.Mode)
|
||||
|
||||
access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID})
|
||||
assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
|
||||
assert.Equal(t, perm.AccessModeAdmin, access.Mode)
|
||||
|
||||
require.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
|
||||
|
||||
|
|
70
models/repo/moderation.go
Normal file
70
models/repo/moderation.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forgejo.org/models/moderation"
|
||||
"forgejo.org/modules/json"
|
||||
"forgejo.org/modules/timeutil"
|
||||
)
|
||||
|
||||
// RepositoryData represents a trimmed down repository that is used for preserving
|
||||
// only the fields needed for abusive content reports (mainly string fields).
|
||||
type RepositoryData struct {
|
||||
OwnerID int64
|
||||
OwnerName string
|
||||
Name string
|
||||
Description string
|
||||
Website string
|
||||
Topics []string
|
||||
Avatar string
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
// newRepositoryData creates a trimmed down repository to be used just to create a JSON structure
|
||||
// (keeping only the fields relevant for moderation purposes)
|
||||
func newRepositoryData(repo *Repository) RepositoryData {
|
||||
return RepositoryData{
|
||||
OwnerID: repo.OwnerID,
|
||||
OwnerName: repo.OwnerName,
|
||||
Name: repo.Name,
|
||||
Description: repo.Description,
|
||||
Website: repo.Website,
|
||||
Topics: repo.Topics,
|
||||
Avatar: repo.Avatar,
|
||||
CreatedUnix: repo.CreatedUnix,
|
||||
UpdatedUnix: repo.UpdatedUnix,
|
||||
}
|
||||
}
|
||||
|
||||
// IfNeededCreateShadowCopyForRepository checks if for the given repository there are any reports of abusive content submitted
|
||||
// and if found a shadow copy of relevant repository fields will be stored into DB and linked to the above report(s).
|
||||
// This function should be called when a repository is deleted or updated.
|
||||
func IfNeededCreateShadowCopyForRepository(ctx context.Context, repo *Repository, forUpdates bool) error {
|
||||
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeRepository, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if shadowCopyNeeded {
|
||||
if forUpdates {
|
||||
// get the unmodified repository fields
|
||||
repo, err = GetRepositoryByID(ctx, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
repoData := newRepositoryData(repo)
|
||||
content, err := json.Marshal(repoData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return moderation.CreateShadowCopyForRepository(ctx, repo.ID, string(content))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -67,7 +67,7 @@ func TestPushMirrorPrivatekey(t *testing.T) {
|
|||
t.Run("Normal retrieval", func(t *testing.T) {
|
||||
actualPrivateKey, err := m.Privatekey()
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, privateKey, actualPrivateKey)
|
||||
assert.Equal(t, privateKey, actualPrivateKey)
|
||||
})
|
||||
|
||||
t.Run("Incorrect retrieval", func(t *testing.T) {
|
||||
|
|
|
@ -402,27 +402,28 @@ func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit
|
|||
return ru
|
||||
}
|
||||
|
||||
if tp == unit.TypeExternalWiki {
|
||||
switch tp {
|
||||
case unit.TypeExternalWiki:
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(ExternalWikiConfig),
|
||||
}
|
||||
} else if tp == unit.TypeExternalTracker {
|
||||
case unit.TypeExternalTracker:
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(ExternalTrackerConfig),
|
||||
}
|
||||
} else if tp == unit.TypePullRequests {
|
||||
case unit.TypePullRequests:
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(PullRequestsConfig),
|
||||
}
|
||||
} else if tp == unit.TypeIssues {
|
||||
case unit.TypeIssues:
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(IssuesConfig),
|
||||
}
|
||||
} else if tp == unit.TypeActions {
|
||||
case unit.TypeActions:
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(ActionsConfig),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue