internal/httpd/orgweb.go
120 lines · 3586 bytes
3 symbols in this file
1package httpd
2
3import (
4 "net/http"
5 "strings"
6
7 "gitbay.org/gitbay/internal/store"
8)
9
10// teamView is a team with the two things an admin needs to see about it:
11// who is in it and what it reaches.
12type teamView struct {
13 Name string
14 Members []string
15 Grants []store.TeamGrant
16}
17
18// orgAdminView gathers the management state for an organization page. It
19// returns ok=false for user pages and for viewers who do not administer the
20// org, so the page renders read-only for everyone else.
21func (s *Server) orgAdminView(viewer store.User, kind, name string) (teams []teamView, ok bool) {
22 if kind != "org" || viewer.ID == 0 {
23 return nil, false
24 }
25 org, err := s.st.OrgByName(name)
26 if err != nil {
27 return nil, false
28 }
29 if role, _ := s.st.OrgRole(org.ID, viewer.ID); role != "admin" {
30 return nil, false
31 }
32 list, _ := s.st.ListTeams(org.ID)
33 for _, t := range list {
34 members, _ := s.st.TeamMembers(t.ID)
35 grants, _ := s.st.TeamGrants(t.ID)
36 teams = append(teams, teamView{Name: t.Name, Members: members, Grants: grants})
37 }
38 return teams, true
39}
40
41// orgSubmit routes the organization forms on an owner page. Every branch
42// dispatches the matching control command, so membership rules and audit
43// entries stay in one implementation.
44func (s *Server) orgSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
45 owner := r.PathValue("owner")
46 // The member and team forms live on the profile's people tab (#242),
47 // which is where a result has to land for its flash to render.
48 back := func(msg string) {
49 s.setFlash(w, msg)
50 http.Redirect(w, r, "/"+owner+"/-/people", http.StatusSeeOther)
51 }
52 field := r.FormValue("field")
53 team := strings.TrimSpace(r.FormValue("team"))
54 user := strings.TrimSpace(r.FormValue("user"))
55
56 // Create and rename land on a different page than the one they were
57 // posted from: a new org has no page yet, and a renamed one has moved.
58 switch field {
59 case "org-create", "org-rename":
60 name := strings.TrimSpace(r.FormValue("name"))
61 argv := []string{"org", "create", name}
62 if field == "org-rename" {
63 argv = []string{"org", "rename", owner, name}
64 }
65 if _, msg, ok := s.runControl(u, argv); !ok {
66 back(msg)
67 return
68 }
69 http.Redirect(w, r, "/"+name, http.StatusSeeOther)
70 return
71 }
72
73 var argv []string
74 switch field {
75 case "member-add":
76 argv = []string{"org", "members", "add", owner, user}
77 if role := r.FormValue("role"); role == "admin" || role == "member" {
78 argv = append(argv, "--role", role)
79 }
80 case "member-remove":
81 if ok, msg := confirmed(r, user); !ok {
82 back(msg)
83 return
84 }
85 argv = []string{"org", "members", "remove", owner, user}
86 case "team-create":
87 argv = []string{"org", "team", "create", owner, team}
88 case "team-delete":
89 if ok, msg := confirmed(r, team); !ok {
90 back(msg)
91 return
92 }
93 argv = []string{"org", "team", "delete", owner, team}
94 case "team-add":
95 argv = append([]string{"org", "team", "add", owner, team}, strings.Fields(user)...)
96 case "team-remove":
97 if ok, msg := confirmed(r, team); !ok {
98 back(msg)
99 return
100 }
101 argv = append([]string{"org", "team", "remove", owner, team}, strings.Fields(user)...)
102 case "team-grant":
103 argv = []string{"org", "team", "grant", owner, team,
104 strings.TrimSpace(r.FormValue("repo")), r.FormValue("role")}
105 case "team-revoke":
106 if ok, msg := confirmed(r, team); !ok {
107 back(msg)
108 return
109 }
110 argv = []string{"org", "team", "revoke", owner, team, strings.TrimSpace(r.FormValue("repo"))}
111 default:
112 back("unknown form")
113 return
114 }
115 if _, msg, ok := s.runControl(u, argv); !ok {
116 back(msg)
117 return
118 }
119 back("")
120}