diff --git a/.env b/.env index f1c495d9f..dd4f0d5c4 100644 --- a/.env +++ b/.env @@ -10,13 +10,14 @@ API_PORT=3333 API_NAME=bsafe-api API_DOCKERFILE= API_ENVIRONMENT=development -UI_URL=http://localhost:5175 +#UI_URL=http://localhost:5175 +UI_URL=https://app.bsafe.pro API_URL=http://localhost:3333 # Admin user APP_ADMIN_EMAIL=admin_user_email APP_ADMIN_PASSWORD=admin_user_password - +TOKEN_EXPIRATION_TIME=15 # ADMIN USER APP_ADMIN_EMAIL=admin_user_email diff --git a/.gitignore b/.gitignore index e206e2456..6d441cf55 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ yarn.lock package-lock.json .editorconfig bsafe/ +pnpm-lock.yaml #env .env.staging diff --git a/Dockerfile.stg b/Dockerfile.stg index ea04e620d..77c106541 100644 --- a/Dockerfile.stg +++ b/Dockerfile.stg @@ -1,4 +1,4 @@ -FROM node:18.14.2 +FROM node:18.18.2 # Create app directory diff --git a/package.json b/package.json index 7e9b89ead..808275b0d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "database:dev": "make -C ./docker/database start env_file=.env.dev", "database:stop": "make -C ./docker/database start", "database:start": "make -C ./docker/database start", - "postinstall": "patch-package --use-yarn", "run:prod": "make -C ./ prod env_file=.env.prod", "run:stg": "make -C ./ stg env_file=.env.staging" }, @@ -26,16 +25,17 @@ "axios": "1.5.1", "bcrypt": "5.1.0", "body-parser": "1.20.2", - "bsafe": "0.0.35", + "bsafe": "0.0.43", "cheerio": "1.0.0-rc.12", "class-validator": "0.14.0", "cookie-parser": "1.4.6", "copyfiles": "2.4.1", "cors": "2.8.5", "date-fns": "2.30.0", - "dotenv": "8.2.0", + "dotenv": "16.4.5", "express": "4.17.1", "express-joi-validation": "5.0.0", + "fuels": "0.73.0", "joi": "17.4.0", "jsonwebtoken": "9.0.1", "morgan": "1.10.0", diff --git a/src/database/migrations/1695162520664-add-parovider-and-connected-to-users.ts b/src/database/migrations/1695162520664-add-parovider-and-connected-to-users.ts index d14be4be1..bf364914d 100644 --- a/src/database/migrations/1695162520664-add-parovider-and-connected-to-users.ts +++ b/src/database/migrations/1695162520664-add-parovider-and-connected-to-users.ts @@ -1,21 +1,22 @@ -import { MigrationInterface, QueryRunner, Table, TableColumn } from 'typeorm'; +import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; + +const cProvider = new TableColumn({ + name: 'provider', + type: 'varchar', +}); + +const cUsers = new TableColumn({ + name: 'address', + type: 'varchar', +}); export class addParoviderAndConnectedToUsers1695162520664 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumns('users', [ - new TableColumn({ - name: 'address', - type: 'varchar', - }), - new TableColumn({ - name: 'provider', - type: 'varchar', - }), - ]); + await queryRunner.addColumns('users', [cProvider, cUsers]); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumns('users', ['connected_users', 'provider']); + await queryRunner.dropColumns('users', [cProvider, cUsers]); } } diff --git a/src/database/migrations/1695163991051-add-collumns-to-usertoken.ts b/src/database/migrations/1695163991051-add-collumns-to-usertoken.ts index fb8cbe530..00471cd96 100644 --- a/src/database/migrations/1695163991051-add-collumns-to-usertoken.ts +++ b/src/database/migrations/1695163991051-add-collumns-to-usertoken.ts @@ -1,29 +1,27 @@ import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; +const cExpired = new TableColumn({ + name: 'expired_at', + type: 'timestamp', + isNullable: true, +}); + +const cEncoder = new TableColumn({ + name: 'encoder', + type: 'varchar', +}); + +const cProvider = new TableColumn({ + name: 'provider', + type: 'varchar', +}); + export class addCollumnsToUsertoken1695163991051 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumns('user_tokens', [ - new TableColumn({ - name: 'expired_at', - type: 'timestamp', - isNullable: true, - }), - new TableColumn({ - name: 'encoder', - type: 'varchar', - }), - new TableColumn({ - name: 'provider', - type: 'varchar', - }), - ]); + await queryRunner.addColumns('user_tokens', [cExpired, cEncoder, cProvider]); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumns('user_tokens', [ - 'expired_at', - 'encoder', - 'provider', - ]); + await queryRunner.dropColumns('user_tokens', [cExpired, cEncoder, cProvider]); } } diff --git a/src/database/migrations/1695646779754-add-collumn-to-user-token.ts b/src/database/migrations/1695646779754-add-collumn-to-user-token.ts index e2bed0839..8b9f4fe58 100644 --- a/src/database/migrations/1695646779754-add-collumn-to-user-token.ts +++ b/src/database/migrations/1695646779754-add-collumn-to-user-token.ts @@ -1,16 +1,15 @@ import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; +const cpayload = new TableColumn({ + name: 'payload', + type: 'text', +}); export class addCollumnToUserToken1695646779754 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumns('user_tokens', [ - new TableColumn({ - name: 'payload', - type: 'text', - }), - ]); + await queryRunner.addColumns('user_tokens', [cpayload]); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumns('user_tokens', ['payload']); + await queryRunner.dropColumns('user_tokens', [cpayload]); } } diff --git a/src/database/migrations/1702391257625-add-notifications-columns-to-users-table.ts b/src/database/migrations/1702391257625-add-notifications-columns-to-users-table.ts index eac14cc04..8472b1160 100644 --- a/src/database/migrations/1702391257625-add-notifications-columns-to-users-table.ts +++ b/src/database/migrations/1702391257625-add-notifications-columns-to-users-table.ts @@ -1,23 +1,24 @@ import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; +const cnotify = new TableColumn({ + name: 'notify', + type: 'boolean', + default: false, +}); + +const cFirstLogin = new TableColumn({ + name: 'first_login', + type: 'boolean', + default: true, +}); + export class addNotificationsColumnsToUsersTable1702391257625 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumns('users', [ - new TableColumn({ - name: 'first_login', - type: 'boolean', - default: true, - }), - new TableColumn({ - name: 'notify', - type: 'boolean', - default: false, - }), - ]); + await queryRunner.addColumns('users', [cFirstLogin, cnotify]); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumns('users', ['first_login', 'notify']); + await queryRunner.dropColumns('users', [cnotify, cFirstLogin]); } } diff --git a/src/middlewares/auth/types.ts b/src/middlewares/auth/types.ts index 7a24b4b66..68c7b3b3b 100644 --- a/src/middlewares/auth/types.ts +++ b/src/middlewares/auth/types.ts @@ -19,4 +19,10 @@ export interface AuthValidatedRequest workspace?: Workspace; } +export interface UnloggedRequest extends Request { + body: T[ContainerTypes.Body]; + headers: T[ContainerTypes.Headers]; +} + export type IAuthRequest = AuthValidatedRequest; +export type IChangeWorkspaceRequest = AuthValidatedRequest; diff --git a/src/modules/addressBook/controller.ts b/src/modules/addressBook/controller.ts index 069d32057..deac03517 100644 --- a/src/modules/addressBook/controller.ts +++ b/src/modules/addressBook/controller.ts @@ -149,20 +149,46 @@ export class AddressBookController { try { const owner = [workspace.id]; - if (includePersonal) { - await new WorkspaceService() - .filter({ - user: user.id, - single: true, - }) - .list() - .then((response: Workspace[]) => owner.push(response[0].id)); + const singleWk = await new WorkspaceService() + .filter({ + user: user.id, + single: true, + }) + .list() + .then((response: Workspace[]) => response[0].id); + + if (includePersonal === 'true') { + owner.push(singleWk); } + const response = await this.addressBookService .filter({ owner, q }) .ordination({ orderBy, sort }) .paginate({ page, perPage }) - .list(); + .list() + .then((res: AddressBook[]) => { + return res.reduce((acc, currentItem) => { + const existingItem = acc.find( + item => item.user.id === currentItem.user.id, + ); + + if (!existingItem) { + acc.push(currentItem); + return acc; + } + // Se já existe, retornar de preferencia o que tem o wk igual ao single + if ( + currentItem.owner.id === (includePersonal ? singleWk : workspace.id) + ) { + const existingIndex = acc.findIndex( + item => item.user.id === currentItem.user.id, + ); + acc[existingIndex] = currentItem; + } + + return acc; + }, []); + }); return successful(response, Responses.Ok); } catch (e) { diff --git a/src/modules/addressBook/services.ts b/src/modules/addressBook/services.ts index b28b552ef..a18da17d4 100644 --- a/src/modules/addressBook/services.ts +++ b/src/modules/addressBook/services.ts @@ -56,7 +56,13 @@ export class AddressBookService implements IAddressBookService { .select(['ab.id', 'ab.nickname']) .innerJoin('ab.user', 'user') .innerJoin('ab.owner', 'owner') - .addSelect(['user.id', 'user.address', 'user.avatar', 'owner.id']); + .addSelect([ + 'user.id', + 'user.address', + 'user.avatar', + 'user.address', + 'owner.id', + ]); const handleInternalError = e => { if (e instanceof GeneralError) throw e; diff --git a/src/modules/addressBook/types.ts b/src/modules/addressBook/types.ts index 2fef11e2f..8414ce613 100644 --- a/src/modules/addressBook/types.ts +++ b/src/modules/addressBook/types.ts @@ -65,7 +65,7 @@ interface IListAddressBookRequestSchema extends ValidatedRequestSchema { sort: Sort; page: string; perPage: string; - includePersonal: boolean; + includePersonal: string; }; } diff --git a/src/modules/auth/controller.ts b/src/modules/auth/controller.ts index 47ec642b2..ef8b432e0 100644 --- a/src/modules/auth/controller.ts +++ b/src/modules/auth/controller.ts @@ -3,10 +3,6 @@ import { add, addMinutes } from 'date-fns'; import { Encoder } from '@src/models'; import { Workspace } from '@src/models/Workspace'; import GeneralError, { ErrorTypes } from '@src/utils/error/GeneralError'; -import { - Unauthorized, - UnauthorizedErrorTitles, -} from '@src/utils/error/Unauthorized'; import { IAuthRequest } from '@middlewares/auth/types'; @@ -89,7 +85,6 @@ export class AuthController { async updateWorkspace(req: IChangeWorkspaceRequest) { try { const { workspace: workspaceId, user } = req.body; - const workspace = await new WorkspaceService() .filter({ id: workspaceId }) .list() @@ -104,14 +99,6 @@ export class AuthController { const isUserMember = workspace.members.find(m => m.id === user); - // if (!isUserMember) { - // throw new Unauthorized({ - // type: ErrorTypes.NotFound, - // title: UnauthorizedErrorTitles.INVALID_PERMISSION, - // detail: `User not found`, - // }); - // } - const token = await this.authService.findToken({ userId: user, }); diff --git a/src/modules/auth/types.ts b/src/modules/auth/types.ts index c8e549423..ef43938a8 100644 --- a/src/modules/auth/types.ts +++ b/src/modules/auth/types.ts @@ -5,7 +5,7 @@ import { IPermissions, Workspace } from '@src/models/Workspace'; import UserToken, { Encoder } from '@models/UserToken'; import { User } from '@models/index'; -import { AuthValidatedRequest } from '@middlewares/auth/types'; +import { AuthValidatedRequest, UnloggedRequest } from '@middlewares/auth/types'; export interface ICreateUserTokenPayload { token: string; @@ -93,7 +93,8 @@ export interface IUpgradeWorkspace extends ValidatedRequestSchema { } export type IListRequest = AuthValidatedRequest; -export type ISignInRequest = AuthValidatedRequest; +export type ISignInRequest = UnloggedRequest; +export type IGoToSingleWorkspaceRequest = AuthValidatedRequest; export type IFindDappRequest = AuthValidatedRequest; export type IActiveSession = AuthValidatedRequest; export type IChangeWorkspaceRequest = AuthValidatedRequest; diff --git a/src/modules/notification/routes.ts b/src/modules/notification/routes.ts index ab8a744cd..d2660a41a 100644 --- a/src/modules/notification/routes.ts +++ b/src/modules/notification/routes.ts @@ -11,10 +11,11 @@ import { NotificationService } from './services'; const router = Router(); const notificationService = new NotificationService(); const { readAll, list } = new NotificationController(notificationService); +const { MAIL_TESTING_NOTIFICATIONS } = process.env; // ENDPOINT TO VALIDATE EMAIL SENDING router.get('/mail', async (_, res) => { - const to = 'guilherme@infinitybase.com'; + const to = MAIL_TESTING_NOTIFICATIONS; const data = { summary: { vaultName: 'Vault Name', diff --git a/src/modules/predicate/controller.ts b/src/modules/predicate/controller.ts index 529c7f57d..52eedc264 100644 --- a/src/modules/predicate/controller.ts +++ b/src/modules/predicate/controller.ts @@ -120,24 +120,11 @@ export class PredicateController { } } - async findById({ params: { id }, user, workspace }: IFindByIdRequest) { + async findById({ params: { id }, user }: IFindByIdRequest) { try { const predicate = await this.predicateService.findById(id, user.address); - const membersIds = predicate.members.map(member => member.id); - const favorites = (await this.addressBookService - .filter({ owner: [workspace.id], userIds: membersIds }) - .list()) as AddressBook[]; - const response = { - ...predicate, - members: predicate.members.map(member => ({ - ...member, - nickname: - favorites?.find(({ user }) => user.id === member.id)?.nickname ?? - undefined, - })), - }; - return successful(response, Responses.Ok); + return successful(predicate, Responses.Ok); } catch (e) { return error(e.error, e.statusCode); } diff --git a/src/modules/predicate/services.ts b/src/modules/predicate/services.ts index dc9838de0..d5422ba9d 100644 --- a/src/modules/predicate/services.ts +++ b/src/modules/predicate/services.ts @@ -205,6 +205,8 @@ export class PredicateService implements IPredicateService { if (this._filter.signer) { qb.orWhere(subQb => { const subQuery = subQb + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore .subQuery() .select('1') .from('predicate_members', 'pm') diff --git a/src/modules/transaction/controller.ts b/src/modules/transaction/controller.ts index d27c415d2..125352ab6 100644 --- a/src/modules/transaction/controller.ts +++ b/src/modules/transaction/controller.ts @@ -98,11 +98,8 @@ export class TransactionController { ), ).length ?? 0, transactionsBlocked: - result.filter(transaction => - transaction.witnesses.find( - w => w.status === WitnessesStatus.PENDING, - ), - ).length > 0 ?? false, + result.filter(t => t.status === TransactionStatus.AWAIT_REQUIREMENTS) + .length > 0 ?? false, }; }); return successful(result, Responses.Ok); @@ -269,7 +266,7 @@ export class TransactionController { // acc_signed, // Signer.recoverAddress(hashMessage(hash), signer).toString(), // ); - if (signer && confirm) { + if (signer && confirm === 'true') { const acc_signed = Signer.recoverAddress(hashMessage(hash), signer).toString() == user.address; diff --git a/src/modules/transaction/types.ts b/src/modules/transaction/types.ts index b67ba71b5..b90425bbc 100644 --- a/src/modules/transaction/types.ts +++ b/src/modules/transaction/types.ts @@ -88,7 +88,7 @@ export type ICloseTransactionBody = { export interface ISignByIdPayload { signer: string; account: string; - confirm: boolean; + confirm: string; } interface ICreateTransactionRequestSchema extends ValidatedRequestSchema { diff --git a/src/modules/user/__tests__/user.tests.ts b/src/modules/user/__tests__/user.tests.ts index af165886a..d10f02e81 100644 --- a/src/modules/user/__tests__/user.tests.ts +++ b/src/modules/user/__tests__/user.tests.ts @@ -1,5 +1,5 @@ import axios from 'axios'; -import { accounts } from 'bsafe/dist/cjs/mocks/accounts'; +import { accounts } from 'bsafe'; import { Address } from 'fuels'; import { networks, providers } from '@src/mocks/networks'; diff --git a/src/modules/workspace/controller.ts b/src/modules/workspace/controller.ts index e11f5a578..a35f1d046 100644 --- a/src/modules/workspace/controller.ts +++ b/src/modules/workspace/controller.ts @@ -1,5 +1,5 @@ import axios from 'axios'; -import { Vault, defaultConfigurable } from 'bsafe'; +import { Vault, defaultConfig } from 'bsafe'; import { BN, Provider, bn } from 'fuels'; import { parse } from 'path'; @@ -218,7 +218,7 @@ export class WorkspaceController { if (!data) { return await new UserService().create({ address: member, - provider: defaultConfigurable['provider'], + provider: defaultConfig['provider'], avatar: await new UserService().randomAvatar(), }); } diff --git a/src/modules/workspace/services.ts b/src/modules/workspace/services.ts index 2eb91a767..25497f8f5 100644 --- a/src/modules/workspace/services.ts +++ b/src/modules/workspace/services.ts @@ -1,4 +1,4 @@ -import { defaultConfigurable } from 'bsafe'; +import { defaultConfig } from 'bsafe'; import { Brackets } from 'typeorm'; import { User } from '@src/models'; @@ -162,7 +162,7 @@ export class WorkspaceService implements IWorkspaceService { if (!data) { return await new UserService().create({ address: member, - provider: defaultConfigurable['provider'], + provider: defaultConfig['provider'], avatar: await new UserService().randomAvatar(), }); } diff --git a/src/server/bootstrap.ts b/src/server/bootstrap.ts index 863e775ba..6d111d389 100644 --- a/src/server/bootstrap.ts +++ b/src/server/bootstrap.ts @@ -4,8 +4,6 @@ import { getConnection } from 'typeorm'; import startConnection from '@database/connection'; import runSeeders from '@database/seeders'; -import config from '../config/database'; - class Bootstrap { static async connectDatabase() { return await startConnection(); diff --git a/src/server/index.ts b/src/server/index.ts index 39925fbf4..dfe1914b1 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -10,8 +10,8 @@ const start = async () => { }; BSafe.setup({ - api_url: process.env.API_URL, - bsafe_url: process.env.UI_URL, + API_URL: process.env.API_URL, + BSAFE_URL: process.env.UI_URL, }); try { diff --git a/src/socket/types.ts b/src/socket/types.ts index eb8c54c13..f4e55c06b 100644 --- a/src/socket/types.ts +++ b/src/socket/types.ts @@ -1,5 +1,3 @@ -import { Operation } from '@fuel-ts/providers'; - export enum SocketEvents { //auth CONNECTION = 'connection', @@ -44,7 +42,7 @@ export interface BaseSocketEvent { origin: string; name?: string; hash?: string; - operations?: Operation[]; + operations?: unknown[]; } export interface ISocketEvent { diff --git a/src/templates/transaction-completed.html b/src/templates/transaction-completed.html index 5d39dc058..ff5c7f3c0 100644 --- a/src/templates/transaction-completed.html +++ b/src/templates/transaction-completed.html @@ -12,11 +12,6 @@ font-family: Roboto, Arial, Helvetica, sans-serif; } - a { - text-decoration: none; - color: #000000 !important; - } - .Body { max-width: 100%; width: 585px; @@ -75,9 +70,9 @@

- To view your transaction details, please click - here to log in to your BSAFE account and navigate - to your vault. + To view your transaction details, please + click here to log in to your BSAFE account and + navigate to your vault.