Is it possible to restrict part of an Ektron smart form to a specific user group? - ektron

Is it possible to restrict part of a smart to only a certain user group and if the user trying to edit the smart form content is not of that group, then the user cannot change that portion of the content?
Example:
Let's say I have an Employee smart form with fields for EmployeeBio, EmployeeHireDate, and EmployeeDept. Would it be possible to allow the general author user group to be able to edit the EmployeeBio field, but restrict the EmployeeDept and EmployeeHireDate fields to only an HRAdmin user group?
If it helps, I am using Ektron 9.00 SP3.

As far as I know, you either can edit a content block or you can't; there isn't a way to subdivide permissions on a per-smartform-field basis.
What you can do, is group the "restricted" fields into their own smartform, and then reference that via a content resource selector field.
So your Employee smart form might look like this:
/root/txtName (not in your example, I know...)
/root/rtfBio
/root/cresHRID
Side note: I'm using hungarian notation on my field names here. txt indicates a plain text field, rtf indicates a rich text (html) field, and cres indicates a content resource selector.
Then you could have a second smart form... let's call it "EmployeeHR", and it would have the following structure:
/root/hireDate
/root/txtDepartment
That would, in theory, work. However, I must say that I really don't like splitting up this particular type of data in this way. First, department feels like it would function better as a taxonomy to which you could add the content block. Second, it feels like this type of data would be better served by housing it outside of ektron and then using a DxH (Digital Experience Hub) connector to bring the data into Ektron. This way the external system could handle permissions at a more granular level, and you would still have access to the data within Ektron for use elsewhere within the site.
UPDATE
As I ponder this question some more, another option comes to mind. You could write an ASPX page or UserControl that checks to make sure you're logged in and a member of a particular group before presenting you with a custom edit screen. The following code will check if the current user is a member of the admin group; you can swap out a different group id to fit your needs:
// Not sure off hand which of these using statements provides access to EkConstants...
using Ektron.Cms;
using Ektron.Cms.Common;
using Ektron.Cms.Content;
var userGroupApi = new Ektron.Cms.Framework.User.UserGroupManager();
var isInGroup = userGroupApi.IsUserInGroup(currentUserId, EkConstants.g_AdminGroup);
This could be implemented as an ASPX page on your site, or it could be implemented as a widget and placed on the user's Smart Desktop tab of the workarea. Either way, you have a lot of options for getting what you want, just nothing "out of the box".

Related

Is there a way to add a "no-readers" field to a Lotus Notes document?

In Lotus Notes/Domino, we have the functionality of Readers fields, which I know all about. These say who CAN see a document. I would like to know if there is some way (may be undocumented) where you can have that type of thing that says specifically who CANNOT see a certain document.
We have an application for HR, and some of the documents in there reflect negatively about certain people (complaints, for example) and everyone who has access to the database currently can see every document. I would like to hide this type of document from that specific person. I have not enacted any Readers fields on any documents in question.
It would be really nice to have a way to keep that current setup, but insert a factor of who to HIDE the document from like Readers fields do.
I know there are undocumented features people have learned about over the years, and wondered if anyone knows of such a thing that I can use.
Create a role called [ReadAll].
Create a Group called HR Readers and one called HR Restricted.
Add the people who can't read documents to the HR Restricted group. Add all others to HR Readers.
Add these two groups to the ACL and give the HR Readers group the [ReadAll] role.
Add a readers field that is computed to "[ReadAll]" on the documents you want to prevent the people in the "HR Restricted" group to not see.
No, there is no feature that does what you want. Not on a user-by-user basis. You can play with groups and roles, as suggested by Rob Mason, but those groups and roles have to be pre-determined. We asked for Non-Readers fields (at least) 20 years ago so that we could do what you want, but Iris, Lotus, IBM, and HCL never did it. I presume that either (a) it's hard, or (b) there isn't enough demand. Or both.
To hide content from specific people, you can use hide-when formulas within a form. I.e., the hide-when formula on one or more sensitive fields would be set to
#isMember(#UserName; RestrictedUsers)
where RestrictedUsers is a field that contains the list of people who cannot see the data in the fields.
But this is not real security. A user can see the document in views, and can see the hidden fields by bringing up the document properties dialog, or with a tool like NotesPeek. If you're talking about a Domino web app, and users don't have Notes clients and you have strictly-managed desktops so you are sure that is the case+, then it kind of sort of works. Admins and developers, though, would probably have the clients and would be able to see fields in documents that they're not supposed to.
I believe if I simply compute a Readers field to say something like:
whoToHideFrom:="John Smith/org";
#Name([ABBREVIATE];#Username) != whoToHideFrom
I will try this and mark this as successful or not successful after I test it

What's the optimal way to filter a set of entities in a lookup?

