Skip to content
Snippets Groups Projects
Commit ac27cf14 authored by piotr.kupczyk@id.ethz.ch's avatar piotr.kupczyk@id.ethz.ch
Browse files

SSDM-11550 : Personal Access Tokens (PAT) - check if validToDate is not in the...

SSDM-11550 : Personal Access Tokens (PAT) - check if validToDate is not in the past when creating a new PAT
parent 4864defc
No related branches found
No related tags found
1 merge request!40SSDM-13578 : 2PT : Database and V3 Implementation - include the new AFS "free"...
......@@ -27,6 +27,7 @@ import ch.systemsx.cisd.base.annotation.JsonObject;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.common.utilities.ITimeProvider;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonDAO;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonalAccessTokenDAO;
......@@ -51,6 +52,8 @@ public class PersonalAccessTokenDAO implements IPersonalAccessTokenDAO
private final HashGenerator generator;
private final ITimeProvider timeProvider;
private Map<String, FileToken> fileTokens = new LinkedHashMap<>();
private Map<String, FileSession> fileSessions = new LinkedHashMap<>();
......@@ -78,11 +81,17 @@ public class PersonalAccessTokenDAO implements IPersonalAccessTokenDAO
{
return SessionTokenHash.create(user, System.currentTimeMillis()).toString();
}
}, new ITimeProvider()
{
@Override public long getTimeInMilliseconds()
{
return System.currentTimeMillis();
}
});
}
PersonalAccessTokenDAO(final IPersonalAccessTokenConfig config, final IPersonDAO personDAO,
final HashGenerator generator)
final HashGenerator generator, final ITimeProvider timeProvider)
{
if (config == null)
{
......@@ -99,9 +108,15 @@ public class PersonalAccessTokenDAO implements IPersonalAccessTokenDAO
throw new IllegalArgumentException("Hash generator cannot be null");
}
if (timeProvider == null)
{
throw new IllegalArgumentException("Time provider cannot be null");
}
this.config = config;
this.personDAO = personDAO;
this.generator = generator;
this.timeProvider = timeProvider;
if (config.arePersonalAccessTokensEnabled())
{
......@@ -172,6 +187,11 @@ public class PersonalAccessTokenDAO implements IPersonalAccessTokenDAO
throw new UserFailureException("Valid to date cannot be null.");
}
if (creation.getValidToDate().getTime() < timeProvider.getTimeInMilliseconds())
{
throw new UserFailureException("Valid to date cannot be in the past.");
}
if (creation.getValidFromDate().getTime() >= creation.getValidToDate().getTime())
{
throw new UserFailureException("Valid to date has to be after valid from date.");
......
......@@ -204,13 +204,18 @@ public class CreatePersonalAccessTokenTest extends AbstractPersonalAccessTokenTe
@Test
public void testCreateWithValidToDateInThePast()
{
PersonalAccessTokenCreation creation = tokenCreation();
creation.setValidFromDate(new Date(System.currentTimeMillis() - 2 * DateUtils.MILLIS_PER_DAY));
creation.setValidToDate(new Date(System.currentTimeMillis() - DateUtils.MILLIS_PER_DAY));
PersonalAccessToken token = createToken(TEST_USER, PASSWORD, creation);
assertUserFailureException(new IDelegatedAction()
{
@Override
public void execute()
{
PersonalAccessTokenCreation creation = tokenCreation();
creation.setValidFromDate(new Date(System.currentTimeMillis() - 2 * DateUtils.MILLIS_PER_DAY));
creation.setValidToDate(new Date(System.currentTimeMillis() - DateUtils.MILLIS_PER_DAY));
assertFalse(v3api.isSessionActive(token.getHash()));
PersonalAccessToken token = createToken(TEST_USER, PASSWORD, creation);
}
}, "Valid to date cannot be in the past");
}
@Test
......@@ -273,8 +278,8 @@ public class CreatePersonalAccessTokenTest extends AbstractPersonalAccessTokenTe
public void execute()
{
PersonalAccessTokenCreation creation = tokenCreation();
creation.setValidFromDate(new Date(2));
creation.setValidToDate(new Date(1));
creation.setValidFromDate(new Date(System.currentTimeMillis() + 2 * DateUtils.MILLIS_PER_DAY));
creation.setValidToDate(new Date(System.currentTimeMillis() + DateUtils.MILLIS_PER_DAY));
createToken(TEST_USER, PASSWORD, creation);
}
}, "Valid to date has to be after valid from date");
......@@ -289,8 +294,8 @@ public class CreatePersonalAccessTokenTest extends AbstractPersonalAccessTokenTe
public void execute()
{
PersonalAccessTokenCreation creation = tokenCreation();
creation.setValidFromDate(new Date(1));
creation.setValidToDate(new Date(1));
creation.setValidFromDate(new Date(System.currentTimeMillis() + DateUtils.MILLIS_PER_DAY));
creation.setValidToDate(new Date(System.currentTimeMillis() + DateUtils.MILLIS_PER_DAY));
createToken(TEST_USER, PASSWORD, creation);
}
}, "Valid to date has to be after valid from date");
......
......@@ -24,7 +24,6 @@ import static org.testng.Assert.fail;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.test.context.transaction.TestTransaction;
......@@ -35,7 +34,6 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.authorizationgroup.create.Author
import ch.ethz.sis.openbis.generic.asapi.v3.dto.authorizationgroup.delete.AuthorizationGroupDeletionOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.authorizationgroup.fetchoptions.AuthorizationGroupFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.authorizationgroup.id.IAuthorizationGroupId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.pat.create.PersonalAccessTokenCreation;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.pat.id.PersonalAccessTokenPermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.create.PersonCreation;
......
......@@ -12,6 +12,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Assert;
import org.testng.annotations.Test;
......@@ -84,14 +85,16 @@ public class GetSessionInformationTest extends AbstractTest
}
@Test
public void testGetWithPersonalAccessTokenInvalid()
public void testGetWithPersonalAccessTokenInvalid() throws InterruptedException
{
PersonalAccessTokenCreation tokenCreation = tokenCreation();
tokenCreation.setValidFromDate(new Date(0));
tokenCreation.setValidToDate(new Date(1));
tokenCreation.setValidFromDate(new Date());
tokenCreation.setValidToDate(new Date(System.currentTimeMillis() + 250));
PersonalAccessToken token = createToken(TEST_USER, PASSWORD, tokenCreation);
Thread.sleep(250);
try
{
v3api.getSessionInformation(token.getHash());
......
......@@ -32,6 +32,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.common.filesystem.FileUtilities;
import ch.systemsx.cisd.common.logging.BufferedAppender;
import ch.systemsx.cisd.common.test.AssertionUtil;
import ch.systemsx.cisd.common.utilities.ITimeProvider;
import ch.systemsx.cisd.common.utilities.TestResources;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonDAO;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.PersonalAccessTokenDAO.HashGenerator;
......@@ -124,7 +125,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-valid-file.json", 60 * 60);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
List<PersonalAccessToken> tokens = dao.listTokens();
assertEquals(tokens.size(), 3);
......@@ -138,7 +140,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(false, "test-valid-file.json", 60 * 60);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
try
{
......@@ -164,7 +167,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-empty.json", 60 * 60);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
PersonalAccessToken creation1 = tokenCreation("test owner", "test session", new Date(0), new Date(2 * 60 * 60 * 1000));
PersonalAccessToken creation2 = tokenCreation("test owner", "test session", new Date(0), new Date(59 * 60 * 1000));
......@@ -184,8 +188,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-empty.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
PersonalAccessToken tokenCreationA1 = tokenCreation("test owner", "test session A", new Date(5), new Date(10));
PersonalAccessToken tokenCreationB1 = tokenCreation("test owner", "test session B", new Date(10), new Date(20));
......@@ -249,8 +253,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "i-do-not-exist.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 0);
assertEquals(dao.listSessions().size(), 0);
......@@ -261,8 +265,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-incorrect-owner-id.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 0);
assertEquals(dao.listSessions().size(), 0);
......@@ -278,8 +282,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-valid-from-date-equal-to-valid-to-date.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 0);
assertEquals(dao.listSessions().size(), 0);
......@@ -295,8 +299,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-valid-from-date-after-valid-to-date.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 0);
assertEquals(dao.listSessions().size(), 0);
......@@ -312,8 +316,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-validity-period-longer-than-allowed-maximum.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 1);
assertEquals(dao.listSessions().size(), 1);
......@@ -331,8 +335,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-tokens-only.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertEquals(dao.listTokens().size(), 3);
assertEquals(dao.listSessions().size(), 2);
......@@ -345,8 +349,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-unknown-users.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertNull(dao.getTokenByHash("token-1"));
assertNotNull(dao.getTokenByHash("token-2"));
......@@ -365,8 +369,8 @@ public class PersonalAccessTokenDAOTest
{
IPersonalAccessTokenConfig config = config(true, "test-inactive-users.json", TEST_VALIDITY_PERIOD);
TestGenerator generator = new TestGenerator();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator);
TestTimeProvider timeProvider = new TestTimeProvider();
PersonalAccessTokenDAO dao = new PersonalAccessTokenDAO(config, personDAO, generator, timeProvider);
assertNull(dao.getTokenByHash("token-1"));
assertNotNull(dao.getTokenByHash("token-2"));
......@@ -499,4 +503,12 @@ public class PersonalAccessTokenDAOTest
return "session-" + sessionCounter++;
}
}
private static class TestTimeProvider implements ITimeProvider
{
@Override public long getTimeInMilliseconds()
{
return 0;
}
}
}
......@@ -244,6 +244,7 @@ const keys = {
VALID_FROM: 'VALID_FROM',
VALID_TO: 'VALID_TO',
VALID_TO_HAS_TO_AFTER_VALID_FROM: 'VALID_TO_HAS_TO_AFTER_VALID_FROM',
VALID_TO_CANNOT_BE_IN_THE_PAST: 'VALID_TO_CANNOT_BE_IN_THE_PAST',
VALIDITY_LEFT: 'VALIDITY_LEFT',
VALIDITY_PERIOD: 'VALIDITY_PERIOD',
VALIDATION_CANNOT_BE_EMPTY: 'VALIDATION_CANNOT_BE_EMPTY',
......@@ -511,6 +512,7 @@ const messages_en = {
[keys.VALID_FROM]: 'Valid From',
[keys.VALID_TO]: 'Valid To',
[keys.VALID_TO_HAS_TO_AFTER_VALID_FROM]: 'Valid To has to be after Valid From',
[keys.VALID_TO_CANNOT_BE_IN_THE_PAST]: 'Valid To cannot be in the past',
[keys.VALIDITY_LEFT]: 'Validity Left',
[keys.VALIDITY_PERIOD]: 'Validity Period',
[keys.VALIDATION_CANNOT_BE_EMPTY]: '${0} cannot be empty',
......
......@@ -101,5 +101,15 @@ export default class PersonalAccessTokenFormControllerValidate extends PageContr
}
}
}
if (pat.validToDate.value && pat.validToDate.value.dateObject) {
if (pat.validToDate.value.dateObject.getTime() < new Date().getTime()) {
validator.addError(
pat,
'validToDate',
messages.get(messages.VALID_TO_CANNOT_BE_IN_THE_PAST)
)
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment