Initial implementation of questions support.
This commit is contained in:
parent
38a357cb28
commit
8d7c351912
@ -66,6 +66,11 @@ public abstract class MPAlgorithm {
|
|||||||
*/
|
*/
|
||||||
public abstract MPResultType mpw_default_login_type();
|
public abstract MPResultType mpw_default_login_type();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mpw: defaults: answer result type.
|
||||||
|
*/
|
||||||
|
public abstract MPResultType mpw_default_answer_type();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mpw: defaults: initial counter value.
|
* mpw: defaults: initial counter value.
|
||||||
*/
|
*/
|
||||||
|
@ -256,6 +256,11 @@ public class MPAlgorithmV0 extends MPAlgorithm {
|
|||||||
return MPResultType.GeneratedName;
|
return MPResultType.GeneratedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MPResultType mpw_default_answer_type() {
|
||||||
|
return MPResultType.GeneratedPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnsignedInteger mpw_default_counter() {
|
public UnsignedInteger mpw_default_counter() {
|
||||||
return UnsignedInteger.ONE;
|
return UnsignedInteger.ONE;
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
//==============================================================================
|
||||||
|
// 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.ifNotNullElse;
|
||||||
|
|
||||||
|
import com.lyndir.masterpassword.*;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2018-05-14
|
||||||
|
*/
|
||||||
|
public class MPFileQuestion extends MPQuestion {
|
||||||
|
|
||||||
|
private final MPSite 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) {
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
|||||||
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
|
import java.util.*;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.joda.time.Instant;
|
import org.joda.time.Instant;
|
||||||
@ -36,9 +37,9 @@ public class MPFileSite extends MPSite {
|
|||||||
private final MPFileUser user;
|
private final MPFileUser user;
|
||||||
|
|
||||||
private String siteName;
|
private String siteName;
|
||||||
|
private UnsignedInteger siteCounter;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String siteState;
|
private String siteState;
|
||||||
private UnsignedInteger siteCounter;
|
|
||||||
private MPResultType resultType;
|
private MPResultType resultType;
|
||||||
private MPAlgorithm algorithm;
|
private MPAlgorithm algorithm;
|
||||||
|
|
||||||
@ -51,6 +52,8 @@ public class MPFileSite extends MPSite {
|
|||||||
private int uses;
|
private int uses;
|
||||||
private ReadableInstant lastUsed;
|
private ReadableInstant lastUsed;
|
||||||
|
|
||||||
|
private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
|
||||||
|
|
||||||
public MPFileSite(final MPFileUser user, final String siteName) {
|
public MPFileSite(final MPFileUser user, final String siteName) {
|
||||||
this( user, siteName, null, null, user.getAlgorithm() );
|
this( user, siteName, null, null, user.getAlgorithm() );
|
||||||
}
|
}
|
||||||
@ -66,11 +69,12 @@ public class MPFileSite extends MPSite {
|
|||||||
@Nullable final String loginState, @Nullable final MPResultType loginType,
|
@Nullable final String loginState, @Nullable final MPResultType loginType,
|
||||||
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
|
||||||
this.siteName = siteName;
|
this.siteName = siteName;
|
||||||
this.siteState = siteState;
|
this.siteState = siteState;
|
||||||
this.siteCounter = ifNotNullElse( siteCounter, user.getAlgorithm().mpw_default_counter() );
|
this.siteCounter = ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() );
|
||||||
this.resultType = ifNotNullElse( resultType, user.getAlgorithm().mpw_default_password_type() );
|
this.resultType = ifNotNullElse( resultType, getAlgorithm().mpw_default_password_type() );
|
||||||
this.algorithm = algorithm;
|
|
||||||
this.loginState = loginState;
|
this.loginState = loginState;
|
||||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||||
this.url = url;
|
this.url = url;
|
||||||
@ -116,15 +120,15 @@ public class MPFileSite extends MPSite {
|
|||||||
return siteState;
|
return siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSitePassword(final MPResultType resultType, @Nullable final String result)
|
public void setSitePassword(final MPResultType resultType, @Nullable final String password)
|
||||||
throws MPKeyUnavailableException {
|
throws MPKeyUnavailableException {
|
||||||
this.resultType = resultType;
|
this.resultType = resultType;
|
||||||
|
|
||||||
if (result == null)
|
if (password == null)
|
||||||
this.siteState = null;
|
this.siteState = null;
|
||||||
else
|
else
|
||||||
this.siteState = user.getMasterKey().siteState(
|
this.siteState = getState(
|
||||||
siteName, siteCounter, MPKeyPurpose.Authentication, null, resultType, result, algorithm );
|
MPKeyPurpose.Authentication, null, siteCounter, resultType, password );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -155,7 +159,6 @@ public class MPFileSite extends MPSite {
|
|||||||
@Override
|
@Override
|
||||||
public void setLoginType(@Nullable final MPResultType loginType) {
|
public void setLoginType(@Nullable final MPResultType loginType) {
|
||||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,6 +171,11 @@ public class MPFileSite extends MPSite {
|
|||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends MPQuestion> getQuestions() {
|
||||||
|
return Collections.unmodifiableCollection( questions );
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getLoginState() {
|
public String getLoginState() {
|
||||||
return loginState;
|
return loginState;
|
||||||
@ -176,9 +184,7 @@ public class MPFileSite extends MPSite {
|
|||||||
public void setLoginName(@Nonnull final MPResultType loginType, @Nonnull final String loginName)
|
public void setLoginName(@Nonnull final MPResultType loginType, @Nonnull final String loginName)
|
||||||
throws MPKeyUnavailableException {
|
throws MPKeyUnavailableException {
|
||||||
this.loginType = loginType;
|
this.loginType = loginType;
|
||||||
this.loginState = user.getMasterKey().siteState(
|
this.loginState = getState( MPKeyPurpose.Identification, null, null, this.loginType, loginName );
|
||||||
siteName, algorithm.mpw_default_counter(), MPKeyPurpose.Identification, null,
|
|
||||||
this.loginType, loginName, algorithm );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -39,7 +39,7 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
|||||||
private static final Logger logger = Logger.get( MPFileUser.class );
|
private static final Logger logger = Logger.get( MPFileUser.class );
|
||||||
|
|
||||||
private final String fullName;
|
private final String fullName;
|
||||||
private final Collection<MPFileSite> sites = Sets.newHashSet();
|
private final Collection<MPFileSite> sites = new LinkedHashSet<>();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private byte[] keyID;
|
private byte[] keyID;
|
||||||
@ -136,7 +136,7 @@ public class MPFileUser extends MPUser<MPFileSite> implements Comparable<MPFileU
|
|||||||
lastUsed = new Instant();
|
lastUsed = new Instant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<MPFileSite> getSites() {
|
public Collection<MPFileSite> getSites() {
|
||||||
return Collections.unmodifiableCollection( sites );
|
return Collections.unmodifiableCollection( sites );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
//==============================================================================
|
||||||
|
// 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 com.lyndir.masterpassword.*;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2018-05-14
|
||||||
|
*/
|
||||||
|
public abstract class MPQuestion {
|
||||||
|
|
||||||
|
public abstract MPSite getSite();
|
||||||
|
|
||||||
|
public abstract String getKeyword();
|
||||||
|
|
||||||
|
public abstract MPResultType getType();
|
||||||
|
|
||||||
|
public String getAnswer(@Nullable final String state)
|
||||||
|
throws MPKeyUnavailableException {
|
||||||
|
|
||||||
|
return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
|
||||||
|
}
|
||||||
|
}
|
@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
package com.lyndir.masterpassword.model;
|
package com.lyndir.masterpassword.model;
|
||||||
|
|
||||||
|
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||||
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@ -54,21 +56,40 @@ public abstract class MPSite {
|
|||||||
public abstract void setAlgorithm(MPAlgorithm algorithm);
|
public abstract void setAlgorithm(MPAlgorithm algorithm);
|
||||||
|
|
||||||
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||||
@Nullable final String siteContent)
|
@Nullable final String state)
|
||||||
|
throws MPKeyUnavailableException {
|
||||||
|
|
||||||
|
return getResult( keyPurpose, keyContext, getSiteCounter(), getResultType(), state );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||||
|
@Nullable final UnsignedInteger siteCounter, final MPResultType type,
|
||||||
|
@Nullable final String state)
|
||||||
throws MPKeyUnavailableException {
|
throws MPKeyUnavailableException {
|
||||||
|
|
||||||
return getUser().getMasterKey().siteResult(
|
return getUser().getMasterKey().siteResult(
|
||||||
getSiteName(), getSiteCounter(), keyPurpose, keyContext, getResultType(), siteContent, getAlgorithm() );
|
getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||||
|
type, state, getAlgorithm() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
|
||||||
|
@Nullable final UnsignedInteger siteCounter, final MPResultType type,
|
||||||
|
@Nullable final String state)
|
||||||
|
throws MPKeyUnavailableException {
|
||||||
|
|
||||||
|
return getUser().getMasterKey().siteState(
|
||||||
|
getSiteName(), ifNotNullElse( siteCounter, getAlgorithm().mpw_default_counter() ), keyPurpose, keyContext,
|
||||||
|
type, state, getAlgorithm() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLogin(@Nullable final String loginContent)
|
public String getLogin(@Nullable final String loginContent)
|
||||||
throws MPKeyUnavailableException {
|
throws MPKeyUnavailableException {
|
||||||
|
|
||||||
return getUser().getMasterKey().siteResult(
|
return getResult( MPKeyPurpose.Identification, null,null, getLoginType(), loginContent );
|
||||||
getSiteName(), getAlgorithm().mpw_default_counter(), MPKeyPurpose.Identification, null,
|
|
||||||
getLoginType(), loginContent, getAlgorithm() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract Collection<? extends MPQuestion> getQuestions();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getSiteName(), ((MPSite) obj).getSiteName() ));
|
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getSiteName(), ((MPSite) obj).getSiteName() ));
|
||||||
|
@ -20,11 +20,13 @@ package com.lyndir.masterpassword.gui.model;
|
|||||||
|
|
||||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
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.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.MPAlgorithm;
|
import com.lyndir.masterpassword.MPAlgorithm;
|
||||||
import com.lyndir.masterpassword.MPResultType;
|
import com.lyndir.masterpassword.MPResultType;
|
||||||
import com.lyndir.masterpassword.model.MPSite;
|
import com.lyndir.masterpassword.model.*;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
import java.util.Collection;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +97,11 @@ public class IncognitoSite extends MPSite {
|
|||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<MPQuestion> getQuestions() {
|
||||||
|
return ImmutableList.of();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnsignedInteger getSiteCounter() {
|
public UnsignedInteger getSiteCounter() {
|
||||||
return siteCounter;
|
return siteCounter;
|
||||||
|
@ -260,9 +260,7 @@ public abstract class PasswordFrame<U extends MPUser<S>, S extends MPSite> exten
|
|||||||
@Override
|
@Override
|
||||||
public String call()
|
public String call()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
return user.getMasterKey()
|
return site.getResult( MPKeyPurpose.Authentication, null, null );
|
||||||
.siteResult( site.getSiteName(), site.getSiteCounter(), MPKeyPurpose.Authentication, null, site.getResultType(),
|
|
||||||
null, site.getAlgorithm() );
|
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
Futures.addCallback( passwordFuture, new FutureCallback<String>() {
|
Futures.addCallback( passwordFuture, new FutureCallback<String>() {
|
||||||
|
Loading…
Reference in New Issue
Block a user