Mongo Aggregate Nested Array, Lookup - mongodb

I am creating a web application using MongoDB and Go, which includes role based access control. I am storing the information regarding this in 2 collections, permissions and roles.
This is how these two collections look like.
Permissions
{
"operation": "create",
"resource": "project"
}
{
"operation": "read",
"resource": "project"
}
{
"operation": "update",
"resource": "project"
}
{
"operation": "delete",
"resource": "project"
}
{
"operation": "create",
"resource": "user"
}
resource is something on which an operation is performed. So if there is some operation which cannot be performed on some resource, then, I needn't store it. For example user can only be created hence only create user need to be stored.
Currently there are only 4 operations(create, read, update, delete) in the scope of the application, but could increase, like upload could come into picture.
Roles
{
"role": "admin",
"display_name": "Administrator",
"permissions": [
{
"operation": "create",
"resource": "project"
},
{
"operation": "read",
"resource": "project"
},
{
"operation": "update",
"resource": "project"
},
{
"operation": "delete",
"resource": "project"
}
]
}
Roles contain role, the name of role to be displayed on UI and the set of permissions that role has.
I need to send this information to UI using a REST API in a specific format, which would describe whether a specific role can perform an operation on a resource or not using the checked flag and whether a specific operation on a resource is editable or not by using the flag isEditable.
For example the permissions collection doesn't contain an operation delete on resource user, so it should not be editable, hence flag is set to false. Similarly user can be created, hence it is set to true.
{
display_name: "System Administrator",
role: "admin",
permissions: [
{
resource: "user",
privilages: {
create: { checked: false, isEditable: true },
delete: { checked: false, isEditable: false },
update: { checked: false, isEditable: false },
read: { checked: false, isEditable: false }
}
},
{
resource: "project",
privilages: {
create: { checked: true, isEditable: true },
delete: { checked: true, isEditable: true },
update: { checked: true, isEditable: true },
read: { checked: true, isEditable: true }
}
}
]
}
Is it possible to perform this using mongo aggregations? Or do I need to make modifications in my schema, If yes, then what modifications should I make.

I was able to solve the problem in 3 steps:
Include all the permissions for every role and add a flag called checked. This increased data redundancy but that wasn't a big issue.
Do a group by on resource field in roles collection.
Populate the missing privileges for every resource with isEditable set to false on server side.
I had to traverse the data on server side, but this was the most efficient way I could think of.

Related

How to export/import a client "WITH ROLES" on Keycloak?

Is it possible to export the client role(s) with the client?
If not, is there a workaround (for example modify manually the JSON before reimporting it ?) or another process that can be automated ?
Yes, you can but it's a little tricky.
You have to export entire realm and clean it leaving only this two items:
{
"roles": {
"client": {
"<client-name>": [
{
"name": <role-name>,
"clientRole": true,
...
},
]
}
},
"clients": [
{
"clientId": "<client-name>",
...
}
]
}
The only thing you cannot do in the same step is importing permissions because import process cannot import permissions based on roles that not exists.

Acumatica Web Services - Adding Crossreference alternate ID to Stock Item

We are trying to add new Alternate Id to a current Stock Item, when pushing the service body we receive the point back without any error. However, it does not add the additional Cross Reference Item.
{
"InventoryID": {
"value": "APR000195XXX"
},
"CrossReferences": [
{
"AlternateID": {
"value": "19405"
},
"AlternateType": {
"value": "Global"
},
"Description": {
"value": "XXXPUL0001"
},
"Subitem": {
"value": "000000"
},
"VendorOrCustomer": {},
"custom": {},
"files": []
}
]
}
the issue came down to screen rights on roles that were not set
If you want add line Cross-Reference to existing stock Item your request should work.
Just check that you use correct type - "PUT" and correct endpoint:

Add new user with credentials Temporary property does not working

