// merge applies the properties of the passed-in User to the User on which it // is called and returns a new User with these modifications applied. Think of // all Users as immutable sets of data. Merge allows you to perform the set // operations (desired grants and revokes) atomically func (u User) merge(n User) (User, error) { var out User if u.User != n.User { return out, authErr(http.StatusConflict, "Merging user data with conflicting usernames: %s %s", u.User, n.User) } out.User = u.User if n.Password != "" { hash, err := bcrypt.GenerateFromPassword([]byte(n.Password), bcrypt.DefaultCost) if err != nil { return User{}, err } out.Password = string(hash) } else { out.Password = u.Password } currentRoles := types.NewUnsafeSet(u.Roles...) for _, g := range n.Grant { if currentRoles.Contains(g) { plog.Noticef("granting duplicate role %s for user %s", g, n.User) return User{}, authErr(http.StatusConflict, fmt.Sprintf("Granting duplicate role %s for user %s", g, n.User)) } currentRoles.Add(g) } for _, r := range n.Revoke { if !currentRoles.Contains(r) { plog.Noticef("revoking ungranted role %s for user %s", r, n.User) return User{}, authErr(http.StatusConflict, fmt.Sprintf("Revoking ungranted role %s for user %s", r, n.User)) } currentRoles.Remove(r) } out.Roles = currentRoles.Values() sort.Strings(out.Roles) return out, nil }
func DetectDataDir(dirpath string) (DataDirVersion, error) { names, err := fileutil.ReadDir(dirpath) if err != nil { if os.IsNotExist(err) { err = nil } // Error reading the directory return DataDirUnknown, err } nameSet := types.NewUnsafeSet(names...) if nameSet.Contains("member") { ver, err := DetectDataDir(path.Join(dirpath, "member")) if ver == DataDir2_0 { return DataDir2_0_1, nil } return ver, err } if nameSet.ContainsAll([]string{"snap", "wal"}) { // .../wal cannot be empty to exist. walnames, err := fileutil.ReadDir(path.Join(dirpath, "wal")) if err == nil && len(walnames) > 0 { return DataDir2_0, nil } } if nameSet.ContainsAll([]string{"proxy"}) { return DataDir2_0Proxy, nil } return DataDirUnknown, nil }
// Grant adds a set of permissions to the permission object on which it is called, // returning a new permission object. func (rw RWPermission) Grant(n RWPermission) (RWPermission, error) { var out RWPermission currentRead := types.NewUnsafeSet(rw.Read...) for _, r := range n.Read { if currentRead.Contains(r) { return out, authErr(http.StatusConflict, "Granting duplicate read permission %s", r) } currentRead.Add(r) } currentWrite := types.NewUnsafeSet(rw.Write...) for _, w := range n.Write { if currentWrite.Contains(w) { return out, authErr(http.StatusConflict, "Granting duplicate write permission %s", w) } currentWrite.Add(w) } out.Read = currentRead.Values() out.Write = currentWrite.Values() sort.Strings(out.Read) sort.Strings(out.Write) return out, nil }
func newStore(namespaces ...string) *store { s := new(store) s.CurrentVersion = defaultVersion s.Root = newDir(s, "/", s.CurrentIndex, nil, Permanent) for _, namespace := range namespaces { s.Root.Add(newDir(s, namespace, s.CurrentIndex, s.Root, Permanent)) } s.Stats = newStats() s.WatcherHub = newWatchHub(1000) s.ttlKeyHeap = newTtlKeyHeap() s.readonlySet = types.NewUnsafeSet(append(namespaces, "/")...) return s }
// Revoke removes a set of permissions to the permission object on which it is called, // returning a new permission object. func (rw RWPermission) Revoke(n RWPermission) (RWPermission, error) { var out RWPermission currentRead := types.NewUnsafeSet(rw.Read...) for _, r := range n.Read { if !currentRead.Contains(r) { plog.Noticef("revoking ungranted read permission %s", r) continue } currentRead.Remove(r) } currentWrite := types.NewUnsafeSet(rw.Write...) for _, w := range n.Write { if !currentWrite.Contains(w) { plog.Noticef("revoking ungranted write permission %s", w) continue } currentWrite.Remove(w) } out.Read = currentRead.Values() out.Write = currentWrite.Values() sort.Strings(out.Read) sort.Strings(out.Write) return out, nil }