code.gitea.io/gitea@v1.22.3/routers/web/org/setting.go (about)

     1  // Copyright 2014 The Gogs Authors. All rights reserved.
     2  // Copyright 2019 The Gitea Authors. All rights reserved.
     3  // SPDX-License-Identifier: MIT
     4  
     5  package org
     6  
     7  import (
     8  	"net/http"
     9  	"net/url"
    10  
    11  	"code.gitea.io/gitea/models"
    12  	"code.gitea.io/gitea/models/db"
    13  	repo_model "code.gitea.io/gitea/models/repo"
    14  	user_model "code.gitea.io/gitea/models/user"
    15  	"code.gitea.io/gitea/models/webhook"
    16  	"code.gitea.io/gitea/modules/base"
    17  	"code.gitea.io/gitea/modules/log"
    18  	"code.gitea.io/gitea/modules/optional"
    19  	repo_module "code.gitea.io/gitea/modules/repository"
    20  	"code.gitea.io/gitea/modules/setting"
    21  	"code.gitea.io/gitea/modules/web"
    22  	shared_user "code.gitea.io/gitea/routers/web/shared/user"
    23  	user_setting "code.gitea.io/gitea/routers/web/user/setting"
    24  	"code.gitea.io/gitea/services/context"
    25  	"code.gitea.io/gitea/services/forms"
    26  	org_service "code.gitea.io/gitea/services/org"
    27  	repo_service "code.gitea.io/gitea/services/repository"
    28  	user_service "code.gitea.io/gitea/services/user"
    29  )
    30  
    31  const (
    32  	// tplSettingsOptions template path for render settings
    33  	tplSettingsOptions base.TplName = "org/settings/options"
    34  	// tplSettingsDelete template path for render delete repository
    35  	tplSettingsDelete base.TplName = "org/settings/delete"
    36  	// tplSettingsHooks template path for render hook settings
    37  	tplSettingsHooks base.TplName = "org/settings/hooks"
    38  	// tplSettingsLabels template path for render labels settings
    39  	tplSettingsLabels base.TplName = "org/settings/labels"
    40  )
    41  
    42  // Settings render the main settings page
    43  func Settings(ctx *context.Context) {
    44  	ctx.Data["Title"] = ctx.Tr("org.settings")
    45  	ctx.Data["PageIsOrgSettings"] = true
    46  	ctx.Data["PageIsSettingsOptions"] = true
    47  	ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
    48  	ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
    49  	ctx.Data["ContextUser"] = ctx.ContextUser
    50  
    51  	err := shared_user.LoadHeaderCount(ctx)
    52  	if err != nil {
    53  		ctx.ServerError("LoadHeaderCount", err)
    54  		return
    55  	}
    56  
    57  	ctx.HTML(http.StatusOK, tplSettingsOptions)
    58  }
    59  
    60  // SettingsPost response for settings change submitted
    61  func SettingsPost(ctx *context.Context) {
    62  	form := web.GetForm(ctx).(*forms.UpdateOrgSettingForm)
    63  	ctx.Data["Title"] = ctx.Tr("org.settings")
    64  	ctx.Data["PageIsOrgSettings"] = true
    65  	ctx.Data["PageIsSettingsOptions"] = true
    66  	ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
    67  
    68  	if ctx.HasError() {
    69  		ctx.HTML(http.StatusOK, tplSettingsOptions)
    70  		return
    71  	}
    72  
    73  	org := ctx.Org.Organization
    74  
    75  	if org.Name != form.Name {
    76  		if err := user_service.RenameUser(ctx, org.AsUser(), form.Name); err != nil {
    77  			if user_model.IsErrUserAlreadyExist(err) {
    78  				ctx.Data["Err_Name"] = true
    79  				ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
    80  			} else if db.IsErrNameReserved(err) {
    81  				ctx.Data["Err_Name"] = true
    82  				ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
    83  			} else if db.IsErrNamePatternNotAllowed(err) {
    84  				ctx.Data["Err_Name"] = true
    85  				ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
    86  			} else {
    87  				ctx.ServerError("RenameUser", err)
    88  			}
    89  			return
    90  		}
    91  
    92  		ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(org.Name)
    93  	}
    94  
    95  	if form.Email != "" {
    96  		if err := user_service.ReplacePrimaryEmailAddress(ctx, org.AsUser(), form.Email); err != nil {
    97  			ctx.Data["Err_Email"] = true
    98  			ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSettingsOptions, &form)
    99  			return
   100  		}
   101  	}
   102  
   103  	opts := &user_service.UpdateOptions{
   104  		FullName:                  optional.Some(form.FullName),
   105  		Description:               optional.Some(form.Description),
   106  		Website:                   optional.Some(form.Website),
   107  		Location:                  optional.Some(form.Location),
   108  		Visibility:                optional.Some(form.Visibility),
   109  		RepoAdminChangeTeamAccess: optional.Some(form.RepoAdminChangeTeamAccess),
   110  	}
   111  	if ctx.Doer.IsAdmin {
   112  		opts.MaxRepoCreation = optional.Some(form.MaxRepoCreation)
   113  	}
   114  
   115  	visibilityChanged := org.Visibility != form.Visibility
   116  
   117  	if err := user_service.UpdateUser(ctx, org.AsUser(), opts); err != nil {
   118  		ctx.ServerError("UpdateUser", err)
   119  		return
   120  	}
   121  
   122  	// update forks visibility
   123  	if visibilityChanged {
   124  		repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{
   125  			Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos},
   126  		})
   127  		if err != nil {
   128  			ctx.ServerError("GetRepositories", err)
   129  			return
   130  		}
   131  		for _, repo := range repos {
   132  			repo.OwnerName = org.Name
   133  			if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
   134  				ctx.ServerError("UpdateRepository", err)
   135  				return
   136  			}
   137  		}
   138  	}
   139  
   140  	log.Trace("Organization setting updated: %s", org.Name)
   141  	ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success"))
   142  	ctx.Redirect(ctx.Org.OrgLink + "/settings")
   143  }
   144  
   145  // SettingsAvatar response for change avatar on settings page
   146  func SettingsAvatar(ctx *context.Context) {
   147  	form := web.GetForm(ctx).(*forms.AvatarForm)
   148  	form.Source = forms.AvatarLocal
   149  	if err := user_setting.UpdateAvatarSetting(ctx, form, ctx.Org.Organization.AsUser()); err != nil {
   150  		ctx.Flash.Error(err.Error())
   151  	} else {
   152  		ctx.Flash.Success(ctx.Tr("org.settings.update_avatar_success"))
   153  	}
   154  
   155  	ctx.Redirect(ctx.Org.OrgLink + "/settings")
   156  }
   157  
   158  // SettingsDeleteAvatar response for delete avatar on settings page
   159  func SettingsDeleteAvatar(ctx *context.Context) {
   160  	if err := user_service.DeleteAvatar(ctx, ctx.Org.Organization.AsUser()); err != nil {
   161  		ctx.Flash.Error(err.Error())
   162  	}
   163  
   164  	ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
   165  }
   166  
   167  // SettingsDelete response for deleting an organization
   168  func SettingsDelete(ctx *context.Context) {
   169  	ctx.Data["Title"] = ctx.Tr("org.settings")
   170  	ctx.Data["PageIsOrgSettings"] = true
   171  	ctx.Data["PageIsSettingsDelete"] = true
   172  
   173  	if ctx.Req.Method == "POST" {
   174  		if ctx.Org.Organization.Name != ctx.FormString("org_name") {
   175  			ctx.Data["Err_OrgName"] = true
   176  			ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil)
   177  			return
   178  		}
   179  
   180  		if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
   181  			if models.IsErrUserOwnRepos(err) {
   182  				ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
   183  				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
   184  			} else if models.IsErrUserOwnPackages(err) {
   185  				ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
   186  				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
   187  			} else {
   188  				ctx.ServerError("DeleteOrganization", err)
   189  			}
   190  		} else {
   191  			log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
   192  			ctx.Redirect(setting.AppSubURL + "/")
   193  		}
   194  		return
   195  	}
   196  
   197  	err := shared_user.LoadHeaderCount(ctx)
   198  	if err != nil {
   199  		ctx.ServerError("LoadHeaderCount", err)
   200  		return
   201  	}
   202  
   203  	ctx.HTML(http.StatusOK, tplSettingsDelete)
   204  }
   205  
   206  // Webhooks render webhook list page
   207  func Webhooks(ctx *context.Context) {
   208  	ctx.Data["Title"] = ctx.Tr("org.settings")
   209  	ctx.Data["PageIsOrgSettings"] = true
   210  	ctx.Data["PageIsSettingsHooks"] = true
   211  	ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks"
   212  	ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
   213  	ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
   214  
   215  	ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID})
   216  	if err != nil {
   217  		ctx.ServerError("ListWebhooksByOpts", err)
   218  		return
   219  	}
   220  
   221  	err = shared_user.LoadHeaderCount(ctx)
   222  	if err != nil {
   223  		ctx.ServerError("LoadHeaderCount", err)
   224  		return
   225  	}
   226  
   227  	ctx.Data["Webhooks"] = ws
   228  	ctx.HTML(http.StatusOK, tplSettingsHooks)
   229  }
   230  
   231  // DeleteWebhook response for delete webhook
   232  func DeleteWebhook(ctx *context.Context) {
   233  	if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
   234  		ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
   235  	} else {
   236  		ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
   237  	}
   238  
   239  	ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/hooks")
   240  }
   241  
   242  // Labels render organization labels page
   243  func Labels(ctx *context.Context) {
   244  	ctx.Data["Title"] = ctx.Tr("repo.labels")
   245  	ctx.Data["PageIsOrgSettings"] = true
   246  	ctx.Data["PageIsOrgSettingsLabels"] = true
   247  	ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
   248  
   249  	err := shared_user.LoadHeaderCount(ctx)
   250  	if err != nil {
   251  		ctx.ServerError("LoadHeaderCount", err)
   252  		return
   253  	}
   254  
   255  	ctx.HTML(http.StatusOK, tplSettingsLabels)
   256  }