Skip to content

Commit aa85d80

Browse files
authored
Merge branch 'main' into patch-actions-email-2
2 parents b7719ee + c0f24bd commit aa85d80

File tree

12 files changed

+189
-67
lines changed

12 files changed

+189
-67
lines changed

models/user/user.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,16 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error {
955955
return err
956956
}
957957

958+
// UpdateUserColsNoAutoTime update user according special columns
959+
func UpdateUserColsNoAutoTime(ctx context.Context, u *User, cols ...string) error {
960+
if err := ValidateUser(u, cols...); err != nil {
961+
return err
962+
}
963+
964+
_, err := db.GetEngine(ctx).ID(u.ID).Cols(cols...).NoAutoTime().Update(u)
965+
return err
966+
}
967+
958968
// GetInactiveUsers gets all inactive users
959969
func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, error) {
960970
cond := builder.And(

modules/indexer/issues/util.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,14 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
9797
return nil, false, err
9898
}
9999

100+
if err := issue.Repo.LoadOwner(ctx); err != nil {
101+
return nil, false, fmt.Errorf("issue.Repo.LoadOwner: %w", err)
102+
}
103+
100104
return &internal.IndexerData{
101105
ID: issue.ID,
102106
RepoID: issue.RepoID,
103-
IsPublic: !issue.Repo.IsPrivate,
107+
IsPublic: !issue.Repo.IsPrivate && issue.Repo.Owner.Visibility.IsPublic(),
104108
Title: issue.Title,
105109
Content: issue.Content,
106110
Comments: comments,

options/locale/locale_en-US.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ error404 = The page you are trying to reach either <strong>does not exist</stron
120120
error503 = The server could not complete your request. Please try again later.
121121
go_back = Go Back
122122
invalid_data = Invalid data: %v
123+
nothing_has_been_changed = Nothing has been changed.
123124

124125
never = Never
125126
unknown = Unknown
@@ -2843,6 +2844,11 @@ settings.location = Location
28432844
settings.permission = Permissions
28442845
settings.repoadminchangeteam = Repository admin can add and remove access for teams
28452846
settings.visibility = Visibility
2847+
settings.change_visibility = Change Visibility
2848+
settings.change_visibility_notices_1 = If the organization is converted to private, the repository stars will be removed and cannot be restored.
2849+
settings.change_visibility_notices_2 = Non-members will lose access to the organization’s repositories if visibility is changed to private.
2850+
settings.change_visibility_success = The visibility of organization %s has been successfully changed.
2851+
settings.visibility_desc = Change who can view the organization and its repositories.
28462852
settings.visibility.public = Public
28472853
settings.visibility.limited = Limited (Visible to authenticated users only)
28482854
settings.visibility.limited_shortname = Limited

routers/web/org/setting.go

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"code.gitea.io/gitea/modules/optional"
1818
repo_module "code.gitea.io/gitea/modules/repository"
1919
"code.gitea.io/gitea/modules/setting"
20+
"code.gitea.io/gitea/modules/structs"
2021
"code.gitea.io/gitea/modules/templates"
2122
"code.gitea.io/gitea/modules/util"
2223
"code.gitea.io/gitea/modules/web"
@@ -25,7 +26,6 @@ import (
2526
"code.gitea.io/gitea/services/context"
2627
"code.gitea.io/gitea/services/forms"
2728
org_service "code.gitea.io/gitea/services/org"
28-
repo_service "code.gitea.io/gitea/services/repository"
2929
user_service "code.gitea.io/gitea/services/user"
3030
)
3131

@@ -83,38 +83,17 @@ func SettingsPost(ctx *context.Context) {
8383
Description: optional.Some(form.Description),
8484
Website: optional.Some(form.Website),
8585
Location: optional.Some(form.Location),
86-
Visibility: optional.Some(form.Visibility),
8786
RepoAdminChangeTeamAccess: optional.Some(form.RepoAdminChangeTeamAccess),
8887
}
8988
if ctx.Doer.IsAdmin {
9089
opts.MaxRepoCreation = optional.Some(form.MaxRepoCreation)
9190
}
9291

93-
visibilityChanged := org.Visibility != form.Visibility
94-
9592
if err := user_service.UpdateUser(ctx, org.AsUser(), opts); err != nil {
9693
ctx.ServerError("UpdateUser", err)
9794
return
9895
}
9996

100-
// update forks visibility
101-
if visibilityChanged {
102-
repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{
103-
Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos},
104-
})
105-
if err != nil {
106-
ctx.ServerError("GetRepositories", err)
107-
return
108-
}
109-
for _, repo := range repos {
110-
repo.OwnerName = org.Name
111-
if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
112-
ctx.ServerError("UpdateRepository", err)
113-
return
114-
}
115-
}
116-
}
117-
11897
log.Trace("Organization setting updated: %s", org.Name)
11998
ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success"))
12099
ctx.Redirect(ctx.Org.OrgLink + "/settings")
@@ -251,3 +230,28 @@ func SettingsRenamePost(ctx *context.Context) {
251230
ctx.Flash.Success(ctx.Tr("org.settings.rename_success", oldOrgName, newOrgName))
252231
ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(newOrgName) + "/settings")
253232
}
233+
234+
// SettingsChangeVisibilityPost response for change organization visibility
235+
func SettingsChangeVisibilityPost(ctx *context.Context) {
236+
visibility, ok := structs.VisibilityModes[ctx.FormString("visibility")]
237+
if !ok {
238+
ctx.Flash.Error(ctx.Tr("invalid_data", visibility))
239+
ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings")
240+
return
241+
}
242+
243+
if ctx.Org.Organization.Visibility == visibility {
244+
ctx.Flash.Info(ctx.Tr("nothing_has_been_changed"))
245+
ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings")
246+
return
247+
}
248+
249+
if err := org_service.ChangeOrganizationVisibility(ctx, ctx.Org.Organization, visibility); err != nil {
250+
log.Error("ChangeOrganizationVisibility: %v", err)
251+
ctx.JSONError(ctx.Tr("error.occurred"))
252+
return
253+
}
254+
255+
ctx.Flash.Success(ctx.Tr("org.settings.change_visibility_success", ctx.Org.Organization.Name))
256+
ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings")
257+
}

routers/web/web.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,7 @@ func registerWebRoutes(m *web.Router) {
971971

972972
m.Post("/rename", web.Bind(forms.RenameOrgForm{}), org.SettingsRenamePost)
973973
m.Post("/delete", org.SettingsDeleteOrgPost)
974+
m.Post("/visibility", org.SettingsChangeVisibilityPost)
974975

975976
m.Group("/packages", func() {
976977
m.Get("", org.Packages)

services/forms/org.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ type UpdateOrgSettingForm struct {
4141
Description string `binding:"MaxSize(255)"`
4242
Website string `binding:"ValidUrl;MaxSize(255)"`
4343
Location string `binding:"MaxSize(50)"`
44-
Visibility structs.VisibleType
4544
MaxRepoCreation int
4645
RepoAdminChangeTeamAccess bool
4746
}

services/org/org.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ import (
88
"fmt"
99

1010
actions_model "code.gitea.io/gitea/models/actions"
11+
activities_model "code.gitea.io/gitea/models/activities"
1112
"code.gitea.io/gitea/models/db"
1213
org_model "code.gitea.io/gitea/models/organization"
1314
packages_model "code.gitea.io/gitea/models/packages"
15+
access_model "code.gitea.io/gitea/models/perm/access"
1416
repo_model "code.gitea.io/gitea/models/repo"
1517
secret_model "code.gitea.io/gitea/models/secret"
1618
user_model "code.gitea.io/gitea/models/user"
19+
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
1720
"code.gitea.io/gitea/modules/storage"
21+
"code.gitea.io/gitea/modules/structs"
1822
"code.gitea.io/gitea/modules/util"
1923
repo_service "code.gitea.io/gitea/services/repository"
2024
)
@@ -102,3 +106,70 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge
102106

103107
return nil
104108
}
109+
110+
func updateOrgRepoForVisibilityChanged(ctx context.Context, repo *repo_model.Repository, makePrivate bool) error {
111+
// Organization repository need to recalculate access table when visibility is changed.
112+
if err := access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
113+
return fmt.Errorf("recalculateTeamAccesses: %w", err)
114+
}
115+
116+
if makePrivate {
117+
if _, err := db.GetEngine(ctx).Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
118+
IsPrivate: true,
119+
}); err != nil {
120+
return err
121+
}
122+
123+
if err := repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
124+
return err
125+
}
126+
}
127+
128+
// Create/Remove git-daemon-export-ok for git-daemon...
129+
if err := repo_service.CheckDaemonExportOK(ctx, repo); err != nil {
130+
return err
131+
}
132+
133+
// If visibility is changed, we need to update the issue indexer.
134+
// Since the data in the issue indexer have field to indicate if the repo is public or not.
135+
// FIXME: it should check organization visibility instead of repository visibility only.
136+
issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
137+
138+
forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
139+
if err != nil {
140+
return fmt.Errorf("getRepositoriesByForkID: %w", err)
141+
}
142+
for i := range forkRepos {
143+
if err := updateOrgRepoForVisibilityChanged(ctx, forkRepos[i], makePrivate); err != nil {
144+
return fmt.Errorf("updateRepoForVisibilityChanged[%s]: %w", forkRepos[i].FullName(), err)
145+
}
146+
}
147+
return nil
148+
}
149+
150+
func ChangeOrganizationVisibility(ctx context.Context, org *org_model.Organization, visibility structs.VisibleType) error {
151+
if org.Visibility == visibility {
152+
return nil
153+
}
154+
155+
org.Visibility = visibility
156+
// FIXME: If it's a big forks network(forks and sub forks), the database transaction will be too long to fail.
157+
return db.WithTx(ctx, func(ctx context.Context) error {
158+
if err := user_model.UpdateUserColsNoAutoTime(ctx, org.AsUser(), "visibility"); err != nil {
159+
return err
160+
}
161+
162+
repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{
163+
Actor: org.AsUser(), Private: true, ListOptions: db.ListOptionsAll,
164+
})
165+
if err != nil {
166+
return err
167+
}
168+
for _, repo := range repos {
169+
if err := updateOrgRepoForVisibilityChanged(ctx, repo, visibility == structs.VisibleTypePrivate); err != nil {
170+
return fmt.Errorf("updateOrgRepoForVisibilityChanged: %w", err)
171+
}
172+
}
173+
return nil
174+
})
175+
}

