mirror of
				https://gitlab.com/comunic/comunicapiv2
				synced 2025-11-04 11:34:04 +00:00 
			
		
		
		
	Implement groups visibility system
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
				
			|||||||
import { RequestHandler } from "../entities/RequestHandler";
 | 
					import { RequestHandler } from "../entities/RequestHandler";
 | 
				
			||||||
import { GroupsHelper } from "../helpers/GroupsHelper";
 | 
					import { GroupsHelper } from "../helpers/GroupsHelper";
 | 
				
			||||||
 | 
					import { GroupsAccessLevel } from "../entities/Group";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Groups API controller
 | 
					 * Groups API controller
 | 
				
			||||||
@@ -18,4 +19,13 @@ export class GroupsController {
 | 
				
			|||||||
		h.send(await GroupsHelper.GetListUser(h.getUserId()));
 | 
							h.send(await GroupsHelper.GetListUser(h.getUserId()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get information about a single group
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param h Request handler
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static async GetInfoSingle(h: RequestHandler) {
 | 
				
			||||||
 | 
							const groupID = await h.postGroupIDWithAccess("id", GroupsAccessLevel.LIMITED_ACCESS);
 | 
				
			||||||
 | 
							h.send("Good progress!");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -86,4 +86,6 @@ export const Routes : Route[] = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Groups controller
 | 
						// Groups controller
 | 
				
			||||||
	{path: "/groups/get_my_list", cb: (h) => GroupsController.GetListUser(h)},
 | 
						{path: "/groups/get_my_list", cb: (h) => GroupsController.GetListUser(h)},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{path: "/groups/get_info", cb: (h) => GroupsController.GetInfoSingle(h)},
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/entities/Group.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/entities/Group.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Single group information
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @author Pierre HUBERT
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Group visibility level
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export enum GroupVisibilityLevel {
 | 
				
			||||||
 | 
						OPEN_GROUP = 0,
 | 
				
			||||||
 | 
						PRIVATE_GROUP = 1,
 | 
				
			||||||
 | 
						SECRETE_GROUP = 2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Access level of a user to a group
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export enum GroupsAccessLevel {
 | 
				
			||||||
 | 
						NO_ACCESS = 0, //Can not even know if the group exists or not
 | 
				
			||||||
 | 
						LIMITED_ACCESS = 1, //Access to the name of the group only
 | 
				
			||||||
 | 
						VIEW_ACCESS = 2, //Can see the posts of the group, but not a member of the group
 | 
				
			||||||
 | 
						MEMBER_ACCESS = 3, //Member access (same as view access but as member)
 | 
				
			||||||
 | 
						MODERATOR_ACCESS = 4, //Can create posts, even if posts creation is restricted
 | 
				
			||||||
 | 
						ADMIN_ACCESS = 5, //Can do everything
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/entities/GroupMember.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/entities/GroupMember.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Group membership information
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @author Pierre HUBERT
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum GroupMembershipLevels {
 | 
				
			||||||
 | 
						ADMINISTRATOR = 0,
 | 
				
			||||||
 | 
					    MODERATOR = 1,
 | 
				
			||||||
 | 
						MEMBER = 2,
 | 
				
			||||||
 | 
						INVITED = 3,
 | 
				
			||||||
 | 
						PENDING = 4, //When the group membership has not been approved yet
 | 
				
			||||||
 | 
						VISITOR = 5, //Simple visitor
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,6 +7,8 @@ import { UploadedFile } from "express-fileupload";
 | 
				
			|||||||
import { prepareFileCreation, generateNewUserDataFileName, pathUserData } from "../utils/UserDataUtils";
 | 
					import { prepareFileCreation, generateNewUserDataFileName, pathUserData } from "../utils/UserDataUtils";
 | 
				
			||||||
import * as sharp from 'sharp';
 | 
					import * as sharp from 'sharp';
 | 
				
			||||||
import { UserHelper } from "../helpers/UserHelper";
 | 
					import { UserHelper } from "../helpers/UserHelper";
 | 
				
			||||||
 | 
					import { GroupsAccessLevel } from "./Group";
 | 
				
			||||||
 | 
					import { GroupsHelper } from "../helpers/GroupsHelper";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Response to a request
 | 
					 * Response to a request
 | 
				
			||||||
@@ -196,6 +198,41 @@ export class RequestHandler {
 | 
				
			|||||||
		return userID;
 | 
							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.getUserId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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 information about an uploaded file
 | 
						 * Get information about an uploaded file
 | 
				
			||||||
	 * 
 | 
						 * 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
import { DatabaseHelper } from "./DatabaseHelper";
 | 
					import { DatabaseHelper } from "./DatabaseHelper";
 | 
				
			||||||
 | 
					import { GroupsAccessLevel, GroupVisibilityLevel } from "../entities/Group";
 | 
				
			||||||
 | 
					import { GroupMembershipLevels } from "../entities/GroupMember";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Groups helper
 | 
					 * Groups helper
 | 
				
			||||||
@@ -11,6 +13,20 @@ const GROUPS_MEMBERS_TABLE = "comunic_groups_members";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export class GroupsHelper {
 | 
					export class GroupsHelper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Check out whether a group exists or not
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param groupID Target group ID
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static async Exists(groupID: number) : Promise<boolean> {
 | 
				
			||||||
 | 
							return await DatabaseHelper.Count({
 | 
				
			||||||
 | 
								table: GROUPS_LIST_TABLE,
 | 
				
			||||||
 | 
								where: {
 | 
				
			||||||
 | 
									id: groupID
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}) > 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Get the list of groups of a user
 | 
						 * Get the list of groups of a user
 | 
				
			||||||
	 * 
 | 
						 * 
 | 
				
			||||||
@@ -28,4 +44,86 @@ export class GroupsHelper {
 | 
				
			|||||||
		return list.map(e => e.groups_id);
 | 
							return list.map(e => e.groups_id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get the visibility level of a group
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param groupID Target group ID
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static async GetVisibility(groupID: number) : Promise<GroupVisibilityLevel> {
 | 
				
			||||||
 | 
							const result = await DatabaseHelper.QueryRow({
 | 
				
			||||||
 | 
								table: GROUPS_LIST_TABLE,
 | 
				
			||||||
 | 
								where: {
 | 
				
			||||||
 | 
									id: groupID
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								fields: ["visibility"]
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(result == null)
 | 
				
			||||||
 | 
								throw Error("Group " + groupID + " does not exists!");
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return result.visibility;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get the membership level of a user for a group
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param groupID The ID of target group
 | 
				
			||||||
 | 
						 * @param userID The ID of target user
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static async GetMembershipLevel(groupID: number, userID: number) : Promise<GroupMembershipLevels> {
 | 
				
			||||||
 | 
							const result = await DatabaseHelper.Query({
 | 
				
			||||||
 | 
								table: GROUPS_MEMBERS_TABLE,
 | 
				
			||||||
 | 
								where: {
 | 
				
			||||||
 | 
									groups_id: groupID,
 | 
				
			||||||
 | 
									user_id: userID
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								fields: ["level"]
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// If user has no membership
 | 
				
			||||||
 | 
							if(result.length == 0)
 | 
				
			||||||
 | 
								return GroupMembershipLevels.VISITOR;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return result[0].level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Get the current access of a user to a group
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @param groupID The ID of the target group
 | 
				
			||||||
 | 
						 * @param userID The ID of the target user
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static async GetAccessLevel(groupID: number, userID: number) : Promise<GroupsAccessLevel> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const membershipLevel = 
 | 
				
			||||||
 | 
								userID > 0 ? await this.GetMembershipLevel(userID, groupID) : GroupMembershipLevels.VISITOR;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//Check if the user is a confirmed member of group
 | 
				
			||||||
 | 
							if(membershipLevel == GroupMembershipLevels.ADMINISTRATOR)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.ADMIN_ACCESS;
 | 
				
			||||||
 | 
							if(membershipLevel == GroupMembershipLevels.MODERATOR)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.MODERATOR_ACCESS;
 | 
				
			||||||
 | 
							if(membershipLevel == GroupMembershipLevels.MEMBER)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.MEMBER_ACCESS;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							const groupVisibilityLevel = await this.GetVisibility(groupID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//If the group is open, everyone has view access
 | 
				
			||||||
 | 
							if(groupVisibilityLevel == GroupVisibilityLevel.OPEN_GROUP)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.VIEW_ACCESS;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//Else, all pending and invited membership get limited access
 | 
				
			||||||
 | 
							if(membershipLevel == GroupMembershipLevels.PENDING ||
 | 
				
			||||||
 | 
								membershipLevel == GroupMembershipLevels.INVITED)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.LIMITED_ACCESS;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//Private groups gives limited access
 | 
				
			||||||
 | 
							if(groupVisibilityLevel == GroupVisibilityLevel.PRIVATE_GROUP)
 | 
				
			||||||
 | 
								return GroupsAccessLevel.LIMITED_ACCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Else the user can not see the group
 | 
				
			||||||
 | 
							// Especially in the case of secret groupe
 | 
				
			||||||
 | 
							return GroupsAccessLevel.NO_ACCESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user