I've got a lookup field on Account entity called something. Each such Something has a reference to an account. When my users click the magnifying glass, I want them to see a list of available Something records but filtered to view only such instances that link to the currently treated entity.
Also, I'll need to design such a filtration for Contact instances to only show the Something records that are related to the account that the currently regarded contact is a member of.
I can't decide between a plugin on Retrieve and some JS in OnLoad registering a fetchXML. All such operations will be done client-side. The solution needs only to work in CRM13 (and if possible apply some cool functionality in that version).
Suggestions?
JavaScript & FetchXml are your best option here as with a Retrieve plugin you're taking the performance hit of executing on every retrieve regardless of whether the entity is being retrieved for the lookup. A filtered lookup in JS only applies for those scenarios that require a change to the field on Account.
Another other good reason for using a filtered lookup in Js is they are now a supported feature in CRM 2013 as opposed to the "hack" that was required in 2011.
Some more info on addPreSearch and addCustomFilter can be found on MSDN and there's a decent blog post providing examples here.

different permissions based on workflow state

I need to set up different permission on an object based on its workflow state. For instance, 'manager group' can edit the object only if state=draft but 'super manager group' can edit it also if state=validated.
It seems that's not possible using ir.model.access and I'm evaluating if it could be done using ir.rule. It seems not...
Is there a official way to get this or do I need to implement this feature (maybe by adding a condition into ir.model.access machinery).
This is not possible by default with ir.model.access, because this permission model is designed to act like simple Unix permission on CRUD operations, and it is statically defined, per-model and per-group.
You may be able to implement something like this using ir.rule, as it implements dynamic per-record access control based on field values. By having a set of rules defined only on the write and unlink operations and based on the state field, you will be able to prevent some groups from modifying records in certain states. By using the technique of an always-true rule [(1,'=',1)] you can then relax a non-global rule for users who have a "super-access" group. See also this answer.
This option will have important caveats however:
Be careful not to make those rules apply for read, as it will make the records completely disappear, and generally wreak havoc in your processes
The interface will not become read-only when the rule is in effect, and if you want to make the fields and buttons read-only you will have to find a way to specify this via attrs in a manner that depends on the user's groups. See also this Launchpad question.
the Save button in the UI will not be disabled
The standard error reporting in case of ir.rule restriction is not very clear, so it will certainly confuse users (note: it's being improved for 7.0)
As you see, using ir.rule filters for this purpose is far from a perfect solution, and you will first need to find appropriate solutions for the above issues.
Ultimately, you might have an easier task of implementing your own logic for this, plugging a new mechanism in the ORM primitive API methods: fields_view_get (for making fields dynamically read-only based on the user groups) and the CRUD methods (for actually restricting the operations)
There is another way instead of hacking web-client.
You can always have 2 views for the same Object .
For manager group.
For super manager group.
In manager group you can use attrs = {'readonly': [('state', '!=', 'draft')]}
or any condition as you needed.
And in the same way in super manager group, you can put his condition for fields.
I have this feature working on a production environment, using just Record Rules: in Project Issues, "basic users" can create and cancel issues, but can't open or close them.
Despite the GUI limitations mentioned by #odony, it works perfectly.
These are the Record Rules used::
There is a special case that needs attention: changing from a read-write State to a read-only State:
In the action's method, if the the State is changed after other write operations, the user will be able to change the State; but if there are some write operations after the State update, the user will not be able to change State.
In my example, the Project Issue method to Open an issue is case_open(). It first changes State and then does additional changes, like settting Open Date, User and Message history. Because of this, basic users can't Open issues. If you want them to be able to do so, case_open() must be overridden so that it changes State after all other write operations are done.
I got a similar requirement...
My requirement was to make a char field(say "test_123") readonly in the sale.order if the user comes under the group "sale user" otherwise editable for the group "Sale Manager".
That is, if the sale order is in draft state then anyone can edit, but it the sale order is confirmed then this field "test_123" is only editable for "Sale Manger"
What I did is I added a functional field (is_group_manager) which returns True if the user comes under the group "sale manager" and the state is not "draft" otherwise false.
Then in the xml view I added the field "test_123" with attribute attrs="{'readonly':[('is_group_manager','=',0)]}"
for example
<field name="is_group_manager" invisible="1"/>
<field name="test_123" attrs="{'readonly':[('is_group_manager','=',0)]}"/>
This will work only in openerp v6.0. Maybe this will be helpful for you. :)

Can you restrict the access on a custom field type?

I want to create a custom field type (MyCompLookup) that will be used in lists that all users will have access to. However, the field type will be fairly complicated / confusing to a regular user who is creating a simple list in their department's site. Is there a way to restrict certain users from selecting the custom field when they are creating columns for their lists?
I'm afraid you can't set ACL on field types.
A few things you can do to achieve some kind of workaround:
Add a custom logic in SPField OnAdded method that removes the field immediately after it was added by a regular user. This method might be very confusing for users, so at least you should give a descriptive name to your field. You can find a similar solution here, where I add extra fields to the list in this method.
You can add a custom editor control (see a simple sample here) to your field, that interactsts with other controls on the add new field page, for example disables the OK button.
Hope it helps.

