forked from Qortal/qortal
Added /render/authorize/{service}/{resourceId}* APIs
These allow the UI to pre-authorize a resource and therefore avoid having to pass a sensitive API key to a website or app.
This commit is contained in:
parent
d0000c6131
commit
b4f3105035
@ -25,6 +25,7 @@ import org.qortal.api.Security;
|
|||||||
import org.qortal.arbitrary.misc.Service;
|
import org.qortal.arbitrary.misc.Service;
|
||||||
import org.qortal.arbitrary.*;
|
import org.qortal.arbitrary.*;
|
||||||
import org.qortal.arbitrary.exception.MissingDataException;
|
import org.qortal.arbitrary.exception.MissingDataException;
|
||||||
|
import org.qortal.controller.arbitrary.ArbitraryDataRenderManager;
|
||||||
import org.qortal.data.transaction.ArbitraryTransactionData.*;
|
import org.qortal.data.transaction.ArbitraryTransactionData.*;
|
||||||
import org.qortal.repository.DataException;
|
import org.qortal.repository.DataException;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
@ -94,11 +95,34 @@ public class RenderResource {
|
|||||||
return "Unable to generate preview URL";
|
return "Unable to generate preview URL";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("authorize/{service}/{resourceId}")
|
||||||
|
@SecurityRequirement(name = "apiKey")
|
||||||
|
public boolean authorizeResource(@PathParam("service") Service service,
|
||||||
|
@PathParam("resourceId") String resourceId) {
|
||||||
|
Security.checkApiCallAllowed(request);
|
||||||
|
ArbitraryDataResource resource = new ArbitraryDataResource(resourceId, null, service, null);
|
||||||
|
ArbitraryDataRenderManager.getInstance().addToAuthorizedResources(resource);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("authorize/{service}/{resourceId}/{identifier}")
|
||||||
|
@SecurityRequirement(name = "apiKey")
|
||||||
|
public boolean authorizeResource(@PathParam("service") Service service,
|
||||||
|
@PathParam("resourceId") String resourceId,
|
||||||
|
@PathParam("identifier") String identifier) {
|
||||||
|
Security.checkApiCallAllowed(request);
|
||||||
|
ArbitraryDataResource resource = new ArbitraryDataResource(resourceId, null, service, identifier);
|
||||||
|
ArbitraryDataRenderManager.getInstance().addToAuthorizedResources(resource);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/signature/{signature}")
|
@Path("/signature/{signature}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getIndexBySignature(@PathParam("signature") String signature) {
|
public HttpServletResponse getIndexBySignature(@PathParam("signature") String signature) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(signature, Service.WEBSITE, null);
|
||||||
return this.get(signature, ResourceIdType.SIGNATURE, null, "/", null, "/render/signature", true, true);
|
return this.get(signature, ResourceIdType.SIGNATURE, null, "/", null, "/render/signature", true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +130,7 @@ public class RenderResource {
|
|||||||
@Path("/signature/{signature}/{path:.*}")
|
@Path("/signature/{signature}/{path:.*}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getPathBySignature(@PathParam("signature") String signature, @PathParam("path") String inPath) {
|
public HttpServletResponse getPathBySignature(@PathParam("signature") String signature, @PathParam("path") String inPath) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(signature, Service.WEBSITE, null);
|
||||||
return this.get(signature, ResourceIdType.SIGNATURE, null, inPath,null, "/render/signature", true, true);
|
return this.get(signature, ResourceIdType.SIGNATURE, null, inPath,null, "/render/signature", true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +138,7 @@ public class RenderResource {
|
|||||||
@Path("/hash/{hash}")
|
@Path("/hash/{hash}")
|
||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getIndexByHash(@PathParam("hash") String hash58, @QueryParam("secret") String secret58) {
|
public HttpServletResponse getIndexByHash(@PathParam("hash") String hash58, @QueryParam("secret") String secret58) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(hash58, Service.WEBSITE, null);
|
||||||
return this.get(hash58, ResourceIdType.FILE_HASH, Service.WEBSITE, "/", secret58, "/render/hash", true, false);
|
return this.get(hash58, ResourceIdType.FILE_HASH, Service.WEBSITE, "/", secret58, "/render/hash", true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +147,7 @@ public class RenderResource {
|
|||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getPathByHash(@PathParam("hash") String hash58, @PathParam("path") String inPath,
|
public HttpServletResponse getPathByHash(@PathParam("hash") String hash58, @PathParam("path") String inPath,
|
||||||
@QueryParam("secret") String secret58) {
|
@QueryParam("secret") String secret58) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(hash58, Service.WEBSITE, null);
|
||||||
return this.get(hash58, ResourceIdType.FILE_HASH, Service.WEBSITE, inPath, secret58, "/render/hash", true, false);
|
return this.get(hash58, ResourceIdType.FILE_HASH, Service.WEBSITE, inPath, secret58, "/render/hash", true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +157,7 @@ public class RenderResource {
|
|||||||
public HttpServletResponse getPathByName(@PathParam("service") Service service,
|
public HttpServletResponse getPathByName(@PathParam("service") Service service,
|
||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@PathParam("path") String inPath) {
|
@PathParam("path") String inPath) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(name, service, null);
|
||||||
String prefix = String.format("/render/%s", service);
|
String prefix = String.format("/render/%s", service);
|
||||||
return this.get(name, ResourceIdType.NAME, service, inPath, null, prefix, true, true);
|
return this.get(name, ResourceIdType.NAME, service, inPath, null, prefix, true, true);
|
||||||
}
|
}
|
||||||
@ -143,7 +167,7 @@ public class RenderResource {
|
|||||||
@SecurityRequirement(name = "apiKey")
|
@SecurityRequirement(name = "apiKey")
|
||||||
public HttpServletResponse getIndexByName(@PathParam("service") Service service,
|
public HttpServletResponse getIndexByName(@PathParam("service") Service service,
|
||||||
@PathParam("name") String name) {
|
@PathParam("name") String name) {
|
||||||
Security.checkApiCallAllowed(request);
|
requirePriorAuthorization(name, service, null);
|
||||||
String prefix = String.format("/render/%s", service);
|
String prefix = String.format("/render/%s", service);
|
||||||
return this.get(name, ResourceIdType.NAME, service, "/", null, prefix, true, true);
|
return this.get(name, ResourceIdType.NAME, service, "/", null, prefix, true, true);
|
||||||
}
|
}
|
||||||
@ -176,4 +200,11 @@ public class RenderResource {
|
|||||||
return renderer.render();
|
return renderer.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requirePriorAuthorization(String resourceId, Service service, String identifier) {
|
||||||
|
ArbitraryDataResource resource = new ArbitraryDataResource(resourceId, null, service, identifier);
|
||||||
|
if (!ArbitraryDataRenderManager.getInstance().isAuthorized(resource)) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.UNAUTHORIZED, "Call /render/authorize first");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,23 @@ public class ArbitraryDataResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resourceIdString() {
|
||||||
|
return resourceId != null ? resourceId : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resourceIdTypeString() {
|
||||||
|
return resourceIdType != null ? resourceIdType.toString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serviceString() {
|
||||||
|
return service != null ? service.toString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
private String identifierString() {
|
private String identifierString() {
|
||||||
return identifier != null ? identifier : "";
|
return identifier != null ? identifier : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s-%s-%s-%s", resourceIdString(), resourceIdTypeString(), serviceString(), identifierString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package org.qortal.controller.arbitrary;
|
||||||
|
|
||||||
|
import org.qortal.arbitrary.ArbitraryDataFile;
|
||||||
|
import org.qortal.arbitrary.ArbitraryDataResource;
|
||||||
|
import org.qortal.arbitrary.misc.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class ArbitraryDataRenderManager {
|
||||||
|
|
||||||
|
private static ArbitraryDataRenderManager instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List to keep track of authorized resources for rendering.
|
||||||
|
*/
|
||||||
|
private List<ArbitraryDataResource> authorizedResources = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
|
||||||
|
public ArbitraryDataRenderManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArbitraryDataRenderManager getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new ArbitraryDataRenderManager();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthorized(ArbitraryDataResource resource) {
|
||||||
|
for (ArbitraryDataResource authorizedResource : this.authorizedResources) {
|
||||||
|
if (authorizedResource != null && resource != null) {
|
||||||
|
if (Objects.equals(authorizedResource.toString(), resource.toString())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToAuthorizedResources(ArbitraryDataResource resource) {
|
||||||
|
if (!this.isAuthorized(resource)) {
|
||||||
|
this.authorizedResources.add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user