Skip to content

Commit

Permalink
core: Rename some classes and, track and store the accumulated durati…
Browse files Browse the repository at this point in the history
…on and size (bytes) for each query associated with a token (i.e., user), #TASK-4791, #TASK-4641
  • Loading branch information
jtarraga committed Jul 20, 2023
1 parent 6cfecae commit ed35983
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import com.beust.jcommander.*;
import org.opencb.cellbase.app.cli.CliOptionsParser;
import org.opencb.cellbase.core.token.DataAccessToken;
import org.opencb.cellbase.core.token.QuotaPayload;

import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -170,7 +170,7 @@ public class DataTokenCommandOptions {

@Parameter(names = {"--max-num-queries"}, description = "Use this parameter in conjunction with --create-token to specify the"
+ " maximum number of queries per month", arity = 1)
public long maxNumQueries = DataAccessToken.DEFAULT_MAX_NUM_QUERIES;
public long maxNumQueries = QuotaPayload.DEFAULT_MAX_NUM_QUERIES;

@Parameter(names = {"--view-token"}, description = "Token to view", arity = 1)
public String tokenToView;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.apache.commons.lang3.StringUtils;
import org.opencb.cellbase.app.cli.CommandExecutor;
import org.opencb.cellbase.app.cli.admin.AdminCliOptionsParser;
import org.opencb.cellbase.core.token.DataAccessToken;
import org.opencb.cellbase.core.token.QuotaPayload;
import org.opencb.cellbase.core.token.DataAccessTokenManager;

import javax.crypto.spec.SecretKeySpec;
Expand Down Expand Up @@ -53,7 +53,7 @@ public void execute() {
try {
if (StringUtils.isNotEmpty(dataTokenCommandOptions.createWithDataSources)) {
// Create data token
DataAccessToken dataSources = DataAccessToken.parse(dataTokenCommandOptions.createWithDataSources,
QuotaPayload dataSources = QuotaPayload.parse(dataTokenCommandOptions.createWithDataSources,
dataTokenCommandOptions.maxNumQueries);
String token = datManager.encode(dataTokenCommandOptions.organization, dataSources);
System.out.println("Data access token generated:\n" + token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import java.security.Key;
import java.util.*;

import static org.opencb.cellbase.core.token.DataAccessToken.MAX_NUM_ANOYMOUS_QUERIES;
import static org.opencb.cellbase.core.token.DataAccessToken.dateFormatter;
import static org.opencb.cellbase.core.token.QuotaPayload.MAX_NUM_ANOYMOUS_QUERIES;
import static org.opencb.cellbase.core.token.QuotaPayload.dateFormatter;

public class DataAccessTokenManager {
private SignatureAlgorithm algorithm;
Expand All @@ -56,15 +56,15 @@ public DataAccessTokenManager(String algorithm, Key secretKey) {
this.privateKey = secretKey;
this.publicKey = secretKey;
jwtParser = Jwts.parserBuilder().setSigningKey(publicKey).build();
defaultToken = encode("ANONYMOUS", new DataAccessToken(DataAccessToken.CURRENT_VERSION, new HashMap<>(), MAX_NUM_ANOYMOUS_QUERIES),
defaultToken = encode("ANONYMOUS", new QuotaPayload(QuotaPayload.CURRENT_VERSION, new HashMap<>(), MAX_NUM_ANOYMOUS_QUERIES),
true);
}

public String encode(String organization, DataAccessToken dat) {
public String encode(String organization, QuotaPayload dat) {
return encode(organization, dat, false);
}

public String encode(String organization, DataAccessToken dat, boolean skipIssuedAt) {
public String encode(String organization, QuotaPayload dat, boolean skipIssuedAt) {
JwtBuilder jwtBuilder = Jwts.builder();

Map<String, Object> claims = new HashMap<>();
Expand All @@ -84,8 +84,8 @@ public String encode(String organization, DataAccessToken dat, boolean skipIssue
return jwtBuilder.compact();
}

public DataAccessToken decode(String token) {
DataAccessToken dat = new DataAccessToken();
public QuotaPayload decode(String token) {
QuotaPayload dat = new QuotaPayload();

Claims body = parse(token);
for (Map.Entry<String, Object> entry : body.entrySet()) {
Expand All @@ -109,7 +109,7 @@ public DataAccessToken decode(String token) {
}

public String recode(String token) {
DataAccessToken dataAccessToken = decode(token);
QuotaPayload dataAccessToken = decode(token);
if (MapUtils.isNotEmpty(dataAccessToken.getSources())) {
Map<String, Long> sources = new HashMap<>();
for (Map.Entry<String, Long> entry : dataAccessToken.getSources().entrySet()) {
Expand All @@ -128,7 +128,7 @@ public void validate(String token) {
}

public boolean hasExpiredSource(String source, String token) throws IllegalArgumentException {
DataAccessToken dat = decode(token);
QuotaPayload dat = decode(token);
if (MapUtils.isNotEmpty(dat.getSources()) && dat.getSources().containsKey(source)) {
return (new Date().getTime() > dat.getSources().get(source));
}
Expand All @@ -146,7 +146,7 @@ public Set<String> getValidSources(String token, Set<String> init) throws Illega
}

if (StringUtils.isNotEmpty(token)) {
DataAccessToken dat = decode(token);
QuotaPayload dat = decode(token);
if (MapUtils.isNotEmpty(dat.getSources())) {
for (Map.Entry<String, Long> entry : dat.getSources().entrySet()) {
if (new Date().getTime() <= entry.getValue()) {
Expand All @@ -164,7 +164,7 @@ public Set<String> getValidSources(String token, Set<String> init) throws Illega
}

public long getMaxNumQueries(String token) {
DataAccessToken dat = decode(token);
QuotaPayload dat = decode(token);
return dat.getMaxNumQueries();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import java.util.HashMap;
import java.util.Map;

public class DataAccessToken {
public class QuotaPayload {

private String version;
private Map<String, Long> sources;
Expand All @@ -34,15 +34,15 @@ public class DataAccessToken {
public static final Long MAX_NUM_ANOYMOUS_QUERIES = 1000000L;
public static final Long DEFAULT_MAX_NUM_QUERIES = 10000000L;

public DataAccessToken() {
this(CURRENT_VERSION, new HashMap<>(), 0L);
public QuotaPayload() {
this(CURRENT_VERSION, new HashMap<>(), DEFAULT_MAX_NUM_QUERIES);
}

public DataAccessToken(String version, Map<String, Long> sources) {
this(version, sources, 0L);
public QuotaPayload(String version, Map<String, Long> sources) {
this(version, sources, DEFAULT_MAX_NUM_QUERIES);
}

public DataAccessToken(String version, Map<String, Long> sources, Long maxNumQueries) {
public QuotaPayload(String version, Map<String, Long> sources, Long maxNumQueries) {
this.version = version;
this.sources = sources;
this.maxNumQueries = maxNumQueries;
Expand All @@ -54,12 +54,12 @@ public static DateFormat dateFormatter() {
return dateFormatter;
}

public static DataAccessToken parse(String sources) throws ParseException {
public static QuotaPayload parse(String sources) throws ParseException {
return parse(sources, null);
}

public static DataAccessToken parse(String sources, Long maxNumQueries) throws ParseException {
DataAccessToken dataAccessToken = new DataAccessToken();
public static QuotaPayload parse(String sources, Long maxNumQueries) throws ParseException {
QuotaPayload dataAccessToken = new QuotaPayload();
Map<String, Long> sourcesMap = new HashMap<>();
String[] split = sources.split(",");
for (String source : split) {
Expand All @@ -82,7 +82,7 @@ public static DataAccessToken parse(String sources, Long maxNumQueries) throws P

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("DataAccessToken{");
final StringBuilder sb = new StringBuilder("QuotaPayload{");
sb.append("version='").append(version).append('\'');
sb.append(", sources=").append(sources);
sb.append(", maxNumQueries=").append(maxNumQueries);
Expand All @@ -94,7 +94,7 @@ public String getVersion() {
return version;
}

public DataAccessToken setVersion(String version) {
public QuotaPayload setVersion(String version) {
this.version = version;
return this;
}
Expand All @@ -103,7 +103,7 @@ public Map<String, Long> getSources() {
return sources;
}

public DataAccessToken setSources(Map<String, Long> sources) {
public QuotaPayload setSources(Map<String, Long> sources) {
this.sources = sources;
return this;
}
Expand All @@ -112,7 +112,7 @@ public Long getMaxNumQueries() {
return maxNumQueries;
}

public DataAccessToken setMaxNumQueries(Long maxNumQueries) {
public QuotaPayload setMaxNumQueries(Long maxNumQueries) {
this.maxNumQueries = maxNumQueries;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,36 @@

package org.opencb.cellbase.core.token;

public class Quota {
public class TokenStats {
private String token;
private String date; // date consists of year + month, e.g.: 202304
private long numQueries;
private long duration;
private long bytes;

public Quota() {
public TokenStats() {
}

public Quota(String token, String date, long numQueries) {
public TokenStats(String token, String date) {
this(token, date, 0, 0, 0);
}

public TokenStats(String token, String date, long numQueries, long duration, long bytes) {
this.token = token;
this.date = date;
this.numQueries = numQueries;
this.duration = duration;
this.bytes = bytes;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Quota{");
final StringBuilder sb = new StringBuilder("TokenStats{");
sb.append("token='").append(token).append('\'');
sb.append(", date='").append(date).append('\'');
sb.append(", numQueries=").append(numQueries);
sb.append(", duration=").append(duration);
sb.append(", bytes=").append(bytes);
sb.append('}');
return sb.toString();
}
Expand All @@ -44,7 +54,7 @@ public String getToken() {
return token;
}

public Quota setToken(String token) {
public TokenStats setToken(String token) {
this.token = token;
return this;
}
Expand All @@ -53,12 +63,7 @@ public String getDate() {
return date;
}

public Quota setDate(int year, int month) {
this.date = year + String.format("%02d", month);
return this;
}

public Quota setDate(String date) {
public TokenStats setDate(String date) {
this.date = date;
return this;
}
Expand All @@ -67,8 +72,26 @@ public long getNumQueries() {
return numQueries;
}

public Quota setNumQueries(long numQueries) {
public TokenStats setNumQueries(long numQueries) {
this.numQueries = numQueries;
return this;
}

public long getDuration() {
return duration;
}

public TokenStats setDuration(long duration) {
this.duration = duration;
return this;
}

public long getBytes() {
return bytes;
}

public TokenStats setBytes(long bytes) {
this.bytes = bytes;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import org.opencb.cellbase.core.api.query.ProjectionQueryOptions;
import org.opencb.cellbase.core.exception.CellBaseException;
import org.opencb.cellbase.core.result.CellBaseDataResult;
import org.opencb.cellbase.core.token.Quota;
import org.opencb.cellbase.core.token.TokenStats;
import org.opencb.cellbase.lib.iterator.CellBaseIterator;
import org.opencb.commons.datastore.core.FacetField;
import org.opencb.commons.datastore.core.QueryOptions;
Expand All @@ -44,7 +44,7 @@
public class MetaMongoDBAdaptor extends MongoDBAdaptor implements CellBaseCoreDBAdaptor {

private MongoDBCollection mongoDBCollection;
private MongoDBCollection quotaMongoDBCollection;
private MongoDBCollection tokenStatsMongoDBCollection;

public MetaMongoDBAdaptor(MongoDataStore mongoDataStore) {
super(mongoDataStore);
Expand All @@ -56,7 +56,7 @@ public MetaMongoDBAdaptor(MongoDataStore mongoDataStore) {
private void init() {
logger.debug("MetaMongoDBAdaptor: in 'constructor'");
mongoDBCollection = mongoDataStore.getCollection("metadata");
quotaMongoDBCollection = mongoDataStore.getCollection("quota");
tokenStatsMongoDBCollection = mongoDataStore.getCollection("token_stats");
}

public CellBaseDataResult getAll() {
Expand Down Expand Up @@ -110,30 +110,36 @@ public CellBaseDataResult getQuota(String token, String date) {
andBsonList.add(Filters.eq("date", date));
Bson query = Filters.and(andBsonList);

return new CellBaseDataResult<>(quotaMongoDBCollection.find(query, null, Quota.class, QueryOptions.empty()));
return new CellBaseDataResult<>(tokenStatsMongoDBCollection.find(query, null, TokenStats.class, QueryOptions.empty()));
}

public CellBaseDataResult initQuota(String token, String date) throws CellBaseException {
public CellBaseDataResult initTokenStats(String token, String date) throws CellBaseException {
try {
Quota quota = new Quota(token, date, 0);
Document document = Document.parse(new ObjectMapper().writeValueAsString(quota));
return new CellBaseDataResult<>(quotaMongoDBCollection.insert(document, QueryOptions.empty()));
TokenStats tokenStats = new TokenStats(token, date);
Document document = Document.parse(new ObjectMapper().writeValueAsString(tokenStats));
return new CellBaseDataResult<>(tokenStatsMongoDBCollection.insert(document, QueryOptions.empty()));
} catch (IOException e) {
throw new CellBaseException("Error initializing quota for token '" + token.substring(0, 10) + "...': " + e.getMessage());
}
}

public CellBaseDataResult update(String token, String date, long value) {
public CellBaseDataResult incTokenStats(String token, String date, long incNumQueries, long incDuration, long incBytes) {
List<Bson> andBsonList = new ArrayList<>();
andBsonList.add(Filters.eq("token", token));
andBsonList.add(Filters.eq("date", date));
Bson query = Filters.and(andBsonList);

Document projection = new Document("numQueries", true);
Bson update = Updates.set("numQueries", value);
Bson update = Updates.combine(Updates.inc("numQueries", incNumQueries),
Updates.inc("duration", incDuration),
Updates.inc("bytes", incBytes));

Document projection = new Document("numQueries", true)
.append("duration", true)
.append("bytes", true);

QueryOptions queryOptions = new QueryOptions("replace", true);
System.out.println("query = " + query);
System.out.println("update = " + update);
return new CellBaseDataResult<>(quotaMongoDBCollection.findAndUpdate(query, projection, null, update, Quota.class, queryOptions));

return new CellBaseDataResult<>(tokenStatsMongoDBCollection.findAndUpdate(query, projection, null, update, TokenStats.class,
queryOptions));
}
}
Loading

0 comments on commit ed35983

Please sign in to comment.