Skip to content

Permissions API

Every data object in Backendless has its own access control list (ACL) - a matrix of operations and principals (application's users or roles). An intersection of an operation and a principal contains a permission which determines whether the principal has the right to execute the operation. These permission could be either grant or deny. Backendless console provides an easy to understand way to see and manage these permissions. For example, the screenshot below demonstrates an ACL matrix for an object. Notice the intersection of a column for the Create operation and the AuthenticatedUser role. The cell contains a green checkmark icon representing that the permission is granted:

permission-matrix

In addition to managing the ACL permissions with Backendless Console there is also Permissions API:

// Permission operations
typedef SWIFT_ENUM(NSInteger, PermissionOperation, closed) {
    PermissionOperationDATA_UPDATE = 0,
    PermissionOperationDATA_FIND = 1,
    PermissionOperationDATA_REMOVE = 2,
};

// grants or denies a permission to the user to perform the operation on the object.
- (void)grantForUserWithUserId:(NSString * _Nonnull)userId entity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
- (void)denyForUserWithUserId:(NSString * _Nonnull)userId entity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// grants or denies a permission to a role to perform the operation on an object.
- (void)grantForRoleWithRole:(NSString *)role entity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
- (void)denyForRoleWithRole:(NSString *)role entity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// grants or denies a permission to all users to perform the operation on an object.
- (void)grantForAllUsersWithEntity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
- (void)denyForAllUsersWithEntity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// grants or denies a permission to all roles to perform the operation on an object.
- (void)grantForAllRolesWithEntity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
- (void)denyForAllRolesWithEntity:(id _Nonnull)entity operation:(enum PermissionOperation)operation responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
// Permission operations
@objc public enum PermissionOperation : Int, Codable { 
    case DATA_UPDATE                                   
    case DATA_FIND                                     
    case DATA_REMOVE
}

// grants or denies a permission to the user to perform the operation on the object.
func grantForUser(userId: String, entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)
func denyForUser(userId: String, entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

// grants or denies a permission to a role to perform the operation on an object.
func grantForRole(role: String, entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)
func denyForRole(role: String, entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

// grants or denies a permission to all users to perform the operation on an object.
func grantForAllUsers(entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)
func denyForAllUsers(entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

// grants or denies a permission to all roles to perform the operation on an object.
func grantForAllRoles(entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)
func denyForAllRoles(entity: Any, operation: PermissionOperation, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

Example

// Person.h
@interface Person : NSObject

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;

@end

// **************************************************

[Backendless.shared.userService loginWithIdentity:@"bob@foo.com" password:@"bob" responseHandler:^(BackendlessUser *loggedInUser) {
    [Backendless.shared.userService getUserRolesWithResponseHandler:^(NSArray *roles) {

        Person *person = [Person new];
        person.name = @"Jack";
        person.age = @20;

        DataStoreFactory *dataStore = [Backendless.shared.data of:[Person class]];
        [dataStore saveWithEntity:person responseHandler:^(Person *savedPerson) {
            // grant for role
            [Backendless.shared.data.permissions grantForRoleWithRole:roles.firstObject entity:savedPerson operation:PermissionOperationDATA_UPDATE responseHandler:^{
            savedPerson.name = @"Tom";
                [dataStore updateWithEntity:savedPerson responseHandler:^(Person *updatedPerson) {
                    // the Person object is updated
                } errorHandler:^(Fault *fault) {
                    NSLog(@"Error: %@", fault.message);
                }];
            } errorHandler:^(Fault *fault) {
                NSLog(@"Error: %@", fault.message);
            }];

            //  deny for user
            [Backendless.shared.data.permissions denyForUserWithUserId:loggedInUser.objectId entity:savedPerson operation:PermissionOperationDATA_UPDATE responseHandler:^{
                savedPerson.name = @"Tom";
                [dataStore updateWithEntity:savedPerson responseHandler:^(Person *updatedPerson) {
                    // the Person object isn't updated because the update operation is denied for current user
                } errorHandler:^(Fault *fault) {
                    NSLog(@"Error: %@", fault.message);
                }];
            } errorHandler:^(Fault *fault) {
                NSLog(@"Error: %@", fault.message);
            }];
        } errorHandler:^(Fault *fault) {
            NSLog(@"Error: %@", fault.message);
        }];

    } errorHandler:^(Fault *fault) {
        NSLog(@"Error: %@", fault.message);
    }];
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
@objcMembers class Person: NSObject {
    var objectId: String?
    var name : String?
    var age : NSNumber?
}

// **************************************************

Backendless.shared.userService.login(identity: "bob@foo.com", password: "bob", responseHandler: { loggedInUser in
    Backendless.shared.userService.getUserRoles(responseHandler: { roles in

        let person = Person()
        person.name = "Jack"
        person.age = 20

        let dataStore = Backendless.shared.data.of(Person.self)
        dataStore.save(entity: person, responseHandler: { savedPerson in
            // grant for role
            if let role = roles.first {
                Backendless.shared.data.permissions.grantForRole(role: role, entity: savedPerson, operation: .DATA_UPDATE, responseHandler: {
                    if let savedPerson = savedPerson as? Person {
                        savedPerson.name = "Tom"
                        dataStore.update(entity: savedPerson, responseHandler: { updatedPerson in
                            // the Person object is updated
                        }, errorHandler: { fault in
                            print("Error: \(fault.message ?? "")")
                        })                                        
                    }
                }, errorHandler: { fault in
                    print("Error: \(fault.message ?? "")")
                })
            }

            // deny for user
            Backendless.shared.data.permissions.denyForUser(userId: loggedInUser.objectId, entity: savedPerson, operation: .DATA_UPDATE, responseHandler: {
                if let savedPerson = savedPerson as? Person {
                    savedPerson.name = "Tom"
                    dataStore.update(entity: savedPerson, responseHandler: { updatedPerson in
                        // the Person object isn't updated because the update operation is denied for current user
                    }, errorHandler: { fault in
                        print("Error: \(fault.message ?? "")")
                    })
                }
            }, errorHandler: { fault in
                print("Error: \(fault.message ?? "")")
            })

        }, errorHandler: { fault in
            print("Error: \(fault.message ?? "")")
        })

    }, errorHandler: { fault in
        print("Error: \(fault.message ?? "")")
    })
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})