From a8b677979d09d03e79850b2c7165709b63f8c527 Mon Sep 17 00:00:00 2001 From: nael Date: Mon, 25 Dec 2023 17:01:42 +0100 Subject: [PATCH] :bug: Fixed api keys across the project --- .../src/components/api-keys/data/columns.tsx | 21 ++++++- apps/webapp/src/components/api-keys/index.tsx | 13 ++-- .../src/hooks/mutations/useApiKeyMutation.tsx | 9 +-- packages/api/prisma/schema.prisma | 60 +++++++++++++++++++ packages/api/scripts/seed.sql | 2 +- packages/api/src/@core/auth/auth.service.ts | 13 ++-- .../api/src/@core/auth/dto/api-key.dto.ts | 6 +- .../api/src/@core/auth/dto/create-user.dto.ts | 4 +- packages/api/swagger/swagger-spec.json | 17 +++++- 9 files changed, 120 insertions(+), 25 deletions(-) diff --git a/apps/webapp/src/components/api-keys/data/columns.tsx b/apps/webapp/src/components/api-keys/data/columns.tsx index a8afefaad..f1f789d6f 100644 --- a/apps/webapp/src/components/api-keys/data/columns.tsx +++ b/apps/webapp/src/components/api-keys/data/columns.tsx @@ -8,6 +8,13 @@ import { ApiKey } from "./schema" import { DataTableColumnHeader } from "../../shared/data-table-column-header" import { DataTableRowActions } from "../../shared/data-table-row-actions" +function insertDots(originalString: string): string { + if (originalString.length <= 50) { + return originalString; +} +return originalString.substring(0, 50 - 3) + '...'; +} + export const columns: ColumnDef[] = [ { accessorKey: "name", @@ -23,7 +30,19 @@ export const columns: ColumnDef[] = [ header: ({ column }) => ( ), - cell: ({ row }) =>
{row.getValue("token")}
, + cell: ({ row }) => +
+
+ {insertDots(row.getValue("token"))} +
+
navigator.clipboard.writeText(row.getValue("token"))} + > + +
+
+ , }, { diff --git a/apps/webapp/src/components/api-keys/index.tsx b/apps/webapp/src/components/api-keys/index.tsx index a8956c904..0c49839aa 100644 --- a/apps/webapp/src/components/api-keys/index.tsx +++ b/apps/webapp/src/components/api-keys/index.tsx @@ -38,20 +38,18 @@ export default function ApiKeysPage() { } const handleSubmit = (e: React.FormEvent) => { - console.log("ddd") e.preventDefault(); // Prevent default form submission - //console.log("submitting with project "+ selectedProject.id_project); mutate({ userId: profile!.id_user, - projectId: idProject - //keyName: keyName + projectId: idProject, + keyName: keyName }); }; const tsApiKeys = apiKeys?.map((key) => ({ - name: key.id_api_key,// key.name - token: key.api_key_hash, // or any other property that corresponds to 'token' - created: new Date().toISOString() // or any other property that corresponds to 'created' + name: key.name || "", + token: key.api_key_hash, + created: new Date().toISOString() })) return ( @@ -93,7 +91,6 @@ export default function ApiKeysPage() { - {/*isLoading && */} {tsApiKeys && } diff --git a/apps/webapp/src/hooks/mutations/useApiKeyMutation.tsx b/apps/webapp/src/hooks/mutations/useApiKeyMutation.tsx index deb60a4f8..12cdadaa7 100644 --- a/apps/webapp/src/hooks/mutations/useApiKeyMutation.tsx +++ b/apps/webapp/src/hooks/mutations/useApiKeyMutation.tsx @@ -5,17 +5,19 @@ import toast from 'react-hot-toast'; interface IApiKeyDto { projectId: string; userId: string; - //keyName: string; + keyName?: string; } const useApiKeyMutation = () => { const addApiKey = async (data: IApiKeyDto) => { console.log("user id is " + data.userId ) + + //TODO: in cloud environment this step must be done when user logs in directly inside his dashboard // Fetch the token const loginResponse = await fetch(`${config.API_URL}/auth/login`, { method: 'POST', - body: JSON.stringify({ id_user: data.userId.trim(), password_hash: 'pwd_audrey123' }), + body: JSON.stringify({ id_user: data.userId.trim(), password_hash: 'my_password' }), headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json', }, }); @@ -23,7 +25,6 @@ const useApiKeyMutation = () => { throw new Error('Failed to login'); } const { access_token } = await loginResponse.json(); - //console.log("token is "+ access_token) const response = await fetch(`${config.API_URL}/auth/generate-apikey`, { method: 'POST', diff --git a/packages/api/prisma/schema.prisma b/packages/api/prisma/schema.prisma index 83d180f96..92e6c1e7e 100644 --- a/packages/api/prisma/schema.prisma +++ b/packages/api/prisma/schema.prisma @@ -10,6 +10,7 @@ datasource db { model api_keys { id_api_key String @id(map: "id_") @db.Uuid api_key_hash String @unique(map: "unique_api_keys") + name String? id_project String @db.Uuid id_user String @db.Uuid projects projects @relation(fields: [id_project], references: [id_project], onDelete: NoAction, onUpdate: NoAction, map: "fk_7") @@ -449,3 +450,62 @@ model webhooks_reponses { http_status_code String webhook_delivery_attempts webhook_delivery_attempts[] } + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model tcg_comments { + id_tcg_comment String @id(map: "pk_tcg_comments") @db.Uuid + remote_id String? + body String? + html_body String? + is_private Boolean? + created_at DateTime? @db.Timestamp(6) + modified_at DateTime? @db.Timestamp(6) + id_tcg_ticket String? @db.Uuid + id_tcg_contact String? @db.Uuid + tcg_tickets tcg_tickets? @relation(fields: [id_tcg_ticket], references: [id_tcg_ticket], onDelete: NoAction, onUpdate: NoAction, map: "fk_40_1") + tcg_contacts tcg_contacts? @relation(fields: [id_tcg_contact], references: [id_tcg_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_41") + + @@index([id_tcg_contact], map: "fk_tcg_comment_tcg_contact") + @@index([id_tcg_ticket], map: "fk_tcg_comment_tcg_ticket") +} + +model tcg_contacts { + id_tcg_contact String @id(map: "pk_tcg_contact") @db.Uuid + remote_id String? + name String? + email_address String? + phone_number String? + details String? + created_at DateTime? @db.Timestamp(6) + modified_at DateTime? @db.Timestamp(6) + tcg_comments tcg_comments[] +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model tcg_tickets { + id_tcg_ticket String @id(map: "pk_tcg_tickets") @db.Uuid + remote_id String? + name String? + status String? + description String? + due_date DateTime? @db.Timestamp(6) + ticket_type String? + parent_ticket String? @db.Uuid + tags String? + completed_at DateTime? @db.Timestamp(6) + priority String? + created_at DateTime @db.Timestamp(6) + modified_at DateTime @db.Timestamp(6) + assigned_to String[] + tcg_comments tcg_comments[] +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model tcg_users { + id_tcg_user String @id(map: "pk_tcg_users") @db.Uuid + remote_id String? + name String? + email_address String? + created_at DateTime? @db.Timestamp(6) + modified_at DateTime? @db.Timestamp(6) +} diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql index 7f691de62..f0ccab672 100644 --- a/packages/api/scripts/seed.sql +++ b/packages/api/scripts/seed.sql @@ -2,7 +2,7 @@ INSERT INTO organizations (id_organization, name, stripe_customer_id) VALUES ('55222419-795d-4183-8478-361626363e58', 'Acme Inc', 'cust_stripe_acme_56604f75-7bf8-4541-9ab4-5928aade4bb8' ); INSERT INTO users (id_user, email, password_hash, first_name, last_name, id_organization) VALUES -('0ce39030-2901-4c56-8db0-5e326182ec6b', 'audrey@aubry.io', 'pwd_audrey123', 'Audrey', 'Aubry', +('0ce39030-2901-4c56-8db0-5e326182ec6b', 'audrey@aubry.io', 'my_password', 'Audrey', 'Aubry', '55222419-795d-4183-8478-361626363e58' (SELECT id_organization FROM organizations WHERE name = 'Acme Inc')); DO $$ diff --git a/packages/api/src/@core/auth/auth.service.ts b/packages/api/src/@core/auth/auth.service.ts index 062ad11f1..7c6ba77be 100644 --- a/packages/api/src/@core/auth/auth.service.ts +++ b/packages/api/src/@core/auth/auth.service.ts @@ -49,6 +49,7 @@ export class AuthService { password_hash: hashedPassword, first_name: user.first_name, last_name: user.last_name, + id_organization: user.id_organisation || null, }, }); if (!res) { @@ -124,7 +125,7 @@ export class AuthService { async generateApiKeyForUser( userId: string, projectId: string, - keyName?: string, + keyName: string, ): Promise<{ api_key: string }> { try { const foundProject = await this.prisma.projects.findUnique({ @@ -150,12 +151,12 @@ export class AuthService { // Generate a new API key (use a secure method for generation) const { access_token } = await this.generateApiKey(projectId, userId); // Store the API key in the database associated with the user - const hashed_token = this.hashApiKey(access_token); + //const hashed_token = this.hashApiKey(access_token); const new_api_key = await this.prisma.api_keys.create({ data: { id_api_key: uuidv4(), - api_key_hash: hashed_token, - //name: keyName, + api_key_hash: access_token, + name: keyName, id_project: projectId as string, id_user: userId as string, }, @@ -177,10 +178,10 @@ export class AuthService { secret: process.env.JWT_SECRET, }); - const hashed_api_key = this.hashApiKey(apiKey); + //const hashed_api_key = this.hashApiKey(apiKey); const saved_api_key = await this.prisma.api_keys.findUnique({ where: { - api_key_hash: hashed_api_key, + api_key_hash: apiKey, }, }); if (!saved_api_key) { diff --git a/packages/api/src/@core/auth/dto/api-key.dto.ts b/packages/api/src/@core/auth/dto/api-key.dto.ts index 47233e44e..58beed038 100644 --- a/packages/api/src/@core/auth/dto/api-key.dto.ts +++ b/packages/api/src/@core/auth/dto/api-key.dto.ts @@ -1,10 +1,10 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class ApiKeyDto { @ApiProperty() projectId: string; @ApiProperty() userId: string; - @ApiPropertyOptional() - keyName?: string; + @ApiProperty() + keyName: string; } diff --git a/packages/api/src/@core/auth/dto/create-user.dto.ts b/packages/api/src/@core/auth/dto/create-user.dto.ts index c98e66db9..0a8f34657 100644 --- a/packages/api/src/@core/auth/dto/create-user.dto.ts +++ b/packages/api/src/@core/auth/dto/create-user.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty } from '@nestjs/swagger'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; export class CreateUserDto { @ApiProperty() @@ -9,4 +9,6 @@ export class CreateUserDto { email: string; @ApiProperty() password_hash: string; + @ApiPropertyOptional() + id_organisation?: string; } diff --git a/packages/api/swagger/swagger-spec.json b/packages/api/swagger/swagger-spec.json index 43236595a..55b486b16 100644 --- a/packages/api/swagger/swagger-spec.json +++ b/packages/api/swagger/swagger-spec.json @@ -12,6 +12,17 @@ } } }, + "/protected": { + "get": { + "operationId": "AppController_getHello2", + "parameters": [], + "responses": { + "200": { + "description": "" + } + } + } + }, "/auth/register": { "post": { "operationId": "signUp", @@ -936,6 +947,9 @@ }, "password_hash": { "type": "string" + }, + "id_organisation": { + "type": "string" } }, "required": [ @@ -977,7 +991,8 @@ }, "required": [ "projectId", - "userId" + "userId", + "keyName" ] }, "WebhookDto": {