mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-27 18:52:53 +00:00
Compare commits
12 Commits
interfaces
...
platform-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64ec14391b | ||
|
|
b5939080b8 | ||
|
|
528db1335f | ||
|
|
403d169d95 | ||
|
|
4c6d5e4055 | ||
|
|
1ec30662be | ||
|
|
f07cc158fe | ||
|
|
2a2fa898d7 | ||
|
|
f1d5d4f846 | ||
|
|
fdfed3103f | ||
|
|
128a4687e2 | ||
|
|
58e42df94b |
@@ -1763,6 +1763,124 @@ components:
|
||||
- type
|
||||
- orgId
|
||||
type: object
|
||||
ServiceaccounttypesFactorAPIKey:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
expires_at:
|
||||
minimum: 0
|
||||
type: integer
|
||||
id:
|
||||
type: string
|
||||
key:
|
||||
type: string
|
||||
last_used:
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
service_account_id:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- key
|
||||
- expires_at
|
||||
- last_used
|
||||
- service_account_id
|
||||
type: object
|
||||
ServiceaccounttypesPostableFactorAPIKey:
|
||||
properties:
|
||||
expires_at:
|
||||
minimum: 0
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- expires_at
|
||||
type: object
|
||||
ServiceaccounttypesPostableServiceAccount:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
roles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- name
|
||||
- email
|
||||
- roles
|
||||
type: object
|
||||
ServiceaccounttypesServiceAccount:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
orgID:
|
||||
type: string
|
||||
roles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- email
|
||||
- roles
|
||||
- status
|
||||
- orgID
|
||||
type: object
|
||||
ServiceaccounttypesUpdatableFactorAPIKey:
|
||||
properties:
|
||||
expires_at:
|
||||
minimum: 0
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- expires_at
|
||||
type: object
|
||||
ServiceaccounttypesUpdatableServiceAccount:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
roles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- name
|
||||
- email
|
||||
- roles
|
||||
type: object
|
||||
ServiceaccounttypesUpdatableServiceAccountStatus:
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
type: object
|
||||
TelemetrytypesFieldContext:
|
||||
enum:
|
||||
- metric
|
||||
@@ -4537,6 +4655,586 @@ paths:
|
||||
summary: Patch objects for a role by relation
|
||||
tags:
|
||||
- role
|
||||
/api/v1/service_accounts:
|
||||
get:
|
||||
deprecated: false
|
||||
description: This endpoint lists the service accounts for an organisation
|
||||
operationId: ListServiceAccounts
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesServiceAccount'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: List service accounts
|
||||
tags:
|
||||
- serviceaccount
|
||||
post:
|
||||
deprecated: false
|
||||
description: This endpoint creates a service account
|
||||
operationId: CreateServiceAccount
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesPostableServiceAccount'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesIdentifiable'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: Created
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"409":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Conflict
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Create service account
|
||||
tags:
|
||||
- serviceaccount
|
||||
/api/v1/service_accounts/{id}:
|
||||
delete:
|
||||
deprecated: false
|
||||
description: This endpoint deletes an existing service account
|
||||
operationId: DeleteServiceAccount
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Deletes a service account
|
||||
tags:
|
||||
- serviceaccount
|
||||
get:
|
||||
deprecated: false
|
||||
description: This endpoint gets an existing service account
|
||||
operationId: GetServiceAccount
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesServiceAccount'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Gets a service account
|
||||
tags:
|
||||
- serviceaccount
|
||||
put:
|
||||
deprecated: false
|
||||
description: This endpoint updates an existing service account
|
||||
operationId: UpdateServiceAccount
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesUpdatableServiceAccount'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Updates a service account
|
||||
tags:
|
||||
- serviceaccount
|
||||
/api/v1/service_accounts/{id}/keys:
|
||||
get:
|
||||
deprecated: false
|
||||
description: This endpoint lists the service account keys
|
||||
operationId: ListServiceAccountKeys
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesFactorAPIKey'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: List service account keys
|
||||
tags:
|
||||
- serviceaccount
|
||||
post:
|
||||
deprecated: false
|
||||
description: This endpoint creates a service account key
|
||||
operationId: CreateServiceAccountKey
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesPostableFactorAPIKey'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesIdentifiable'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: Created
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"409":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Conflict
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Create a service account key
|
||||
tags:
|
||||
- serviceaccount
|
||||
/api/v1/service_accounts/{id}/keys/{fid}:
|
||||
delete:
|
||||
deprecated: false
|
||||
description: This endpoint revokes an existing service account key
|
||||
operationId: RevokeServiceAccountKey
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: fid
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Revoke a service account key
|
||||
tags:
|
||||
- serviceaccount
|
||||
put:
|
||||
deprecated: false
|
||||
description: This endpoint updates an existing service account key
|
||||
operationId: UpdateServiceAccountKey
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: fid
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesUpdatableFactorAPIKey'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Updates a service account key
|
||||
tags:
|
||||
- serviceaccount
|
||||
/api/v1/service_accounts/{id}/status:
|
||||
put:
|
||||
deprecated: false
|
||||
description: This endpoint updates an existing service account status
|
||||
operationId: UpdateServiceAccountStatus
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceaccounttypesUpdatableServiceAccountStatus'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
description: No Content
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Updates a service account status
|
||||
tags:
|
||||
- serviceaccount
|
||||
/api/v1/user:
|
||||
get:
|
||||
deprecated: false
|
||||
|
||||
@@ -98,16 +98,20 @@ func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.
|
||||
return provider.pkgAuthzService.ListByOrgIDAndNames(ctx, orgID, names)
|
||||
}
|
||||
|
||||
func (provider *provider) Grant(ctx context.Context, orgID valuer.UUID, name string, subject string) error {
|
||||
return provider.pkgAuthzService.Grant(ctx, orgID, name, subject)
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.Role, error) {
|
||||
return provider.pkgAuthzService.ListByOrgIDAndIDs(ctx, orgID, ids)
|
||||
}
|
||||
|
||||
func (provider *provider) ModifyGrant(ctx context.Context, orgID valuer.UUID, existingRoleName string, updatedRoleName string, subject string) error {
|
||||
return provider.pkgAuthzService.ModifyGrant(ctx, orgID, existingRoleName, updatedRoleName, subject)
|
||||
func (provider *provider) Grant(ctx context.Context, orgID valuer.UUID, names []string, subject string) error {
|
||||
return provider.pkgAuthzService.Grant(ctx, orgID, names, subject)
|
||||
}
|
||||
|
||||
func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, name string, subject string) error {
|
||||
return provider.pkgAuthzService.Revoke(ctx, orgID, name, subject)
|
||||
func (provider *provider) ModifyGrant(ctx context.Context, orgID valuer.UUID, existingRoleNames []string, updatedRoleNames []string, subject string) error {
|
||||
return provider.pkgAuthzService.ModifyGrant(ctx, orgID, existingRoleNames, updatedRoleNames, subject)
|
||||
}
|
||||
|
||||
func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, names []string, subject string) error {
|
||||
return provider.pkgAuthzService.Revoke(ctx, orgID, names, subject)
|
||||
}
|
||||
|
||||
func (provider *provider) CreateManagedRoles(ctx context.Context, orgID valuer.UUID, managedRoles []*roletypes.Role) error {
|
||||
|
||||
973
frontend/src/api/generated/services/serviceaccount/index.ts
Normal file
973
frontend/src/api/generated/services/serviceaccount/index.ts
Normal file
@@ -0,0 +1,973 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
MutationFunction,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
import type { BodyType, ErrorType } from '../../../generatedAPIInstance';
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type {
|
||||
CreateServiceAccount201,
|
||||
CreateServiceAccountKey201,
|
||||
CreateServiceAccountKeyPathParameters,
|
||||
DeleteServiceAccountPathParameters,
|
||||
GetServiceAccount200,
|
||||
GetServiceAccountPathParameters,
|
||||
ListServiceAccountKeys200,
|
||||
ListServiceAccountKeysPathParameters,
|
||||
ListServiceAccounts200,
|
||||
RenderErrorResponseDTO,
|
||||
RevokeServiceAccountKeyPathParameters,
|
||||
ServiceaccounttypesPostableFactorAPIKeyDTO,
|
||||
ServiceaccounttypesPostableServiceAccountDTO,
|
||||
ServiceaccounttypesUpdatableFactorAPIKeyDTO,
|
||||
ServiceaccounttypesUpdatableServiceAccountDTO,
|
||||
ServiceaccounttypesUpdatableServiceAccountStatusDTO,
|
||||
UpdateServiceAccountKeyPathParameters,
|
||||
UpdateServiceAccountPathParameters,
|
||||
UpdateServiceAccountStatusPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
type AwaitedInput<T> = PromiseLike<T> | T;
|
||||
|
||||
type Awaited<O> = O extends AwaitedInput<infer T> ? T : never;
|
||||
|
||||
/**
|
||||
* This endpoint lists the service accounts for an organisation
|
||||
* @summary List service accounts
|
||||
*/
|
||||
export const listServiceAccounts = (signal?: AbortSignal) => {
|
||||
return GeneratedAPIInstance<ListServiceAccounts200>({
|
||||
url: `/api/v1/service_accounts`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListServiceAccountsQueryKey = () => {
|
||||
return [`/api/v1/service_accounts`] as const;
|
||||
};
|
||||
|
||||
export const getListServiceAccountsQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listServiceAccounts>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccounts>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListServiceAccountsQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listServiceAccounts>>
|
||||
> = ({ signal }) => listServiceAccounts(signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccounts>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListServiceAccountsQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listServiceAccounts>>
|
||||
>;
|
||||
export type ListServiceAccountsQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List service accounts
|
||||
*/
|
||||
|
||||
export function useListServiceAccounts<
|
||||
TData = Awaited<ReturnType<typeof listServiceAccounts>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccounts>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListServiceAccountsQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List service accounts
|
||||
*/
|
||||
export const invalidateListServiceAccounts = async (
|
||||
queryClient: QueryClient,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListServiceAccountsQueryKey() },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a service account
|
||||
* @summary Create service account
|
||||
*/
|
||||
export const createServiceAccount = (
|
||||
serviceaccounttypesPostableServiceAccountDTO: BodyType<ServiceaccounttypesPostableServiceAccountDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateServiceAccount201>({
|
||||
url: `/api/v1/service_accounts`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: serviceaccounttypesPostableServiceAccountDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateServiceAccountMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>,
|
||||
TError,
|
||||
{ data: BodyType<ServiceaccounttypesPostableServiceAccountDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>,
|
||||
TError,
|
||||
{ data: BodyType<ServiceaccounttypesPostableServiceAccountDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createServiceAccount'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>,
|
||||
{ data: BodyType<ServiceaccounttypesPostableServiceAccountDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createServiceAccount(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateServiceAccountMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>
|
||||
>;
|
||||
export type CreateServiceAccountMutationBody = BodyType<ServiceaccounttypesPostableServiceAccountDTO>;
|
||||
export type CreateServiceAccountMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create service account
|
||||
*/
|
||||
export const useCreateServiceAccount = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>,
|
||||
TError,
|
||||
{ data: BodyType<ServiceaccounttypesPostableServiceAccountDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createServiceAccount>>,
|
||||
TError,
|
||||
{ data: BodyType<ServiceaccounttypesPostableServiceAccountDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateServiceAccountMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint deletes an existing service account
|
||||
* @summary Deletes a service account
|
||||
*/
|
||||
export const deleteServiceAccount = ({
|
||||
id,
|
||||
}: DeleteServiceAccountPathParameters) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/service_accounts/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteServiceAccountMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>,
|
||||
TError,
|
||||
{ pathParams: DeleteServiceAccountPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>,
|
||||
TError,
|
||||
{ pathParams: DeleteServiceAccountPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteServiceAccount'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>,
|
||||
{ pathParams: DeleteServiceAccountPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteServiceAccount(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteServiceAccountMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>
|
||||
>;
|
||||
|
||||
export type DeleteServiceAccountMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Deletes a service account
|
||||
*/
|
||||
export const useDeleteServiceAccount = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>,
|
||||
TError,
|
||||
{ pathParams: DeleteServiceAccountPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteServiceAccount>>,
|
||||
TError,
|
||||
{ pathParams: DeleteServiceAccountPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteServiceAccountMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint gets an existing service account
|
||||
* @summary Gets a service account
|
||||
*/
|
||||
export const getServiceAccount = (
|
||||
{ id }: GetServiceAccountPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetServiceAccount200>({
|
||||
url: `/api/v1/service_accounts/${id}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetServiceAccountQueryKey = ({
|
||||
id,
|
||||
}: GetServiceAccountPathParameters) => {
|
||||
return [`/api/v1/service_accounts/${id}`] as const;
|
||||
};
|
||||
|
||||
export const getGetServiceAccountQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getServiceAccount>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetServiceAccountPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getServiceAccount>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getGetServiceAccountQueryKey({ id });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getServiceAccount>>
|
||||
> = ({ signal }) => getServiceAccount({ id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!id,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getServiceAccount>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetServiceAccountQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getServiceAccount>>
|
||||
>;
|
||||
export type GetServiceAccountQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Gets a service account
|
||||
*/
|
||||
|
||||
export function useGetServiceAccount<
|
||||
TData = Awaited<ReturnType<typeof getServiceAccount>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: GetServiceAccountPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getServiceAccount>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetServiceAccountQueryOptions({ id }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Gets a service account
|
||||
*/
|
||||
export const invalidateGetServiceAccount = async (
|
||||
queryClient: QueryClient,
|
||||
{ id }: GetServiceAccountPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetServiceAccountQueryKey({ id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates an existing service account
|
||||
* @summary Updates a service account
|
||||
*/
|
||||
export const updateServiceAccount = (
|
||||
{ id }: UpdateServiceAccountPathParameters,
|
||||
serviceaccounttypesUpdatableServiceAccountDTO: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/service_accounts/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: serviceaccounttypesUpdatableServiceAccountDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateServiceAccountMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateServiceAccount'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>,
|
||||
{
|
||||
pathParams: UpdateServiceAccountPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateServiceAccount(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateServiceAccountMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>
|
||||
>;
|
||||
export type UpdateServiceAccountMutationBody = BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
export type UpdateServiceAccountMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Updates a service account
|
||||
*/
|
||||
export const useUpdateServiceAccount = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateServiceAccount>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateServiceAccountMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint lists the service account keys
|
||||
* @summary List service account keys
|
||||
*/
|
||||
export const listServiceAccountKeys = (
|
||||
{ id }: ListServiceAccountKeysPathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListServiceAccountKeys200>({
|
||||
url: `/api/v1/service_accounts/${id}/keys`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListServiceAccountKeysQueryKey = ({
|
||||
id,
|
||||
}: ListServiceAccountKeysPathParameters) => {
|
||||
return [`/api/v1/service_accounts/${id}/keys`] as const;
|
||||
};
|
||||
|
||||
export const getListServiceAccountKeysQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listServiceAccountKeys>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: ListServiceAccountKeysPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccountKeys>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListServiceAccountKeysQueryKey({ id });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listServiceAccountKeys>>
|
||||
> = ({ signal }) => listServiceAccountKeys({ id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!id,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccountKeys>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListServiceAccountKeysQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listServiceAccountKeys>>
|
||||
>;
|
||||
export type ListServiceAccountKeysQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List service account keys
|
||||
*/
|
||||
|
||||
export function useListServiceAccountKeys<
|
||||
TData = Awaited<ReturnType<typeof listServiceAccountKeys>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>
|
||||
>(
|
||||
{ id }: ListServiceAccountKeysPathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listServiceAccountKeys>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListServiceAccountKeysQueryOptions({ id }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List service account keys
|
||||
*/
|
||||
export const invalidateListServiceAccountKeys = async (
|
||||
queryClient: QueryClient,
|
||||
{ id }: ListServiceAccountKeysPathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListServiceAccountKeysQueryKey({ id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint creates a service account key
|
||||
* @summary Create a service account key
|
||||
*/
|
||||
export const createServiceAccountKey = (
|
||||
{ id }: CreateServiceAccountKeyPathParameters,
|
||||
serviceaccounttypesPostableFactorAPIKeyDTO: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateServiceAccountKey201>({
|
||||
url: `/api/v1/service_accounts/${id}/keys`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: serviceaccounttypesPostableFactorAPIKeyDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateServiceAccountKeyMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createServiceAccountKey'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>,
|
||||
{
|
||||
pathParams: CreateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return createServiceAccountKey(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateServiceAccountKeyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>
|
||||
>;
|
||||
export type CreateServiceAccountKeyMutationBody = BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
export type CreateServiceAccountKeyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create a service account key
|
||||
*/
|
||||
export const useCreateServiceAccountKey = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: CreateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesPostableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateServiceAccountKeyMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint revokes an existing service account key
|
||||
* @summary Revoke a service account key
|
||||
*/
|
||||
export const revokeServiceAccountKey = ({
|
||||
id,
|
||||
fid,
|
||||
}: RevokeServiceAccountKeyPathParameters) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/service_accounts/${id}/keys/${fid}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getRevokeServiceAccountKeyMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>,
|
||||
TError,
|
||||
{ pathParams: RevokeServiceAccountKeyPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>,
|
||||
TError,
|
||||
{ pathParams: RevokeServiceAccountKeyPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['revokeServiceAccountKey'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>,
|
||||
{ pathParams: RevokeServiceAccountKeyPathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return revokeServiceAccountKey(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type RevokeServiceAccountKeyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>
|
||||
>;
|
||||
|
||||
export type RevokeServiceAccountKeyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Revoke a service account key
|
||||
*/
|
||||
export const useRevokeServiceAccountKey = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>,
|
||||
TError,
|
||||
{ pathParams: RevokeServiceAccountKeyPathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof revokeServiceAccountKey>>,
|
||||
TError,
|
||||
{ pathParams: RevokeServiceAccountKeyPathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getRevokeServiceAccountKeyMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint updates an existing service account key
|
||||
* @summary Updates a service account key
|
||||
*/
|
||||
export const updateServiceAccountKey = (
|
||||
{ id, fid }: UpdateServiceAccountKeyPathParameters,
|
||||
serviceaccounttypesUpdatableFactorAPIKeyDTO: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/service_accounts/${id}/keys/${fid}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: serviceaccounttypesUpdatableFactorAPIKeyDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateServiceAccountKeyMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateServiceAccountKey'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>,
|
||||
{
|
||||
pathParams: UpdateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateServiceAccountKey(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateServiceAccountKeyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>
|
||||
>;
|
||||
export type UpdateServiceAccountKeyMutationBody = BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
export type UpdateServiceAccountKeyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Updates a service account key
|
||||
*/
|
||||
export const useUpdateServiceAccountKey = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateServiceAccountKey>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountKeyPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableFactorAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateServiceAccountKeyMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* This endpoint updates an existing service account status
|
||||
* @summary Updates a service account status
|
||||
*/
|
||||
export const updateServiceAccountStatus = (
|
||||
{ id }: UpdateServiceAccountStatusPathParameters,
|
||||
serviceaccounttypesUpdatableServiceAccountStatusDTO: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/service_accounts/${id}/status`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: serviceaccounttypesUpdatableServiceAccountStatusDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getUpdateServiceAccountStatusMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountStatusPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountStatusPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateServiceAccountStatus'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>,
|
||||
{
|
||||
pathParams: UpdateServiceAccountStatusPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
return updateServiceAccountStatus(pathParams, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateServiceAccountStatusMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>
|
||||
>;
|
||||
export type UpdateServiceAccountStatusMutationBody = BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
export type UpdateServiceAccountStatusMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Updates a service account status
|
||||
*/
|
||||
export const useUpdateServiceAccountStatus = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountStatusPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateServiceAccountStatus>>,
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateServiceAccountStatusPathParameters;
|
||||
data: BodyType<ServiceaccounttypesUpdatableServiceAccountStatusDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateServiceAccountStatusMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
@@ -2090,6 +2090,143 @@ export interface RoletypesRoleDTO {
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesFactorAPIKeyDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
expires_at: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
last_used: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
service_account_id: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesPostableFactorAPIKeyDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
expires_at: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesPostableServiceAccountDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
email: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesServiceAccountDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
email: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
orgID: string;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
roles: string[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesUpdatableFactorAPIKeyDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
expires_at: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesUpdatableServiceAccountDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
email: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesUpdatableServiceAccountStatusDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
}
|
||||
|
||||
export enum TelemetrytypesFieldContextDTO {
|
||||
metric = 'metric',
|
||||
log = 'log',
|
||||
@@ -3050,6 +3187,78 @@ export type PatchObjectsPathParameters = {
|
||||
id: string;
|
||||
relation: string;
|
||||
};
|
||||
export type ListServiceAccounts200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: ServiceaccounttypesServiceAccountDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type CreateServiceAccount201 = {
|
||||
data: TypesIdentifiableDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type DeleteServiceAccountPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetServiceAccountPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetServiceAccount200 = {
|
||||
data: ServiceaccounttypesServiceAccountDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type UpdateServiceAccountPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type ListServiceAccountKeysPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type ListServiceAccountKeys200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: ServiceaccounttypesFactorAPIKeyDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type CreateServiceAccountKeyPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type CreateServiceAccountKey201 = {
|
||||
data: TypesIdentifiableDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type RevokeServiceAccountKeyPathParameters = {
|
||||
id: string;
|
||||
fid: string;
|
||||
};
|
||||
export type UpdateServiceAccountKeyPathParameters = {
|
||||
id: string;
|
||||
fid: string;
|
||||
};
|
||||
export type UpdateServiceAccountStatusPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type ListUsers200 = {
|
||||
/**
|
||||
* @type array
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/preference"
|
||||
"github.com/SigNoz/signoz/pkg/modules/promote"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
@@ -48,6 +49,7 @@ type provider struct {
|
||||
authzHandler authz.Handler
|
||||
zeusHandler zeus.Handler
|
||||
querierHandler querier.Handler
|
||||
serviceAccountHandler serviceaccount.Handler
|
||||
}
|
||||
|
||||
func NewFactory(
|
||||
@@ -69,6 +71,7 @@ func NewFactory(
|
||||
authzHandler authz.Handler,
|
||||
zeusHandler zeus.Handler,
|
||||
querierHandler querier.Handler,
|
||||
serviceAccountHandler serviceaccount.Handler,
|
||||
) factory.ProviderFactory[apiserver.APIServer, apiserver.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName("signoz"), func(ctx context.Context, providerSettings factory.ProviderSettings, config apiserver.Config) (apiserver.APIServer, error) {
|
||||
return newProvider(
|
||||
@@ -93,6 +96,7 @@ func NewFactory(
|
||||
authzHandler,
|
||||
zeusHandler,
|
||||
querierHandler,
|
||||
serviceAccountHandler,
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -119,6 +123,7 @@ func newProvider(
|
||||
authzHandler authz.Handler,
|
||||
zeusHandler zeus.Handler,
|
||||
querierHandler querier.Handler,
|
||||
serviceAccountHandler serviceaccount.Handler,
|
||||
) (apiserver.APIServer, error) {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/apiserver/signozapiserver")
|
||||
router := mux.NewRouter().UseEncodedPath()
|
||||
@@ -143,6 +148,7 @@ func newProvider(
|
||||
authzHandler: authzHandler,
|
||||
zeusHandler: zeusHandler,
|
||||
querierHandler: querierHandler,
|
||||
serviceAccountHandler: serviceAccountHandler,
|
||||
}
|
||||
|
||||
provider.authZ = middleware.NewAuthZ(settings.Logger(), orgGetter, authz)
|
||||
@@ -223,6 +229,10 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := provider.addServiceAccountRoutes(router); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
184
pkg/apiserver/signozapiserver/serviceaccount.go
Normal file
184
pkg/apiserver/signozapiserver/serviceaccount.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package signozapiserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.Create), handler.OpenAPIDef{
|
||||
ID: "CreateServiceAccount",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Create service account",
|
||||
Description: "This endpoint creates a service account",
|
||||
Request: new(serviceaccounttypes.PostableServiceAccount),
|
||||
RequestContentType: "",
|
||||
Response: new(types.Identifiable),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.List), handler.OpenAPIDef{
|
||||
ID: "ListServiceAccounts",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "List service accounts",
|
||||
Description: "This endpoint lists the service accounts for an organisation",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*serviceaccounttypes.ServiceAccount, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.Get), handler.OpenAPIDef{
|
||||
ID: "GetServiceAccount",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Gets a service account",
|
||||
Description: "This endpoint gets an existing service account",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(serviceaccounttypes.ServiceAccount),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.Update), handler.OpenAPIDef{
|
||||
ID: "UpdateServiceAccount",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Updates a service account",
|
||||
Description: "This endpoint updates an existing service account",
|
||||
Request: new(serviceaccounttypes.UpdatableServiceAccount),
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}/status", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.UpdateStatus), handler.OpenAPIDef{
|
||||
ID: "UpdateServiceAccountStatus",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Updates a service account status",
|
||||
Description: "This endpoint updates an existing service account status",
|
||||
Request: new(serviceaccounttypes.UpdatableServiceAccountStatus),
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.Delete), handler.OpenAPIDef{
|
||||
ID: "DeleteServiceAccount",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Deletes a service account",
|
||||
Description: "This endpoint deletes an existing service account",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.CreateFactorAPIKey), handler.OpenAPIDef{
|
||||
ID: "CreateServiceAccountKey",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Create a service account key",
|
||||
Description: "This endpoint creates a service account key",
|
||||
Request: new(serviceaccounttypes.PostableFactorAPIKey),
|
||||
RequestContentType: "",
|
||||
Response: new(types.Identifiable),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}/keys", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.ListFactorAPIKey), handler.OpenAPIDef{
|
||||
ID: "ListServiceAccountKeys",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "List service account keys",
|
||||
Description: "This endpoint lists the service account keys",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*serviceaccounttypes.FactorAPIKey, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.UpdateFactorAPIKey), handler.OpenAPIDef{
|
||||
ID: "UpdateServiceAccountKey",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Updates a service account key",
|
||||
Description: "This endpoint updates an existing service account key",
|
||||
Request: new(serviceaccounttypes.UpdatableFactorAPIKey),
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/service_accounts/{id}/keys/{fid}", handler.New(provider.authZ.AdminAccess(provider.serviceAccountHandler.RevokeFactorAPIKey), handler.OpenAPIDef{
|
||||
ID: "RevokeServiceAccountKey",
|
||||
Tags: []string{"serviceaccount"},
|
||||
Summary: "Revoke a service account key",
|
||||
Description: "This endpoint revokes an existing service account key",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -62,14 +62,17 @@ type AuthZ interface {
|
||||
// Lists all the roles for the organization filtered by name
|
||||
ListByOrgIDAndNames(context.Context, valuer.UUID, []string) ([]*roletypes.Role, error)
|
||||
|
||||
// Lists all the roles for the organization filtered by ids
|
||||
ListByOrgIDAndIDs(context.Context, valuer.UUID, []valuer.UUID) ([]*roletypes.Role, error)
|
||||
|
||||
// Grants a role to the subject based on role name.
|
||||
Grant(context.Context, valuer.UUID, string, string) error
|
||||
Grant(context.Context, valuer.UUID, []string, string) error
|
||||
|
||||
// Revokes a granted role from the subject based on role name.
|
||||
Revoke(context.Context, valuer.UUID, string, string) error
|
||||
Revoke(context.Context, valuer.UUID, []string, string) error
|
||||
|
||||
// Changes the granted role for the subject based on role name.
|
||||
ModifyGrant(context.Context, valuer.UUID, string, string, string) error
|
||||
ModifyGrant(context.Context, valuer.UUID, []string, []string, string) error
|
||||
|
||||
// Bootstrap the managed roles.
|
||||
CreateManagedRoles(context.Context, valuer.UUID, []*roletypes.Role) error
|
||||
|
||||
@@ -96,6 +96,39 @@ func (store *store) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) != len(names) {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(
|
||||
nil,
|
||||
roletypes.ErrCodeRoleNotFound,
|
||||
"not all roles found for the provided names: %v", names,
|
||||
)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (store *store) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.StorableRole, error) {
|
||||
roles := make([]*roletypes.StorableRole, 0)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&roles).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("id IN (?)", bun.In(ids)).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) != len(ids) {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(
|
||||
nil,
|
||||
roletypes.ErrCodeRoleNotFound,
|
||||
"not all roles found for the provided ids: %v", ids,
|
||||
)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -114,28 +114,46 @@ func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (provider *provider) Grant(ctx context.Context, orgID valuer.UUID, name string, subject string) error {
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.Role, error) {
|
||||
storableRoles, err := provider.store.ListByOrgIDAndIDs(ctx, orgID, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roles := make([]*roletypes.Role, len(storableRoles))
|
||||
for idx, storable := range storableRoles {
|
||||
roles[idx] = roletypes.NewRoleFromStorableRole(storable)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (provider *provider) Grant(ctx context.Context, orgID valuer.UUID, names []string, subject string) error {
|
||||
selectors := make([]authtypes.Selector, len(names))
|
||||
for idx, name := range names {
|
||||
selectors[idx] = authtypes.MustNewSelector(authtypes.TypeRole, name)
|
||||
}
|
||||
|
||||
tuples, err := authtypes.TypeableRole.Tuples(
|
||||
subject,
|
||||
authtypes.RelationAssignee,
|
||||
[]authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, name),
|
||||
},
|
||||
selectors,
|
||||
orgID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return provider.Write(ctx, tuples, nil)
|
||||
}
|
||||
|
||||
func (provider *provider) ModifyGrant(ctx context.Context, orgID valuer.UUID, existingRoleName string, updatedRoleName string, subject string) error {
|
||||
err := provider.Revoke(ctx, orgID, existingRoleName, subject)
|
||||
func (provider *provider) ModifyGrant(ctx context.Context, orgID valuer.UUID, existingRoleNames []string, updatedRoleNames []string, subject string) error {
|
||||
err := provider.Revoke(ctx, orgID, existingRoleNames, subject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = provider.Grant(ctx, orgID, updatedRoleName, subject)
|
||||
err = provider.Grant(ctx, orgID, updatedRoleNames, subject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,13 +161,16 @@ func (provider *provider) ModifyGrant(ctx context.Context, orgID valuer.UUID, ex
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, name string, subject string) error {
|
||||
func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, names []string, subject string) error {
|
||||
selectors := make([]authtypes.Selector, len(names))
|
||||
for idx, name := range names {
|
||||
selectors[idx] = authtypes.MustNewSelector(authtypes.TypeRole, name)
|
||||
}
|
||||
|
||||
tuples, err := authtypes.TypeableRole.Tuples(
|
||||
subject,
|
||||
authtypes.RelationAssignee,
|
||||
[]authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, name),
|
||||
},
|
||||
selectors,
|
||||
orgID,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -178,7 +199,7 @@ func (provider *provider) CreateManagedRoles(ctx context.Context, _ valuer.UUID,
|
||||
}
|
||||
|
||||
func (provider *provider) CreateManagedUserRoleTransactions(ctx context.Context, orgID valuer.UUID, userID valuer.UUID) error {
|
||||
return provider.Grant(ctx, orgID, roletypes.SigNozAdminRoleName, authtypes.MustNewSubject(authtypes.TypeableUser, userID.String(), orgID, nil))
|
||||
return provider.Grant(ctx, orgID, []string{roletypes.SigNozAdminRoleName}, authtypes.MustNewSubject(authtypes.TypeableUser, userID.String(), orgID, nil))
|
||||
}
|
||||
|
||||
func (setter *provider) Create(_ context.Context, _ valuer.UUID, _ *roletypes.Role) error {
|
||||
|
||||
335
pkg/modules/serviceaccount/implserviceaccount/handler.go
Normal file
335
pkg/modules/serviceaccount/implserviceaccount/handler.go
Normal file
@@ -0,0 +1,335 @@
|
||||
package implserviceaccount
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/binding"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
module serviceaccount.Module
|
||||
}
|
||||
|
||||
func NewHandler(module serviceaccount.Module) serviceaccount.Handler {
|
||||
return &handler{module: module}
|
||||
}
|
||||
|
||||
func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(serviceaccounttypes.PostableServiceAccount)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount := serviceaccounttypes.NewServiceAccount(req.Name, req.Email, req.Roles, serviceaccounttypes.StatusActive, valuer.MustNewUUID(claims.OrgID))
|
||||
err = handler.module.Create(ctx, valuer.MustNewUUID(claims.OrgID), serviceAccount)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, types.Identifiable{ID: serviceAccount.ID})
|
||||
}
|
||||
|
||||
func (handler *handler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.Get(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, serviceAccount)
|
||||
}
|
||||
|
||||
func (handler *handler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccounts, err := handler.module.List(ctx, valuer.MustNewUUID(claims.OrgID))
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, serviceAccounts)
|
||||
}
|
||||
|
||||
func (handler *handler) Update(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(serviceaccounttypes.UpdatableServiceAccount)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.Get(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount.Update(req.Name, req.Email, req.Roles)
|
||||
err = handler.module.Update(ctx, valuer.MustNewUUID(claims.OrgID), serviceAccount)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateStatus(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(serviceaccounttypes.UpdatableServiceAccountStatus)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.Get(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount.UpdateStatus(req.Status)
|
||||
err = handler.module.UpdateStatus(ctx, valuer.MustNewUUID(claims.OrgID), serviceAccount)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.Delete(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) CreateFactorAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(serviceaccounttypes.PostableFactorAPIKey)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
// this takes care of checking the existence of service account and the org constraint.
|
||||
serviceAccount, err := handler.module.GetWithoutRoles(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKey, err := serviceAccount.NewFactorAPIKey(req.Name, req.ExpiresAt)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.CreateFactorAPIKey(ctx, factorAPIKey)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusCreated, types.Identifiable{ID: factorAPIKey.ID})
|
||||
}
|
||||
|
||||
func (handler *handler) ListFactorAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.GetWithoutRoles(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKeys, err := handler.module.ListFactorAPIKey(ctx, serviceAccount.ID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, serviceaccounttypes.NewGettableFactorAPIKeys(factorAPIKeys))
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateFactorAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKeyID, err := valuer.NewUUID(mux.Vars(r)["fid"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(serviceaccounttypes.UpdatableFactorAPIKey)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.GetWithoutRoles(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKey, err := handler.module.GetFactorAPIKey(ctx, serviceAccount.ID, factorAPIKeyID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKey.Update(req.Name, req.ExpiresAt)
|
||||
err = handler.module.UpdateFactorAPIKey(ctx, serviceAccount.ID, factorAPIKey)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) RevokeFactorAPIKey(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
factorAPIKeyID, err := valuer.NewUUID(mux.Vars(r)["fid"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceAccount, err := handler.module.GetWithoutRoles(ctx, valuer.MustNewUUID(claims.OrgID), id)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.RevokeFactorAPIKey(ctx, serviceAccount.ID, factorAPIKeyID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
351
pkg/modules/serviceaccount/implserviceaccount/module.go
Normal file
351
pkg/modules/serviceaccount/implserviceaccount/module.go
Normal file
@@ -0,0 +1,351 @@
|
||||
package implserviceaccount
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authz"
|
||||
"github.com/SigNoz/signoz/pkg/emailing"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/emailtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type module struct {
|
||||
store serviceaccounttypes.Store
|
||||
authz authz.AuthZ
|
||||
emailing emailing.Emailing
|
||||
settings factory.ScopedProviderSettings
|
||||
}
|
||||
|
||||
func NewModule(store serviceaccounttypes.Store, authz authz.AuthZ, emailing emailing.Emailing, providerSettings factory.ProviderSettings) serviceaccount.Module {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/modules/serviceaccount/implserviceaccount")
|
||||
return &module{store: store, authz: authz, emailing: emailing, settings: settings}
|
||||
}
|
||||
|
||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, serviceAccount *serviceaccounttypes.ServiceAccount) error {
|
||||
// validates the presence of all roles passed in the create request
|
||||
roles, err := module.authz.ListByOrgIDAndNames(ctx, orgID, serviceAccount.Roles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// authz actions cannot run in sql transactions
|
||||
err = module.authz.Grant(ctx, orgID, serviceAccount.Roles, authtypes.MustNewSubject(authtypes.TypeableUser, serviceAccount.ID.String(), orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storableServiceAccount := serviceaccounttypes.NewStorableServiceAccount(serviceAccount)
|
||||
storableServiceAccountRoles := serviceaccounttypes.NewStorableServiceAccountRoles(serviceAccount.ID, roles)
|
||||
err = module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
err := module.store.Create(ctx, storableServiceAccount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.CreateServiceAccountRoles(ctx, storableServiceAccountRoles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*serviceaccounttypes.ServiceAccount, error) {
|
||||
storableServiceAccount, err := module.store.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// did the orchestration on application layer instead of DB as the ORM also does it anyways for many to many tables.
|
||||
storableServiceAccountRoles, err := module.store.GetServiceAccountRoles(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleIDs := make([]valuer.UUID, len(storableServiceAccountRoles))
|
||||
for idx, sar := range storableServiceAccountRoles {
|
||||
roleIDs[idx] = valuer.MustNewUUID(sar.RoleID)
|
||||
}
|
||||
|
||||
roles, err := module.authz.ListByOrgIDAndIDs(ctx, orgID, roleIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rolesNames, err := serviceaccounttypes.NewRolesFromStorableServiceAccountRoles(storableServiceAccountRoles, roles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serviceAccount := serviceaccounttypes.NewServiceAccountFromStorables(storableServiceAccount, rolesNames)
|
||||
return serviceAccount, nil
|
||||
}
|
||||
|
||||
func (module *module) GetWithoutRoles(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*serviceaccounttypes.ServiceAccount, error) {
|
||||
storableServiceAccount, err := module.store.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// passing []string{} (not nil to prevent panics) roles as the function isn't supposed to put roles.
|
||||
serviceAccount := serviceaccounttypes.NewServiceAccountFromStorables(storableServiceAccount, []string{})
|
||||
return serviceAccount, nil
|
||||
}
|
||||
|
||||
func (module *module) List(ctx context.Context, orgID valuer.UUID) ([]*serviceaccounttypes.ServiceAccount, error) {
|
||||
storableServiceAccounts, err := module.store.List(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storableServiceAccountRoles, err := module.store.ListServiceAccountRolesByOrgID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// convert the service account roles to structured data
|
||||
saIDToRoleIDs, roleIDs := serviceaccounttypes.GetUniqueRolesAndServiceAccountMapping(storableServiceAccountRoles)
|
||||
roles, err := module.authz.ListByOrgIDAndIDs(ctx, orgID, roleIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// fill in the role fetched data back to service account
|
||||
serviceAccounts := serviceaccounttypes.NewServiceAccountsFromRoles(storableServiceAccounts, roles, saIDToRoleIDs)
|
||||
return serviceAccounts, nil
|
||||
}
|
||||
|
||||
func (module *module) Update(ctx context.Context, orgID valuer.UUID, input *serviceaccounttypes.ServiceAccount) error {
|
||||
serviceAccount, err := module.Get(ctx, orgID, input.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
roles, err := module.authz.ListByOrgIDAndNames(ctx, orgID, input.Roles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// gets the role diff if any to modify grants.
|
||||
grants, revokes := serviceAccount.PatchRoles(input)
|
||||
err = module.authz.ModifyGrant(ctx, orgID, revokes, grants, authtypes.MustNewSubject(authtypes.TypeableUser, serviceAccount.ID.String(), orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storableServiceAccountRoles := serviceaccounttypes.NewStorableServiceAccountRoles(serviceAccount.ID, roles)
|
||||
err = module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
err := module.store.Update(ctx, orgID, serviceaccounttypes.NewStorableServiceAccount(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete all the service account roles and create new rather than diff here.
|
||||
err = module.store.DeleteServiceAccountRoles(ctx, input.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.CreateServiceAccountRoles(ctx, storableServiceAccountRoles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) UpdateStatus(ctx context.Context, orgID valuer.UUID, input *serviceaccounttypes.ServiceAccount) error {
|
||||
serviceAccount, err := module.Get(ctx, orgID, input.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if input.Status == serviceAccount.Status {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch input.Status {
|
||||
case serviceaccounttypes.StatusActive:
|
||||
err := module.activateServiceAccount(ctx, orgID, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serviceaccounttypes.StatusDisabled:
|
||||
err := module.disableServiceAccount(ctx, orgID, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error {
|
||||
serviceAccount, err := module.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// revoke from authz first as this cannot run in sql transaction
|
||||
err = module.authz.Revoke(ctx, orgID, serviceAccount.Roles, authtypes.MustNewSubject(authtypes.TypeableUser, serviceAccount.ID.String(), orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
err := module.store.DeleteServiceAccountRoles(ctx, serviceAccount.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.RevokeAllFactorAPIKeys(ctx, serviceAccount.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.Delete(ctx, serviceAccount.OrgID, serviceAccount.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) CreateFactorAPIKey(ctx context.Context, factorAPIKey *serviceaccounttypes.FactorAPIKey) error {
|
||||
storableFactorAPIKey := serviceaccounttypes.NewStorableFactorAPIKey(factorAPIKey)
|
||||
|
||||
err := module.store.CreateFactorAPIKey(ctx, storableFactorAPIKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceAccount, err := module.store.GetByID(ctx, factorAPIKey.ServiceAccountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.emailing.SendHTML(ctx, serviceAccount.Email, "New API Key created for your SigNoz account", emailtypes.TemplateNameAPIKeyEvent, map[string]any{
|
||||
"Name": serviceAccount.Name,
|
||||
"KeyName": factorAPIKey.Name,
|
||||
"KeyID": factorAPIKey.ID.String(),
|
||||
"KeyCreatedAt": factorAPIKey.CreatedAt.String(),
|
||||
}); err != nil {
|
||||
module.settings.Logger().ErrorContext(ctx, "failed to send email", "error", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) GetFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, id valuer.UUID) (*serviceaccounttypes.FactorAPIKey, error) {
|
||||
storableFactorAPIKey, err := module.store.GetFactorAPIKey(ctx, serviceAccountID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serviceaccounttypes.NewFactorAPIKeyFromStorable(storableFactorAPIKey), nil
|
||||
}
|
||||
|
||||
func (module *module) ListFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID) ([]*serviceaccounttypes.FactorAPIKey, error) {
|
||||
storables, err := module.store.ListFactorAPIKey(ctx, serviceAccountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serviceaccounttypes.NewFactorAPIKeyFromStorables(storables), nil
|
||||
}
|
||||
|
||||
func (module *module) UpdateFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, factorAPIKey *serviceaccounttypes.FactorAPIKey) error {
|
||||
return module.store.UpdateFactorAPIKey(ctx, serviceAccountID, serviceaccounttypes.NewStorableFactorAPIKey(factorAPIKey))
|
||||
}
|
||||
|
||||
func (module *module) RevokeFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, id valuer.UUID) error {
|
||||
factorAPIKey, err := module.GetFactorAPIKey(ctx, serviceAccountID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.RevokeFactorAPIKey(ctx, serviceAccountID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceAccount, err := module.store.GetByID(ctx, serviceAccountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.emailing.SendHTML(ctx, serviceAccount.Email, "API Key revoked for your SigNoz account", emailtypes.TemplateNameAPIKeyEvent, map[string]any{
|
||||
"Name": serviceAccount.Name,
|
||||
"KeyName": factorAPIKey.Name,
|
||||
"KeyID": factorAPIKey.ID.String(),
|
||||
"KeyCreatedAt": factorAPIKey.CreatedAt.String(),
|
||||
}); err != nil {
|
||||
module.settings.Logger().ErrorContext(ctx, "failed to send email", "error", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) disableServiceAccount(ctx context.Context, orgID valuer.UUID, input *serviceaccounttypes.ServiceAccount) error {
|
||||
err := module.authz.Revoke(ctx, orgID, input.Roles, authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.String(), orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
// revoke all the API keys on disable
|
||||
err := module.store.RevokeAllFactorAPIKeys(ctx, input.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update the status but do not delete the role mappings as we will reuse them on activation.
|
||||
err = module.Update(ctx, orgID, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) activateServiceAccount(ctx context.Context, orgID valuer.UUID, input *serviceaccounttypes.ServiceAccount) error {
|
||||
err := module.authz.Grant(ctx, orgID, input.Roles, authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.String(), orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.Update(ctx, orgID, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
282
pkg/modules/serviceaccount/implserviceaccount/store.go
Normal file
282
pkg/modules/serviceaccount/implserviceaccount/store.go
Normal file
@@ -0,0 +1,282 @@
|
||||
package implserviceaccount
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
sqlstore sqlstore.SQLStore
|
||||
}
|
||||
|
||||
func NewStore(sqlstore sqlstore.SQLStore) serviceaccounttypes.Store {
|
||||
return &store{sqlstore: sqlstore}
|
||||
}
|
||||
|
||||
func (store *store) Create(ctx context.Context, storable *serviceaccounttypes.StorableServiceAccount) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewInsert().
|
||||
Model(storable).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, serviceaccounttypes.ErrCodeServiceAccountAlreadyExists, "service account with id: %s already exists", storable.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*serviceaccounttypes.StorableServiceAccount, error) {
|
||||
storable := new(serviceaccounttypes.StorableServiceAccount)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(storable).
|
||||
Where("id = ?", id).
|
||||
Where("org_id = ?", orgID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, serviceaccounttypes.ErrCodeServiceAccountNotFound, "service account with id: %s doesn't exist in org: %s", id, orgID)
|
||||
}
|
||||
|
||||
return storable, nil
|
||||
}
|
||||
|
||||
func (store *store) GetByID(ctx context.Context, id valuer.UUID) (*serviceaccounttypes.StorableServiceAccount, error) {
|
||||
storable := new(serviceaccounttypes.StorableServiceAccount)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(storable).
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, serviceaccounttypes.ErrCodeServiceAccountNotFound, "service account with id: %s doesn't exist", id)
|
||||
}
|
||||
|
||||
return storable, nil
|
||||
}
|
||||
|
||||
func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*serviceaccounttypes.StorableServiceAccount, error) {
|
||||
storables := make([]*serviceaccounttypes.StorableServiceAccount, 0)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&storables).
|
||||
Where("org_id = ?", orgID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storables, nil
|
||||
}
|
||||
|
||||
func (store *store) Update(ctx context.Context, orgID valuer.UUID, storable *serviceaccounttypes.StorableServiceAccount) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewUpdate().
|
||||
Model(storable).
|
||||
WherePK().
|
||||
Where("org_id = ?", orgID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(serviceaccounttypes.StorableServiceAccount)).
|
||||
Where("id = ?", id).
|
||||
Where("org_id = ?", orgID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) CreateServiceAccountRoles(ctx context.Context, storables []*serviceaccounttypes.StorableServiceAccountRole) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewInsert().
|
||||
Model(&storables).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, serviceaccounttypes.ErrCodeServiceAccountRoleAlreadyExists, "duplicate role assignments for service account")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetServiceAccountRoles(ctx context.Context, id valuer.UUID) ([]*serviceaccounttypes.StorableServiceAccountRole, error) {
|
||||
storables := make([]*serviceaccounttypes.StorableServiceAccountRole, 0)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&storables).
|
||||
Where("service_account_id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
// no need to wrap not found here as this is many to many table
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storables, nil
|
||||
}
|
||||
|
||||
func (store *store) ListServiceAccountRolesByOrgID(ctx context.Context, orgID valuer.UUID) ([]*serviceaccounttypes.StorableServiceAccountRole, error) {
|
||||
storables := make([]*serviceaccounttypes.StorableServiceAccountRole, 0)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&storables).
|
||||
Join("JOIN service_account").
|
||||
JoinOn("service_account.id = service_account_role.service_account_id").
|
||||
Where("service_account.org_id = ?", orgID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storables, nil
|
||||
}
|
||||
|
||||
func (store *store) DeleteServiceAccountRoles(ctx context.Context, id valuer.UUID) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(serviceaccounttypes.StorableServiceAccountRole)).
|
||||
Where("service_account_id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) CreateFactorAPIKey(ctx context.Context, storable *serviceaccounttypes.StorableFactorAPIKey) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewInsert().
|
||||
Model(storable).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, serviceaccounttypes.ErrCodeServiceAccountFactorAPIKeyAlreadyExists, "api key with name: %s already exists for service account: %s", storable.Name, storable.ServiceAccountID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, id valuer.UUID) (*serviceaccounttypes.StorableFactorAPIKey, error) {
|
||||
storable := new(serviceaccounttypes.StorableFactorAPIKey)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(storable).
|
||||
Where("id = ?", id).
|
||||
Where("service_account_id = ?", serviceAccountID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, serviceaccounttypes.ErrCodeServiceAccounFactorAPIKeytNotFound, "api key with id: %s doesn't exist for service account: %s", id, serviceAccountID)
|
||||
}
|
||||
|
||||
return storable, nil
|
||||
}
|
||||
|
||||
func (store *store) ListFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID) ([]*serviceaccounttypes.StorableFactorAPIKey, error) {
|
||||
storables := make([]*serviceaccounttypes.StorableFactorAPIKey, 0)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(&storables).
|
||||
Where("service_account_id = ?", serviceAccountID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storables, nil
|
||||
}
|
||||
|
||||
func (store *store) UpdateFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, storable *serviceaccounttypes.StorableFactorAPIKey) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewUpdate().
|
||||
Model(storable).
|
||||
Where("service_account_id = ?", serviceAccountID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) RevokeFactorAPIKey(ctx context.Context, serviceAccountID valuer.UUID, id valuer.UUID) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(serviceaccounttypes.StorableFactorAPIKey)).
|
||||
Where("service_account_id = ?", serviceAccountID).
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) RevokeAllFactorAPIKeys(ctx context.Context, serviceAccountID valuer.UUID) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(serviceaccounttypes.StorableFactorAPIKey)).
|
||||
Where("service_account_id = ?", serviceAccountID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) RunInTx(ctx context.Context, cb func(context.Context) error) error {
|
||||
return store.sqlstore.RunInTxCtx(ctx, nil, func(ctx context.Context) error {
|
||||
return cb(ctx)
|
||||
})
|
||||
}
|
||||
69
pkg/modules/serviceaccount/serviceaccount.go
Normal file
69
pkg/modules/serviceaccount/serviceaccount.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package serviceaccount
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Module interface {
|
||||
// Creates a new service account for an organization.
|
||||
Create(context.Context, valuer.UUID, *serviceaccounttypes.ServiceAccount) error
|
||||
|
||||
// Gets a service account by id.
|
||||
Get(context.Context, valuer.UUID, valuer.UUID) (*serviceaccounttypes.ServiceAccount, error)
|
||||
|
||||
// Gets a service account by id without fetching roles.
|
||||
GetWithoutRoles(context.Context, valuer.UUID, valuer.UUID) (*serviceaccounttypes.ServiceAccount, error)
|
||||
|
||||
// List all service accounts for an organization.
|
||||
List(context.Context, valuer.UUID) ([]*serviceaccounttypes.ServiceAccount, error)
|
||||
|
||||
// Updates an existing service account
|
||||
Update(context.Context, valuer.UUID, *serviceaccounttypes.ServiceAccount) error
|
||||
|
||||
// Updates an existing service account status
|
||||
UpdateStatus(context.Context, valuer.UUID, *serviceaccounttypes.ServiceAccount) error
|
||||
|
||||
// Deletes an existing service account by id
|
||||
Delete(context.Context, valuer.UUID, valuer.UUID) error
|
||||
|
||||
// Creates a new API key for a service account
|
||||
CreateFactorAPIKey(context.Context, *serviceaccounttypes.FactorAPIKey) error
|
||||
|
||||
// Gets a factor API key by id
|
||||
GetFactorAPIKey(context.Context, valuer.UUID, valuer.UUID) (*serviceaccounttypes.FactorAPIKey, error)
|
||||
|
||||
// Lists all the API keys for a service account
|
||||
ListFactorAPIKey(context.Context, valuer.UUID) ([]*serviceaccounttypes.FactorAPIKey, error)
|
||||
|
||||
// Updates an existing API key for a service account
|
||||
UpdateFactorAPIKey(context.Context, valuer.UUID, *serviceaccounttypes.FactorAPIKey) error
|
||||
|
||||
// Revokes an existing API key for a service account
|
||||
RevokeFactorAPIKey(context.Context, valuer.UUID, valuer.UUID) error
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
Create(http.ResponseWriter, *http.Request)
|
||||
|
||||
Get(http.ResponseWriter, *http.Request)
|
||||
|
||||
List(http.ResponseWriter, *http.Request)
|
||||
|
||||
Update(http.ResponseWriter, *http.Request)
|
||||
|
||||
UpdateStatus(http.ResponseWriter, *http.Request)
|
||||
|
||||
Delete(http.ResponseWriter, *http.Request)
|
||||
|
||||
CreateFactorAPIKey(http.ResponseWriter, *http.Request)
|
||||
|
||||
ListFactorAPIKey(http.ResponseWriter, *http.Request)
|
||||
|
||||
UpdateFactorAPIKey(http.ResponseWriter, *http.Request)
|
||||
|
||||
RevokeFactorAPIKey(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (module *Module) CreateUser(ctx context.Context, input *types.User, opts ..
|
||||
createUserOpts := root.NewCreateUserOptions(opts...)
|
||||
|
||||
// since assign is idempotant multiple calls to assign won't cause issues in case of retries.
|
||||
err := module.authz.Grant(ctx, input.OrgID, roletypes.MustGetSigNozManagedRoleFromExistingRole(input.Role), authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.StringValue(), input.OrgID, nil))
|
||||
err := module.authz.Grant(ctx, input.OrgID, []string{roletypes.MustGetSigNozManagedRoleFromExistingRole(input.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.StringValue(), input.OrgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -236,8 +236,8 @@ func (m *Module) UpdateUser(ctx context.Context, orgID valuer.UUID, id string, u
|
||||
if user.Role != "" && user.Role != existingUser.Role {
|
||||
err = m.authz.ModifyGrant(ctx,
|
||||
orgID,
|
||||
roletypes.MustGetSigNozManagedRoleFromExistingRole(existingUser.Role),
|
||||
roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role),
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(existingUser.Role)},
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -294,7 +294,7 @@ func (module *Module) DeleteUser(ctx context.Context, orgID valuer.UUID, id stri
|
||||
}
|
||||
|
||||
// since revoke is idempotant multiple calls to revoke won't cause issues in case of retries
|
||||
err = module.authz.Revoke(ctx, orgID, roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role), authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil))
|
||||
err = module.authz.Revoke(ctx, orgID, []string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -159,8 +159,8 @@ func (s *service) createOrPromoteRootUser(ctx context.Context, orgID valuer.UUID
|
||||
if oldRole != types.RoleAdmin {
|
||||
if err := s.authz.ModifyGrant(ctx,
|
||||
orgID,
|
||||
roletypes.MustGetSigNozManagedRoleFromExistingRole(oldRole),
|
||||
roletypes.MustGetSigNozManagedRoleFromExistingRole(types.RoleAdmin),
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(oldRole)},
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(types.RoleAdmin)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, existingUser.ID.StringValue(), orgID, nil),
|
||||
); err != nil {
|
||||
return err
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/rawdataexport/implrawdataexport"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview/implsavedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount/implserviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/services"
|
||||
"github.com/SigNoz/signoz/pkg/modules/services/implservices"
|
||||
"github.com/SigNoz/signoz/pkg/modules/spanpercentile"
|
||||
@@ -36,22 +38,23 @@ import (
|
||||
)
|
||||
|
||||
type Handlers struct {
|
||||
SavedView savedview.Handler
|
||||
Apdex apdex.Handler
|
||||
Dashboard dashboard.Handler
|
||||
QuickFilter quickfilter.Handler
|
||||
TraceFunnel tracefunnel.Handler
|
||||
RawDataExport rawdataexport.Handler
|
||||
SpanPercentile spanpercentile.Handler
|
||||
Services services.Handler
|
||||
MetricsExplorer metricsexplorer.Handler
|
||||
Global global.Handler
|
||||
FlaggerHandler flagger.Handler
|
||||
GatewayHandler gateway.Handler
|
||||
Fields fields.Handler
|
||||
AuthzHandler authz.Handler
|
||||
ZeusHandler zeus.Handler
|
||||
QuerierHandler querier.Handler
|
||||
SavedView savedview.Handler
|
||||
Apdex apdex.Handler
|
||||
Dashboard dashboard.Handler
|
||||
QuickFilter quickfilter.Handler
|
||||
TraceFunnel tracefunnel.Handler
|
||||
RawDataExport rawdataexport.Handler
|
||||
SpanPercentile spanpercentile.Handler
|
||||
Services services.Handler
|
||||
MetricsExplorer metricsexplorer.Handler
|
||||
Global global.Handler
|
||||
FlaggerHandler flagger.Handler
|
||||
GatewayHandler gateway.Handler
|
||||
Fields fields.Handler
|
||||
AuthzHandler authz.Handler
|
||||
ZeusHandler zeus.Handler
|
||||
QuerierHandler querier.Handler
|
||||
ServiceAccountHandler serviceaccount.Handler
|
||||
}
|
||||
|
||||
func NewHandlers(
|
||||
@@ -68,21 +71,22 @@ func NewHandlers(
|
||||
zeusService zeus.Zeus,
|
||||
) Handlers {
|
||||
return Handlers{
|
||||
SavedView: implsavedview.NewHandler(modules.SavedView),
|
||||
Apdex: implapdex.NewHandler(modules.Apdex),
|
||||
Dashboard: impldashboard.NewHandler(modules.Dashboard, providerSettings),
|
||||
QuickFilter: implquickfilter.NewHandler(modules.QuickFilter),
|
||||
TraceFunnel: impltracefunnel.NewHandler(modules.TraceFunnel),
|
||||
RawDataExport: implrawdataexport.NewHandler(modules.RawDataExport),
|
||||
Services: implservices.NewHandler(modules.Services),
|
||||
MetricsExplorer: implmetricsexplorer.NewHandler(modules.MetricsExplorer),
|
||||
SpanPercentile: implspanpercentile.NewHandler(modules.SpanPercentile),
|
||||
Global: signozglobal.NewHandler(global),
|
||||
FlaggerHandler: flagger.NewHandler(flaggerService),
|
||||
GatewayHandler: gateway.NewHandler(gatewayService),
|
||||
Fields: implfields.NewHandler(providerSettings, telemetryMetadataStore),
|
||||
AuthzHandler: signozauthzapi.NewHandler(authz),
|
||||
ZeusHandler: zeus.NewHandler(zeusService, licensing),
|
||||
QuerierHandler: querierHandler,
|
||||
SavedView: implsavedview.NewHandler(modules.SavedView),
|
||||
Apdex: implapdex.NewHandler(modules.Apdex),
|
||||
Dashboard: impldashboard.NewHandler(modules.Dashboard, providerSettings),
|
||||
QuickFilter: implquickfilter.NewHandler(modules.QuickFilter),
|
||||
TraceFunnel: impltracefunnel.NewHandler(modules.TraceFunnel),
|
||||
RawDataExport: implrawdataexport.NewHandler(modules.RawDataExport),
|
||||
Services: implservices.NewHandler(modules.Services),
|
||||
MetricsExplorer: implmetricsexplorer.NewHandler(modules.MetricsExplorer),
|
||||
SpanPercentile: implspanpercentile.NewHandler(modules.SpanPercentile),
|
||||
Global: signozglobal.NewHandler(global),
|
||||
FlaggerHandler: flagger.NewHandler(flaggerService),
|
||||
GatewayHandler: gateway.NewHandler(gatewayService),
|
||||
Fields: implfields.NewHandler(providerSettings, telemetryMetadataStore),
|
||||
AuthzHandler: signozauthzapi.NewHandler(authz),
|
||||
ZeusHandler: zeus.NewHandler(zeusService, licensing),
|
||||
QuerierHandler: querierHandler,
|
||||
ServiceAccountHandler: implserviceaccount.NewHandler(modules.ServiceAccount),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/rawdataexport/implrawdataexport"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview/implsavedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount/implserviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/services"
|
||||
"github.com/SigNoz/signoz/pkg/modules/services/implservices"
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
@@ -66,6 +68,7 @@ type Modules struct {
|
||||
SpanPercentile spanpercentile.Module
|
||||
MetricsExplorer metricsexplorer.Module
|
||||
Promote promote.Module
|
||||
ServiceAccount serviceaccount.Module
|
||||
}
|
||||
|
||||
func NewModules(
|
||||
@@ -110,5 +113,6 @@ func NewModules(
|
||||
Services: implservices.NewModule(querier, telemetryStore),
|
||||
MetricsExplorer: implmetricsexplorer.NewModule(telemetryStore, telemetryMetadataStore, cache, ruleStore, dashboard, providerSettings, config.MetricsExplorer),
|
||||
Promote: implpromote.NewModule(telemetryMetadataStore, telemetryStore),
|
||||
ServiceAccount: implserviceaccount.NewModule(implserviceaccount.NewStore(sqlstore), authz, emailing, providerSettings),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/preference"
|
||||
"github.com/SigNoz/signoz/pkg/modules/promote"
|
||||
"github.com/SigNoz/signoz/pkg/modules/serviceaccount"
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
@@ -59,6 +60,7 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta
|
||||
struct{ authz.Handler }{},
|
||||
struct{ zeus.Handler }{},
|
||||
struct{ querier.Handler }{},
|
||||
struct{ serviceaccount.Handler }{},
|
||||
).New(ctx, instrumentation.ToProviderSettings(), apiserver.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -255,6 +255,7 @@ func NewAPIServerProviderFactories(orgGetter organization.Getter, authz authz.Au
|
||||
handlers.AuthzHandler,
|
||||
handlers.ZeusHandler,
|
||||
handlers.QuerierHandler,
|
||||
handlers.ServiceAccountHandler,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ var (
|
||||
var (
|
||||
TemplateNameInvitationEmail = TemplateName{valuer.NewString("invitation")}
|
||||
TemplateNameResetPassword = TemplateName{valuer.NewString("reset_password")}
|
||||
TemplateNameAPIKeyEvent = TemplateName{valuer.NewString("api_key_event")}
|
||||
)
|
||||
|
||||
type TemplateName struct{ valuer.String }
|
||||
@@ -28,6 +29,8 @@ func NewTemplateName(name string) (TemplateName, error) {
|
||||
return TemplateNameInvitationEmail, nil
|
||||
case TemplateNameResetPassword.StringValue():
|
||||
return TemplateNameResetPassword, nil
|
||||
case TemplateNameAPIKeyEvent.StringValue():
|
||||
return TemplateNameAPIKeyEvent, nil
|
||||
default:
|
||||
return TemplateName{}, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid template name: %s", name)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ type Store interface {
|
||||
GetByOrgIDAndName(context.Context, valuer.UUID, string) (*StorableRole, error)
|
||||
List(context.Context, valuer.UUID) ([]*StorableRole, error)
|
||||
ListByOrgIDAndNames(context.Context, valuer.UUID, []string) ([]*StorableRole, error)
|
||||
ListByOrgIDAndIDs(context.Context, valuer.UUID, []valuer.UUID) ([]*StorableRole, error)
|
||||
Update(context.Context, valuer.UUID, *StorableRole) error
|
||||
Delete(context.Context, valuer.UUID, valuer.UUID) error
|
||||
RunInTx(context.Context, func(ctx context.Context) error) error
|
||||
|
||||
147
pkg/types/serviceaccounttypes/factor_api_key.go
Normal file
147
pkg/types/serviceaccounttypes/factor_api_key.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package serviceaccounttypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCodeServiceAccountFactorAPIkeyInvalidInput = errors.MustNewCode("service_account_factor_api_key_invalid_input")
|
||||
ErrCodeServiceAccountFactorAPIKeyAlreadyExists = errors.MustNewCode("service_account_factor_api_key_already_exists")
|
||||
ErrCodeServiceAccounFactorAPIKeytNotFound = errors.MustNewCode("service_account_factor_api_key_not_found")
|
||||
)
|
||||
|
||||
type StorableFactorAPIKey struct {
|
||||
bun.BaseModel `bun:"table:factor_api_key"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `bun:"name"`
|
||||
Key string `bun:"key"`
|
||||
ExpiresAt uint64 `bun:"expires_at"`
|
||||
LastUsed time.Time `bun:"last_used"`
|
||||
ServiceAccountID string `bun:"service_account_id"`
|
||||
}
|
||||
|
||||
type FactorAPIKey struct {
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `json:"name" requrired:"true"`
|
||||
Key string `json:"key" required:"true"`
|
||||
ExpiresAt uint64 `json:"expires_at" required:"true"`
|
||||
LastUsed time.Time `json:"last_used" required:"true"`
|
||||
ServiceAccountID valuer.UUID `json:"service_account_id" required:"true"`
|
||||
}
|
||||
|
||||
type GettableFactorAPIKey struct {
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `json:"name" requrired:"true"`
|
||||
ExpiresAt uint64 `json:"expires_at" required:"true"`
|
||||
LastUsed time.Time `json:"last_used" required:"true"`
|
||||
ServiceAccountID valuer.UUID `json:"service_account_id" required:"true"`
|
||||
}
|
||||
|
||||
type PostableFactorAPIKey struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
ExpiresAt uint64 `json:"expires_at" required:"true"`
|
||||
}
|
||||
|
||||
type UpdatableFactorAPIKey struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
ExpiresAt uint64 `json:"expires_at" required:"true"`
|
||||
}
|
||||
|
||||
func NewFactorAPIKeyFromStorable(storable *StorableFactorAPIKey) *FactorAPIKey {
|
||||
return &FactorAPIKey{
|
||||
Identifiable: storable.Identifiable,
|
||||
TimeAuditable: storable.TimeAuditable,
|
||||
Name: storable.Name,
|
||||
Key: storable.Key,
|
||||
ExpiresAt: storable.ExpiresAt,
|
||||
LastUsed: storable.LastUsed,
|
||||
ServiceAccountID: valuer.MustNewUUID(storable.ServiceAccountID),
|
||||
}
|
||||
}
|
||||
|
||||
func NewFactorAPIKeyFromStorables(storables []*StorableFactorAPIKey) []*FactorAPIKey {
|
||||
factorAPIKeys := make([]*FactorAPIKey, len(storables))
|
||||
|
||||
for idx, storable := range storables {
|
||||
factorAPIKeys[idx] = NewFactorAPIKeyFromStorable(storable)
|
||||
}
|
||||
|
||||
return factorAPIKeys
|
||||
}
|
||||
|
||||
func NewStorableFactorAPIKey(factorAPIKey *FactorAPIKey) *StorableFactorAPIKey {
|
||||
return &StorableFactorAPIKey{
|
||||
Identifiable: factorAPIKey.Identifiable,
|
||||
TimeAuditable: factorAPIKey.TimeAuditable,
|
||||
Name: factorAPIKey.Name,
|
||||
Key: factorAPIKey.Key,
|
||||
ExpiresAt: factorAPIKey.ExpiresAt,
|
||||
LastUsed: factorAPIKey.LastUsed,
|
||||
ServiceAccountID: factorAPIKey.ServiceAccountID.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewGettableFactorAPIKeys(keys []*FactorAPIKey) []*GettableFactorAPIKey {
|
||||
gettables := make([]*GettableFactorAPIKey, len(keys))
|
||||
|
||||
for idx, key := range keys {
|
||||
gettables[idx] = &GettableFactorAPIKey{
|
||||
Identifiable: key.Identifiable,
|
||||
TimeAuditable: key.TimeAuditable,
|
||||
Name: key.Name,
|
||||
ExpiresAt: key.ExpiresAt,
|
||||
LastUsed: key.LastUsed,
|
||||
ServiceAccountID: key.ServiceAccountID,
|
||||
}
|
||||
}
|
||||
|
||||
return gettables
|
||||
}
|
||||
|
||||
func (apiKey *FactorAPIKey) Update(name string, expiresAt uint64) {
|
||||
apiKey.Name = name
|
||||
apiKey.ExpiresAt = expiresAt
|
||||
apiKey.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
func (key *PostableFactorAPIKey) UnmarshalJSON(data []byte) error {
|
||||
type Alias PostableFactorAPIKey
|
||||
|
||||
var temp Alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if temp.Name == "" {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountFactorAPIkeyInvalidInput, "name cannot be empty")
|
||||
}
|
||||
|
||||
*key = PostableFactorAPIKey(temp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (key *UpdatableFactorAPIKey) UnmarshalJSON(data []byte) error {
|
||||
type Alias UpdatableFactorAPIKey
|
||||
|
||||
var temp Alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if temp.Name == "" {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountFactorAPIkeyInvalidInput, "name cannot be empty")
|
||||
}
|
||||
|
||||
*key = UpdatableFactorAPIKey(temp)
|
||||
return nil
|
||||
}
|
||||
253
pkg/types/serviceaccounttypes/service_acccount.go
Normal file
253
pkg/types/serviceaccounttypes/service_acccount.go
Normal file
@@ -0,0 +1,253 @@
|
||||
package serviceaccounttypes
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCodeServiceAccountInvalidInput = errors.MustNewCode("service_account_invalid_input")
|
||||
ErrCodeServiceAccountAlreadyExists = errors.MustNewCode("service_account_already_exists")
|
||||
ErrCodeServiceAccountNotFound = errors.MustNewCode("service_account_not_found")
|
||||
ErrCodeServiceAccountRoleAlreadyExists = errors.MustNewCode("service_account_role_already_exists")
|
||||
)
|
||||
|
||||
var (
|
||||
StatusActive = valuer.NewString("active")
|
||||
StatusDisabled = valuer.NewString("disabled")
|
||||
ValidStatus = []valuer.String{StatusActive, StatusDisabled}
|
||||
)
|
||||
|
||||
type StorableServiceAccount struct {
|
||||
bun.BaseModel `bun:"table:service_account,alias:service_account"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `bun:"name"`
|
||||
Email string `bun:"email"`
|
||||
Status valuer.String `bun:"status"`
|
||||
OrgID string `bun:"org_id"`
|
||||
}
|
||||
|
||||
type ServiceAccount struct {
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
Name string `json:"name" required:"true"`
|
||||
Email valuer.Email `json:"email" required:"true"`
|
||||
Roles []string `json:"roles" required:"true" nullable:"false"`
|
||||
Status valuer.String `json:"status" required:"true"`
|
||||
OrgID valuer.UUID `json:"orgID" required:"true"`
|
||||
}
|
||||
|
||||
type PostableServiceAccount struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Email valuer.Email `json:"email" required:"true"`
|
||||
Roles []string `json:"roles" required:"true" nullable:"false"`
|
||||
}
|
||||
|
||||
type UpdatableServiceAccount struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
Email valuer.Email `json:"email" required:"true"`
|
||||
Roles []string `json:"roles" required:"true" nullable:"false"`
|
||||
}
|
||||
|
||||
type UpdatableServiceAccountStatus struct {
|
||||
Status valuer.String `json:"status" required:"true"`
|
||||
}
|
||||
|
||||
func NewServiceAccount(name string, email valuer.Email, roles []string, status valuer.String, orgID valuer.UUID) *ServiceAccount {
|
||||
return &ServiceAccount{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: valuer.GenerateUUID(),
|
||||
},
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
Name: name,
|
||||
Email: email,
|
||||
Roles: roles,
|
||||
Status: status,
|
||||
OrgID: orgID,
|
||||
}
|
||||
}
|
||||
|
||||
func NewServiceAccountFromStorables(storableServiceAccount *StorableServiceAccount, roles []string) *ServiceAccount {
|
||||
return &ServiceAccount{
|
||||
Identifiable: storableServiceAccount.Identifiable,
|
||||
TimeAuditable: storableServiceAccount.TimeAuditable,
|
||||
Name: storableServiceAccount.Name,
|
||||
Email: valuer.MustNewEmail(storableServiceAccount.Email),
|
||||
Roles: roles,
|
||||
Status: storableServiceAccount.Status,
|
||||
OrgID: valuer.MustNewUUID(storableServiceAccount.OrgID),
|
||||
}
|
||||
}
|
||||
|
||||
func NewServiceAccountsFromRoles(storableServiceAccounts []*StorableServiceAccount, roles []*roletypes.Role, serviceAccountIDToRoleIDsMap map[string][]valuer.UUID) []*ServiceAccount {
|
||||
serviceAccounts := make([]*ServiceAccount, 0, len(storableServiceAccounts))
|
||||
|
||||
roleIDToRole := make(map[string]*roletypes.Role, len(roles))
|
||||
for _, role := range roles {
|
||||
roleIDToRole[role.ID.String()] = role
|
||||
}
|
||||
|
||||
for _, sa := range storableServiceAccounts {
|
||||
roleIDs := serviceAccountIDToRoleIDsMap[sa.ID.String()]
|
||||
|
||||
roleNames := make([]string, len(roleIDs))
|
||||
for idx, rid := range roleIDs {
|
||||
if role, ok := roleIDToRole[rid.String()]; ok {
|
||||
roleNames[idx] = role.Name
|
||||
}
|
||||
}
|
||||
|
||||
account := NewServiceAccountFromStorables(sa, roleNames)
|
||||
serviceAccounts = append(serviceAccounts, account)
|
||||
}
|
||||
|
||||
return serviceAccounts
|
||||
}
|
||||
|
||||
func NewStorableServiceAccount(serviceAccount *ServiceAccount) *StorableServiceAccount {
|
||||
return &StorableServiceAccount{
|
||||
Identifiable: serviceAccount.Identifiable,
|
||||
TimeAuditable: serviceAccount.TimeAuditable,
|
||||
Name: serviceAccount.Name,
|
||||
Email: serviceAccount.Email.String(),
|
||||
Status: serviceAccount.Status,
|
||||
OrgID: serviceAccount.OrgID.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (sa *ServiceAccount) Update(name string, email valuer.Email, roles []string) {
|
||||
sa.Name = name
|
||||
sa.Email = email
|
||||
sa.Roles = roles
|
||||
sa.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
func (sa *ServiceAccount) UpdateStatus(status valuer.String) {
|
||||
sa.Status = status
|
||||
sa.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
func (sa *ServiceAccount) NewFactorAPIKey(name string, expiresAt uint64) (*FactorAPIKey, error) {
|
||||
key := make([]byte, 32)
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.TypeInternal, errors.CodeInternal, "failed to generate token")
|
||||
}
|
||||
// Encode the token in base64.
|
||||
encodedKey := base64.StdEncoding.EncodeToString(key)
|
||||
|
||||
return &FactorAPIKey{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: valuer.GenerateUUID(),
|
||||
},
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
Name: name,
|
||||
Key: encodedKey,
|
||||
ExpiresAt: expiresAt,
|
||||
LastUsed: time.Now(),
|
||||
ServiceAccountID: sa.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (sa *ServiceAccount) PatchRoles(input *ServiceAccount) ([]string, []string) {
|
||||
currentRolesSet := make(map[string]struct{}, len(sa.Roles))
|
||||
inputRolesSet := make(map[string]struct{}, len(input.Roles))
|
||||
|
||||
for _, role := range sa.Roles {
|
||||
currentRolesSet[role] = struct{}{}
|
||||
}
|
||||
for _, role := range input.Roles {
|
||||
inputRolesSet[role] = struct{}{}
|
||||
}
|
||||
|
||||
// additions: roles present in input but not in current
|
||||
additions := []string{}
|
||||
for _, role := range input.Roles {
|
||||
if _, exists := currentRolesSet[role]; !exists {
|
||||
additions = append(additions, role)
|
||||
}
|
||||
}
|
||||
|
||||
// deletions: roles present in current but not in input
|
||||
deletions := []string{}
|
||||
for _, role := range sa.Roles {
|
||||
if _, exists := inputRolesSet[role]; !exists {
|
||||
deletions = append(deletions, role)
|
||||
}
|
||||
}
|
||||
|
||||
return additions, deletions
|
||||
}
|
||||
|
||||
func (sa *PostableServiceAccount) UnmarshalJSON(data []byte) error {
|
||||
type Alias PostableServiceAccount
|
||||
|
||||
var temp Alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if temp.Name == "" {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountInvalidInput, "name cannot be empty")
|
||||
}
|
||||
|
||||
if len(temp.Roles) == 0 {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountInvalidInput, "roles cannot be empty")
|
||||
}
|
||||
|
||||
*sa = PostableServiceAccount(temp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sa *UpdatableServiceAccount) UnmarshalJSON(data []byte) error {
|
||||
type Alias UpdatableServiceAccount
|
||||
|
||||
var temp Alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if temp.Name == "" {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountInvalidInput, "name cannot be empty")
|
||||
}
|
||||
|
||||
if len(temp.Roles) == 0 {
|
||||
return errors.New(errors.TypeInvalidInput, ErrCodeServiceAccountInvalidInput, "roles cannot be empty")
|
||||
}
|
||||
|
||||
*sa = UpdatableServiceAccount(temp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sa *UpdatableServiceAccountStatus) UnmarshalJSON(data []byte) error {
|
||||
type Alias UpdatableServiceAccountStatus
|
||||
|
||||
var temp Alias
|
||||
if err := json.Unmarshal(data, &temp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !slices.Contains(ValidStatus, temp.Status) {
|
||||
return errors.Newf(errors.TypeInvalidInput, ErrCodeServiceAccountInvalidInput, "invalid status: %s, allowed status are: %v", temp.Status, ValidStatus)
|
||||
}
|
||||
|
||||
*sa = UpdatableServiceAccountStatus(temp)
|
||||
return nil
|
||||
}
|
||||
81
pkg/types/serviceaccounttypes/service_account_role.go
Normal file
81
pkg/types/serviceaccounttypes/service_account_role.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package serviceaccounttypes
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type StorableServiceAccountRole struct {
|
||||
bun.BaseModel `bun:"table:service_account_role,alias:service_account_role"`
|
||||
|
||||
types.Identifiable
|
||||
types.TimeAuditable
|
||||
ServiceAccountID string `bun:"service_account_id"`
|
||||
RoleID string `bun:"role_id"`
|
||||
}
|
||||
|
||||
func NewStorableServiceAccountRoles(serviceAccountID valuer.UUID, roles []*roletypes.Role) []*StorableServiceAccountRole {
|
||||
storableServiceAccountRoles := make([]*StorableServiceAccountRole, len(roles))
|
||||
for idx, role := range roles {
|
||||
storableServiceAccountRoles[idx] = &StorableServiceAccountRole{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: valuer.GenerateUUID(),
|
||||
},
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
ServiceAccountID: serviceAccountID.String(),
|
||||
RoleID: role.ID.String(),
|
||||
}
|
||||
}
|
||||
|
||||
return storableServiceAccountRoles
|
||||
}
|
||||
|
||||
func NewRolesFromStorableServiceAccountRoles(storable []*StorableServiceAccountRole, roles []*roletypes.Role) ([]string, error) {
|
||||
roleIDToName := make(map[string]string, len(roles))
|
||||
for _, role := range roles {
|
||||
roleIDToName[role.ID.String()] = role.Name
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(storable))
|
||||
for _, sar := range storable {
|
||||
roleName, ok := roleIDToName[sar.RoleID]
|
||||
if !ok {
|
||||
return nil, errors.Newf(errors.TypeInternal, errors.CodeInternal, "role id %s not found in provided roles", sar.RoleID)
|
||||
}
|
||||
names = append(names, roleName)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func GetUniqueRolesAndServiceAccountMapping(storableServiceAccountRoles []*StorableServiceAccountRole) (map[string][]valuer.UUID, []valuer.UUID) {
|
||||
serviceAccountIDRoles := make(map[string][]valuer.UUID)
|
||||
uniqueRoleIDSet := make(map[string]struct{})
|
||||
|
||||
for _, sar := range storableServiceAccountRoles {
|
||||
saID := sar.ServiceAccountID
|
||||
roleID := sar.RoleID
|
||||
if _, ok := serviceAccountIDRoles[saID]; !ok {
|
||||
serviceAccountIDRoles[saID] = make([]valuer.UUID, 0)
|
||||
}
|
||||
|
||||
roleUUID := valuer.MustNewUUID(roleID)
|
||||
serviceAccountIDRoles[saID] = append(serviceAccountIDRoles[saID], roleUUID)
|
||||
uniqueRoleIDSet[roleID] = struct{}{}
|
||||
}
|
||||
|
||||
roleIDs := make([]valuer.UUID, 0, len(uniqueRoleIDSet))
|
||||
for rid := range uniqueRoleIDSet {
|
||||
roleIDs = append(roleIDs, valuer.MustNewUUID(rid))
|
||||
}
|
||||
|
||||
return serviceAccountIDRoles, roleIDs
|
||||
}
|
||||
33
pkg/types/serviceaccounttypes/store.go
Normal file
33
pkg/types/serviceaccounttypes/store.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package serviceaccounttypes
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
// Service Account
|
||||
Create(context.Context, *StorableServiceAccount) error
|
||||
Get(context.Context, valuer.UUID, valuer.UUID) (*StorableServiceAccount, error)
|
||||
GetByID(context.Context, valuer.UUID) (*StorableServiceAccount, error)
|
||||
List(context.Context, valuer.UUID) ([]*StorableServiceAccount, error)
|
||||
Update(context.Context, valuer.UUID, *StorableServiceAccount) error
|
||||
Delete(context.Context, valuer.UUID, valuer.UUID) error
|
||||
|
||||
// Service Account Role
|
||||
CreateServiceAccountRoles(context.Context, []*StorableServiceAccountRole) error
|
||||
GetServiceAccountRoles(context.Context, valuer.UUID) ([]*StorableServiceAccountRole, error)
|
||||
ListServiceAccountRolesByOrgID(context.Context, valuer.UUID) ([]*StorableServiceAccountRole, error)
|
||||
DeleteServiceAccountRoles(context.Context, valuer.UUID) error
|
||||
|
||||
// Service Account Factor API Key
|
||||
CreateFactorAPIKey(context.Context, *StorableFactorAPIKey) error
|
||||
GetFactorAPIKey(context.Context, valuer.UUID, valuer.UUID) (*StorableFactorAPIKey, error)
|
||||
ListFactorAPIKey(context.Context, valuer.UUID) ([]*StorableFactorAPIKey, error)
|
||||
UpdateFactorAPIKey(context.Context, valuer.UUID, *StorableFactorAPIKey) error
|
||||
RevokeFactorAPIKey(context.Context, valuer.UUID, valuer.UUID) error
|
||||
RevokeAllFactorAPIKeys(context.Context, valuer.UUID) error
|
||||
|
||||
RunInTx(context.Context, func(context.Context) error) error
|
||||
}
|
||||
88
templates/email/api_key_event.gotmpl
Normal file
88
templates/email/api_key_event.gotmpl
Normal file
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{.subject}}</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;line-height:1.6;color:#333;background:#fff">
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background:#fff">
|
||||
<tr>
|
||||
<td align="center" style="padding:0">
|
||||
<table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="max-width:600px;width:100%">
|
||||
{{ if .format.Header.Enabled }}
|
||||
<tr>
|
||||
<td align="center" style="padding:16px 20px 16px">
|
||||
<img src="{{.format.Header.LogoURL}}" alt="SigNoz" width="160" height="40" style="display:block;border:0;outline:none;max-width:100%;height:auto">
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr>
|
||||
<td style="padding:16px 20px 16px">
|
||||
<p style="margin:0 0 16px;font-size:16px;color:#333">
|
||||
Hi there,
|
||||
</p>
|
||||
<p style="margin:0 0 16px;font-size:16px;color:#333;line-height:1.6">
|
||||
An API key was {{.Event}} for your service account <strong>{{.Name}}</strong>.
|
||||
</p>
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="margin:0 0 16px">
|
||||
<tr>
|
||||
<td style="padding:20px;background:#f5f5f5;border-radius:6px;border-left:4px solid #4E74F8">
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td style="padding:0 0 8px">
|
||||
<p style="margin:0;font-size:15px;color:#333;line-height:1.6">
|
||||
<strong>Key ID:</strong> {{.KeyID}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 0 8px">
|
||||
<p style="margin:0;font-size:15px;color:#333;line-height:1.6">
|
||||
<strong>Key Name:</strong> {{.KeyName}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 0 8px">
|
||||
<p style="margin:0;font-size:15px;color:#333;line-height:1.6">
|
||||
<strong>Created At:</strong> {{.KeyCreatedAt}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ if .format.Help.Enabled }}
|
||||
<p style="margin:0 0 16px;font-size:16px;color:#333;line-height:1.6">
|
||||
Need help? Chat with our team in the SigNoz application or email us at <a href="mailto:{{.format.Help.Email}}" style="color:#4E74F8;text-decoration:none">{{.format.Help.Email}}</a>.
|
||||
</p>
|
||||
{{ end }}
|
||||
<p style="margin:0;font-size:16px;color:#333;line-height:1.6">
|
||||
Thanks,<br><strong>The SigNoz Team</strong>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
{{ if .format.Footer.Enabled }}
|
||||
<tr>
|
||||
<td align="center" style="padding:8px 16px 8px">
|
||||
<p style="margin:0 0 8px;font-size:12px;color:#999;line-height:1.5">
|
||||
<a href="https://signoz.io/terms-of-service/" style="color:#4E74F8;text-decoration:none">Terms of Service</a> - <a href="https://signoz.io/privacy/" style="color:#4E74F8;text-decoration:none">Privacy Policy</a>
|
||||
</p>
|
||||
<p style="margin:0;font-size:12px;color:#999;line-height:1.5">
|
||||
© 2026 SigNoz Inc.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user