Skip to content

Commit

Permalink
user management system, version 1.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
bvdmitri committed Apr 6, 2016
1 parent 68cd5fc commit c178a36
Show file tree
Hide file tree
Showing 22 changed files with 793 additions and 218 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ Default: ``1``
Default user name prefix.
Default: `vdjviz`

- ``userManagementSystem``
Enable user management (admin) panel for users with admin rights
Default: `true`

- ``userManagementSystemAccounts``
Specifies the list of user accounts with predefined emails and passwords that will be granted admin rights. The ``email`` and ``password`` properties in ``application.conf`` should be used to specify their credentials.

- ``db.default.url``
Points to the path that will be used to store H2 database file.
Default value: ``~/vdjviz/h2.db``
Expand Down
36 changes: 36 additions & 0 deletions app/Global.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

import java.io.File;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


Expand Down Expand Up @@ -123,6 +125,40 @@ public void onStart(Application app) {
}
}

if (Configuration.isUserManagementSystemEnabled()) {
UserService userService = new UserService(app);
String username = "administrator";
try {
List<Map<String, String>> userManagementSystemAccounts = Configuration.getUserManagementSystemAccounts();
for (Map<String, String> userManagementSystemAccount : userManagementSystemAccounts) {
String email = userManagementSystemAccount.get("email");
String password = userManagementSystemAccount.get("password");
LocalUser localUser = LocalUser.find.byId(email);
if (localUser != null) {
localUser.account.setPrivelegies(true);
localUser.account.update();
localUser.update();
} else {
Option<PasswordHasher> bcrypt = Registry.hashers().get("bcrypt");
SocialUser socialUser = new SocialUser(new IdentityId(email, "userpass"),
username, username, String.format("%s %s", username, username),
Option.apply(email), null, AuthenticationMethod.UserPassword(),
null, null, Some.apply(new PasswordInfo("bcrypt", BCrypt.hashpw(password, BCrypt.gensalt()), null))
);
userService.doSave(socialUser);
LocalUser localUser1 = LocalUser.find.byId(email);
localUser1.account.setPrivelegies(true);
localUser1.account.update();
localUser1.update();
}
Logger.info("Administrator user: " + email + " created.");
}
} catch (RuntimeException e) {
Logger.error("Error while creating admin users");
e.printStackTrace();
}
}

