package controllers;
import com.fasterxml.jackson.databind.node.ObjectNode;
import controllers.Navigation.Level;
import managers.*;
import models.*;
import models.base.FileOperationException;
import models.base.ValidationException;
import models.enums.AccountRole;
import models.enums.AvatarSize;
import models.enums.EmailNotifications;
import play.Configuration;
import play.Logger;
import play.api.i18n.Lang;
import play.data.Form;
import play.data.FormFactory;
import play.db.jpa.Transactional;
import play.i18n.MessagesApi;
import play.libs.Json;
import play.mvc.Http.MultipartFormData;
import play.mvc.Result;
import play.mvc.Security;
import views.html.Profile.*;
import views.html.Profile.snippets.streamRaw;
import javax.inject.Inject;
import java.io.File;
import java.util.Collections;
import java.util.List;
@Transactional
@Security.Authenticated(Secured.class)
public class ProfileController extends BaseController {
AccountManager accountManager;
GroupAccountManager groupAccountManager;
PostManager postManager;
AccountController accountController;
StudycourseManager studycourseManager;
AvatarManager avatarManager;
MediaManager mediaManager;
FriendshipManager friendshipManager;
Configuration configuration;
FormFactory formFactory;
MessagesApi messagesApi;
@Inject
public ProfileController(AccountManager accountManager,
GroupAccountManager groupAccountManager,
PostManager postManager,
AccountController accountController,
StudycourseManager studycourseManager,
AvatarManager avatarManager,
MediaManager mediaManager, FriendshipManager friendshipManager,
Configuration configuration,FormFactory formFactory, MessagesApi messagesApi) {
this.accountManager = accountManager;
this.groupAccountManager = groupAccountManager;
this.postManager = postManager;
this.accountController = accountController;
this.studycourseManager = studycourseManager;
this.avatarManager = avatarManager;
this.mediaManager = mediaManager;
this.friendshipManager = friendshipManager;
this.configuration = configuration;
this.formFactory = formFactory;
this.messagesApi = messagesApi;
this.accountForm = formFactory.form(Account.class);
this.postForm = formFactory.form(Post.class);
this.loginForm = formFactory.form(Login.class);
this.LIMIT = configuration.getInt("htwplus.post.limit");
}
Form<Account> accountForm;
Form<Post> postForm;
Form<Login> loginForm;
int LIMIT;
static final int PAGE = 1;
public Result me() {
Navigation.set(Level.PROFILE, "Ich");
Account account = Component.currentAccount();
if (account == null) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
} else {
return ok(index.render(account, postForm));
}
}
public Result view(final Long id) {
Account account = accountManager.findById(id);
if (account == null || account.role == AccountRole.DUMMY) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
} else {
if(Secured.isFriend(account) || Component.currentAccount().equals(account)) {
return redirect(routes.ProfileController.stream(account.id, PAGE, false));
} else {
Navigation.set(Level.USER, "Profil", account.name, controllers.routes.ProfileController.view(account.id));
}
return ok(index.render(account, postForm));
}
}
@Transactional
public Result stream(Long accountId, int page, boolean raw) {
Account account = accountManager.findById(accountId);
Account currentUser = Component.currentAccount();
if (account == null || account.role == AccountRole.DUMMY) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
}
if (currentUser.equals(account)) {
Navigation.set(Level.PROFILE, "Newsstream");
} else {
Navigation.set(Level.FRIENDS, "Newsstream", account.name,
controllers.routes.ProfileController.view(account.id));
}
// case for friends and own profile
if (friendshipManager.alreadyFriendly(Component.currentAccount(), account)
|| currentUser.equals(account) || Secured.isAdmin()) {
if (raw) {
return ok(streamRaw.render(account, postManager.getFriendStream(account, LIMIT, page),
postForm, postManager.countFriendStream(account), LIMIT, page));
} else {
return ok(stream.render(account, postManager.getFriendStream(account, LIMIT, page),
postForm, postManager.countFriendStream(account), LIMIT, page));
}
}
// case for visitors
flash("info", "Du kannst nur den Stream deiner Kontakte betrachten!");
return redirect(controllers.routes.ProfileController.view(accountId));
}
public Result convert(Long id) {
Account account = accountManager.findById(id);
if (account == null) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
}
// Check Access
if (!Secured.isAdmin()) {
return redirect(controllers.routes.Application.index());
}
Navigation.set(Level.PROFILE, "Konvertieren");
return ok(convert.render(account, accountForm.fill(account)));
}
public Result saveConvert(Long id) {
// Get regarding Object
Account account = accountManager.findById(id);
if (account == null) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
}
// Create error switch
Boolean error = false;
// Check Access
if (!Secured.isAdmin()) {
return redirect(controllers.routes.Application.index());
}
// Get data from request
Form<Account> filledForm = accountForm.bindFromRequest();
// Remove all unnecessary fields
filledForm.errors().remove("firstname");
filledForm.errors().remove("lastname");
// Store old and new password for validation
String email = filledForm.field("email").value();
String password = filledForm.field("password").value();
String repeatPassword = filledForm.field("repeatPassword").value();
// Perform JPA Validation
if (filledForm.hasErrors()) {
error = true;
}
if (email.isEmpty()) {
filledForm.reject("email", "Für einen lokalen Account ist eine EMail nötig!");
error = true;
}
if (password.length() < 6) {
filledForm.reject("password", "Das Passwort muss mindestens 6 Zeichen haben.");
error = true;
}
if (!password.equals(repeatPassword)) {
filledForm.reject("repeatPassword", "Die Passwörter stimmen nicht überein.");
error = true;
}
if (error) {
return badRequest(convert.render(account, filledForm));
} else {
account.password = Component.md5(password);
account.email = email;
accountManager.update(account);
flash("success", "Account erfolgreich konvertiert.");
}
return redirect(controllers.routes.ProfileController.view(id));
}
public Result edit(Long id) {
Account account = accountManager.findById(id);
if (account == null) {
flash("info", "Diese Person gibt es nicht.");
return Secured.nullRedirect(request());
}
// Check Access
if (!Secured.editAccount(account)) {
return Secured.nullRedirect(request());
}
Navigation.set(Level.PROFILE, "Editieren");
return ok(edit.render(account, accountForm.fill(account), loginForm, studycourseManager.getAll()));
}
public Result update(Long id) {
// Get regarding Object
Account account = accountManager.findById(id);
if (account == null) {
flash("info", "Diese Person gibt es nicht.");
return redirect(controllers.routes.Application.index());
}
// Check Access
if (!Secured.editAccount(account)) {
return redirect(controllers.routes.Application.index());
}
// Get the data from the request
Form<Account> filledForm = accountForm.bindFromRequest();
Navigation.set(Level.PROFILE, "Editieren");
// Remove expected errors
filledForm.errors().remove("password");
filledForm.errors().remove("studycourse");
filledForm.errors().remove("firstname");
filledForm.errors().remove("lastname");
// Custom Validations
Account exisitingAccount = accountManager.findByEmail(filledForm.field("email").value());
if (exisitingAccount != null && !exisitingAccount.equals(account)) {
filledForm.reject("email", "Diese Mail wird bereits verwendet!");
return badRequest(edit.render(account, filledForm, loginForm, studycourseManager.getAll()));
}
// Perform JPA Validation
if (filledForm.hasErrors()) {
return badRequest(edit.render(account, filledForm, loginForm, studycourseManager.getAll()));
} else {
// Fill an and update the model manually
// because the its just a partial form
if (!filledForm.field("email").value().isEmpty()) {
account.email = filledForm.field("email").value();
} else {
account.email = null;
account.emailNotifications = EmailNotifications.NONE;
account.dailyEmailNotificationHour = null;
}
if (filledForm.data().containsKey("degree")) {
if (filledForm.field("degree").value().equals("null")) {
account.degree = null;
} else {
account.degree = filledForm.field("degree").value();
}
}
if (filledForm.data().containsKey("semester")) {
if (filledForm.field("semester").value().equals("0")) {
account.semester = null;
} else {
account.semester = Integer.parseInt(filledForm.field("semester").value());
}
}
if (filledForm.data().containsKey("emailNotifications") && (account.email != null && !account.email.isEmpty())) {
account.emailNotifications = EmailNotifications.valueOf(filledForm.field("emailNotifications").value());
if (account.emailNotifications.equals(EmailNotifications.COLLECTED_DAILY)
&& filledForm.data().containsKey("dailyEmailNotificationHour")) {
account.dailyEmailNotificationHour = Integer.valueOf(
filledForm.field("dailyEmailNotificationHour").value()
);
}
}
Long studycourseId = Long.parseLong(filledForm.field("studycourse").value());
Studycourse studycourse;
if (studycourseId != 0) {
studycourse = studycourseManager.findById(studycourseId);
} else {
studycourse = null;
}
account.studycourse = studycourse;
if (!filledForm.field("about").value().isEmpty()) {
account.about = filledForm.field("about").value();
} else {
account.about = null;
}
if (!filledForm.field("homepage").value().isEmpty()) {
account.homepage = filledForm.field("homepage").value();
} else {
account.homepage = null;
}
accountManager.update(account);
flash("success", "Profil erfolgreich gespeichert.");
return redirect(controllers.routes.ProfileController.me());
}
}
public Result groups(Long id) {
Account account = accountManager.findById(id);
if (Secured.isFriend(account)) {
Navigation.set(Level.FRIENDS, "Gruppen & Kurse", account.name, controllers.routes.ProfileController.view(account.id));
} else {
if (Secured.isMe(account)) {
Navigation.set(Level.PROFILE, "Gruppen & Kurse");
} else {
Navigation.set(Level.USER, "Gruppen & Kurse", account.name, controllers.routes.ProfileController.view(account.id));
}
}
return ok(groups.render(account, groupAccountManager.findGroupsEstablished(account), groupAccountManager.findCoursesEstablished(account)));
}
public Result files(Long accountId) {
Account account = accountManager.findById(accountId);
// check account
if (account == null) {
flash("info", messagesApi.get(Lang.defaultLang(), "Diese Person gibt es nicht."));
return Secured.nullRedirect(request());
}
// unknown user
if (Secured.isUnknown(account)) {
flash("info", "Du kannst nur Dateien deiner Kontakte sehen.");
return redirect(controllers.routes.ProfileController.view(account.id));
}
// set Navigation
if (Secured.isFriend(account)) {
Navigation.set(Level.FRIENDS, "Dateien", account.name, controllers.routes.ProfileController.view(account.id));
} else {
if (Secured.isMe(account)) {
Navigation.set(Level.PROFILE, "Dateien");
} else {
Navigation.set(Level.USER, "Dateien", account.name, controllers.routes.ProfileController.view(account.id));
}
}
// gather information
Folder accountRootFolder = account.rootFolder;
List<Media> fileList = accountRootFolder.files;
List<Folder> folderList = accountRootFolder.folders;
List<Folder> navigationFolder = accountRootFolder.findAncestors(accountRootFolder);
Collections.reverse(navigationFolder);
// hacky, but prevents accessing MediaController from view. use dto instead
for (Media media : fileList) {
media.sizeInByte = mediaManager.bytesToString(media.size, false);
}
return ok(files.render(account, fileList, folderList));
}
@Transactional
public Result deleteProfile(Long accountId) {
Account current = accountManager.findById(accountId);
if (!Secured.deleteAccount(current)) {
flash("error", messagesApi.get(Lang.defaultLang(), "profile.delete.nopermission"));
return redirect(controllers.routes.Application.index());
}
// Check Password //
Form<Login> filledForm = loginForm.bindFromRequest();
String entered = filledForm.field("password").value();
if (entered == null || entered.length() == 0) {
flash("error", messagesApi.get(Lang.defaultLang(), "profile.delete.nopassword"));
return redirect(controllers.routes.ProfileController.update(current.id));
} else if (!accountController.checkPassword(accountId, entered)) {
return redirect(controllers.routes.ProfileController.update(current.id));
}
// ACTUAL DELETION //
Logger.info("Deleting Account[#" + current.id + "]...");
accountManager.delete(current);
// override logout message
flash("success", messagesApi.get(Lang.defaultLang(), "profile.delete.success"));
return redirect(controllers.routes.AccountController.logout());
}
/**
* Handles the upload of the temporary avatar image
*
* @param id
* @return
*/
public Result createTempAvatar(Long id) {
Account account = accountManager.findById(id);
if (account == null) {
return notFound();
}
ObjectNode result = Json.newObject();
MultipartFormData body = request().body().asMultipartFormData();
if (body == null) {
result.put("error", "No file attached");
return badRequest(result);
}
MultipartFormData.FilePart avatar = body.getFile("avatarimage");
if (avatar == null) {
result.put("error", "No file with key 'avatarimage'");
return badRequest(result);
}
try {
avatarManager.setTempAvatar(avatar, account.id);
} catch (ValidationException e) {
result.put("error", e.getMessage());
return badRequest(result);
}
result.put("success", getTempAvatar(id).toString());
return ok(result);
}
/**
* Get the temporary avatar image
*
* @param id
* @return
*/
public Result getTempAvatar(Long id) {
ObjectNode result = Json.newObject();
Account account = accountManager.findById(id);
if (account == null) {
return notFound();
}
if (!Secured.editAccount(account)) {
result.put("error", "Not allowed.");
return forbidden(result);
}
File tempAvatar = avatarManager.getTempAvatar(account.id);
if (tempAvatar != null) {
return ok(tempAvatar);
} else {
return notFound();
}
}
/**
* Create the real avatar with the given dimensions
*
* @param id
* @return
*/
public Result createAvatar(long id) {
ObjectNode result = Json.newObject();
Account account = accountManager.findById(id);
if (account == null) {
return notFound();
}
if (!Secured.editAccount(account)) {
result.put("error", "Not allowed.");
return forbidden(result);
}
Form<Avatar> form = formFactory.form(Avatar.class).bindFromRequest();
if (form.hasErrors()) {
result.set("error", form.errorsAsJson());
return badRequest(result);
}
try {
accountManager.saveAvatar(form.get(), account);
result.put("success", "saved");
return ok(result);
} catch (FileOperationException e) {
result.put("error", "Unexpected Error while saving avatar.");
return internalServerError(result);
}
}
/**
* Get the avatar of a user.
*
* @param id User ID
* @param size Size - Possible values: "small", "medium", "large"
* @return
*/
public Result getAvatar(long id, String size) {
Account account = accountManager.findById(id);
if (account != null) {
File avatar;
switch (size) {
case "small":
avatar = avatarManager.getAvatar(AvatarSize.SMALL, account.id);
break;
case "medium":
avatar = avatarManager.getAvatar(AvatarSize.MEDIUM, account.id);
break;
case "large":
avatar = avatarManager.getAvatar(AvatarSize.LARGE, account.id);
break;
default:
avatar = avatarManager.getAvatar(AvatarSize.SMALL, account.id);
}
response().setHeader("Content-disposition", "inline");
if (avatar != null) {
return ok(avatar);
} else {
return notFound();
}
} else {
return notFound();
}
}
}