Serenity: Custom service operation permission when reusing other methods

Created on 28 Oct 2016  路  3Comments  路  Source: serenity-is/Serenity

I have developed a custom form for users with limited rights that should only be able to approve a single XY-record and not change any other field. I have created a custom MVC-Form and XY-PageController action for this.

For this I have created a new service operation and repository method. Internally I reuse the other repository methods Retrieve and Update in order to perform the operation.

Simplified Code-Snippet of Repository Method:

public class XYApprovalRequest: ServiceRequest
{
    public int Id { get; set; }
    public string Notes { get; set; }
}

public XYApprovalResponse SetApproved(IUnitOfWork uow, XYApprovalRequest request)
{  
    var entity = Retrieve(uow.Connection, new RetrieveRequest()
    {
        EntityId = request.Id
    }).Entity;

    entity.Notes  = request.Notes ;
    entity.Status = XYStatus.Approved
    entity.Date = DateTime.Today;

    var updateResponse = Update(uow, new SaveRequest<MyRow>()
    {
        EntityId = entity.Id,
        Entity = entity
    });
   ...
}

Now my problem is if I set more restrictive permissions on the service operations or attributes, like ModifyPermission[] on XYRow, my custom operation fails, because it reuses the Retrieve / Update methods internally, which check the user authorization again.

How can I modify this in order to guarantee, that:

  • Users with full Permission A have full access to all standard serenity entity dialogs and service operations.
  • Users with limited Permission B can only execute the SetApproved service operation.

Surely I could implement the update method via custom SQL, however I'd loose the advantages of the typed objects provided by the serenity entities.

Most helpful comment

Another possibility:

Find this in SiteInitialization.cs:

registrar.RegisterInstance<IPermissionService>(new Administration.PermissionService());

Replace with:

registrar.RegisterInstance<IPermissionService>(
     new Serenity.Web.TransientGrantingPermissionService(new Administration.PermissionService()));

Then in your SetApproved method:

public XYApprovalResponse SetApproved(IUnitOfWork uow, XYApprovalRequest request)
{  
    var grantor = (ITransientGrantor)Dependency.Resolve<IPermissionService>();
    grantor.GrantAll();
    try
    {
        var entity = Retrieve(uow.Connection, new RetrieveRequest()
        {
            EntityId = request.Id
        }).Entity;
   }
   finally 
   {
        grantor.UndoGrant();
   }

This grants all permissions to current user temporarily.

You may also use grantor.Grant("B") instead of grantor.GrantAll() to grant only that permission temporarily.

All 3 comments

If users with permission B should be able to retrieve a record, then set B as read permission. Or use a generic basic permission and grant both group of users that one.

If that's not possible, you need to either add a second parameter, e.g. ignorePermissions to your Retrieve method in repository, or, use connection.ById < > instead of calling the repository.

Another possibility:

Find this in SiteInitialization.cs:

registrar.RegisterInstance<IPermissionService>(new Administration.PermissionService());

Replace with:

registrar.RegisterInstance<IPermissionService>(
     new Serenity.Web.TransientGrantingPermissionService(new Administration.PermissionService()));

Then in your SetApproved method:

public XYApprovalResponse SetApproved(IUnitOfWork uow, XYApprovalRequest request)
{  
    var grantor = (ITransientGrantor)Dependency.Resolve<IPermissionService>();
    grantor.GrantAll();
    try
    {
        var entity = Retrieve(uow.Connection, new RetrieveRequest()
        {
            EntityId = request.Id
        }).Entity;
   }
   finally 
   {
        grantor.UndoGrant();
   }

This grants all permissions to current user temporarily.

You may also use grantor.Grant("B") instead of grantor.GrantAll() to grant only that permission temporarily.

I have just implemented the second solution and it worked perfectly.

Thank you for the great template and assistance!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Estrusco picture Estrusco  路  3Comments

Shraddha996 picture Shraddha996  路  3Comments

kilroyFR picture kilroyFR  路  3Comments

gfo2007 picture gfo2007  路  3Comments

Pinellus picture Pinellus  路  3Comments