Skip to content

Commit

Permalink
Merge pull request #10 from Duna-System/feat/last-modified-projects
Browse files Browse the repository at this point in the history
Feat/last modified projects
  • Loading branch information
sedoski-duna authored Jun 26, 2023
2 parents 6aa5378 + b70b102 commit c44fb0c
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 38 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,18 @@ reply: ok message.

`http://localhost:9095/info`

### Get the latest modified projects

- Crie uma nova request com o meotodo get o parametro `latestProjectsSize` coloque essa rota:

Neste caso `latestProjectsSize` será o tamanho da lista retornada.

`http://localhost:9095/info?latestProjectsSize=4`

| Status Code | Description |
| ----------- | ------------ |
| 500 | Invalid Size |

### Error

| Status Code | Description |
Expand Down
78 changes: 56 additions & 22 deletions src/BaseBucketManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import * as fs from 'fs';
import { Config, DataError, JsonDB } from 'node-json-db';
import * as path from 'path';

import { BucketObject } from './Bucket';
import { ProjectObject } from './Project';
import { EntityType } from './EntityTypes';
import { IBucket, IEntity } from './Interfaces';
import { IProject, IEntity, IProjectsInfo } from './Interfaces';
import { ErrorMessages } from './Messages';

/**
Expand Down Expand Up @@ -99,7 +99,7 @@ export abstract class BaseBucketManager {
* @param entity Entity object. If entity exists in the database, overwrite
* it.
*/
protected addEntityToDB(bucket: BucketObject, entity: IEntity) {
protected addEntityToDB(bucket: ProjectObject, entity: IEntity) {
let idx: number;
switch (entity.type) {
case EntityType.PointCloud:
Expand All @@ -125,13 +125,13 @@ export abstract class BaseBucketManager {
}

/**
* Update entity usage size.
* Update entity usage size and modifiedAt.
* @param user_id (uuid) of owner of project.
* @param project_id
*/
protected async updateRemaining(user_id: string, project_id: string) {
try {
const item: BucketObject = await this.getProjectInfo(user_id, project_id);
const item: ProjectObject = await this.getProjectInfo(user_id, project_id);

let used: number = 0;
item.clouds;
Expand All @@ -149,6 +149,7 @@ export abstract class BaseBucketManager {
used += bim.sizeMB;
}
item.quota.BIMUsedMB = used;
item.modifiedAt = Date.now();
} catch (err) {
throw new Error(`user_id '${project_id}' does not exist.`);
}
Expand Down Expand Up @@ -183,11 +184,11 @@ export abstract class BaseBucketManager {
* @returns A REFERENCE to the object in the DB. This means that any change to
* the returned data is made persistent if db.save() is called afterwards.
*/
public async getProjectInfo(user_id: string, project_id: string): Promise<BucketObject> {
public async getProjectInfo(user_id: string, project_id: string): Promise<ProjectObject> {
try {
const info: BucketObject | undefined = await this.db.find(
const info: ProjectObject | undefined = await this.db.find(
this.dbPath(user_id, 'projects'),
(entry: BucketObject): boolean => {
(entry: ProjectObject): boolean => {
return entry.id === project_id;
}
);
Expand All @@ -207,9 +208,29 @@ export abstract class BaseBucketManager {
* @param user_id (uuid) of owner of project.
* @returns
*/
public async getInfo(user_id: string): Promise<Array<BucketObject>> {
public async getInfo(user_id: string): Promise<IProjectsInfo> {
try {
return await this.db.getObject<Array<BucketObject>>(this.dbPath(user_id));
return await this.db.getObject<IProjectsInfo>(this.dbPath(user_id));
} catch (err) {
throw Error(`No Project for user_id '${user_id}' exists.`);
}
}

/**
* Get the latest modified projects belonging to `user_id`
* @param user_id (uuid) of owner of project.
* @param n size of the returned list
* @returns
*/
public async getLatestModifiedInfo(user_id: string, n: number): Promise<IProjectsInfo> {
try {
const project_info = await this.db.getObject<IProjectsInfo>(this.dbPath(user_id));

let last_modified_projects = [...project_info.projects];
last_modified_projects.sort((a, b) => b.modifiedAt - a.modifiedAt);
last_modified_projects = last_modified_projects.slice(0, n);

return { ...project_info, projects: last_modified_projects };
} catch (err) {
throw Error(`No Project for user_id '${user_id}' exists.`);
}
Expand All @@ -225,7 +246,7 @@ export abstract class BaseBucketManager {
*/
public async getQuotaInfo(user_id: string, project_id: string): Promise<any> {
try {
const project_info = (await this.getProjectInfo(user_id, project_id)) as BucketObject;
const project_info = (await this.getProjectInfo(user_id, project_id)) as ProjectObject;
return project_info.quota;
} catch (err) {
throw err;
Expand All @@ -248,7 +269,7 @@ export abstract class BaseBucketManager {
filepath: string,
filename: string,
size: number
): Promise<IBucket> {
): Promise<IProject> {
if (type == EntityType.Unknown) throw new Error(`Invalid capture entity type.`);

try {
Expand All @@ -265,6 +286,7 @@ export abstract class BaseBucketManager {

this.addEntityToDB(project, entity_info);

//Update the remaining quota and set modifiedAt to now.
await this.updateRemaining(user_id, project_id);
this.db.save();

Expand Down Expand Up @@ -302,7 +324,7 @@ export abstract class BaseBucketManager {
if (type == EntityType.Unknown) throw new Error(ErrorMessages.InvalidEntity);
try {
// Query DB
let ret = (await this.getProjectInfo(user_id, project_id)) as BucketObject;
let ret = (await this.getProjectInfo(user_id, project_id)) as ProjectObject;

if (ret == undefined) throw new Error(`Project '${project_id}' does not exist.`);

Expand All @@ -329,16 +351,17 @@ export abstract class BaseBucketManager {
project_name: string,
client_name: string,
project_type: string
): Promise<BucketObject> {
const bucket_obj = new BucketObject(project_name, client_name, project_type);
): Promise<ProjectObject> {
const bucket_obj = new ProjectObject(project_name, client_name, project_type);

try {
// if Exists
if (await this.db.exists(this.dbPath(user_id, 'projects'))) {
const projects: Array<BucketObject> = await this.db.getData(
const projects: Array<ProjectObject> = await this.db.getData(
this.dbPath(user_id, 'projects')
);
// TODO is is possible to use `this.db.find` instead of fetching object?
if (projects.find((element: BucketObject) => element.name === project_name))
if (projects.find((element: ProjectObject) => element.name === project_name))
throw Error(`${ErrorMessages.ProkectExists} '${project_name}' for user '${user_id}'`);
}

Expand Down Expand Up @@ -366,7 +389,7 @@ export abstract class BaseBucketManager {
new_project_name: string,
new_client_name: string,
new_project_type: string
): Promise<BucketObject> {
): Promise<ProjectObject> {
let project = await this.getProjectInfo(user_id, project_id);

if (
Expand All @@ -375,9 +398,11 @@ export abstract class BaseBucketManager {
new_project_name != project.name
) {
// Check if other projects do not have the same name
const projects: Array<BucketObject> = await this.db.getData(this.dbPath(user_id, 'projects'));
const projects: Array<ProjectObject> = await this.db.getData(
this.dbPath(user_id, 'projects')
);

if (projects.find((element: BucketObject) => element.name === new_project_name))
if (projects.find((element: ProjectObject) => element.name === new_project_name))
throw Error(`${ErrorMessages.ProkectExists} '${new_project_name}' for user '${user_id}'`);

project.name = new_project_name;
Expand All @@ -388,6 +413,9 @@ export abstract class BaseBucketManager {
if (new_project_type != undefined && new_project_type != '')
project.projectType = new_project_type;

//Updating modifiedAt
project.modifiedAt = Date.now();

this.db.save();
return project;
}
Expand All @@ -405,7 +433,7 @@ export abstract class BaseBucketManager {
project_id: string,
type: EntityType,
entity: string
): Promise<BucketObject> {
): Promise<ProjectObject> {
// Check if project exists.
if ((await this.db.exists(this.dbPath(user_id))) === false)
throw new Error(`No Project for '${user_id}' does exists.`);
Expand All @@ -423,7 +451,9 @@ export abstract class BaseBucketManager {
)
);

//Update the remaining quota and set modifiedAt to now.
this.updateRemaining(user_id, project_id);

// Return updated project info
return await this.getProjectInfo(user_id, project_id);
}
Expand All @@ -434,7 +464,7 @@ export abstract class BaseBucketManager {
type: EntityType,
current_entity_name: string,
new_entity_name: string
): Promise<BucketObject> {
): Promise<ProjectObject> {
// Search for the entity.
const { entity_idx, project_idx } = await this.getEntityPathIndices(
user_id,
Expand Down Expand Up @@ -469,6 +499,10 @@ export abstract class BaseBucketManager {
entityObject.location = new_location;
entityObject.name = new_name_with_ext;

//Updating modifiedAt
let project = await this.getProjectInfo(user_id, project_id);
project.modifiedAt = Date.now();

this.db.save();

return await this.getProjectInfo(user_id, project_id);
Expand Down
17 changes: 16 additions & 1 deletion src/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,28 @@ export class Controller {
public async handleGetProjectInfo(req: any, res: any) {
const project_id = req.params.project_id;
const owner_uuid = res.locals.token_uuid;
const latest_projects_size = req.query.latestProjectsSize;

if (owner_uuid === undefined) return res.status(400).send(ErrorMessages.InvalidFormat).end();

try {
// Send general info.
if (project_id === undefined) {
const ret = await this.bucketManager.getInfo(owner_uuid);
// If n is not defined, just return all the projects info
if (latest_projects_size === undefined) {
const ret = await this.bucketManager.getInfo(owner_uuid);
res.status(200).send(ret).end();
return;
} // n is defined, but less than 1
else if (latest_projects_size <= 0) {
throw new Error('n must be greater or equal to 1.');
}

// n correctly defined, return the latest projects
const ret = await this.bucketManager.getLatestModifiedInfo(
owner_uuid,
latest_projects_size
);
res.status(200).send(ret).end();
return;
} else {
Expand Down
8 changes: 7 additions & 1 deletion src/Interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './EntityTypes';

export interface IBucket {
export interface IProject {
id: string;
name: string;
clientName: string;
Expand All @@ -9,6 +9,12 @@ export interface IBucket {
clouds: Array<IEntity>;
images: Array<IEntity>;
bim: Array<IEntity>;
createdAt: number;
modifiedAt: number;
}

export interface IProjectsInfo {
projects: Array<IProject>;
}

export interface IEntity {
Expand Down
15 changes: 9 additions & 6 deletions src/Bucket.ts → src/Project.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { IBucket, IEntity, QuotaInfo } from './Interfaces';
import { IProject, IEntity, QuotaInfo } from './Interfaces';
import { v4 as uuidv4 } from 'uuid';

/**
* Bucket object is a representation of a storage for capture entities/assets.
* Project object is a representation of a storage for capture entities/assets.
*/
export class BucketObject implements IBucket {
export class ProjectObject implements IProject {
id: string;
name: string;
clientName: string;
Expand All @@ -13,11 +13,12 @@ export class BucketObject implements IBucket {
clouds: Array<IEntity>;
bim: Array<IEntity>;
quota: QuotaInfo;

createdAt: number;
modifiedAt: number;
/**
*
* @param name Bucket/project name
* @param uuid UUID of bucket owner
* @param name project name
* @param uuid UUID of project owner
* @param pc_quota Quota (Maximum allowed storage) for Pointclouds
* @param img_quota Quota (Maximum allowed storage) for Images
* @param bim_quota Quota (Maximum allowed storage) for BIM models
Expand All @@ -37,6 +38,8 @@ export class BucketObject implements IBucket {
this.images = new Array<IEntity>();
this.clouds = new Array<IEntity>();
this.bim = new Array<IEntity>();
this.createdAt = Date.now();
this.modifiedAt = Date.now();
this.quota = {
pointCloudQuotaMB: pc_quota,
imageSizeQuotaMB: img_quota,
Expand Down
Loading

0 comments on commit c44fb0c

Please sign in to comment.