Sitecore Workflow Only for Specific User - permissions

I have three users (A, B and C) and set workflow for items.
The workflow process is perfectly working as I expected.
In this case, I'd like to set workflow only for A user and other users (B and C) will not use any workflow process even the process was already assigned into content items.
So, A user will follow the process like "submit", "approval" and "publish".
B and C users will not use workflow and they are not required, just change and publish.
How can I do this??? I guess I need to update workflow permission in security??

You'll have to write some custom code to do this as you can't skip the workflow on an item.
Instead you can write some code to hook into an event - on save seems like a good option. you can check:
if the item has workflow
If the user had a specific role to skip workflow (users b and c)
If Workflow is in the correct state
On these conditions you can then programmatically action the workflow to the next state or set the workflow field to approved.
Some great sample code from Cognifide here on actioning or updating the workflow on an item programmatically
https://www.cognifide.com/blogs/sitecore/changing-workflow-state-of-sitecore-items-programmatically/
There's also an example here of somebody setting up a skip approval action to push the items workflow to the final state.
How to programmatically approve a content item in Sitecore
I'd advise you to be careful with skipping workflow as content can easily end up being approved accidentally if the power user edits editor's content. It can be annoying for some users to keep pressing submit and approve all the time but it is a good fail safe.
Another thing you could do is create a custom workflow action after the draft state to update the workflow to the final state when a new item is created in draft by users b and c.

What you can do is use a AutoSubmitAction that will be allowed only for Power Editor role (or whatever role are users B and C assigned to) and that will change the state of edited item to the final state of workflow every time the item is saved. This action should be added under the initial state of your workflow (under __Save command).
Obviously the workflow is still there but users B and C don't have to submit or approve.
No coding is required but you need to remember that workflow is a powerful tool and skipping it can be dangerous if your power editors are not careful.

Related

How can I figure out if the authenticated user is authorized to access an area/controller/action?

Being in a view and you know the area-name, controller-name and action-name of a destination to which you want the user to provide a link to, how can I figure out if the area/controller/action is authorized for the authenticated user.
Imaginary Use-case:
I have a table with a list of books (the result of bookscontroller.index). To the far right are some icons to edit or delete a specific book. The edit link refers to bookscontroller.edit and the delete link to bookscontroller.delete.
On the actions there are custom authorizationattributes and this works perfect. If a user want to access books/edit/1 and the user is not allowed to edit books, the user gets redirected to the logon page.
It is a bit stupid to have that edit-icon there if the user is not allowed to edit books. So at view level I would like to be able to figure out if the user is allowed to use the edit action of the bookscontroller. If he is, show the icon if not, do not show the action.
Goal: use that knowledge to create a custom tag-helper.
The go-to method is reactive, i.e. you check if a user can do action when the user tries to do. Since you do not want to go that way, here is how. (yet, this is anti-pattern)
Have the authentication token of the user send back to backend. The backend should have an API end point for each button on the page user can click. With the authentication token, the back-end resolve whether to dim or enable the buttons.
Now, what the backend does to resolve this is not very efficient. The backend needs to literally attempt certain actions and aborts the transaction. For create and retrieve, it is trivial (you can pre-resolve them) but for edit and delete, this requires a lot of resources.
The standard way of controlling such actions on UI is to use role based authorization.
For the buttons or other such UI elements, setup role tags, e.g. "admin:edit", "viewer:readonly" etc.
When you are authenticating a user, send the applicable roles from the backend server, store them in a way that is globally accessible to your UI and use them for filtering UI elements across your application.

Site Workflow Not Working With Contribute Permissions

I have set up a form where when someone presses the "Submit" button it initiates a site workflow to create a list item. It all works well when I (full control permissions) do it, but if someone with contribute permissions tries, it fails. I tried adding an impersonation step, but that doesn't seem to be working either. Also, I am trying to record the person who created the list item, and the impersonation step uses my name (workflow author) for "Created By."
Any suggestions as to what I could've possible done wrong, or what I should try to do/add? Thanks in advance...
Simple answer is No.
As you can see the checkboxes in workflow property, you can set the trigger to be
trigger itself when item added or modified.
manually start by users.
For the read-only user, they are not able to click the "start a workflow" button. Also, these users do not have permission to add or modify list item.
You can configure your workflow with "impersonation step". In this way, the workflow will be running under the account of "workflow creator" instead of the user trigger the workflow. However, even you applied "impersonation step", the read-only user still not able to trigger a workflow

CRM 2013 - Prevent Deletion of a record based on a condition

