added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / sync / sync_permission.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2017 Realm Inc.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #ifndef REALM_OS_SYNC_PERMISSION_HPP
20 #define REALM_OS_SYNC_PERMISSION_HPP
21
22 #include "results.hpp"
23 #include "shared_realm.hpp"
24
25 namespace realm {
26
27 class Permissions;
28 class SyncUser;
29 class Object;
30
31 namespace util {
32     class Any;
33 }
34
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 {
39     None,
40     Read,
41     Write,
42     Admin,
43 };
44
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.
48 struct Permission {
49     // The path of the Realm to which this permission pertains.
50     std::string path;
51
52     AccessLevel access;
53
54     // Return the string description of an `AccessLevel`.
55     static std::string description_for_access_level(AccessLevel level);
56
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);
65
66     // Condition is a userId or a KeyValue pair
67     // Other conditions may be supported in the future
68     struct Condition {
69         enum class Type {
70             // The permission is applied to a single user based on their user ID
71             UserId,
72             // The permission is based on any user that meets a criterion specified by key/value.
73             KeyValue,
74         };
75         Type type;
76
77         // FIXME: turn this back into a union type
78         std::string user_id;
79         std::pair<std::string, std::string> key_value;
80
81         Condition() {}
82
83         Condition(std::string id)
84         : type(Type::UserId)
85         , user_id(std::move(id))
86         { }
87
88         Condition(std::string key, std::string value)
89         : type(Type::KeyValue)
90         , key_value(std::make_pair(std::move(key), std::move(value)))
91         { }
92     };
93     Condition condition;
94
95     Timestamp updated_at;
96
97     /// Create a Permission value from an `Object`.
98     Permission(Object&);
99
100     /// Create a Permission value from raw values.
101     Permission(std::string path, AccessLevel, Condition, Timestamp updated_at=Timestamp());
102 };
103
104 struct PermissionOffer {
105     std::string path;
106     AccessLevel access;
107     Timestamp expiration;
108 };
109
110 class Permissions {
111 public:
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)>;
115
116     // Callback used to asynchronously vend permissions results.
117     using PermissionResultsCallback = std::function<void(Results, std::exception_ptr)>;
118
119     // Callback used to asynchronously vend permission offer or response URL.
120     using PermissionOfferCallback = std::function<void(util::Optional<std::string>, std::exception_ptr)>;
121
122     // Asynchronously retrieve a `Results` containing the permissions for the provided user.
123     static void get_permissions(std::shared_ptr<SyncUser>, PermissionResultsCallback, const ConfigMaker&);
124
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)>;
129
130     // Set a permission as the provided user.
131     static void set_permission(std::shared_ptr<SyncUser>, Permission, PermissionChangeCallback, const ConfigMaker&);
132
133     // Delete a permission as the provided user.
134     static void delete_permission(std::shared_ptr<SyncUser>, Permission, PermissionChangeCallback, const ConfigMaker&);
135
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&);
138
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&);
141
142     using AsyncOperationHandler = std::function<void(Object*, std::exception_ptr)>;
143
144 private:
145     static SharedRealm management_realm(std::shared_ptr<SyncUser>, const ConfigMaker&);
146     static SharedRealm permission_realm(std::shared_ptr<SyncUser>, const ConfigMaker&);
147
148     /**
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
151      fail.
152
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.
156
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.
160      */
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>,
165                                         const ConfigMaker&);
166 };
167
168 struct PermissionActionException : std::runtime_error {
169     long long code;
170
171     PermissionActionException(std::string message, long long code)
172     : std::runtime_error(std::move(message))
173     , code(code)
174     { }
175 };
176
177 }
178
179 #endif /* REALM_OS_SYNC_PERMISSION_HPP */