Commit cd8c8bd4 authored by redmitry@list.ru's avatar redmitry@list.ru

protect Challenge collection

parent 1c1d6538
......@@ -286,4 +286,43 @@ public class OpenEBenchService {
return Response.ok(dataset, MediaType.APPLICATION_JSON).build();
}
@GET
@Path("/Challenge")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getChallenges(@Context SecurityContext sc) {
StreamingOutput stream = (OutputStream out) -> {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))) {
dao.getChallenges(writer, sc);
} catch(Exception ex) {
Logger.getLogger(OpenEBenchService.class.getName()).log(Level.SEVERE, null, ex);
}
};
return Response.ok(stream, MediaType.APPLICATION_JSON).build();
}
@GET
@Path("/Challenge/{id : .*}")
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public Response getChallenges(@Context SecurityContext sc,
@PathParam("id")
@Parameter(description = "challenge id",
example = "OEBX00200001FO")
@Encoded final String id) {
final String challenge = dao.getChallenge(id, sc);
if (challenge == null) {
return Response.status(Status.NOT_FOUND).build();
}
if ("{}".equals(challenge)) {
return Response.status(Status.UNAUTHORIZED).build();
}
return Response.ok(challenge, MediaType.APPLICATION_JSON).build();
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest.dao;
import com.mongodb.DBCollection;
......@@ -172,6 +197,66 @@ public class Database {
}
}
public String getChallenge(final String id, final SecurityContext sc) {
try {
final MongoDatabase mdb = mc.getDatabase(uri.getDatabase());
final MongoCollection<Document> challenges = mdb.getCollection("Challenge");
final MongoCollection<Document> events = mdb.getCollection("BenchmarkingEvent");
final Document challenge = challenges.find(Filters.eq("_id", id)).first();
if (challenge != null && checkChallengeAccess(challenge, sc, events)) {
challenge.remove("@provenance");
return challenge.toJson();
}
return "{}";
} catch(Exception ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public void getChallenges(final Writer writer, final SecurityContext sc) {
try {
MongoDatabase mdb = mc.getDatabase(uri.getDatabase());
final MongoCollection<Document> challenges = mdb.getCollection("Challenge");
final MongoCollection<Document> events = mdb.getCollection("BenchmarkingEvent");
final JsonWriter jwriter = new ReusableJsonWriter(writer);
try {
jwriter.writeStartArray();
final DocumentCodec codec = new DocumentCodec() {
@Override
public void encode(BsonWriter writer,
Document document,
EncoderContext encoderContext) {
super.encode(jwriter, document, encoderContext);
}
};
final Map<String, String> mcommunities = new HashMap<>();
FindIterable<Document> iter = challenges.find();
try (MongoCursor<Document> cursor = iter.iterator()) {
loop:
while (cursor.hasNext()) {
final Document challenge = cursor.next();
if (checkChallengeAccess(challenge, sc, events, mcommunities)) {
challenge.remove("@provenance");
challenge.toJson(codec);
}
}
}
} finally {
jwriter.writeEndArray();
jwriter.close();
}
} catch(Exception ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getDataset(final String id, final SecurityContext sc) {
try {
final MongoDatabase mdb = mc.getDatabase(uri.getDatabase());
......@@ -240,6 +325,38 @@ public class Database {
}
}
private boolean checkChallengeAccess(final Document challenge, final SecurityContext sc,
final MongoCollection<Document> events) {
return checkChallengeAccess(challenge, sc, events, null);
}
private boolean checkChallengeAccess(final Document challenge, final SecurityContext sc,
final MongoCollection<Document> events, final Map<String, String> mcommunities) {
if (sc.isUserInRole(Roles.ADMIN)) {
return true;
}
final String challenge_id = challenge.getString("_id");
if (sc.isUserInRole(Roles.CONTRIBUTOR + ":" + challenge_id) ||
sc.isUserInRole(Roles.MANAGER + ":" + challenge_id)) {
return true;
}
final String community_id = getCommunityId(challenge, events);
if (community_id == null) {
return false;
}
if (mcommunities != null) {
mcommunities.put(challenge_id, community_id);
}
return sc.isUserInRole(Roles.OWNER + ":" + community_id);
}
/**
* Check the access to the dataset according provided security context.
*
......@@ -252,9 +369,13 @@ public class Database {
* @return true if access is granted, false otherwise
*/
private boolean checkDatasetAccess(final Document dataset, final SecurityContext sc,
final MongoCollection<Document> challenges, MongoCollection<Document> events,
final MongoCollection<Document> challenges, final MongoCollection<Document> events,
final Map<String, String> mcommunities) {
if (sc.isUserInRole(Roles.ADMIN)) {
return true;
}
final String visibility = dataset.getString("visibility");
if ("public".equals(visibility)) {
return true;
......@@ -262,8 +383,8 @@ public class Database {
final List<String> challenge_ids = dataset.get("challenge_ids", List.class);
for (String challenge_id : challenge_ids) {
if (("participant".equals(visibility) &&
sc.isUserInRole("contributor:" + challenge_id)) ||
sc.isUserInRole("manager:" + challenge_id)) {
sc.isUserInRole(Roles.CONTRIBUTOR + ":" + challenge_id)) ||
sc.isUserInRole(Roles.MANAGER + ":" + challenge_id)) {
return true;
}
String community_id = mcommunities.get(challenge_id);
......@@ -272,28 +393,43 @@ public class Database {
if (challenge == null) {
continue;
}
final String benchmarking_event_id = challenge.getString("benchmarking_event_id");
if (benchmarking_event_id == null) {
continue;
}
final Document event = events.find(Filters.eq("_id", benchmarking_event_id)).first();
if (event == null) {
continue;
}
community_id = event.getString("community_id");
community_id = getCommunityId(challenge, events);
if (community_id == null) {
continue;
}
mcommunities.put(challenge_id, community_id);
}
if (sc.isUserInRole("owner:" + community_id)) {
if (sc.isUserInRole(Roles.OWNER + ":" + community_id)) {
return true;
}
}
}
return false;
}
/**
* Find the 'Community' associated to the 'Challenge'.
*
* @param challenge 'Challenge' JSON document
* @param events MongoDB 'BenchmarikingEvent' collection
*
* @return either the 'community_id' or 'null'
*/
private String getCommunityId(final Document challenge, final MongoCollection<Document> events) {
final String benchmarking_event_id = challenge.getString("benchmarking_event_id");
if (benchmarking_event_id == null) {
return null;
}
final Document event = events.find(Filters.eq("_id", benchmarking_event_id)).first();
if (event == null) {
return null;
}
return event.getString("community_id");
}
public static class ReusableJsonWriter extends JsonWriter {
public ReusableJsonWriter(Writer writer) {
......@@ -305,5 +441,4 @@ public class Database {
return true;
}
}
}
/**
* *****************************************************************************
* Copyright (C) 2020 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/
package es.bsc.inb.elixir.openebench.rest.dao;
/**
* @author Dmitry Repchevsky
*/
public final class Roles {
public final static String ADMIN = "admin:oeb";
public final static String OWNER = "owner";
public final static String MANAGER = "manager";
public final static String CONTRIBUTOR = "contributor";
public final static String PARTICIPANT = "participant";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment