Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update token model and db to support github token format #1188

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jhipster/Token.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"fieldName": "renewable",
"fieldType": "Boolean",
"fieldValidateRules": ["required"]
},
{
"fieldName": "newToken",
"fieldType": "String"
}
],
"changelogDate": "20190823204705",
Expand Down
3 changes: 2 additions & 1 deletion jhipster-jdl.jdl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ entity Token {
expiration Instant,
usageLimit Integer,
currentUsage Integer required,
renewable Boolean required
renewable Boolean required,
newToken String
}

entity TokenStats {
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/org/mskcc/cbio/oncokb/domain/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.hibernate.annotations.Type;
import org.mskcc.cbio.oncokb.domain.enumeration.TokenType;

import javax.persistence.*;
import javax.validation.constraints.*;
Expand Down Expand Up @@ -44,6 +45,10 @@ public class Token implements Serializable {
@Column(name = "renewable", nullable = false)
private Boolean renewable = true;

@Convert(converter = TokenKeyConverter.class)
@Column(name = "new_token")
private TokenKey newToken;

@ManyToOne
@JsonIgnoreProperties(value = "tokens", allowSetters = true)
private User user;
Expand Down Expand Up @@ -135,6 +140,19 @@ public void setRenewable(Boolean renewable) {
this.renewable = renewable;
}

public TokenKey getNewToken() {
return newToken;
}

public Token newToken(TokenKey newToken) {
this.newToken = newToken;
return this;
}

public void setNewToken(TokenKey newToken) {
this.newToken = newToken;
}

public User getUser() {
return user;
}
Expand Down Expand Up @@ -176,6 +194,54 @@ public String toString() {
", usageLimit=" + getUsageLimit() +
", currentUsage=" + getCurrentUsage() +
", renewable='" + isRenewable() + "'" +
", newToken='" + getNewToken() + "'" +
"}";
}
}

class TokenKeyConverter implements AttributeConverter<TokenKey, String> {
@Override
public String convertToDatabaseColumn(TokenKey tokenKey) {
if (tokenKey.getTokenType() == null || tokenKey.getToken() == null || tokenKey.getChecksum() == null) {
return null;
}
if (tokenKey.getToken().length() != TokenKey.TOKEN_CHAR_LENGTH || tokenKey.getChecksum().length() != TokenKey.CHECKSUM_CHAR_LENGTH) {
return null;
}
return tokenKey.getTokenType().getType() + "_" + tokenKey.getToken() + tokenKey.getChecksum();
}

@Override
public TokenKey convertToEntityAttribute(String dbData) {
if (dbData == null) {
return null;
}
String[] parts = dbData.split("_");
if (parts.length != 2) {
return null;
}


TokenKey tokenKey = new TokenKey();
String type = parts[0];
if (type.equals(TokenType.SERVICE.getType())) {
tokenKey.setTokenType(TokenType.SERVICE);
} else if (type.equals(TokenType.USER.getType())) {
tokenKey.setTokenType(TokenType.USER);
} else {
return null;
}

String tokenAndChecksum = parts[1];
if (tokenAndChecksum.length() == TokenKey.TOKEN_CHAR_LENGTH + TokenKey.CHECKSUM_CHAR_LENGTH) {
String token = tokenAndChecksum.substring(0, TokenKey.TOKEN_CHAR_LENGTH);
String checksum = tokenAndChecksum.substring(TokenKey.TOKEN_CHAR_LENGTH);
tokenKey.setToken(token);
tokenKey.setChecksum(checksum);
} else {
return null;
}

return tokenKey;
}
}
84 changes: 84 additions & 0 deletions src/main/java/org/mskcc/cbio/oncokb/domain/TokenKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.mskcc.cbio.oncokb.domain;

import java.io.Serializable;
import java.security.SecureRandom;
import java.util.zip.CRC32;

import org.apache.commons.lang3.StringUtils;
import org.mskcc.cbio.oncokb.domain.enumeration.TokenType;

public class TokenKey implements Serializable {
public static int TOKEN_CHAR_LENGTH = 30;

public static int CHECKSUM_CHAR_LENGTH = 6;

private static String BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

private TokenType tokenType;

private String token;

private String checksum;

public static TokenKey generate(TokenType type) {
TokenKey tokenKey = new TokenKey();
tokenKey.setTokenType(type);

CRC32 crc32 = new CRC32();

String token = generateToken();
tokenKey.setToken(token);

crc32.update(token.getBytes());
String base62Checksum = toBase62(crc32.getValue());
if (base62Checksum.length() < CHECKSUM_CHAR_LENGTH) {
base62Checksum = StringUtils.repeat('0', CHECKSUM_CHAR_LENGTH - base62Checksum.length());
}
tokenKey.setChecksum(base62Checksum);

return tokenKey;
}

private static String generateToken() {
SecureRandom secureRandom = new SecureRandom();
StringBuilder token = new StringBuilder();
for (int i = 0; i < TOKEN_CHAR_LENGTH; i++) {
token.append(BASE62_CHARS.charAt(secureRandom.nextInt(BASE62_CHARS.length())));
}
return token.toString();
}

public static String toBase62(long val) {
StringBuffer sb = new StringBuffer();
while(val > 0) {
int remainder = (int) (val % 62);
val = val / 62;
sb.insert(0, BASE62_CHARS.charAt((int) remainder));
}
return sb.toString();
}

public TokenType getTokenType() {
return tokenType;
}

public void setTokenType(TokenType tokenType) {
this.tokenType = tokenType;
}

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}

public String getChecksum() {
return checksum;
}

public void setChecksum(String checksum) {
this.checksum = checksum;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.mskcc.cbio.oncokb.domain.enumeration;

public enum TokenType {
USER("ocku"),
SERVICE("okbs");

String type;

TokenType(String type) {
this.type = type;
}

public String getType() {
return this.type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.mskcc.cbio.oncokb.domain.Authority;
import org.mskcc.cbio.oncokb.domain.Token;
import org.mskcc.cbio.oncokb.domain.TokenKey;
import org.mskcc.cbio.oncokb.domain.User;
import org.mskcc.cbio.oncokb.domain.enumeration.TokenType;
import org.mskcc.cbio.oncokb.repository.UserRepository;
import org.mskcc.cbio.oncokb.security.AuthoritiesConstants;
import org.mskcc.cbio.oncokb.security.SecurityUtils;
Expand Down Expand Up @@ -74,6 +76,7 @@ private Token getNewToken(Set<Authority> authorities, Optional<Instant> definedE
token.setExpiration(expirationTime);
}
token.setToken(UUID.randomUUID());
token.setNewToken(TokenKey.generate(TokenType.USER));
return token;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-3.9.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.9.xsd">
<changeSet author="preiserb (generated)" id="1731955350576-1">
<addColumn tableName="token">
<column name="new_token" type="varchar(255)"/>
</addColumn>
</changeSet>
</databaseChangeLog>
1 change: 1 addition & 0 deletions src/main/resources/config/liquibase/master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<include file="config/liquibase/changelog/20191230201137_added_entity_constraints_UserMails.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/changelog/20210927165533_added_entity_constraints_CompanyDomain.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/changelog/20210927165433_added_entity_constraints_Company.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/changelog/20241118184124_added_field_newToken_to_Token.xml" relativeToChangelogFile="false"/>
<!-- jhipster-needle-liquibase-add-constraints-changelog - JHipster will add liquibase constraints changelogs here -->
<!-- jhipster-needle-liquibase-add-incremental-changelog - JHipster will add incremental liquibase changelogs here -->
</databaseChangeLog>
31 changes: 31 additions & 0 deletions src/test/java/org/mskcc/cbio/oncokb/domain/TokenKeyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.mskcc.cbio.oncokb.domain;

import static org.assertj.core.api.Assertions.assertThat;

import java.nio.ByteBuffer;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

public class TokenKeyTest {
@Test
public void toBase62() {
String test = "d";
assertThat(TokenKey.toBase62(stringToLong(test))).isEqualTo("1c");

test = "hello";
assertThat(TokenKey.toBase62(stringToLong(test))).isEqualTo("7tQLFHz");

test = "oncokb";
assertThat(TokenKey.toBase62(122519905332066L)).isEqualTo("Yn1xclvu");
}

private long stringToLong(String str) {
if (str.length() < Long.BYTES) {
str = StringUtils.repeat('\0', Long.BYTES - str.length()) + str;
}

ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());
return buffer.getLong(0);
}
}
Loading