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 regular member in the group.
093         */
094        MEMBER("member");
095
096        /**
097         * String representation of the groupRole.
098         */
099        private final String jsonValue;
100
101        /**
102         * Constructor.
103         *
104         * @param jsonValue string representation of the role.
105         */
106        GroupRole(String jsonValue) {
107            this.jsonValue = jsonValue;
108        }
109
110        /**
111         * Creates the groupRole from given string.
112         *
113         * @param jsonValue string to be converted to role.
114         * @return the role, created from string value.
115         */
116        static GroupRole fromJSONString(String jsonValue) {
117            for (GroupRole role : GroupRole.values()) {
118                if (role.jsonValue.equalsIgnoreCase(jsonValue)) {
119                    return role;
120                }
121            }
122            throw new IllegalArgumentException("Invalid value for enum GroupRole: " + jsonValue);
123        }
124
125        /**
126         * @return string representation of the groupRole.
127         */
128        String toJSONString() {
129            return this.jsonValue;
130        }
131    }
132
133    /**
134     * Enumerates the possible permissions that a user can have as a group admin.
135     */
136    public enum Permission {
137        /**
138         * The user can create accounts.
139         */
140        CAN_CREATE_ACCOUNTS("can_create_accounts"),
141
142        /**
143         * The user can edit accounts.
144         */
145        CAN_EDIT_ACCOUNTS("can_edit_accounts"),
146
147        /**
148         * The user can instant login as another user.
149         */
150        CAN_INSTANT_LOGIN("can_instant_login"),
151
152        /**
153         * The user can run reports.
154         */
155        CAN_RUN_REPORTS("can_run_reports");
156
157        private final String jsonValue;
158
159        Permission(String jsonValue) {
160            this.jsonValue = jsonValue;
161        }
162
163        static Permission fromJSONValue(String jsonValue) {
164            return Permission.valueOf(jsonValue.toUpperCase());
165        }
166
167        String toJSONValue() {
168            return this.jsonValue;
169        }
170    }
171
172    /**
173     * Contains information about a BoxGroupMembership.
174     */
175    public class Info extends BoxResource.Info {
176
177        /**
178         * @see #getUser()
179         */
180        private BoxUser.Info user;
181
182        /**
183         * @see #getGroup()
184         */
185        private BoxGroup.Info group;
186
187        /**
188         * @see #getGroupRole()
189         */
190        private GroupRole groupRole;
191
192        /**
193         * @see #getCreatedAt()
194         */
195        private Date createdAt;
196
197        /**
198         * @see #getModifiedAt()
199         */
200        private Date modifiedAt;
201
202        /**
203         * @see #getConfigurablePermissions()
204         */
205        private Map<Permission, Boolean> configurablePermissions;
206
207        /**
208         * Constructs an empty Info object.
209         */
210        public Info() {
211            super();
212        }
213
214        /**
215         * Constructs an Info object by parsing information from a JSON string.
216         *
217         * @param json the JSON string to parse.
218         */
219        public Info(String json) {
220            super(json);
221        }
222
223        /**
224         * Constructs an Info object using an already parsed JSON object.
225         *
226         * @param jsonObject the parsed JSON object.
227         */
228        Info(JsonObject jsonObject) {
229            super(jsonObject);
230        }
231
232        /**
233         * Gets the user belonging to the group.
234         *
235         * <p>Note: the BoxUser.Info returned by this method will only have the ID, name, and login fields
236         * populated.</p>
237         *
238         * @return the user belonging to the group.
239         */
240        public BoxUser.Info getUser() {
241            return this.user;
242        }
243
244        /**
245         * Gets the group the user belongs to.
246         *
247         * <p>Note: the BoxGroup.Info returned by this method will only have the ID and name fields populated.</p>
248         *
249         * @return the group the user belongs to.
250         */
251        public BoxGroup.Info getGroup() {
252            return this.group;
253        }
254
255        /**
256         * Gets the level of access the user has.
257         *
258         * @return the level of access the user has.
259         */
260        public GroupRole getGroupRole() {
261            return this.groupRole;
262        }
263
264        /**
265         * Sets the level of access the user has.
266         *
267         * @param role the new level of access to give the user.
268         */
269        public void setGroupRole(GroupRole role) {
270            this.groupRole = role;
271            this.addPendingChange("role", role.toJSONString());
272        }
273
274        /**
275         * Gets the time the group membership was created.
276         *
277         * @return the time the group membership was created.
278         */
279        public Date getCreatedAt() {
280            return this.createdAt;
281        }
282
283        /**
284         * Gets the time the group membership was last modified.
285         *
286         * @return the time the group membership was last modified.
287         */
288        public Date getModifiedAt() {
289            return this.modifiedAt;
290        }
291
292        /**
293         * Gets the configurablePermissions that the current user has on the group as group admin.
294         *
295         * @return the configurablePermissions that the current user has on the group as group admin.
296         */
297        public Map<Permission, Boolean> getConfigurablePermissions() {
298            return this.configurablePermissions;
299        }
300
301        /**
302         * Sets the configurablePermissions that the current user has on the group as group admin.
303         *
304         * @param configurablePermissions a Map representing the group admin configurable permissions
305         */
306        public void setConfigurablePermissions(Map<Permission, Boolean> configurablePermissions) {
307            this.configurablePermissions = configurablePermissions;
308            this.addPendingChange("configurable_permissions", this.configurablePermissionJson());
309        }
310
311        /**
312         * append new configurable permissions to the previous existing list.
313         *
314         * @param permission the group admin permission one wants to enable or disable of the user on the group.
315         * @param value      the true/false value of the attribute to set.
316         */
317        public void appendConfigurablePermissions(Permission permission, Boolean value) {
318            this.configurablePermissions.put(permission, value);
319            this.addPendingChange("configurable_permissions", this.configurablePermissionJson());
320        }
321
322        private JsonObject configurablePermissionJson() {
323            JsonObject configurablePermissionJson = new JsonObject();
324            for (Permission attrKey : this.configurablePermissions.keySet()) {
325                configurablePermissionJson.set(attrKey.toJSONValue(), this.configurablePermissions.get(attrKey));
326            }
327            return configurablePermissionJson;
328        }
329
330        /**
331         * {@inheritDoc}
332         */
333        @Override
334        public BoxGroupMembership getResource() {
335            return BoxGroupMembership.this;
336        }
337
338        private Map<Permission, Boolean> parseConfigurablePermissions(JsonObject jsonObject) {
339            if (jsonObject == null) {
340                return null;
341            }
342            Map<Permission, Boolean> permissions = new HashMap<>();
343            for (JsonObject.Member member : jsonObject) {
344                String memberName = member.getName();
345                boolean memberValue = member.getValue().asBoolean();
346                switch (memberName) {
347                    case "can_create_accounts":
348                        permissions.put(Permission.CAN_CREATE_ACCOUNTS, memberValue);
349                        break;
350                    case "can_edit_accounts":
351                        permissions.put(Permission.CAN_EDIT_ACCOUNTS, memberValue);
352                        break;
353                    case "can_instant_login":
354                        permissions.put(Permission.CAN_INSTANT_LOGIN, memberValue);
355                        break;
356                    case "can_run_reports":
357                        permissions.put(Permission.CAN_RUN_REPORTS, memberValue);
358                        break;
359                    default:
360                        break;
361                }
362            }
363            return permissions;
364        }
365
366        /**
367         * {@inheritDoc}
368         */
369        @Override
370        protected void parseJSONMember(JsonObject.Member member) {
371            super.parseJSONMember(member);
372
373            String memberName = member.getName();
374            JsonValue value = member.getValue();
375
376            try {
377                switch (memberName) {
378                    case "user":
379                        JsonObject userJSON = value.asObject();
380                        if (this.user == null) {
381                            String userID = userJSON.get("id").asString();
382                            BoxUser user = new BoxUser(getAPI(), userID);
383                            this.user = user.new Info(userJSON);
384                        } else {
385                            this.user.update(userJSON);
386                        }
387
388                        break;
389                    case "group":
390                        JsonObject groupJSON = value.asObject();
391                        if (this.group == null) {
392                            String userID = groupJSON.get("id").asString();
393                            BoxGroup group = new BoxGroup(getAPI(), userID);
394                            this.group = group.new Info(groupJSON);
395                        } else {
396                            this.group.update(groupJSON);
397                        }
398
399                        break;
400                    case "role":
401                        this.groupRole = GroupRole.fromJSONString(value.asString());
402
403                        break;
404                    case "created_at":
405                        this.createdAt = BoxDateFormat.parse(value.asString());
406
407                        break;
408                    case "modified_at":
409                        this.modifiedAt = BoxDateFormat.parse(value.asString());
410
411                        break;
412                    case "configurable_permissions":
413                        this.configurablePermissions = this.parseConfigurablePermissions(value.asObject());
414
415                        break;
416                    default:
417                        break;
418                }
419            } catch (Exception e) {
420                throw new BoxDeserializationException(memberName, value.toString(), e);
421            }
422        }
423    }
424}