setCanDeleteDocuments() Lotus Notes ACL - xpages

I am trying to delete document,where conditions is...
Where the user is in Group and having the deletion rights & every users in group is able to delete the document.
But problem is when, If the name I specify is also listed explicitly in the ACL and does not have deletion rights.Then it does not check the group rights which is fair enough.
For that i am trying to give deletion rights to those users who are in group by code given below.
var acl:NotesACL=database.getACL();
var entry:NotesACLEntry=acl.getFirstEntry();
if(entry!=null)
{
var user:NotesACLEntry=acl.getEntry(#UserName());
if(user.isCanDeleteDocuments()==false)
{
user.setCanDeleteDocuments(true);
acl.save();
}
}
Where it shows error like,
Exception occurred calling method NotesACL.save() null.
Even explicitly added user is having user type=person & Access= Manager in ACL.
is there any other way to do this?
Any help would be appreciated.
Thanks in advance.

Using database as a starting point means you're getting the database as the user. Unless the user already has Manager access to the database, this will fail because the user doesn't have access to update the ACL.
You can use sessionAsSigner, but bear in mind you cannot use the getCurrentDatabase() method. Instead you must use the getDatabase(server,filePath) method in order to get the database with the signer authority. Obviously the signer also needs rights to modify the ACL.

Related

Display customer specific information on product detail page - what about the caching?

We want to display customer (actually customer-group) specific information on product detail pages in Shopware 6.
There seems to be the HTTP cache and we are afraid that the page would be cached if a specific customer group displays the page and the information would be leaked to non-customers.
Is this assumption correct?
The documentation does not reveal much information about this.
Is there a way to set specific cache tags, so that the information is only displayed to the correct customer group?
Or do we need to fetch the data dynamically via AJAX?
Bonus question: Can the HTTP cache be simulated in automatic tests to ensure the functionality works?
What I found out so far:
The is annotation #httpCache for controller, which seems to control whether a page is cached or not
The cache key is generated in \Shopware\Storefront\Framework\Cache\HttpCacheKeyGenerator::generate. It take the full request URI into account, and some cacheHash which is injected. I believe it would not take the customer group into account
Maybe this generate() method could be decorated, but I am not sure if that is the right way.
There is a cookie being set sw-cache-hash which influences the caching. It takes the customer into account.
sw-cache-hash is created here:
if ($context->getCustomer() || $cart->getLineItems()->count() > 0) {
$cookie = Cookie::create(self::CONTEXT_CACHE_COOKIE, $this->buildCacheHash($context));
$cookie->setSecureDefault($request->isSecure());
$response->headers->setCookie($cookie);
} else {
$response->headers->removeCookie(self::CONTEXT_CACHE_COOKIE);
$response->headers->clearCookie(self::CONTEXT_CACHE_COOKIE);
}
So as soon you are logged in or have some items in the cart, a different cache hash is used. This depends on the following, but not on the customer group it self:
private function buildCacheHash(SalesChannelContext $context): string
{
return md5(json_encode([
$context->getRuleIds(),
$context->getContext()->getVersionId(),
$context->getCurrency()->getId(),
]));
}
Additionally there is the notion of cache-invalidation states, that describe when the caching should not be used.
You can configure that inside the shopware.yaml config file for the http-cache as a whole or on route level for the store-api routes.
From the default config inside platform:
shopware:
cache:
invalidation:
http_cache: ['logged-in', 'cart-filled']
product_listing_route: []
As you can see by default the http-cache won't be used if a user logs in or has something in his cart.
As you can see in the last code snippet, it takes into account the active Rule ids.
This means that if you create a rule (through Settings > Rule Builder) that is active on a certain group, but not on another or no group, it will be taken into account & create a different cache hash for the different customer groups.

REST API - How to implement user specific authorisation?

So I'm currently learning/building a REST API backend server for my web application using NodeJS, ExpressJS, and MySQL as the database. My question is in regards to the best way to implement authorisation to ensure User A does not access or edit the data belonging to another User. Please note that I understand there are a lot of examples for implementation of role based authorisation (ie user groups vs admin groups, etc) but this is not what I'm asking. Instead, how do I authorise a user against the data they are accessing?
It is possible that I'm overthinking this and this is not even necessary; that I should just check whether the data belongs to the user in every SQL query, but I thought I'd ask if there's a middleware or policy architecture that takes care of this, or maybe even authorise through caching.
The only solution I can think of is that every SQL query returns the the user id with the result, then I just create a service that checks every result if the id matches or not. If yes, then proceed. If not rollback the query and return unauthorised error. Is this ok?
I very much appreciate your advice, help, and if you can point me in the right direction.
Many thanks in advance.
Save the userId (or ownerId) in every table, and create a middleware where each db access method requires the userId as a parameter, for example:
readOne(id, userId) {
// implements SELECT * FROM example WHERE id = id AND userId = userId
}
updateOne(id, data, userId) {
// implements UPDATE example SET data = data WHERE id = id AND userId = userId
}
...
For security reasons, never send as a response "Requested data exist by you aren't the owner".
The simplest things usually work best. You wouldn't have to have a special service for checking authorization rights for every entity and you can do it at data access level eg. SELECT * FROM foo WHERE user_id = :currentUser or UPDATE foo SET foo = bar WHERE user_id = :currentUser
It also depends whether you want to notify the user about unallowed access via HTTP401 or not to reveal that such a resource even exists for different user HTTP404.
For HTTP401 the scenario would be:
const entity = loadFromDB(id);
if(entity.userId !== currentUserId) {
res.send(401);
return;
}
... update entity logic ...

IBM Domino 10 - Java XPage create session or compare credentials of another user

I'm writing Java code in an XPage Rest Service basing on https://setza-projects.atlassian.net/wiki/spaces/RSD/pages/44007659/IBM+Domino which is an REST service written in Java used to handle Resource Reservations database. However the way it currently works, it creates the reservations for the current session user only:
private JsonObject createIntanceAppointment(ResourceDefinition rd, Database reDatabase, Date dtStart, Date dtEnd, String subject) throws NotesException {
Session session = reDatabase.getParent();
Name nnOrganizier = session.createName(session.getEffectiveUserName());
Name nnREsource = session.createName(rd.getFullName());
DateTime dt_startDateUTC = session.createDateTime(dtStart);
DateTime dt_endDateUTC = session.createDateTime(dtEnd);
Document doc = reDatabase.createDocument();
doc.replaceItemValue("form", "Reservation");
doc.replaceItemValue("Purpose", subject);
doc.replaceItemValue("ReservedFor", nnOrganizier.getCanonical());
doc.replaceItemValue("ResourceName", nnREsource.getAbbreviated());
doc.replaceItemValue("ResNameFormat", nnREsource.getAbbreviated());
I'm doing a very similar integration with Domino, although I'd prefer to have the reservations created for individual users (they provide their username & password on the room-booking application on a touch screen).
I could just authenticate as the user in my REST client, but if I understand the installation requirements for that RoomZ api correctly, the 'api managing user' needs to be exclusively signed to the database, so I would need to do that for every user in Domino that could make reservations.
I tried using NotesFactory.createSession("", "user", "password"); but that doesn't work, it gives Cannot create a session from an agent error
If I cannot create another session, is there any way I could verify that the username and password passed to the API in the payload is correct (to verify if the user can login)? Then I could just set the organizer/reserved for to this user.
Also, is there any way to make these reservation also appear in the organizer's Notes calendar? Currently they are succesfully created in the Reservations database and all, but the organizer is unaware of them despite he's assigned to the reservation.
You do not need to create a session for every user. The important thing is the nnOrganizer = session.createName(" ") which should contain the user. Probably you'll also need to set additional fields like chair or from for the reservation.
If you want to have some entries in the organizers calendar, send them a proper invitation or create a calendar entry in their mailfile.

Multiple database application ACL (part 2)

I posted this question Access Control with a multi database application
So I tried putting it into application. Here is the case. I have a mainDB that has an ACL with no roles defined. The User clicks a button and it opens a control for CRUD with a datasource that has a computed filepath to a different database call it appDB. In appDB the ACL has several roles defined, and I have added myself to the ACL and assigned me the roles [Admin] and [Finance]. In this control I have added an After Page Load event that does the following:
var roles = context.getUser().getRoles();
viewScope.put("vsRoles", roles);
Upon opening the page the viewScope vsRoles is [] so it has not recognized that I have an additional set of roles in the appDB. So it would appear that context.getUser().getRoles() only gets my roles at authentication time when I log into the mainDB.nsf, and is not picking up the roles when I open appDB. I need to use the roles to configure what actions a person can perform, plus which documents a user can read and/or edit.
To complicate the issue the user may switch between multiple target application databases and will no doubt have different roles and access to each one.
thanks for the response to my previous question,but I might not have explained it in enough detail.
So, as far as I understood, what you need is to learn what specific roles the user has for the appDb.
context.getUser().getRoles() provides information about the current application (mainDB.nsf in your case). You are accessing appDB.nsf at a data source level. You can use a java method to learn the roles of a specific user in a target database:
public static List<String> getRoles(Database targetDb, String userName) {
ACL acl=null;
List<String> roles=new ArrayList<String>();
try {
acl=targetDb.getACL();
roles.addAll(targetDb.queryAccessRoles(userName));
} catch (NotesException e) {
// failed, nothing to do...
} finally {
if(acl!=null) acl.recycle();
}
return roles;
}
As an example:
Session session=ExtLibUtil.getCurrentSession();
Database appDb=session.getDatabase("", "appdb.nsf");
// Make sure appDb is not null...
List<String> roleList=getRoles(appDb, session.getEffectiveUserName());
ExtLibUtil.getViewScope().put("vsRoles", roleList);

Setting up user_ctx field on CouchDB Replicator

"user_ctx": {
"name": "adminuser",
"role": "[\"_admin\"]"
},
"_replication_state": "error",
"_replication_state_time": "2011-08-30T15:09:03+00:00",
"_replication_id": "08fd9d6dcc5a0882fc9fd0d971b05938"
}
For some reason, I can't get my replicator to work. The log continues to show "unauthorized to access database", referring to my localhost. I know I need to have user_ctx set, but for some reason it just doesn't like to work. I copied the info out of my source. I even created new admin users to try and fix the problem, none worked. Do I need to specify more roles for the user?
The other has a good resource https://gist.github.com/832610, but the user_ctx he set's in the example isn't the admin user, the appear to just be random roles.
Anyone have any experience with the CouchDB replicating to the localhost?
If you create the document as the server admin, then you do not need this field. I think omitting it completely will work.
If you create the document as a normal user, then it should match your name and roles which you can get by querying /_session. In fact, I think you can copy the userCtx field from the session response directly into the user_ctx field of the replication document.
Found out what I did thanks to the CouchDB Apache Mailing Lists. Should have had "roles" instead of "role".

Resources