You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

teams.go 8.1 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package org
  5. import (
  6. "path"
  7. "strings"
  8. "github.com/Unknwon/com"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/auth"
  11. "code.gitea.io/gitea/modules/base"
  12. "code.gitea.io/gitea/modules/context"
  13. "code.gitea.io/gitea/modules/log"
  14. )
  15. const (
  16. // tplTeams template path for teams list page
  17. tplTeams base.TplName = "org/team/teams"
  18. // tplTeamNew template path for create new team page
  19. tplTeamNew base.TplName = "org/team/new"
  20. // tplTeamMembers template path for showing team members page
  21. tplTeamMembers base.TplName = "org/team/members"
  22. // tplTeamRepositories template path for showing team repositories page
  23. tplTeamRepositories base.TplName = "org/team/repositories"
  24. )
  25. // Teams render teams list page
  26. func Teams(ctx *context.Context) {
  27. org := ctx.Org.Organization
  28. ctx.Data["Title"] = org.FullName
  29. ctx.Data["PageIsOrgTeams"] = true
  30. for _, t := range org.Teams {
  31. if err := t.GetMembers(); err != nil {
  32. ctx.Handle(500, "GetMembers", err)
  33. return
  34. }
  35. }
  36. ctx.Data["Teams"] = org.Teams
  37. ctx.HTML(200, tplTeams)
  38. }
  39. // TeamsAction response for join, leave, remove, add operations to team
  40. func TeamsAction(ctx *context.Context) {
  41. uid := com.StrTo(ctx.Query("uid")).MustInt64()
  42. if uid == 0 {
  43. ctx.Redirect(ctx.Org.OrgLink + "/teams")
  44. return
  45. }
  46. page := ctx.Query("page")
  47. var err error
  48. switch ctx.Params(":action") {
  49. case "join":
  50. if !ctx.Org.IsOwner {
  51. ctx.Error(404)
  52. return
  53. }
  54. err = ctx.Org.Team.AddMember(ctx.User.ID)
  55. case "leave":
  56. err = ctx.Org.Team.RemoveMember(ctx.User.ID)
  57. case "remove":
  58. if !ctx.Org.IsOwner {
  59. ctx.Error(404)
  60. return
  61. }
  62. err = ctx.Org.Team.RemoveMember(uid)
  63. page = "team"
  64. case "add":
  65. if !ctx.Org.IsOwner {
  66. ctx.Error(404)
  67. return
  68. }
  69. uname := ctx.Query("uname")
  70. // uname may be formatted as "username (fullname)"
  71. if strings.Contains(uname, "(") && strings.HasSuffix(uname, ")") {
  72. uname = strings.TrimSpace(strings.Split(uname, "(")[0])
  73. }
  74. var u *models.User
  75. u, err = models.GetUserByName(uname)
  76. if err != nil {
  77. if models.IsErrUserNotExist(err) {
  78. ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
  79. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
  80. } else {
  81. ctx.Handle(500, " GetUserByName", err)
  82. }
  83. return
  84. }
  85. if u.IsOrganization() {
  86. ctx.Flash.Error(ctx.Tr("form.cannot_add_org_to_team"))
  87. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
  88. return
  89. }
  90. err = ctx.Org.Team.AddMember(u.ID)
  91. page = "team"
  92. }
  93. if err != nil {
  94. if models.IsErrLastOrgOwner(err) {
  95. ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
  96. } else {
  97. log.Error(3, "Action(%s): %v", ctx.Params(":action"), err)
  98. ctx.JSON(200, map[string]interface{}{
  99. "ok": false,
  100. "err": err.Error(),
  101. })
  102. return
  103. }
  104. }
  105. switch page {
  106. case "team":
  107. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
  108. case "home":
  109. ctx.Redirect(ctx.Org.Organization.HomeLink())
  110. default:
  111. ctx.Redirect(ctx.Org.OrgLink + "/teams")
  112. }
  113. }
  114. // TeamsRepoAction operate team's repository
  115. func TeamsRepoAction(ctx *context.Context) {
  116. if !ctx.Org.IsOwner {
  117. ctx.Error(404)
  118. return
  119. }
  120. var err error
  121. switch ctx.Params(":action") {
  122. case "add":
  123. repoName := path.Base(ctx.Query("repo_name"))
  124. var repo *models.Repository
  125. repo, err = models.GetRepositoryByName(ctx.Org.Organization.ID, repoName)
  126. if err != nil {
  127. if models.IsErrRepoNotExist(err) {
  128. ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo"))
  129. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
  130. return
  131. }
  132. ctx.Handle(500, "GetRepositoryByName", err)
  133. return
  134. }
  135. err = ctx.Org.Team.AddRepository(repo)
  136. case "remove":
  137. err = ctx.Org.Team.RemoveRepository(com.StrTo(ctx.Query("repoid")).MustInt64())
  138. }
  139. if err != nil {
  140. log.Error(3, "Action(%s): '%s' %v", ctx.Params(":action"), ctx.Org.Team.Name, err)
  141. ctx.Handle(500, "TeamsRepoAction", err)
  142. return
  143. }
  144. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
  145. }
  146. // NewTeam render create new team page
  147. func NewTeam(ctx *context.Context) {
  148. ctx.Data["Title"] = ctx.Org.Organization.FullName
  149. ctx.Data["PageIsOrgTeams"] = true
  150. ctx.Data["PageIsOrgTeamsNew"] = true
  151. ctx.Data["Team"] = &models.Team{}
  152. ctx.Data["Units"] = models.Units
  153. ctx.HTML(200, tplTeamNew)
  154. }
  155. // NewTeamPost response for create new team
  156. func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
  157. ctx.Data["Title"] = ctx.Org.Organization.FullName
  158. ctx.Data["PageIsOrgTeams"] = true
  159. ctx.Data["PageIsOrgTeamsNew"] = true
  160. ctx.Data["Units"] = models.Units
  161. t := &models.Team{
  162. OrgID: ctx.Org.Organization.ID,
  163. Name: form.TeamName,
  164. Description: form.Description,
  165. Authorize: models.ParseAccessMode(form.Permission),
  166. }
  167. if t.Authorize < models.AccessModeAdmin {
  168. t.UnitTypes = form.Units
  169. }
  170. ctx.Data["Team"] = t
  171. if ctx.HasError() {
  172. ctx.HTML(200, tplTeamNew)
  173. return
  174. }
  175. if t.Authorize < models.AccessModeAdmin && len(form.Units) == 0 {
  176. ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
  177. return
  178. }
  179. if err := models.NewTeam(t); err != nil {
  180. ctx.Data["Err_TeamName"] = true
  181. switch {
  182. case models.IsErrTeamAlreadyExist(err):
  183. ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
  184. default:
  185. ctx.Handle(500, "NewTeam", err)
  186. }
  187. return
  188. }
  189. log.Trace("Team created: %s/%s", ctx.Org.Organization.Name, t.Name)
  190. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + t.LowerName)
  191. }
  192. // TeamMembers render team members page
  193. func TeamMembers(ctx *context.Context) {
  194. ctx.Data["Title"] = ctx.Org.Team.Name
  195. ctx.Data["PageIsOrgTeams"] = true
  196. if err := ctx.Org.Team.GetMembers(); err != nil {
  197. ctx.Handle(500, "GetMembers", err)
  198. return
  199. }
  200. ctx.HTML(200, tplTeamMembers)
  201. }
  202. // TeamRepositories show the repositories of team
  203. func TeamRepositories(ctx *context.Context) {
  204. ctx.Data["Title"] = ctx.Org.Team.Name
  205. ctx.Data["PageIsOrgTeams"] = true
  206. if err := ctx.Org.Team.GetRepositories(); err != nil {
  207. ctx.Handle(500, "GetRepositories", err)
  208. return
  209. }
  210. ctx.HTML(200, tplTeamRepositories)
  211. }
  212. // EditTeam render team edit page
  213. func EditTeam(ctx *context.Context) {
  214. ctx.Data["Title"] = ctx.Org.Organization.FullName
  215. ctx.Data["PageIsOrgTeams"] = true
  216. ctx.Data["team_name"] = ctx.Org.Team.Name
  217. ctx.Data["desc"] = ctx.Org.Team.Description
  218. ctx.Data["Units"] = models.Units
  219. ctx.HTML(200, tplTeamNew)
  220. }
  221. // EditTeamPost response for modify team information
  222. func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
  223. t := ctx.Org.Team
  224. ctx.Data["Title"] = ctx.Org.Organization.FullName
  225. ctx.Data["PageIsOrgTeams"] = true
  226. ctx.Data["Team"] = t
  227. ctx.Data["Units"] = models.Units
  228. isAuthChanged := false
  229. if !t.IsOwnerTeam() {
  230. // Validate permission level.
  231. auth := models.ParseAccessMode(form.Permission)
  232. t.Name = form.TeamName
  233. if t.Authorize != auth {
  234. isAuthChanged = true
  235. t.Authorize = auth
  236. }
  237. }
  238. t.Description = form.Description
  239. if t.Authorize < models.AccessModeAdmin {
  240. t.UnitTypes = form.Units
  241. } else {
  242. t.UnitTypes = nil
  243. }
  244. if ctx.HasError() {
  245. ctx.HTML(200, tplTeamNew)
  246. return
  247. }
  248. if t.Authorize < models.AccessModeAdmin && len(form.Units) == 0 {
  249. ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
  250. return
  251. }
  252. if err := models.UpdateTeam(t, isAuthChanged); err != nil {
  253. ctx.Data["Err_TeamName"] = true
  254. switch {
  255. case models.IsErrTeamAlreadyExist(err):
  256. ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
  257. default:
  258. ctx.Handle(500, "UpdateTeam", err)
  259. }
  260. return
  261. }
  262. ctx.Redirect(ctx.Org.OrgLink + "/teams/" + t.LowerName)
  263. }
  264. // DeleteTeam response for the delete team request
  265. func DeleteTeam(ctx *context.Context) {
  266. if err := models.DeleteTeam(ctx.Org.Team); err != nil {
  267. ctx.Flash.Error("DeleteTeam: " + err.Error())
  268. } else {
  269. ctx.Flash.Success(ctx.Tr("org.teams.delete_team_success"))
  270. }
  271. ctx.JSON(200, map[string]interface{}{
  272. "redirect": ctx.Org.OrgLink + "/teams",
  273. })
  274. }