package com.kryptnostic.kodex.v1.models;
import static com.kryptnostic.kodex.v1.constants.Names.ATTRIBUTES_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.CERTIFICATE_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.DOMAIN_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.EMAIL_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.FAMILY_NAME_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.GIVEN_NAME_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.GROUPS_PROPERTY;
import static com.kryptnostic.kodex.v1.constants.Names.ID_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.REALM_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.ROLES_FIELD;
import static com.kryptnostic.kodex.v1.constants.Names.USERNAME_FIELD;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kryptnostic.directory.v1.principal.User;
import com.kryptnostic.kodex.v1.constants.Names;
import com.kryptnostic.kodex.v1.crypto.ciphers.BlockCiphertext;
/**
* Model for a Heracles user.
*
* @author Nick Hewitt
* @author Matthew Tamayo-Rios <matthew@kryptnostic.com>
*
*/
@Deprecated
public final class KryptnosticUser implements User, Serializable {
private static final long serialVersionUID = 3581755283203968675L;
private final UUID id;
private final String email;
private final String domain;
private final String username;
private final byte[] certificate;
private final Set<UUID> groups = Sets.newHashSet();
private final Set<String> roles = Sets.newHashSet();
private final UserAttributes attributes = new UserAttributes( Maps.<String, Object> newConcurrentMap() );
/**
* Either the realm or domain must be specified. If both are specified the realm takes precedence until it is
* removed as a field.
*
* @param id
* @param realm
* @param domain
* @param username
* @param email
* @param certificate
* @param groups
* @param roles
* @param attributes
*/
@JsonCreator
public KryptnosticUser(
@JsonProperty( ID_FIELD ) UUID id,
@JsonProperty( REALM_FIELD ) Optional<String> realm,
@JsonProperty( DOMAIN_FIELD ) Optional<String> domain,
@JsonProperty( USERNAME_FIELD ) String username,
@JsonProperty( EMAIL_FIELD ) String email,
@JsonProperty( CERTIFICATE_FIELD ) Optional<byte[]> certificate,
@JsonProperty( GROUPS_PROPERTY ) Set<UUID> groups,
@JsonProperty( ROLES_FIELD ) Set<String> roles,
@JsonProperty( ATTRIBUTES_FIELD ) UserAttributes attributes ) {
this.id = id;
this.domain = realm.or( domain.get() );
this.username = username;
this.groups.addAll( groups );
this.attributes.putAll( ( attributes == null ) ? ImmutableMap.<String, String> of() : attributes );
this.roles.addAll( roles );
this.certificate = certificate.or( new byte[ 0 ] );
this.email = email;
}
@Override
public UUID getId() {
return id;
}
@Override
@JsonProperty( EMAIL_FIELD )
public String getEmail() {
return email;
}
@Override
@JsonProperty( GIVEN_NAME_FIELD )
public Optional<String> getGivenName() {
return Optional.of( (String) MoreObjects.firstNonNull( attributes.get( GIVEN_NAME_FIELD ), "" ) );
}
@Override
@JsonProperty( FAMILY_NAME_FIELD )
public Optional<String> getFamilyName() {
return Optional.of( (String) MoreObjects.firstNonNull( attributes.get( FAMILY_NAME_FIELD ), "" ) );
}
@Override
@JsonProperty( CERTIFICATE_FIELD )
public byte[] getCertificate() {
return certificate;
}
@Override
@JsonProperty( ATTRIBUTES_FIELD )
public UserAttributes getAttributes() {
return attributes;
}
@Override
@JsonProperty( GROUPS_PROPERTY )
public Set<UUID> getGroups() {
return groups;
}
@Override
@JsonProperty( USERNAME_FIELD )
public String getName() {
return this.username;
}
@Override
@JsonProperty( REALM_FIELD )
public String getRealm() {
return getDomain();
}
@Override
@JsonProperty( DOMAIN_FIELD )
public String getDomain() {
return this.domain;
}
@Override
public Optional<Object> getAttribute( String key ) {
return Optional.fromNullable( attributes.get( key ) );
}
@Override
public Set<String> getRoles() {
return roles;
}
@Override
public String toString() {
return "KryptnosticUser [id=" + id + ", email=" + email + ", domain=" + domain + ", username=" + username
+ ", certificate=" + Arrays.toString( certificate ) + ", groups=" + groups + ", roles=" + roles
+ ", attributes=" + attributes + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( ( attributes == null ) ? 0 : attributes.hashCode() );
result = prime * result + Arrays.hashCode( certificate );
result = prime * result + ( ( domain == null ) ? 0 : domain.hashCode() );
result = prime * result + ( ( email == null ) ? 0 : email.hashCode() );
result = prime * result + ( ( groups == null ) ? 0 : groups.hashCode() );
result = prime * result + ( ( id == null ) ? 0 : id.hashCode() );
result = prime * result + ( ( roles == null ) ? 0 : roles.hashCode() );
result = prime * result + ( ( username == null ) ? 0 : username.hashCode() );
return result;
}
@Override
public boolean equals( Object obj ) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( !( obj instanceof KryptnosticUser ) ) {
return false;
}
KryptnosticUser other = (KryptnosticUser) obj;
if ( attributes == null ) {
if ( other.attributes != null ) {
return false;
}
} else if ( !attributes.equals( other.attributes ) ) {
return false;
}
if ( !Arrays.equals( certificate, other.certificate ) ) {
return false;
}
if ( domain == null ) {
if ( other.domain != null ) {
return false;
}
} else if ( !domain.equals( other.domain ) ) {
return false;
}
if ( email == null ) {
if ( other.email != null ) {
return false;
}
} else if ( !email.equals( other.email ) ) {
return false;
}
if ( groups == null ) {
if ( other.groups != null ) {
return false;
}
} else if ( !groups.equals( other.groups ) ) {
return false;
}
if ( id == null ) {
if ( other.id != null ) {
return false;
}
} else if ( !id.equals( other.id ) ) {
return false;
}
if ( roles == null ) {
if ( other.roles != null ) {
return false;
}
} else if ( !roles.equals( other.roles ) ) {
return false;
}
if ( username == null ) {
if ( other.username != null ) {
return false;
}
} else if ( !username.equals( other.username ) ) {
return false;
}
return true;
}
public static class HeraclesUserBuilder {
public UUID id;
public String domain;
public String username;
public String email;
public String givenName;
public String familyName;
public BlockCiphertext encryptedSalt = null;
public byte[] certificate;
public Set<UUID> groups;
public Set<String> roles;
public UserAttributes attributes;
public HeraclesUserBuilder( String email ) {
this.email = email;
this.username = email;
this.givenName = "";
this.familyName = "";
this.certificate = new byte[ 0 ];
this.groups = Sets.newConcurrentHashSet();
this.attributes = new UserAttributes( Maps.<String, Object> newConcurrentMap() );
this.roles = Sets.newConcurrentHashSet();
}
@Deprecated
public HeraclesUserBuilder withRealm( String realm ) {
this.domain = realm;
return this;
}
public HeraclesUserBuilder withDomain( String domain ) {
this.domain = domain;
return this;
}
public HeraclesUserBuilder withCertificate( byte[] certificate ) {
this.certificate = certificate;
return this;
}
public HeraclesUserBuilder withEmptyCertificate() {
this.certificate = new byte[ 0 ];
return this;
}
public HeraclesUserBuilder withEmail( String email ) {
this.email = email;
return this;
}
public HeraclesUserBuilder withGivenName( String givenName ) {
this.givenName = givenName;
return this;
}
public HeraclesUserBuilder withFamilyName( String familyName ) {
this.familyName = familyName;
return this;
}
public HeraclesUserBuilder withId( UUID id ) {
this.id = id;
return this;
}
public HeraclesUserBuilder asUser() {
addRoles( SecurityRoles.USER );
return this;
}
public HeraclesUserBuilder asDeveloper() {
addRoles( SecurityRoles.DEVELOPER );
return this;
}
public HeraclesUserBuilder asAdmin() {
addRoles( SecurityRoles.ADMIN );
return this;
}
public HeraclesUserBuilder asRegistrar() {
addRoles( SecurityRoles.REGISTRAR );
return this;
}
public HeraclesUserBuilder withGroups( Set<UUID> groups ) {
Preconditions.checkNotNull( groups, "Groups cannot be null." );
this.groups.addAll( groups );
return this;
}
private void addRoles( String role ) {
this.roles.add( role );
}
public HeraclesUserBuilder withAttributes( Map<String, String> attributes ) {
this.attributes.putAll( attributes );
return this;
}
public KryptnosticUser build() {
Preconditions.checkNotNull( this.domain );
Preconditions.checkNotNull( this.username );
Preconditions.checkState( !this.roles.isEmpty(), "User must be assigned to at least one role." );
return new KryptnosticUser(
id,
Optional.of( domain ),
Optional.of( domain ),
username,
email,
Optional.of( certificate ),
groups,
roles,
attributes );
}
}
@Override
public int getUserVersion() {
return (int) MoreObjects.firstNonNull( getAttribute( Names.VERSION_FIELD ), 0 );
}
}