Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19a8a72674 | |||
| 5f548e134d | |||
| 61c8867742 |
@@ -185,16 +185,15 @@ func (s *nodeServiceImpl) getPermContext() (*permContext, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User and namespace nodes are globally readable (they represent identities,
|
// User nodes are globally readable (they represent identities,
|
||||||
// and anyone can reference or assign to them).
|
// and anyone can reference or assign to them).
|
||||||
for _, nodeType := range []string{"user", "namespace"} {
|
// Namespace nodes are NOT globally readable; access must be explicitly granted.
|
||||||
nodes, _ := s.store.FindNodes([]*models.Rel{{Type: models.RelType("_type::" + nodeType), Target: ""}})
|
nodes, _ := s.store.FindNodes([]*models.Rel{{Type: "_type::user", Target: ""}})
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if pc.levels[n.ID] < permRead {
|
if pc.levels[n.ID] < permRead {
|
||||||
pc.levels[n.ID] = permRead
|
pc.levels[n.ID] = permRead
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return pc, nil
|
return pc, nil
|
||||||
}
|
}
|
||||||
@@ -496,10 +495,16 @@ func (s *nodeServiceImpl) Add(input AddInput) (*models.Node, error) {
|
|||||||
if nsRef == "" {
|
if nsRef == "" {
|
||||||
nsRef = s.userID
|
nsRef = s.userID
|
||||||
}
|
}
|
||||||
nsID, err := s.resolveNamespaceRef(st, nsRef)
|
nsID, nsCreated, err := s.resolveNamespaceRef(st, nsRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Skip the write check when the namespace was just created — the
|
||||||
|
// current user is the creator/owner, but the permContext was built
|
||||||
|
// before the namespace existed and therefore doesn't reflect it.
|
||||||
|
if input.Namespace != "" && !nsCreated && !pc.canWrite(nsID) {
|
||||||
|
return fmt.Errorf("permission denied: no write access to namespace %q", input.Namespace)
|
||||||
|
}
|
||||||
ownerID = nsID
|
ownerID = nsID
|
||||||
}
|
}
|
||||||
if err := st.AddRel(ownerID, string(models.RelHasOwnership), id); err != nil {
|
if err := st.AddRel(ownerID, string(models.RelHasOwnership), id); err != nil {
|
||||||
@@ -723,7 +728,7 @@ func (s *nodeServiceImpl) Update(id string, input UpdateInput) (*models.Node, er
|
|||||||
|
|
||||||
// Namespace change: transfer ownership from the current namespace to the new one.
|
// Namespace change: transfer ownership from the current namespace to the new one.
|
||||||
if input.Namespace != nil {
|
if input.Namespace != nil {
|
||||||
newNsID, err := s.resolveNamespaceRef(st, *input.Namespace)
|
newNsID, _, err := s.resolveNamespaceRef(st, *input.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -971,11 +976,16 @@ func (s *nodeServiceImpl) ensureUser(st store.GraphStore, username string) (stri
|
|||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *nodeServiceImpl) resolveNamespaceRef(st store.GraphStore, ref string) (string, error) {
|
// resolveNamespaceRef returns the namespace ID and whether it was newly created.
|
||||||
|
func (s *nodeServiceImpl) resolveNamespaceRef(st store.GraphStore, ref string) (string, bool, error) {
|
||||||
if exists, _ := st.NodeExists(ref); exists {
|
if exists, _ := st.NodeExists(ref); exists {
|
||||||
return ref, nil
|
return ref, false, nil
|
||||||
}
|
}
|
||||||
return s.ensureNamespace(st, ref)
|
id, err := s.ensureNamespace(st, ref)
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
return id, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *nodeServiceImpl) ensureNamespace(st store.GraphStore, name string) (string, error) {
|
func (s *nodeServiceImpl) ensureNamespace(st store.GraphStore, name string) (string, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user