2019-11-22 07:50:15 +00:00
|
|
|
import { RequestHandler } from "../entities/RequestHandler";
|
2019-11-23 12:16:28 +00:00
|
|
|
import { AccountHelper } from "../helpers/AccountHelper";
|
2019-12-29 18:40:35 +00:00
|
|
|
import { UserHelper } from "../helpers/UserHelper";
|
2019-12-30 12:44:54 +00:00
|
|
|
import { NewAccount } from "../entities/NewAccount";
|
|
|
|
import { removeHTMLNodes } from "../utils/StringUtils";
|
2020-03-25 08:04:04 +00:00
|
|
|
import { limit_query } from "./APILimitsController";
|
|
|
|
import { Action } from "../helpers/APILimitsHelper";
|
2020-03-25 17:24:46 +00:00
|
|
|
import { UserController } from "./UserController";
|
2020-03-25 17:44:51 +00:00
|
|
|
import { PostsController } from "./PostsController";
|
2020-03-25 17:55:25 +00:00
|
|
|
import { CommentsController } from "./CommentsController";
|
2020-03-25 18:08:43 +00:00
|
|
|
import { LikesController } from "./LikesController";
|
2020-03-26 11:11:06 +00:00
|
|
|
import { SurveyController } from "./SurveyController";
|
2020-03-26 11:13:53 +00:00
|
|
|
import { MoviesController } from "./MoviesController";
|
2020-03-26 12:05:14 +00:00
|
|
|
import { ConversationsController } from "./ConversationsController";
|
2019-11-22 07:50:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Account controller
|
|
|
|
*
|
|
|
|
* @author Pierre HUBERT
|
|
|
|
*/
|
|
|
|
|
|
|
|
export class AccountController {
|
|
|
|
|
2019-12-30 12:44:54 +00:00
|
|
|
/**
|
|
|
|
* Create a new account
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async Create(h: RequestHandler) {
|
2020-03-25 17:06:42 +00:00
|
|
|
// Limit request
|
|
|
|
await limit_query(h, Action.CREATE_ACCOUNT, false);
|
2019-12-30 12:44:54 +00:00
|
|
|
|
|
|
|
// Get & check email address
|
|
|
|
const email = h.postEmail("emailAddress");
|
|
|
|
if(await AccountHelper.ExistsEmail(email))
|
|
|
|
h.error(409, "This email address already belongs to an account!");
|
|
|
|
|
|
|
|
const newAccount = <NewAccount>{
|
|
|
|
firstName: removeHTMLNodes(h.postString("firstName")),
|
|
|
|
lastName: removeHTMLNodes(h.postString("lastName")),
|
|
|
|
email: email,
|
|
|
|
password: h.postString("password", 3)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Try to create the account
|
|
|
|
await AccountHelper.Create(newAccount);
|
|
|
|
|
2020-03-25 17:06:42 +00:00
|
|
|
// Trigger the API limit
|
|
|
|
await limit_query(h, Action.CREATE_ACCOUNT, true);
|
2019-12-30 12:44:54 +00:00
|
|
|
|
|
|
|
// Success
|
|
|
|
h.success("The account has been created!");
|
|
|
|
}
|
|
|
|
|
2019-11-22 07:50:15 +00:00
|
|
|
/**
|
|
|
|
* Attempt to login user
|
|
|
|
*
|
2020-03-25 08:04:04 +00:00
|
|
|
* @param h Request handler
|
2019-11-22 07:50:15 +00:00
|
|
|
*/
|
2020-03-25 08:04:04 +00:00
|
|
|
public static async LoginUser(h: RequestHandler) {
|
2019-11-22 07:50:15 +00:00
|
|
|
|
2019-11-23 12:16:28 +00:00
|
|
|
// Get post data
|
2020-03-25 08:04:04 +00:00
|
|
|
const email = h.postEmail("userMail");
|
|
|
|
const password = h.postString("userPassword");
|
2019-11-23 12:16:28 +00:00
|
|
|
|
2020-03-25 08:04:04 +00:00
|
|
|
// Limit request
|
|
|
|
await limit_query(h, Action.LOGIN_FAILED, false);
|
2019-11-23 12:16:28 +00:00
|
|
|
|
|
|
|
// Authenticate user
|
2020-03-25 08:04:04 +00:00
|
|
|
const tokens = await AccountHelper.LoginUser(email, password, h.getClientInfo());
|
2019-11-23 12:16:28 +00:00
|
|
|
|
|
|
|
if(tokens == null) {
|
2020-03-25 08:04:04 +00:00
|
|
|
// Trigger limit
|
|
|
|
await limit_query(h, Action.LOGIN_FAILED, true);
|
2019-11-23 12:16:28 +00:00
|
|
|
|
2020-03-25 08:04:04 +00:00
|
|
|
h.error(401, "Invalid e-mail address / password !");
|
2019-11-23 12:16:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Success
|
2020-03-25 08:04:04 +00:00
|
|
|
h.send({
|
2019-11-23 12:16:28 +00:00
|
|
|
success: "User signed in!",
|
|
|
|
tokens: {
|
|
|
|
token1: tokens.token1,
|
|
|
|
token2: tokens.token2
|
|
|
|
}
|
|
|
|
});
|
2019-11-22 07:50:15 +00:00
|
|
|
}
|
|
|
|
|
2019-11-23 13:03:14 +00:00
|
|
|
/**
|
|
|
|
* Disconnect user
|
|
|
|
*
|
|
|
|
* @param handler
|
|
|
|
*/
|
|
|
|
public static async LogoutUser(handler: RequestHandler) {
|
|
|
|
|
|
|
|
await AccountHelper.DestroyUserTokens(handler.getClientInfo(),
|
|
|
|
handler.getUserId());
|
|
|
|
|
|
|
|
handler.success("User has been disconnected!");
|
|
|
|
}
|
|
|
|
|
2019-11-23 12:48:16 +00:00
|
|
|
/**
|
|
|
|
* Get current user ID
|
|
|
|
*
|
|
|
|
* @param handler
|
|
|
|
*/
|
|
|
|
public static CurrentUserID(handler: RequestHandler) {
|
|
|
|
handler.send({
|
|
|
|
userID: handler.getUserId()
|
|
|
|
});
|
|
|
|
}
|
2019-12-28 16:05:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check out whether an email is associated to an account
|
|
|
|
* or not
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async ExistsMail(h: RequestHandler) {
|
|
|
|
const email = h.postEmail("email");
|
|
|
|
|
|
|
|
h.send({
|
|
|
|
exists: await AccountHelper.ExistsEmail(email)
|
|
|
|
})
|
|
|
|
}
|
2019-12-29 18:40:35 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if an account associated with an email address has
|
|
|
|
* setup security questions or not
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async HasSecurityQuestions(h: RequestHandler) {
|
|
|
|
const userID = await h.postUserIdFromEmail("email");
|
|
|
|
const settings = await UserHelper.GetUserInfo(userID);
|
|
|
|
|
|
|
|
h.send({
|
|
|
|
defined: settings.hasSecurityQuestions
|
|
|
|
})
|
|
|
|
}
|
2019-12-30 07:16:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the security questions of a user, in order to reset its
|
|
|
|
* password
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async GetSecurityQuestions(h: RequestHandler) {
|
|
|
|
const userID = await h.postUserIdFromEmail("email");
|
|
|
|
const settings = await UserHelper.GetUserInfo(userID);
|
|
|
|
|
|
|
|
if(!settings.hasSecurityQuestions)
|
|
|
|
h.error(401, "Specified user has not setup security questions !");
|
|
|
|
|
|
|
|
h.send({
|
|
|
|
questions: [
|
|
|
|
settings.security_question_1,
|
|
|
|
settings.security_question_2
|
|
|
|
]
|
|
|
|
})
|
|
|
|
}
|
2019-12-30 07:36:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check the answer given by the user
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async CheckSecurityAnswers(h: RequestHandler) {
|
|
|
|
const userID = await h.postUserIdFromEmail("email");
|
|
|
|
const settings = await UserHelper.GetUserInfo(userID);
|
|
|
|
|
|
|
|
if(!settings.hasSecurityQuestions)
|
|
|
|
h.error(401, "Specified user has not setup security questions !");
|
|
|
|
|
|
|
|
// Get the answers of the user
|
|
|
|
const answers = h.postString("answers", 3).split("&")
|
|
|
|
.map((e) => decodeURIComponent(e).toLowerCase().trim());
|
|
|
|
|
|
|
|
if(answers.length != 2)
|
|
|
|
h.error(401, "Please specify two security answers !");
|
|
|
|
|
|
|
|
// Check the answers
|
|
|
|
if(answers[0] != settings.security_answer_1.toLowerCase().trim() ||
|
|
|
|
answers[1] != settings.security_answer_2.toLowerCase().trim())
|
|
|
|
h.error(401, "Specified ecurity answers are invalid!");
|
|
|
|
|
|
|
|
// If we get there, security answers are valid, we can create a password reset token
|
|
|
|
h.send({
|
|
|
|
reset_token: await AccountHelper.GenerateNewPasswordResetToken(userID)
|
|
|
|
});
|
|
|
|
}
|
2019-12-30 11:11:33 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check the validity of a password reset Token
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async CheckPasswordResetToken(h: RequestHandler) {
|
2019-12-30 12:20:24 +00:00
|
|
|
// We just get user ID to check the validity of the token
|
2019-12-30 11:11:33 +00:00
|
|
|
await this.GetUserIDFromPasswordResetToken(h, "token");
|
|
|
|
h.success("The token is valid.");
|
|
|
|
}
|
|
|
|
|
2019-12-30 12:20:24 +00:00
|
|
|
/**
|
|
|
|
* Reset user password
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async ResetUserPassword(h: RequestHandler) {
|
|
|
|
const userID = await this.GetUserIDFromPasswordResetToken(h, "token");
|
|
|
|
const newPassword = h.postString("password", 3);
|
|
|
|
|
|
|
|
// Set new password
|
|
|
|
await AccountHelper.ChangePassword(userID, newPassword);
|
|
|
|
|
|
|
|
// Destroy reset token
|
|
|
|
await AccountHelper.DestroyPasswordResetTokenForUser(userID);
|
|
|
|
|
|
|
|
h.success("Password changed!");
|
|
|
|
}
|
|
|
|
|
2019-12-30 12:50:59 +00:00
|
|
|
/**
|
|
|
|
* Export the data of the user
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async ExportData(h: RequestHandler) {
|
|
|
|
await h.needUserPostPassword("password");
|
|
|
|
|
2020-03-25 17:24:46 +00:00
|
|
|
// Query the database
|
2020-03-25 17:20:43 +00:00
|
|
|
const data = await AccountHelper.Export(h.getUserId());
|
|
|
|
|
|
|
|
const out: any = {
|
2020-03-25 17:24:46 +00:00
|
|
|
userID: data.userID,
|
|
|
|
|
|
|
|
// General account information
|
2020-03-25 17:44:51 +00:00
|
|
|
advanced_info: await UserController.UserToAPI(data.userInfo, h, true),
|
|
|
|
|
|
|
|
// User posts
|
2020-03-25 17:55:25 +00:00
|
|
|
posts: await Promise.all(data.postsList.map((p) => PostsController.PostToAPI(h, p))),
|
|
|
|
|
|
|
|
// User comments
|
|
|
|
comments: await CommentsController.CommentsToAPI(h, data.comments),
|
2020-03-25 18:08:43 +00:00
|
|
|
|
|
|
|
// User likes
|
2020-03-26 11:11:06 +00:00
|
|
|
likes: data.likes.map(LikesController.UserLikeToAPI),
|
|
|
|
|
|
|
|
// Responses to surveys
|
2020-03-26 11:13:53 +00:00
|
|
|
survey_responses: data.surveyResponses.map(SurveyController.SurveyResponseToAPI),
|
|
|
|
|
|
|
|
// User movies
|
|
|
|
movies: data.movies.map(MoviesController.MovieToAPI),
|
2020-03-26 12:05:14 +00:00
|
|
|
|
|
|
|
// Conversations messages
|
2020-03-26 12:09:15 +00:00
|
|
|
all_conversation_messages: data.conversationMessages.map(ConversationsController.ConversationMessageToAPI),
|
|
|
|
|
|
|
|
// Conversations list
|
|
|
|
conversations_list: data.conversations.map(ConversationsController.ConversationToAPI),
|
|
|
|
|
2020-03-25 17:20:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-25 17:55:25 +00:00
|
|
|
// TODO : continue (additional user info)
|
2020-03-25 17:20:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
h.send(out);
|
2019-12-30 12:50:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete a user account
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async DeleteAccount(h: RequestHandler) {
|
|
|
|
await h.needUserPostPassword("password");
|
|
|
|
|
|
|
|
// TODO : implement
|
|
|
|
h.error(500, "Method not implemented yet.");
|
|
|
|
}
|
|
|
|
|
2019-12-30 11:11:33 +00:00
|
|
|
/**
|
|
|
|
* Get the user ID associated to a password reset token
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
* @param name The name of the POST field containing the token
|
|
|
|
*/
|
|
|
|
private static async GetUserIDFromPasswordResetToken(h: RequestHandler, name: string) : Promise<number> {
|
|
|
|
const token = h.postString(name, 10);
|
|
|
|
const userID = await AccountHelper.GetUserIDFromPasswordResetToken(token);
|
|
|
|
|
|
|
|
if(userID < 1)
|
|
|
|
h.error(401, "Invalid password reset token!");
|
|
|
|
|
|
|
|
return userID;
|
|
|
|
}
|
2019-11-22 07:50:15 +00:00
|
|
|
}
|