From b6294870ce24b490a046a539ca1d8aced51a3d9d Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 23 Nov 2019 16:10:51 +0100 Subject: [PATCH] Start to process user account image --- src/controllers/UserController.ts | 25 ++++++++++- src/entities/AccountImage.ts | 43 ++++++++++++++++++ src/entities/RequestHandler.ts | 7 +++ src/entities/User.ts | 5 +++ src/helpers/AccountImageHelper.ts | 75 +++++++++++++++++++++++++++++++ src/helpers/UserHelper.ts | 6 ++- src/utils/UserDataUtils.ts | 22 +++++++++ 7 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 src/entities/AccountImage.ts create mode 100644 src/helpers/AccountImageHelper.ts create mode 100644 src/utils/UserDataUtils.ts diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 73f2b64..439cb23 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -1,6 +1,7 @@ import { RequestHandler } from "../entities/RequestHandler"; import { UserHelper } from "../helpers/UserHelper"; import { User, UserPageStatus } from "../entities/User"; +import { AccountImage, AccountImageVisibilityLevel } from "../entities/AccountImage"; /** * User information controller @@ -20,7 +21,7 @@ export class UserController { if(!user) handler.error(404, "Could not get user data!"); - handler.send(this.UserToAPI(user)); + handler.send(this.UserToAPI(user, handler)); } /** @@ -30,7 +31,7 @@ export class UserController { } - private static UserToAPI(user : User) : any { + private static UserToAPI(user : User, handler: RequestHandler) : Object { return { "userID": user.id, "firstName": user.firstName, @@ -38,6 +39,26 @@ export class UserController { "publicPage": user.pageStatus == UserPageStatus.PUBLIC, "openPage": user.pageStatus == UserPageStatus.OPEN, "virtualDirectory": user.virtualDirectory, + "accountImage": this.GetAccountImageURL(user.accountImage, handler) }; } + + private static GetAccountImageURL(image : AccountImage, handler: RequestHandler) { + + if(image.level == AccountImageVisibilityLevel.EVERYONE + || (handler.signedIn && handler.getUserId() == image.userID)) + return image.url; + + if(image.level == AccountImageVisibilityLevel.COMUNIC_USERS) { + if(handler.signedIn) + return image.url; + else + return AccountImage.errorURL; + } + + // TODO : implement frienship support + console.error("ERR: Can not check friends for now (for account image)!"); + + return AccountImage.errorURL; + } } \ No newline at end of file diff --git a/src/entities/AccountImage.ts b/src/entities/AccountImage.ts new file mode 100644 index 0000000..a53cddd --- /dev/null +++ b/src/entities/AccountImage.ts @@ -0,0 +1,43 @@ +import { pathUserData } from "../utils/UserDataUtils"; + +/** + * Single user account image + * + * @author Pierre HUBERT + */ + +const defaultAccountImage = "0Reverse.png"; +const errorAccountImage = "0Red.png"; + +export enum AccountImageVisibilityLevel { + FRIENDS = 1, + COMUNIC_USERS = 2, + EVERYONE = 3 +} + +export class AccountImage { + + public constructor( + public userID: number, + public path : string, + public level: AccountImageVisibilityLevel + ) {} + + /** + * Get account image URL + */ + get url() : string { + if(this.path.length < 1) + return AccountImage.urlForFile(defaultAccountImage); + + return AccountImage.urlForFile(this.path); + } + + static get errorURL() : string { + return this.urlForFile(errorAccountImage); + } + + private static urlForFile(file : string) : string { + return pathUserData("avatars/" + file, false); + } +} \ No newline at end of file diff --git a/src/entities/RequestHandler.ts b/src/entities/RequestHandler.ts index b4a750c..26fcf3b 100644 --- a/src/entities/RequestHandler.ts +++ b/src/entities/RequestHandler.ts @@ -167,6 +167,13 @@ export class RequestHandler { return this.userID; } + /** + * Check out whether user is signed in or not + */ + public get signedIn() : boolean { + return this.userID > 0; + } + /** * Output an error code and throws an error * diff --git a/src/entities/User.ts b/src/entities/User.ts index f53d046..c81cf61 100644 --- a/src/entities/User.ts +++ b/src/entities/User.ts @@ -1,3 +1,5 @@ +import { AccountImage } from "./AccountImage"; + /** * User information * @@ -17,6 +19,7 @@ export interface UserBuilder { timeCreate: number, virtualDirectory: string, pageStatus: UserPageStatus, + accountImage: AccountImage, } export class User { @@ -26,6 +29,7 @@ export class User { timeCreate: number; virtualDirectory: string; pageStatus: UserPageStatus; + accountImage: AccountImage; public constructor(info : UserBuilder) { this.id = info.id; @@ -34,6 +38,7 @@ export class User { this.timeCreate = info.timeCreate; this.virtualDirectory = info.virtualDirectory; this.pageStatus = info.pageStatus; + this.accountImage = info.accountImage; } } \ No newline at end of file diff --git a/src/helpers/AccountImageHelper.ts b/src/helpers/AccountImageHelper.ts new file mode 100644 index 0000000..ef59794 --- /dev/null +++ b/src/helpers/AccountImageHelper.ts @@ -0,0 +1,75 @@ +import { pathUserData } from "../utils/UserDataUtils"; +import { existsSync, readFileSync } from "fs"; +import { AccountImage, AccountImageVisibilityLevel } from "../entities/AccountImage"; + +/** + * Account image helper + * + * @author Pierre HUBERT + */ + +export class AccountImageHelper { + + /** + * Get information about the account image of a specific user ID + * + * @param userID Target user ID + * @return The path to user image + */ + public static async Get(userID : number) : Promise { + + const accountImageFileContent = this.GetFileAccountImage(userID); + const level = this.GetVisibilityLevel(userID); + + return new AccountImage(userID, accountImageFileContent, level); + } + + /** + * Get the content of the file associated to the user account image, if any + * + * @param userID Target user ID + * @returns The content of the file + */ + private static GetFileAccountImage(userID: number) : string { + const fileName = this.GetPathMetadataFile(userID); + + if(!existsSync(fileName)) + return ""; + + return readFileSync(fileName, {encoding: "utf-8"}); + + } + + /** + * Get the visibility leve of a user account image + * + * @param userID Target user ID + */ + private static GetVisibilityLevel(userID: number) : AccountImageVisibilityLevel { + const filePath = this.GetPathVisibilityFile(userID); + + if(!existsSync(filePath)) + return AccountImageVisibilityLevel.EVERYONE; + + return Number.parseInt(readFileSync(filePath, {encoding: "utf-8"})); + + } + + /** + * Get the path to the file that contains the path to user account image + * + * @param userID Target user ID + */ + private static GetPathMetadataFile(userID: number) { + return pathUserData("avatars/adresse_avatars/" + userID.toString() + ".txt", true); + } + + /** + * Get the path to visibility file + * + * @param userID Target user ID + */ + private static GetPathVisibilityFile(userID: number) { + return pathUserData("avatars/adresse_avatars/limit_view_" + userID + ".txt", true); + } +} \ No newline at end of file diff --git a/src/helpers/UserHelper.ts b/src/helpers/UserHelper.ts index a317830..7d4dff9 100644 --- a/src/helpers/UserHelper.ts +++ b/src/helpers/UserHelper.ts @@ -1,5 +1,6 @@ import { User, UserPageStatus } from "../entities/User"; import { DatabaseHelper } from "./DatabaseHelper"; +import { AccountImageHelper } from "./AccountImageHelper"; /** * User helper @@ -32,14 +33,15 @@ export class UserHelper { } - private static DbToUser(row: any) : User { + private static async DbToUser(row: any) : Promise { return new User({ id: row.ID, firstName: row.prenom, lastName: row.nom, timeCreate: new Date(row.date_creation).getTime()/1000, virtualDirectory: row.sous_repertoire, - pageStatus: row.pageouverte == 1 ? UserPageStatus.OPEN : (row.public == 1 ? UserPageStatus.PUBLIC : UserPageStatus.PRIVATE) + pageStatus: row.pageouverte == 1 ? UserPageStatus.OPEN : (row.public == 1 ? UserPageStatus.PUBLIC : UserPageStatus.PRIVATE), + accountImage: await AccountImageHelper.Get(row.ID) }); } } \ No newline at end of file diff --git a/src/utils/UserDataUtils.ts b/src/utils/UserDataUtils.ts new file mode 100644 index 0000000..21c3602 --- /dev/null +++ b/src/utils/UserDataUtils.ts @@ -0,0 +1,22 @@ +import { conf } from "../helpers/ConfigHelper"; +import { join } from "path"; + +/** + * User data utilities + * + * @author Pierre HUBERT + */ + +/** + * Get and returns the URL path to an userdata file + * + * @param uri Optionnal, defines the URI pointing on the file + * @param sysPath Optionnal, defines if system path is required instead of URL + * @return The full URL to the userdata file + */ +export function pathUserData(uri: string = "", sysPath: boolean = false) : string { + if(!sysPath) + return join(conf().storageURL, uri); + else + return join(conf().storagePath, uri); +} \ No newline at end of file