001/*
002 * Copyright 2020 Global Biodiversity Information Facility (GBIF)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.gbif.api.model.common;
017
018import java.util.Date;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.Locale;
022import java.util.Map;
023import java.util.Objects;
024import java.util.Set;
025import java.util.StringJoiner;
026import java.util.stream.Collectors;
027import java.util.stream.Stream;
028
029import org.gbif.api.util.validators.email.ValidEmail;
030import org.gbif.api.vocabulary.UserRole;
031
032import com.fasterxml.jackson.annotation.JsonIgnore;
033
034import javax.validation.constraints.NotNull;
035import javax.validation.constraints.Pattern;
036import javax.validation.constraints.Size;
037
038/**
039 * An abstract GBIF user account. The main purpose of this abstraction is to let subclasses handle
040 * key and password information only if required. By doing so, it is possible to have classes
041 * working for user information without having to carry those information around.
042 */
043@SuppressWarnings("unused")
044public abstract class AbstractGbifUser {
045
046  protected String userName;
047  protected String firstName;
048  protected String lastName;
049  protected String email;
050  protected Set<UserRole> roles = new HashSet<>();
051  protected Map<String, String> settings = new HashMap<>();
052  // settings that the user will not set directly
053  protected Map<String, String> systemSettings = new HashMap<>();
054  protected Date deleted;
055
056  @NotNull
057  @ValidEmail
058  public String getEmail() {
059    return email;
060  }
061
062  public void setEmail(String email) {
063    this.email = email;
064  }
065
066  /**
067   * The unique, immutable drupal user account name. This name should be used for referring to a
068   * user. The account name is made of ASCII lower case alphanumerics, underscore, dash or dots and
069   * is in particular void of whitespace.
070   */
071  @NotNull
072  @Pattern(regexp = "^[a-z0-9_.-]+$")
073  @Size(min = 3, max = 64)
074  public String getUserName() {
075    return userName;
076  }
077
078  public void setUserName(String userName) {
079    this.userName = userName;
080  }
081
082  /** @return the first name of a person */
083  public String getFirstName() {
084    return firstName;
085  }
086
087  public void setFirstName(String firstName) {
088    this.firstName = firstName;
089  }
090
091  /** @return the last name of the user */
092  public String getLastName() {
093    return lastName;
094  }
095
096  public void setLastName(String lastName) {
097    this.lastName = lastName;
098  }
099
100  /** @return the first and last name of the user concatenated with a space */
101  @JsonIgnore
102  public String getName() {
103    return Stream.of(firstName, lastName).filter(Objects::nonNull).collect(Collectors.joining(" "));
104  }
105
106  @NotNull
107  public Set<UserRole> getRoles() {
108    return roles;
109  }
110
111  public void setRoles(Set<UserRole> roles) {
112    this.roles = roles;
113  }
114
115  public void addRole(UserRole role) {
116    roles.add(role);
117  }
118
119  /**
120   * Checks if the user has the given user role.
121   *
122   * @param role user role
123   * @return true if the user has the requested role
124   */
125  public boolean hasRole(UserRole role) {
126    return role != null && roles.contains(role);
127  }
128
129  /** Sets the settings object, setting an empty map if null is provided. */
130  public void setSettings(Map<String, String> settings) {
131    // safeguard against misuse to avoid NPE
132    this.settings = settings == null ? new HashMap<>() : settings;
133  }
134
135  /** Gets the settings which may be empty but never null. */
136  @NotNull
137  public Map<String, String> getSettings() {
138    return settings;
139  }
140
141  /** Sets the settings object, setting an empty map if null is provided. */
142  public void setSystemSettings(Map<String, String> systemSettings) {
143    // safeguard against misuse to avoid NPE
144    this.systemSettings = systemSettings == null ? new HashMap<>() : systemSettings;
145  }
146
147  /** Gets the settings which may be empty but never null. */
148  @NotNull
149  public Map<String, String> getSystemSettings() {
150    return systemSettings;
151  }
152
153  public Date getDeleted() {
154    return deleted;
155  }
156
157  public void setDeleted(Date deleted) {
158    this.deleted = deleted;
159  }
160
161  @JsonIgnore
162  public Locale getLocale() {
163    String languageTag = settings.get("locale");
164    return languageTag != null ? Locale.forLanguageTag(languageTag) : null;
165  }
166
167  @Override
168  public boolean equals(Object o) {
169    if (this == o) {
170      return true;
171    }
172    if (o == null || getClass() != o.getClass()) {
173      return false;
174    }
175    AbstractGbifUser that = (AbstractGbifUser) o;
176    return Objects.equals(userName, that.userName)
177        && Objects.equals(firstName, that.firstName)
178        && Objects.equals(lastName, that.lastName)
179        && Objects.equals(email, that.email)
180        && Objects.equals(roles, that.roles)
181        && Objects.equals(settings, that.settings)
182        && Objects.equals(systemSettings, that.systemSettings)
183        && Objects.equals(deleted, that.deleted);
184  }
185
186  @Override
187  public int hashCode() {
188    return Objects.hash(
189        userName, firstName, lastName, email, roles, settings, systemSettings, deleted);
190  }
191
192  @Override
193  public String toString() {
194    return new StringJoiner(", ", AbstractGbifUser.class.getSimpleName() + "[", "]")
195        .add("userName='" + userName + "'")
196        .add("firstName='" + firstName + "'")
197        .add("lastName='" + lastName + "'")
198        .add("email='" + email + "'")
199        .add("roles=" + roles)
200        .add("settings=" + settings)
201        .add("systemSettings=" + systemSettings)
202        .add("deleted=" + deleted)
203        .toString();
204  }
205}