/
role.go
148 lines (132 loc) · 3.65 KB
/
role.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package api
import (
"fmt"
"log"
"net/http"
"strconv"
"github.com/dmartzol/hmm/internal/hmm"
"github.com/gorilla/mux"
)
type AccountRole struct {
Account Account
Role Role
}
func AccountRoleView(ar *hmm.AccountRole, options map[string]bool) AccountRole {
view := AccountRole{}
return view
}
type Role struct {
Name string
Permissions []string
PermissionBit int
}
func RolesView(rs hmm.Roles, options map[string]bool) []Role {
var views []Role
for _, r := range rs {
views = append(views, RoleView(r, options))
}
return views
}
func RoleView(r *hmm.Role, options map[string]bool) Role {
roleView := Role{
Name: r.Name,
PermissionBit: r.PermissionsBit.Int(),
}
if len(r.Permissions) == 0 {
r.Populate()
}
roleView.Permissions = r.Permissions
return roleView
}
func (h API) CreateRole(w http.ResponseWriter, r *http.Request) {
var req hmm.CreateRoleReq
err := h.Unmarshal(r, &req)
if err != nil {
h.Logger.Errorf("unable to unmarshal: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
role, err := h.RoleService.Create(req.Name)
if err != nil {
h.Logger.Errorf("unable to create role: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
h.RespondJSON(w, RoleView(role, nil))
}
func (h API) GetRoles(w http.ResponseWriter, r *http.Request) {
roles, err := h.RoleService.Roles()
if err != nil {
log.Printf("GetRoles Roles ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
h.RespondJSON(w, RolesView(roles, nil))
}
func validateEditRole(req hmm.EditRoleReq, targetRole *hmm.Role) error {
if req.Name == nil && len(req.Permissions) == 0 {
return fmt.Errorf("no updates found")
}
return nil
}
func (h API) EditRole(w http.ResponseWriter, r *http.Request) {
// parsing parameters
params := mux.Vars(r)
idString, ok := params[idQueryParameter]
if !ok {
errMsg := fmt.Sprintf("parameter '%s' not found", idQueryParameter)
h.RespondJSONError(w, errMsg, http.StatusBadRequest)
return
}
roleID, err := strconv.ParseInt(idString, 10, 64)
if err != nil {
errMsg := fmt.Sprintf("wrong parameter '%s'", idString)
h.RespondJSONError(w, errMsg, http.StatusBadRequest)
return
}
// checking permissions
ctx := r.Context()
requesterID := ctx.Value(contextRequesterAccountIDKey).(int64)
err = h.AuthorizeAccount(requesterID, hmm.PermissionRolesEdit)
if err != nil {
log.Printf("WARNING: account %d requested to edit role %d", requesterID, roleID)
log.Printf("EditRole AuthorizeAccount ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusUnauthorized)
return
}
var req hmm.EditRoleReq
err = h.Unmarshal(r, &req)
if err != nil {
log.Printf("CreateRole Unmarshal ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
role, err := h.RoleService.Role(roleID)
if err != nil {
log.Printf("EditRole Role ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
err = validateEditRole(req, role)
if err != nil {
log.Printf("EditRole validateEditRole ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusBadRequest)
return
}
newBit := 0
for _, p := range req.Permissions {
newBit = newBit | hmm.StringToRolePermission(p).Int()
}
if role.PermissionsBit.Int() == newBit {
log.Printf("EditRole ERROR: role already has those permissions")
h.RespondJSONError(w, "", http.StatusBadRequest)
return
}
updatedRole, err := h.RoleService.Update(role.ID, newBit)
if err != nil {
log.Printf("EditRole UpdateRole ERROR: %+v", err)
h.RespondJSONError(w, "", http.StatusInternalServerError)
return
}
h.RespondJSON(w, RoleView(updatedRole, nil))
}