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