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