package client import ( "encoding/json" "fmt" "io/ioutil" "net/http" "reflect" ) // CompanyPrivileges contains the privileges for a combination of email address and company id type CompanyPrivileges struct { Admin bool `json:"admin"` Company bool `json:"company"` Consumer bool `json:"consumer"` Time bool `json:"time"` Invoicing bool `json:"invoicing"` Accounting bool `json:"accounting"` Supplier bool `json:"supplier"` } // PrivilegeAdded is the event sent when a new privilege is added type PrivilegeAdded struct { Email string `json:"email"` CompanyID string `json:"companyId"` Admin bool `json:"admin"` Company bool `json:"company"` Consumer bool `json:"consumer"` Time bool `json:"time"` Invoicing bool `json:"invoicing"` Accounting bool `json:"accounting"` Supplier bool `json:"supplier"` } // PrivilegeHandler processes PrivilegeAdded-events and fetches the initial set of privileges from an authz-service type PrivilegeHandler struct { client *http.Client baseURL string privileges map[string]map[string]CompanyPrivileges } // OptsFunc is used to configure the PrivilegeHandler type OptsFunc func(handler *PrivilegeHandler) // WithBaseURL sets the base URL to the authz-service func WithBaseURL(url string) OptsFunc { return func(handler *PrivilegeHandler) { handler.baseURL = url } } // New creates a new PrivilegeHandler. Pass OptsFuncs to configure. func New(opts ...OptsFunc) *PrivilegeHandler { handler := &PrivilegeHandler{ client: &http.Client{}, baseURL: "http://authz-service", privileges: map[string]map[string]CompanyPrivileges{}, } for _, opt := range opts { opt(handler) } return handler } // Fetch the initial set of privileges from an authz-service func (h *PrivilegeHandler) Fetch() error { resp, err := h.client.Get(fmt.Sprintf("%s/authz", h.baseURL)) if err != nil { return err } buff, err := ioutil.ReadAll(resp.Body) if err != nil { return err } err = json.Unmarshal(buff, &h.privileges) if err != nil { return err } return nil } // Process privilege-related events and update the internal state func (h *PrivilegeHandler) Process(msg interface{}) bool { if ev, ok := msg.(*PrivilegeAdded); ok { h.setPrivileges(ev) return true } else { fmt.Printf("Got unexpected message type (%s): '%+v'\n", reflect.TypeOf(msg).String(), msg) } return false } func (h *PrivilegeHandler) setPrivileges(ev *PrivilegeAdded) { if priv, exists := h.privileges[ev.Email]; exists { priv[ev.CompanyID] = CompanyPrivileges{ Admin: ev.Admin, Company: ev.Company, Consumer: ev.Consumer, Time: ev.Time, Invoicing: ev.Invoicing, Accounting: ev.Accounting, Supplier: ev.Supplier, } } else { h.privileges[ev.Email] = map[string]CompanyPrivileges{ ev.CompanyID: {}, } h.setPrivileges(ev) } } // CompaniesByUser return a slice of company ids matching the provided email and predicate func func (h *PrivilegeHandler) CompaniesByUser(email string, predicate func(privileges CompanyPrivileges) bool) []string { var result []string if p, exists := h.privileges[email]; exists { for k, v := range p { if predicate(v) { result = append(result, k) } } } return result }