mirror of
https://gitlab.com/comunic/comunicapiv2
synced 2024-11-27 07:49:22 +00:00
460 lines
12 KiB
TypeScript
460 lines
12 KiB
TypeScript
import { RequestHandler } from "../entities/RequestHandler";
|
|
import { UserHelper } from "../helpers/UserHelper";
|
|
import { PostsHelper } from "../helpers/PostsHelper";
|
|
import { Post, PostVisibilityLevel, PostKind, PostAccessLevel, PostPageKind, PostFile, PostLink } from "../entities/Post";
|
|
import { MoviesController } from "./MoviesController";
|
|
import { MoviesHelper } from "../helpers/MoviesHelper";
|
|
import { SurveyHelper } from "../helpers/SurveyHelper";
|
|
import { SurveyController } from "./SurveyController";
|
|
import { LikesHelper, LikesType } from "../helpers/LikesHelper";
|
|
import { CommentsHelper } from "../helpers/CommentsHelper";
|
|
import { CommentsController } from "./CommentsController";
|
|
import { GroupsAccessLevel } from "../entities/Group";
|
|
import { GroupsHelper } from "../helpers/GroupsHelper";
|
|
import { time } from "../utils/DateUtils";
|
|
import { findKey } from "../utils/ArrayUtils";
|
|
import { check_string_before_insert, check_youtube_id, checkURL } from "../utils/StringUtils";
|
|
import { pathUserData } from "../utils/UserDataUtils";
|
|
import { statSync } from "fs";
|
|
import { lookup } from "mime-types";
|
|
import { NewSurvey } from "../entities/NewSurvey";
|
|
import { FriendsHelper } from "../helpers/FriendsHelper";
|
|
import { NotifEventType } from "../entities/Notification";
|
|
import { NotificationsHelper } from "../helpers/NotificationsHelper";
|
|
|
|
/**
|
|
* Posts controller
|
|
*
|
|
* @author Pierre HUBERT
|
|
*/
|
|
|
|
const VISIBILITY_LEVELS_API = {};
|
|
VISIBILITY_LEVELS_API[PostVisibilityLevel.VISIBILITY_PUBLIC] = "public";
|
|
VISIBILITY_LEVELS_API[PostVisibilityLevel.VISIBILITY_FRIENDS] = "friends";
|
|
VISIBILITY_LEVELS_API[PostVisibilityLevel.VISIBILITY_USER] = "private";
|
|
VISIBILITY_LEVELS_API[PostVisibilityLevel.VISIBILITY_GROUP_MEMBERS] = "members";
|
|
|
|
|
|
const ACCESS_LEVELS_API = {};
|
|
ACCESS_LEVELS_API[PostAccessLevel.NO_ACCESS] = "no-access";
|
|
ACCESS_LEVELS_API[PostAccessLevel.BASIC_ACCESS] = "basic";
|
|
ACCESS_LEVELS_API[PostAccessLevel.INTERMEDIATE_ACCESS] = "intermediate";
|
|
ACCESS_LEVELS_API[PostAccessLevel.FULL_ACCESS] = "full";
|
|
|
|
|
|
export class PostsController {
|
|
|
|
/**
|
|
* Get the posts of a user
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async GetListUser(h: RequestHandler) {
|
|
const userID = await h.postUserId("userID");
|
|
const startFrom = h.postInt("startFrom", 0);
|
|
|
|
if(!await UserHelper.CanSeeUserPage(h.optionnalUserID, userID))
|
|
h.error(401, "You are not allowed to access this user posts !");
|
|
|
|
const posts = await PostsHelper.GetUserPosts(h.optionnalUserID, userID, startFrom);
|
|
|
|
await this.SendMultiplePosts(h, posts);
|
|
}
|
|
|
|
/**
|
|
* Get the list of posts of a group
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async GetListGroup(h: RequestHandler) {
|
|
const groupID = await h.postGroupIDWithAccess("groupID", GroupsAccessLevel.VIEW_ACCESS);
|
|
const startFrom = h.postInt("startFrom", 0);
|
|
|
|
const posts = await PostsHelper.GetGroupPosts(h.optionnalUserID, groupID, startFrom);
|
|
|
|
await this.SendMultiplePosts(h, posts);
|
|
}
|
|
|
|
/**
|
|
* Get the list of latest posts
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async GetLatest(h: RequestHandler) {
|
|
const startFrom = h.postInt("startFrom", 0);
|
|
const includeGroups = h.postBool('include_groups', false);
|
|
|
|
const posts = await PostsHelper.GetLatest(h.getUserId(), startFrom, 10, includeGroups);
|
|
|
|
await this.SendMultiplePosts(h, posts);
|
|
}
|
|
|
|
/**
|
|
* Get information about a single post
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async GetSingle(h: RequestHandler) {
|
|
const postID = await h.postPostIDWithAccess("postID");
|
|
|
|
const post = await PostsHelper.GetSingle(postID);
|
|
|
|
h.send(await this.PostToAPI(h, post));
|
|
}
|
|
|
|
/**
|
|
* Create a new post
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async CreatePost(h: RequestHandler) {
|
|
|
|
// Determine the target for the new post
|
|
let kindPage: PostPageKind;
|
|
let pageID: number;
|
|
|
|
let survey : NewSurvey | undefined = undefined;
|
|
|
|
switch(h.postString("kind-page")) {
|
|
|
|
// If the post is targetting a user
|
|
case "user":
|
|
kindPage = PostPageKind.PAGE_KIND_USER;
|
|
pageID = await h.postUserId("kind-id");
|
|
|
|
if(!await UserHelper.CanCreatePosts(h.getUserId(), pageID))
|
|
h.error(401, "You are not allowed to create posts on this page!");
|
|
|
|
break;
|
|
|
|
// For groups
|
|
case "group":
|
|
kindPage = PostPageKind.PAGE_KIND_GROUP;
|
|
pageID = await h.postGroupIDWithAccess("kind-id", GroupsAccessLevel.MEMBER_ACCESS);
|
|
|
|
// Check if the user can create posts on this group
|
|
if(!await GroupsHelper.CanUserCreatePosts(pageID, h.getUserId()))
|
|
h.error(401, "You are not allowed to create posts on this group!");
|
|
|
|
break;
|
|
|
|
default:
|
|
h.error(500, "Unsupported kind of page!");
|
|
|
|
}
|
|
|
|
// Initialize new post information
|
|
const newPost = new Post({
|
|
// Basic information about the post
|
|
id: -1,
|
|
userID: h.getUserId(),
|
|
timeCreate: time(),
|
|
kind: <PostKind>h.postString("kind"),
|
|
content: h.postContent("content", 0),
|
|
visibilityLevel: this.PostVisibilityLevel(h, "visibility"),
|
|
|
|
// Post target
|
|
kindPage: kindPage,
|
|
pageID: pageID,
|
|
|
|
});
|
|
|
|
// Process each kind of post
|
|
switch(newPost.kind) {
|
|
|
|
// Text posts
|
|
case PostKind.POST_KIND_TEXT:
|
|
|
|
// Check the string
|
|
if(!check_string_before_insert(newPost.content))
|
|
h.error(400, "Specified post content is invalid!");
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Image posts
|
|
case PostKind.POST_KIND_IMAGE:
|
|
|
|
if(!h.hasFile("image"))
|
|
h.error(400, "An error occured while receiving the image!");
|
|
|
|
// Save image
|
|
const path = await h.savePostImage("image", "imgpost", 2000, 2000);
|
|
|
|
newPost.file = new PostFile({
|
|
path: path,
|
|
type: <string>lookup(pathUserData(path, true)),
|
|
size: statSync(pathUserData(path, true)).size
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
// YouTube posts
|
|
case PostKind.POST_KIND_YOUTUBE:
|
|
|
|
const youtubeID = h.postString("youtube_id");
|
|
|
|
if(!check_youtube_id(youtubeID))
|
|
h.error(400, "Invalid YouTube ID!");
|
|
|
|
newPost.file = new PostFile({
|
|
path: youtubeID,
|
|
size: 0,
|
|
type: "youtube"
|
|
})
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Personnal movies posts
|
|
case PostKind.POST_KIND_MOVIE:
|
|
const movieID = h.postInt("movieID");
|
|
|
|
if(!await MoviesHelper.DoesUserHas(h.getUserId(), movieID))
|
|
h.error(401, "You are not authorized to use this movie!");
|
|
|
|
newPost.movieID = movieID;
|
|
|
|
break;
|
|
|
|
|
|
// Web links posts
|
|
case PostKind.POST_KIND_WEBLINK:
|
|
|
|
const url = h.postURL("url");
|
|
|
|
// For now, for safety, we do not fetch page content
|
|
newPost.link = new PostLink({
|
|
url: url,
|
|
title: undefined,
|
|
description: undefined,
|
|
image: undefined
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
// PDF posts
|
|
case PostKind.POST_KIND_PDF:
|
|
|
|
if(!h.hasFile("pdf"))
|
|
h.error(401, "Missing PDF in 'pdf'!");
|
|
|
|
const pdf_path = await h.savePostFile("pdf", "post_pdf", "pdf", "application/pdf");
|
|
|
|
newPost.file = new PostFile({
|
|
path: pdf_path,
|
|
type: <string>lookup(pathUserData(pdf_path, true)),
|
|
size: statSync(pathUserData(pdf_path, true)).size
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
// Countdown timers
|
|
case PostKind.POST_KIND_COUNTDOWN:
|
|
newPost.timeEnd = h.postInt("time-end");
|
|
break;
|
|
|
|
|
|
// Survey controller
|
|
case PostKind.POST_KIND_SURVEY:
|
|
|
|
// Create the survey
|
|
survey = new NewSurvey({
|
|
question: h.postString("question"),
|
|
userID: h.getUserId(),
|
|
choices: h.postString("answers").split("<>")
|
|
})
|
|
|
|
if(survey.choices.length < 2)
|
|
h.error(401, "Survey must have at least two answers!");
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
h.error(500, "Unsupported kind of post!");
|
|
}
|
|
|
|
// Create the post
|
|
const postID = await PostsHelper.Create(newPost);
|
|
|
|
// Create associated survey (if any)
|
|
if(survey != undefined) {
|
|
survey.postID = postID;
|
|
SurveyHelper.Create(survey);
|
|
}
|
|
|
|
|
|
// Create a notification
|
|
await NotificationsHelper.CreatePostNotification(
|
|
h.getUserId(), postID, NotifEventType.ELEM_CREATED);
|
|
|
|
h.send({
|
|
success: "The post has been created!",
|
|
postID: postID
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Change the visiblity level of a post
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async SetVisibilityLevel(h: RequestHandler) {
|
|
|
|
const postID = await h.postPostIDWithAccess("postID", PostAccessLevel.FULL_ACCESS);
|
|
const newVisibility = this.PostVisibilityLevel(h, "new_level");
|
|
|
|
await PostsHelper.SetLevel(postID, newVisibility);
|
|
|
|
// Depending on new level, delete (or not) notifications about the post
|
|
if(newVisibility == PostVisibilityLevel.VISIBILITY_USER)
|
|
await NotificationsHelper.DeleteAllRelatedWithPost(postID);
|
|
|
|
h.success("");
|
|
}
|
|
|
|
/**
|
|
* Update the content of a post
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async UpdateContent(h: RequestHandler) {
|
|
const postID = await h.postPostIDWithAccess("postID", PostAccessLevel.FULL_ACCESS);
|
|
const content = h.postContent("new_content");
|
|
|
|
if(!check_string_before_insert(content))
|
|
h.error(401, "Given content is invalid!");
|
|
|
|
await PostsHelper.SetContent(postID, content);
|
|
|
|
// Delete notifications targetting current user about the post
|
|
await NotificationsHelper.DeleteAllPostsNotificationsTargetingUser(h.getUserId(), postID);
|
|
|
|
h.success();
|
|
}
|
|
|
|
/**
|
|
* Delete a post
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async DeletePost(h: RequestHandler) {
|
|
const postID = await h.postPostIDWithAccess("postID", PostAccessLevel.INTERMEDIATE_ACCESS);
|
|
|
|
await PostsHelper.Delete(postID);
|
|
|
|
h.success();
|
|
}
|
|
|
|
/**
|
|
* Get the lists of targets where the current user can create posts
|
|
*
|
|
* @param h Request handler
|
|
*/
|
|
public static async GetTargets(h: RequestHandler) {
|
|
const friends = await FriendsHelper.GetListThatAllowsPostsFromUser(h.getUserId());
|
|
const groups = await GroupsHelper.GetListUserWhereCanCreatePosts(h.getUserId());
|
|
|
|
h.send({
|
|
friends: friends,
|
|
groups: groups
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Send multiple posts to the API
|
|
*
|
|
* @param h Request handler
|
|
* @param posts The list of post to send
|
|
*/
|
|
private static async SendMultiplePosts(h: RequestHandler, posts: Array<Post>) {
|
|
let list = [];
|
|
for (const p of posts) {
|
|
list.push(await this.PostToAPI(h, p));
|
|
}
|
|
|
|
h.send(list);
|
|
}
|
|
|
|
|
|
/**
|
|
* Turn a post object into an API entry
|
|
*
|
|
* @param h Request handler
|
|
* @param p The post
|
|
*/
|
|
public static async PostToAPI(h: RequestHandler, p: Post) : Promise<any> {
|
|
let data : any = {
|
|
ID: p.id,
|
|
userID: p.userID,
|
|
user_page_id: p.userPageID,
|
|
group_id: p.groupID,
|
|
post_time: p.timeCreate,
|
|
content: p.hasContent ? p.content : null,
|
|
visibility_level: VISIBILITY_LEVELS_API[p.visibilityLevel],
|
|
kind: p.kind,
|
|
|
|
|
|
// File specific
|
|
file_size: !p.hasFile ? null : p.file.size,
|
|
file_type: !p.hasFile ? null : p.file.type,
|
|
file_path: !p.hasFile ? null : p.file.path,
|
|
file_path_url: !p.hasFile ? null : p.file.url,
|
|
|
|
|
|
// Movie specific
|
|
video_id: p.hasMovie ? p.movieID : null,
|
|
video_info: p.hasMovie ?
|
|
MoviesController.MovieToAPI(await MoviesHelper.GetInfo(p.movieID)) : null,
|
|
|
|
|
|
// Countdown timer specific
|
|
time_end: p.hasTimeEnd ? p.timeEnd : null,
|
|
|
|
// Weblink specific
|
|
link_url: !p.hasLink ? null : p.link.url,
|
|
link_title: !p.hasLink ? null : p.link.title,
|
|
link_description: !p.hasLink ? null : p.link.description,
|
|
link_image: !p.hasLink ? null : p.link.image,
|
|
|
|
|
|
// Survey specific
|
|
data_survey: !p.hasSurvey ? null : await SurveyController.SurveyToAPI(h, await SurveyHelper.GetInfo(p.id)),
|
|
|
|
|
|
// Likes information
|
|
likes: await LikesHelper.Count(p.id, LikesType.POST),
|
|
userlike: h.signedIn ? await LikesHelper.IsLiking(h.getUserId(), p.id, LikesType.POST) : false,
|
|
|
|
// Determine user access level
|
|
user_access: ACCESS_LEVELS_API[await PostsHelper.GetAccessLevel(h.optionnalUserID, p)],
|
|
|
|
// Load comments (if possible)
|
|
comments: await PostsHelper.AllowCommentsOnPost(p) ? await CommentsController.CommentsToAPI(h, await CommentsHelper.Get(p.id)) : null,
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Get the visibility level for a POST included in a request
|
|
*
|
|
* @param h Request handler
|
|
* @param name The name of the POST field containing the visibility level of the user
|
|
*/
|
|
private static PostVisibilityLevel(h: RequestHandler, name: string) : PostVisibilityLevel {
|
|
const levelKey = findKey(VISIBILITY_LEVELS_API, h.postString(name, 3));
|
|
if(levelKey == null)
|
|
h.error(400, "Post visibility level level not recognized!");
|
|
return <PostVisibilityLevel>Number(levelKey);
|
|
}
|
|
} |