I have an entity titled Document Access. Now, this entity Document Access has a N:1 relationship with Incident (One Incident can have many Document Access).
When someone creates a new Document Access record, I have a JS which checks if the person who is creating the record (current logged in user) is the same as the Incident's owner. If not, I disallow the creation (this is set on the Save of the record).
The Document Access record's owner can be anyone (not necessarily the Incident's owner). How can I ensure the prevention of the deletion of these Document Access records unless it is done by the Owner of the Incident?
Can I achieve it via Security Roles? I am not able to come up with a solution that can achieve this via Security Roles so that the Delete button does not even appear when a View or a Form is displayed.
Can I achieve the same via JavaScript hooking into the Delete button as part of
the ribbon? If so, how can I get the Incident id that is being selected for Deletion? Would it also be triggered if we did a bulk delete?
If it is a plugin, should it be on the Pre-Validation stage of the Delete operation?
I'll attempt to answer and qualify each of your own options:
Using Security Roles. No because you want to control the deletion based on the ownership of a related entity which isn't possible.
Using JavaScript. You could hide the buttons with a custom JavaScript ribbon rule that compares the Incident owner to the Document Access record owner. However, this approach won't support all use cases including bulk delete.
Using a Plugin. This is the correct approach and registering on Pre-Validation is fine. It will enforce your business rule regardless of where the delete request originates. This could be from a user via the UI, a bulk delete or platform operation such as an external integration request. Make sure you return a meaningful message in the exception that explains the business rule.
The best approcah is to do this through a plugin on Delete of Document Access records.
In your code you may follow this steps:
Retrieve the Owner of the Incident related with the Document Access:
Guid incidentId --> You get this form the lookup field, you have in Document Access to Incident
Entity incident = service.Retrive("incident", incidentId, new ColumnSet("onwerid"));
Check if the user who triggered the plugin is the Owner of the Incident
// context --> execution plugin context
Guid ownerIncident = ((EntityReference)incident.Attributes["ownerid"]).Id;
if(ownerIncident != context.InitiatingUserId)
{
throw new InvalidPluginExecutionContext("Can't delete Documet Access record");
} // otherwise let the record to be deleted

SharePoint 2010 Authorization Question

Let’s say I have 2 pages in a sharepoint site. Let’s call them page A and B. We are using windows based authentication mechanism. Let’s say I have 2 already authenticated users X & Y. The page A should be visible to users who have certain attribute set to 1 in active directory. Page B should only be visible to those users that does not have this attribute set to 1. Let’s call this attribute SpecialUser. If SpecialUser is 1 for a given user, user should be able to see page A only and not be page B. If SpecialUser has any other value, user should be able to see page B only and not be page A.
In this case, user X has the attribute SpecialUser set to 1 and user Y does not. So user X should only see page A while user Y should only see page B.
There is no group in active directory that includes only users that have SpecialUser attribute value set to 1. We don’t want to create sharepoint group and add these users manually either.
Given these constraints, how can we achieve this authorization? I am thinking there may be a need for custom coding. If custom coding is required, how do I go about it. If not, what is the solution?
If your Web Application can be setup to use Claims Based Mode instead of Classic Mode, you should be able to achieve this without custom coding, since an Active Directory attribute can be used as a claim when setting permissions on the page.
Otherwise custom coding would be required. You can create a custom web part that you place on the page, which can either redirect the user or call SPUtility.HandleAccessDenied(new UnauthorizedAccessException()) for invalid users. To security trim the pages (make them invisible), you would need similar logic in any menus or web parts that display the pages.
If the Active Directory attribute is part of the SharePoint User Profile, you can use the UserProfile class. Otherwise, you can use System.DirectoryServices.AccountManagement to retrieve the value of the attribute.
I think that the easiest thing to do might be to stick with the active directory side. Sharepoint authentication can be a bit fickle. Off the top of my head I would probably suggest creating an active directory group that's meant to hold a list of these users. Rather than updating it manually you could have a service to run every so often (once a day? once an hour? depends on how long you're willing to have stale authentication) and check the user lists in active directory for this flag. The service would then update the group you're using for authentication.
There might be a way to do this more gracefully within the walls of Sharepoint development, but I've not heard of anything like it.

Sharepoint 2010 anonymous publishing site - workflows not running

We're working on a publishing site with sharepoint 2010. It allows anonymous access, and these anonymous users can fill out certain forms. The form submission works fine as the anonymous user has permission to insert to the lists.
There is a simple workflow attached to each form that emails the contents of the form to an internal user. This works fine if you add the list item manually (ie logged in as a certain user), but the workflow can't be initiated by an anonymous user. It hangs in progress, then eventually fails.
I tried this:
http://blog.furuknap.net/enabling-declarative-workflows-for-anonymous-users-in-sp20102007
But it didn't seem to work either. Some comments from users refer to this same issue - and no one stated a resolution.
I'm worried that the only solution is the run with elevated privileges on each form as a custom web part.
Any solutions out there?
thanks.
The steps described in the mentioned post only work for items added to the list by email. So any items added (new form, new document, new event) added using the sharepoint UI will NOT trigger the workflows. (see the related MS KB article).
There are 2 things I can think of you could try:
Use an ItemEventReceiver bound to the list to send the email in the ItemAdded event.
If all the workflow does is send an email to a user, just have that user subscribe to the list using an alert