//Deleting empty files
for (Account account: Account.findAll()) {
for (UserFile userFile: account.getUserfiles()) {
Expand Down
18 changes: 9 additions & 9 deletions app/controllers/AccountAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public Result apply() throws Throwable {
if (file == null) {
return ok(Json.toJson(new ServerResponse("error", "You should upload the file first")));
}
if (account.getMaxFilesSize() > 0) {
if (account.getMaxFilesSize() != 0) {
Long sizeMB = file.getFile().length() / 1024;
if (sizeMB > account.getMaxFilesSize()) {
return ok(Json.toJson(new ServerResponse("error", "File is too large")));
Expand Down Expand Up @@ -616,23 +616,23 @@ private static Result rarefaction(Account account, Boolean needToCreateNew) thro
return ok(Json.toJson(new CacheServerResponse("success", rarefactionChart.create(needToCreateNew))));
}

public static class TagRequest {
public static class TagRequestClient {
public String description;
public String color;
public String tagName;
public long id;

public TagRequest() {}
public TagRequestClient() {}
}

public static Result createTag() {
Account account = getCurrentAccount();
JsonNode request = request().body().asJson();

TagRequest tagRequest;
TagRequestClient tagRequest;
try {
ObjectMapper objectMapper = new ObjectMapper();
tagRequest = objectMapper.convertValue(request, TagRequest.class);
tagRequest = objectMapper.convertValue(request, TagRequestClient.class);
} catch (Exception e) {
e.printStackTrace();
return badRequest(Json.toJson(new ServerResponse("error", "Invalid request")));
Expand All @@ -646,17 +646,17 @@ public static Result editTag() {
Account account = getCurrentAccount();
JsonNode request = request().body().asJson();

TagRequest tagRequest;
TagRequestClient tagRequest;
try {
ObjectMapper objectMapper = new ObjectMapper();
tagRequest = objectMapper.convertValue(request, TagRequest.class);
tagRequest = objectMapper.convertValue(request, TagRequestClient.class);
} catch (Exception e) {
e.printStackTrace();
return badRequest(Json.toJson(new ServerResponse("error", "Invalid request")));
}
Tag tag = Tag.findById(tagRequest.id, account);
if (tag == null) return badRequest(Json.toJson(new ServerResponse("error", "Invalid tag")));
tag.updateTag(tagRequest);
tag.updateTag(tagRequest.description, tagRequest.color, tagRequest.tagName);
return ok(Json.toJson(new Tag.TagInformation(tag)));
}

Expand Down Expand Up @@ -734,7 +734,7 @@ public void invoke(JsonNode event) {
sample = sampleFileConnection.getSample();
file.setSampleCount(sample.getDiversity(), sample.getCount());

if (account.getMaxClonotypesCount() > 0) {
if (account.getMaxClonotypesCount() != 0) {
if (file.getClonotypesCount() > account.getMaxClonotypesCount()) {
UserFile.deleteFile(file);
out.write(Json.toJson(new WSResponse("error", "render", fileName, "Number of clonotypes in a sample should be less than " + account.getMaxClonotypesCount())));
Expand Down
144 changes: 144 additions & 0 deletions app/controllers/AdministratorAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package controllers;

import com.fasterxml.jackson.databind.JsonNode;
import models.Account;
import models.LocalUser;
import org.mindrot.jbcrypt.BCrypt;
import play.Logger;
import play.Play;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Result;
import scala.Option;
import scala.Some;
import securesocial.core.*;
import securesocial.core.java.SecureSocial;
import securesocial.core.providers.utils.PasswordHasher;
import utils.UserService;
import utils.server.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* Created by bvdmitri on 06.04.16.
*/
@SecureSocial.SecuredAction
public class AdministratorAPI extends Controller {

private static Account getCurrentAccount() {
Identity user = (Identity) ctx().args.get(SecureSocial.USER_KEY);
LocalUser localUser = LocalUser.find.byId(user.identityId().userId());
return localUser.account;
}

private static String getAdministratorName() {
Identity user = (Identity) ctx().args.get(SecureSocial.USER_KEY);
return user.identityId().userId();
}

private static Boolean isAccessDenied() {
return !Configuration.isUserManagementSystemEnabled() || !getCurrentAccount().isPrivilege();
}

public static Result index() {
if (isAccessDenied()) {
return redirect("/");
}
return ok(views.html.administrator.index.render(getAdministratorName()));
}

public static Result getAllAccounts() {
if (isAccessDenied()) return badRequest();
List<Account.AccountInformation> accounts = new ArrayList<>();
for (Account account : Account.findAll()) {
accounts.add(Account.getAccountInformation(account));
}
return ok(Json.toJson(accounts));
}

public static Result deleteUser() {
if (isAccessDenied()) return badRequest("Access denied");
JsonNode request = request().body().asJson();
if (!request.has("userName")) {
return badRequest(Json.toJson("Empty user name"));
}
try {
Account account = Account.findByUserName(request.get("userName").asText());
if (account == null) return badRequest("Invalid user name");
account.deleteAccount();
return ok("Successfully deleted");
} catch (Exception e) {
e.printStackTrace();
return badRequest("Error while deleting");
}
}

public static Result createUser() {
if (isAccessDenied()) return badRequest("Access denied");
JsonNode request = request().body().asJson();
if (!request.has("userName") || !request.has("password")) return badRequest("Invalid request");
String userName = request.get("userName").asText();
String password = request.get("password").asText();
Integer maxFileSize = request.has("maxFileSize") ? request.get("maxFileSize").asInt() : Configuration.getMaxFileSize();
Integer maxFilesCount = request.has("maxFilesCount") ? request.get("maxFilesCount").asInt() : Configuration.getMaxFilesCount();
Integer maxClonotypesCount = request.has("maxClonotypesCount") ? request.get("maxClonotypesCount").asInt() : Configuration.getMaxClonotypesCount();
Integer maxSharedGroups = request.has("maxSharedFiles") ? request.get("maxSharedFiles").asInt() : Configuration.getMaxSharedGroups();
Boolean privelegies = request.has("privelegies") && request.get("privelegies").asBoolean();

UserService userService = new UserService(Play.application());
//Integer minimalPasswordLength = Play.application().configuration().getInt("securesocial.userpass.minimumPasswordLength");

//if (password.length() < minimalPasswordLength) return badRequest("Minimal password length: " + minimalPasswordLength);

try {
LocalUser localUser = LocalUser.find.byId(userName);
if (localUser != null) return badRequest("User " + userName + " already created");
Option<PasswordHasher> bcrypt = Registry.hashers().get("bcrypt");
SocialUser socialUser = new SocialUser(new IdentityId(userName, "userpass"),
userName, userName, String.format("%s %s", userName, userName),
Option.apply(userName), null, AuthenticationMethod.UserPassword(),
null, null, Some.apply(new PasswordInfo("bcrypt", BCrypt.hashpw(password, BCrypt.gensalt()), null))
);
userService.doSave(socialUser);
Account createdAccount = Account.findByUserName(userName);
createdAccount.setPrivelegies(privelegies);
createdAccount.setMaxClonotypesCount(maxClonotypesCount);
createdAccount.setMaxFilesCount(maxFilesCount);
createdAccount.setMaxFilesSize(maxFileSize);
createdAccount.setMaxSharedFiles(maxSharedGroups);
createdAccount.update();
createdAccount.save();
return ok("Successfully created");
} catch (RuntimeException e) {
Logger.error("Error while creating default users");
e.printStackTrace();
}
return ok();
}

public static Result editUser() {
if (isAccessDenied()) return badRequest("Access denied");
JsonNode request = request().body().asJson();
if (!request.has("userName")) return badRequest("Invalid request");
String oldUserName = request.get("userName").asText();
Account account = Account.findByUserName(oldUserName);
if (account == null) return badRequest("Invalid request");
Integer maxFileSize = request.has("maxFileSize") ? request.get("maxFileSize").asInt() : account.getMaxFilesSize();
Integer maxFilesCount = request.has("maxFilesCount") ? request.get("maxFilesCount").asInt() : account.getMaxFilesCount();
Integer maxClonotypesCount = request.has("maxClonotypesCount") ? request.get("maxClonotypesCount").asInt() : account.getMaxClonotypesCount();
Integer maxSharedGroups = request.has("maxSharedFiles") ? request.get("maxSharedFiles").asInt() : account.getMaxSharedFiles();
Boolean privelegies = request.has("privelegies") && request.get("privelegies").asBoolean();

account.setPrivelegies(privelegies);
account.setMaxClonotypesCount(maxClonotypesCount);
account.setMaxFilesCount(maxFilesCount);
account.setMaxFilesSize(maxFileSize);
account.setMaxSharedFiles(maxSharedGroups);
account.update();
account.save();
return ok("Successfully edited");
}

}
54 changes: 51 additions & 3 deletions app/models/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,16 @@ public static class AccountInformation {
public String userName;
public Boolean privelegies;
public Integer filesCount;
public Integer sharedGroupsCount;
public Integer maxSharedGroupsCount;
public FilesInformation filesInformation;
public List<Tag.TagInformation> tags;

public AccountInformation(Account account) {
this.userName = account.userName;
this.filesCount = account.getFilesCount();
this.maxSharedGroupsCount = account.getMaxSharedFiles();
this.sharedGroupsCount = SharedGroup.findByAccount(account).size();
this.filesInformation = getFilesInformation(account);
this.privelegies = account.isPrivilege();
this.tags = new ArrayList<>();
Expand Down Expand Up @@ -134,15 +138,15 @@ public Integer getMaxSharedFiles() {
}

public Boolean isMaxSharedGroupsCountExceeded() {
if (getMaxSharedFiles() > 0) {
if (getMaxSharedFiles() != 0) {
List<SharedGroup> byAccount = SharedGroup.findByAccount(this);
if (byAccount.size() >= getMaxSharedFiles()) return true;
}
return false;
}

public Boolean isMaxFilesCountExceeded() {
if (getMaxFilesCount() > 0) {
if (getMaxFilesCount() != 0) {
if (getFilesCount() > getMaxFilesCount()) {
return true;
}
Expand Down Expand Up @@ -214,13 +218,39 @@ public List<UserFile> getRenderedUserFiles() {
}

public long getMaxSampleCount() {
long max = 0l;
long max = 0L;
for (UserFile userFile : getRenderedUserFiles()) {
max = userFile.getSampleCount() > max ? userFile.getSampleCount() : max;
}
return max;
}



public void setUserName(String userName) {
this.userName = userName;
}

public void setMaxFilesSize(Integer maxFilesSize) {
this.maxFilesSize = maxFilesSize;
}

public void setMaxFilesCount(Integer maxFilesCount) {
this.maxFilesCount = maxFilesCount;
}

public void setMaxClonotypesCount(Integer maxClonotypesCount) {
this.maxClonotypesCount = maxClonotypesCount;
}

public void setMaxSharedFiles(Integer maxSharedFiles) {
this.maxSharedFiles = maxSharedFiles;
}

public void setPrivelegies(Boolean privelegies) {
this.privelegies = privelegies;
}

public String getUserName() {
return userName;
}
Expand All @@ -245,6 +275,24 @@ public String toString() {
return String.format("%s", userName);
}

public void deleteAccount() {
for (UserFile userfile : userfiles) {
UserFile.deleteFile(userfile);
}
for (Tag tag : Tag.findByAccount(this)) {
tag.deleteTag();
}
for (SharedGroup sharedGroup : SharedGroup.findByAccount(this)) {
sharedGroup.deleteGroup();
}
File userDirectory = new File(userDirPath);
userDirectory.delete();
user.account = null;
user.update();
this.delete();
user.delete();
}

public static List<Account> findAll() {
return find().all();
}
Expand Down
8 changes: 4 additions & 4 deletions app/models/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public void tagFiles(String[] selectedFiles) {
}
}

public void updateTag(AccountAPI.TagRequest tagRequest) {
this.color = tagRequest.color;
this.description = tagRequest.description;
this.tagName = tagRequest.tagName;
public void updateTag(String description, String color, String tagName) {
this.color = color;
this.description = description;
this.tagName = tagName;
this.update();
}

Expand Down
Loading

0 comments on commit c178a36

Please sign in to comment.