Provide direct access to nested resources in WEB API request without specifying parents? - rest

I'm developing a web-api that manages a two level hierarchy objects:
Group -> SubGroup.
The group are added only by their names and it is a unique identifier for the group
The sub groups are added only by their names and the group name + sub group name is a unique identifier for the sub group.
The subgroup can "live" only in the context of its parent (the group).
Both the group and subgroup have unique ids in the system (besides the names).
The user should have an option to get a certain subgroup details and i'm uncertain if i should give him an endpoint that lets him access it directly.
I researched some threads by didn't get a good answer (1,2,3)
I have two options:
Option 1:
create an endpoint that lets the user to access subgroup only by specifying its name and its parent group name:
/groups/subgroups?groupName="x"&subGroupName="y"
Option 2:
create a "direct" access endpoint that lets the user access the subgroup directly without specifying the parent group name by using its internal id (In the subgroup creation return this id)
for example:
/subgroups?id="52regfd235fdsf325f" (the id of subgroup "y")
What is the best practice for this situation? is adding a "direct" access endpoint to a nested resource is fine or it should be avoided? what will be the case for a subgroup removal endpoint for example? should it be identified by the subgroup id or by its name?
In the general case, when we have H1->H2->H3->...Hn hierarchies. For trying to access the last resource in the chain, what will be a good rule of thumb here?

Related

Use ldap attribute for role-ldap-mapper role name

