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!