Keycloak REST API in UserRepresentation model there is a "credentials" property, which has ( type = "password", value="some", temporary=true/false }
On adding new user I wonna force the user to change his password on the first login. I know that it can be done globally in Required Actions in Realm/Authorization options, but if "force changing password" is not setted as default. I thought to control it by the setup that property in user.credentials model, but looks like it's totally dummy property and not makes any effect, always works as false. Am I right ?
P.S. I also take a look at the model in https://github.com/keycloak/keycloak/blob/b4b3527df7656bfaaee351ec414e56c683c134c2/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java I fond in resetPassword it's setted up, but not in updateUser ( which I assume is used for add user also ).
{
"username": "New_User_3",
"enabled": true,
"firstName": "NewUserDemoFirst",
"lastName": "NewUserDemoLast",
"email": "New_User_3#mail.test",
"attributes": {
},
"access": {
"manageGroupMembership": false,
"view": false,
"mapRoles": false,
"impersonate": false,
"manage": false
},
"credentials": [
{
"type": "password",
"temporary": true,
"value": "xM0K+G"
}
]
}
You could add required actions to the JSON object as shown. This would force the user to update the password upon login for the first time.
{
"username": "userxyz",
"credentials": [
{
"type": "password",
"value": "passwordabc",
"temporary": true
}
],
"requiredActions": [
"UPDATE_PASSWORD"
],
...
}
but looks like it's totally dummy property and not makes any effect, always works as false. Am I right ?
Yes.
This seem to be a bug of Keycloak. I can reproduce it too.
To fix the bug, I think the following lines should be added to org.keycloak.services.resources.admin.UserResource.updateUserFromRep():
List<CredentialRepresentation> credentials = rep.getCredentials();
if (credentials != null) {
for (CredentialRepresentation credential : credentials) {
if (CredentialRepresentation.PASSWORD.equals(credential.getType())
&& credential.isTemporary() != null && credential.isTemporary()) {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
}
}
A workaround is to call reset-password after creating a user.
PUT /{realm}/users/{id}/reset-password
See also:https://www.keycloak.org/docs-api/7.0/rest-api/index.html

Get all vertices having a labelname

I am using ibm graph in bluemix and new to this.
I created a graph named 'test' using the GUI provided by bluemix and uploaded the sample data 'Music Festival' provided by ibm in that graph.
Now I am trying to query all the vertices having label 'attendee' using below query.
def gt = graph.traversal();
gt.V().hasLabel("attendee");
But I am getting error as
Error: Error encountered evaluating script def gt = graph.traversal();gt.V().hasLabel("attendee"); with reason com.thinkaurelius.titan.core.TitanException: Could not find a suitable index to answer graph query and graph scans are disabled: [(~label = attendee)]:VERTEX
Not sure what I am doing wrong.
Can somebody tell where am i going wrong?
How can i get rid of this error and get the expected output?
Thanks
#Radhika, Your Gremlin query is a valid Gremlin query. However, some vendors (such as IBM Graph and Titan) chose to only allow users to start their queries with a query that is indexed.This is to make sure you get the performance of your queries. Calling hasLabel() by itself will give you the Could not find a suitable index... error as you can't create indexes for labels. What you need to do is follow this step with a step that uses a indexed property as in this query :
graph.traversal();gt.V().hasLabel("band").has("genre","pop");
An index for genre has been created in the schema for the sample music festival data as you can see below
{
"propertyKeys": [
{ "name": "name", "dataType": "String", "cardinality": "SINGLE" },
{ "name": "gender", "dataType": "String", "cardinality": "SINGLE" },
{ "name": "age", "dataType": "Integer", "cardinality": "SINGLE" },
{ "name": "genre", "dataType": "String", "cardinality": "SINGLE" },
{ "name": "monthly_listeners", "dataType": "String", "cardinality": "SINGLE" },
{ "name":"date","dataType":"String","cardinality":"SINGLE" },
{ "name":"time","dataType":"String","cardinality":"SINGLE" }
],
"vertexLabels": [
{ "name": "attendee" },
{ "name": "band" },
{ "name": "venue" }
],
"edgeLabels": [
{ "name": "bought_ticket", "multiplicity": "MULTI" },
{ "name":"advertised_to","multiplicity":"MULTI" },
{ "name":"performing_at","multiplicity":"MULTI" }
],
"vertexIndexes": [
{ "name": "vByName", "propertyKeys": ["name"], "composite": true, "unique": false },
{ "name": "vByGender", "propertyKeys": ["gender"], "composite": true, "unique": false },
{ "name": "vByGenre", "propertyKeys": ["genre"], "composite": true, "unique": false}
],
"edgeIndexes" :[
{ "name": "eByBoughtTicket", "propertyKeys": ["time"], "composite": true, "unique": false }
]
That's why the above query works and you need to do the same.
If you don't have a schema, create one. You can model it after the
one above or follow the API
doc
Create an (Vertex/Label) index for the properties that you'll start
your traversals from. In this example, Name, Gender and Genre for
vertex properties and name for the edge properties.
Call the schema
endpoint
to add your schema to your graph
It's recommended to create your schema before adding any data to
your graph so that you don't have to reindex later. That'll save you
a lot of time.
Once you create your schema, you can't modify what you created
already, but you can add new properties/indexes later on.
Look at the following code samples for Java and Nodejs for the exact code to use.
I hope that helps

Restricting access to specific fields in MongoDB?

I have a _User Class in MongoDb for which I do not want sensitive items such as email being returned queries (unless the correct session token is sent).
I can set CLP in the _Schema like so:
```
"_metadata": {
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"update": {
"*": true
},
"create": {
"*": true
},
"delete": {
"*": true
},
"addField": {
"*": true
},
"readUserFields": [],
"writeUserFields": []
}
},
"username": "string",
"email": "string"...
```
I do not want to whole Class to be hidden - i.g., I want to keep get and find as publicly readable. I just want to hide certain columns.
I couldn't find any documentation on the field readUserFields as seen above, nor did it help to add fields within it, i.e. readUserField: ["trivialField"].
If it helps, this database structure was migrated from https://parse.com - but I believe the question is more relevant to MongoDB as a whole; there was no useful information regarding this from the Parse community.
Any help would be appreciated!