code.gitea.io/gitea@v1.21.7/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  	"strings"
    11  
    12  	"code.gitea.io/gitea/models"
    13  	"code.gitea.io/gitea/models/db"
    14  	repo_model "code.gitea.io/gitea/models/repo"
    15  	user_model "code.gitea.io/gitea/models/user"
    16  	"code.gitea.io/gitea/models/webhook"
    17  	"code.gitea.io/gitea/modules/base"
    18  	"code.gitea.io/gitea/modules/context"
    19  	"code.gitea.io/gitea/modules/log"
    20  	repo_module "code.gitea.io/gitea/modules/repository"
    21  	"code.gitea.io/gitea/modules/setting"
    22  	"code.gitea.io/gitea/modules/web"
    23  	shared_user "code.gitea.io/gitea/routers/web/shared/user"
    24  	user_setting "code.gitea.io/gitea/routers/web/user/setting"
    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  	nameChanged := org.Name != form.Name
    75  
    76  	// Check if organization name has been changed.
    77  	if nameChanged {
    78  		err := user_service.RenameUser(ctx, org.AsUser(), form.Name)
    79  		switch {
    80  		case user_model.IsErrUserAlreadyExist(err):
    81  			ctx.Data["OrgName"] = true
    82  			ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
    83  			return
    84  		case db.IsErrNameReserved(err):
    85  			ctx.Data["OrgName"] = true
    86  			ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
    87  			return
    88  		case db.IsErrNamePatternNotAllowed(err):
    89  			ctx.Data["OrgName"] = true
    90  			ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
    91  			return
    92  		case err != nil:
    93  			ctx.ServerError("org_service.RenameOrganization", err)
    94  			return
    95  		}
    96  
    97  		// reset ctx.org.OrgLink with new name
    98  		ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(form.Name)
    99  		log.Trace("Organization name changed: %s -> %s", org.Name, form.Name)
   100  	}
   101  
   102  	// In case it's just a case change.
   103  	org.Name = form.Name
   104  	org.LowerName = strings.ToLower(form.Name)
   105  
   106  	if ctx.Doer.IsAdmin {
   107  		org.MaxRepoCreation = form.MaxRepoCreation
   108  	}
   109  
   110  	org.FullName = form.FullName
   111  	org.Email = form.Email
   112  	org.Description = form.Description
   113  	org.Website = form.Website
   114  	org.Location = form.Location
   115  	org.RepoAdminChangeTeamAccess = form.RepoAdminChangeTeamAccess
   116  
   117  	visibilityChanged := form.Visibility != org.Visibility
   118  	org.Visibility = form.Visibility
   119  
   120  	if err := user_model.UpdateUser(ctx, org.AsUser(), false); err != nil {
   121  		ctx.ServerError("UpdateUser", err)
   122  		return
   123  	}
   124  
   125  	// update forks visibility
   126  	if visibilityChanged {
   127  		repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{
   128  			Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos},
   129  		})
   130  		if err != nil {
   131  			ctx.ServerError("GetRepositories", err)
   132  			return
   133  		}
   134  		for _, repo := range repos {
   135  			repo.OwnerName = org.Name
   136  			if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
   137  				ctx.ServerError("UpdateRepository", err)
   138  				return
   139  			}
   140  		}
   141  	}
   142  
   143  	log.Trace("Organization setting updated: %s", org.Name)
   144  	ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success"))
   145  	ctx.Redirect(ctx.Org.OrgLink + "/settings")
   146  }
   147  
   148  // SettingsAvatar response for change avatar on settings page
   149  func SettingsAvatar(ctx *context.Context) {
   150  	form := web.GetForm(ctx).(*forms.AvatarForm)
   151  	form.Source = forms.AvatarLocal
   152  	if err := user_setting.UpdateAvatarSetting(ctx, form, ctx.Org.Organization.AsUser()); err != nil {
   153  		ctx.Flash.Error(err.Error())
   154  	} else {
   155  		ctx.Flash.Success(ctx.Tr("org.settings.update_avatar_success"))
   156  	}
   157  
   158  	ctx.Redirect(ctx.Org.OrgLink + "/settings")
   159  }
   160  
   161  // SettingsDeleteAvatar response for delete avatar on settings page
   162  func SettingsDeleteAvatar(ctx *context.Context) {
   163  	if err := user_service.DeleteAvatar(ctx.Org.Organization.AsUser()); err != nil {
   164  		ctx.Flash.Error(err.Error())
   165  	}
   166  
   167  	ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
   168  }
   169  
   170  // SettingsDelete response for deleting an organization
   171  func SettingsDelete(ctx *context.Context) {
   172  	ctx.Data["Title"] = ctx.Tr("org.settings")
   173  	ctx.Data["PageIsOrgSettings"] = true
   174  	ctx.Data["PageIsSettingsDelete"] = true
   175  
   176  	if ctx.Req.Method == "POST" {
   177  		if ctx.Org.Organization.Name != ctx.FormString("org_name") {
   178  			ctx.Data["Err_OrgName"] = true
   179  			ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil)
   180  			return
   181  		}
   182  
   183  		if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
   184  			if models.IsErrUserOwnRepos(err) {
   185  				ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
   186  				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
   187  			} else if models.IsErrUserOwnPackages(err) {
   188  				ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
   189  				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
   190  			} else {
   191  				ctx.ServerError("DeleteOrganization", err)
   192  			}
   193  		} else {
   194  			log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
   195  			ctx.Redirect(setting.AppSubURL + "/")
   196  		}
   197  		return
   198  	}
   199  
   200  	err := shared_user.LoadHeaderCount(ctx)
   201  	if err != nil {
   202  		ctx.ServerError("LoadHeaderCount", err)
   203  		return
   204  	}
   205  
   206  	ctx.HTML(http.StatusOK, tplSettingsDelete)
   207  }
   208  
   209  // Webhooks render webhook list page
   210  func Webhooks(ctx *context.Context) {
   211  	ctx.Data["Title"] = ctx.Tr("org.settings")
   212  	ctx.Data["PageIsOrgSettings"] = true
   213  	ctx.Data["PageIsSettingsHooks"] = true
   214  	ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks"
   215  	ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
   216  	ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
   217  
   218  	ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID})
   219  	if err != nil {
   220  		ctx.ServerError("ListWebhooksByOpts", err)
   221  		return
   222  	}
   223  
   224  	err = shared_user.LoadHeaderCount(ctx)
   225  	if err != nil {
   226  		ctx.ServerError("LoadHeaderCount", err)
   227  		return
   228  	}
   229  
   230  	ctx.Data["Webhooks"] = ws
   231  	ctx.HTML(http.StatusOK, tplSettingsHooks)
   232  }
   233  
   234  // DeleteWebhook response for delete webhook
   235  func DeleteWebhook(ctx *context.Context) {
   236  	if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
   237  		ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
   238  	} else {
   239  		ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
   240  	}
   241  
   242  	ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/hooks")
   243  }
   244  
   245  // Labels render organization labels page
   246  func Labels(ctx *context.Context) {
   247  	ctx.Data["Title"] = ctx.Tr("repo.labels")
   248  	ctx.Data["PageIsOrgSettings"] = true
   249  	ctx.Data["PageIsOrgSettingsLabels"] = true
   250  	ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
   251  
   252  	err := shared_user.LoadHeaderCount(ctx)
   253  	if err != nil {
   254  		ctx.ServerError("LoadHeaderCount", err)
   255  		return
   256  	}
   257  
   258  	ctx.HTML(http.StatusOK, tplSettingsLabels)
   259  }