services/repository/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ func cleanupRepository(repoID int64) {
469469
}
470470

471471
func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) error {
472-
if err := checkDaemonExportOK(ctx, repo); err != nil {
472+
if err := CheckDaemonExportOK(ctx, repo); err != nil {
473473
return fmt.Errorf("checkDaemonExportOK: %w", err)
474474
}
475475

services/repository/repository.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func MakeRepoPublic(ctx context.Context, repo *repo_model.Repository) (err error
142142
}
143143

144144
// Create/Remove git-daemon-export-ok for git-daemon...
145-
if err := checkDaemonExportOK(ctx, repo); err != nil {
145+
if err := CheckDaemonExportOK(ctx, repo); err != nil {
146146
return err
147147
}
148148

@@ -197,7 +197,7 @@ func MakeRepoPrivate(ctx context.Context, repo *repo_model.Repository) (err erro
197197
}
198198

199199
// Create/Remove git-daemon-export-ok for git-daemon...
200-
if err := checkDaemonExportOK(ctx, repo); err != nil {
200+
if err := CheckDaemonExportOK(ctx, repo); err != nil {
201201
return err
202202
}
203203

@@ -243,8 +243,8 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode
243243
return nil, -1, nil
244244
}
245245

246-
// checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
247-
func checkDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
246+
// CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
247+
func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
248248
if err := repo.LoadOwner(ctx); err != nil {
249249
return err
250250
}
@@ -314,7 +314,7 @@ func updateRepository(ctx context.Context, repo *repo_model.Repository, visibili
314314
}
315315

316316
// Create/Remove git-daemon-export-ok for git-daemon...
317-
if err := checkDaemonExportOK(ctx, repo); err != nil {
317+
if err := CheckDaemonExportOK(ctx, repo); err != nil {
318318
return err
319319
}
320320

templates/org/settings/options.tmpl

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,6 @@
2929
<input id="location" name="location" value="{{.Org.Location}}" maxlength="50">
3030
</div>
3131

32-
<div class="divider"></div>
33-
<div class="field" id="visibility_box">
34-
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
35-
<div class="field">
36-
<div class="ui radio checkbox">
37-
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if eq .CurrentVisibility 0}}checked{{end}}>
38-
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
39-
</div>
40-
</div>
41-
<div class="field">
42-
<div class="ui radio checkbox">
43-
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if eq .CurrentVisibility 1}}checked{{end}}>
44-
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
45-
</div>
46-
</div>
47-
<div class="field">
48-
<div class="ui radio checkbox">
49-
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if eq .CurrentVisibility 2}}checked{{end}}>
50-
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
51-
</div>
52-
</div>
53-
</div>
54-
5532
<div class="field" id="permission_box">
5633
<label>{{ctx.Locale.Tr "org.settings.permission"}}</label>
5734
<div class="field">

0 commit comments

Comments
 (0)