diff --git a/openapi.yaml b/openapi.yaml index 504cfe3f..c92578f3 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -80,8 +80,363 @@ tags: description: Department goals management - name: Subusers description: Subuser registration and setup + - name: Bird + description: Voice Calls via Bird paths: + # Bird Voice Calls + /bird/voice/calls: + post: + tags: + - Bird + summary: Create/place a voice call via Bird + operationId: birdCreateVoiceCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + to: + type: string + description: E.164 phone number of the callee + example: "+4511122233" + from: + type: string + description: E.164 phone number of the caller (sender) + example: "+4599988877" + responses: + '200': + description: Call created + content: + application/json: + schema: + type: object + additionalProperties: true + get: + tags: + - Bird + summary: List voice calls + operationId: birdListVoiceCalls + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: query + name: page + schema: + type: integer + required: false + responses: + '200': + description: A list of calls + content: + application/json: + schema: + type: object + additionalProperties: true + + /bird/voice/calls/{id}: + get: + tags: + - Bird + summary: Get a voice call by ID + operationId: birdGetVoiceCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: path + name: id + required: true + schema: + type: string + responses: + '200': + description: Call details + content: + application/json: + schema: + type: object + additionalProperties: true + + /bird/voice/calls/{id}/hangup: + post: + tags: + - Bird + summary: Hang up a voice call by ID + operationId: birdHangupVoiceCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: path + name: id + required: true + schema: + type: string + responses: + '200': + description: Hangup requested + content: + application/json: + schema: + type: object + additionalProperties: true + + # Bird Numbers + /bird/numbers: + get: + tags: + - Bird + summary: List your numbers + operationId: birdListNumbers + parameters: + - in: query + name: page + required: false + schema: + type: integer + - in: query + name: limit + required: false + schema: + type: integer + responses: + '200': + description: A list of numbers + content: + application/json: + schema: + type: object + additionalProperties: true + + # Bird Voice Flash Calling + /bird/voice/flash-calls: + post: + tags: + - Bird + summary: Create/place a flash call via Bird + operationId: birdCreateFlashCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: Flash call created + content: + application/json: + schema: + type: object + additionalProperties: true + get: + tags: + - Bird + summary: List flash calls + operationId: birdListFlashCalls + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: query + name: page + schema: + type: integer + required: false + responses: + '200': + description: A list of flash calls + content: + application/json: + schema: + type: object + additionalProperties: true + + /bird/voice/flash-calls/{id}: + get: + tags: + - Bird + summary: Get a flash call by ID + operationId: birdGetFlashCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: path + name: id + required: true + schema: + type: string + responses: + '200': + description: Flash call details + content: + application/json: + schema: + type: object + additionalProperties: true + post: + tags: + - Bird + summary: Complete/end a flash call by ID + description: Posts a completion/update payload to the flash call resource to finalize verification. + operationId: birdEndFlashCall + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + - in: path + name: id + required: true + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: Flash call completed + content: + application/json: + schema: + type: object + additionalProperties: true + + /bird/voice/flash-calls/end: + post: + tags: + - Bird + summary: Complete/end a flash call using from/to numbers + description: Ends an ongoing flash call by specifying the originating and destination numbers. + operationId: birdEndFlashCallByNumbers + parameters: + - in: query + name: workspaceId + schema: + type: string + required: true + description: Bird Workspace identifier + - in: query + name: channelId + schema: + type: string + required: true + description: Bird Channel identifier + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + properties: + from: + type: string + description: E.164 formatted caller number + example: "+4599988877" + to: + type: string + description: E.164 formatted callee number + example: "+4511122233" + responses: + '200': + description: Flash call completed (by numbers) + content: + application/json: + schema: + type: object + additionalProperties: true + # Subusers (public registration + setup) /subusers: get: @@ -158,6 +513,9 @@ paths: type: string format: date-time nullable: true + two_factor_enabled: + type: boolean + description: Indicates if 2FA is enabled for this account permissions: type: array description: Aggregated permission keys granted for the caller's customer @@ -476,12 +834,24 @@ paths: content: application/json: schema: - type: object - properties: - session: - type: string - description: Newly generated subuser session token - example: "2f7a8c0e-9b1d-4c6a-91a9-1a2b3c4d5e6f" + oneOf: + - type: object + required: [session] + properties: + session: + type: string + description: Newly generated subuser session token + example: "2f7a8c0e-9b1d-4c6a-91a9-1a2b3c4d5e6f" + - type: object + required: [2fa_required, 2fa_token] + properties: + 2fa_required: + type: boolean + example: true + 2fa_token: + type: string + description: Temporary 2FA verification token + example: "557a3e7b1a2b..." '400': { $ref: '#/components/responses/BadRequest' } '404': { $ref: '#/components/responses/NotFound' } '500': { $ref: '#/components/responses/InternalServerError' } @@ -685,12 +1055,24 @@ paths: content: application/json: schema: - type: object - properties: - token: - type: string - description: Bearer authentication token - example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + oneOf: + - type: object + required: [token] + properties: + token: + type: string + description: Bearer authentication token + example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + - type: object + required: [2fa_required, 2fa_token] + properties: + 2fa_required: + type: boolean + example: true + 2fa_token: + type: string + description: Temporary 2FA verification token + example: "557a3e7b1a2b..." '400': $ref: '#/components/responses/BadRequest' '401': @@ -728,11 +1110,22 @@ paths: content: application/json: schema: - type: object - properties: - token: - type: string - description: Bearer authentication token + oneOf: + - type: object + required: [token] + properties: + token: + type: string + description: Bearer authentication token + - type: object + required: [2fa_required, 2fa_token] + properties: + 2fa_required: + type: boolean + example: true + 2fa_token: + type: string + description: Temporary 2FA verification token '400': $ref: '#/components/responses/BadRequest' '401': @@ -772,7 +1165,134 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/User' + allOf: + - $ref: '#/components/schemas/User' + - type: object + properties: + two_factor_enabled: + type: boolean + description: Indicates if 2FA is enabled for this account + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + + /auth/2fa/setup: + post: + tags: + - Authentication + summary: Generate 2FA secret + description: Generate a new TOTP secret for the authenticated user/subuser + operationId: setup2fa + responses: + '200': + description: 2FA secret generated successfully + content: + application/json: + schema: + type: object + properties: + secret: + type: string + description: The base32 encoded TOTP secret + qr_code_url: + type: string + description: An otpauth URL for generating a QR code + '401': + $ref: '#/components/responses/Unauthorized' + + /auth/2fa/enable: + post: + tags: + - Authentication + summary: Enable 2FA + description: Verify a code and enable 2FA for the authenticated user/subuser + operationId: enable2fa + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [code] + properties: + code: + type: string + description: The 6-digit TOTP code + responses: + '200': + description: 2FA enabled successfully + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + + /auth/2fa/disable: + post: + tags: + - Authentication + summary: Disable 2FA + description: Verify a code and disable 2FA for the authenticated user/subuser + operationId: disable2fa + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [code] + properties: + code: + type: string + description: The 6-digit TOTP code + responses: + '200': + description: 2FA disabled successfully + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + + /auth/2fa/verify: + post: + tags: + - Authentication + summary: Verify 2FA code during login + description: Complete the login process by verifying the 2FA code + operationId: verify2fa + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [2fa_token, code] + properties: + 2fa_token: + type: string + description: The temporary 2FA verification token + code: + type: string + description: The 6-digit TOTP code + responses: + '200': + description: Login successful + content: + application/json: + schema: + oneOf: + - type: object + required: [token] + properties: + token: + type: string + description: Bearer authentication token (for users/employees) + - type: object + required: [session] + properties: + session: + type: string + description: Session token (for subusers) '400': $ref: '#/components/responses/BadRequest' '401': @@ -6693,6 +7213,9 @@ components: type: string format: date-time nullable: true + two_factor_enabled: + type: boolean + description: Indicates if 2FA is enabled for this account PermissionNode: type: object diff --git a/src/components/forms/auth/LoginForm.vue b/src/components/forms/auth/LoginForm.vue index 28b0e3fa..9023b817 100644 --- a/src/components/forms/auth/LoginForm.vue +++ b/src/components/forms/auth/LoginForm.vue @@ -1,12 +1,24 @@