1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2017 Realm Inc.
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////
19 #ifndef REALM_OS_SYNC_PERMISSION_HPP
20 #define REALM_OS_SYNC_PERMISSION_HPP
22 #include "results.hpp"
23 #include "shared_realm.hpp"
35 // A permission encapsulates a single access level.
36 // Each level includes all the capabilities of the level
37 // above it (for example, 'write' implies 'read').
38 enum class AccessLevel {
45 // Permission object used to represent a user permission.
46 // Permission objects can be passed into or returned by various permissions
47 // APIs. They are immutable objects.
49 // The path of the Realm to which this permission pertains.
54 // Return the string description of an `AccessLevel`.
55 static std::string description_for_access_level(AccessLevel level);
57 // Return whether two paths are equivalent: either because they are exactly
58 // equal, or because user ID subtitution of one tilde-delimited path results
59 // in a path identical to the other path.
60 // Warning: this method does NOT strip or add leading or trailing slashes or whitespace.
61 // For example: "/~/foo" is equivalent to "/~/foo"; "/1/foo" is equivalent to "/1/foo".
62 // "/~/foo" is equivalent to "/1/foo" for a user ID of 1.
63 static bool paths_are_equivalent(std::string path_1, std::string path_2,
64 const std::string& user_id_1, const std::string& user_id_2);
66 // Condition is a userId or a KeyValue pair
67 // Other conditions may be supported in the future
70 // The permission is applied to a single user based on their user ID
72 // The permission is based on any user that meets a criterion specified by key/value.
77 // FIXME: turn this back into a union type
79 std::pair<std::string, std::string> key_value;
83 Condition(std::string id)
85 , user_id(std::move(id))
88 Condition(std::string key, std::string value)
89 : type(Type::KeyValue)
90 , key_value(std::make_pair(std::move(key), std::move(value)))
97 /// Create a Permission value from an `Object`.
100 /// Create a Permission value from raw values.
101 Permission(std::string path, AccessLevel, Condition, Timestamp updated_at=Timestamp());
104 struct PermissionOffer {
107 Timestamp expiration;
112 // Consumers of these APIs need to pass in a method which creates a Config with the proper
113 // SyncConfig and associated callbacks, as well as the path and other parameters.
114 using ConfigMaker = std::function<Realm::Config(std::shared_ptr<SyncUser>, std::string url)>;
116 // Callback used to asynchronously vend permissions results.
117 using PermissionResultsCallback = std::function<void(Results, std::exception_ptr)>;
119 // Callback used to asynchronously vend permission offer or response URL.
120 using PermissionOfferCallback = std::function<void(util::Optional<std::string>, std::exception_ptr)>;
122 // Asynchronously retrieve a `Results` containing the permissions for the provided user.
123 static void get_permissions(std::shared_ptr<SyncUser>, PermissionResultsCallback, const ConfigMaker&);
125 // Callback used to monitor success or errors when changing permissions
126 // or accepting a permission offer.
127 // `exception_ptr` is null_ptr on success
128 using PermissionChangeCallback = std::function<void(std::exception_ptr)>;
130 // Set a permission as the provided user.
131 static void set_permission(std::shared_ptr<SyncUser>, Permission, PermissionChangeCallback, const ConfigMaker&);
133 // Delete a permission as the provided user.
134 static void delete_permission(std::shared_ptr<SyncUser>, Permission, PermissionChangeCallback, const ConfigMaker&);
136 // Create a permission offer. The callback will be passed the token, if successful.
137 static void make_offer(std::shared_ptr<SyncUser>, PermissionOffer, PermissionOfferCallback, const ConfigMaker&);
139 // Accept a permission offer based on the token value within the offer.
140 static void accept_offer(std::shared_ptr<SyncUser>, const std::string&, PermissionOfferCallback, const ConfigMaker&);
142 using AsyncOperationHandler = std::function<void(Object*, std::exception_ptr)>;
145 static SharedRealm management_realm(std::shared_ptr<SyncUser>, const ConfigMaker&);
146 static SharedRealm permission_realm(std::shared_ptr<SyncUser>, const ConfigMaker&);
149 Perform an asynchronous operation that involves writing an object to the
150 user's management Realm, and then waiting for the operation to succeed or
153 The object in question must have at least `id`, `createdAt`, and `updatedAt`,
154 properties to be set as part of the request, and it must report its success
155 or failure by setting its `statusCode` and `statusMessage` properties.
157 The callback is invoked upon success or failure, and will be called with
158 exactly one of its two arguments not set to null. The object can be used to
159 extract additional data to be returned to the caller.
161 static void perform_async_operation(const std::string& object_type,
162 std::shared_ptr<SyncUser>,
163 AsyncOperationHandler,
164 std::map<std::string, util::Any>,
168 struct PermissionActionException : std::runtime_error {
171 PermissionActionException(std::string message, long long code)
172 : std::runtime_error(std::move(message))
179 #endif /* REALM_OS_SYNC_PERMISSION_HPP */