package org.hadatac.console.controllers.triplestore;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import play.*;
import play.data.Form;
import play.mvc.*;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.RDFDataMgr;
import org.hadatac.console.controllers.AuthApplication;
import org.hadatac.console.providers.MyUsernamePasswordAuthProvider;
import org.hadatac.console.http.PermissionQueries;
import org.hadatac.console.http.SolrUtils;
import org.hadatac.console.models.UserPreRegistrationForm;
import org.hadatac.console.models.GroupRegistrationForm;
import org.hadatac.console.models.LinkedAccount;
import org.hadatac.console.models.SparqlQueryResults;
import org.hadatac.console.models.TripleDocument;
import org.hadatac.console.views.html.triplestore.*;
import org.hadatac.console.models.SysUser;
import org.hadatac.console.models.TokenAction;
import org.hadatac.entity.pojo.User;
import org.hadatac.entity.pojo.UserGroup;
import org.hadatac.metadata.loader.PermissionsContext;
import org.hadatac.metadata.loader.RDFContext;
import org.hadatac.metadata.loader.SpreadsheetProcessing;
import org.hadatac.metadata.loader.ValueCellProcessing;
import org.hadatac.utils.Collections;
import org.hadatac.utils.Feedback;
import org.hadatac.utils.NameSpaces;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import be.objectify.deadbolt.java.actions.Group;
import be.objectify.deadbolt.java.actions.Restrict;
public class UserManagement extends Controller {
private static final String UPLOAD_NAME = "tmp/uploads/users-spreadsheet.xls";
private static final String UPLOAD_NAME_TTL = "tmp/uploads/user-graph.ttl";
private static final String UPLOAD_NAME_JSON = "tmp/uploads/user-auth.json";
public static String getSpreadSheetPath(){
return UPLOAD_NAME;
}
public static String getTurtlePath(){
return UPLOAD_NAME_TTL;
}
public static String getJsonPath(){
return UPLOAD_NAME_JSON;
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result index(String oper) {
return ok(users.render(oper, "", User.find(), UserGroup.find(), ""));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postIndex(String oper) {
return index(oper);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result onLinePreRegistration(String oper) {
return ok(preregister.render(oper, UserGroup.find()));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postOnLinePreRegistration(String oper) {
return onLinePreRegistration(oper);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result onLineGroupRegistration(String oper) {
return ok(preregisterGroup.render(oper, UserGroup.find()));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postOnLineGroupRegistration(String oper) {
return onLineGroupRegistration(oper);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result grantAdminPermission(String user_uri) {
try {
user_uri = URLDecoder.decode(user_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
SysUser su = SysUser.findByEmail(User.find(user_uri).getEmail());
if(su != null){
su.addSecurityRole(AuthApplication.DATA_MANAGER_ROLE);
su.save();
}
return redirect(routes.UserManagement.index("init"));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postGrantAdminPermission(String user_uri) {
return grantAdminPermission(user_uri);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result revokeAdminPermission(String user_uri) {
try {
user_uri = URLDecoder.decode(user_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
SysUser su = SysUser.findByEmail(User.find(user_uri).getEmail());
if(su != null){
su.removeSecurityRole(AuthApplication.DATA_MANAGER_ROLE);
su.save();
}
return redirect(routes.UserManagement.index("init"));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postRevokeAdminPermission(String user_uri) {
return revokeAdminPermission(user_uri);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result assignUserAccessLevel(String user_uri, String group_uri) {
User.changeAccessLevel(user_uri, group_uri);
return ok(users.render("init", "", User.find(), UserGroup.find(), ""));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postAssignUserAccessLevel(String user_uri, String group_uri) {
User.changeAccessLevel(user_uri, group_uri);
return ok(users.render("init", "", User.find(), UserGroup.find(), ""));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result editGroup(String group_uri) {
try {
group_uri = URLDecoder.decode(group_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(UserGroup.find().size());
return ok(editregisterGroup.render("edit", UserGroup.find(), UserGroup.find(group_uri)));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postEditGroup(String group_uri) {
try {
group_uri = URLDecoder.decode(group_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ok(editregisterGroup.render("edit", UserGroup.find(), UserGroup.find(group_uri)));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result editUser(String user_uri) {
try {
user_uri = URLDecoder.decode(user_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ok(editregister.render("edit", UserGroup.find(), User.find(user_uri)));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postEditUser(String user_uri) {
try {
user_uri = URLDecoder.decode(user_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ok(editregister.render("edit", UserGroup.find(), User.find(user_uri)));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result deleteUser(String user_uri, boolean deleteAuth, boolean deleteMember) {
try {
user_uri = URLDecoder.decode(user_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
User.deleteUser(user_uri, deleteAuth, deleteMember);
return redirect(routes.UserManagement.index("init"));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postDeleteUser(String user_uri, boolean deleteAuth, boolean deleteMember) {
return deleteUser(user_uri, deleteAuth, deleteMember);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result backupUserAuthentication() {
JSONArray sys_user = (JSONArray) JSONValue.parse(SysUser.outputAsJson());
for (int i = 0; i < sys_user.size(); i++) {
((JSONObject)sys_user.get(i)).remove("_version_");
}
JSONArray linked_account = (JSONArray) JSONValue.parse(LinkedAccount.outputAsJson());
for (int i = 0; i < linked_account.size(); i++) {
((JSONObject)linked_account.get(i)).remove("_version_");
}
JSONArray token = (JSONArray) JSONValue.parse(TokenAction.outputAsJson());
for (int i = 0; i < token.size(); i++) {
((JSONObject)token.get(i)).remove("_version_");
}
HashMap<String,Object> combined = new HashMap<String,Object>();
combined.put("sys_user", sys_user);
combined.put("linked_account", linked_account);
combined.put("token", token);
File ret_file = new File(getJsonPath());
try {
FileUtils.writeStringToFile(ret_file, new JSONObject(combined).toJSONString());
} catch (IOException e) {
e.printStackTrace();
}
return ok(ret_file);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static String recoverUserAuthentication() {
System.out.println("Recovering User Authentication ...");
try {
if (!SolrUtils.clearCollection(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS)) {
return "Failed to clear original \"users\" collection! ";
}
if (!SolrUtils.clearCollection(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_ACCOUNTS)) {
return "Failed to clear original \"linked_account\" collection! ";
}
if (!SolrUtils.clearCollection(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_TOKENS)) {
return "Failed to clear original \"token_action\" collection! ";
}
JSONObject combined = (JSONObject) JSONValue.parse(new FileReader(UPLOAD_NAME_JSON));
if (!SolrUtils.commitJsonDataToSolr(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS, combined.get("sys_user").toString())) {
return "Failed to recover \"users\" collection! ";
}
if (!SolrUtils.commitJsonDataToSolr(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_ACCOUNTS, combined.get("linked_account").toString())) {
return "Failed to recover \"linked_account\" collection! ";
}
if (!SolrUtils.commitJsonDataToSolr(Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_TOKENS, combined.get("token").toString())) {
return "Failed to recover \"token_action\" collection! ";
}
} catch (FileNotFoundException e) {
return "Failed to find uploaded json file! ";
}
return "Successfully recovered user authentications! ";
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postBackupUserAuthentication() {
return backupUserAuthentication();
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result backupUserGraph() {
return ok(User.outputAsTurtle());
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postBackupUserGraph() {
return backupUserGraph();
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result sendInvitationEmail(String user_name, String user_email) {
MyUsernamePasswordAuthProvider.getProvider().sendInvitationMailing(
user_name, user_email, ctx());
return redirect(routes.UserManagement.index("init"));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result postSendInvitationEmail(String user_name, String user_email) {
return sendInvitationEmail(user_name, user_email);
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static Result submitPreRegistrationForm(String oper) {
return ok(users.render(oper, "", User.find(), UserGroup.find(), "form"));
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static String commitUserPreRegistration(String source) {
System.out.println("Adding pre-registered user...");
int mode = Feedback.WEB;
String oper = "load";
String message = "";
PermissionsContext rdf = new PermissionsContext(
"user",
"password",
Play.application().configuration().getString("hadatac.solr.permissions"),
false);
if(source.equals("batch")){
message = SpreadsheetProcessing.generateTTL(mode, oper, rdf, UPLOAD_NAME);
}
else if(source.equals("form")){
Form<UserPreRegistrationForm> form = Form.form(UserPreRegistrationForm.class).bindFromRequest();
UserPreRegistrationForm data = form.get();
String usr_uri = data.getUserUri();
String given_name = data.getGivenName();
String family_name = data.getFamilyName();
String comment = data.getComment();
String email = data.getEmail();
String homepage = data.getHomepage();
String group_uri = data.getGroupUri();
Map<String, String> pred_value_map = new HashMap<String, String>();
pred_value_map.put("a", "foaf:Person, prov:Person");
pred_value_map.put("foaf:name", given_name + " " + family_name);
pred_value_map.put("foaf:familyName", family_name);
pred_value_map.put("foaf:givenName", given_name);
pred_value_map.put("rdfs:comment", comment);
pred_value_map.put("foaf:mbox", email);
pred_value_map.put("foaf:homepage", "<" + homepage + ">");
pred_value_map.put("hadatac:isMemberOfGroup", group_uri);
deleteUser(usr_uri, false, false);
message = generateTTL(mode, oper, rdf, usr_uri, pred_value_map);
}
return message;
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static String commitGroupRegistration(String source) {
System.out.println("Adding registered group...");
int mode = Feedback.WEB;
String oper = "load";
String message = "";
PermissionsContext rdf = new PermissionsContext(
"user",
"password",
Play.application().configuration().getString("hadatac.solr.permissions"),
false);
if(source.equals("batch")){
message = SpreadsheetProcessing.generateTTL(mode, oper, rdf, UPLOAD_NAME);
}
else if(source.equals("form")){
Form<GroupRegistrationForm> form = Form.form(GroupRegistrationForm.class).bindFromRequest();
GroupRegistrationForm data = form.get();
String group_uri = data.getGroupUri();
String group_name = data.getGroupName();
String comment = data.getComment();
String homepage = data.getHomepage();
String parent_group_uri = data.getParentGroupUri();
Map<String, String> pred_value_map = new HashMap<String, String>();
pred_value_map.put("a", "foaf:Group, prov:Group");
pred_value_map.put("foaf:name", group_name);
pred_value_map.put("rdfs:comment", comment);
pred_value_map.put("foaf:homepage", "<" + homepage + ">");
pred_value_map.put("hadatac:isMemberOfGroup", parent_group_uri);
deleteUser(group_uri, false, false);
message = generateTTL(mode, oper, rdf, group_uri, pred_value_map);
}
return message;
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static String commitUserGraphRegistration() {
System.out.println("Adding pre-registered user...");
int mode = Feedback.WEB;
String message = "";
PermissionsContext rdf = new PermissionsContext(
"user",
"password",
Play.application().configuration().getString("hadatac.solr.permissions"),
false);
try {
Model model = RDFDataMgr.loadModel(UPLOAD_NAME_TTL);
message += Feedback.println(mode, " ");
message += Feedback.print(mode, "SUCCESS parsing the document!");
message += Feedback.println(mode, " ");
} catch (Exception e) {
message += Feedback.println(mode, " ");
message += Feedback.print(mode, "ERROR parsing the document!");
message += Feedback.println(mode, " ");
message += e.getMessage();
message += Feedback.println(mode, " ");
message += Feedback.println(mode, " ");
message += Feedback.println(mode, "==== TURTLE (TTL) UPLOADED ====");
return message;
}
message += Feedback.print(mode, " Uploading generated file.");
rdf.loadLocalFile(mode, UPLOAD_NAME_TTL, SpreadsheetProcessing.KB_FORMAT);
message += Feedback.println(mode, "");
message += Feedback.println(mode, " ");
message += Feedback.println(mode, " Triples after [preregistration]: " + rdf.totalTriples());
return message;
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
public static String generateTTL(int mode, String oper, RDFContext rdf,
String uri, Map<String, String> pred_value_map){
String message = "";
message += Feedback.println(mode, " Triples before [preregistration]: " + rdf.totalTriples());
message += Feedback.println(mode, " ");
String ttl = NameSpaces.getInstance().printTurtleNameSpaceList();
ttl = ttl + "# properties: ";
for(String key : pred_value_map.keySet()){
ttl = ttl + "[" + key + "] ";
}
ttl = ttl + "\n\n";
ValueCellProcessing.validateNameSpace("hasURI");
ttl = ttl + ValueCellProcessing.execCellValue(uri, "hasURI");
for(String key : pred_value_map.keySet()){
String value = pred_value_map.get(key);
ValueCellProcessing.validateNameSpace(key);
ttl = ttl + ValueCellProcessing.execCellValue(value, key);
ttl = ttl + "\n";
}
System.out.println(ttl);
String fileName = "";
try {
String timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
fileName = SpreadsheetProcessing.TTL_DIR + "HASNetO-" + timeStamp + ".ttl";
FileUtils.writeStringToFile(new File(fileName), ttl);
} catch (IOException e) {
message += e.getMessage();
return message;
}
String listing = "";
try {
listing = URLEncoder.encode(SpreadsheetProcessing.printFileWithLineNumber(mode, fileName), "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
message += Feedback.println(mode, " ");
message += Feedback.println(mode, " Generated " + fileName + " and stored locally.");
try {
Model model = RDFDataMgr.loadModel(fileName);
message += Feedback.println(mode, " ");
message += Feedback.print(mode, "SUCCESS parsing the document!");
message += Feedback.println(mode, " ");
} catch (Exception e) {
message += Feedback.println(mode, " ");
message += Feedback.print(mode, "ERROR parsing the document!");
message += Feedback.println(mode, " ");
message += e.getMessage();
message += Feedback.println(mode, " ");
message += Feedback.println(mode, " ");
message += Feedback.println(mode, "==== TURTLE (TTL) CODE GENERATED FROM THE SPREADSHEET ====");
message += listing;
return message;
}
if (oper.equals("load")) {
message += Feedback.print(mode, " Uploading generated file.");
rdf.loadLocalFile(mode, fileName, SpreadsheetProcessing.KB_FORMAT);
message += Feedback.println(mode, "");
message += Feedback.println(mode, " ");
message += Feedback.println(mode, " Triples after [preregistration]: " + rdf.totalTriples());
}
return message;
}
@Restrict(@Group(AuthApplication.DATA_MANAGER_ROLE))
@BodyParser.Of(value = BodyParser.MultipartFormData.class, maxLength = 500 * 1024 * 1024)
public static Result uploadFile(String file_type) {
MultipartFormData body = request().body().asMultipartFormData();
FilePart uploadedfile = body.getFile("pic");
if (uploadedfile != null) {
File file = uploadedfile.getFile();
String file_name = "";
if(file_type.equals("xls")){
file_name = UPLOAD_NAME;
}
else if(file_type.equals("ttl")){
file_name = UPLOAD_NAME_TTL;
}
else if(file_type.equals("json")){
file_name = UPLOAD_NAME_JSON;
}
File newFile = new File(file_name);
InputStream fileInputStream;
try {
fileInputStream = new FileInputStream(file);
byte[] byteFile = IOUtils.toByteArray(fileInputStream);
FileUtils.writeByteArrayToFile(newFile, byteFile);
fileInputStream.close();
} catch (Exception e) {
return ok (users.render("fail", "Could not find uploaded file", User.find(), UserGroup.find(), ""));
}
if(file_type.equals("ttl")) {
System.out.println("Uploaded turtle file!");
return ok(users.render("loaded", "File uploaded successfully.", User.find(), UserGroup.find(), "turtle"));
}
else if(file_type.equals("json")) {
System.out.println("Uploaded json file!");
return ok(users.render("loaded", "File uploaded successfully.", User.find(), UserGroup.find(), "json"));
}
else {
return ok(users.render("loaded", "File uploaded successfully.", User.find(), UserGroup.find(), "batch"));
}
}
else {
return ok (users.render("fail", "Error uploading file. Please try again.", User.find(), UserGroup.find(), ""));
}
}
public static boolean isPreRegistered(String email) {
String json = PermissionQueries.exec(PermissionQueries.PERMISSION_BY_EMAIL, email);
SparqlQueryResults results = new SparqlQueryResults(json, false);
if (results == null || !results.sparqlResults.values().iterator().hasNext())
return false;
TripleDocument docPermission = results.sparqlResults.values().iterator().next();
String uri = docPermission.get("uri");
if (uri != null && !uri.equals("")) {
return true;
}
return false;
}
public static String getUriByEmail(String email) {
String json = PermissionQueries.exec(PermissionQueries.PERMISSION_BY_EMAIL, email);
SparqlQueryResults results = new SparqlQueryResults(json, false);
if (results == null
|| results.sparqlResults == null
|| !results.sparqlResults.values().iterator().hasNext()){
return null;
}
TripleDocument docPermission = results.sparqlResults.values().iterator().next();
String uri = docPermission.get("uri");
return uri;
}
}