001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonObject;
005import com.eclipsesource.json.JsonValue;
006import java.net.URL;
007import java.util.Date;
008import java.util.HashMap;
009import java.util.Map;
010
011/**
012 * Represents a relationship between a user and a group.
013 *
014 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
015 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
016 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
017 */
018@BoxResourceType("group_membership")
019public class BoxGroupMembership extends BoxResource {
020
021    /**
022     * The URL template for all group membership requests.
023     *
024     * @see #getInfo()
025     */
026    public static final URLTemplate MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships/%s");
027
028    /**
029     * Constructs a BoxGroupMembership for a group membership with a given ID.
030     *
031     * @param api the API connection to be used by the group membership.
032     * @param id  the ID of the group membership.
033     */
034    public BoxGroupMembership(BoxAPIConnection api, String id) {
035        super(api, id);
036    }
037
038    /**
039     * Gets information about this group membership.
040     *
041     * @return info about this group membership.
042     */
043    public Info getInfo() {
044        BoxAPIConnection api = this.getAPI();
045        URL url = MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL(), this.getID());
046
047        BoxJSONRequest request = new BoxJSONRequest(api, url, "GET");
048        try (BoxJSONResponse response = request.send()) {
049            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
050            return new Info(jsonObject);
051        }
052    }
053
054    /**
055     * Updates the information about this group membership with any info fields that have been modified locally.
056     *
057     * @param info the updated info.
058     */
059    public void updateInfo(Info info) {
060        BoxAPIConnection api = this.getAPI();
061        URL url = MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL(), this.getID());
062
063        BoxJSONRequest request = new BoxJSONRequest(api, url, "PUT");
064        request.setBody(info.getPendingChanges());
065        try (BoxJSONResponse response = request.send()) {
066            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
067            info.update(jsonObject);
068        }
069    }
070
071    /**
072     * Deletes this group membership.
073     */
074    public void delete() {
075        BoxAPIConnection api = this.getAPI();
076        URL url = MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL(), this.getID());
077
078        BoxAPIRequest request = new BoxAPIRequest(api, url, "DELETE");
079        request.send().close();
080    }
081
082    /**
083     * Enumerates the possible roles that a user can have within a group.
084     */
085    public enum GroupRole {
086        /**
087         * The user is an administrator in the group.
088         */
089        ADMIN("admin"),
090
091        /**
092         * The user is a coadmin in the group.
093         */
094        COADMIN("submaster"),
095
096        /**
097         * The user is a regular member in the group.
098         */
099        MEMBER("member");
100
101        /**
102         * String representation of the groupRole.
103         */
104        private final String jsonValue;
105
106        /**
107         * Constructor.
108         *
109         * @param jsonValue string representation of the role.
110         */
111        GroupRole(String jsonValue) {
112            this.jsonValue = jsonValue;
113        }
114
115        /**
116         * Creates the groupRole from given string.
117         *
118         * @param jsonValue string to be converted to role.
119         * @return the role, created from string value.
120         */
121        static GroupRole fromJSONString(String jsonValue) {
122            for (GroupRole role : GroupRole.values()) {
123                if (role.jsonValue.equalsIgnoreCase(jsonValue)) {
124                    return role;
125                }
126            }
127            throw new IllegalArgumentException("Invalid value for enum GroupRole: " + jsonValue);
128        }
129
130        /**
131         * @return string representation of the groupRole.
132         */
133        String toJSONString() {
134            return this.jsonValue;
135        }
136    }
137
138    /**
139     * Enumerates the possible permissions that a user can have as a group admin.
140     */
141    public enum Permission {
142        /**
143         * The user can create accounts.
144         */
145        CAN_CREATE_ACCOUNTS("can_create_accounts"),
146
147        /**
148         * The user can edit accounts.
149         */
150        CAN_EDIT_ACCOUNTS("can_edit_accounts"),
151
152        /**
153         * The user can instant login as another user.
154         */
155        CAN_INSTANT_LOGIN("can_instant_login"),
156
157        /**
158         * The user can run reports.
159         */
160        CAN_RUN_REPORTS("can_run_reports");
161
162        private final String jsonValue;
163
164        Permission(String jsonValue) {
165            this.jsonValue = jsonValue;
166        }
167
168        static Permission fromJSONValue(String jsonValue) {
169            return Permission.valueOf(jsonValue.toUpperCase());
170        }
171
172        String toJSONValue() {
173            return this.jsonValue;
174        }
175    }
176
177    /**
178     * Contains information about a BoxGroupMembership.
179     */
180    public class Info extends BoxResource.Info {
181
182        /**
183         * @see #getUser()
184         */
185        private BoxUser.Info user;
186
187        /**
188         * @see #getGroup()
189         */
190        private BoxGroup.Info group;
191
192        /**
193         * @see #getGroupRole()
194         */
195        private GroupRole groupRole;
196
197        /**
198         * @see #getCreatedAt()
199         */
200        private Date createdAt;
201
202        /**
203         * @see #getModifiedAt()
204         */
205        private Date modifiedAt;
206
207        /**
208         * @see #getConfigurablePermissions()
209         */
210        private Map<Permission, Boolean> configurablePermissions;
211
212        /**
213         * Constructs an empty Info object.
214         */
215        public Info() {
216            super();
217        }
218
219        /**
220         * Constructs an Info object by parsing information from a JSON string.
221         *
222         * @param json the JSON string to parse.
223         */
224        public Info(String json) {
225            super(json);
226        }
227
228        /**
229         * Constructs an Info object using an already parsed JSON object.
230         *
231         * @param jsonObject the parsed JSON object.
232         */
233        Info(JsonObject jsonObject) {
234            super(jsonObject);
235        }
236
237        /**
238         * Gets the user belonging to the group.
239         *
240         * <p>Note: the BoxUser.Info returned by this method will only have the ID, name, and login fields
241         * populated.</p>
242         *
243         * @return the user belonging to the group.
244         */
245        public BoxUser.Info getUser() {
246            return this.user;
247        }
248
249        /**
250         * Gets the group the user belongs to.
251         *
252         * <p>Note: the BoxGroup.Info returned by this method will only have the ID and name fields populated.</p>
253         *
254         * @return the group the user belongs to.
255         */
256        public BoxGroup.Info getGroup() {
257            return this.group;
258        }
259
260        /**
261         * Gets the level of access the user has.
262         *
263         * @return the level of access the user has.
264         */
265        public GroupRole getGroupRole() {
266            return this.groupRole;
267        }
268
269        /**
270         * Sets the level of access the user has.
271         *
272         * @param role the new level of access to give the user.
273         */
274        public void setGroupRole(GroupRole role) {
275            this.groupRole = role;
276            this.addPendingChange("role", role.toJSONString());
277        }
278
279        /**
280         * Gets the time the group membership was created.
281         *
282         * @return the time the group membership was created.
283         */
284        public Date getCreatedAt() {
285            return this.createdAt;
286        }
287
288        /**
289         * Gets the time the group membership was last modified.
290         *
291         * @return the time the group membership was last modified.
292         */
293        public Date getModifiedAt() {
294            return this.modifiedAt;
295        }
296
297        /**
298         * Gets the configurablePermissions that the current user has on the group as group admin.
299         *
300         * @return the configurablePermissions that the current user has on the group as group admin.
301         */
302        public Map<Permission, Boolean> getConfigurablePermissions() {
303            return this.configurablePermissions;
304        }
305
306        /**
307         * Sets the configurablePermissions that the current user has on the group as group admin.
308         *
309         * @param configurablePermissions a Map representing the group admin configurable permissions
310         */
311        public void setConfigurablePermissions(Map<Permission, Boolean> configurablePermissions) {
312            this.configurablePermissions = configurablePermissions;
313            this.addPendingChange("configurable_permissions", this.configurablePermissionJson());
314        }
315
316        /**
317         * append new configurable permissions to the previous existing list.
318         *
319         * @param permission the group admin permission one wants to enable or disable of the user on the group.
320         * @param value      the true/false value of the attribute to set.
321         */
322        public void appendConfigurablePermissions(Permission permission, Boolean value) {
323            this.configurablePermissions.put(permission, value);
324            this.addPendingChange("configurable_permissions", this.configurablePermissionJson());
325        }
326
327        private JsonObject configurablePermissionJson() {
328            JsonObject configurablePermissionJson = new JsonObject();
329            for (Permission attrKey : this.configurablePermissions.keySet()) {
330                configurablePermissionJson.set(attrKey.toJSONValue(), this.configurablePermissions.get(attrKey));
331            }
332            return configurablePermissionJson;
333        }
334
335        /**
336         * {@inheritDoc}
337         */
338        @Override
339        public BoxGroupMembership getResource() {
340            return BoxGroupMembership.this;
341        }
342
343        private Map<Permission, Boolean> parseConfigurablePermissions(JsonObject jsonObject) {
344            if (jsonObject == null) {
345                return null;
346            }
347            Map<Permission, Boolean> permissions = new HashMap<>();
348            for (JsonObject.Member member : jsonObject) {
349                String memberName = member.getName();
350                boolean memberValue = member.getValue().asBoolean();
351                switch (memberName) {
352                    case "can_create_accounts":
353                        permissions.put(Permission.CAN_CREATE_ACCOUNTS, memberValue);
354                        break;
355                    case "can_edit_accounts":
356                        permissions.put(Permission.CAN_EDIT_ACCOUNTS, memberValue);
357                        break;
358                    case "can_instant_login":
359                        permissions.put(Permission.CAN_INSTANT_LOGIN, memberValue);
360                        break;
361                    case "can_run_reports":
362                        permissions.put(Permission.CAN_RUN_REPORTS, memberValue);
363                        break;
364                    default:
365                        break;
366                }
367            }
368            return permissions;
369        }
370
371        /**
372         * {@inheritDoc}
373         */
374        @Override
375        protected void parseJSONMember(JsonObject.Member member) {
376            super.parseJSONMember(member);
377
378            String memberName = member.getName();
379            JsonValue value = member.getValue();
380
381            try {
382                switch (memberName) {
383                    case "user":
384                        JsonObject userJSON = value.asObject();
385                        if (this.user == null) {
386                            String userID = userJSON.get("id").asString();
387                            BoxUser user = new BoxUser(getAPI(), userID);
388                            this.user = user.new Info(userJSON);
389                        } else {
390                            this.user.update(userJSON);
391                        }
392
393                        break;
394                    case "group":
395                        JsonObject groupJSON = value.asObject();
396                        if (this.group == null) {
397                            String userID = groupJSON.get("id").asString();
398                            BoxGroup group = new BoxGroup(getAPI(), userID);
399                            this.group = group.new Info(groupJSON);
400                        } else {
401                            this.group.update(groupJSON);
402                        }
403
404                        break;
405                    case "role":
406                        this.groupRole = GroupRole.fromJSONString(value.asString());
407
408                        break;
409                    case "created_at":
410                        this.createdAt = BoxDateFormat.parse(value.asString());
411
412                        break;
413                    case "modified_at":
414                        this.modifiedAt = BoxDateFormat.parse(value.asString());
415
416                        break;
417                    case "configurable_permissions":
418                        this.configurablePermissions = this.parseConfigurablePermissions(value.asObject());
419
420                        break;
421                    default:
422                        break;
423                }
424            } catch (Exception e) {
425                throw new BoxDeserializationException(memberName, value.toString(), e);
426            }
427        }
428    }
429}