Setting Up Permissions with Realm Object Server for shared Realms

440 views Asked by At

I am trying to set up a shared realm, which all users have access to. I also intend for users to create realms as required, which represent projects. I would like to give the user permissions to read and write any project realms that they have created, however have read access to all of the other users' realms. I would also like the ability to assign write permissions as required, to other users, without giving them admin status in the Realm Object Server.

I am thinking that my application will allow a user to login with minimal permissions, and having a second admin user working in the background, for managing permissions. The admin user would not be exposed to the user.

I have been following an example provided at https://github.com/realm-demos/realm-teamwork-MR, however haven't had any success with setting up permissions. My test case is as follows:

import UIKit
import RealmSwift
import Realm

let ApplicationName = "SyncTest"
let syncHost = "127.0.0.1" //  The realm-oject-server is hosted on AWS, however changed for this example to keep user data private. HTTPS has also been implemented.
let syncAuthURL = URL(string: "https://\(syncHost):9443")!
let commonRealmURL:URL = URL(string: "realms://\(syncHost):9443/\(ApplicationName)-CommonRealm")!

class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        updateUserPermissions()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    private func updateUserPermissions() {

        // Create the callback block that will perform the request
        let logInBlock: ((SyncCredentials) -> Void) = { credentials in
            SyncUser.logIn(with: credentials, server: syncAuthURL, timeout: 30, onCompletion: { (user, error) in
                DispatchQueue.main.async {
                    // Display an error message if the login failed
                    if let error = error {
                        self.showError(title: "Unable to Sign In", message: error.localizedDescription)
                        return
                    }
                    guard let user = user else { return }

                    print("ID: \(String(describing: user.identity)), Total Users Logged In: \(SyncUser.all.count)")

                    let config = Realm.Configuration(syncConfiguration: SyncConfiguration(user: user, realmURL: commonRealmURL), objectTypes: [Dog.self])

                    let adminRealm:Realm = try! Realm(configuration: config)

                    let permission = SyncPermissionValue(realmPath: adminRealm.configuration.syncConfiguration!.realmURL.path,
                                                         username: "[email protected]",
                                                         accessLevel: .write)
                    user.applyPermission(permission) { error in
                        if let error = error {
                            self.showError(title: "Unable to Apply Permissions", message: error.localizedDescription)
                            return
                        }
                    }

                    let myDog = Dog()
                    myDog.name = "admin" + Date().description
                    myDog.age = 1

                    try! adminRealm.write {
                        adminRealm.add(myDog)
                    }

                    let results = adminRealm.objects(Dog.self)

                    print("Number of results after admin login: \(results.count)")

                    self.logInUser()
                }
            })
        }

        let credentials = SyncCredentials.usernamePassword(username: "[email protected]", password: "admin", register: false)

        logInBlock(credentials)

    }


    private func showError(title: String, message: String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(alertController, animated: true, completion: nil)
    }

    private func logInUser() {

        // Create the callback block that will perform the request
        let logInBlock: ((SyncCredentials) -> Void) = { credentials in
            SyncUser.logIn(with: credentials, server: syncAuthURL, timeout: 30, onCompletion: { (user, error) in
                DispatchQueue.main.async {
                    // Display an error message if the login failed
                    if let error = error {
                        self.showError(title: "Unable to Sign In", message: error.localizedDescription)
                        return
                    }
                    guard let user = user else { return }

                    let config = Realm.Configuration(syncConfiguration: SyncConfiguration(user: user, realmURL: commonRealmURL), objectTypes: [Dog.self])
                    let userRealm = try! Realm(configuration: config)

                    let myDog = Dog()
                    myDog.name = "user" + Date().description
                    myDog.age = 2

                    try! userRealm.write {
                        userRealm.add(myDog)
                    }

                    let results = userRealm.objects(Dog.self)

                    print("Number of results after user login: \(results.count)")

                }
            })
        }

        let credentials = SyncCredentials.usernamePassword(username: "[email protected]", password: "user", register: false)

        logInBlock(credentials)



    }

}

Any ideas how I can successfully assign permissions with a background admin user? Or would I be better off using a different structure for my databases? Thanks!

0

There are 0 answers