package de.skuzzle.polly.core.internal.httpv2;
import java.util.List;
import java.util.Map;
import de.skuzzle.polly.http.annotations.Get;
import de.skuzzle.polly.http.annotations.OnRegister;
import de.skuzzle.polly.http.annotations.Param;
import de.skuzzle.polly.http.annotations.Post;
import de.skuzzle.polly.http.api.AlternativeAnswerException;
import de.skuzzle.polly.http.api.Controller;
import de.skuzzle.polly.http.api.answers.HttpAnswer;
import de.skuzzle.polly.sdk.MyPolly;
import de.skuzzle.polly.sdk.PersistenceManagerV2.Atomic;
import de.skuzzle.polly.sdk.PersistenceManagerV2.Write;
import de.skuzzle.polly.sdk.User;
import de.skuzzle.polly.sdk.UserManager;
import de.skuzzle.polly.sdk.exceptions.ConstraintException;
import de.skuzzle.polly.sdk.exceptions.DatabaseException;
import de.skuzzle.polly.sdk.exceptions.InvalidUserNameException;
import de.skuzzle.polly.sdk.exceptions.RoleException;
import de.skuzzle.polly.sdk.exceptions.UnknownUserException;
import de.skuzzle.polly.sdk.exceptions.UserExistsException;
import de.skuzzle.polly.sdk.httpv2.GsonHttpAnswer;
import de.skuzzle.polly.sdk.httpv2.PollyController;
import de.skuzzle.polly.sdk.httpv2.SuccessResult;
import de.skuzzle.polly.sdk.httpv2.WebinterfaceManager;
import de.skuzzle.polly.sdk.httpv2.html.HTMLTable;
import de.skuzzle.polly.sdk.roles.RoleManager;
public class UserController extends PollyController {
private final static String ADMIN_CATEGORY_KEY = "userAdminCategory"; //$NON-NLS-1$
private final static String USER_NAME_KEY = "userManagerPage"; //$NON-NLS-1$
private final static String USER_DESC_KEY = "userManagerDesc"; //$NON-NLS-1$
public final static String PAGE_USER_MANAGER = "/pages/users"; //$NON-NLS-1$
public final static String PAGE_EDIT_USER = "/pages/editUser"; //$NON-NLS-1$
private static final String CONTENT_USER_MANAGER = "templatesv2/users.html"; //$NON-NLS-1$
private static final String CONTENT_EDIT_USER = "templatesv2/edit.user.html"; //$NON-NLS-1$
public final static String API_DELETE_USER = "/api/deleteUser"; //$NON-NLS-1$
public final static String API_SET_PASSWORD = "api/setPassword"; //$NON-NLS-1$
public final static String API_ADD_USER = "/api/addUser"; //$NON-NLS-1$
public final static String API_SET_ATTRIBUTE = "api/setAttribute"; //$NON-NLS-1$
public final static String API_ADD_ROLE = "api/addRole"; //$NON-NLS-1$
public final static String API_REMOVE_ROLE = "api/removeRole"; //$NON-NLS-1$
public static void createUserTable(MyPolly myPolly) {
final HTMLTable<User> table = new HTMLTable<>("userList", //$NON-NLS-1$
new UserTableModel(myPolly.users()), myPolly);
myPolly.webInterface().getServer().addHttpEventHandler("/api/allUsers", table); //$NON-NLS-1$
}
public UserController(MyPolly myPolly) {
super(myPolly);
}
@Override
protected Controller createInstance() {
return new UserController(this.getMyPolly());
}
@Get(value = PAGE_USER_MANAGER, name = USER_NAME_KEY)
@OnRegister({
WebinterfaceManager.ADD_MENU_ENTRY,
MSG.FAMILY,
ADMIN_CATEGORY_KEY,
USER_DESC_KEY,
RoleManager.ADMIN_PERMISSION
})
public HttpAnswer users() throws AlternativeAnswerException {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
final Map<String, Object> c = this.createContext(CONTENT_USER_MANAGER);
c.put("users", this.getMyPolly().users().getRegisteredUsers()); //$NON-NLS-1$
return this.makeAnswer(c);
}
@Get(PAGE_EDIT_USER)
public HttpAnswer editUser(@Param("userId") int id)
throws AlternativeAnswerException {
final User user = this.getMyPolly().users().getUser(id);
if (user == null) {
// TODO:
}
if (this.getSessionUser() != user) {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
}
final Map<String, Object> c = this.createContext(CONTENT_EDIT_USER);
c.put("editUser", user); //$NON-NLS-1$
return this.makeAnswer(c);
}
@Get(API_DELETE_USER)
public HttpAnswer deleteUser(@Param("id") int id) throws AlternativeAnswerException {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
final UserManager um = this.getMyPolly().users();
final User user = um.getUser(id);
if (user == null) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userUnknownId, id)));
}
try {
um.deleteUser(user);
} catch (UnknownUserException ignore) {
// can not happen
throw new RuntimeException(ignore);
} catch (DatabaseException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.userDatebaseFail));
}
return new GsonHttpAnswer(200,
new SuccessResult(true, MSG.bind(MSG.userDeleteSuccess, user.getName())));
}
@Post(API_SET_PASSWORD)
public HttpAnswer setPassword(
@Param("userId") int userId,
@Param("newPassword") final String newPassword,
@Param("retype") String retype) throws DatabaseException, AlternativeAnswerException {
final User user = this.getSessionUser();
if (user == null || user.getId() != userId) {
// session has no id OR session user is not the edited user:
// then you need admin permissions to edit the attributes
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
}
final User target = this.getMyPolly().users().getUser(userId);
if (target == null) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userUnknownId, userId)));
} else if (!newPassword.equals(retype)) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.userPasswordMismatch));
} else {
this.getMyPolly().persistence().writeAtomic(new Atomic() {
@Override
public void perform(Write write) {
target.setPassword(newPassword);
}
});
return new GsonHttpAnswer(200,
new SuccessResult(true, MSG.userPasswordChanged));
}
}
@Post(API_ADD_USER)
public HttpAnswer addUser(
@Param("newName") String name,
@Param("newPassword") String password,
@Param(value = "initialRoles", typeHint = String.class) List<String> roles)
throws AlternativeAnswerException {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
final UserManager um = this.getMyPolly().users();
final RoleManager rm = this.getMyPolly().roles();
try {
final User newUser = um.addUser(name, password);
for (final String roleName : roles) {
rm.assignRole(newUser, roleName);
}
} catch (InvalidUserNameException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userInvalidFormat, name)));
} catch (UserExistsException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userAlreadyExists, name)));
} catch (DatabaseException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.userDatebaseFail));
} catch (RoleException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, e.getMessage()));
}
return new GsonHttpAnswer(200,
new SuccessResult(true, MSG.bind(MSG.userAdded, name)));
}
public final static class SetAttributeResult extends SuccessResult {
public String newValue;
public SetAttributeResult(boolean success, String msg, String newValue) {
super(success, msg);
this.newValue = newValue;
}
}
@Get(API_SET_ATTRIBUTE)
public HttpAnswer setAttribute(
@Param("userId") int userId,
@Param("attribute") String attribute,
@Param(value = "value", optional = true, defaultValue = "") String value)
throws AlternativeAnswerException {
final User user = this.getSessionUser();
final User target = this.getMyPolly().users().getUser(userId);
if (user == null || user != target) {
// session has no id OR session user is not the edited user:
// then you need admin permissions to edit the attributes
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
}
if (target == null) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userUnknownId, userId)));
}
try {
final String newValue = this.getMyPolly().users().setAttributeFor(
user, target, attribute, value);
return new GsonHttpAnswer(200,
new SetAttributeResult(true, "", newValue)); //$NON-NLS-1$
} catch (DatabaseException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.userDatebaseFail));
} catch (ConstraintException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false,
MSG.bind(MSG.userAttributeConstraintFail, value, attribute)));
}
}
@Get(API_ADD_ROLE)
public HttpAnswer addRole(
@Param("userId") int userId,
@Param("role") String role) throws AlternativeAnswerException {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
final User target = this.getMyPolly().users().getUser(userId);
if (target == null) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userUnknownId, userId)));
} else {
try {
this.getMyPolly().roles().assignRole(target, role);
return new GsonHttpAnswer(200, new SuccessResult(true, MSG.userRoleAdded));
} catch (RoleException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, e.getMessage()));
} catch (DatabaseException e) {
return new GsonHttpAnswer(200, new SuccessResult(false,
MSG.userDatebaseFail));
}
}
}
@Get(API_REMOVE_ROLE)
public HttpAnswer removeRole(
@Param("userId") int userId,
@Param("role") String role) throws AlternativeAnswerException {
this.requirePermissions(RoleManager.ADMIN_PERMISSION);
final User target = this.getMyPolly().users().getUser(userId);
if (target == null) {
return new GsonHttpAnswer(200,
new SuccessResult(false, MSG.bind(MSG.userUnknownId, userId)));
} else {
try {
if (target.isPollyAdmin() && role.equals(RoleManager.ADMIN_ROLE)) {
return new GsonHttpAnswer(200, new SuccessResult(false,
MSG.userCantRemoveAdminRole));
}
this.getMyPolly().roles().removeRole(target, role);
return new GsonHttpAnswer(200, new SuccessResult(true,
MSG.userRoleRemoved));
} catch (RoleException e) {
return new GsonHttpAnswer(200,
new SuccessResult(false, e.getMessage()));
} catch (DatabaseException e) {
return new GsonHttpAnswer(200, new SuccessResult(false,
MSG.userDatebaseFail));
}
}
}
}