import { PostKind, PostVisibilityLevel, Post, PostPageKind, PostFile, PostLink, PostAccessLevel } from "../entities/Post"; import { FriendsHelper } from "./FriendsHelper"; import { DatabaseHelper } from "./DatabaseHelper"; import { UserHelper } from "./UserHelper"; import { GroupsHelper } from "./GroupsHelper"; import { GroupMembershipLevels } from "../entities/GroupMember"; /** * Posts helper * * @author Pierre HUBERT */ /** * Table name */ const TABLE_NAME = "texte"; /** * Database mapping */ const PostDBTypes : Record = { "texte": PostKind.POST_KIND_IMAGE, "image": PostKind.POST_KIND_IMAGE, "webpage_link": PostKind.POST_KIND_WEBLINK, "pdf": PostKind.POST_KIND_PDF, "video": PostKind.POST_KIND_MOVIE, "count_down": PostKind.POST_KIND_COUNTDOWN, "sondage": PostKind.POST_KIND_SURVEY, "youtube": PostKind.POST_KIND_YOUTUBE } /** * Posts helper */ export class PostsHelper { /** * Get the posts of a user * * @param userID The ID of the user making the request * @param targetID The ID of the target user * @param startFrom Start point (0 = none) * @param limit Maximum number of messages to fetch */ public static async GetUserPosts(userID: number, targetID: number, startFrom: number = 0, limit: number = 10) : Promise> { if(limit < 1) throw Error("Limit of post query must be greater or equal to one!"); // Determine max user visibility let level : PostVisibilityLevel = PostVisibilityLevel.VISIBILITY_PUBLIC; if(userID == targetID) level = PostVisibilityLevel.VISIBILITY_USER; else if(userID > 0 && await FriendsHelper.AreFriend(userID, targetID)) level = PostVisibilityLevel.VISIBILITY_FRIENDS; // Preprocess conditions /// ============= PERMISSION CONDITIONS ================= // Visibility level let customWhere = "((niveau_visibilite <= ?) "; let customWhereArgs = [level.toString()]; // Add user post (if user signed in) if(userID > 0) { customWhere += " OR (ID_amis = ?) "; customWhereArgs.push(userID.toString()); } customWhere += ")" /// ============= /PERMISSION CONDITIONS ================ // ============== START POINT CONDITION ================= if(startFrom != 0) { customWhere += " AND ID <= ?"; customWhereArgs.push(startFrom.toString()); } // ============== /START POINT CONDITION ================ // Perform the request const entries = await DatabaseHelper.Query({ table: TABLE_NAME, // Base conditions where: { ID_personne: targetID, group_id: 0 }, customWhere: customWhere, customWhereArgs: customWhereArgs, order: "ID DESC", limit: limit, }); return entries.map((r) => this.DBToPost(r)); } /** * Get the access level of a user over a post * * @param userID Target user ID * @param post Target post */ public static async GetAccessLevel(userID: number, post: Post) : Promise { // User is the owner of the post if(userID == post.userID) return PostAccessLevel.FULL_ACCESS; // User page if(post.kindPage == PostPageKind.PAGE_KIND_USER) { // Post made on user page if(post.pageID == userID) return PostAccessLevel.INTERMEDIATE_ACCESS; // Check if the post is private if(post.visibilityLevel == PostVisibilityLevel.VISIBILITY_USER) return PostAccessLevel.NO_ACCESS; // In case the post is only for friends else if(post.visibilityLevel == PostVisibilityLevel.VISIBILITY_FRIENDS) { if(userID < 1 /* user not signed in */ || !await FriendsHelper.AreFriend(userID, post.pageID) /* not a friend */) return PostAccessLevel.NO_ACCESS; else return PostAccessLevel.BASIC_ACCESS; } // In case of public post else if(post.visibilityLevel == PostVisibilityLevel.VISIBILITY_PUBLIC) { // Check if the user can see the page if(await UserHelper.CanSeeUserPage(userID, post.userPageID)) return PostAccessLevel.BASIC_ACCESS; // Else no access to the user return PostAccessLevel.NO_ACCESS; } } // Group page else if(post.kindPage == PostPageKind.PAGE_KIND_GROUP) { // TODO : check this code const accessLevel = await GroupsHelper.GetMembershipLevel(userID, post.groupID); // Moderator & admin = intermediate access if(accessLevel < GroupMembershipLevels.MEMBER) return PostAccessLevel.INTERMEDIATE_ACCESS; // Members can see all the posts of a group if(accessLevel == GroupMembershipLevels.MEMBER) return PostAccessLevel.BASIC_ACCESS; // Now we check if the post is public & the group is open if(post.visibilityLevel != PostVisibilityLevel.VISIBILITY_PUBLIC || !await GroupsHelper.IsOpen(post.groupID)) return PostAccessLevel.NO_ACCESS; // Public post + open group = basic access return PostAccessLevel.BASIC_ACCESS; } throw Error("GetAccessLevel reached an unimplemented status!"); } /** * Turn a database entry into a row object * * @param row The database entry */ private static DBToPost(row: any) : Post { const postPageKind = row.group_id == 0 ? PostPageKind.PAGE_KIND_USER : PostPageKind.PAGE_KIND_GROUP; const postType = PostDBTypes[row.type]; return new Post({ // General info id: row.ID, userID: row.ID_amis == 0 ? row.ID_personne : row.ID_amis, // Kind of target of the page and its ID kindPage: postPageKind, pageID: postPageKind == PostPageKind.PAGE_KIND_USER ? row.ID_personne : row.group_id, // Basic info timeCreate: row.time_insert == null ? (new Date(row.date_envoi).getTime() / 1000) : row.time_insert, content: row.texte, visibilityLevel: row.niveau_visibilite, kind: postType, // Files specific file: row.path == null ? undefined : new PostFile({ size: Number(row.size), type: row.file_type, path: row.path }), // Movies specific movieID: row.idvideo == null ? undefined : row.idvideo, // Coutdown timer specific timeEnd: (row.time_end && row.time_end) > 0 ? row.time_end // Coutdown legacy support : (row.annee_fin && row.annee_fin > 2010 ? new Date(row.annee_fin + "/" + row.mois_fin + "/" + row.jour_fin).getTime() / 1000 : undefined), // Weblink - specific link: row.url_page == null ? undefined : new PostLink({ url: row.url_page, title: row.titre_page, description: row.description_page, image: row.image_page }), }); } }