package io.fathom.cloud.server.auth;
import io.fathom.cloud.WellKnownRoles;
import io.fathom.cloud.protobuf.CloudCommons.TokenInfo;
import io.fathom.cloud.protobuf.CloudCommons.TokenScope;
import io.fathom.cloud.server.model.Project;
import io.fathom.cloud.server.model.User;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
public class TokenAuth implements Auth {
private static final Logger log = LoggerFactory.getLogger(TokenAuth.class);
private final TokenInfo token;
public TokenAuth(TokenInfo token) {
Preconditions.checkNotNull(token);
this.token = token;
if (hasExpired(token)) {
throw new IllegalArgumentException();
}
}
@Override
public Auth.Domain findDomainWithAdminRole() {
if (getTokenScope() == TokenScope.Domain) {
long domainId = token.getDomainId();
if (domainId == 0) {
throw new IllegalStateException();
}
if (!isInDomainRole(WellKnownRoles.ROLE_ID_ADMIN)) {
return null;
}
return new DomainImpl(domainId);
} else {
log.warn("Using compatible behaviour; accepting non-domain token for domain action");
long domainId = token.getDomainId();
if (domainId == 0) {
log.warn("No domain id set in token: {}", token);
return null;
}
if (!isInDomainRole(WellKnownRoles.ROLE_ID_ADMIN)) {
return null;
}
return new DomainImpl(domainId);
}
}
private boolean isInRole(long roleId) {
for (int i = 0; i < token.getRolesCount(); i++) {
if (roleId == token.getRoles(i)) {
return true;
}
}
return false;
}
private boolean isInDomainRole(long roleId) {
for (int i = 0; i < token.getDomainRolesCount(); i++) {
if (roleId == token.getDomainRoles(i)) {
return true;
}
}
return false;
}
static class DomainImpl implements Domain {
final long id;
public DomainImpl(long id) {
this.id = id;
}
@Override
public long getId() {
return id;
}
}
public TokenScope getTokenScope() {
return token.getTokenScope();
}
@Override
public boolean checkProject(long projectId) {
switch (getTokenScope()) {
case Domain: {
// Domain domainAdmin = findDomainAdmin();
// if (domainAdmin != null) {
// return false;
// }
log.warn("Attempt to use domain token for project access: not supported");
throw new UnsupportedOperationException();
}
case Project: {
return token.getProjectId() == projectId;
}
case Unscoped:
log.debug("Attempt to use unscoped token for project access: denied");
return false;
}
throw new IllegalStateException();
}
public static boolean hasExpired(TokenInfo tokenInfo) {
if (!tokenInfo.hasExpiration()) {
if (isServiceToken(tokenInfo)) {
// Service tokens are allowed not to expire
return false;
} else {
log.warn("Token did not have expiration time; defensively treating as expired");
return true;
}
}
long expiration = tokenInfo.getExpiration();
long now = System.currentTimeMillis() / 1000L;
return expiration < now;
}
private static boolean isServiceToken(TokenInfo tokenInfo) {
return tokenInfo.getServiceToken();
}
@Override
public User getUser() {
if (token.hasUserId()) {
return new User(token.getUserId());
}
return null;
}
@Override
public Project getProject() {
if (token.hasProjectId()) {
return new Project(token.getProjectId());
}
return null;
}
public TokenInfo getTokenInfo() {
return token;
}
public static Date getExpiration(TokenInfo tokenInfo) {
long expiration = tokenInfo.getExpiration();
expiration *= 1000L;
return new Date(expiration);
}
@Override
public String toString() {
return "TokenAuth [userId=" + token.getUserId() + "]";
}
}