How to decide whether to split up a VB.Net application and, if so, how to split it up?

I have 2 1/2 years experience of VB.Net, mostly self taught, so please bear with me if I seem rather noobish still and do not know some of the basics. I would recommend you grab a cup of tea before starting on this, as it appears to have got quite long...
I currently have a rather large application (VB.Net website) of over 15000 lines of code at the last count. It does not do retail or anything particularly complex like that - it is literally just a wholesale viewing website with admin frontend, catalogue / catalogue management system and pageview system.
I don't really know much about how .Net applications work in the background - whether they are all loaded on the same thread or if each has its own thread... I just know how to code them, or at least like to think I do... :-)
Basically my application is set up as follows:
There are two different areas - the customer area and the administration frontend.
The main part of the customer frontend is the Catalogue. The MasterPage will load a list of products but that's all, and this is common to all the customer frontend pages.
I tend to work on only one or several parts of the application at a time before uploading the changes. So, for example, I may alter the hierarchy of the Catalogue and change the Catalogue page to match the hierarchy change whilst leaving everything else alone.
The pageview database is getting really quite large and so it is getting rather slow when the application is first requested due to the way it works.
The application timeout is set to 5 minutes - don't know how to change it, I have even tried asking this question on here and seem to remember the solution was quite complex and I was recommended not to change it, but if a customer requests the application 5 minutes after the last page view then it will reload the application from scratch. This means there is a very slow page load whenever it exceeds 5 minutes of inactivity.
I am not sure if this needs consideration to determine how best to split the application up, if at all, but each part of the catalogue system is set up as follows:
A Manager class at the top level, which is used by the admin frontend to add, edit and remove items of the specified type and the customer frontend to retrieve a list of items of the specified type. For example the "RangeManager" will contain a list of product "Ranges" and will be used to interact with these from the customer frontend.
An Item class, for example Range, which contains a list of Attributes. For example Name, Description, Visible, Created, CreatedBy and so on. The form for adding / editing loops through these to display relevant controls for the administrator. For example a Checkbox for BooleanAttribute.
An Attribute class, which can be of type StringAttribute, BooleanAttribute, IntegerAttribute and so on. There are also custom Attributes (not just datatypes) such as RangeAttribute, UserAttribute and so on. These are given a data field which is used to get a piece of data specific to the item it is contained in when it is first requested. Basically the Item is given a DataRow which is stored and accessed by Attributes only when they are first requested.
When one item is requested from a specific manager is requested, the manager will loop through all the items in the database and create a new instance of the item class. For example when a Range is requested from the RangeManager, the RangeManager will loop through all of the DataRows in the Ranges table and create a new instance of Range for each one. As stated above it simply creates a new instance with the DataRow, rather than loading all the data into it there and then. The Attributes themselves fetch the relevant data from the DataRow as and when they're first requested.
It just seems a tad stupid, in my mind, to recompile and upload the entire application every time I fix a minor bug or a spelling mistake for a word which is in the code behind (for example if I set the text of a Label dynamically). A fix / change to the Catalogue page, the way it is now, may mean a customer trying to view the Contact page, which is in no way related to the Catalogue page apart from by having the same MasterPage, cannot do so because the DLL is being uploaded.
Basically my question is, given my current situation, how would people suggest I change the architecture of the application by way of splitting it into multiple applications? I mean would it be just customer / admin, or customer / admin and pageviews, or some other way? Or not at all? Are there any other alternatives which I have not mentioned here? Could web services come in handy here? Like split the catalogue itself into a different application and just have the masterpage for all the other pages use a web service to get the names of the products to list on the left hand side? Am I just way WAY over-complicating things? Judging by the length of this question I probably am, and it wouldn't be the first time... I have tried to keep it short, but I always fail... :-)
Many thanks in advance, and sorry if I have just totally confused you!
Regards,
Richard
15000 LOC is not really all that big.
It sounds like you are not pre-compiling your site for publishing. You may want to read this: http://msdn.microsoft.com/en-us/library/1y1404zt(v=vs.80).aspx
Recompiling and uploading the application is the best way to do it. If all you are changing is your markup, that can be uploaded individually (e.g. changing some html layout in an aspx page).
I don't know what you mean here by application timeout, but if your app domain recycles every 5 minutes, then that doesn't seem right at all. You should look into this.
Also, if you find yourself working on various different parts of the site (i.e. many different changes), but need to deploy only some items in isolation, then you should look into how you are using your source control tools (you are using one, aren't you?). Look into something like GIT and branching/merging.
Start by reading:
Application Architecture Guide