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

org.go 7.3KB

API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 years ago
8 years ago
8 years ago
8 years ago
Team permission allow different unit has different permission (#17811) * Team permission allow different unit has different permission * Finish the interface and the logic * Fix lint * Fix translation * align center for table cell content * Fix fixture * merge * Fix test * Add deprecated * Improve code * Add tooltip * Fix swagger * Fix newline * Fix tests * Fix tests * Fix test * Fix test * Max permission of external wiki and issues should be read * Move team units with limited max level below units table * Update label and column names * Some improvements * Fix lint * Some improvements * Fix template variables * Add permission docs * improve doc * Fix fixture * Fix bug * Fix some bug * fix * gofumpt * Integration test for migration (#18124) integrations: basic test for Gitea {dump,restore}-repo This is a first step for integration testing of DumpRepository and RestoreRepository. It: runs a Gitea server, dumps a repo via DumpRepository to the filesystem, restores the repo via RestoreRepository from the filesystem, dumps the restored repository to the filesystem, compares the first and second dump and expects them to be identical The verification is trivial and the goal is to add more tests for each topic of the dump. Signed-off-by: Loïc Dachary <loic@dachary.org> * Team permission allow different unit has different permission * Finish the interface and the logic * Fix lint * Fix translation * align center for table cell content * Fix fixture * merge * Fix test * Add deprecated * Improve code * Add tooltip * Fix swagger * Fix newline * Fix tests * Fix tests * Fix test * Fix test * Max permission of external wiki and issues should be read * Move team units with limited max level below units table * Update label and column names * Some improvements * Fix lint * Some improvements * Fix template variables * Add permission docs * improve doc * Fix fixture * Fix bug * Fix some bug * Fix bug Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Aravinth Manivannan <realaravinth@batsense.net>
2 years ago
Move macaron to chi (#14293) Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2020 The Gitea Authors.
  3. // SPDX-License-Identifier: MIT
  4. package context
  5. import (
  6. "strings"
  7. "code.gitea.io/gitea/models/organization"
  8. "code.gitea.io/gitea/models/perm"
  9. "code.gitea.io/gitea/models/unit"
  10. user_model "code.gitea.io/gitea/models/user"
  11. "code.gitea.io/gitea/modules/markup"
  12. "code.gitea.io/gitea/modules/markup/markdown"
  13. "code.gitea.io/gitea/modules/setting"
  14. "code.gitea.io/gitea/modules/structs"
  15. )
  16. // Organization contains organization context
  17. type Organization struct {
  18. IsOwner bool
  19. IsMember bool
  20. IsTeamMember bool // Is member of team.
  21. IsTeamAdmin bool // In owner team or team that has admin permission level.
  22. Organization *organization.Organization
  23. OrgLink string
  24. CanCreateOrgRepo bool
  25. PublicMemberOnly bool // Only display public members
  26. Team *organization.Team
  27. Teams []*organization.Team
  28. }
  29. func (org *Organization) CanWriteUnit(ctx *Context, unitType unit.Type) bool {
  30. return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeWrite
  31. }
  32. func (org *Organization) CanReadUnit(ctx *Context, unitType unit.Type) bool {
  33. return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeRead
  34. }
  35. func GetOrganizationByParams(ctx *Context) {
  36. orgName := ctx.Params(":org")
  37. var err error
  38. ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
  39. if err != nil {
  40. if organization.IsErrOrgNotExist(err) {
  41. redirectUserID, err := user_model.LookupUserRedirect(ctx, orgName)
  42. if err == nil {
  43. RedirectToUser(ctx.Base, orgName, redirectUserID)
  44. } else if user_model.IsErrUserRedirectNotExist(err) {
  45. ctx.NotFound("GetUserByName", err)
  46. } else {
  47. ctx.ServerError("LookupUserRedirect", err)
  48. }
  49. } else {
  50. ctx.ServerError("GetUserByName", err)
  51. }
  52. return
  53. }
  54. }
  55. // HandleOrgAssignment handles organization assignment
  56. func HandleOrgAssignment(ctx *Context, args ...bool) {
  57. var (
  58. requireMember bool
  59. requireOwner bool
  60. requireTeamMember bool
  61. requireTeamAdmin bool
  62. )
  63. if len(args) >= 1 {
  64. requireMember = args[0]
  65. }
  66. if len(args) >= 2 {
  67. requireOwner = args[1]
  68. }
  69. if len(args) >= 3 {
  70. requireTeamMember = args[2]
  71. }
  72. if len(args) >= 4 {
  73. requireTeamAdmin = args[3]
  74. }
  75. var err error
  76. if ctx.ContextUser == nil {
  77. // if Organization is not defined, get it from params
  78. if ctx.Org.Organization == nil {
  79. GetOrganizationByParams(ctx)
  80. if ctx.Written() {
  81. return
  82. }
  83. }
  84. } else if ctx.ContextUser.IsOrganization() {
  85. if ctx.Org == nil {
  86. ctx.Org = &Organization{}
  87. }
  88. ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser)
  89. } else {
  90. // ContextUser is an individual User
  91. return
  92. }
  93. org := ctx.Org.Organization
  94. // Handle Visibility
  95. if org.Visibility != structs.VisibleTypePublic && !ctx.IsSigned {
  96. // We must be signed in to see limited or private organizations
  97. ctx.NotFound("OrgAssignment", err)
  98. return
  99. }
  100. if org.Visibility == structs.VisibleTypePrivate {
  101. requireMember = true
  102. } else if ctx.IsSigned && ctx.Doer.IsRestricted {
  103. requireMember = true
  104. }
  105. ctx.ContextUser = org.AsUser()
  106. ctx.Data["Org"] = org
  107. // Admin has super access.
  108. if ctx.IsSigned && ctx.Doer.IsAdmin {
  109. ctx.Org.IsOwner = true
  110. ctx.Org.IsMember = true
  111. ctx.Org.IsTeamMember = true
  112. ctx.Org.IsTeamAdmin = true
  113. ctx.Org.CanCreateOrgRepo = true
  114. } else if ctx.IsSigned {
  115. ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID)
  116. if err != nil {
  117. ctx.ServerError("IsOwnedBy", err)
  118. return
  119. }
  120. if ctx.Org.IsOwner {
  121. ctx.Org.IsMember = true
  122. ctx.Org.IsTeamMember = true
  123. ctx.Org.IsTeamAdmin = true
  124. ctx.Org.CanCreateOrgRepo = true
  125. } else {
  126. ctx.Org.IsMember, err = org.IsOrgMember(ctx, ctx.Doer.ID)
  127. if err != nil {
  128. ctx.ServerError("IsOrgMember", err)
  129. return
  130. }
  131. ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx, ctx.Doer.ID)
  132. if err != nil {
  133. ctx.ServerError("CanCreateOrgRepo", err)
  134. return
  135. }
  136. }
  137. } else {
  138. // Fake data.
  139. ctx.Data["SignedUser"] = &user_model.User{}
  140. }
  141. if (requireMember && !ctx.Org.IsMember) ||
  142. (requireOwner && !ctx.Org.IsOwner) {
  143. ctx.NotFound("OrgAssignment", err)
  144. return
  145. }
  146. ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
  147. ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
  148. ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
  149. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  150. ctx.Data["IsPublicMember"] = func(uid int64) bool {
  151. is, _ := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, uid)
  152. return is
  153. }
  154. ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo
  155. ctx.Org.OrgLink = org.AsUser().OrganisationLink()
  156. ctx.Data["OrgLink"] = ctx.Org.OrgLink
  157. // Member
  158. ctx.Org.PublicMemberOnly = ctx.Doer == nil || !ctx.Org.IsMember && !ctx.Doer.IsAdmin
  159. opts := &organization.FindOrgMembersOpts{
  160. OrgID: org.ID,
  161. PublicOnly: ctx.Org.PublicMemberOnly,
  162. }
  163. ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts)
  164. if err != nil {
  165. ctx.ServerError("CountOrgMembers", err)
  166. return
  167. }
  168. // Team.
  169. if ctx.Org.IsMember {
  170. shouldSeeAllTeams := false
  171. if ctx.Org.IsOwner {
  172. shouldSeeAllTeams = true
  173. } else {
  174. teams, err := org.GetUserTeams(ctx, ctx.Doer.ID)
  175. if err != nil {
  176. ctx.ServerError("GetUserTeams", err)
  177. return
  178. }
  179. for _, team := range teams {
  180. if team.IncludesAllRepositories && team.AccessMode >= perm.AccessModeAdmin {
  181. shouldSeeAllTeams = true
  182. break
  183. }
  184. }
  185. }
  186. if shouldSeeAllTeams {
  187. ctx.Org.Teams, err = org.LoadTeams(ctx)
  188. if err != nil {
  189. ctx.ServerError("LoadTeams", err)
  190. return
  191. }
  192. } else {
  193. ctx.Org.Teams, err = org.GetUserTeams(ctx, ctx.Doer.ID)
  194. if err != nil {
  195. ctx.ServerError("GetUserTeams", err)
  196. return
  197. }
  198. }
  199. ctx.Data["NumTeams"] = len(ctx.Org.Teams)
  200. }
  201. teamName := ctx.Params(":team")
  202. if len(teamName) > 0 {
  203. teamExists := false
  204. for _, team := range ctx.Org.Teams {
  205. if team.LowerName == strings.ToLower(teamName) {
  206. teamExists = true
  207. ctx.Org.Team = team
  208. ctx.Org.IsTeamMember = true
  209. ctx.Data["Team"] = ctx.Org.Team
  210. break
  211. }
  212. }
  213. if !teamExists {
  214. ctx.NotFound("OrgAssignment", err)
  215. return
  216. }
  217. ctx.Data["IsTeamMember"] = ctx.Org.IsTeamMember
  218. if requireTeamMember && !ctx.Org.IsTeamMember {
  219. ctx.NotFound("OrgAssignment", err)
  220. return
  221. }
  222. ctx.Org.IsTeamAdmin = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.AccessMode >= perm.AccessModeAdmin
  223. ctx.Data["IsTeamAdmin"] = ctx.Org.IsTeamAdmin
  224. if requireTeamAdmin && !ctx.Org.IsTeamAdmin {
  225. ctx.NotFound("OrgAssignment", err)
  226. return
  227. }
  228. }
  229. ctx.Data["ContextUser"] = ctx.ContextUser
  230. ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects)
  231. ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages)
  232. ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode)
  233. ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
  234. if len(ctx.ContextUser.Description) != 0 {
  235. content, err := markdown.RenderString(&markup.RenderContext{
  236. Metas: map[string]string{"mode": "document"},
  237. Ctx: ctx,
  238. }, ctx.ContextUser.Description)
  239. if err != nil {
  240. ctx.ServerError("RenderString", err)
  241. return
  242. }
  243. ctx.Data["RenderedDescription"] = content
  244. }
  245. }
  246. // OrgAssignment returns a middleware to handle organization assignment
  247. func OrgAssignment(args ...bool) func(ctx *Context) {
  248. return func(ctx *Context) {
  249. HandleOrgAssignment(ctx, args...)
  250. }
  251. }