Refactor masterpassword-model
This commit is contained in:
parent
8d7c351912
commit
bda1ac3bd4
@ -5,10 +5,10 @@ plugins {
|
||||
description = 'Master Password Algorithm Implementation'
|
||||
|
||||
dependencies {
|
||||
compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.6-p11' ) {
|
||||
compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: 'GIT-SNAPSHOT' ) {
|
||||
exclude( module: 'joda-time' )
|
||||
}
|
||||
compile group: 'com.lyndir.lhunath.opal', name: 'opal-crypto', version: '1.6-p11'
|
||||
compile group: 'com.lyndir.lhunath.opal', name: 'opal-crypto', version: 'GIT-SNAPSHOT'
|
||||
|
||||
compile group: 'com.lambdaworks', name: 'scrypt', version: '1.4.0'
|
||||
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
|
||||
|
@ -59,7 +59,7 @@ public abstract class MPAlgorithm {
|
||||
/**
|
||||
* mpw: defaults: password result type.
|
||||
*/
|
||||
public abstract MPResultType mpw_default_password_type();
|
||||
public abstract MPResultType mpw_default_result_type();
|
||||
|
||||
/**
|
||||
* mpw: defaults: login result type.
|
||||
|
@ -247,7 +247,7 @@ public class MPAlgorithmV0 extends MPAlgorithm {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType mpw_default_password_type() {
|
||||
public MPResultType mpw_default_result_type() {
|
||||
return MPResultType.GeneratedLong;
|
||||
}
|
||||
|
||||
|
@ -1,212 +0,0 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.util.*;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Instant;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-05
|
||||
*/
|
||||
public class MPFileSite extends MPSite {
|
||||
|
||||
private final MPFileUser user;
|
||||
|
||||
private String siteName;
|
||||
private UnsignedInteger siteCounter;
|
||||
@Nullable
|
||||
private String siteState;
|
||||
private MPResultType resultType;
|
||||
private MPAlgorithm algorithm;
|
||||
|
||||
@Nullable
|
||||
private String loginState;
|
||||
private MPResultType loginType;
|
||||
|
||||
@Nullable
|
||||
private String url;
|
||||
private int uses;
|
||||
private ReadableInstant lastUsed;
|
||||
|
||||
private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
|
||||
|
||||
public MPFileSite(final MPFileUser user, final String siteName) {
|
||||
this( user, siteName, null, null, user.getAlgorithm() );
|
||||
}
|
||||
|
||||
public MPFileSite(final MPFileUser user, final String siteName, @Nullable final UnsignedInteger siteCounter,
|
||||
@Nullable final MPResultType resultType, final MPAlgorithm algorithm) {
|
||||
this( user, siteName, null, siteCounter, resultType, algorithm,
|
||||
null, null, null, 0, new Instant() );
|
||||
}
|
||||
|
||||
protected MPFileSite(final MPFileUser user, final String siteName, @Nullable final String siteState,
|
||||
@Nullable final UnsignedInteger siteCounter, @Nullable final MPResultType resultType, final MPAlgorithm algorithm,
|
||||
@Nullable final String loginState, @Nullable final MPResultType loginType,
|
||||
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
||||
this.user = user;
|
||||
this.algorithm = algorithm;
|
||||
|
||||
this.siteName = siteName;
|
||||
this.siteState = siteState;
|
||||
this.siteCounter = ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() );
|
||||
this.resultType = ifNotNullElse( resultType, getAlgorithm().mpw_default_password_type() );
|
||||
this.loginState = loginState;
|
||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||
this.url = url;
|
||||
this.uses = uses;
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
|
||||
public String getResult()
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( MPKeyPurpose.Authentication, null );
|
||||
}
|
||||
|
||||
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( keyPurpose, keyContext, siteState );
|
||||
}
|
||||
|
||||
public String getLogin()
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getLogin( loginState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPUser<?> getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSiteName(final String siteName) {
|
||||
this.siteName = siteName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSiteState() {
|
||||
return siteState;
|
||||
}
|
||||
|
||||
public void setSitePassword(final MPResultType resultType, @Nullable final String password)
|
||||
throws MPKeyUnavailableException {
|
||||
this.resultType = resultType;
|
||||
|
||||
if (password == null)
|
||||
this.siteState = null;
|
||||
else
|
||||
this.siteState = getState(
|
||||
MPKeyPurpose.Authentication, null, siteCounter, resultType, password );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnsignedInteger getSiteCounter() {
|
||||
return siteCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSiteCounter(final UnsignedInteger siteCounter) {
|
||||
this.siteCounter = siteCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultType(final MPResultType resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getLoginType() {
|
||||
return loginType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoginType(@Nullable final MPResultType loginType) {
|
||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends MPQuestion> getQuestions() {
|
||||
return Collections.unmodifiableCollection( questions );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getLoginState() {
|
||||
return loginState;
|
||||
}
|
||||
|
||||
public void setLoginName(@Nonnull final MPResultType loginType, @Nonnull final String loginName)
|
||||
throws MPKeyUnavailableException {
|
||||
this.loginType = loginType;
|
||||
this.loginState = getState( MPKeyPurpose.Identification, null, null, this.loginType, loginName );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(@Nullable final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public int getUses() {
|
||||
return uses;
|
||||
}
|
||||
|
||||
public ReadableInstant getLastUsed() {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
public void use() {
|
||||
uses++;
|
||||
lastUsed = new Instant();
|
||||
user.use();
|
||||
}
|
||||
}
|
@ -18,20 +18,21 @@
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-17
|
||||
*/
|
||||
public class MPIncorrectMasterPasswordException extends Exception {
|
||||
|
||||
private final MPFileUser user;
|
||||
private final MPUser<?> user;
|
||||
|
||||
public MPIncorrectMasterPasswordException(final MPFileUser user) {
|
||||
public MPIncorrectMasterPasswordException(final MPUser<?> user) {
|
||||
super( "Incorrect master password for user: " + user.getFullName() );
|
||||
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public MPFileUser getUser() {
|
||||
public MPUser<?> getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
@ -18,24 +18,35 @@
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
|
||||
import com.lyndir.masterpassword.MPResultType;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2018-05-14
|
||||
* @author lhunath, 2018-05-15
|
||||
*/
|
||||
public abstract class MPQuestion {
|
||||
public interface MPQuestion extends Comparable<MPQuestion> {
|
||||
|
||||
public abstract MPSite getSite();
|
||||
// -- Meta
|
||||
|
||||
public abstract String getKeyword();
|
||||
@Nonnull
|
||||
String getKeyword();
|
||||
|
||||
public abstract MPResultType getType();
|
||||
// -- Algorithm
|
||||
|
||||
public String getAnswer(@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
@Nonnull
|
||||
MPResultType getType();
|
||||
|
||||
return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
|
||||
}
|
||||
void setType(MPResultType type);
|
||||
|
||||
@Nonnull
|
||||
String getAnswer(@Nullable String state)
|
||||
throws MPKeyUnavailableException;
|
||||
|
||||
// -- Relationship
|
||||
|
||||
@Nonnull
|
||||
MPSite getSite();
|
||||
}
|
||||
|
@ -18,90 +18,50 @@
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-16
|
||||
* @author lhunath, 2018-05-14
|
||||
*/
|
||||
public abstract class MPSite {
|
||||
public interface MPSite extends Comparable<MPSite> {
|
||||
|
||||
public abstract MPUser<?> getUser();
|
||||
// - Meta
|
||||
|
||||
public abstract String getSiteName();
|
||||
String getName();
|
||||
|
||||
public abstract void setSiteName(String siteName);
|
||||
void setName(String name);
|
||||
|
||||
public abstract UnsignedInteger getSiteCounter();
|
||||
// - Algorithm
|
||||
|
||||
public abstract void setSiteCounter(UnsignedInteger siteCounter);
|
||||
MPAlgorithm getAlgorithm();
|
||||
|
||||
public abstract MPResultType getResultType();
|
||||
void setAlgorithm(MPAlgorithm algorithm);
|
||||
|
||||
public abstract void setResultType(MPResultType resultType);
|
||||
UnsignedInteger getCounter();
|
||||
|
||||
public abstract MPResultType getLoginType();
|
||||
void setCounter(UnsignedInteger counter);
|
||||
|
||||
public abstract void setLoginType(@Nullable MPResultType loginType);
|
||||
MPResultType getResultType();
|
||||
|
||||
public abstract MPAlgorithm getAlgorithm();
|
||||
void setResultType(MPResultType resultType);
|
||||
|
||||
public abstract void setAlgorithm(MPAlgorithm algorithm);
|
||||
MPResultType getLoginType();
|
||||
|
||||
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||
@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
void setLoginType(@Nullable MPResultType loginType);
|
||||
|
||||
return getResult( keyPurpose, keyContext, getSiteCounter(), getResultType(), state );
|
||||
}
|
||||
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext, @Nullable String state)
|
||||
throws MPKeyUnavailableException;
|
||||
|
||||
protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||
@Nullable final UnsignedInteger siteCounter, final MPResultType type,
|
||||
@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
String getLogin(@Nullable String state)
|
||||
throws MPKeyUnavailableException;
|
||||
|
||||
return getUser().getMasterKey().siteResult(
|
||||
getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||
type, state, getAlgorithm() );
|
||||
}
|
||||
// - Relations
|
||||
|
||||
protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||
@Nullable final UnsignedInteger siteCounter, final MPResultType type,
|
||||
@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
MPUser<? extends MPSite> getUser();
|
||||
|
||||
return getUser().getMasterKey().siteState(
|
||||
getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||
type, state, getAlgorithm() );
|
||||
}
|
||||
|
||||
public String getLogin(@Nullable final String loginContent)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( MPKeyPurpose.Identification, null,null, getLoginType(), loginContent );
|
||||
}
|
||||
|
||||
public abstract Collection<? extends MPQuestion> getQuestions();
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getSiteName(), ((MPSite) obj).getSiteName() ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getSiteName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getSiteName() );
|
||||
}
|
||||
Collection<? extends MPQuestion> getQuestions();
|
||||
}
|
||||
|
@ -21,35 +21,41 @@ package com.lyndir.masterpassword.model;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-07
|
||||
*/
|
||||
public class MPSiteResult {
|
||||
public class MPSiteResult implements Comparable<MPSiteResult> {
|
||||
|
||||
private final MPFileSite site;
|
||||
private final MPSite site;
|
||||
|
||||
public MPSiteResult(final MPFileSite site) {
|
||||
public MPSiteResult(final MPSite site) {
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
public MPFileSite getSite() {
|
||||
public MPSite getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( site, ((MPSiteResult) obj).site ));
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getSite() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( site );
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( getSite(), ((MPSiteResult) obj).getSite() ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull final MPSiteResult o) {
|
||||
return getSite().compareTo( o.getSite() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{MPSiteResult: %s}", site );
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getSite() );
|
||||
}
|
||||
}
|
||||
|
110
core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java
Executable file → Normal file
110
core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java
Executable file → Normal file
@ -18,72 +18,78 @@
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-06-08
|
||||
* @author lhunath, 2018-05-14
|
||||
*/
|
||||
public abstract class MPUser<S extends MPSite> {
|
||||
public interface MPUser<S extends MPSite> extends Comparable<MPUser<?>> {
|
||||
|
||||
// - Meta
|
||||
|
||||
int getAvatar();
|
||||
|
||||
void setAvatar(int avatar);
|
||||
|
||||
@Nonnull
|
||||
String getFullName();
|
||||
|
||||
// - Algorithm
|
||||
|
||||
@Nonnull
|
||||
MPAlgorithm getAlgorithm();
|
||||
|
||||
void setAlgorithm(MPAlgorithm algorithm);
|
||||
|
||||
@Nullable
|
||||
protected MPMasterKey key;
|
||||
byte[] getKeyID();
|
||||
|
||||
public abstract String getFullName();
|
||||
@Nullable
|
||||
String exportKeyID();
|
||||
|
||||
public boolean isMasterKeyAvailable() {
|
||||
return key != null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public MPMasterKey getMasterKey()
|
||||
throws MPKeyUnavailableException {
|
||||
if (key == null)
|
||||
throw new MPKeyUnavailableException();
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public String exportKeyID()
|
||||
throws MPKeyUnavailableException {
|
||||
return CodeUtils.encodeHex( getMasterKey().getKeyID( getAlgorithm() ) );
|
||||
}
|
||||
|
||||
public abstract MPAlgorithm getAlgorithm();
|
||||
|
||||
public int getAvatar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public abstract void addSite(S site);
|
||||
|
||||
public abstract void deleteSite(S site);
|
||||
|
||||
public abstract Collection<S> findSites(String query);
|
||||
|
||||
@Nonnull
|
||||
public abstract MPMasterKey authenticate(char[] masterPassword)
|
||||
/**
|
||||
* Performs an authentication attempt against the keyID for this user.
|
||||
*
|
||||
* Note: If a keyID is not set, authentication will always succeed and the keyID will be set to match the given master password.
|
||||
*
|
||||
* @param masterPassword The password to authenticate with.
|
||||
*
|
||||
* @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
|
||||
*/
|
||||
void authenticate(char[] masterPassword)
|
||||
throws MPIncorrectMasterPasswordException;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getFullName() );
|
||||
}
|
||||
/**
|
||||
* Performs an authentication attempt against the keyID for this user.
|
||||
*
|
||||
* Note: If a keyID is not set, authentication will always succeed and the keyID will be set to match the given key.
|
||||
*
|
||||
* @param masterKey The master key to authenticate with.
|
||||
*
|
||||
* @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
|
||||
*/
|
||||
void authenticate(MPMasterKey masterKey)
|
||||
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException;
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPUser) && Objects.equals( getFullName(), ((MPUser<?>) obj).getFullName() ));
|
||||
}
|
||||
boolean isMasterKeyAvailable();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getFullName() );
|
||||
}
|
||||
@Nonnull
|
||||
MPMasterKey getMasterKey()
|
||||
throws MPKeyUnavailableException;
|
||||
|
||||
// - Relations
|
||||
|
||||
void addSite(S site);
|
||||
|
||||
void deleteSite(S site);
|
||||
|
||||
@Nonnull
|
||||
Collection<S> getSites();
|
||||
|
||||
@Nonnull
|
||||
Collection<S> findSites(String query);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import com.lyndir.masterpassword.model.impl.MPFileUser;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
@ -26,28 +27,28 @@ import java.util.SortedSet;
|
||||
/**
|
||||
* @author lhunath, 14-12-05
|
||||
*/
|
||||
public abstract class MPUserManager {
|
||||
public abstract class MPUserManager<U extends MPUser<?>> {
|
||||
|
||||
private final Map<String, MPFileUser> usersByName = Maps.newHashMap();
|
||||
private final Map<String, U> usersByName = Maps.newHashMap();
|
||||
|
||||
protected MPUserManager(final Iterable<MPFileUser> users) {
|
||||
for (final MPFileUser user : users)
|
||||
protected MPUserManager(final Iterable<U> users) {
|
||||
for (final U user : users)
|
||||
usersByName.put( user.getFullName(), user );
|
||||
}
|
||||
|
||||
public SortedSet<MPFileUser> getUsers() {
|
||||
public SortedSet<U> getUsers() {
|
||||
return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
|
||||
}
|
||||
|
||||
public MPFileUser getUserNamed(final String fullName) {
|
||||
public U getUserNamed(final String fullName) {
|
||||
return usersByName.get( fullName );
|
||||
}
|
||||
|
||||
public void addUser(final MPFileUser user) {
|
||||
public void addUser(final U user) {
|
||||
usersByName.put( user.getFullName(), user );
|
||||
}
|
||||
|
||||
public void deleteUser(final MPFileUser user) {
|
||||
public void deleteUser(final U user) {
|
||||
usersByName.remove( user.getFullName() );
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.MPQuestion;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2018-05-14
|
||||
*/
|
||||
public abstract class MPBasicQuestion implements MPQuestion {
|
||||
|
||||
private final String keyword;
|
||||
private MPResultType type;
|
||||
|
||||
protected MPBasicQuestion(final String keyword, final MPResultType type) {
|
||||
this.keyword = keyword;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPResultType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(final MPResultType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getAnswer(@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public abstract MPBasicSite getSite();
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getKeyword() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPQuestion) && Objects.equals( getKeyword(), ((MPQuestion) obj).getKeyword() ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull final MPQuestion o) {
|
||||
return getKeyword().compareTo( o.getKeyword() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getKeyword() );
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.MPQuestion;
|
||||
import com.lyndir.masterpassword.model.MPSite;
|
||||
import java.util.*;
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-16
|
||||
*/
|
||||
public abstract class MPBasicSite implements MPSite {
|
||||
|
||||
private String name;
|
||||
private MPAlgorithm algorithm;
|
||||
private UnsignedInteger counter;
|
||||
private MPResultType resultType;
|
||||
private MPResultType loginType;
|
||||
|
||||
private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
|
||||
|
||||
protected MPBasicSite(final String name, final MPAlgorithm algorithm) {
|
||||
this( name, algorithm, null, null, null );
|
||||
}
|
||||
|
||||
protected MPBasicSite(final String name, final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
|
||||
@Nullable final MPResultType resultType, @Nullable final MPResultType loginType) {
|
||||
this.name = name;
|
||||
this.algorithm = algorithm;
|
||||
this.counter = (counter == null)? algorithm.mpw_default_counter(): counter;
|
||||
this.resultType = (resultType == null)? algorithm.mpw_default_result_type(): resultType;
|
||||
this.loginType = (loginType == null)? algorithm.mpw_default_login_type(): loginType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnsignedInteger getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCounter(final UnsignedInteger counter) {
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultType(final MPResultType resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getLoginType() {
|
||||
return loginType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoginType(@Nullable final MPResultType loginType) {
|
||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext, @Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( keyPurpose, keyContext, getCounter(), getResultType(), state );
|
||||
}
|
||||
|
||||
protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||
@Nullable final UnsignedInteger counter, final MPResultType type, @Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getUser().getMasterKey().siteResult(
|
||||
getName(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||
type, state, getAlgorithm() );
|
||||
}
|
||||
|
||||
protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||
@Nullable final UnsignedInteger counter, final MPResultType type, @Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getUser().getMasterKey().siteState(
|
||||
getName(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||
type, state, getAlgorithm() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogin(@Nullable final String state)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( MPKeyPurpose.Identification, null, null, getLoginType(), state );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends MPQuestion> getQuestions() {
|
||||
return Collections.unmodifiableCollection( questions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getName(), ((MPSite) obj).getName() ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull final MPSite o) {
|
||||
return getName().compareTo( o.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getName() );
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import java.util.*;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-06-08
|
||||
*/
|
||||
public abstract class MPBasicUser<S extends MPBasicSite> implements MPUser<S> {
|
||||
|
||||
private int avatar;
|
||||
private final String fullName;
|
||||
private MPAlgorithm algorithm;
|
||||
@Nullable
|
||||
protected MPMasterKey masterKey;
|
||||
|
||||
private final Collection<S> sites = new LinkedHashSet<>();
|
||||
|
||||
protected MPBasicUser(final String fullName, final MPAlgorithm algorithm) {
|
||||
this( 0, fullName, algorithm );
|
||||
}
|
||||
|
||||
protected MPBasicUser(final int avatar, final String fullName, final MPAlgorithm algorithm) {
|
||||
this.avatar = avatar;
|
||||
this.fullName = fullName;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAvatar(final int avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public byte[] getKeyID() {
|
||||
try {
|
||||
return getMasterKey().getKeyID( getAlgorithm() );
|
||||
}
|
||||
catch (final MPKeyUnavailableException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String exportKeyID() {
|
||||
return CodeUtils.encodeHex( getKeyID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticate(final char[] masterPassword)
|
||||
throws MPIncorrectMasterPasswordException {
|
||||
try {
|
||||
authenticate( new MPMasterKey( getFullName(), masterPassword ) );
|
||||
}
|
||||
catch (final MPKeyUnavailableException e) {
|
||||
throw new IllegalStateException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticate(final MPMasterKey masterKey)
|
||||
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
|
||||
if (!masterKey.getFullName().equals( getFullName() ))
|
||||
throw new IllegalArgumentException(
|
||||
"Master key (for " + masterKey.getFullName() + ") is not for this user (" + getFullName() + ")." );
|
||||
|
||||
byte[] keyID = getKeyID();
|
||||
if ((keyID != null) && !Arrays.equals( masterKey.getKeyID( getAlgorithm() ), keyID ))
|
||||
throw new MPIncorrectMasterPasswordException( this );
|
||||
|
||||
this.masterKey = masterKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMasterKeyAvailable() {
|
||||
return masterKey != null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPMasterKey getMasterKey()
|
||||
throws MPKeyUnavailableException {
|
||||
if (masterKey == null)
|
||||
throw new MPKeyUnavailableException();
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSite(final S site) {
|
||||
sites.add( site );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSite(final S site) {
|
||||
sites.remove( site );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<S> getSites() {
|
||||
return Collections.unmodifiableCollection( sites );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<S> findSites(final String query) {
|
||||
ImmutableList.Builder<S> results = ImmutableList.builder();
|
||||
for (final S site : getSites())
|
||||
if (site.getName().startsWith( query ))
|
||||
results.add( site );
|
||||
|
||||
return results.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( getFullName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return (this == obj) || ((obj instanceof MPUser) && Objects.equals( getFullName(), ((MPUser<?>) obj).getFullName() ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final MPUser<?> o) {
|
||||
return getFullName().compareTo( o.getFullName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{%s: %s}", getClass().getSimpleName(), getFullName() );
|
||||
}
|
||||
}
|
@ -16,69 +16,52 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||
|
||||
import com.lyndir.masterpassword.*;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2018-05-14
|
||||
*/
|
||||
public class MPFileQuestion extends MPQuestion {
|
||||
public class MPFileQuestion extends MPBasicQuestion {
|
||||
|
||||
private final MPSite site;
|
||||
private final MPFileSite site;
|
||||
|
||||
private String keyword;
|
||||
@Nullable
|
||||
private String state;
|
||||
private MPResultType type;
|
||||
|
||||
public MPFileQuestion(final MPSite site, final String keyword, @Nullable final String state, @Nullable final MPResultType type) {
|
||||
public MPFileQuestion(final MPFileSite site, final String keyword,
|
||||
@Nullable final MPResultType type, @Nullable final String state) {
|
||||
super( keyword, ifNotNullElse( type, site.getAlgorithm().mpw_default_answer_type() ) );
|
||||
|
||||
this.site = site;
|
||||
this.keyword = keyword;
|
||||
this.state = state;
|
||||
this.type = ifNotNullElse( type, site.getAlgorithm().mpw_default_answer_type() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPSite getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(final String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
public void setAnswer(final MPResultType type, @Nullable final String answer)
|
||||
throws MPKeyUnavailableException {
|
||||
this.type = type;
|
||||
|
||||
if (answer == null)
|
||||
this.state = null;
|
||||
else
|
||||
this.state = getSite().getState(
|
||||
MPKeyPurpose.Recovery, getKeyword(), null, type, answer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final MPResultType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getAnswer()
|
||||
throws MPKeyUnavailableException {
|
||||
return getAnswer( state );
|
||||
}
|
||||
|
||||
public void setAnswer(final MPResultType type, @Nullable final String answer)
|
||||
throws MPKeyUnavailableException {
|
||||
setType( type );
|
||||
|
||||
if (answer == null)
|
||||
this.state = null;
|
||||
else
|
||||
this.state = getSite().getState(
|
||||
MPKeyPurpose.Recovery, getKeyword(), null, getType(), answer );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPFileSite getSite() {
|
||||
return site;
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Instant;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-05
|
||||
*/
|
||||
public class MPFileSite extends MPBasicSite {
|
||||
|
||||
private final MPFileUser user;
|
||||
|
||||
@Nullable
|
||||
private String url;
|
||||
private int uses;
|
||||
private ReadableInstant lastUsed;
|
||||
|
||||
@Nullable
|
||||
private String resultState;
|
||||
@Nullable
|
||||
private String loginState;
|
||||
|
||||
public MPFileSite(final MPFileUser user, final String name) {
|
||||
this( user, name, null, null, null );
|
||||
}
|
||||
|
||||
public MPFileSite(final MPFileUser user, final String name,
|
||||
@Nullable final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
|
||||
@Nullable final MPResultType resultType) {
|
||||
this( user, name, algorithm, counter, resultType, null,
|
||||
null, null, null, 0, new Instant() );
|
||||
}
|
||||
|
||||
protected MPFileSite(final MPFileUser user, final String name,
|
||||
@Nullable final MPAlgorithm algorithm, @Nullable final UnsignedInteger counter,
|
||||
@Nullable final MPResultType resultType, @Nullable final String resultState,
|
||||
@Nullable final MPResultType loginType, @Nullable final String loginState,
|
||||
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
||||
super( name, (algorithm == null)? user.getAlgorithm(): algorithm, counter, resultType, loginType );
|
||||
|
||||
this.user = user;
|
||||
this.resultState = resultState;
|
||||
this.loginState = loginState;
|
||||
this.url = url;
|
||||
this.uses = uses;
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(@Nullable final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public int getUses() {
|
||||
return uses;
|
||||
}
|
||||
|
||||
public ReadableInstant getLastUsed() {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
public void use() {
|
||||
uses++;
|
||||
lastUsed = new Instant();
|
||||
user.use();
|
||||
}
|
||||
|
||||
public String getResult()
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( MPKeyPurpose.Authentication, null );
|
||||
}
|
||||
|
||||
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext)
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getResult( keyPurpose, keyContext, getResultState() );
|
||||
}
|
||||
|
||||
public String getLogin()
|
||||
throws MPKeyUnavailableException {
|
||||
|
||||
return getLogin( getLoginState() );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getResultState() {
|
||||
return resultState;
|
||||
}
|
||||
|
||||
public void setSitePassword(final MPResultType resultType, @Nullable final String password)
|
||||
throws MPKeyUnavailableException {
|
||||
setResultType( resultType );
|
||||
|
||||
if (password == null)
|
||||
this.resultState = null;
|
||||
else
|
||||
this.resultState = getState(
|
||||
MPKeyPurpose.Authentication, null, getCounter(), getResultType(), password );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getLoginState() {
|
||||
return loginState;
|
||||
}
|
||||
|
||||
public void setLoginName(@Nonnull final MPResultType loginType, @Nullable final String loginName)
|
||||
throws MPKeyUnavailableException {
|
||||
setLoginType( loginType );
|
||||
|
||||
if (loginName == null)
|
||||
this.loginState = null;
|
||||
else
|
||||
this.loginState = getState(
|
||||
MPKeyPurpose.Identification, null, null, getLoginType(), loginName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPUser<? extends com.lyndir.masterpassword.model.MPSite> getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
@ -16,13 +16,12 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.util.*;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Instant;
|
||||
@ -33,21 +32,16 @@ import org.joda.time.ReadableInstant;
|
||||
* @author lhunath, 14-12-07
|
||||
*/
|
||||
@SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
|
||||
public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileUser> {
|
||||
public class MPFileUser extends MPBasicUser<MPFileSite> {
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private static final Logger logger = Logger.get( MPFileUser.class );
|
||||
|
||||
private final String fullName;
|
||||
private final Collection<MPFileSite> sites = new LinkedHashSet<>();
|
||||
|
||||
@Nullable
|
||||
private byte[] keyID;
|
||||
private MPAlgorithm algorithm;
|
||||
private MPMarshalFormat format;
|
||||
private MPMarshaller.ContentMode contentMode;
|
||||
|
||||
private int avatar;
|
||||
private MPResultType defaultType;
|
||||
private ReadableInstant lastUsed;
|
||||
|
||||
@ -59,40 +53,43 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
||||
}
|
||||
|
||||
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm) {
|
||||
this( fullName, keyID, algorithm, 0, algorithm.mpw_default_password_type(), new Instant(),
|
||||
this( fullName, keyID, algorithm, 0, algorithm.mpw_default_result_type(), new Instant(),
|
||||
MPMarshalFormat.DEFAULT, MPMarshaller.ContentMode.PROTECTED );
|
||||
}
|
||||
|
||||
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm, final int avatar,
|
||||
final MPResultType defaultType, final ReadableInstant lastUsed,
|
||||
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm,
|
||||
final int avatar, final MPResultType defaultType, final ReadableInstant lastUsed,
|
||||
final MPMarshalFormat format, final MPMarshaller.ContentMode contentMode) {
|
||||
this.fullName = fullName;
|
||||
super( avatar, fullName, algorithm );
|
||||
|
||||
this.keyID = (keyID == null)? null: keyID.clone();
|
||||
this.algorithm = algorithm;
|
||||
this.avatar = avatar;
|
||||
this.defaultType = defaultType;
|
||||
this.lastUsed = lastUsed;
|
||||
this.format = format;
|
||||
this.contentMode = contentMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public byte[] getKeyID() {
|
||||
return (keyID == null)? null: keyID.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
if (!algorithm.equals( getAlgorithm() ) && (keyID != null)) {
|
||||
if (masterKey == null)
|
||||
throw new IllegalStateException( "Cannot update algorithm when keyID is set but masterKey is unavailable." );
|
||||
|
||||
try {
|
||||
keyID = masterKey.getKeyID( algorithm );
|
||||
}
|
||||
catch (final MPKeyUnavailableException e) {
|
||||
throw new IllegalStateException( "Cannot update algorithm when keyID is set but masterKey is unavailable.", e );
|
||||
}
|
||||
}
|
||||
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
super.setAlgorithm( algorithm );
|
||||
}
|
||||
|
||||
public MPMarshalFormat getFormat() {
|
||||
@ -111,15 +108,6 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
||||
this.contentMode = contentMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public void setAvatar(final int avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public MPResultType getDefaultType() {
|
||||
return defaultType;
|
||||
}
|
||||
@ -136,30 +124,6 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
||||
lastUsed = new Instant();
|
||||
}
|
||||
|
||||
public Collection<MPFileSite> getSites() {
|
||||
return Collections.unmodifiableCollection( sites );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSite(final MPFileSite site) {
|
||||
sites.add( site );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSite(final MPFileSite site) {
|
||||
sites.remove( site );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MPFileSite> findSites(final String query) {
|
||||
ImmutableList.Builder<MPFileSite> results = ImmutableList.builder();
|
||||
for (final MPFileSite site : getSites())
|
||||
if (site.getSiteName().startsWith( query ))
|
||||
results.add( site );
|
||||
|
||||
return results.build();
|
||||
}
|
||||
|
||||
public void setJSON(final MPJSONFile json) {
|
||||
this.json = json;
|
||||
}
|
||||
@ -169,33 +133,13 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
||||
return (json == null)? json = new MPJSONFile(): json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an authentication attempt against the keyID for this user.
|
||||
*
|
||||
* Note: If this user doesn't have a keyID set yet, authentication will always succeed and the key ID will be set as a result.
|
||||
*
|
||||
* @param masterPassword The password to authenticate with.
|
||||
*
|
||||
* @return The master key for the user if authentication was successful.
|
||||
*
|
||||
* @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPMasterKey authenticate(final char[] masterPassword)
|
||||
throws MPIncorrectMasterPasswordException {
|
||||
try {
|
||||
key = new MPMasterKey( getFullName(), masterPassword );
|
||||
if ((keyID == null) || (keyID.length == 0))
|
||||
keyID = key.getKeyID( algorithm );
|
||||
else if (!Arrays.equals( key.getKeyID( algorithm ), keyID ))
|
||||
throw new MPIncorrectMasterPasswordException( this );
|
||||
public void authenticate(final MPMasterKey masterKey)
|
||||
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
|
||||
super.authenticate( masterKey );
|
||||
|
||||
return key;
|
||||
}
|
||||
catch (final MPKeyUnavailableException e) {
|
||||
throw logger.bug( e );
|
||||
}
|
||||
if (keyID == null)
|
||||
keyID = masterKey.getKeyID( getAlgorithm() );
|
||||
}
|
||||
|
||||
void save()
|
||||
@ -204,11 +148,11 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final MPFileUser o) {
|
||||
int comparison = getLastUsed().compareTo( o.getLastUsed() );
|
||||
if (comparison == 0)
|
||||
comparison = getFullName().compareTo( o.getFullName() );
|
||||
|
||||
public int compareTo(final MPUser<?> o) {
|
||||
int comparison = (o instanceof MPFileUser)? getLastUsed().compareTo( ((MPFileUser) o).getLastUsed() ): 0;
|
||||
if (comparison != 0)
|
||||
return comparison;
|
||||
|
||||
return super.compareTo( o );
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.CharSink;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -37,7 +38,7 @@ import javax.annotation.Nonnull;
|
||||
* @author lhunath, 14-12-07
|
||||
*/
|
||||
@SuppressWarnings("CallToSystemGetenv")
|
||||
public class MPFileUserManager extends MPUserManager {
|
||||
public class MPFileUserManager extends MPUserManager<MPFileUser> {
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private static final Logger logger = Logger.get( MPFileUserManager.class );
|
||||
@ -137,7 +138,7 @@ public class MPFileUserManager extends MPUserManager {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private File getUserFile(final MPFileUser user, final MPMarshalFormat format) {
|
||||
private File getUserFile(final MPUser<?> user, final MPMarshalFormat format) {
|
||||
return new File( path, user.getFullName() + format.fileSuffix() );
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
@ -59,7 +59,7 @@ public class MPFlatMarshaller implements MPMarshaller {
|
||||
|
||||
for (final MPFileSite site : user.getSites()) {
|
||||
String loginName = site.getLoginState();
|
||||
String password = site.getSiteState();
|
||||
String password = site.getResultState();
|
||||
if (!user.getContentMode().isRedacted()) {
|
||||
loginName = site.getLogin();
|
||||
password = site.getResult();
|
||||
@ -71,9 +71,9 @@ public class MPFlatMarshaller implements MPMarshaller {
|
||||
strf( "%d:%d:%d", //
|
||||
site.getResultType().getType(), // type
|
||||
site.getAlgorithm().version().toInt(), // algorithm
|
||||
site.getSiteCounter().intValue() ), // counter
|
||||
site.getCounter().intValue() ), // counter
|
||||
ifNotNullElse( loginName, "" ), // loginName
|
||||
site.getSiteName(), // siteName
|
||||
site.getName(), // siteName
|
||||
ifNotNullElse( password, "" ) // password
|
||||
) );
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.google.common.base.*;
|
||||
import com.google.common.io.CharStreams;
|
||||
@ -25,6 +25,7 @@ import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import java.io.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -115,11 +116,11 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
|
||||
switch (importFormat) {
|
||||
case 0:
|
||||
site = new MPFileSite( user, //
|
||||
siteMatcher.group( 5 ), clearContent? null: siteMatcher.group( 6 ),
|
||||
siteMatcher.group( 5 ), MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
|
||||
colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
|
||||
user.getAlgorithm().mpw_default_counter(),
|
||||
MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
|
||||
MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
|
||||
colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
|
||||
clearContent? null: siteMatcher.group( 6 ),
|
||||
null, null, null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
|
||||
MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
|
||||
if (clearContent)
|
||||
@ -128,12 +129,12 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
|
||||
|
||||
case 1:
|
||||
site = new MPFileSite( user, //
|
||||
siteMatcher.group( 7 ), clearContent? null: siteMatcher.group( 8 ),
|
||||
siteMatcher.group( 7 ), MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
|
||||
colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
|
||||
UnsignedInteger.valueOf( colon.matcher( siteMatcher.group( 5 ) ).replaceAll( "" ) ),
|
||||
MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
|
||||
MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN(
|
||||
colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ).getAlgorithm(),
|
||||
clearContent? null: siteMatcher.group( 6 ), MPResultType.GeneratedName, null,
|
||||
clearContent? null: siteMatcher.group( 8 ),
|
||||
MPResultType.GeneratedName, clearContent? null: siteMatcher.group( 6 ), null,
|
||||
ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ),
|
||||
MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() );
|
||||
if (clearContent) {
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
@ -16,20 +16,16 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.io.IOException;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import java.util.*;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Instant;
|
||||
@ -62,7 +58,7 @@ public class MPJSONFile extends MPJSONAnyObject {
|
||||
user.avatar = modelUser.getAvatar();
|
||||
user.full_name = modelUser.getFullName();
|
||||
user.last_used = MPConstant.dateTimeFormatter.print( modelUser.getLastUsed() );
|
||||
user.key_id = CodeUtils.encodeHex( modelUser.getKeyID() );
|
||||
user.key_id = modelUser.exportKeyID();
|
||||
user.algorithm = modelUser.getAlgorithm().version();
|
||||
user.default_type = modelUser.getDefaultType();
|
||||
|
||||
@ -75,21 +71,21 @@ public class MPJSONFile extends MPJSONAnyObject {
|
||||
// Clear Text
|
||||
content = modelSite.getResult();
|
||||
loginContent = modelUser.getMasterKey().siteResult(
|
||||
modelSite.getSiteName(), modelSite.getAlgorithm().mpw_default_counter(),
|
||||
modelSite.getName(), modelSite.getAlgorithm().mpw_default_counter(),
|
||||
MPKeyPurpose.Identification, null, modelSite.getLoginType(), modelSite.getLoginState(), modelSite.getAlgorithm() );
|
||||
} else {
|
||||
// Redacted
|
||||
if (modelSite.getResultType().supportsTypeFeature( MPSiteFeature.ExportContent ))
|
||||
content = modelSite.getSiteState();
|
||||
content = modelSite.getResultState();
|
||||
if (modelSite.getLoginType().supportsTypeFeature( MPSiteFeature.ExportContent ))
|
||||
loginContent = modelSite.getLoginState();
|
||||
}
|
||||
|
||||
Site site = sites.get( modelSite.getSiteName() );
|
||||
Site site = sites.get( modelSite.getName() );
|
||||
if (site == null)
|
||||
sites.put( modelSite.getSiteName(), site = new Site() );
|
||||
sites.put( modelSite.getName(), site = new Site() );
|
||||
site.type = modelSite.getResultType();
|
||||
site.counter = modelSite.getSiteCounter().longValue();
|
||||
site.counter = modelSite.getCounter().longValue();
|
||||
site.algorithm = modelSite.getAlgorithm().version();
|
||||
site.password = content;
|
||||
site.login_name = loginContent;
|
||||
@ -140,7 +136,7 @@ public class MPJSONFile extends MPJSONAnyObject {
|
||||
MPAlgorithm algorithm = ifNotNullElse( user.algorithm, MPMasterKey.Version.CURRENT ).getAlgorithm();
|
||||
MPFileUser model = new MPFileUser(
|
||||
user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,
|
||||
(user.default_type != null)? user.default_type: algorithm.mpw_default_password_type(),
|
||||
(user.default_type != null)? user.default_type: algorithm.mpw_default_result_type(),
|
||||
(user.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(),
|
||||
MPMarshalFormat.JSON, export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE );
|
||||
model.setJSON( this );
|
||||
@ -151,9 +147,9 @@ public class MPJSONFile extends MPJSONAnyObject {
|
||||
String siteName = siteEntry.getKey();
|
||||
Site fileSite = siteEntry.getValue();
|
||||
MPFileSite site = new MPFileSite(
|
||||
model, siteName, export.redacted? fileSite.password: null, UnsignedInteger.valueOf( fileSite.counter ),
|
||||
fileSite.type, fileSite.algorithm.getAlgorithm(),
|
||||
export.redacted? fileSite.login_name: null, fileSite.login_type,
|
||||
model, siteName, fileSite.algorithm.getAlgorithm(), UnsignedInteger.valueOf( fileSite.counter ), fileSite.type,
|
||||
export.redacted? fileSite.password: null,
|
||||
fileSite.login_type, export.redacted? fileSite.login_name: null,
|
||||
(fileSite._ext_mpw != null)? fileSite._ext_mpw.url: null, fileSite.uses,
|
||||
(fileSite.last_used != null)? MPConstant.dateTimeFormatter.parseDateTime( fileSite.last_used ): new Instant() );
|
||||
|
@ -16,9 +16,9 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.masterpassword.model.MPJSONFile.objectMapper;
|
||||
import static com.lyndir.masterpassword.model.impl.MPJSONFile.objectMapper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
|
@ -16,13 +16,14 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import static com.lyndir.masterpassword.model.MPJSONFile.objectMapper;
|
||||
import static com.lyndir.masterpassword.model.impl.MPJSONFile.objectMapper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
/**
|
||||
* @author lhunath, 2018-04-26
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
/**
|
||||
* @author lhunath, 2017-09-20
|
@ -16,7 +16,7 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
|
||||
import javax.annotation.Nonnull;
|
@ -16,9 +16,10 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
package com.lyndir.masterpassword.model;
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import com.lyndir.masterpassword.MPKeyUnavailableException;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
@ -0,0 +1,25 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
/**
|
||||
* @author lhunath, 2018-05-14
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
package com.lyndir.masterpassword.model.impl;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
@ -148,7 +148,7 @@ public final class Preferences {
|
||||
|
||||
@Nonnull
|
||||
public MPResultType getDefaultResultType() {
|
||||
return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, getDefaultVersion().getAlgorithm().mpw_default_password_type().ordinal() )];
|
||||
return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, getDefaultVersion().getAlgorithm().mpw_default_result_type().ordinal() )];
|
||||
}
|
||||
|
||||
public boolean setDefaultVersion(final MPMasterKey.Version value) {
|
||||
|
@ -18,97 +18,32 @@
|
||||
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.MPAlgorithm;
|
||||
import com.lyndir.masterpassword.MPResultType;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import com.lyndir.masterpassword.model.impl.MPBasicSite;
|
||||
import java.util.Collection;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-16
|
||||
*/
|
||||
public class IncognitoSite extends MPSite {
|
||||
public class IncognitoSite extends MPBasicSite {
|
||||
|
||||
private final IncognitoUser user;
|
||||
|
||||
private String siteName;
|
||||
private UnsignedInteger siteCounter;
|
||||
private MPResultType resultType;
|
||||
private MPResultType loginType;
|
||||
private MPAlgorithm algorithm;
|
||||
public IncognitoSite(final IncognitoUser user, final String siteName) {
|
||||
super( siteName, user.getAlgorithm() );
|
||||
|
||||
public IncognitoSite(final IncognitoUser user, final String siteName, final UnsignedInteger siteCounter, final MPResultType resultType,
|
||||
final MPAlgorithm algorithm) {
|
||||
this.user = user;
|
||||
this.siteName = siteName;
|
||||
this.siteCounter = siteCounter;
|
||||
this.resultType = resultType;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPUser<?> getUser() {
|
||||
public MPUser<? extends MPSite> getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSiteName(final String siteName) {
|
||||
this.siteName = siteName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultType(final MPResultType resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPResultType getLoginType() {
|
||||
return loginType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoginType(@Nullable final MPResultType loginType) {
|
||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MPQuestion> getQuestions() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnsignedInteger getSiteCounter() {
|
||||
return siteCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSiteCounter(final UnsignedInteger siteCounter) {
|
||||
this.siteCounter = siteCounter;
|
||||
}
|
||||
}
|
||||
|
@ -18,53 +18,23 @@
|
||||
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lyndir.masterpassword.MPAlgorithm;
|
||||
import com.lyndir.masterpassword.MPMasterKey;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import java.util.Collection;
|
||||
import javax.annotation.Nonnull;
|
||||
import com.lyndir.masterpassword.model.impl.MPBasicUser;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-06-08
|
||||
*/
|
||||
public class IncognitoUser extends MPUser<IncognitoSite> {
|
||||
|
||||
private final String fullName;
|
||||
public class IncognitoUser extends MPBasicUser<IncognitoSite> {
|
||||
|
||||
public IncognitoUser(final String fullName) {
|
||||
this.fullName = fullName;
|
||||
super(fullName, MPMasterKey.Version.CURRENT.getAlgorithm());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPAlgorithm getAlgorithm() {
|
||||
return MPMasterKey.Version.CURRENT.getAlgorithm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSite(final IncognitoSite site) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSite(final IncognitoSite site) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IncognitoSite> findSites(final String query) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MPMasterKey authenticate(final char[] masterPassword)
|
||||
throws MPIncorrectMasterPasswordException {
|
||||
return key = new MPMasterKey( getFullName(), masterPassword );
|
||||
public byte[] getKeyID() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ import com.lyndir.masterpassword.MPResultType;
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import com.lyndir.masterpassword.model.impl.*;
|
||||
import com.lyndir.masterpassword.model.impl.MPFileSite;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.annotation.Nonnull;
|
||||
@ -214,7 +216,7 @@ public class ModelAuthenticationPanel extends AuthenticationPanel<MPFileUser> im
|
||||
protected MPFileSite createSite(final MPFileUser user, final String siteName, final UnsignedInteger siteCounter,
|
||||
final MPResultType resultType,
|
||||
final MPAlgorithm algorithm) {
|
||||
return new MPFileSite( user, siteName, siteCounter, resultType, algorithm );
|
||||
return new MPFileSite( user, siteName, algorithm, siteCounter, resultType );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.gui.util.UnsignedIntegerModel;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import com.lyndir.masterpassword.model.impl.MPBasicSite;
|
||||
import com.lyndir.masterpassword.model.impl.MPFileSite;
|
||||
import com.lyndir.masterpassword.model.impl.MPFileUser;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
@ -45,7 +48,7 @@ import javax.swing.event.*;
|
||||
/**
|
||||
* @author lhunath, 2014-06-08
|
||||
*/
|
||||
public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> extends JFrame implements DocumentListener {
|
||||
public abstract class PasswordFrame<U extends MPUser<S>, S extends MPBasicSite> extends JFrame implements DocumentListener {
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final Components.GradientPanel root;
|
||||
@ -147,7 +150,7 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
|
||||
siteCounterField = Components.spinner( siteCounterModel ) );
|
||||
sitePanel.add( siteSettings );
|
||||
resultTypeField.setFont( Res.valueFont().deriveFont( resultTypeField.getFont().getSize2D() ) );
|
||||
resultTypeField.setSelectedItem( user.getAlgorithm().mpw_default_password_type() );
|
||||
resultTypeField.setSelectedItem( user.getAlgorithm().mpw_default_result_type() );
|
||||
resultTypeField.addItemListener( new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(final ItemEvent e) {
|
||||
@ -245,15 +248,15 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
|
||||
siteResults = FluentIterable.from( siteResults ).filter( new Predicate<S>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable final S siteResult) {
|
||||
return (siteResult != null) && siteNameQuery.equals( siteResult.getSiteName() );
|
||||
return (siteResult != null) && siteNameQuery.equals( siteResult.getName() );
|
||||
}
|
||||
} );
|
||||
final S site = ifNotNullElse( Iterables.getFirst( siteResults, null ),
|
||||
createSite( user, siteNameQuery, siteCounter, resultType, siteAlgorithm ) );
|
||||
if ((currentSite != null) && currentSite.getSiteName().equals( site.getSiteName() )) {
|
||||
if ((currentSite != null) && currentSite.getName().equals( site.getName() )) {
|
||||
site.setResultType( resultType );
|
||||
site.setAlgorithm( siteAlgorithm );
|
||||
site.setSiteCounter( siteCounter );
|
||||
site.setCounter( siteCounter );
|
||||
}
|
||||
|
||||
ListenableFuture<String> passwordFuture = Res.execute( this, new Callable<String>() {
|
||||
@ -278,8 +281,8 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
|
||||
siteActionButton.setText( "Add Site" );
|
||||
resultTypeField.setSelectedItem( currentSite.getResultType() );
|
||||
siteVersionField.setSelectedItem( currentSite.getAlgorithm() );
|
||||
siteCounterField.setValue( currentSite.getSiteCounter() );
|
||||
siteNameField.setText( currentSite.getSiteName() );
|
||||
siteCounterField.setValue( currentSite.getCounter() );
|
||||
siteNameField.setText( currentSite.getName() );
|
||||
if (siteNameField.getText().startsWith( siteNameQuery ))
|
||||
siteNameField.select( siteNameQuery.length(), siteNameField.getText().length() );
|
||||
|
||||
|
@ -24,8 +24,7 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
import com.lyndir.masterpassword.MPIdenticon;
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.Future;
|
||||
@ -49,7 +48,7 @@ public class UnlockFrame extends JFrame {
|
||||
private Future<?> identiconFuture;
|
||||
private boolean incognito;
|
||||
@Nullable
|
||||
private MPUser<?> user;
|
||||
private MPUser<? extends MPSite> user;
|
||||
|
||||
public UnlockFrame(final SignInCallback signInCallback) {
|
||||
super( "Unlock Master Password" );
|
||||
@ -158,7 +157,7 @@ public class UnlockFrame extends JFrame {
|
||||
} );
|
||||
}
|
||||
|
||||
void updateUser(@Nullable final MPUser<?> user) {
|
||||
void updateUser(@Nullable final MPUser<? extends MPSite> user) {
|
||||
this.user = user;
|
||||
checkSignIn();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user