package org.gcube.data.access.storagehub.handlers; import static org.gcube.common.storagehub.model.Constants.enchriptedPrefix; import static org.gcube.common.storagehub.model.Constants.enchriptedVolatile; import static org.gcube.common.storagehub.model.Constants.versionPrefix; import java.util.Base64; import jakarta.inject.Singleton; import jakarta.servlet.ServletContext; import org.gcube.common.encryption.encrypter.StringEncrypter; import org.gcube.common.security.AuthorizedTasks; import org.gcube.common.security.secrets.Secret; import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.data.access.storagehub.types.LinkType; import org.gcube.data.access.storagehub.types.PublicLink; import org.gcube.smartgears.ContextProvider; @Singleton public class PublicLinkHandler { public String getForItem(String itemId, ServletContext context) throws BackendGenericError{ return getUrl(itemId, enchriptedPrefix, context); } public String getForVersionedItem(String itemId, String version, ServletContext context) throws BackendGenericError { return getUrl(String.format("%s%s%s",itemId, versionPrefix, version), enchriptedPrefix, context); } public String getForVolatile(String fileId, String storageName, ServletContext context) throws BackendGenericError { return getUrl(String.format("%s_%s",fileId, storageName), enchriptedVolatile, context); } public PublicLink resolveEnchriptedId(String enchriptedId) throws StorageHubException { String complexId = enchriptedId; boolean isVolatile = false; if (enchriptedId.startsWith(enchriptedPrefix) || enchriptedId.startsWith(enchriptedVolatile) ) { final String enchriptedValue = enchriptedId.startsWith(enchriptedPrefix) ? enchriptedPrefix : enchriptedVolatile; isVolatile = enchriptedId.startsWith(enchriptedVolatile); try { String infraContext = String.format("/%s", ContextProvider.get().container().configuration().infrastructure()); Secret infraSecret = ContextProvider.get().container().authorizationProvider().getSecretForContext(infraContext); complexId = AuthorizedTasks.executeSafely(() -> { return StringEncrypter.getEncrypter().decrypt( new String(Base64.getUrlDecoder().decode(enchriptedId.replace(enchriptedValue, "")))); }, infraSecret); }catch(Throwable e){ throw new BackendGenericError("invalid public url",e); } } if (isVolatile) { String[] volatileIdSplit = complexId.split("_"); return new VolatilePublicLink(volatileIdSplit[0], volatileIdSplit[1]); }else { if (complexId.contains(versionPrefix)) { String[] split = complexId.split(versionPrefix); String itemId = split[0]; String versionName = split[1]; return new ItemPublicLink(itemId, versionName); } else return new ItemPublicLink(complexId); } } private String getUrl(String toEnchript, String prefix, ServletContext context) throws BackendGenericError{ String infraContext = String.format("/%s", ContextProvider.get().container().configuration().infrastructure()); Secret infraSecret = ContextProvider.get().container().authorizationProvider().getSecretForContext(infraContext); try { String enchriptedQueryString = AuthorizedTasks.executeSafely( () -> {return StringEncrypter.getEncrypter().encrypt(toEnchript);},infraSecret); String basepath = context.getInitParameter("resolver-basepath"); String filePublicUrl = String.format("%s/%s%s",basepath, prefix, Base64.getUrlEncoder().encodeToString(enchriptedQueryString.getBytes())); return filePublicUrl; }catch (Throwable e) { throw new BackendGenericError("error encrypting item id",e ); } } public static class VolatilePublicLink implements PublicLink { private String storageKey; private String storageName; protected VolatilePublicLink(String storageKey, String storageName){ this.storageKey = storageKey; this.storageName = storageName; } @Override public LinkType getType() {return LinkType.VOLATILE;} @Override public String getId() { return storageKey; } @Override public String getStorageName() { return storageName; } } public static class ItemPublicLink implements PublicLink { private String itemId; private String version; private LinkType type; protected ItemPublicLink(String itemId){ this.itemId = itemId; this.type = LinkType.STANDARD; } protected ItemPublicLink(String itemId, String version){ this.itemId = itemId; this.version = version; this.type = LinkType.VERSIONED; } @Override public LinkType getType() {return type;} @Override public String getId() { return itemId; } @Override public String getVersion() { return version; } } }