From 3fed1fdd4757c9ca2d65f38fda8502858cd77879 Mon Sep 17 00:00:00 2001 From: mattthew Date: Tue, 3 Jun 2025 20:53:44 -0400 Subject: [PATCH 1/4] Check context for string namespace metadata Attach that namespace if found -- will be overwritten if JWL-ACLs namespaces are found --- edgraph/server.go | 16 +++++++++++++++- x/x.go | 13 +++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/edgraph/server.go b/edgraph/server.go index 6bfedb0c4c8..08a8e45c44c 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -1194,7 +1194,21 @@ func (s *Server) Query(ctx context.Context, req *api.Request) (*api.Response, er // Query handles queries or mutations func (s *Server) QueryNoGrpc(ctx context.Context, req *api.Request) (*api.Response, error) { - ctx = x.AttachJWTNamespace(ctx) + // if the `namespace-str` is present in the metadata, use it to attach the namespace + // otherwise, use the namespace from the JWT. + nsStr, err := x.ExtractNamespaceStr(ctx) + if err == nil { + ns, err := getNamespaceIDFromName(x.AttachNamespace(ctx, x.RootNamespace), nsStr) + if err == nil { + ctx = x.AttachNamespace(ctx, ns) + } else { + ctx = x.AttachJWTNamespace(ctx) + } + } else { + ctx = x.AttachJWTNamespace(ctx) + } + // if acl is enabled, then the namespace from the JWT will be applied in the test below + // overriding any namespace from the metadata obtained from the `namespace-str` above. if x.WorkerConfig.AclEnabled && req.GetStartTs() != 0 { // A fresh StartTs is assigned if it is 0. ns, err := x.ExtractNamespace(ctx) diff --git a/x/x.go b/x/x.go index db2053f0706..bb1e5c59c77 100644 --- a/x/x.go +++ b/x/x.go @@ -268,6 +268,19 @@ func ExtractNamespace(ctx context.Context) (uint64, error) { return namespace, nil } +// ExtractNamespaceStr parses the namespace string value from the incoming gRPC context. +func ExtractNamespaceStr(ctx context.Context) (string, error) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return "", errors.New("No metadata in the context") + } + ns := md.Get("namespace-str") + if len(ns) == 0 { + return "", errors.New("No namespace-str in the metadata of context") + } + return ns[0], nil +} + func IsRootNsOperation(ctx context.Context) bool { md, ok := metadata.FromIncomingContext(ctx) if !ok { From 11c4d08ae98c42da0c0d0c4744cdad1adc08ae13 Mon Sep 17 00:00:00 2001 From: mattthew Date: Thu, 5 Jun 2025 13:15:09 -0400 Subject: [PATCH 2/4] Add a namespace not found Error type --- x/x.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/x.go b/x/x.go index bb1e5c59c77..2e5c2cc4bb5 100644 --- a/x/x.go +++ b/x/x.go @@ -65,6 +65,8 @@ var ( ErrConflict = errors.New("Transaction conflict") // ErrHashMismatch is returned when the hash does not matches the startTs ErrHashMismatch = errors.New("hash mismatch the claimed startTs|namespace") + // ErrNamespaceNotFound is returned when a namespace is not found. + ErrNamespaceNotFound = errors.New("namespace not found") ) const ( From 2b87a6242d35e414e8829376f825a30866837bae Mon Sep 17 00:00:00 2001 From: mattthew Date: Thu, 5 Jun 2025 13:16:23 -0400 Subject: [PATCH 3/4] Add log output if error from getting workspace by name is something other than "not found" --- edgraph/namespace.go | 2 +- edgraph/server.go | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/edgraph/namespace.go b/edgraph/namespace.go index 4531ea05469..e7373b109b7 100644 --- a/edgraph/namespace.go +++ b/edgraph/namespace.go @@ -310,7 +310,7 @@ func getNamespaceIDFromName(ctx context.Context, nsName string) (uint64, error) return 0, err } if len(data.Namespaces) == 0 { - return 0, errors.Errorf("namespace %q not found", nsName) + return 0, errors.Wrapf(x.ErrNamespaceNotFound, "namespace %q not found", nsName) } glog.Infof("Found namespace [%v] with id [%d]", nsName, data.Namespaces[0].ID) diff --git a/edgraph/server.go b/edgraph/server.go index 08a8e45c44c..43d9df0f2a2 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -1194,20 +1194,25 @@ func (s *Server) Query(ctx context.Context, req *api.Request) (*api.Response, er // Query handles queries or mutations func (s *Server) QueryNoGrpc(ctx context.Context, req *api.Request) (*api.Response, error) { - // if the `namespace-str` is present in the metadata, use it to attach the namespace + // If the `namespace-str` is present in the metadata, use it to attach the namespace // otherwise, use the namespace from the JWT. - nsStr, err := x.ExtractNamespaceStr(ctx) - if err == nil { + var attached bool + nsStr, _ := x.ExtractNamespaceStr(ctx) + if nsStr != "" { ns, err := getNamespaceIDFromName(x.AttachNamespace(ctx, x.RootNamespace), nsStr) if err == nil { ctx = x.AttachNamespace(ctx, ns) + attached = true } else { - ctx = x.AttachJWTNamespace(ctx) + if !errors.Is(err, x.ErrNamespaceNotFound) { + glog.Warningf("Error getting namespace ID from name: %v. Defaulting to default or JWT namespace", err) + } } - } else { + } + if !attached { ctx = x.AttachJWTNamespace(ctx) } - // if acl is enabled, then the namespace from the JWT will be applied in the test below + // If acl is enabled, then the namespace from the JWT will be applied in the test below // overriding any namespace from the metadata obtained from the `namespace-str` above. if x.WorkerConfig.AclEnabled && req.GetStartTs() != 0 { // A fresh StartTs is assigned if it is 0. From f0650ee528b63a96fae766bd097dd48a084b1f65 Mon Sep 17 00:00:00 2001 From: mattthew Date: Mon, 11 Aug 2025 21:00:24 -0400 Subject: [PATCH 4/4] Wrap errors --- edgraph/namespace.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edgraph/namespace.go b/edgraph/namespace.go index e7373b109b7..c4e9e16e7e6 100644 --- a/edgraph/namespace.go +++ b/edgraph/namespace.go @@ -302,18 +302,18 @@ func getNamespaceIDFromName(ctx context.Context, nsName string) (uint64, error) req := &api.Request{Query: fmt.Sprintf(queryNamespaceByName, nsName)} resp, err := (&Server{}).doQuery(ctx, &Request{req: req, doAuth: NoAuthorize}) if err != nil { - return 0, err + return 0, errors.Wrapf(err, "failed to get namespace ID from name %q", nsName) } var data resultNamespaces if err := json.Unmarshal(resp.GetJson(), &data); err != nil { - return 0, err + return 0, errors.Wrapf(err, "failed to unmarshal JSON results for namespace query %q", req.Query) } if len(data.Namespaces) == 0 { return 0, errors.Wrapf(x.ErrNamespaceNotFound, "namespace %q not found", nsName) } - glog.Infof("Found namespace [%v] with id [%d]", nsName, data.Namespaces[0].ID) + glog.V(2).Infof("Found namespace [%v] with id [%d]", nsName, data.Namespaces[0].ID) return data.Namespaces[0].ID, nil }