code.gitea.io/gitea@v1.21.7/routers/web/repo/setting/collaboration.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package setting
     5  
     6  import (
     7  	"net/http"
     8  	"strings"
     9  
    10  	"code.gitea.io/gitea/models/db"
    11  	"code.gitea.io/gitea/models/organization"
    12  	"code.gitea.io/gitea/models/perm"
    13  	repo_model "code.gitea.io/gitea/models/repo"
    14  	unit_model "code.gitea.io/gitea/models/unit"
    15  	user_model "code.gitea.io/gitea/models/user"
    16  	"code.gitea.io/gitea/modules/context"
    17  	"code.gitea.io/gitea/modules/log"
    18  	repo_module "code.gitea.io/gitea/modules/repository"
    19  	"code.gitea.io/gitea/modules/setting"
    20  	"code.gitea.io/gitea/routers/utils"
    21  	"code.gitea.io/gitea/services/mailer"
    22  	org_service "code.gitea.io/gitea/services/org"
    23  	repo_service "code.gitea.io/gitea/services/repository"
    24  )
    25  
    26  // Collaboration render a repository's collaboration page
    27  func Collaboration(ctx *context.Context) {
    28  	ctx.Data["Title"] = ctx.Tr("repo.settings.collaboration")
    29  	ctx.Data["PageIsSettingsCollaboration"] = true
    30  
    31  	users, err := repo_model.GetCollaborators(ctx, ctx.Repo.Repository.ID, db.ListOptions{})
    32  	if err != nil {
    33  		ctx.ServerError("GetCollaborators", err)
    34  		return
    35  	}
    36  	ctx.Data["Collaborators"] = users
    37  
    38  	teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
    39  	if err != nil {
    40  		ctx.ServerError("GetRepoTeams", err)
    41  		return
    42  	}
    43  	ctx.Data["Teams"] = teams
    44  	ctx.Data["Repo"] = ctx.Repo.Repository
    45  	ctx.Data["OrgID"] = ctx.Repo.Repository.OwnerID
    46  	ctx.Data["OrgName"] = ctx.Repo.Repository.OwnerName
    47  	ctx.Data["Org"] = ctx.Repo.Repository.Owner
    48  	ctx.Data["Units"] = unit_model.Units
    49  
    50  	ctx.HTML(http.StatusOK, tplCollaboration)
    51  }
    52  
    53  // CollaborationPost response for actions for a collaboration of a repository
    54  func CollaborationPost(ctx *context.Context) {
    55  	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("collaborator")))
    56  	if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
    57  		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
    58  		return
    59  	}
    60  
    61  	u, err := user_model.GetUserByName(ctx, name)
    62  	if err != nil {
    63  		if user_model.IsErrUserNotExist(err) {
    64  			ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
    65  			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
    66  		} else {
    67  			ctx.ServerError("GetUserByName", err)
    68  		}
    69  		return
    70  	}
    71  
    72  	if !u.IsActive {
    73  		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_inactive_user"))
    74  		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
    75  		return
    76  	}
    77  
    78  	// Organization is not allowed to be added as a collaborator.
    79  	if u.IsOrganization() {
    80  		ctx.Flash.Error(ctx.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
    81  		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
    82  		return
    83  	}
    84  
    85  	if got, err := repo_model.IsCollaborator(ctx, ctx.Repo.Repository.ID, u.ID); err == nil && got {
    86  		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_duplicate"))
    87  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
    88  		return
    89  	}
    90  
    91  	// find the owner team of the organization the repo belongs too and
    92  	// check if the user we're trying to add is an owner.
    93  	if ctx.Repo.Repository.Owner.IsOrganization() {
    94  		if isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Repo.Repository.Owner.ID, u.ID); err != nil {
    95  			ctx.ServerError("IsOrganizationOwner", err)
    96  			return
    97  		} else if isOwner {
    98  			ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_owner"))
    99  			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
   100  			return
   101  		}
   102  	}
   103  
   104  	if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
   105  		ctx.ServerError("AddCollaborator", err)
   106  		return
   107  	}
   108  
   109  	if setting.Service.EnableNotifyMail {
   110  		mailer.SendCollaboratorMail(u, ctx.Doer, ctx.Repo.Repository)
   111  	}
   112  
   113  	ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
   114  	ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
   115  }
   116  
   117  // ChangeCollaborationAccessMode response for changing access of a collaboration
   118  func ChangeCollaborationAccessMode(ctx *context.Context) {
   119  	if err := repo_model.ChangeCollaborationAccessMode(
   120  		ctx,
   121  		ctx.Repo.Repository,
   122  		ctx.FormInt64("uid"),
   123  		perm.AccessMode(ctx.FormInt("mode"))); err != nil {
   124  		log.Error("ChangeCollaborationAccessMode: %v", err)
   125  	}
   126  }
   127  
   128  // DeleteCollaboration delete a collaboration for a repository
   129  func DeleteCollaboration(ctx *context.Context) {
   130  	if err := repo_service.DeleteCollaboration(ctx, ctx.Repo.Repository, ctx.FormInt64("id")); err != nil {
   131  		ctx.Flash.Error("DeleteCollaboration: " + err.Error())
   132  	} else {
   133  		ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
   134  	}
   135  
   136  	ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/collaboration")
   137  }
   138  
   139  // AddTeamPost response for adding a team to a repository
   140  func AddTeamPost(ctx *context.Context) {
   141  	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
   142  		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
   143  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   144  		return
   145  	}
   146  
   147  	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("team")))
   148  	if len(name) == 0 {
   149  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   150  		return
   151  	}
   152  
   153  	team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(ctx, name)
   154  	if err != nil {
   155  		if organization.IsErrTeamNotExist(err) {
   156  			ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
   157  			ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   158  		} else {
   159  			ctx.ServerError("GetTeam", err)
   160  		}
   161  		return
   162  	}
   163  
   164  	if team.OrgID != ctx.Repo.Repository.OwnerID {
   165  		ctx.Flash.Error(ctx.Tr("repo.settings.team_not_in_organization"))
   166  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   167  		return
   168  	}
   169  
   170  	if organization.HasTeamRepo(ctx, ctx.Repo.Repository.OwnerID, team.ID, ctx.Repo.Repository.ID) {
   171  		ctx.Flash.Error(ctx.Tr("repo.settings.add_team_duplicate"))
   172  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   173  		return
   174  	}
   175  
   176  	if err = org_service.TeamAddRepository(ctx, team, ctx.Repo.Repository); err != nil {
   177  		ctx.ServerError("TeamAddRepository", err)
   178  		return
   179  	}
   180  
   181  	ctx.Flash.Success(ctx.Tr("repo.settings.add_team_success"))
   182  	ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   183  }
   184  
   185  // DeleteTeam response for deleting a team from a repository
   186  func DeleteTeam(ctx *context.Context) {
   187  	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
   188  		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
   189  		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
   190  		return
   191  	}
   192  
   193  	team, err := organization.GetTeamByID(ctx, ctx.FormInt64("id"))
   194  	if err != nil {
   195  		ctx.ServerError("GetTeamByID", err)
   196  		return
   197  	}
   198  
   199  	if err = repo_service.RemoveRepositoryFromTeam(ctx, team, ctx.Repo.Repository.ID); err != nil {
   200  		ctx.ServerError("team.RemoveRepositorys", err)
   201  		return
   202  	}
   203  
   204  	ctx.Flash.Success(ctx.Tr("repo.settings.remove_team_success"))
   205  	ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/collaboration")
   206  }