How can I let only managers to acces a certain view, what do i need to write in the PostOpen of the view(lotusscript),
TY very much guys
AFAIK there is a "Security Tab" in the view design editor where you can specify who (person,roles) can use the view. No script necessary. The view will be hidden for persons that is not allow to access the view.
As you are not describing in your question, why you want to hide the view, here are a view general comments:
Hiding a view from a group of people does not limit access to certain documents to this group of people. Unless the documents are otherwise protected, users can create private views and folders that display the documents shown in the restricted view. If you do not want to grant them access to the documents, please use reader fields.
"Managers" in the ACL have the right to change the database ACL, ... In regards to read access to documents, there is no difference to "Reader"s, as long as you are not using Reader fields in documents.
If you meant "Managers" as a role, please follow Peter's and Knuth's advice but keep in mind once more that limiting access to a view does not limit access to the documents via another view.
For more details on access rights, ... please take a look at Access levels in the ACL, Roles in the ACL, Creating read access lists to limit view and folder access and The Domino security model.
Related
I'm currently reading a lot about access control possibilites/mechanisms that can be used to protect resources in an application or web application. There's ACL, RBAC, ABAC and many other concepts out there.
Assuming I have developed a simple webservice that returns knowledgebase articles on a route like '/api/article'. The 'controller' connects to the database and fetches all articles and returns them as XML or JSON.
Now I would like to have control over which article in the database is accessible for which user or group. So for instance if user 'peter' accesses the route '/api/article' with his credentials, the webservice shall return only articles that are visible for 'peter'.
I would want to use ACL to control what each user/group can read/write/delete. But what I don't quite understand:
Where does one enforce the access control? Do I just fetch all records in the controller if a user accesses the route '/api/articles' and check each single record against an access control list (that doesn't sound very good performance wise)? Or is there a way that the 'SELECT' statement to the database only return the records that can actually be seen by that specific user?
I really tried hard to find more information on that topic, and there is a lot about different access control mechanisms, but not about where and how the actual enforcement happens...and it even get's more complex if it comes to other actions like modification, deletion and so on...
This is really a matter of implementation and everyone does it its own way. It also depends on the nature of the data, particularly on the size of your authorization (do your have 5 roles and users are attached to them or does each user have a specific set of articles he can access, different for each user - for instance)
If you do not want to make the processing on the controller, you could store the authorization information in your database, in a table which links a user to a set of KB articles, or a role (which would then be reflected in the article). In that case your SELECT query would just pass the authenticated user ID. This requires that the maintenance of the relationship is done of the database, which may not be obvious.
Alternatively you can store the ACL on the controller and build a query from there - for specific articles or groups of articles.
Getting all the articles and checking them on the controller is not a good idea (as you mention), DBs have been designed also to avoid such issues.
I have an old local copy of a lotus notes database that I need to have the user's access to be read only. Right now they can open a record and change anything inside of it and save it.
Now for every view(role) to show up for anyone, I had to uncheck 'Enforce a consistent access control list across all replicas'
If I don't uncheck that, the views inside the database (records) are not visible. Is there any code I can insert in the database via Designer to lock this down?
thanks
You need to get the ACL (and any group memberships associated with it) right so that the users are assigned the correct roles. That way you can put the checkmark back on the "Enforce consistent access..." property without users losing access to the views.
I'm not 100% sure about this, but I think you'll need to have them pull new local replicas from your server after you correct the ACL in order for their Notes clients to recognize the change in their permissions.
I have a navigation bar at the top of my Xpages applications. This element is going to be shared among many Xpage apps - it will work kind of like a intranet for our Xpage apps.
I do not want to display databases links to users who do not have access to the database.
How do I determine if a user can access a db? And is this something that I should somehow cache, so it doesn't have to be loaded again and again:
You can use the Database method queryAccess(name) to get the ACL level for the individual user. You can then check for No Access and for Depositor. Here's an example that returns true if the user has access to db:
db.queryAccess(userName) != ACL.LEVEL_NOACCESS && db.queryAccess(userName) != ACL.LEVEL_DEPOSITOR
I will suggest that you cache this in a user bean for the user.
Per's suggestion is great but be aware of one limitation on queryaccess:
From the documentation:
If the name you specify is listed explicitly in the ACL, queryAccess returns the access level for that ACL entry and does not check the groups.
If the name you specify is not listed explicitly in the ACL, queryAccess checks if the name is a member of a group in the primary Address Book known to the computer on which the script is running. On a local workstation, that address book is the Personal Address Book. On a server, that address book is the Domino® Directory. If queryAccess finds the name in one or more groups, it returns the highest access level among those groups. If the name you specify is not listed in the ACL either individually or as part of a group, queryAccess returns the default access level for the ACL.
First of all - if code runs under user's privileges, you can't call queryAccess for database you can't open. To work around this you could force the code to use signer's session and get the access. But...
I recommend this: make a bean named hasAccess. About the scope:
application scope is shared among users - useless
session scope - quite fine, but in case of ACL change
you would need to restart http or wait for session timeout
view scope is recommended
request scope wont help much
Implement map interface, so you can bind it like #{hasAccess[database]} where database will be filepath, or some special key to lookup database. Implement cache and return true/false, according to user's access. How do you determine user's access is up to you, but I think the best method is to use try/catch with attempt to open that database and check it with isOpen().
When developing xPages applications, what is the best practice for securing the nsf from a traditional Notes client. I would like to prevent any access to the database through the Notes client while having no impact to the xPage.
I would like to restrict access for a number of reasons. Security to the documents and the views, preventing users from using the application in notes and forcing them to use xPages. It looks like there is no silver bullet to accomplish this, but rather I need to use a number of different solutions.
You can't prevent it by ACL. You can redirect common users to open your application in browser, tho. In our applications, to prevent opening them in client and XPiNC, I have made simple subform with queryOpen script:
Dim ws as New NotesUIWorkspace
ws.URLOpen Source.Document.HttpUrl
Continue = False
This subform is put inside forms that user can get doclinks to or open from view. At view level you can adopt similar approach for all visible views and/or OpenDatabase script.
This works very well with this tweak: native Domino links and XPages
Why do you want to prevent access?
I assume that administrators and servers should be able to access the nsf. So LocalDomainAdmins, LocalDomainServers, etc. should be part of the ACL.
You can restrict user access from the Notes client to the nsf itself by making sure that user access groups in the ACL contain the names of user accounts (person documents in names.nsf) that have no matching Notes name (Notes id). The users can then only access the application from web and not from Notes.
But this might not be a feasible solution if users already have Notes access. Because then you have to create new person documents with user names that does not match the existing person documents, meaning that existing users then have a person document for Notes access and a person document for web access.
Instead you should perhaps look at restricting access to documents (using Readers fields) and views (through restricting access to a certain role).
I'd consider going even simpler on this and simply changing the launch property for the client to redirect to a page that indicates the user should access the application through a browser, and provide the URL to access the system. This isn't a perfect solution, depending on how information is disseminated in this system, but if users are simply opening the application through the notes client this would provide a good redirect as well as retraining the end user how the application is meant to be used in the future.
Split the app into two .nsfs. One for data other for only xpage design. Lock down the data .nsf and restrict it to only allow design signer access. It will cause some headaches as you will need to use sessionAsSigner to pull data.
Create a new role in the database called "Admin"
Put code in database script post open event that will use uidatabase.close if user do not have the admin role
Put script in alla views "query open" events with continue = false for all users without the admin role. ( this will prevent user from opening a view from the workspace using the go to view menu action)
Assign the "Admin" role in the acl only to the people that should be able to access it from the Notes client
You can also "hide" all views from Notes for everyone except the "Admin" role, but this might cause other problems depending on how the application is designed.
By either stripping the fields from the Forms or hiding all of them, you can make attempting to access the data in Notes unpalatable. You could then hide the views from the Notes client and make accessing the documents even more difficult (though someone could still create private views).
In one of our databases, the database opens to an XPage in XPiNC, which displays a link only for administrators to open the views.
var server:NotesName = session.createName(#Subset ( #DbName(), 1));
var filepath = database.getFilePath();
return "Notes://" + server.getCommon() + "/" + filepath + "/ViewToOpen?OpenView";
While it doesn't prevent the end user from accessing the Notes client version in all circumstances (someone could still send a doclink or view link), it allows users to follow their normal double-click pattern and open the database the way I want them to see it. With the link, I can allow such for those who really need Notes client access to it.
Maybe a bit late to the party, but here is our solution, to be put into the DatabaseScript PostOpen event.
#If(
#IsNotMember("[Admin]"; #UserRoles);
#Do(
httphostname := #DbLookup("" : "NoCache"; #ServerName : "names.nsf"; "($ServersLookup)"; #ServerName; "HTTP_HostName"; [FailSilent]);
#URLOpen("https://" + httphostname + "/" + #WebDbName);
#Command([FileCloseWindow])
);
""
)
This checks for the [Admin] role (to grant administrators backend access, could be left out if not needed) and if the user is not a member, gets the configured server hostname from the Domino server's addressbook, then builds and opens the URL in the browser, and finally closes the database.
Other than LotusScript in the PostOpen event, this #Formula code is capable of closing the database. And with this, you have all the code in one place only, and it gets triggered regardless if the user enters the db using a document or a view link or just opens the database via tile.
I have some user-specific data that I need to store in SharePoint and make accessible to the user through custom webparts. Let's say a list of favorite URLs. What would be the most straightforward way to store this information?
Some builtin propertybag for SPUser or similar that I'm not aware of.
SPList, associated through User column.
Custom database table, associated through SPUser ID.
Otherwise?
Sounds like a RTFM to me, but I'm probably asking google the wrong questions.
[Update]
We eventually stored this information in a simple list, in a fixed location, with a Person field to filter on. Perhaps the simplest solution indeed, but technically I think the marked answer below is nicer.
If you want to make them reusable across the site collection for each user you can add Fields to the User Information List. You can add a feature receiver to your web parts solution that can create this column or check to see if this column exists in the User information list to be sure that the Column exists.
The User Information list is a Standard SharePoint list that SharePoint uses to store user information.
To access the User Information List you can go to the Root web of the Site Collection and use the SiteUserInfoList property
E.G.
SPList userInformationlist = SPContext.Current.Site.RootWeb.SiteUserInfoList;
//Or
SPWeb web = SPContext.Current.Site.RootWeb;
SPList userInformationlist = web.SiteUserInfoList;
To access a users List Item you can use the Users Id to get the ListItem back from the User Information List
E.G.
SPListItem currentUserItem = userInformationlist.GetItemById(web.CurrentUser.ID);
If you are using MOSS you can store this information in the User Profiles and make it available across Site Collections this does not need My Sites to be enabled. You would need to use the User Profile classes to access this.
I would go for the properties on the user profiles. You do not want to store the information on the root web as it is not information regarding the root web.
Your example with the favorite urls, each user has a "quick links" collection on their profile. An ideal place for storing urls for each user. :)
Build a webpart that reads/writes a custom database and you'll have the flexibility to use the webpart across SiteCollections, WebApps, or even seperate Farms.
This was implemented where I work and it has been a big success. We needed a way to provide our end users a large selection of important, commonly used links. End users have the ability to display the links that are useful for their particular job function and have a webpart that can be put anywhere to reference those links that are important to them. You also have the ability for an “admin” to go to the custom database and update any URL’s that might change without the end user ever being impacted or ending up with a broken link.
This is a very good question.
Although I have no perfect answer, here are some things you can consider:
Store data in a browser cookie if this is feasible.
Store in the Site collection's rootweb in the Properties, keyed by the user's login ID. You may want to elevate when reading / writing the properties just in case the user has access to a subweb, but not the rootweb.