mirror of
https://gitlab.com/comunic/comunicapiv2
synced 2024-11-22 21:39:22 +00:00
Implement groups visibility system
This commit is contained in:
parent
ee6579efa0
commit
af9e95a914
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user