2020-03-31 12:03:26 +00:00
|
|
|
/**
|
|
|
|
* Base requests handler
|
|
|
|
*
|
|
|
|
* @author Pierre Hubert
|
|
|
|
*/
|
|
|
|
|
2020-03-31 12:06:07 +00:00
|
|
|
import { UserHelper } from "../helpers/UserHelper";
|
2020-03-31 12:29:32 +00:00
|
|
|
import { removeHTMLNodes, checkMail, checkURL } from "../utils/StringUtils";
|
|
|
|
import { FriendsHelper } from "../helpers/FriendsHelper";
|
|
|
|
import { AccountHelper } from "../helpers/AccountHelper";
|
|
|
|
import { GroupsHelper } from "../helpers/GroupsHelper";
|
|
|
|
import { GroupsAccessLevel } from "./Group";
|
|
|
|
import { PostsHelper } from "../helpers/PostsHelper";
|
|
|
|
import { PostAccessLevel } from "./Post";
|
|
|
|
import { CommentsHelper } from "../helpers/CommentsHelper";
|
|
|
|
import { checkVirtualDirectory } from "../utils/VirtualDirsUtils";
|
2020-04-01 09:11:41 +00:00
|
|
|
import { ConversationsHelper } from "../helpers/ConversationsHelper";
|
2020-03-31 12:06:07 +00:00
|
|
|
|
2020-03-31 12:03:26 +00:00
|
|
|
export abstract class BaseRequestsHandler {
|
|
|
|
|
2020-03-31 12:16:04 +00:00
|
|
|
protected abstract get userID() : number;
|
|
|
|
|
2020-03-31 12:03:26 +00:00
|
|
|
protected abstract getPostParam(name : string) : any;
|
|
|
|
public abstract hasPostParameter(name: string) : boolean;
|
|
|
|
public abstract error(code : number, message : string) : void;
|
|
|
|
public abstract success(message: string) : void;
|
|
|
|
public abstract send(data: any): void;
|
|
|
|
|
2020-03-31 12:16:04 +00:00
|
|
|
/**
|
|
|
|
* Get information about current user
|
|
|
|
*/
|
|
|
|
public getUserId() : number {
|
|
|
|
if(this.userID < 1)
|
|
|
|
throw Error("Trying to get user ID but none are available!");
|
|
|
|
|
|
|
|
return this.userID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of the current user (if any)
|
|
|
|
* or 0 if the user is not signed in
|
|
|
|
*/
|
|
|
|
public get optionnalUserID(): number {
|
|
|
|
return this.userID >= 1 ? this.userID : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check out whether user is signed in or not
|
|
|
|
*/
|
|
|
|
public get signedIn() : boolean {
|
|
|
|
return this.userID > 0;
|
|
|
|
}
|
|
|
|
|
2020-03-31 12:06:07 +00:00
|
|
|
/**
|
|
|
|
* Check out whether a POST string is present in the request or not
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field to check
|
|
|
|
* @param minLength Minimal length of the parameter
|
|
|
|
*/
|
|
|
|
public hasPostString(name: string, minLength: number = 0) : boolean {
|
|
|
|
return this.hasPostParameter(name) && this.getPostParam(name).length >= minLength;
|
|
|
|
}
|
|
|
|
|
2020-03-31 12:03:26 +00:00
|
|
|
/**
|
|
|
|
* Get a String from the request
|
|
|
|
*
|
|
|
|
* @param name The name of the string to get
|
|
|
|
* @param minLength Minimal required size of the string
|
|
|
|
* @param required If set to true (true by default), an error will
|
|
|
|
* be thrown if the string is not included in the request
|
|
|
|
*/
|
|
|
|
public postString(name : string, minLength : number = 1, required : boolean = true) : string {
|
|
|
|
const param = this.getPostParam(name);
|
|
|
|
|
|
|
|
// Check if parameter was not found
|
|
|
|
if(param == undefined) {
|
|
|
|
if(required)
|
|
|
|
this.error(400, "Could not find required string: '"+name+"'");
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if(param.length < minLength)
|
|
|
|
this.error(400, "Parameter "+name+" is too short!");
|
|
|
|
|
|
|
|
return param;
|
|
|
|
}
|
2020-03-31 12:06:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get some content for post and satinize it (remove HTML nodes)
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field
|
|
|
|
* @param minLength Optionnal minimal length for the post
|
|
|
|
*/
|
|
|
|
public postContent(name: string, minLength ?: number) : string {
|
|
|
|
const content = this.postString(name, minLength);
|
|
|
|
|
|
|
|
if(content.match(/data:image/))
|
|
|
|
this.error(401, "Please do not include inline images!");
|
|
|
|
|
|
|
|
return removeHTMLNodes(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an email address included in a post request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST filed
|
|
|
|
*/
|
|
|
|
public postEmail(name: string) : string {
|
|
|
|
const email = this.postString(name, 3);
|
|
|
|
|
|
|
|
if(!checkMail(email))
|
|
|
|
this.error(400, email + " is not a valid email address!");
|
|
|
|
|
|
|
|
return email;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an integer included in the request
|
|
|
|
*
|
|
|
|
* @param name Name of POST field
|
|
|
|
* @param fallback Fallback value (if none, throw an error)
|
|
|
|
* @returns The number (throws in case of error)
|
|
|
|
*/
|
|
|
|
public postInt(name: string, fallback ?: number) : number {
|
|
|
|
const param = this.getPostParam(name);
|
|
|
|
|
|
|
|
if(param == undefined) {
|
|
|
|
if(fallback == undefined)
|
|
|
|
this.error(400, "Missing integer '"+name+"' in the request!");
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check number
|
|
|
|
if(Number.parseInt(param).toString() !== param.toString())
|
|
|
|
this.error(400, "'"+name+"' is an invalid integer!");
|
|
|
|
|
|
|
|
return Number.parseInt(param);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a list of integeres included in the request
|
|
|
|
*
|
|
|
|
* @param name The name of the post field
|
|
|
|
* @param minEntries Specify the minimum number of entries required
|
|
|
|
*/
|
|
|
|
public postNumbersList(name: string, minEntries : number = 1) : Array<number> {
|
|
|
|
const param = this.postString(name, minEntries < 1 ? 0 : minEntries, minEntries > 0);
|
|
|
|
let list = [];
|
|
|
|
for (const el of param.split(",")) {
|
|
|
|
|
|
|
|
if(el == "")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(Number.parseInt(el).toString() != el)
|
|
|
|
this.error(400, "Invalid number detected in '"+name+"'!");
|
|
|
|
|
|
|
|
list.push(Number.parseInt(el));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(list.length < minEntries)
|
|
|
|
this.error(400, "Not enough entries in '" + name + "'!")
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Turn a list of string into a Set object
|
|
|
|
*
|
|
|
|
* @param name Name of POST field
|
|
|
|
* @param minEntries Minimum number of entries to specify
|
|
|
|
*/
|
|
|
|
public postNumbersSet(name : string, minEntries : number = 1) : Set<number> {
|
|
|
|
return new Set(this.postNumbersList(name, minEntries));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempt to decode JSON included in a POST request
|
|
|
|
*
|
|
|
|
* @param name Name of POST field
|
|
|
|
*/
|
|
|
|
public postJSON(name: string) : any {
|
|
|
|
const src = this.getPostParam(name);
|
|
|
|
|
|
|
|
if(src == undefined)
|
|
|
|
this.error(400, "Missing JSON '" + name + "' in the request!");
|
|
|
|
|
|
|
|
try {
|
|
|
|
const response = JSON.parse(src);
|
|
|
|
return response;
|
|
|
|
} catch(e) {
|
|
|
|
this.error(500, "'" + name + "' is not a valid JSON !");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a boolean included in the request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field
|
|
|
|
* @param fallback Fallback value to use if the value is not
|
|
|
|
* found in the request
|
|
|
|
*/
|
|
|
|
public postBool(name: string, fallback ?: boolean) : boolean {
|
|
|
|
const param = this.getPostParam(name);
|
|
|
|
|
|
|
|
if(param == undefined) {
|
|
|
|
if(fallback != undefined)
|
|
|
|
return fallback;
|
|
|
|
|
|
|
|
this.error(400, "Missing boolean '" + name + "' in the request!");
|
|
|
|
}
|
|
|
|
|
|
|
|
return param === "true" || param === true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of a user specified in a POST request
|
|
|
|
*
|
|
|
|
* @param name Name of the POST field
|
|
|
|
*/
|
|
|
|
public async postUserId(name: string) : Promise<number> {
|
|
|
|
const userID = this.postInt(name);
|
|
|
|
|
|
|
|
if(userID < 1)
|
|
|
|
this.error(400, "Invalid user ID specified in '" + name +"'!");
|
|
|
|
|
|
|
|
if(!await UserHelper.Exists(userID))
|
|
|
|
this.error(404, "User with ID " + userID + " not found!");
|
|
|
|
|
|
|
|
return userID;
|
|
|
|
}
|
2020-03-31 12:29:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of a friend included in a POST request
|
|
|
|
*
|
|
|
|
* @param name Name of the POST field
|
|
|
|
*/
|
|
|
|
public async postFriendId(name: string) : Promise<number> {
|
|
|
|
const friendID = await this.postUserId(name);
|
|
|
|
|
|
|
|
if(!await FriendsHelper.AreFriend(this.getUserId(), friendID))
|
|
|
|
this.error(401, "You are not friend with this personn!");
|
|
|
|
|
|
|
|
return friendID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find user ID based on its email address, included in a POST request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing the email address of the user
|
|
|
|
*/
|
|
|
|
public async postUserIdFromEmail(name: string) : Promise<number> {
|
|
|
|
const email = this.postEmail(name);
|
|
|
|
const userID = await AccountHelper.FindIDFromEmail(email);
|
|
|
|
|
|
|
|
if(userID < 1)
|
|
|
|
this.error(404, "Email not found!");
|
|
|
|
|
|
|
|
return userID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a POST group ID
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field
|
|
|
|
*/
|
|
|
|
public async postGroupID(name: string) : Promise<number> {
|
|
|
|
const groupID = this.postInt(name);
|
|
|
|
|
|
|
|
if(!await GroupsHelper.Exists(groupID))
|
|
|
|
this.error(404, "Specified group not found!");
|
|
|
|
|
|
|
|
return groupID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a POST group ID with a check for access level of current user
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing group ID
|
|
|
|
* @param minVisibility Minimum visiblity requested to the group
|
|
|
|
* @returns The ID of the group (throws in case of failure)
|
|
|
|
*/
|
|
|
|
public async postGroupIDWithAccess(name: string, minVisibility : GroupsAccessLevel) : Promise<number> {
|
|
|
|
const groupID = await this.postGroupID(name);
|
|
|
|
|
|
|
|
const access = await GroupsHelper.GetAccessLevel(groupID, this.optionnalUserID);
|
|
|
|
|
|
|
|
if(access == GroupsAccessLevel.NO_ACCESS)
|
|
|
|
this.error(404, "Specified group not found!");
|
|
|
|
|
|
|
|
if(access < minVisibility)
|
|
|
|
this.error(401, "You do not have enough rights to perform what you intend to do on this group!");
|
|
|
|
|
|
|
|
return groupID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of post included in a POST request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing the id of the target post
|
|
|
|
*/
|
|
|
|
public async postPostID(name: string) : Promise<number> {
|
|
|
|
const postID = this.postInt(name);
|
|
|
|
|
|
|
|
if(postID < 1)
|
|
|
|
this.error(400, "Invalid post ID!");
|
|
|
|
|
|
|
|
if(!await PostsHelper.Exists(postID))
|
|
|
|
this.error(404, "Specified post does not exists!");
|
|
|
|
|
|
|
|
return postID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of a post a user has access to
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing the ID of the target post
|
|
|
|
*/
|
|
|
|
public async postPostIDWithAccess(name: string, minLevel: PostAccessLevel = PostAccessLevel.BASIC_ACCESS) : Promise<number> {
|
|
|
|
const postID = await this.postPostID(name);
|
|
|
|
|
|
|
|
if(await PostsHelper.GetAccessLevelFromPostID(this.optionnalUserID, postID) < minLevel)
|
|
|
|
this.error(401, "Your are not allowed to access this post information!");
|
|
|
|
|
|
|
|
return postID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the ID of a comment that the user is allowed to access
|
|
|
|
*
|
|
|
|
* @param name The name of the comment field
|
|
|
|
*/
|
|
|
|
public async postCommentIDWithAccess(name: string) : Promise<number> {
|
|
|
|
const commentID = this.postInt(name);
|
|
|
|
|
|
|
|
if(!await CommentsHelper.Exists(commentID))
|
|
|
|
this.error(404, "Specified comment not found!");
|
|
|
|
|
|
|
|
const postID = await CommentsHelper.GetAssociatedPost(commentID);
|
|
|
|
const post = await PostsHelper.GetSingle(postID);
|
|
|
|
|
|
|
|
if(await PostsHelper.GetAccessLevel(this.getUserId(), post) == PostAccessLevel.NO_ACCESS)
|
|
|
|
this.error(401, "You are not allowed to acess this post information!");
|
|
|
|
|
|
|
|
return commentID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a virtual directory included in a POST request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST variable
|
|
|
|
* @return The virtual directory, if found as valid
|
|
|
|
*/
|
|
|
|
public postVirtualDirectory(name: string) : string {
|
|
|
|
const dir = this.postString(name);
|
|
|
|
|
|
|
|
if(!checkVirtualDirectory(dir))
|
|
|
|
this.error(401, "Specified directory seems to be invalid!");
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an URL included in a POST request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing
|
|
|
|
* the URL
|
|
|
|
*/
|
|
|
|
public postURL(name: string) : string {
|
|
|
|
const url = this.postString(name);
|
|
|
|
|
|
|
|
if(!checkURL(url))
|
|
|
|
this.error(401, "Specified URL in '"+name+"' seems to be invalid!");
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check the user password included in the request
|
|
|
|
*
|
|
|
|
* @param postField The name of the post field
|
|
|
|
* containing user password
|
|
|
|
*/
|
|
|
|
public async needUserPostPassword(postField: string) {
|
|
|
|
const password = this.postString(postField, 3);
|
|
|
|
|
|
|
|
if(!await AccountHelper.CheckUserPassword(this.getUserId(), password))
|
|
|
|
this.error(401, "Invalid password!");
|
|
|
|
}
|
2020-04-01 09:11:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get and return safely a conversation ID specified in a $_POST Request
|
|
|
|
*
|
|
|
|
* @param name The name of the POST field containing the ID of the conversation
|
|
|
|
* @param handler
|
|
|
|
*/
|
|
|
|
public async postConversationId(name : string) : Promise<number> {
|
|
|
|
const convID = this.postInt(name);
|
|
|
|
|
|
|
|
// Check out whether the user belongs to the conversation or not
|
|
|
|
if(!await ConversationsHelper.DoesUsersBelongsTo(this.getUserId(), convID))
|
|
|
|
this.error(401, "You are not allowed to perform queries on this conversation!");
|
|
|
|
|
|
|
|
return convID;
|
|
|
|
}
|
2020-03-31 12:03:26 +00:00
|
|
|
}
|