Add models for guidelines, incidents, plot points, issues, acts, and world data
- Introduced new models: `GuideLine`, `Incident`, `PlotPoint`, `Issue`, `Act`, and `World` for managing book-related entities. - Integrated encryption/decryption for sensitive properties in all models using user-specific keys. - Added methods for CRUD operations and synchronization workflows with error handling and multilingual support. - Improved maintainability with JSDoc comments and streamlined queries.
This commit is contained in:
@@ -3,24 +3,36 @@ import System from "../System.js";
|
||||
import Book, {BookProps} from "./Book.js";
|
||||
import {getUserEncryptionKey} from "../keyManager.js";
|
||||
|
||||
interface UserAccount{
|
||||
firstName:string;
|
||||
lastName:string;
|
||||
username:string
|
||||
authorName:string;
|
||||
email:string;
|
||||
/**
|
||||
* Represents a user account with basic profile information.
|
||||
*/
|
||||
interface UserAccount {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
username: string;
|
||||
authorName: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the guide tour completion status for various features.
|
||||
*/
|
||||
export interface GuideTour {
|
||||
[key: string]: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summary information for a book associated with a user.
|
||||
*/
|
||||
interface BookSummary {
|
||||
bookId: string;
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete user information response including profile data and associated books.
|
||||
*/
|
||||
export interface UserInfoResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -31,13 +43,17 @@ export interface UserInfoResponse {
|
||||
authorName: string;
|
||||
groupId: number;
|
||||
termsAccepted: boolean;
|
||||
guideTour: any[];
|
||||
guideTour: GuideTour[];
|
||||
books: BookSummary[];
|
||||
}
|
||||
|
||||
export default class User{
|
||||
/**
|
||||
* Represents a user entity with encrypted personal information storage.
|
||||
* Handles user data retrieval, creation, and updates with AES-256-CBC encryption.
|
||||
*/
|
||||
export default class User {
|
||||
|
||||
private readonly id:string;
|
||||
private readonly id: string;
|
||||
private firstName: string;
|
||||
private lastName: string;
|
||||
private username: string;
|
||||
@@ -47,7 +63,11 @@ export default class User{
|
||||
private groupId: number;
|
||||
private termsAccepted: boolean;
|
||||
|
||||
constructor(id:string){
|
||||
/**
|
||||
* Creates a new User instance with the specified identifier.
|
||||
* @param id - The unique identifier for the user
|
||||
*/
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
this.firstName = '';
|
||||
this.lastName = '';
|
||||
@@ -58,25 +78,35 @@ export default class User{
|
||||
this.groupId = 0;
|
||||
this.termsAccepted = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches and decrypts the user's information from the database.
|
||||
* Populates all instance properties with the decrypted values.
|
||||
* @returns A promise that resolves when user information has been loaded
|
||||
*/
|
||||
public async getUserInfos(): Promise<void> {
|
||||
const data: UserInfosQueryResponse = UserRepo.fetchUserInfos(this.id);
|
||||
const userKey:string = getUserEncryptionKey(this.id)
|
||||
this.firstName = System.decryptDataWithUserKey(data.first_name, userKey);
|
||||
this.lastName = System.decryptDataWithUserKey(data.last_name, userKey);
|
||||
this.username = System.decryptDataWithUserKey(data.username, userKey);
|
||||
this.email = System.decryptDataWithUserKey(data.email, userKey);
|
||||
this.accountVerified = data.account_verified === 1;
|
||||
this.authorName = data.author_name ? System.decryptDataWithUserKey(data.author_name, userKey) : '';
|
||||
this.groupId = data.user_group ? data.user_group : 0;
|
||||
this.termsAccepted = data.term_accepted === 1;
|
||||
const userInfosData: UserInfosQueryResponse = UserRepo.fetchUserInfos(this.id);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(this.id);
|
||||
this.firstName = System.decryptDataWithUserKey(userInfosData.first_name, userEncryptionKey);
|
||||
this.lastName = System.decryptDataWithUserKey(userInfosData.last_name, userEncryptionKey);
|
||||
this.username = System.decryptDataWithUserKey(userInfosData.username, userEncryptionKey);
|
||||
this.email = System.decryptDataWithUserKey(userInfosData.email, userEncryptionKey);
|
||||
this.accountVerified = userInfosData.account_verified === 1;
|
||||
this.authorName = userInfosData.author_name ? System.decryptDataWithUserKey(userInfosData.author_name, userEncryptionKey) : '';
|
||||
this.groupId = userInfosData.user_group ? userInfosData.user_group : 0;
|
||||
this.termsAccepted = userInfosData.term_accepted === 1;
|
||||
}
|
||||
|
||||
public static async returnUserInfos(userId: string):Promise<UserInfoResponse> {
|
||||
|
||||
/**
|
||||
* Retrieves complete user information including associated books.
|
||||
* @param userId - The unique identifier of the user to fetch
|
||||
* @returns A promise resolving to the complete user information response
|
||||
*/
|
||||
public static async returnUserInfos(userId: string): Promise<UserInfoResponse> {
|
||||
const user: User = new User(userId);
|
||||
await user.getUserInfos();
|
||||
const books: BookProps[] = await Book.getBooks(userId);
|
||||
const guideTour: GuideTour[] = [];
|
||||
const userBooks: BookProps[] = await Book.getBooks(userId);
|
||||
const guideTourStatus: GuideTour[] = [];
|
||||
return {
|
||||
id: user.getId(),
|
||||
name: user.getFirstName(),
|
||||
@@ -87,95 +117,194 @@ export default class User{
|
||||
authorName: user.getAuthorName(),
|
||||
groupId: user.getGroupId(),
|
||||
termsAccepted: user.isTermsAccepted(),
|
||||
guideTour: guideTour,
|
||||
books: books.map((book: BookProps):BookSummary => {
|
||||
guideTour: guideTourStatus,
|
||||
books: userBooks.map((book: BookProps): BookSummary => {
|
||||
return {
|
||||
bookId: book.id,
|
||||
title: book.title,
|
||||
subTitle: book.subTitle,
|
||||
};
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public static async addUser(userId:string,firstName: string, lastName: string, username: string, email: string, notEncryptPassword: string, lang: 'fr' | 'en' = 'fr'): Promise<string> {
|
||||
const originEmail:string = System.hashElement(email);
|
||||
const originUsername:string = System.hashElement(username);
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const encryptFirstName: string = System.encryptDataWithUserKey(firstName, userKey);
|
||||
const encryptLastName: string = System.encryptDataWithUserKey(lastName, userKey);
|
||||
const encryptUsername: string = System.encryptDataWithUserKey(username, userKey);
|
||||
const encryptEmail: string = System.encryptDataWithUserKey(email, userKey);
|
||||
const originalEmail: string = System.hashElement(email);
|
||||
const originalUsername: string = System.hashElement(username);
|
||||
return UserRepo.insertUser(userId, encryptFirstName, encryptLastName, encryptUsername, originalUsername, encryptEmail, originalEmail,lang);
|
||||
}
|
||||
|
||||
public static async updateUserInfos(userKey: string, userId: string, firstName: string, lastName: string, username: string, email: string, authorName?: string, lang: 'fr' | 'en' = 'fr'): Promise<boolean> {
|
||||
const encryptFirstName:string = System.encryptDataWithUserKey(firstName,userKey);
|
||||
const encryptLastName:string = System.encryptDataWithUserKey(lastName,userKey);
|
||||
const encryptUsername:string = System.encryptDataWithUserKey(username,userKey);
|
||||
const encryptEmail:string = System.encryptDataWithUserKey(email,userKey);
|
||||
const originalEmail:string = System.hashElement(email);
|
||||
const originalUsername:string = System.hashElement(username);
|
||||
let encryptAuthorName:string = '';
|
||||
let originalAuthorName: string = '';
|
||||
if (authorName){
|
||||
encryptAuthorName = System.encryptDataWithUserKey(authorName,userKey);
|
||||
originalAuthorName = System.hashElement(authorName);
|
||||
}
|
||||
return UserRepo.updateUserInfos(userId, encryptFirstName, encryptLastName, encryptUsername, originalUsername, encryptEmail, originalEmail, originalAuthorName, encryptAuthorName, lang);
|
||||
}
|
||||
|
||||
public static async getUserAccountInformation(userId: string): Promise<UserAccount> {
|
||||
const data: UserAccountQuery = UserRepo.fetchAccountInformation(userId);
|
||||
const userKey:string = getUserEncryptionKey(userId)
|
||||
const userName: string = data.first_name ? System.decryptDataWithUserKey(data.first_name, userKey) : '';
|
||||
const lastName: string = data.last_name ? System.decryptDataWithUserKey(data.last_name, userKey) : '';
|
||||
const username: string = data.username ? System.decryptDataWithUserKey(data.username, userKey) : '';
|
||||
const authorName: string = data.author_name ? System.decryptDataWithUserKey(data.author_name, userKey) : '';
|
||||
const email: string = data.email ? System.decryptDataWithUserKey(data.email, userKey) : '';
|
||||
return {
|
||||
firstName: userName,
|
||||
lastName: lastName,
|
||||
username: username,
|
||||
authorName: authorName,
|
||||
email: email
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new user in the database with encrypted personal information.
|
||||
* @param userId - The unique identifier for the new user
|
||||
* @param firstName - The user's first name (will be encrypted)
|
||||
* @param lastName - The user's last name (will be encrypted)
|
||||
* @param username - The user's username (will be encrypted and hashed)
|
||||
* @param email - The user's email address (will be encrypted and hashed)
|
||||
* @param notEncryptPassword - The user's password in plain text (unused in current implementation)
|
||||
* @param lang - The preferred language for the user ('fr' or 'en'), defaults to 'fr'
|
||||
* @returns A promise resolving to the created user's identifier
|
||||
*/
|
||||
public static async addUser(
|
||||
userId: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
username: string,
|
||||
email: string,
|
||||
notEncryptPassword: string,
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): Promise<string> {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const encryptedFirstName: string = System.encryptDataWithUserKey(firstName, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(lastName, userEncryptionKey);
|
||||
const encryptedUsername: string = System.encryptDataWithUserKey(username, userEncryptionKey);
|
||||
const encryptedEmail: string = System.encryptDataWithUserKey(email, userEncryptionKey);
|
||||
const hashedEmail: string = System.hashElement(email);
|
||||
const hashedUsername: string = System.hashElement(username);
|
||||
return UserRepo.insertUser(
|
||||
userId,
|
||||
encryptedFirstName,
|
||||
encryptedLastName,
|
||||
encryptedUsername,
|
||||
hashedUsername,
|
||||
encryptedEmail,
|
||||
hashedEmail,
|
||||
lang
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing user's profile information in the database.
|
||||
* @param userKey - The encryption key for the user's data
|
||||
* @param userId - The unique identifier of the user to update
|
||||
* @param firstName - The updated first name (will be encrypted)
|
||||
* @param lastName - The updated last name (will be encrypted)
|
||||
* @param username - The updated username (will be encrypted and hashed)
|
||||
* @param email - The updated email address (will be encrypted and hashed)
|
||||
* @param authorName - The optional author/pen name (will be encrypted and hashed if provided)
|
||||
* @param lang - The preferred language for the user ('fr' or 'en'), defaults to 'fr'
|
||||
* @returns A promise resolving to true if the update was successful
|
||||
*/
|
||||
public static async updateUserInfos(
|
||||
userKey: string,
|
||||
userId: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
username: string,
|
||||
email: string,
|
||||
authorName?: string,
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): Promise<boolean> {
|
||||
const encryptedFirstName: string = System.encryptDataWithUserKey(firstName, userKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(lastName, userKey);
|
||||
const encryptedUsername: string = System.encryptDataWithUserKey(username, userKey);
|
||||
const encryptedEmail: string = System.encryptDataWithUserKey(email, userKey);
|
||||
const hashedEmail: string = System.hashElement(email);
|
||||
const hashedUsername: string = System.hashElement(username);
|
||||
let encryptedAuthorName: string = '';
|
||||
let hashedAuthorName: string = '';
|
||||
if (authorName) {
|
||||
encryptedAuthorName = System.encryptDataWithUserKey(authorName, userKey);
|
||||
hashedAuthorName = System.hashElement(authorName);
|
||||
}
|
||||
return UserRepo.updateUserInfos(
|
||||
userId,
|
||||
encryptedFirstName,
|
||||
encryptedLastName,
|
||||
encryptedUsername,
|
||||
hashedUsername,
|
||||
encryptedEmail,
|
||||
hashedEmail,
|
||||
hashedAuthorName,
|
||||
encryptedAuthorName,
|
||||
lang
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and decrypts the user's account information from the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @returns A promise resolving to the decrypted user account information
|
||||
*/
|
||||
public static async getUserAccountInformation(userId: string): Promise<UserAccount> {
|
||||
const accountData: UserAccountQuery = UserRepo.fetchAccountInformation(userId);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const decryptedFirstName: string = accountData.first_name ? System.decryptDataWithUserKey(accountData.first_name, userEncryptionKey) : '';
|
||||
const decryptedLastName: string = accountData.last_name ? System.decryptDataWithUserKey(accountData.last_name, userEncryptionKey) : '';
|
||||
const decryptedUsername: string = accountData.username ? System.decryptDataWithUserKey(accountData.username, userEncryptionKey) : '';
|
||||
const decryptedAuthorName: string = accountData.author_name ? System.decryptDataWithUserKey(accountData.author_name, userEncryptionKey) : '';
|
||||
const decryptedEmail: string = accountData.email ? System.decryptDataWithUserKey(accountData.email, userEncryptionKey) : '';
|
||||
return {
|
||||
firstName: decryptedFirstName,
|
||||
lastName: decryptedLastName,
|
||||
username: decryptedUsername,
|
||||
authorName: decryptedAuthorName,
|
||||
email: decryptedEmail
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique identifier of the user.
|
||||
* @returns The user's unique identifier
|
||||
*/
|
||||
public getId(): string {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's first name.
|
||||
* @returns The user's first name
|
||||
*/
|
||||
public getFirstName(): string {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's last name.
|
||||
* @returns The user's last name
|
||||
*/
|
||||
public getLastName(): string {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's username.
|
||||
* @returns The user's username
|
||||
*/
|
||||
public getUsername(): string {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's email address.
|
||||
* @returns The user's email address
|
||||
*/
|
||||
public getEmail(): string {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the user's account has been verified.
|
||||
* @returns True if the account is verified, false otherwise
|
||||
*/
|
||||
public isAccountVerified(): boolean {
|
||||
return this.accountVerified;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the user has accepted the terms of service.
|
||||
* @returns True if the terms have been accepted, false otherwise
|
||||
*/
|
||||
public isTermsAccepted(): boolean {
|
||||
return this.termsAccepted;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's group identifier.
|
||||
* @returns The user's group identifier
|
||||
*/
|
||||
public getGroupId(): number {
|
||||
return this.groupId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the user's author/pen name.
|
||||
* @returns The user's author name
|
||||
*/
|
||||
public getAuthorName(): string {
|
||||
return this.authorName;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user