I'm trying to sync my roles from my LDAP to keycloak. As i have objects in my Domain that share the name of my needed roles i can't use the cn as "Role Name LDAP Attribute". Instead i want to create groups with a prefix like keycloak-mygroup and omit said prefix in the keycloak roles.
If that isn't possible, i'd like to create these groups with a prefix and use another attribute of the group as a role name. The roles i want to sync, already exist in my keycloak instance.
If i try to use an attribute like description i get an error ("Violation of UNIQUE KEY constraint "UK_J3RWUVD56ONTGSUHOGM184WW2-2". A duplicate key cannot be inserted into the dbo.KEYCLOAK_ROLE object. The duplicate key value is (, default).") and if i use an attribute like distinguishedName (those roles don't exist) everything is created.
How can i use a different attribute than cn for my role names and have it sync?
I was able to solve this problem. The error happens if a group is missing the attribute used for the group name. Every group has to have the used attribute, otherwise the sync will fail for all groups.

orientdb matching multiple possible edges

I am currently investigating using OrientDB to implement an authorisation system and I'm having some trouble with the edge arrow notation.
The graph has four different vertex types:
User
Group
Role
Resource
And four different edge types:
IN_GROUP
HAS_ROLE
CAN_ACCESS
INHERITS
And the structure is:
User -IN_GROUP-> Group
Group -HAS_ROLE-> Role
Role -CAN_ACCESS-> Resource
Role -INHERITS-> Role
A role may inherit other roles. This means that Role A may inherit Role B which may inherit Role C. I want to produce an Orient query that can say 'For a specific user, give me all of their roles, including any that they inherit'
Currently to get a roles inherited roles I'm doing this but it only retrieves the first level of inherited nodes:
match {class:User, where:(name='Sean')} -IN_GROUP-> {class:Group} -HAS_ROLE-> {} -INHERITS-> {class:Role, as:role} return role.name
What I'm trying to retrieve is the entire chain of nodes that this initial role inherits, can anyone help me with this please?
what you need here is a WHILE condition on the INHERITS relationship:
match
{class:User, where:(name='Sean')} -IN_GROUP->
{class:Group} -HAS_ROLE-> {} -INHERITS-> {class:Role, as:role, while:(true)}
return role.name

How to get the product catalog associated to a product set

Creating a product set requires associating a product_catalog_id:
POST https://graph.facebook.com/<API_VERSION>/<PRODUCT_CATALOG_ID>/product_sets
Reading an product set having the Facebook id is easy:
GET https://graph.facebook.com/<API_VERSION>/<PRODUCT_SET_ID>
Unfortunately, the response for that request contains 3 fields (id, name and filter).
How can I get the product_catalog_id associated to a product set (if I know the product_set_id)?
PS: The documentation does not help with that: https://developers.facebook.com/docs/marketing-api/dynamic-product-ads/product-catalog#productset
The catalog ID is not a field of the product set, so you therefore cannot traverse the graph in this way.
The only way to gather this associated is to read read the catalogues in a business, and their product sets to find the correct association unfortunately.

how to get the repository item for the particuler order Id in atg?

I have task to get the repository item("its like shipping group and payment group details") for the particular order id you now i got all the repository item in one object..
But the thing is i don't know how to fetch the these repository item (shipping group and payment group ) from this object
This my code I have tried..
Repository connection;
connection=/atg/commerce/order/OrderRepository-->this i putted in my property file
Repository repository = (Repository)getConnection();
RepositoryItem Item = (RepositoryItem)
Repository.getItem(getOrderId());
In this "repositoryItem" object I have all the repository item so I have to fetch all the shipping group and payment group from this object..
Pls hep me out..
Thanks in Advance..
For Orders there are two ways to get to the ShippingGroup and PaymentGroup when your starting point is an orderId
Let's start with the Repository way:
RepositoryItem order = getConnection().getItem(getOrderId(), "order"); //The getConnection().getItem(getOrderId()) method is deprecated. Make sure you pass the itemDescriptor in with your query
List<RepositoryItem> shippingGroups = (List<RepositoryItem>) order.getPropertyValue("shippingGroups");
List<RepositoryItem> paymentGroups = (List<RepositoryItem>) order.getPropertyValue("paymentGroups");
However, for certain objects, ATG provide some helper methods to make things easier. So using the out-of-the-box OrderManager, code is likely to make things easier for you:
Order order = getOrderManager().loadOrder(getOrderId());
List<ShippingGroup> shippingGroups = order.getShippingGroups();
List<PaymentGroup> paymentGroups = order.getPaymentGroups();
You will now have easier access to most things in the shipping groups and payment groups. Keep in mind though that your repository customisations will not automatically be exposed in these and you'll have to extend the Order and OrderImpl classes to do so (and similarly for the ShippingGroup and PaymentGroup.
ATG represents orders at two different levels - as repository items (and hence in the database) and as order objects.
It is strongly recommended that you interact with an order at object level, not repository level.
The OrderManager component provides the API you need to load an order by id.
Order order = orderManager.loadOrder(orderId);
where orderManager is the variable that holds a reference to the /atg/commerce/order/OrderManager Nucleus component.
This API hides behind it all the code needed to load the order and its related data entities from the repository.

In Tastypie is there a way to change a resources excludes based on the authentication?

Consider the example of a user resource that has profile pic and email fields. Where any user may see any other users profile pic but a user may only see their own email address.
Is it possible to setup tastypie so that the set of excluded fields can be varied based on the authenticated user?
I realize that an alternative approach is to create separate full and restricted user resources. But for the moment I just want to know whether the approach of limiting the fields based on user authentication is even doable in tastypie.
Also it doesn't have to be the excludes, in the same vein is there a way instead to change the fields property based on the requesting user?
I dont think excluded fields can be brought back into the picture in an elegant fashion. You could probably manipulate the object list based on the request using some object manipulation by including the get_object_list in your resource
But it would be much better and more logical for you to use the apply_limits method in your custom authorization class.
Yes there is a way to do it.
If you define email to be a separate field, not the one of the User(might work and with that but never did it).
You can define dehydrate_email where the bundle.request contains the current request and you could get it. It won't be exactly excluded as a field but it will be None for others.
I created a ModelResource subclass that can be multiple inherited into the required ModelResource instances. Like:
class ResourceThatNeedsToExcludeSomeFields(ExcludeResource, ModelResource):
pass
It takes in the fields to be excluded via GET parameters (like "&exclude=username")
class ExcludeResource(ModelResource):
"""
Generic class to implement exclusion of fields in all the ModelResource classes
All ModelResource classes will be muliple inherited by this class, whose dehydrate method has been overriden
"""
# STACK: How to exclude some fields from a resource list created by tastypie?
def dehydrate(self, bundle):
# I was taking the exclude fields from get paramaters as a comma separated value
if bundle.request.GET.get('exclude'):
exclude_fields = bundle.request.GET.get('exclude').split(',')
for field in exclude_fields:
if str(field) in bundle.data.keys():
del bundle.data[str(field)]
return bundle
You can modify this to get the exclude fields based on user group (or whatever criteria you base the fields on) like this:
class ExcludeResource(ModelResource):
"""
Generic class to implement exclusion of fields in all the ModelResource classes
All ModelResource classes will be muliple inherited by this class, whose dehydrate method has been overriden
"""
# STACK: How to exclude some fields from a resource list created by tastypie?
def dehydrate(self, bundle):
exclude_fields = <get a comma separated list of fields to be excluded based in bundle.request.user>
for field in exclude_fields:
if str(field) in bundle.data.keys():
del bundle.data[str(field)]
return bundle
However, this snippet will not work for related resources specified with "full=True"