package main | package main | ||||
import ( | import ( | ||||
"context" | |||||
"fmt" | "fmt" | ||||
"os" | "os" | ||||
"path/filepath" | "path/filepath" | ||||
var ( | var ( | ||||
generators = []struct { | generators = []struct { | ||||
gen func() (string, error) | |||||
gen func(ctx context.Context) (string, error) | |||||
name string | name string | ||||
}{ | }{ | ||||
{ | { | ||||
fmt.Printf("PrepareTestDatabase: %+v\n", err) | fmt.Printf("PrepareTestDatabase: %+v\n", err) | ||||
os.Exit(1) | os.Exit(1) | ||||
} | } | ||||
ctx := context.Background() | |||||
if len(os.Args) == 0 { | if len(os.Args) == 0 { | ||||
for _, r := range os.Args { | for _, r := range os.Args { | ||||
if err := generate(r); err != nil { | |||||
if err := generate(ctx, r); err != nil { | |||||
fmt.Printf("generate '%s': %+v\n", r, err) | fmt.Printf("generate '%s': %+v\n", r, err) | ||||
os.Exit(1) | os.Exit(1) | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
for _, g := range generators { | for _, g := range generators { | ||||
if err := generate(g.name); err != nil { | |||||
if err := generate(ctx, g.name); err != nil { | |||||
fmt.Printf("generate '%s': %+v\n", g.name, err) | fmt.Printf("generate '%s': %+v\n", g.name, err) | ||||
os.Exit(1) | os.Exit(1) | ||||
} | } | ||||
} | } | ||||
} | } | ||||
func generate(name string) error { | |||||
func generate(ctx context.Context, name string) error { | |||||
for _, g := range generators { | for _, g := range generators { | ||||
if g.name == name { | if g.name == name { | ||||
data, err := g.gen() | |||||
data, err := g.gen(ctx) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } |
} | } | ||||
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. | // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. | ||||
// Note: db.GetEngine(db.DefaultContext).Iterate does not get latest data after insert/delete, so we have to call this function | |||||
// Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function | |||||
// outside any session scope independently. | // outside any session scope independently. | ||||
func RewriteAllPublicKeys(ctx context.Context) error { | func RewriteAllPublicKeys(ctx context.Context) error { | ||||
// Don't rewrite key if internal server | // Don't rewrite key if internal server |
const authorizedPrincipalsFile = "authorized_principals" | const authorizedPrincipalsFile = "authorized_principals" | ||||
// RewriteAllPrincipalKeys removes any authorized principal and rewrite all keys from database again. | // RewriteAllPrincipalKeys removes any authorized principal and rewrite all keys from database again. | ||||
// Note: db.GetEngine(db.DefaultContext).Iterate does not get latest data after insert/delete, so we have to call this function | |||||
// Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function | |||||
// outside any session scope independently. | // outside any session scope independently. | ||||
func RewriteAllPrincipalKeys(ctx context.Context) error { | func RewriteAllPrincipalKeys(ctx context.Context) error { | ||||
// Don't rewrite key if internal server | // Don't rewrite key if internal server |
package models | package models | ||||
import ( | import ( | ||||
"context" | |||||
"fmt" | "fmt" | ||||
"strings" | "strings" | ||||
// GetYamlFixturesAccess returns a string containing the contents | // GetYamlFixturesAccess returns a string containing the contents | ||||
// for the access table, as recalculated using repo.RecalculateAccesses() | // for the access table, as recalculated using repo.RecalculateAccesses() | ||||
func GetYamlFixturesAccess() (string, error) { | |||||
func GetYamlFixturesAccess(ctx context.Context) (string, error) { | |||||
repos := make([]*repo_model.Repository, 0, 50) | repos := make([]*repo_model.Repository, 0, 50) | ||||
if err := db.GetEngine(db.DefaultContext).Find(&repos); err != nil { | |||||
if err := db.GetEngine(ctx).Find(&repos); err != nil { | |||||
return "", err | return "", err | ||||
} | } | ||||
for _, repo := range repos { | for _, repo := range repos { | ||||
repo.MustOwner(db.DefaultContext) | |||||
if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil { | |||||
repo.MustOwner(ctx) | |||||
if err := access_model.RecalculateAccesses(ctx, repo); err != nil { | |||||
return "", err | return "", err | ||||
} | } | ||||
} | } | ||||
var b strings.Builder | var b strings.Builder | ||||
accesses := make([]*access_model.Access, 0, 200) | accesses := make([]*access_model.Access, 0, 200) | ||||
if err := db.GetEngine(db.DefaultContext).OrderBy("user_id, repo_id").Find(&accesses); err != nil { | |||||
if err := db.GetEngine(ctx).OrderBy("user_id, repo_id").Find(&accesses); err != nil { | |||||
return "", err | return "", err | ||||
} | } | ||||
package models | package models | ||||
import ( | import ( | ||||
"context" | |||||
"os" | "os" | ||||
"path/filepath" | "path/filepath" | ||||
"testing" | "testing" | ||||
"code.gitea.io/gitea/models/db" | |||||
"code.gitea.io/gitea/models/unittest" | "code.gitea.io/gitea/models/unittest" | ||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
func TestFixtureGeneration(t *testing.T) { | func TestFixtureGeneration(t *testing.T) { | ||||
assert.NoError(t, unittest.PrepareTestDatabase()) | assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
test := func(gen func() (string, error), name string) { | |||||
expected, err := gen() | |||||
test := func(ctx context.Context, gen func(ctx context.Context) (string, error), name string) { | |||||
expected, err := gen(ctx) | |||||
if !assert.NoError(t, err) { | if !assert.NoError(t, err) { | ||||
return | return | ||||
} | } | ||||
assert.EqualValues(t, expected, data, "Differences detected for %s", p) | assert.EqualValues(t, expected, data, "Differences detected for %s", p) | ||||
} | } | ||||
test(GetYamlFixturesAccess, "access") | |||||
test(db.DefaultContext, GetYamlFixturesAccess, "access") | |||||
} | } |
} | } | ||||
// RemoveOrgUser removes user from given organization. | // RemoveOrgUser removes user from given organization. | ||||
func RemoveOrgUser(orgID, userID int64) error { | |||||
ctx, committer, err := db.TxContext(db.DefaultContext) | |||||
func RemoveOrgUser(ctx context.Context, orgID, userID int64) error { | |||||
ctx, committer, err := db.TxContext(ctx) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } |
import ( | import ( | ||||
"testing" | "testing" | ||||
"code.gitea.io/gitea/models/db" | |||||
"code.gitea.io/gitea/models/organization" | "code.gitea.io/gitea/models/organization" | ||||
"code.gitea.io/gitea/models/unittest" | "code.gitea.io/gitea/models/unittest" | ||||
user_model "code.gitea.io/gitea/models/user" | user_model "code.gitea.io/gitea/models/user" | ||||
// remove a user that is a member | // remove a user that is a member | ||||
unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{UID: 4, OrgID: 3}) | unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{UID: 4, OrgID: 3}) | ||||
prevNumMembers := org.NumMembers | prevNumMembers := org.NumMembers | ||||
assert.NoError(t, RemoveOrgUser(org.ID, 4)) | |||||
assert.NoError(t, RemoveOrgUser(db.DefaultContext, org.ID, 4)) | |||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 4, OrgID: 3}) | unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 4, OrgID: 3}) | ||||
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | ||||
assert.Equal(t, prevNumMembers-1, org.NumMembers) | assert.Equal(t, prevNumMembers-1, org.NumMembers) | ||||
// remove a user that is not a member | // remove a user that is not a member | ||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3}) | unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3}) | ||||
prevNumMembers = org.NumMembers | prevNumMembers = org.NumMembers | ||||
assert.NoError(t, RemoveOrgUser(org.ID, 5)) | |||||
assert.NoError(t, RemoveOrgUser(db.DefaultContext, org.ID, 5)) | |||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3}) | unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3}) | ||||
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | ||||
assert.Equal(t, prevNumMembers, org.NumMembers) | assert.Equal(t, prevNumMembers, org.NumMembers) | ||||
if unittest.BeanExists(t, &organization.OrgUser{OrgID: orgID, UID: userID}) { | if unittest.BeanExists(t, &organization.OrgUser{OrgID: orgID, UID: userID}) { | ||||
expectedNumMembers-- | expectedNumMembers-- | ||||
} | } | ||||
assert.NoError(t, RemoveOrgUser(orgID, userID)) | |||||
assert.NoError(t, RemoveOrgUser(db.DefaultContext, orgID, userID)) | |||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: orgID, UID: userID}) | unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: orgID, UID: userID}) | ||||
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}) | org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}) | ||||
assert.EqualValues(t, expectedNumMembers, org.NumMembers) | assert.EqualValues(t, expectedNumMembers, org.NumMembers) | ||||
testSuccess(3, 4) | testSuccess(3, 4) | ||||
testSuccess(3, 4) | testSuccess(3, 4) | ||||
err := RemoveOrgUser(7, 5) | |||||
err := RemoveOrgUser(db.DefaultContext, 7, 5) | |||||
assert.Error(t, err) | assert.Error(t, err) | ||||
assert.True(t, organization.IsErrLastOrgOwner(err)) | assert.True(t, organization.IsErrLastOrgOwner(err)) | ||||
unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: 7, UID: 5}) | unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: 7, UID: 5}) |
} | } | ||||
// GetUserRepositories returns a list of repositories of given user. | // GetUserRepositories returns a list of repositories of given user. | ||||
func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error) { | |||||
func GetUserRepositories(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { | |||||
if len(opts.OrderBy) == 0 { | if len(opts.OrderBy) == 0 { | ||||
opts.OrderBy = "updated_unix DESC" | opts.OrderBy = "updated_unix DESC" | ||||
} | } | ||||
cond = cond.And(builder.In("lower_name", opts.LowerNames)) | cond = cond.And(builder.In("lower_name", opts.LowerNames)) | ||||
} | } | ||||
sess := db.GetEngine(db.DefaultContext) | |||||
sess := db.GetEngine(ctx) | |||||
count, err := sess.Where(cond).Count(new(Repository)) | count, err := sess.Where(cond).Count(new(Repository)) | ||||
if err != nil { | if err != nil { |
} | } | ||||
// WatchRepoMode watch repository in specific mode. | // WatchRepoMode watch repository in specific mode. | ||||
func WatchRepoMode(userID, repoID int64, mode WatchMode) (err error) { | |||||
func WatchRepoMode(ctx context.Context, userID, repoID int64, mode WatchMode) (err error) { | |||||
var watch Watch | var watch Watch | ||||
if watch, err = GetWatch(db.DefaultContext, userID, repoID); err != nil { | |||||
if watch, err = GetWatch(ctx, userID, repoID); err != nil { | |||||
return err | return err | ||||
} | } | ||||
return watchRepoMode(db.DefaultContext, watch, mode) | |||||
return watchRepoMode(ctx, watch, mode) | |||||
} | } | ||||
// WatchRepo watch or unwatch repository. | // WatchRepo watch or unwatch repository. |
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) | ||||
assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeAuto)) | |||||
assert.NoError(t, repo_model.WatchRepoMode(db.DefaultContext, 12, 1, repo_model.WatchModeAuto)) | |||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | ||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeAuto}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeAuto}, 1) | ||||
assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeNormal)) | |||||
assert.NoError(t, repo_model.WatchRepoMode(db.DefaultContext, 12, 1, repo_model.WatchModeNormal)) | |||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | ||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeNormal}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeNormal}, 1) | ||||
assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeDont)) | |||||
assert.NoError(t, repo_model.WatchRepoMode(db.DefaultContext, 12, 1, repo_model.WatchModeDont)) | |||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) | ||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeDont}, 1) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeDont}, 1) | ||||
assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeNone)) | |||||
assert.NoError(t, repo_model.WatchRepoMode(db.DefaultContext, 12, 1, repo_model.WatchModeNone)) | |||||
unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) | unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) | ||||
} | } |
} | } | ||||
// SaveAppStateContent saves the app state item to database | // SaveAppStateContent saves the app state item to database | ||||
func SaveAppStateContent(key, content string) error { | |||||
return db.WithTx(db.DefaultContext, func(ctx context.Context) error { | |||||
func SaveAppStateContent(ctx context.Context, key, content string) error { | |||||
return db.WithTx(ctx, func(ctx context.Context) error { | |||||
eng := db.GetEngine(ctx) | eng := db.GetEngine(ctx) | ||||
// try to update existing row | // try to update existing row | ||||
res, err := eng.Exec("UPDATE app_state SET revision=revision+1, content=? WHERE id=?", content, key) | res, err := eng.Exec("UPDATE app_state SET revision=revision+1, content=? WHERE id=?", content, key) | ||||
} | } | ||||
// GetAppStateContent gets an app state from database | // GetAppStateContent gets an app state from database | ||||
func GetAppStateContent(key string) (content string, err error) { | |||||
e := db.GetEngine(db.DefaultContext) | |||||
func GetAppStateContent(ctx context.Context, key string) (content string, err error) { | |||||
e := db.GetEngine(ctx) | |||||
appState := &AppState{ID: key} | appState := &AppState{ID: key} | ||||
has, err := e.Get(appState) | has, err := e.Get(appState) | ||||
if err != nil { | if err != nil { |
package system | package system | ||||
import "context" | |||||
// StateStore is the interface to get/set app state items | // StateStore is the interface to get/set app state items | ||||
type StateStore interface { | type StateStore interface { | ||||
Get(item StateItem) error | |||||
Set(item StateItem) error | |||||
Get(ctx context.Context, item StateItem) error | |||||
Set(ctx context.Context, item StateItem) error | |||||
} | } | ||||
// StateItem provides the name for a state item. the name will be used to generate filenames, etc | // StateItem provides the name for a state item. the name will be used to generate filenames, etc |
import ( | import ( | ||||
"testing" | "testing" | ||||
"code.gitea.io/gitea/models/db" | |||||
"code.gitea.io/gitea/models/unittest" | "code.gitea.io/gitea/models/unittest" | ||||
"github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
as := &DBStore{} | as := &DBStore{} | ||||
item1 := new(testItem1) | item1 := new(testItem1) | ||||
assert.NoError(t, as.Get(item1)) | |||||
assert.NoError(t, as.Get(db.DefaultContext, item1)) | |||||
assert.Equal(t, "", item1.Val1) | assert.Equal(t, "", item1.Val1) | ||||
assert.EqualValues(t, 0, item1.Val2) | assert.EqualValues(t, 0, item1.Val2) | ||||
item1 = new(testItem1) | item1 = new(testItem1) | ||||
item1.Val1 = "a" | item1.Val1 = "a" | ||||
item1.Val2 = 2 | item1.Val2 = 2 | ||||
assert.NoError(t, as.Set(item1)) | |||||
assert.NoError(t, as.Set(db.DefaultContext, item1)) | |||||
item2 := new(testItem2) | item2 := new(testItem2) | ||||
item2.K = "V" | item2.K = "V" | ||||
assert.NoError(t, as.Set(item2)) | |||||
assert.NoError(t, as.Set(db.DefaultContext, item2)) | |||||
item1 = new(testItem1) | item1 = new(testItem1) | ||||
assert.NoError(t, as.Get(item1)) | |||||
assert.NoError(t, as.Get(db.DefaultContext, item1)) | |||||
assert.Equal(t, "a", item1.Val1) | assert.Equal(t, "a", item1.Val1) | ||||
assert.EqualValues(t, 2, item1.Val2) | assert.EqualValues(t, 2, item1.Val2) | ||||
item2 = new(testItem2) | item2 = new(testItem2) | ||||
assert.NoError(t, as.Get(item2)) | |||||
assert.NoError(t, as.Get(db.DefaultContext, item2)) | |||||
assert.Equal(t, "V", item2.K) | assert.Equal(t, "V", item2.K) | ||||
} | } |
package system | package system | ||||
import ( | import ( | ||||
"context" | |||||
"code.gitea.io/gitea/models/system" | "code.gitea.io/gitea/models/system" | ||||
"code.gitea.io/gitea/modules/json" | "code.gitea.io/gitea/modules/json" | ||||
type DBStore struct{} | type DBStore struct{} | ||||
// Get reads the state item | // Get reads the state item | ||||
func (f *DBStore) Get(item StateItem) error { | |||||
content, err := system.GetAppStateContent(item.Name()) | |||||
func (f *DBStore) Get(ctx context.Context, item StateItem) error { | |||||
content, err := system.GetAppStateContent(ctx, item.Name()) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Set saves the state item | // Set saves the state item | ||||
func (f *DBStore) Set(item StateItem) error { | |||||
func (f *DBStore) Set(ctx context.Context, item StateItem) error { | |||||
b, err := json.Marshal(item) | b, err := json.Marshal(item) | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
return system.SaveAppStateContent(item.Name(), util.BytesToReadOnlyString(b)) | |||||
return system.SaveAppStateContent(ctx, item.Name(), util.BytesToReadOnlyString(b)) | |||||
} | } |
package updatechecker | package updatechecker | ||||
import ( | import ( | ||||
"context" | |||||
"io" | "io" | ||||
"net/http" | "net/http" | ||||
return err | return err | ||||
} | } | ||||
return UpdateRemoteVersion(respData.Latest.Version) | |||||
return UpdateRemoteVersion(req.Context(), respData.Latest.Version) | |||||
} | } | ||||
// UpdateRemoteVersion updates the latest available version of Gitea | // UpdateRemoteVersion updates the latest available version of Gitea | ||||
func UpdateRemoteVersion(version string) (err error) { | |||||
return system.AppState.Set(&CheckerState{LatestVersion: version}) | |||||
func UpdateRemoteVersion(ctx context.Context, version string) (err error) { | |||||
return system.AppState.Set(ctx, &CheckerState{LatestVersion: version}) | |||||
} | } | ||||
// GetRemoteVersion returns the current remote version (or currently installed version if fail to fetch from DB) | // GetRemoteVersion returns the current remote version (or currently installed version if fail to fetch from DB) | ||||
func GetRemoteVersion() string { | |||||
func GetRemoteVersion(ctx context.Context) string { | |||||
item := new(CheckerState) | item := new(CheckerState) | ||||
if err := system.AppState.Get(item); err != nil { | |||||
if err := system.AppState.Get(ctx, item); err != nil { | |||||
return "" | return "" | ||||
} | } | ||||
return item.LatestVersion | return item.LatestVersion | ||||
} | } | ||||
// GetNeedUpdate returns true whether a newer version of Gitea is available | // GetNeedUpdate returns true whether a newer version of Gitea is available | ||||
func GetNeedUpdate() bool { | |||||
func GetNeedUpdate(ctx context.Context) bool { | |||||
curVer, err := version.NewVersion(setting.AppVer) | curVer, err := version.NewVersion(setting.AppVer) | ||||
if err != nil { | if err != nil { | ||||
// return false to fail silently | // return false to fail silently | ||||
return false | return false | ||||
} | } | ||||
remoteVerStr := GetRemoteVersion() | |||||
remoteVerStr := GetRemoteVersion(ctx) | |||||
if remoteVerStr == "" { | if remoteVerStr == "" { | ||||
// no remote version is known | // no remote version is known | ||||
return false | return false |
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
if err := models.RemoveOrgUser(ctx.Org.Organization.ID, member.ID); err != nil { | |||||
if err := models.RemoveOrgUser(ctx, ctx.Org.Organization.ID, member.ID); err != nil { | |||||
ctx.Error(http.StatusInternalServerError, "RemoveOrgUser", err) | ctx.Error(http.StatusInternalServerError, "RemoveOrgUser", err) | ||||
} | } | ||||
ctx.Status(http.StatusNoContent) | ctx.Status(http.StatusNoContent) |
// "404": | // "404": | ||||
// "$ref": "#/responses/notFound" | // "$ref": "#/responses/notFound" | ||||
if err := org.DeleteOrganization(ctx.Org.Organization); err != nil { | |||||
if err := org.DeleteOrganization(ctx, ctx.Org.Organization); err != nil { | |||||
ctx.Error(http.StatusInternalServerError, "DeleteOrganization", err) | ctx.Error(http.StatusInternalServerError, "DeleteOrganization", err) | ||||
return | return | ||||
} | } |
func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { | func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { | ||||
opts := utils.GetListOptions(ctx) | opts := utils.GetListOptions(ctx) | ||||
repos, count, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
repos, count, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
Actor: u, | Actor: u, | ||||
Private: private, | Private: private, | ||||
ListOptions: opts, | ListOptions: opts, |
func syncAppConfForGit(ctx context.Context) error { | func syncAppConfForGit(ctx context.Context) error { | ||||
runtimeState := new(system.RuntimeState) | runtimeState := new(system.RuntimeState) | ||||
if err := system.AppState.Get(runtimeState); err != nil { | |||||
if err := system.AppState.Get(ctx, runtimeState); err != nil { | |||||
return err | return err | ||||
} | } | ||||
log.Info("re-write ssh public keys ...") | log.Info("re-write ssh public keys ...") | ||||
mustInitCtx(ctx, asymkey_model.RewriteAllPublicKeys) | mustInitCtx(ctx, asymkey_model.RewriteAllPublicKeys) | ||||
return system.AppState.Set(runtimeState) | |||||
return system.AppState.Set(ctx, runtimeState) | |||||
} | } | ||||
return nil | return nil | ||||
} | } |
func Dashboard(ctx *context.Context) { | func Dashboard(ctx *context.Context) { | ||||
ctx.Data["Title"] = ctx.Tr("admin.dashboard") | ctx.Data["Title"] = ctx.Tr("admin.dashboard") | ||||
ctx.Data["PageIsAdminDashboard"] = true | ctx.Data["PageIsAdminDashboard"] = true | ||||
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate() | |||||
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion() | |||||
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate(ctx) | |||||
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion(ctx) | |||||
// FIXME: update periodically | // FIXME: update periodically | ||||
updateSystemStatus() | updateSystemStatus() | ||||
ctx.Data["SysStatus"] = sysStatus | ctx.Data["SysStatus"] = sysStatus |
ctx.Error(http.StatusNotFound) | ctx.Error(http.StatusNotFound) | ||||
return | return | ||||
} | } | ||||
err = models.RemoveOrgUser(org.ID, uid) | |||||
err = models.RemoveOrgUser(ctx, org.ID, uid) | |||||
if organization.IsErrLastOrgOwner(err) { | if organization.IsErrLastOrgOwner(err) { | ||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner")) | ctx.Flash.Error(ctx.Tr("form.last_org_owner")) | ||||
ctx.JSONRedirect(ctx.Org.OrgLink + "/members") | ctx.JSONRedirect(ctx.Org.OrgLink + "/members") | ||||
return | return | ||||
} | } | ||||
case "leave": | case "leave": | ||||
err = models.RemoveOrgUser(org.ID, ctx.Doer.ID) | |||||
err = models.RemoveOrgUser(ctx, org.ID, ctx.Doer.ID) | |||||
if err == nil { | if err == nil { | ||||
ctx.Flash.Success(ctx.Tr("form.organization_leave_success", org.DisplayName())) | ctx.Flash.Success(ctx.Tr("form.organization_leave_success", org.DisplayName())) | ||||
ctx.JSON(http.StatusOK, map[string]any{ | ctx.JSON(http.StatusOK, map[string]any{ |
// update forks visibility | // update forks visibility | ||||
if visibilityChanged { | if visibilityChanged { | ||||
repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos}, | Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos}, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
return | return | ||||
} | } | ||||
if err := org_service.DeleteOrganization(ctx.Org.Organization); err != nil { | |||||
if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization); err != nil { | |||||
if models.IsErrUserOwnRepos(err) { | if models.IsErrUserOwnRepos(err) { | ||||
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) | ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) | ||||
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") | ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") |
"net/http" | "net/http" | ||||
"testing" | "testing" | ||||
"code.gitea.io/gitea/models/db" | |||||
repo_model "code.gitea.io/gitea/models/repo" | repo_model "code.gitea.io/gitea/models/repo" | ||||
"code.gitea.io/gitea/models/unittest" | "code.gitea.io/gitea/models/unittest" | ||||
"code.gitea.io/gitea/modules/contexttest" | "code.gitea.io/gitea/modules/contexttest" | ||||
ctx.Req.Form.Set("state", "open") | ctx.Req.Form.Set("state", "open") | ||||
// Assume: User 30 has access to two Repos with Issues, one of the Repos being archived. | // Assume: User 30 has access to two Repos with Issues, one of the Repos being archived. | ||||
repos, _, _ := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{Actor: ctx.Doer}) | |||||
repos, _, _ := repo_model.GetUserRepositories(db.DefaultContext, &repo_model.SearchRepoOptions{Actor: ctx.Doer}) | |||||
assert.Len(t, repos, 3) | assert.Len(t, repos, 3) | ||||
IsArchived := make(map[int64]bool) | IsArchived := make(map[int64]bool) | ||||
NumIssues := make(map[int64]int) | NumIssues := make(map[int64]int) |
ctx.Data["IsPackagesPage"] = true | ctx.Data["IsPackagesPage"] = true | ||||
ctx.Data["PackageDescriptor"] = pd | ctx.Data["PackageDescriptor"] = pd | ||||
repos, _, _ := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
repos, _, _ := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
Actor: pd.Owner, | Actor: pd.Owner, | ||||
Private: true, | Private: true, | ||||
}) | }) |
return | return | ||||
} | } | ||||
userRepos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
userRepos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
Actor: ctxUser, | Actor: ctxUser, | ||||
Private: true, | Private: true, | ||||
ListOptions: db.ListOptions{ | ListOptions: db.ListOptions{ | ||||
ctx.Data["Dirs"] = repoNames | ctx.Data["Dirs"] = repoNames | ||||
ctx.Data["ReposMap"] = repos | ctx.Data["ReposMap"] = repos | ||||
} else { | } else { | ||||
repos, count64, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{Actor: ctxUser, Private: true, ListOptions: opts}) | |||||
repos, count64, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{Actor: ctxUser, Private: true, ListOptions: opts}) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetUserRepositories", err) | ctx.ServerError("GetUserRepositories", err) | ||||
return | return |
package auth | package auth | ||||
import ( | import ( | ||||
"context" | |||||
"net/http" | "net/http" | ||||
"code.gitea.io/gitea/models/db" | |||||
user_model "code.gitea.io/gitea/models/user" | user_model "code.gitea.io/gitea/models/user" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
) | ) | ||||
// object for that uid. | // object for that uid. | ||||
// Returns nil if there is no user uid stored in the session. | // Returns nil if there is no user uid stored in the session. | ||||
func (s *Session) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { | func (s *Session) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { | ||||
user := SessionUser(sess) | |||||
user := SessionUser(req.Context(), sess) | |||||
if user != nil { | if user != nil { | ||||
return user, nil | return user, nil | ||||
} | } | ||||
} | } | ||||
// SessionUser returns the user object corresponding to the "uid" session variable. | // SessionUser returns the user object corresponding to the "uid" session variable. | ||||
func SessionUser(sess SessionStore) *user_model.User { | |||||
func SessionUser(ctx context.Context, sess SessionStore) *user_model.User { | |||||
if sess == nil { | if sess == nil { | ||||
return nil | return nil | ||||
} | } | ||||
} | } | ||||
// Get user object | // Get user object | ||||
user, err := user_model.GetUserByID(db.DefaultContext, id) | |||||
user, err := user_model.GetUserByID(ctx, id) | |||||
if err != nil { | if err != nil { | ||||
if !user_model.IsErrUserNotExist(err) { | if !user_model.IsErrUserNotExist(err) { | ||||
log.Error("GetUserById: %v", err) | log.Error("GetUserById: %v", err) |
) | ) | ||||
// DeleteOrganization completely and permanently deletes everything of organization. | // DeleteOrganization completely and permanently deletes everything of organization. | ||||
func DeleteOrganization(org *org_model.Organization) error { | |||||
ctx, commiter, err := db.TxContext(db.DefaultContext) | |||||
func DeleteOrganization(ctx context.Context, org *org_model.Organization) error { | |||||
ctx, commiter, err := db.TxContext(ctx) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } |
"testing" | "testing" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/models/db" | |||||
"code.gitea.io/gitea/models/organization" | "code.gitea.io/gitea/models/organization" | ||||
"code.gitea.io/gitea/models/unittest" | "code.gitea.io/gitea/models/unittest" | ||||
user_model "code.gitea.io/gitea/models/user" | user_model "code.gitea.io/gitea/models/user" | ||||
func TestDeleteOrganization(t *testing.T) { | func TestDeleteOrganization(t *testing.T) { | ||||
assert.NoError(t, unittest.PrepareTestDatabase()) | assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6}) | org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6}) | ||||
assert.NoError(t, DeleteOrganization(org)) | |||||
assert.NoError(t, DeleteOrganization(db.DefaultContext, org)) | |||||
unittest.AssertNotExistsBean(t, &organization.Organization{ID: 6}) | unittest.AssertNotExistsBean(t, &organization.Organization{ID: 6}) | ||||
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) | unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) | ||||
unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) | unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) | ||||
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) | ||||
err := DeleteOrganization(org) | |||||
err := DeleteOrganization(db.DefaultContext, org) | |||||
assert.Error(t, err) | assert.Error(t, err) | ||||
assert.True(t, models.IsErrUserOwnRepos(err)) | assert.True(t, models.IsErrUserOwnRepos(err)) | ||||
user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) | user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) | ||||
assert.Error(t, DeleteOrganization(user)) | |||||
assert.Error(t, DeleteOrganization(db.DefaultContext, user)) | |||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) | unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) | ||||
} | } |
} | } | ||||
return err | return err | ||||
} | } | ||||
repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
Actor: ctxUser, | Actor: ctxUser, | ||||
Private: true, | Private: true, | ||||
ListOptions: db.ListOptions{ | ListOptions: db.ListOptions{ |
log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v\nStacktrace: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, e, log.Stack(2)) | log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v\nStacktrace: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, e, log.Stack(2)) | ||||
} | } | ||||
// fixme: Because ctx is canceled here, so the db.DefaultContext is needed. | // fixme: Because ctx is canceled here, so the db.DefaultContext is needed. | ||||
ctx := db.DefaultContext | |||||
if err == nil { | if err == nil { | ||||
err = admin_model.FinishMigrateTask(db.DefaultContext, t) | |||||
err = admin_model.FinishMigrateTask(ctx, t) | |||||
if err == nil { | if err == nil { | ||||
notify_service.MigrateRepository(db.DefaultContext, t.Doer, t.Owner, t.Repo) | |||||
notify_service.MigrateRepository(ctx, t.Doer, t.Owner, t.Repo) | |||||
return | return | ||||
} | } | ||||
t.EndTime = timeutil.TimeStampNow() | t.EndTime = timeutil.TimeStampNow() | ||||
t.Status = structs.TaskStatusFailed | t.Status = structs.TaskStatusFailed | ||||
t.Message = err.Error() | t.Message = err.Error() | ||||
// fixme: Because ctx is canceled here, so the db.DefaultContext is needed. | |||||
if err := t.UpdateCols(db.DefaultContext, "status", "message", "end_time"); err != nil { | |||||
if err := t.UpdateCols(ctx, "status", "message", "end_time"); err != nil { | |||||
log.Error("Task UpdateCols failed: %v", err) | log.Error("Task UpdateCols failed: %v", err) | ||||
} | } | ||||
// An alternative option here would be write a DeleteAllRepositoriesForUserID function which would delete all of the repos | // An alternative option here would be write a DeleteAllRepositoriesForUserID function which would delete all of the repos | ||||
// but such a function would likely get out of date | // but such a function would likely get out of date | ||||
for { | for { | ||||
repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ | |||||
repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ | |||||
ListOptions: db.ListOptions{ | ListOptions: db.ListOptions{ | ||||
PageSize: repo_model.RepositoryListDefaultPageSize, | PageSize: repo_model.RepositoryListDefaultPageSize, | ||||
Page: 1, | Page: 1, | ||||
break | break | ||||
} | } | ||||
for _, org := range orgs { | for _, org := range orgs { | ||||
if err := models.RemoveOrgUser(org.ID, u.ID); err != nil { | |||||
if err := models.RemoveOrgUser(ctx, org.ID, u.ID); err != nil { | |||||
if organization.IsErrLastOrgOwner(err) { | if organization.IsErrLastOrgOwner(err) { | ||||
err = organization.DeleteOrganization(ctx, org) | err = organization.DeleteOrganization(ctx, org) | ||||
} | } |
orgUsers := make([]*organization.OrgUser, 0, 10) | orgUsers := make([]*organization.OrgUser, 0, 10) | ||||
assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&orgUsers, &organization.OrgUser{UID: userID})) | assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&orgUsers, &organization.OrgUser{UID: userID})) | ||||
for _, orgUser := range orgUsers { | for _, orgUser := range orgUsers { | ||||
if err := models.RemoveOrgUser(orgUser.OrgID, orgUser.UID); err != nil { | |||||
if err := models.RemoveOrgUser(db.DefaultContext, orgUser.OrgID, orgUser.UID); err != nil { | |||||
assert.True(t, organization.IsErrLastOrgOwner(err)) | assert.True(t, organization.IsErrLastOrgOwner(err)) | ||||
return | return | ||||
} | } |
assert.True(t, isMember, "Membership should be added to the right team") | assert.True(t, isMember, "Membership should be added to the right team") | ||||
err = models.RemoveTeamMember(db.DefaultContext, team, user.ID) | err = models.RemoveTeamMember(db.DefaultContext, team, user.ID) | ||||
assert.NoError(t, err) | assert.NoError(t, err) | ||||
err = models.RemoveOrgUser(usersOrgs[0].ID, user.ID) | |||||
err = models.RemoveOrgUser(db.DefaultContext, usersOrgs[0].ID, user.ID) | |||||
assert.NoError(t, err) | assert.NoError(t, err) | ||||
} else { | } else { | ||||
// assert members of LDAP group "cn=admin_staff" keep initial team membership since mapped team does not exist | // assert members of LDAP group "cn=admin_staff" keep initial team membership since mapped team does not exist |