fix: prohibit concurrent read/write
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sparetimecoders/goamqp"
|
"github.com/sparetimecoders/goamqp"
|
||||||
)
|
)
|
||||||
@@ -23,6 +24,7 @@ type CompanyPrivileges struct {
|
|||||||
|
|
||||||
// PrivilegeHandler processes PrivilegeAdded-events and fetches the initial set of privileges from an authz-service
|
// PrivilegeHandler processes PrivilegeAdded-events and fetches the initial set of privileges from an authz-service
|
||||||
type PrivilegeHandler struct {
|
type PrivilegeHandler struct {
|
||||||
|
*sync.RWMutex
|
||||||
client *http.Client
|
client *http.Client
|
||||||
baseURL string
|
baseURL string
|
||||||
privileges map[string]map[string]*CompanyPrivileges
|
privileges map[string]map[string]*CompanyPrivileges
|
||||||
@@ -41,6 +43,7 @@ func WithBaseURL(url string) OptsFunc {
|
|||||||
// New creates a new PrivilegeHandler. Pass OptsFuncs to configure.
|
// New creates a new PrivilegeHandler. Pass OptsFuncs to configure.
|
||||||
func New(opts ...OptsFunc) *PrivilegeHandler {
|
func New(opts ...OptsFunc) *PrivilegeHandler {
|
||||||
handler := &PrivilegeHandler{
|
handler := &PrivilegeHandler{
|
||||||
|
RWMutex: &sync.RWMutex{},
|
||||||
client: &http.Client{},
|
client: &http.Client{},
|
||||||
baseURL: "http://authz-service",
|
baseURL: "http://authz-service",
|
||||||
privileges: map[string]map[string]*CompanyPrivileges{},
|
privileges: map[string]map[string]*CompanyPrivileges{},
|
||||||
@@ -63,6 +66,8 @@ func (h *PrivilegeHandler) Fetch() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.RLock()
|
||||||
|
defer h.RUnlock()
|
||||||
err = json.Unmarshal(buff, &h.privileges)
|
err = json.Unmarshal(buff, &h.privileges)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -77,6 +82,8 @@ func (h *PrivilegeHandler) Process(msg interface{}, _ goamqp.Headers) (interface
|
|||||||
if priv, exists := h.privileges[ev.Email]; exists {
|
if priv, exists := h.privileges[ev.Email]; exists {
|
||||||
priv[ev.CompanyID] = &CompanyPrivileges{}
|
priv[ev.CompanyID] = &CompanyPrivileges{}
|
||||||
} else {
|
} else {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
h.privileges[ev.Email] = map[string]*CompanyPrivileges{
|
h.privileges[ev.Email] = map[string]*CompanyPrivileges{
|
||||||
ev.CompanyID: {},
|
ev.CompanyID: {},
|
||||||
}
|
}
|
||||||
@@ -84,13 +91,19 @@ func (h *PrivilegeHandler) Process(msg interface{}, _ goamqp.Headers) (interface
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
case *UserRemoved:
|
case *UserRemoved:
|
||||||
if priv, exists := h.privileges[ev.Email]; exists {
|
if priv, exists := h.privileges[ev.Email]; exists {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
delete(priv, ev.CompanyID)
|
delete(priv, ev.CompanyID)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case *PrivilegeAdded:
|
case *PrivilegeAdded:
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
h.setPrivileges(ev.Email, ev.CompanyID, ev.Privilege, true)
|
h.setPrivileges(ev.Email, ev.CompanyID, ev.Privilege, true)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case *PrivilegeRemoved:
|
case *PrivilegeRemoved:
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
h.setPrivileges(ev.Email, ev.CompanyID, ev.Privilege, false)
|
h.setPrivileges(ev.Email, ev.CompanyID, ev.Privilege, false)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
@@ -130,6 +143,8 @@ func (h *PrivilegeHandler) setPrivileges(email, companyId string, privilege Priv
|
|||||||
|
|
||||||
// CompaniesByUser return a slice of company ids matching the provided email and predicate func
|
// 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 {
|
func (h *PrivilegeHandler) CompaniesByUser(email string, predicate func(privileges CompanyPrivileges) bool) []string {
|
||||||
|
h.RLock()
|
||||||
|
defer h.RUnlock()
|
||||||
var result []string
|
var result []string
|
||||||
if p, exists := h.privileges[email]; exists {
|
if p, exists := h.privileges[email]; exists {
|
||||||
for k, v := range p {
|
for k, v := range p {
|
||||||
@@ -143,6 +158,8 @@ func (h *PrivilegeHandler) CompaniesByUser(email string, predicate func(privileg
|
|||||||
|
|
||||||
// IsAllowed return true if the provided predicate return true for the privileges matching the provided email and companyID, return false otherwise
|
// IsAllowed return true if the provided predicate return true for the privileges matching the provided email and companyID, return false otherwise
|
||||||
func (h *PrivilegeHandler) IsAllowed(email, companyID string, predicate func(privileges CompanyPrivileges) bool) bool {
|
func (h *PrivilegeHandler) IsAllowed(email, companyID string, predicate func(privileges CompanyPrivileges) bool) bool {
|
||||||
|
h.RLock()
|
||||||
|
defer h.RUnlock()
|
||||||
if p, exists := h.privileges[email]; exists {
|
if p, exists := h.privileges[email]; exists {
|
||||||
if v, exists := p[companyID]; exists {
|
if v, exists := p[companyID]; exists {
|
||||||
return predicate(*v)
|
return predicate(*v)
|
||||||
|
|||||||
Reference in New Issue
Block a user