mirror of
https://github.com/SigNoz/signoz.git
synced 2026-03-17 10:22:11 +00:00
Compare commits
12 Commits
refactor/c
...
feat/fix-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f40c178317 | ||
|
|
7a6cfa356e | ||
|
|
3b3190ff38 | ||
|
|
fdf961311f | ||
|
|
debe1608d0 | ||
|
|
e7dc4dfb2a | ||
|
|
a9f13a5bfd | ||
|
|
2cfd894d4c | ||
|
|
6e772fb58d | ||
|
|
4ce220ba92 | ||
|
|
0211ddf0cb | ||
|
|
e5eb62e45b |
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/app"
|
||||
"github.com/SigNoz/signoz/pkg/queryparser"
|
||||
@@ -73,8 +74,8 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
},
|
||||
signoz.NewSQLStoreProviderFactories(),
|
||||
signoz.NewTelemetryStoreProviderFactories(),
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
return signoz.NewAuthNs(ctx, providerSettings, store, licensing)
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing, userGetter user.Getter) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
return signoz.NewAuthNs(ctx, providerSettings, store, licensing, userGetter)
|
||||
},
|
||||
func(ctx context.Context, sqlstore sqlstore.SQLStore, _ licensing.Licensing, _ dashboard.Module) factory.ProviderFactory[authz.AuthZ, authz.Config] {
|
||||
return openfgaauthz.NewProviderFactory(sqlstore, openfgaschema.NewSchema().Get(ctx))
|
||||
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
"github.com/SigNoz/signoz/ee/authn/callbackauthn/oidccallbackauthn"
|
||||
"github.com/SigNoz/signoz/ee/authn/callbackauthn/samlcallbackauthn"
|
||||
"github.com/SigNoz/signoz/ee/authz/openfgaauthz"
|
||||
eequerier "github.com/SigNoz/signoz/ee/querier"
|
||||
"github.com/SigNoz/signoz/ee/authz/openfgaschema"
|
||||
"github.com/SigNoz/signoz/ee/gateway/httpgateway"
|
||||
enterpriselicensing "github.com/SigNoz/signoz/ee/licensing"
|
||||
"github.com/SigNoz/signoz/ee/licensing/httplicensing"
|
||||
"github.com/SigNoz/signoz/ee/modules/dashboard/impldashboard"
|
||||
eequerier "github.com/SigNoz/signoz/ee/querier"
|
||||
enterpriseapp "github.com/SigNoz/signoz/ee/query-service/app"
|
||||
"github.com/SigNoz/signoz/ee/sqlschema/postgressqlschema"
|
||||
"github.com/SigNoz/signoz/ee/sqlstore/postgressqlstore"
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
pkgimpldashboard "github.com/SigNoz/signoz/pkg/modules/dashboard/impldashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
"github.com/SigNoz/signoz/pkg/queryparser"
|
||||
"github.com/SigNoz/signoz/pkg/signoz"
|
||||
@@ -95,7 +96,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
},
|
||||
sqlstoreFactories,
|
||||
signoz.NewTelemetryStoreProviderFactories(),
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing, userGetter user.Getter) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
samlCallbackAuthN, err := samlcallbackauthn.New(ctx, store, licensing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -106,7 +107,7 @@ func runServer(ctx context.Context, config signoz.Config, logger *slog.Logger) e
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authNs, err := signoz.NewAuthNs(ctx, providerSettings, store, licensing)
|
||||
authNs, err := signoz.NewAuthNs(ctx, providerSettings, store, licensing, userGetter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -220,6 +220,13 @@ components:
|
||||
- additions
|
||||
- deletions
|
||||
type: object
|
||||
AuthtypesPatchableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
required:
|
||||
- description
|
||||
type: object
|
||||
AuthtypesPostableAuthDomain:
|
||||
properties:
|
||||
config:
|
||||
@@ -236,6 +243,15 @@ components:
|
||||
password:
|
||||
type: string
|
||||
type: object
|
||||
AuthtypesPostableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
AuthtypesPostableRotateToken:
|
||||
properties:
|
||||
refreshToken:
|
||||
@@ -251,6 +267,31 @@ components:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
AuthtypesRole:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
orgId:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- description
|
||||
- type
|
||||
- orgId
|
||||
type: object
|
||||
AuthtypesRoleMapping:
|
||||
properties:
|
||||
defaultRole:
|
||||
@@ -1722,47 +1763,6 @@ components:
|
||||
- status
|
||||
- error
|
||||
type: object
|
||||
RoletypesPatchableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
required:
|
||||
- description
|
||||
type: object
|
||||
RoletypesPostableRole:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
RoletypesRole:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
orgId:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- description
|
||||
- type
|
||||
- orgId
|
||||
type: object
|
||||
ServiceaccounttypesFactorAPIKey:
|
||||
properties:
|
||||
createdAt:
|
||||
@@ -1984,52 +1984,6 @@ components:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
TypesChangePasswordRequest:
|
||||
properties:
|
||||
newPassword:
|
||||
type: string
|
||||
oldPassword:
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
type: object
|
||||
TypesGettableAPIKey:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
createdBy:
|
||||
type: string
|
||||
createdByUser:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
expiresAt:
|
||||
format: int64
|
||||
type: integer
|
||||
id:
|
||||
type: string
|
||||
lastUsed:
|
||||
format: int64
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
revoked:
|
||||
type: boolean
|
||||
role:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
updatedBy:
|
||||
type: string
|
||||
updatedByUser:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
userId:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesGettableGlobalConfig:
|
||||
properties:
|
||||
external_url:
|
||||
@@ -2044,31 +1998,6 @@ components:
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesInvite:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
inviteLink:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
orgId:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesOrganization:
|
||||
properties:
|
||||
alias:
|
||||
@@ -2091,7 +2020,78 @@ components:
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesPostableAPIKey:
|
||||
UsertypesChangePasswordRequest:
|
||||
properties:
|
||||
newPassword:
|
||||
type: string
|
||||
oldPassword:
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
type: object
|
||||
UsertypesGettableAPIKey:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
createdBy:
|
||||
type: string
|
||||
createdByUser:
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
expiresAt:
|
||||
format: int64
|
||||
type: integer
|
||||
id:
|
||||
type: string
|
||||
lastUsed:
|
||||
format: int64
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
revoked:
|
||||
type: boolean
|
||||
role:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
updatedBy:
|
||||
type: string
|
||||
updatedByUser:
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
userId:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
UsertypesInvite:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
inviteLink:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
orgId:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
UsertypesPostableAPIKey:
|
||||
properties:
|
||||
expiresInDays:
|
||||
format: int64
|
||||
@@ -2101,7 +2101,7 @@ components:
|
||||
role:
|
||||
type: string
|
||||
type: object
|
||||
TypesPostableAcceptInvite:
|
||||
UsertypesPostableAcceptInvite:
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
@@ -2112,16 +2112,16 @@ components:
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
TypesPostableBulkInviteRequest:
|
||||
UsertypesPostableBulkInviteRequest:
|
||||
properties:
|
||||
invites:
|
||||
items:
|
||||
$ref: '#/components/schemas/TypesPostableInvite'
|
||||
$ref: '#/components/schemas/UsertypesPostableInvite'
|
||||
type: array
|
||||
required:
|
||||
- invites
|
||||
type: object
|
||||
TypesPostableForgotPassword:
|
||||
UsertypesPostableForgotPassword:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
@@ -2133,7 +2133,7 @@ components:
|
||||
- orgId
|
||||
- email
|
||||
type: object
|
||||
TypesPostableInvite:
|
||||
UsertypesPostableInvite:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
@@ -2144,14 +2144,14 @@ components:
|
||||
role:
|
||||
type: string
|
||||
type: object
|
||||
TypesPostableResetPassword:
|
||||
UsertypesPostableResetPassword:
|
||||
properties:
|
||||
password:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
TypesResetPasswordToken:
|
||||
UsertypesResetPasswordToken:
|
||||
properties:
|
||||
expiresAt:
|
||||
format: date-time
|
||||
@@ -2165,7 +2165,7 @@ components:
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesStorableAPIKey:
|
||||
UsertypesStorableAPIKey:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
@@ -2192,7 +2192,7 @@ components:
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
TypesUser:
|
||||
UsertypesUser:
|
||||
properties:
|
||||
createdAt:
|
||||
format: date-time
|
||||
@@ -2392,7 +2392,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesChangePasswordRequest'
|
||||
$ref: '#/components/schemas/UsertypesChangePasswordRequest'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
@@ -3197,7 +3197,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesResetPasswordToken'
|
||||
$ref: '#/components/schemas/UsertypesResetPasswordToken'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3302,7 +3302,7 @@ paths:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/TypesInvite'
|
||||
$ref: '#/components/schemas/UsertypesInvite'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
@@ -3345,7 +3345,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableInvite'
|
||||
$ref: '#/components/schemas/UsertypesPostableInvite'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -3353,7 +3353,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesInvite'
|
||||
$ref: '#/components/schemas/UsertypesInvite'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3469,7 +3469,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesInvite'
|
||||
$ref: '#/components/schemas/UsertypesInvite'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3507,7 +3507,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableAcceptInvite'
|
||||
$ref: '#/components/schemas/UsertypesPostableAcceptInvite'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -3515,7 +3515,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -3553,7 +3553,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableBulkInviteRequest'
|
||||
$ref: '#/components/schemas/UsertypesPostableBulkInviteRequest'
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
@@ -3878,7 +3878,7 @@ paths:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/TypesGettableAPIKey'
|
||||
$ref: '#/components/schemas/UsertypesGettableAPIKey'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
@@ -3921,7 +3921,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableAPIKey'
|
||||
$ref: '#/components/schemas/UsertypesPostableAPIKey'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -3929,7 +3929,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesGettableAPIKey'
|
||||
$ref: '#/components/schemas/UsertypesGettableAPIKey'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -4035,7 +4035,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesStorableAPIKey'
|
||||
$ref: '#/components/schemas/UsertypesStorableAPIKey'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
@@ -4196,7 +4196,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableResetPassword'
|
||||
$ref: '#/components/schemas/UsertypesPostableResetPassword'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
@@ -4234,7 +4234,7 @@ paths:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/RoletypesRole'
|
||||
$ref: '#/components/schemas/AuthtypesRole'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
@@ -4277,7 +4277,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RoletypesPostableRole'
|
||||
$ref: '#/components/schemas/AuthtypesPostableRole'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -4422,7 +4422,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/RoletypesRole'
|
||||
$ref: '#/components/schemas/AuthtypesRole'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -4470,7 +4470,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RoletypesPatchableRole'
|
||||
$ref: '#/components/schemas/AuthtypesPatchableRole'
|
||||
responses:
|
||||
"204":
|
||||
content:
|
||||
@@ -5271,7 +5271,7 @@ paths:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
@@ -5369,7 +5369,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -5423,7 +5423,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
@@ -5431,7 +5431,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -5489,7 +5489,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TypesUser'
|
||||
$ref: '#/components/schemas/UsertypesUser'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -5692,7 +5692,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TypesPostableForgotPassword'
|
||||
$ref: '#/components/schemas/UsertypesPostableForgotPassword'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
openfgapkgtransformer "github.com/openfga/language/pkg/go/transformer"
|
||||
@@ -23,7 +22,7 @@ type provider struct {
|
||||
pkgAuthzService authz.AuthZ
|
||||
openfgaServer *openfgaserver.Server
|
||||
licensing licensing.Licensing
|
||||
store roletypes.Store
|
||||
store authtypes.RoleStore
|
||||
registry []authz.RegisterTypeable
|
||||
}
|
||||
|
||||
@@ -82,23 +81,23 @@ func (provider *provider) Write(ctx context.Context, additions []*openfgav1.Tupl
|
||||
return provider.openfgaServer.Write(ctx, additions, deletions)
|
||||
}
|
||||
|
||||
func (provider *provider) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*roletypes.Role, error) {
|
||||
func (provider *provider) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*authtypes.Role, error) {
|
||||
return provider.pkgAuthzService.Get(ctx, orgID, id)
|
||||
}
|
||||
|
||||
func (provider *provider) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*roletypes.Role, error) {
|
||||
func (provider *provider) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*authtypes.Role, error) {
|
||||
return provider.pkgAuthzService.GetByOrgIDAndName(ctx, orgID, name)
|
||||
}
|
||||
|
||||
func (provider *provider) List(ctx context.Context, orgID valuer.UUID) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) List(ctx context.Context, orgID valuer.UUID) ([]*authtypes.Role, error) {
|
||||
return provider.pkgAuthzService.List(ctx, orgID)
|
||||
}
|
||||
|
||||
func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*authtypes.Role, error) {
|
||||
return provider.pkgAuthzService.ListByOrgIDAndNames(ctx, orgID, names)
|
||||
}
|
||||
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*authtypes.Role, error) {
|
||||
return provider.pkgAuthzService.ListByOrgIDAndIDs(ctx, orgID, ids)
|
||||
}
|
||||
|
||||
@@ -114,7 +113,7 @@ func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, names [
|
||||
return provider.pkgAuthzService.Revoke(ctx, orgID, names, subject)
|
||||
}
|
||||
|
||||
func (provider *provider) CreateManagedRoles(ctx context.Context, orgID valuer.UUID, managedRoles []*roletypes.Role) error {
|
||||
func (provider *provider) CreateManagedRoles(ctx context.Context, orgID valuer.UUID, managedRoles []*authtypes.Role) error {
|
||||
return provider.pkgAuthzService.CreateManagedRoles(ctx, orgID, managedRoles)
|
||||
}
|
||||
|
||||
@@ -136,16 +135,16 @@ func (provider *provider) CreateManagedUserRoleTransactions(ctx context.Context,
|
||||
return provider.Write(ctx, tuples, nil)
|
||||
}
|
||||
|
||||
func (provider *provider) Create(ctx context.Context, orgID valuer.UUID, role *roletypes.Role) error {
|
||||
func (provider *provider) Create(ctx context.Context, orgID valuer.UUID, role *authtypes.Role) error {
|
||||
_, err := provider.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
return provider.store.Create(ctx, roletypes.NewStorableRoleFromRole(role))
|
||||
return provider.store.Create(ctx, authtypes.NewStorableRoleFromRole(role))
|
||||
}
|
||||
|
||||
func (provider *provider) GetOrCreate(ctx context.Context, orgID valuer.UUID, role *roletypes.Role) (*roletypes.Role, error) {
|
||||
func (provider *provider) GetOrCreate(ctx context.Context, orgID valuer.UUID, role *authtypes.Role) (*authtypes.Role, error) {
|
||||
_, err := provider.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
@@ -159,10 +158,10 @@ func (provider *provider) GetOrCreate(ctx context.Context, orgID valuer.UUID, ro
|
||||
}
|
||||
|
||||
if existingRole != nil {
|
||||
return roletypes.NewRoleFromStorableRole(existingRole), nil
|
||||
return authtypes.NewRoleFromStorableRole(existingRole), nil
|
||||
}
|
||||
|
||||
err = provider.store.Create(ctx, roletypes.NewStorableRoleFromRole(role))
|
||||
err = provider.store.Create(ctx, authtypes.NewStorableRoleFromRole(role))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -217,13 +216,13 @@ func (provider *provider) GetObjects(ctx context.Context, orgID valuer.UUID, id
|
||||
return objects, nil
|
||||
}
|
||||
|
||||
func (provider *provider) Patch(ctx context.Context, orgID valuer.UUID, role *roletypes.Role) error {
|
||||
func (provider *provider) Patch(ctx context.Context, orgID valuer.UUID, role *authtypes.Role) error {
|
||||
_, err := provider.licensing.GetActive(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
return provider.store.Update(ctx, orgID, roletypes.NewStorableRoleFromRole(role))
|
||||
return provider.store.Update(ctx, orgID, authtypes.NewStorableRoleFromRole(role))
|
||||
}
|
||||
|
||||
func (provider *provider) PatchObjects(ctx context.Context, orgID valuer.UUID, name string, relation authtypes.Relation, additions, deletions []*authtypes.Object) error {
|
||||
@@ -232,12 +231,12 @@ func (provider *provider) PatchObjects(ctx context.Context, orgID valuer.UUID, n
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
additionTuples, err := roletypes.GetAdditionTuples(name, orgID, relation, additions)
|
||||
additionTuples, err := authtypes.GetAdditionTuples(name, orgID, relation, additions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deletionTuples, err := roletypes.GetDeletionTuples(name, orgID, relation, deletions)
|
||||
deletionTuples, err := authtypes.GetDeletionTuples(name, orgID, relation, deletions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -261,7 +260,7 @@ func (provider *provider) Delete(ctx context.Context, orgID valuer.UUID, id valu
|
||||
return err
|
||||
}
|
||||
|
||||
role := roletypes.NewRoleFromStorableRole(storableRole)
|
||||
role := authtypes.NewRoleFromStorableRole(storableRole)
|
||||
err = role.ErrIfManaged()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -271,7 +270,7 @@ func (provider *provider) Delete(ctx context.Context, orgID valuer.UUID, id valu
|
||||
}
|
||||
|
||||
func (provider *provider) MustGetTypeables() []authtypes.Typeable {
|
||||
return []authtypes.Typeable{authtypes.TypeableRole, roletypes.TypeableResourcesRoles}
|
||||
return []authtypes.Typeable{authtypes.TypeableRole, authtypes.TypeableResourcesRoles}
|
||||
}
|
||||
|
||||
func (provider *provider) getManagedRoleGrantTuples(orgID valuer.UUID, userID valuer.UUID) ([]*openfgav1.TupleKey, error) {
|
||||
@@ -283,7 +282,7 @@ func (provider *provider) getManagedRoleGrantTuples(orgID valuer.UUID, userID va
|
||||
adminSubject,
|
||||
authtypes.RelationAssignee,
|
||||
[]authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozAdminRoleName),
|
||||
},
|
||||
orgID,
|
||||
)
|
||||
@@ -298,7 +297,7 @@ func (provider *provider) getManagedRoleGrantTuples(orgID valuer.UUID, userID va
|
||||
anonymousSubject,
|
||||
authtypes.RelationAssignee,
|
||||
[]authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozAnonymousRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozAnonymousRoleName),
|
||||
},
|
||||
orgID,
|
||||
)
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -214,7 +213,7 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return module.pkgDashboardModule.Update(ctx, orgID, id, updatedBy, data, diff)
|
||||
}
|
||||
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role types.Role, lock bool) error {
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role authtypes.LegacyRole, lock bool) error {
|
||||
return module.pkgDashboardModule.LockUnlock(ctx, orgID, id, updatedBy, role, lock)
|
||||
}
|
||||
|
||||
@@ -224,7 +223,7 @@ func (module *module) MustGetTypeables() []authtypes.Typeable {
|
||||
|
||||
func (module *module) MustGetManagedRoleTransactions() map[string][]*authtypes.Transaction {
|
||||
return map[string][]*authtypes.Transaction{
|
||||
roletypes.SigNozAnonymousRoleName: {
|
||||
authtypes.SigNozAnonymousRoleName: {
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Relation: authtypes.RelationRead,
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
"log/slog"
|
||||
@@ -142,10 +142,10 @@ func (ah *APIHandler) getOrCreateCloudIntegrationPAT(ctx context.Context, orgId
|
||||
"cloud_provider", cloudProvider,
|
||||
)
|
||||
|
||||
newPAT, err := types.NewStorableAPIKey(
|
||||
newPAT, err := usertypes.NewStorableAPIKey(
|
||||
integrationPATName,
|
||||
integrationUser.ID,
|
||||
types.RoleViewer,
|
||||
authtypes.RoleViewer,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -165,16 +165,16 @@ func (ah *APIHandler) getOrCreateCloudIntegrationPAT(ctx context.Context, orgId
|
||||
|
||||
func (ah *APIHandler) getOrCreateCloudIntegrationUser(
|
||||
ctx context.Context, orgId string, cloudProvider string,
|
||||
) (*types.User, *basemodel.ApiError) {
|
||||
) (*usertypes.User, *basemodel.ApiError) {
|
||||
cloudIntegrationUserName := fmt.Sprintf("%s-integration", cloudProvider)
|
||||
email := valuer.MustNewEmail(fmt.Sprintf("%s@signoz.io", cloudIntegrationUserName))
|
||||
|
||||
cloudIntegrationUser, err := types.NewUser(cloudIntegrationUserName, email, types.RoleViewer, valuer.MustNewUUID(orgId), types.UserStatusActive)
|
||||
cloudIntegrationUser, err := usertypes.NewUser(cloudIntegrationUserName, email, authtypes.RoleViewer, valuer.MustNewUUID(orgId), usertypes.UserStatusActive)
|
||||
if err != nil {
|
||||
return nil, basemodel.InternalError(fmt.Errorf("couldn't create cloud integration user: %w", err))
|
||||
}
|
||||
|
||||
password := types.MustGenerateFactorPassword(cloudIntegrationUser.ID.StringValue())
|
||||
password := usertypes.MustGenerateFactorPassword(cloudIntegrationUser.ID.StringValue())
|
||||
|
||||
cloudIntegrationUser, err = ah.Signoz.Modules.User.GetOrCreateUser(ctx, cloudIntegrationUser, user.WithFactorPassword(password))
|
||||
if err != nil {
|
||||
|
||||
@@ -217,8 +217,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
||||
}),
|
||||
otelmux.WithPublicEndpoint(),
|
||||
))
|
||||
r.Use(middleware.NewAuthN([]string{"Authorization", "Sec-WebSocket-Protocol"}, s.signoz.Sharder, s.signoz.Tokenizer, s.signoz.Instrumentation.Logger()).Wrap)
|
||||
r.Use(middleware.NewAPIKey(s.signoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.signoz.Instrumentation.Logger(), s.signoz.Sharder).Wrap)
|
||||
r.Use(middleware.NewIdentN(s.signoz.IdentNResolver, s.signoz.Sharder, s.signoz.Instrumentation.Logger()).Wrap)
|
||||
r.Use(middleware.NewTimeout(s.signoz.Instrumentation.Logger(),
|
||||
s.config.APIServer.Timeout.ExcludedRoutes,
|
||||
s.config.APIServer.Timeout.Default,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlschema"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
@@ -32,9 +33,9 @@ func New(ctx context.Context, providerSettings factory.ProviderSettings, config
|
||||
fmter: fmter,
|
||||
settings: settings,
|
||||
operator: sqlschema.NewOperator(fmter, sqlschema.OperatorSupport{
|
||||
DropConstraint: true,
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
SAlterTableAddAndDropColumnIfNotExistsAndExists: true,
|
||||
SAlterTableAlterColumnSetAndDrop: true,
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
@@ -72,8 +73,9 @@ WHERE
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(columns) == 0 {
|
||||
return nil, nil, sql.ErrNoRows
|
||||
return nil, nil, provider.sqlstore.WrapNotFoundErrf(sql.ErrNoRows, errors.CodeNotFound, "table (%s) not found", tableName)
|
||||
}
|
||||
|
||||
sqlschemaColumns := make([]*sqlschema.Column, 0)
|
||||
@@ -220,7 +222,8 @@ SELECT
|
||||
ci.relname AS index_name,
|
||||
i.indisunique AS unique,
|
||||
i.indisprimary AS primary,
|
||||
a.attname AS column_name
|
||||
a.attname AS column_name,
|
||||
array_position(i.indkey, a.attnum) AS column_position
|
||||
FROM
|
||||
pg_index i
|
||||
LEFT JOIN pg_class ct ON ct.oid = i.indrelid
|
||||
@@ -231,9 +234,10 @@ WHERE
|
||||
a.attnum = ANY(i.indkey)
|
||||
AND con.oid IS NULL
|
||||
AND ct.relkind = 'r'
|
||||
AND ct.relname = ?`, string(name))
|
||||
AND ct.relname = ?
|
||||
ORDER BY index_name, column_position`, string(name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, provider.sqlstore.WrapNotFoundErrf(err, errors.CodeNotFound, "no indices for table (%s) found", name)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -250,9 +254,11 @@ WHERE
|
||||
unique bool
|
||||
primary bool
|
||||
columnName string
|
||||
// starts from 0 and is unused in this function, this is to ensure that the column names are in the correct order
|
||||
columnPosition int
|
||||
)
|
||||
|
||||
if err := rows.Scan(&tableName, &indexName, &unique, &primary, &columnName); err != nil {
|
||||
if err := rows.Scan(&tableName, &indexName, &unique, &primary, &columnName, &columnPosition); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -269,8 +275,12 @@ WHERE
|
||||
}
|
||||
|
||||
indices := make([]sqlschema.Index, 0)
|
||||
for _, index := range uniqueIndicesMap {
|
||||
indices = append(indices, index)
|
||||
for indexName, index := range uniqueIndicesMap {
|
||||
if index.Name() == indexName {
|
||||
indices = append(indices, index)
|
||||
} else {
|
||||
indices = append(indices, index.Named(indexName))
|
||||
}
|
||||
}
|
||||
|
||||
return indices, nil
|
||||
|
||||
@@ -21,6 +21,8 @@ import type { BodyType, ErrorType } from '../../../generatedAPIInstance';
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type {
|
||||
AuthtypesPatchableObjectsDTO,
|
||||
AuthtypesPatchableRoleDTO,
|
||||
AuthtypesPostableRoleDTO,
|
||||
CreateRole201,
|
||||
DeleteRolePathParameters,
|
||||
GetObjects200,
|
||||
@@ -31,8 +33,6 @@ import type {
|
||||
PatchObjectsPathParameters,
|
||||
PatchRolePathParameters,
|
||||
RenderErrorResponseDTO,
|
||||
RoletypesPatchableRoleDTO,
|
||||
RoletypesPostableRoleDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
/**
|
||||
@@ -118,14 +118,14 @@ export const invalidateListRoles = async (
|
||||
* @summary Create role
|
||||
*/
|
||||
export const createRole = (
|
||||
roletypesPostableRoleDTO: BodyType<RoletypesPostableRoleDTO>,
|
||||
authtypesPostableRoleDTO: BodyType<AuthtypesPostableRoleDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateRole201>({
|
||||
url: `/api/v1/roles`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: roletypesPostableRoleDTO,
|
||||
data: authtypesPostableRoleDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -137,13 +137,13 @@ export const getCreateRoleMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: BodyType<RoletypesPostableRoleDTO> },
|
||||
{ data: BodyType<AuthtypesPostableRoleDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: BodyType<RoletypesPostableRoleDTO> },
|
||||
{ data: BodyType<AuthtypesPostableRoleDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createRole'];
|
||||
@@ -157,7 +157,7 @@ export const getCreateRoleMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
{ data: BodyType<RoletypesPostableRoleDTO> }
|
||||
{ data: BodyType<AuthtypesPostableRoleDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -170,7 +170,7 @@ export const getCreateRoleMutationOptions = <
|
||||
export type CreateRoleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createRole>>
|
||||
>;
|
||||
export type CreateRoleMutationBody = BodyType<RoletypesPostableRoleDTO>;
|
||||
export type CreateRoleMutationBody = BodyType<AuthtypesPostableRoleDTO>;
|
||||
export type CreateRoleMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -183,13 +183,13 @@ export const useCreateRole = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: BodyType<RoletypesPostableRoleDTO> },
|
||||
{ data: BodyType<AuthtypesPostableRoleDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createRole>>,
|
||||
TError,
|
||||
{ data: BodyType<RoletypesPostableRoleDTO> },
|
||||
{ data: BodyType<AuthtypesPostableRoleDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateRoleMutationOptions(options);
|
||||
@@ -370,13 +370,13 @@ export const invalidateGetRole = async (
|
||||
*/
|
||||
export const patchRole = (
|
||||
{ id }: PatchRolePathParameters,
|
||||
roletypesPatchableRoleDTO: BodyType<RoletypesPatchableRoleDTO>,
|
||||
authtypesPatchableRoleDTO: BodyType<AuthtypesPatchableRoleDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/roles/${id}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: roletypesPatchableRoleDTO,
|
||||
data: authtypesPatchableRoleDTO,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -389,7 +389,7 @@ export const getPatchRoleMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchRolePathParameters;
|
||||
data: BodyType<RoletypesPatchableRoleDTO>;
|
||||
data: BodyType<AuthtypesPatchableRoleDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -398,7 +398,7 @@ export const getPatchRoleMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchRolePathParameters;
|
||||
data: BodyType<RoletypesPatchableRoleDTO>;
|
||||
data: BodyType<AuthtypesPatchableRoleDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -415,7 +415,7 @@ export const getPatchRoleMutationOptions = <
|
||||
Awaited<ReturnType<typeof patchRole>>,
|
||||
{
|
||||
pathParams: PatchRolePathParameters;
|
||||
data: BodyType<RoletypesPatchableRoleDTO>;
|
||||
data: BodyType<AuthtypesPatchableRoleDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -429,7 +429,7 @@ export const getPatchRoleMutationOptions = <
|
||||
export type PatchRoleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof patchRole>>
|
||||
>;
|
||||
export type PatchRoleMutationBody = BodyType<RoletypesPatchableRoleDTO>;
|
||||
export type PatchRoleMutationBody = BodyType<AuthtypesPatchableRoleDTO>;
|
||||
export type PatchRoleMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -444,7 +444,7 @@ export const usePatchRole = <
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchRolePathParameters;
|
||||
data: BodyType<RoletypesPatchableRoleDTO>;
|
||||
data: BodyType<AuthtypesPatchableRoleDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -453,7 +453,7 @@ export const usePatchRole = <
|
||||
TError,
|
||||
{
|
||||
pathParams: PatchRolePathParameters;
|
||||
data: BodyType<RoletypesPatchableRoleDTO>;
|
||||
data: BodyType<AuthtypesPatchableRoleDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
|
||||
@@ -278,6 +278,13 @@ export interface AuthtypesPatchableObjectsDTO {
|
||||
deletions: AuthtypesGettableObjectsDTO[] | null;
|
||||
}
|
||||
|
||||
export interface AuthtypesPatchableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesPostableAuthDomainDTO {
|
||||
config?: AuthtypesAuthDomainConfigDTO;
|
||||
/**
|
||||
@@ -301,6 +308,17 @@ export interface AuthtypesPostableEmailPasswordSessionDTO {
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesPostableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesPostableRotateTokenDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -319,6 +337,39 @@ export interface AuthtypesResourceDTO {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface AuthtypesRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
orgId: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
@@ -2039,57 +2090,6 @@ export interface RenderErrorResponseDTO {
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface RoletypesPatchableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface RoletypesPostableRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface RoletypesRoleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
orgId: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesFactorAPIKeyDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -2330,7 +2330,59 @@ export interface TelemetrytypesTelemetryFieldValuesDTO {
|
||||
stringValues?: string[];
|
||||
}
|
||||
|
||||
export interface TypesChangePasswordRequestDTO {
|
||||
export interface TypesGettableGlobalConfigDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
external_url?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
ingestion_url?: string;
|
||||
}
|
||||
|
||||
export interface TypesIdentifiableDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface TypesOrganizationDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
alias?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
key?: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface UsertypesChangePasswordRequestDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2345,7 +2397,7 @@ export interface TypesChangePasswordRequestDTO {
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
export interface TypesGettableAPIKeyDTO {
|
||||
export interface UsertypesGettableAPIKeyDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -2355,7 +2407,7 @@ export interface TypesGettableAPIKeyDTO {
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
createdByUser?: TypesUserDTO;
|
||||
createdByUser?: UsertypesUserDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
@@ -2395,32 +2447,14 @@ export interface TypesGettableAPIKeyDTO {
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
updatedByUser?: TypesUserDTO;
|
||||
updatedByUser?: UsertypesUserDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
export interface TypesGettableGlobalConfigDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
external_url?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
ingestion_url?: string;
|
||||
}
|
||||
|
||||
export interface TypesIdentifiableDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface TypesInviteDTO {
|
||||
export interface UsertypesInviteDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -2461,41 +2495,7 @@ export interface TypesInviteDTO {
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface TypesOrganizationDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
alias?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
key?: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface TypesPostableAPIKeyDTO {
|
||||
export interface UsertypesPostableAPIKeyDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
@@ -2511,7 +2511,7 @@ export interface TypesPostableAPIKeyDTO {
|
||||
role?: string;
|
||||
}
|
||||
|
||||
export interface TypesPostableAcceptInviteDTO {
|
||||
export interface UsertypesPostableAcceptInviteDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2530,14 +2530,14 @@ export interface TypesPostableAcceptInviteDTO {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface TypesPostableBulkInviteRequestDTO {
|
||||
export interface UsertypesPostableBulkInviteRequestDTO {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
invites: TypesPostableInviteDTO[];
|
||||
invites: UsertypesPostableInviteDTO[];
|
||||
}
|
||||
|
||||
export interface TypesPostableForgotPasswordDTO {
|
||||
export interface UsertypesPostableForgotPasswordDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2552,7 +2552,7 @@ export interface TypesPostableForgotPasswordDTO {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface TypesPostableInviteDTO {
|
||||
export interface UsertypesPostableInviteDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2571,7 +2571,7 @@ export interface TypesPostableInviteDTO {
|
||||
role?: string;
|
||||
}
|
||||
|
||||
export interface TypesPostableResetPasswordDTO {
|
||||
export interface UsertypesPostableResetPasswordDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2582,7 +2582,7 @@ export interface TypesPostableResetPasswordDTO {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface TypesResetPasswordTokenDTO {
|
||||
export interface UsertypesResetPasswordTokenDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -2602,7 +2602,7 @@ export interface TypesResetPasswordTokenDTO {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface TypesStorableAPIKeyDTO {
|
||||
export interface UsertypesStorableAPIKeyDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -2647,7 +2647,7 @@ export interface TypesStorableAPIKeyDTO {
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
export interface TypesUserDTO {
|
||||
export interface UsertypesUserDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
@@ -3018,7 +3018,7 @@ export type GetResetPasswordTokenPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetResetPasswordToken200 = {
|
||||
data: TypesResetPasswordTokenDTO;
|
||||
data: UsertypesResetPasswordTokenDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3037,7 +3037,7 @@ export type ListInvite200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: TypesInviteDTO[];
|
||||
data: UsertypesInviteDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3045,7 +3045,7 @@ export type ListInvite200 = {
|
||||
};
|
||||
|
||||
export type CreateInvite201 = {
|
||||
data: TypesInviteDTO;
|
||||
data: UsertypesInviteDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3059,7 +3059,7 @@ export type GetInvitePathParameters = {
|
||||
token: string;
|
||||
};
|
||||
export type GetInvite200 = {
|
||||
data: TypesInviteDTO;
|
||||
data: UsertypesInviteDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3067,7 +3067,7 @@ export type GetInvite200 = {
|
||||
};
|
||||
|
||||
export type AcceptInvite201 = {
|
||||
data: TypesUserDTO;
|
||||
data: UsertypesUserDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3115,7 +3115,7 @@ export type ListAPIKeys200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: TypesGettableAPIKeyDTO[];
|
||||
data: UsertypesGettableAPIKeyDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3123,7 +3123,7 @@ export type ListAPIKeys200 = {
|
||||
};
|
||||
|
||||
export type CreateAPIKey201 = {
|
||||
data: TypesGettableAPIKeyDTO;
|
||||
data: UsertypesGettableAPIKeyDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3163,7 +3163,7 @@ export type ListRoles200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: RoletypesRoleDTO[];
|
||||
data: AuthtypesRoleDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3185,7 +3185,7 @@ export type GetRolePathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetRole200 = {
|
||||
data: RoletypesRoleDTO;
|
||||
data: AuthtypesRoleDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3290,7 +3290,7 @@ export type ListUsers200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: TypesUserDTO[];
|
||||
data: UsertypesUserDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3304,7 +3304,7 @@ export type GetUserPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetUser200 = {
|
||||
data: TypesUserDTO;
|
||||
data: UsertypesUserDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3315,7 +3315,7 @@ export type UpdateUserPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type UpdateUser200 = {
|
||||
data: TypesUserDTO;
|
||||
data: UsertypesUserDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3323,7 +3323,7 @@ export type UpdateUser200 = {
|
||||
};
|
||||
|
||||
export type GetMyUser200 = {
|
||||
data: TypesUserDTO;
|
||||
data: UsertypesUserDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
|
||||
@@ -38,18 +38,18 @@ import type {
|
||||
ListUsers200,
|
||||
RenderErrorResponseDTO,
|
||||
RevokeAPIKeyPathParameters,
|
||||
TypesChangePasswordRequestDTO,
|
||||
TypesPostableAcceptInviteDTO,
|
||||
TypesPostableAPIKeyDTO,
|
||||
TypesPostableBulkInviteRequestDTO,
|
||||
TypesPostableForgotPasswordDTO,
|
||||
TypesPostableInviteDTO,
|
||||
TypesPostableResetPasswordDTO,
|
||||
TypesStorableAPIKeyDTO,
|
||||
TypesUserDTO,
|
||||
UpdateAPIKeyPathParameters,
|
||||
UpdateUser200,
|
||||
UpdateUserPathParameters,
|
||||
UsertypesChangePasswordRequestDTO,
|
||||
UsertypesPostableAcceptInviteDTO,
|
||||
UsertypesPostableAPIKeyDTO,
|
||||
UsertypesPostableBulkInviteRequestDTO,
|
||||
UsertypesPostableForgotPasswordDTO,
|
||||
UsertypesPostableInviteDTO,
|
||||
UsertypesPostableResetPasswordDTO,
|
||||
UsertypesStorableAPIKeyDTO,
|
||||
UsertypesUserDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
/**
|
||||
@@ -58,14 +58,14 @@ import type {
|
||||
*/
|
||||
export const changePassword = (
|
||||
{ id }: ChangePasswordPathParameters,
|
||||
typesChangePasswordRequestDTO: BodyType<TypesChangePasswordRequestDTO>,
|
||||
usertypesChangePasswordRequestDTO: BodyType<UsertypesChangePasswordRequestDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/changePassword/${id}`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesChangePasswordRequestDTO,
|
||||
data: usertypesChangePasswordRequestDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -79,7 +79,7 @@ export const getChangePasswordMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: ChangePasswordPathParameters;
|
||||
data: BodyType<TypesChangePasswordRequestDTO>;
|
||||
data: BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -88,7 +88,7 @@ export const getChangePasswordMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: ChangePasswordPathParameters;
|
||||
data: BodyType<TypesChangePasswordRequestDTO>;
|
||||
data: BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -105,7 +105,7 @@ export const getChangePasswordMutationOptions = <
|
||||
Awaited<ReturnType<typeof changePassword>>,
|
||||
{
|
||||
pathParams: ChangePasswordPathParameters;
|
||||
data: BodyType<TypesChangePasswordRequestDTO>;
|
||||
data: BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -119,7 +119,7 @@ export const getChangePasswordMutationOptions = <
|
||||
export type ChangePasswordMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof changePassword>>
|
||||
>;
|
||||
export type ChangePasswordMutationBody = BodyType<TypesChangePasswordRequestDTO>;
|
||||
export type ChangePasswordMutationBody = BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
export type ChangePasswordMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -134,7 +134,7 @@ export const useChangePassword = <
|
||||
TError,
|
||||
{
|
||||
pathParams: ChangePasswordPathParameters;
|
||||
data: BodyType<TypesChangePasswordRequestDTO>;
|
||||
data: BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -143,7 +143,7 @@ export const useChangePassword = <
|
||||
TError,
|
||||
{
|
||||
pathParams: ChangePasswordPathParameters;
|
||||
data: BodyType<TypesChangePasswordRequestDTO>;
|
||||
data: BodyType<UsertypesChangePasswordRequestDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -338,14 +338,14 @@ export const invalidateListInvite = async (
|
||||
* @summary Create invite
|
||||
*/
|
||||
export const createInvite = (
|
||||
typesPostableInviteDTO: BodyType<TypesPostableInviteDTO>,
|
||||
usertypesPostableInviteDTO: BodyType<UsertypesPostableInviteDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateInvite201>({
|
||||
url: `/api/v1/invite`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableInviteDTO,
|
||||
data: usertypesPostableInviteDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -357,13 +357,13 @@ export const getCreateInviteMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableInviteDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableInviteDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createInvite'];
|
||||
@@ -377,7 +377,7 @@ export const getCreateInviteMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createInvite>>,
|
||||
{ data: BodyType<TypesPostableInviteDTO> }
|
||||
{ data: BodyType<UsertypesPostableInviteDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -390,7 +390,7 @@ export const getCreateInviteMutationOptions = <
|
||||
export type CreateInviteMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createInvite>>
|
||||
>;
|
||||
export type CreateInviteMutationBody = BodyType<TypesPostableInviteDTO>;
|
||||
export type CreateInviteMutationBody = BodyType<UsertypesPostableInviteDTO>;
|
||||
export type CreateInviteMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -403,13 +403,13 @@ export const useCreateInvite = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableInviteDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableInviteDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateInviteMutationOptions(options);
|
||||
@@ -589,14 +589,14 @@ export const invalidateGetInvite = async (
|
||||
* @summary Accept invite
|
||||
*/
|
||||
export const acceptInvite = (
|
||||
typesPostableAcceptInviteDTO: BodyType<TypesPostableAcceptInviteDTO>,
|
||||
usertypesPostableAcceptInviteDTO: BodyType<UsertypesPostableAcceptInviteDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<AcceptInvite201>({
|
||||
url: `/api/v1/invite/accept`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableAcceptInviteDTO,
|
||||
data: usertypesPostableAcceptInviteDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -608,13 +608,13 @@ export const getAcceptInviteMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof acceptInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAcceptInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableAcceptInviteDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof acceptInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAcceptInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableAcceptInviteDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['acceptInvite'];
|
||||
@@ -628,7 +628,7 @@ export const getAcceptInviteMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof acceptInvite>>,
|
||||
{ data: BodyType<TypesPostableAcceptInviteDTO> }
|
||||
{ data: BodyType<UsertypesPostableAcceptInviteDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -641,7 +641,7 @@ export const getAcceptInviteMutationOptions = <
|
||||
export type AcceptInviteMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof acceptInvite>>
|
||||
>;
|
||||
export type AcceptInviteMutationBody = BodyType<TypesPostableAcceptInviteDTO>;
|
||||
export type AcceptInviteMutationBody = BodyType<UsertypesPostableAcceptInviteDTO>;
|
||||
export type AcceptInviteMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -654,13 +654,13 @@ export const useAcceptInvite = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof acceptInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAcceptInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableAcceptInviteDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof acceptInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAcceptInviteDTO> },
|
||||
{ data: BodyType<UsertypesPostableAcceptInviteDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getAcceptInviteMutationOptions(options);
|
||||
@@ -672,14 +672,14 @@ export const useAcceptInvite = <
|
||||
* @summary Create bulk invite
|
||||
*/
|
||||
export const createBulkInvite = (
|
||||
typesPostableBulkInviteRequestDTO: BodyType<TypesPostableBulkInviteRequestDTO>,
|
||||
usertypesPostableBulkInviteRequestDTO: BodyType<UsertypesPostableBulkInviteRequestDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/invite/bulk`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableBulkInviteRequestDTO,
|
||||
data: usertypesPostableBulkInviteRequestDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -691,13 +691,13 @@ export const getCreateBulkInviteMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableBulkInviteRequestDTO> },
|
||||
{ data: BodyType<UsertypesPostableBulkInviteRequestDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableBulkInviteRequestDTO> },
|
||||
{ data: BodyType<UsertypesPostableBulkInviteRequestDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createBulkInvite'];
|
||||
@@ -711,7 +711,7 @@ export const getCreateBulkInviteMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>,
|
||||
{ data: BodyType<TypesPostableBulkInviteRequestDTO> }
|
||||
{ data: BodyType<UsertypesPostableBulkInviteRequestDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -724,7 +724,7 @@ export const getCreateBulkInviteMutationOptions = <
|
||||
export type CreateBulkInviteMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>
|
||||
>;
|
||||
export type CreateBulkInviteMutationBody = BodyType<TypesPostableBulkInviteRequestDTO>;
|
||||
export type CreateBulkInviteMutationBody = BodyType<UsertypesPostableBulkInviteRequestDTO>;
|
||||
export type CreateBulkInviteMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -737,13 +737,13 @@ export const useCreateBulkInvite = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableBulkInviteRequestDTO> },
|
||||
{ data: BodyType<UsertypesPostableBulkInviteRequestDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createBulkInvite>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableBulkInviteRequestDTO> },
|
||||
{ data: BodyType<UsertypesPostableBulkInviteRequestDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateBulkInviteMutationOptions(options);
|
||||
@@ -841,14 +841,14 @@ export const invalidateListAPIKeys = async (
|
||||
* @summary Create api key
|
||||
*/
|
||||
export const createAPIKey = (
|
||||
typesPostableAPIKeyDTO: BodyType<TypesPostableAPIKeyDTO>,
|
||||
usertypesPostableAPIKeyDTO: BodyType<UsertypesPostableAPIKeyDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateAPIKey201>({
|
||||
url: `/api/v1/pats`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableAPIKeyDTO,
|
||||
data: usertypesPostableAPIKeyDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -860,13 +860,13 @@ export const getCreateAPIKeyMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAPIKey>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAPIKeyDTO> },
|
||||
{ data: BodyType<UsertypesPostableAPIKeyDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAPIKey>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAPIKeyDTO> },
|
||||
{ data: BodyType<UsertypesPostableAPIKeyDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createAPIKey'];
|
||||
@@ -880,7 +880,7 @@ export const getCreateAPIKeyMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createAPIKey>>,
|
||||
{ data: BodyType<TypesPostableAPIKeyDTO> }
|
||||
{ data: BodyType<UsertypesPostableAPIKeyDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -893,7 +893,7 @@ export const getCreateAPIKeyMutationOptions = <
|
||||
export type CreateAPIKeyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createAPIKey>>
|
||||
>;
|
||||
export type CreateAPIKeyMutationBody = BodyType<TypesPostableAPIKeyDTO>;
|
||||
export type CreateAPIKeyMutationBody = BodyType<UsertypesPostableAPIKeyDTO>;
|
||||
export type CreateAPIKeyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -906,13 +906,13 @@ export const useCreateAPIKey = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAPIKey>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAPIKeyDTO> },
|
||||
{ data: BodyType<UsertypesPostableAPIKeyDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createAPIKey>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableAPIKeyDTO> },
|
||||
{ data: BodyType<UsertypesPostableAPIKeyDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getCreateAPIKeyMutationOptions(options);
|
||||
@@ -1002,13 +1002,13 @@ export const useRevokeAPIKey = <
|
||||
*/
|
||||
export const updateAPIKey = (
|
||||
{ id }: UpdateAPIKeyPathParameters,
|
||||
typesStorableAPIKeyDTO: BodyType<TypesStorableAPIKeyDTO>,
|
||||
usertypesStorableAPIKeyDTO: BodyType<UsertypesStorableAPIKeyDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<string>({
|
||||
url: `/api/v1/pats/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesStorableAPIKeyDTO,
|
||||
data: usertypesStorableAPIKeyDTO,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1021,7 +1021,7 @@ export const getUpdateAPIKeyMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateAPIKeyPathParameters;
|
||||
data: BodyType<TypesStorableAPIKeyDTO>;
|
||||
data: BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -1030,7 +1030,7 @@ export const getUpdateAPIKeyMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateAPIKeyPathParameters;
|
||||
data: BodyType<TypesStorableAPIKeyDTO>;
|
||||
data: BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -1047,7 +1047,7 @@ export const getUpdateAPIKeyMutationOptions = <
|
||||
Awaited<ReturnType<typeof updateAPIKey>>,
|
||||
{
|
||||
pathParams: UpdateAPIKeyPathParameters;
|
||||
data: BodyType<TypesStorableAPIKeyDTO>;
|
||||
data: BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -1061,7 +1061,7 @@ export const getUpdateAPIKeyMutationOptions = <
|
||||
export type UpdateAPIKeyMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateAPIKey>>
|
||||
>;
|
||||
export type UpdateAPIKeyMutationBody = BodyType<TypesStorableAPIKeyDTO>;
|
||||
export type UpdateAPIKeyMutationBody = BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
export type UpdateAPIKeyMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -1076,7 +1076,7 @@ export const useUpdateAPIKey = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateAPIKeyPathParameters;
|
||||
data: BodyType<TypesStorableAPIKeyDTO>;
|
||||
data: BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -1085,7 +1085,7 @@ export const useUpdateAPIKey = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateAPIKeyPathParameters;
|
||||
data: BodyType<TypesStorableAPIKeyDTO>;
|
||||
data: BodyType<UsertypesStorableAPIKeyDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -1098,14 +1098,14 @@ export const useUpdateAPIKey = <
|
||||
* @summary Reset password
|
||||
*/
|
||||
export const resetPassword = (
|
||||
typesPostableResetPasswordDTO: BodyType<TypesPostableResetPasswordDTO>,
|
||||
usertypesPostableResetPasswordDTO: BodyType<UsertypesPostableResetPasswordDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/resetPassword`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableResetPasswordDTO,
|
||||
data: usertypesPostableResetPasswordDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -1117,13 +1117,13 @@ export const getResetPasswordMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof resetPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableResetPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableResetPasswordDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof resetPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableResetPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableResetPasswordDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['resetPassword'];
|
||||
@@ -1137,7 +1137,7 @@ export const getResetPasswordMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof resetPassword>>,
|
||||
{ data: BodyType<TypesPostableResetPasswordDTO> }
|
||||
{ data: BodyType<UsertypesPostableResetPasswordDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -1150,7 +1150,7 @@ export const getResetPasswordMutationOptions = <
|
||||
export type ResetPasswordMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof resetPassword>>
|
||||
>;
|
||||
export type ResetPasswordMutationBody = BodyType<TypesPostableResetPasswordDTO>;
|
||||
export type ResetPasswordMutationBody = BodyType<UsertypesPostableResetPasswordDTO>;
|
||||
export type ResetPasswordMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -1163,13 +1163,13 @@ export const useResetPassword = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof resetPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableResetPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableResetPasswordDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof resetPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableResetPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableResetPasswordDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getResetPasswordMutationOptions(options);
|
||||
@@ -1428,13 +1428,13 @@ export const invalidateGetUser = async (
|
||||
*/
|
||||
export const updateUser = (
|
||||
{ id }: UpdateUserPathParameters,
|
||||
typesUserDTO: BodyType<TypesUserDTO>,
|
||||
usertypesUserDTO: BodyType<UsertypesUserDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<UpdateUser200>({
|
||||
url: `/api/v1/user/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesUserDTO,
|
||||
data: usertypesUserDTO,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1445,13 +1445,13 @@ export const getUpdateUserMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateUser>>,
|
||||
TError,
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<TypesUserDTO> },
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<UsertypesUserDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateUser>>,
|
||||
TError,
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<TypesUserDTO> },
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<UsertypesUserDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['updateUser'];
|
||||
@@ -1465,7 +1465,7 @@ export const getUpdateUserMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof updateUser>>,
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<TypesUserDTO> }
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<UsertypesUserDTO> }
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
|
||||
@@ -1478,7 +1478,7 @@ export const getUpdateUserMutationOptions = <
|
||||
export type UpdateUserMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateUser>>
|
||||
>;
|
||||
export type UpdateUserMutationBody = BodyType<TypesUserDTO>;
|
||||
export type UpdateUserMutationBody = BodyType<UsertypesUserDTO>;
|
||||
export type UpdateUserMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -1491,13 +1491,13 @@ export const useUpdateUser = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof updateUser>>,
|
||||
TError,
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<TypesUserDTO> },
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<UsertypesUserDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof updateUser>>,
|
||||
TError,
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<TypesUserDTO> },
|
||||
{ pathParams: UpdateUserPathParameters; data: BodyType<UsertypesUserDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getUpdateUserMutationOptions(options);
|
||||
@@ -1587,14 +1587,14 @@ export const invalidateGetMyUser = async (
|
||||
* @summary Forgot password
|
||||
*/
|
||||
export const forgotPassword = (
|
||||
typesPostableForgotPasswordDTO: BodyType<TypesPostableForgotPasswordDTO>,
|
||||
usertypesPostableForgotPasswordDTO: BodyType<UsertypesPostableForgotPasswordDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v2/factor_password/forgot`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: typesPostableForgotPasswordDTO,
|
||||
data: usertypesPostableForgotPasswordDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -1606,13 +1606,13 @@ export const getForgotPasswordMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof forgotPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableForgotPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableForgotPasswordDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof forgotPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableForgotPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableForgotPasswordDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['forgotPassword'];
|
||||
@@ -1626,7 +1626,7 @@ export const getForgotPasswordMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof forgotPassword>>,
|
||||
{ data: BodyType<TypesPostableForgotPasswordDTO> }
|
||||
{ data: BodyType<UsertypesPostableForgotPasswordDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -1639,7 +1639,7 @@ export const getForgotPasswordMutationOptions = <
|
||||
export type ForgotPasswordMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof forgotPassword>>
|
||||
>;
|
||||
export type ForgotPasswordMutationBody = BodyType<TypesPostableForgotPasswordDTO>;
|
||||
export type ForgotPasswordMutationBody = BodyType<UsertypesPostableForgotPasswordDTO>;
|
||||
export type ForgotPasswordMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
@@ -1652,13 +1652,13 @@ export const useForgotPassword = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof forgotPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableForgotPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableForgotPasswordDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof forgotPassword>>,
|
||||
TError,
|
||||
{ data: BodyType<TypesPostableForgotPasswordDTO> },
|
||||
{ data: BodyType<UsertypesPostableForgotPasswordDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getForgotPasswordMutationOptions(options);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
padding-bottom: 48px;
|
||||
|
||||
.section-heading {
|
||||
font-family: 'Space Mono';
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
@@ -25,6 +26,10 @@
|
||||
letter-spacing: 0.48px;
|
||||
}
|
||||
|
||||
.panel-type-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
padding: 14px 14px 14px 12px;
|
||||
@@ -53,50 +58,6 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.name-description {
|
||||
padding: 0 0 4px 0;
|
||||
|
||||
.name-input {
|
||||
display: flex;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex: 1 0 0;
|
||||
align-self: stretch;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
color: var(--bg-vanilla-100);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.description-input {
|
||||
border-style: unset;
|
||||
.ant-input {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
color: var(--bg-vanilla-100);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-config {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -230,87 +191,6 @@
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.bucket-config {
|
||||
.bucket-size-label {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.bucket-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
|
||||
.ant-input {
|
||||
background: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
|
||||
.combine-hist {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
|
||||
.label {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 138.462% */
|
||||
letter-spacing: 0.52px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alerts {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
min-height: 44px;
|
||||
border-top: 1px solid var(--bg-slate-500);
|
||||
cursor: pointer;
|
||||
|
||||
.left-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.bell-icon {
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
|
||||
.alerts-text {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: 0.14px;
|
||||
}
|
||||
}
|
||||
.plus-icon {
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
}
|
||||
|
||||
.context-links {
|
||||
padding: 12px 12px 16px 12px;
|
||||
border-bottom: 1px solid var(--bg-slate-500);
|
||||
}
|
||||
|
||||
.thresholds-section {
|
||||
padding: 12px 12px 16px 12px;
|
||||
border-top: 1px solid var(--bg-slate-500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,26 +225,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.name-description {
|
||||
.typography {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
|
||||
.name-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
|
||||
.description-input {
|
||||
.ant-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-config {
|
||||
.panel-type-select {
|
||||
.ant-select-selector {
|
||||
@@ -402,21 +262,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bucket-config {
|
||||
.label {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
|
||||
.bucket-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
|
||||
.ant-input {
|
||||
background: var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-time-text {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
@@ -450,31 +295,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alerts {
|
||||
border-top: 1px solid var(--bg-vanilla-300);
|
||||
|
||||
.left-section {
|
||||
.bell-icon {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
|
||||
.alerts-text {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
.plus-icon {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
|
||||
.context-links {
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
|
||||
.thresholds-section {
|
||||
border-top: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
|
||||
.select-option {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
.alerts-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
min-height: 44px;
|
||||
border-top: 1px solid var(--bg-slate-500);
|
||||
cursor: pointer;
|
||||
|
||||
.alerts-section__left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.alerts-section__bell-icon {
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
|
||||
.alerts-section__text {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: 0.14px;
|
||||
}
|
||||
}
|
||||
.alerts-section__plus-icon {
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.alerts-section {
|
||||
border-top: 1px solid var(--bg-vanilla-300);
|
||||
|
||||
.alerts-section__left {
|
||||
.alerts-section__bell-icon {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
|
||||
.alerts-section__text {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
.alerts-section__plus-icon {
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Typography } from 'antd';
|
||||
import { ConciergeBell, Plus, SquareArrowOutUpRight } from 'lucide-react';
|
||||
|
||||
import './AlertsSection.styles.scss';
|
||||
|
||||
interface AlertsSectionProps {
|
||||
onCreateAlertsHandler: () => void;
|
||||
}
|
||||
|
||||
export default function AlertsSection({
|
||||
onCreateAlertsHandler,
|
||||
}: AlertsSectionProps): JSX.Element {
|
||||
return (
|
||||
<section className="alerts-section" onClick={onCreateAlertsHandler}>
|
||||
<div className="alerts-section__left">
|
||||
<ConciergeBell size={14} className="alerts-section__bell-icon" />
|
||||
<Typography.Text className="alerts-section__text">Alerts</Typography.Text>
|
||||
<SquareArrowOutUpRight size={10} className="info-icon" />
|
||||
</div>
|
||||
<Plus size={14} className="alerts-section__plus-icon" />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { InputNumber, Select, Typography } from 'antd';
|
||||
import { Axis3D, LineChart, Spline } from 'lucide-react';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
|
||||
enum LogScale {
|
||||
LINEAR = 'linear',
|
||||
LOGARITHMIC = 'logarithmic',
|
||||
}
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
interface AxesSectionProps {
|
||||
allowSoftMinMax: boolean;
|
||||
allowLogScale: boolean;
|
||||
softMin: number | null;
|
||||
softMax: number | null;
|
||||
setSoftMin: Dispatch<SetStateAction<number | null>>;
|
||||
setSoftMax: Dispatch<SetStateAction<number | null>>;
|
||||
isLogScale: boolean;
|
||||
setIsLogScale: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export default function AxesSection({
|
||||
allowSoftMinMax,
|
||||
allowLogScale,
|
||||
softMin,
|
||||
softMax,
|
||||
setSoftMin,
|
||||
setSoftMax,
|
||||
isLogScale,
|
||||
setIsLogScale,
|
||||
}: AxesSectionProps): JSX.Element {
|
||||
const softMinHandler = (value: number | null): void => {
|
||||
setSoftMin(value);
|
||||
};
|
||||
|
||||
const softMaxHandler = (value: number | null): void => {
|
||||
setSoftMax(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsSection title="Axes" icon={<Axis3D size={14} />}>
|
||||
{allowSoftMinMax && (
|
||||
<section className="soft-min-max">
|
||||
<section className="container">
|
||||
<Typography.Text className="text">Soft Min</Typography.Text>
|
||||
<InputNumber
|
||||
type="number"
|
||||
value={softMin}
|
||||
onChange={softMinHandler}
|
||||
rootClassName="input"
|
||||
/>
|
||||
</section>
|
||||
<section className="container">
|
||||
<Typography.Text className="text">Soft Max</Typography.Text>
|
||||
<InputNumber
|
||||
value={softMax}
|
||||
type="number"
|
||||
rootClassName="input"
|
||||
onChange={softMaxHandler}
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowLogScale && (
|
||||
<section className="log-scale control-container">
|
||||
<Typography.Text className="section-heading">Y Axis Scale</Typography.Text>
|
||||
<Select
|
||||
onChange={(value): void => setIsLogScale(value === LogScale.LOGARITHMIC)}
|
||||
value={isLogScale ? LogScale.LOGARITHMIC : LogScale.LINEAR}
|
||||
className="panel-type-select"
|
||||
defaultValue={LogScale.LINEAR}
|
||||
>
|
||||
<Option value={LogScale.LINEAR}>
|
||||
<div className="select-option">
|
||||
<div className="icon">
|
||||
<LineChart size={16} />
|
||||
</div>
|
||||
<Typography.Text className="display">Linear</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value={LogScale.LOGARITHMIC}>
|
||||
<div className="select-option">
|
||||
<div className="icon">
|
||||
<Spline size={16} />
|
||||
</div>
|
||||
<Typography.Text className="display">Logarithmic</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
</Select>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Switch, Typography } from 'antd';
|
||||
import {
|
||||
FillMode,
|
||||
LineInterpolation,
|
||||
LineStyle,
|
||||
} from 'lib/uPlotV2/config/types';
|
||||
import { Paintbrush } from 'lucide-react';
|
||||
|
||||
import { FillModeSelector } from '../../components/FillModeSelector/FillModeSelector';
|
||||
import { LineInterpolationSelector } from '../../components/LineInterpolationSelector/LineInterpolationSelector';
|
||||
import { LineStyleSelector } from '../../components/LineStyleSelector/LineStyleSelector';
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
|
||||
interface ChartAppearanceSectionProps {
|
||||
fillMode: FillMode;
|
||||
setFillMode: Dispatch<SetStateAction<FillMode>>;
|
||||
lineStyle: LineStyle;
|
||||
setLineStyle: Dispatch<SetStateAction<LineStyle>>;
|
||||
lineInterpolation: LineInterpolation;
|
||||
setLineInterpolation: Dispatch<SetStateAction<LineInterpolation>>;
|
||||
showPoints: boolean;
|
||||
setShowPoints: Dispatch<SetStateAction<boolean>>;
|
||||
allowFillMode: boolean;
|
||||
allowLineStyle: boolean;
|
||||
allowLineInterpolation: boolean;
|
||||
allowShowPoints: boolean;
|
||||
}
|
||||
|
||||
export default function ChartAppearanceSection({
|
||||
fillMode,
|
||||
setFillMode,
|
||||
lineStyle,
|
||||
setLineStyle,
|
||||
lineInterpolation,
|
||||
setLineInterpolation,
|
||||
showPoints,
|
||||
setShowPoints,
|
||||
allowFillMode,
|
||||
allowLineStyle,
|
||||
allowLineInterpolation,
|
||||
allowShowPoints,
|
||||
}: ChartAppearanceSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection title="Chart Appearance" icon={<Paintbrush size={14} />}>
|
||||
{allowFillMode && (
|
||||
<FillModeSelector value={fillMode} onChange={setFillMode} />
|
||||
)}
|
||||
{allowLineStyle && (
|
||||
<LineStyleSelector value={lineStyle} onChange={setLineStyle} />
|
||||
)}
|
||||
{allowLineInterpolation && (
|
||||
<LineInterpolationSelector
|
||||
value={lineInterpolation}
|
||||
onChange={setLineInterpolation}
|
||||
/>
|
||||
)}
|
||||
{allowShowPoints && (
|
||||
<section className="show-points toggle-card">
|
||||
<div className="toggle-card-text-container">
|
||||
<Typography.Text className="section-heading">Show points</Typography.Text>
|
||||
<Typography.Text className="toggle-card-description">
|
||||
Display individual data points on the chart
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Switch size="small" checked={showPoints} onChange={setShowPoints} />
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
.context-links-section {
|
||||
padding: 12px 12px 16px 12px;
|
||||
border-bottom: 1px solid var(--bg-slate-500);
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.context-links-section {
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Link as LinkIcon } from 'lucide-react';
|
||||
import { ContextLinksData, Widgets } from 'types/api/dashboard/getAll';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
import ContextLinks from '../../ContextLinks';
|
||||
|
||||
import './ContextLinksSection.styles.scss';
|
||||
|
||||
interface ContextLinksSectionProps {
|
||||
contextLinks: ContextLinksData;
|
||||
setContextLinks: Dispatch<SetStateAction<ContextLinksData>>;
|
||||
selectedWidget?: Widgets;
|
||||
}
|
||||
|
||||
export default function ContextLinksSection({
|
||||
contextLinks,
|
||||
setContextLinks,
|
||||
selectedWidget,
|
||||
}: ContextLinksSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection
|
||||
title="Context Links"
|
||||
icon={<LinkIcon size={14} />}
|
||||
defaultOpen={!!contextLinks.linksData.length}
|
||||
>
|
||||
<div className="context-links-section">
|
||||
<ContextLinks
|
||||
contextLinks={contextLinks}
|
||||
setContextLinks={setContextLinks}
|
||||
selectedWidget={selectedWidget}
|
||||
/>
|
||||
</div>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Select, Typography } from 'antd';
|
||||
import { PrecisionOption } from 'components/Graph/types';
|
||||
import { PanelDisplay } from 'constants/queryBuilder';
|
||||
import { SlidersHorizontal } from 'lucide-react';
|
||||
import { ColumnUnit } from 'types/api/dashboard/getAll';
|
||||
|
||||
import { ColumnUnitSelector } from '../../ColumnUnitSelector/ColumnUnitSelector';
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
import DashboardYAxisUnitSelectorWrapper from '../../DashboardYAxisUnitSelectorWrapper';
|
||||
|
||||
interface FormattingUnitsSectionProps {
|
||||
selectedPanelDisplay: PanelDisplay | '';
|
||||
yAxisUnit: string;
|
||||
setYAxisUnit: Dispatch<SetStateAction<string>>;
|
||||
isNewDashboard: boolean;
|
||||
decimalPrecision: PrecisionOption;
|
||||
setDecimalPrecision: Dispatch<SetStateAction<PrecisionOption>>;
|
||||
columnUnits: ColumnUnit;
|
||||
setColumnUnits: Dispatch<SetStateAction<ColumnUnit>>;
|
||||
allowYAxisUnit: boolean;
|
||||
allowDecimalPrecision: boolean;
|
||||
allowPanelColumnPreference: boolean;
|
||||
decimapPrecisionOptions: { label: string; value: PrecisionOption }[];
|
||||
}
|
||||
|
||||
export default function FormattingUnitsSection({
|
||||
selectedPanelDisplay,
|
||||
yAxisUnit,
|
||||
setYAxisUnit,
|
||||
isNewDashboard,
|
||||
decimalPrecision,
|
||||
setDecimalPrecision,
|
||||
columnUnits,
|
||||
setColumnUnits,
|
||||
allowYAxisUnit,
|
||||
allowDecimalPrecision,
|
||||
allowPanelColumnPreference,
|
||||
decimapPrecisionOptions,
|
||||
}: FormattingUnitsSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection
|
||||
title="Formatting & Units"
|
||||
icon={<SlidersHorizontal size={14} />}
|
||||
>
|
||||
{allowYAxisUnit && (
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
onSelect={setYAxisUnit}
|
||||
value={yAxisUnit || ''}
|
||||
fieldLabel={
|
||||
selectedPanelDisplay === PanelDisplay.VALUE ||
|
||||
selectedPanelDisplay === PanelDisplay.PIE
|
||||
? 'Unit'
|
||||
: 'Y Axis Unit'
|
||||
}
|
||||
shouldUpdateYAxisUnit={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
|
||||
{allowDecimalPrecision && (
|
||||
<section className="decimal-precision-selector control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Decimal Precision
|
||||
</Typography.Text>
|
||||
<Select
|
||||
options={decimapPrecisionOptions}
|
||||
value={decimalPrecision}
|
||||
className="panel-type-select"
|
||||
defaultValue={decimapPrecisionOptions[0]?.value}
|
||||
onChange={(val: PrecisionOption): void => setDecimalPrecision(val)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowPanelColumnPreference && (
|
||||
<ColumnUnitSelector
|
||||
columnUnits={columnUnits}
|
||||
setColumnUnits={setColumnUnits}
|
||||
isNewDashboard={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
.general-settings__name-description {
|
||||
padding: 0 0 4px 0;
|
||||
|
||||
.general-settings__name-input {
|
||||
display: flex;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex: 1 0 0;
|
||||
align-self: stretch;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
color: var(--bg-vanilla-100);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.general-settings__description-input {
|
||||
border-style: unset;
|
||||
.ant-input {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
color: var(--bg-vanilla-100);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.general-settings__name-description {
|
||||
border-top: 1px solid var(--bg-vanilla-300);
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
|
||||
.general-settings__name-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
|
||||
.general-settings__description-input {
|
||||
.ant-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import {
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import type { InputRef } from 'antd';
|
||||
import { AutoComplete, Input, Typography } from 'antd';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
|
||||
import './GeneralSettingsSection.styles.scss';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
interface VariableOption {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface GeneralSettingsSectionProps {
|
||||
title: string;
|
||||
setTitle: Dispatch<SetStateAction<string>>;
|
||||
description: string;
|
||||
setDescription: Dispatch<SetStateAction<string>>;
|
||||
dashboardVariables: Record<string, { name?: string }>;
|
||||
}
|
||||
|
||||
export default function GeneralSettingsSection({
|
||||
title,
|
||||
setTitle,
|
||||
description,
|
||||
setDescription,
|
||||
dashboardVariables,
|
||||
}: GeneralSettingsSectionProps): JSX.Element {
|
||||
const [inputValue, setInputValue] = useState(title);
|
||||
const [autoCompleteOpen, setAutoCompleteOpen] = useState(false);
|
||||
const [cursorPos, setCursorPos] = useState(0);
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
|
||||
const onChangeHandler = (
|
||||
setFunc: Dispatch<SetStateAction<string>>,
|
||||
value: string,
|
||||
): void => {
|
||||
setFunc(value);
|
||||
};
|
||||
|
||||
const dashboardVariableOptions = useMemo<VariableOption[]>(() => {
|
||||
return Object.entries(dashboardVariables).map(([, value]) => ({
|
||||
value: value.name || '',
|
||||
label: value.name || '',
|
||||
}));
|
||||
}, [dashboardVariables]);
|
||||
|
||||
const updateCursorAndDropdown = useCallback(
|
||||
(value: string, pos: number): void => {
|
||||
setCursorPos(pos);
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
setAutoCompleteOpen(lastDollar !== -1 && pos >= lastDollar + 1);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const onInputChange = useCallback(
|
||||
(value: string): void => {
|
||||
setInputValue(value);
|
||||
onChangeHandler(setTitle, value);
|
||||
setTimeout(() => {
|
||||
const pos = inputRef.current?.input?.selectionStart ?? 0;
|
||||
updateCursorAndDropdown(value, pos);
|
||||
}, 0);
|
||||
},
|
||||
[setTitle, updateCursorAndDropdown],
|
||||
);
|
||||
|
||||
const onSelect = useCallback(
|
||||
(selectedValue: string): void => {
|
||||
const pos = cursorPos;
|
||||
const value = inputValue;
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
const textBeforeDollar = value.substring(0, lastDollar);
|
||||
const textAfterDollar = value.substring(lastDollar + 1);
|
||||
const match = textAfterDollar.match(/^([a-zA-Z0-9_.]*)/);
|
||||
const rest = textAfterDollar.substring(match ? match[1].length : 0);
|
||||
const newValue = `${textBeforeDollar}$${selectedValue}${rest}`;
|
||||
setInputValue(newValue);
|
||||
onChangeHandler(setTitle, newValue);
|
||||
setAutoCompleteOpen(false);
|
||||
setTimeout(() => {
|
||||
const newCursor = `${textBeforeDollar}$${selectedValue}`.length;
|
||||
inputRef.current?.input?.setSelectionRange(newCursor, newCursor);
|
||||
setCursorPos(newCursor);
|
||||
}, 0);
|
||||
},
|
||||
[cursorPos, inputValue, setTitle],
|
||||
);
|
||||
|
||||
const filterOption = useCallback(
|
||||
(currentInputValue: string, option?: VariableOption): boolean => {
|
||||
const pos = cursorPos;
|
||||
const value = currentInputValue;
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
if (lastDollar === -1) {
|
||||
return false;
|
||||
}
|
||||
const afterDollar = value.substring(lastDollar + 1, pos).toLowerCase();
|
||||
return option?.value.toLowerCase().startsWith(afterDollar) || false;
|
||||
},
|
||||
[cursorPos],
|
||||
);
|
||||
|
||||
const handleInputCursor = useCallback((): void => {
|
||||
const pos = inputRef.current?.input?.selectionStart ?? 0;
|
||||
updateCursorAndDropdown(inputValue, pos);
|
||||
}, [inputValue, updateCursorAndDropdown]);
|
||||
|
||||
return (
|
||||
<SettingsSection title="General" defaultOpen icon={null}>
|
||||
<section className="general-settings__name-description control-container">
|
||||
<Typography.Text className="section-heading">Name</Typography.Text>
|
||||
<AutoComplete
|
||||
options={dashboardVariableOptions}
|
||||
value={inputValue}
|
||||
onChange={onInputChange}
|
||||
onSelect={onSelect}
|
||||
filterOption={filterOption}
|
||||
getPopupContainer={popupContainer}
|
||||
placeholder="Enter the panel name here..."
|
||||
open={autoCompleteOpen}
|
||||
>
|
||||
<Input
|
||||
rootClassName="general-settings__name-input"
|
||||
ref={inputRef}
|
||||
onSelect={handleInputCursor}
|
||||
onClick={handleInputCursor}
|
||||
onBlur={(): void => setAutoCompleteOpen(false)}
|
||||
/>
|
||||
</AutoComplete>
|
||||
<Typography.Text className="section-heading">Description</Typography.Text>
|
||||
<TextArea
|
||||
placeholder="Enter the panel description here..."
|
||||
bordered
|
||||
allowClear
|
||||
value={description}
|
||||
onChange={(event): void =>
|
||||
onChangeHandler(setDescription, event.target.value)
|
||||
}
|
||||
rootClassName="general-settings__description-input"
|
||||
/>
|
||||
</section>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
.histogram-settings__bucket-config {
|
||||
.histogram-settings__bucket-size-label {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.histogram-settings__bucket-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 6px 6px 6px 8px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
|
||||
.ant-input {
|
||||
background: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
|
||||
.histogram-settings__combine-hist {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
|
||||
.histogram-settings__merge-label {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 138.462% */
|
||||
letter-spacing: 0.52px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.histogram-settings__bucket-config {
|
||||
.histogram-settings__merge-label {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
|
||||
.histogram-settings__bucket-input {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
|
||||
.ant-input {
|
||||
background: var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { InputNumber, Switch, Typography } from 'antd';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
|
||||
import './HistogramBucketsSection.styles.scss';
|
||||
|
||||
interface HistogramBucketsSectionProps {
|
||||
bucketCount: number;
|
||||
setBucketCount: Dispatch<SetStateAction<number>>;
|
||||
bucketWidth: number;
|
||||
setBucketWidth: Dispatch<SetStateAction<number>>;
|
||||
combineHistogram: boolean;
|
||||
setCombineHistogram: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export default function HistogramBucketsSection({
|
||||
bucketCount,
|
||||
setBucketCount,
|
||||
bucketWidth,
|
||||
setBucketWidth,
|
||||
combineHistogram,
|
||||
setCombineHistogram,
|
||||
}: HistogramBucketsSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection title="Histogram / Buckets">
|
||||
<section className="histogram-settings__bucket-config control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Number of buckets
|
||||
</Typography.Text>
|
||||
<InputNumber
|
||||
value={bucketCount || null}
|
||||
type="number"
|
||||
min={0}
|
||||
rootClassName="bucket-input"
|
||||
placeholder="Default: 30"
|
||||
onChange={(val): void => {
|
||||
setBucketCount(val || 0);
|
||||
}}
|
||||
/>
|
||||
<Typography.Text className="section-heading histogram-settings__bucket-size-label">
|
||||
Bucket width
|
||||
</Typography.Text>
|
||||
<InputNumber
|
||||
value={bucketWidth || null}
|
||||
type="number"
|
||||
precision={2}
|
||||
placeholder="Default: Auto"
|
||||
step={0.1}
|
||||
min={0.0}
|
||||
rootClassName="histogram-settings__bucket-input"
|
||||
onChange={(val): void => {
|
||||
setBucketWidth(val || 0);
|
||||
}}
|
||||
/>
|
||||
<section className="histogram-settings__combine-hist">
|
||||
<Typography.Text className="section-heading">
|
||||
<span className="histogram-settings__merge-label">
|
||||
Merge all series into one
|
||||
</span>
|
||||
</Typography.Text>
|
||||
<Switch
|
||||
checked={combineHistogram}
|
||||
size="small"
|
||||
onChange={(checked): void => setCombineHistogram(checked)}
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import type { UseQueryResult } from 'react-query';
|
||||
import { Select, Typography } from 'antd';
|
||||
import { Layers } from 'lucide-react';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
import { LegendPosition } from 'types/api/dashboard/getAll';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
import LegendColors from '../../LegendColors/LegendColors';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
interface LegendSectionProps {
|
||||
allowLegendPosition: boolean;
|
||||
allowLegendColors: boolean;
|
||||
legendPosition: LegendPosition;
|
||||
setLegendPosition: Dispatch<SetStateAction<LegendPosition>>;
|
||||
customLegendColors: Record<string, string>;
|
||||
setCustomLegendColors: Dispatch<SetStateAction<Record<string, string>>>;
|
||||
queryResponse?: UseQueryResult<
|
||||
SuccessResponse<MetricRangePayloadProps, unknown>,
|
||||
Error
|
||||
>;
|
||||
}
|
||||
|
||||
export default function LegendSection({
|
||||
allowLegendPosition,
|
||||
allowLegendColors,
|
||||
legendPosition,
|
||||
setLegendPosition,
|
||||
customLegendColors,
|
||||
setCustomLegendColors,
|
||||
queryResponse,
|
||||
}: LegendSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection title="Legend" icon={<Layers size={14} />}>
|
||||
{allowLegendPosition && (
|
||||
<section className="legend-position control-container">
|
||||
<Typography.Text className="section-heading">Position</Typography.Text>
|
||||
<Select
|
||||
onChange={(value: LegendPosition): void => setLegendPosition(value)}
|
||||
value={legendPosition}
|
||||
className="panel-type-select"
|
||||
defaultValue={LegendPosition.BOTTOM}
|
||||
>
|
||||
<Option value={LegendPosition.BOTTOM}>
|
||||
<div className="select-option">
|
||||
<Typography.Text className="display">Bottom</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value={LegendPosition.RIGHT}>
|
||||
<div className="select-option">
|
||||
<Typography.Text className="display">Right</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
</Select>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowLegendColors && (
|
||||
<section className="legend-colors">
|
||||
<LegendColors
|
||||
customLegendColors={customLegendColors}
|
||||
setCustomLegendColors={setCustomLegendColors}
|
||||
queryResponse={queryResponse}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
.thresholds-section {
|
||||
padding: 12px 12px 16px 12px;
|
||||
border-top: 1px solid var(--bg-slate-500);
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.thresholds-section {
|
||||
border-top: 1px solid var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { Antenna } from 'lucide-react';
|
||||
import { ColumnUnit } from 'types/api/dashboard/getAll';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
import ThresholdSelector from '../../Threshold/ThresholdSelector';
|
||||
import { ThresholdProps } from '../../Threshold/types';
|
||||
|
||||
import './ThresholdsSection.styles.scss';
|
||||
|
||||
interface ThresholdsSectionProps {
|
||||
thresholds: ThresholdProps[];
|
||||
setThresholds: Dispatch<SetStateAction<ThresholdProps[]>>;
|
||||
yAxisUnit: string;
|
||||
selectedGraph: PANEL_TYPES;
|
||||
columnUnits: ColumnUnit;
|
||||
}
|
||||
|
||||
export default function ThresholdsSection({
|
||||
thresholds,
|
||||
setThresholds,
|
||||
yAxisUnit,
|
||||
selectedGraph,
|
||||
columnUnits,
|
||||
}: ThresholdsSectionProps): JSX.Element {
|
||||
return (
|
||||
<SettingsSection
|
||||
title="Thresholds"
|
||||
icon={<Antenna size={14} />}
|
||||
defaultOpen={!!thresholds.length}
|
||||
>
|
||||
<ThresholdSelector
|
||||
thresholds={thresholds}
|
||||
setThresholds={setThresholds}
|
||||
yAxisUnit={yAxisUnit}
|
||||
selectedGraph={selectedGraph}
|
||||
columnUnits={columnUnits}
|
||||
/>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import { Select, Switch, Typography } from 'antd';
|
||||
import TimePreference from 'components/TimePreferenceDropDown';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import {
|
||||
ItemsProps,
|
||||
PanelTypesWithData,
|
||||
} from 'container/DashboardContainer/PanelTypeSelectionModal/menuItems';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { LayoutDashboard } from 'lucide-react';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import SettingsSection from '../../components/SettingsSection/SettingsSection';
|
||||
import { timePreferance } from '../../timeItems';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
interface VisualizationSettingsSectionProps {
|
||||
selectedGraph: PANEL_TYPES;
|
||||
setGraphHandler: (type: PANEL_TYPES) => void;
|
||||
selectedTime: timePreferance;
|
||||
setSelectedTime: Dispatch<SetStateAction<timePreferance>>;
|
||||
stackedBarChart: boolean;
|
||||
setStackedBarChart: Dispatch<SetStateAction<boolean>>;
|
||||
isFillSpans: boolean;
|
||||
setIsFillSpans: Dispatch<SetStateAction<boolean>>;
|
||||
allowPanelTimePreference: boolean;
|
||||
allowStackingBarChart: boolean;
|
||||
allowFillSpans: boolean;
|
||||
}
|
||||
|
||||
export default function VisualizationSettingsSection({
|
||||
selectedGraph,
|
||||
setGraphHandler,
|
||||
selectedTime,
|
||||
setSelectedTime,
|
||||
stackedBarChart,
|
||||
setStackedBarChart,
|
||||
isFillSpans,
|
||||
setIsFillSpans,
|
||||
allowPanelTimePreference,
|
||||
allowStackingBarChart,
|
||||
allowFillSpans,
|
||||
}: VisualizationSettingsSectionProps): JSX.Element {
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
const [graphTypes, setGraphTypes] = useState<ItemsProps[]>(PanelTypesWithData);
|
||||
|
||||
useEffect(() => {
|
||||
const queryContainsMetricsDataSource = currentQuery.builder.queryData.some(
|
||||
(query) => query.dataSource === DataSource.METRICS,
|
||||
);
|
||||
|
||||
if (queryContainsMetricsDataSource) {
|
||||
setGraphTypes((prev) =>
|
||||
prev.filter((graph) => graph.name !== PANEL_TYPES.LIST),
|
||||
);
|
||||
} else {
|
||||
setGraphTypes(PanelTypesWithData);
|
||||
}
|
||||
}, [currentQuery]);
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
title="Visualization"
|
||||
defaultOpen
|
||||
icon={<LayoutDashboard size={14} />}
|
||||
>
|
||||
<section className="panel-type control-container">
|
||||
<Typography.Text className="section-heading">Panel Type</Typography.Text>
|
||||
<Select
|
||||
onChange={setGraphHandler}
|
||||
value={selectedGraph}
|
||||
className="panel-type-select"
|
||||
data-testid="panel-change-select"
|
||||
data-stacking-state={stackedBarChart ? 'true' : 'false'}
|
||||
>
|
||||
{graphTypes.map((item) => (
|
||||
<Option key={item.name} value={item.name}>
|
||||
<div className="select-option">
|
||||
<div className="icon">{item.icon}</div>
|
||||
<Typography.Text className="display">{item.display}</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</section>
|
||||
|
||||
{allowPanelTimePreference && (
|
||||
<section className="panel-time-preference control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Panel Time Preference
|
||||
</Typography.Text>
|
||||
<TimePreference
|
||||
{...{
|
||||
selectedTime,
|
||||
setSelectedTime,
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowStackingBarChart && (
|
||||
<section className="stack-chart control-container">
|
||||
<Typography.Text className="section-heading">Stack series</Typography.Text>
|
||||
<Switch
|
||||
checked={stackedBarChart}
|
||||
size="small"
|
||||
onChange={(checked): void => setStackedBarChart(checked)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowFillSpans && (
|
||||
<section className="fill-gaps toggle-card">
|
||||
<div className="toggle-card-text-container">
|
||||
<Typography className="section-heading">Fill gaps</Typography>
|
||||
<Typography.Text className="toggle-card-description">
|
||||
Fill gaps in data with 0 for continuity
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Switch
|
||||
checked={isFillSpans}
|
||||
size="small"
|
||||
onChange={(checked): void => setIsFillSpans(checked)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
@@ -189,7 +189,7 @@ describe('RightContainer - Alerts Section', () => {
|
||||
|
||||
const alertsSection = screen.getByText('Alerts').closest('section');
|
||||
expect(alertsSection).toBeInTheDocument();
|
||||
expect(alertsSection).toHaveClass('alerts');
|
||||
expect(alertsSection).toHaveClass('alerts-section');
|
||||
});
|
||||
|
||||
it('renders alerts section with correct text and SquareArrowOutUpRight icon', () => {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
.fill-mode-selector {
|
||||
.fill-mode-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.fill-mode-label {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.fill-mode-selector {
|
||||
.fill-mode-label {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import { ToggleGroup, ToggleGroupItem } from '@signozhq/toggle-group';
|
||||
import { Typography } from 'antd';
|
||||
import { FillMode } from 'lib/uPlotV2/config/types';
|
||||
|
||||
import './FillModeSelector.styles.scss';
|
||||
|
||||
interface FillModeSelectorProps {
|
||||
value: FillMode;
|
||||
onChange: (value: FillMode) => void;
|
||||
}
|
||||
|
||||
export function FillModeSelector({
|
||||
value,
|
||||
onChange,
|
||||
}: FillModeSelectorProps): JSX.Element {
|
||||
return (
|
||||
<section className="fill-mode-selector control-container">
|
||||
<Typography.Text className="section-heading">Fill mode</Typography.Text>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={value}
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onValueChange={(newValue): void => {
|
||||
if (newValue) {
|
||||
onChange(newValue as FillMode);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ToggleGroupItem value={FillMode.None} aria-label="None" title="None">
|
||||
<svg
|
||||
className="fill-mode-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<rect x="8" y="16" width="32" height="16" stroke="#888" fill="none" />
|
||||
</svg>
|
||||
<Typography.Text className="section-heading-small">None</Typography.Text>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value={FillMode.Solid} aria-label="Solid" title="Solid">
|
||||
<svg
|
||||
className="fill-mode-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<rect x="8" y="16" width="32" height="16" fill="#888" />
|
||||
</svg>
|
||||
<Typography.Text className="section-heading-small">Solid</Typography.Text>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value={FillMode.Gradient}
|
||||
aria-label="Gradient"
|
||||
title="Gradient"
|
||||
>
|
||||
<svg
|
||||
className="fill-mode-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="fill-gradient" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stopColor="#888" stopOpacity="0.2" />
|
||||
<stop offset="100%" stopColor="#888" stopOpacity="0.8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect
|
||||
x="8"
|
||||
y="16"
|
||||
width="32"
|
||||
height="16"
|
||||
fill="url(#fill-gradient)"
|
||||
stroke="#888"
|
||||
/>
|
||||
</svg>
|
||||
<Typography.Text className="section-heading-small">
|
||||
Gradient
|
||||
</Typography.Text>
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
.line-interpolation-selector {
|
||||
.line-interpolation-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.line-interpolation-label {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.line-interpolation-selector {
|
||||
.line-interpolation-label {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import { ToggleGroup, ToggleGroupItem } from '@signozhq/toggle-group';
|
||||
import { Typography } from 'antd';
|
||||
import { LineInterpolation } from 'lib/uPlotV2/config/types';
|
||||
|
||||
import './LineInterpolationSelector.styles.scss';
|
||||
|
||||
interface LineInterpolationSelectorProps {
|
||||
value: LineInterpolation;
|
||||
onChange: (value: LineInterpolation) => void;
|
||||
}
|
||||
|
||||
export function LineInterpolationSelector({
|
||||
value,
|
||||
onChange,
|
||||
}: LineInterpolationSelectorProps): JSX.Element {
|
||||
return (
|
||||
<section className="line-interpolation-selector control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Line interpolation
|
||||
</Typography.Text>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={value}
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onValueChange={(newValue): void => {
|
||||
if (newValue) {
|
||||
onChange(newValue as LineInterpolation);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ToggleGroupItem
|
||||
value={LineInterpolation.Linear}
|
||||
aria-label="Linear"
|
||||
title="Linear"
|
||||
>
|
||||
<svg
|
||||
className="line-interpolation-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<circle cx="8" cy="32" r="3" fill="#888" />
|
||||
<circle cx="24" cy="16" r="3" fill="#888" />
|
||||
<circle cx="40" cy="32" r="3" fill="#888" />
|
||||
<path d="M8 32 L24 16 L40 32" stroke="#888" />
|
||||
</svg>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value={LineInterpolation.Spline} aria-label="Spline">
|
||||
<svg
|
||||
className="line-interpolation-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<circle cx="8" cy="32" r="3" fill="#888" />
|
||||
<circle cx="24" cy="16" r="3" fill="#888" />
|
||||
<circle cx="40" cy="32" r="3" fill="#888" />
|
||||
<path d="M8 32 C16 8, 32 8, 40 32" />
|
||||
</svg>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value={LineInterpolation.StepAfter}
|
||||
aria-label="Step After"
|
||||
>
|
||||
<svg
|
||||
className="line-interpolation-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<circle cx="8" cy="32" r="3" fill="#888" />
|
||||
<circle cx="24" cy="16" r="3" fill="#888" />
|
||||
<circle cx="40" cy="32" r="3" fill="#888" />
|
||||
<path d="M8 32 V16 H24 V32 H40" />
|
||||
</svg>
|
||||
</ToggleGroupItem>
|
||||
|
||||
<ToggleGroupItem
|
||||
value={LineInterpolation.StepBefore}
|
||||
aria-label="Step Before"
|
||||
>
|
||||
<svg
|
||||
className="line-interpolation-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<circle cx="8" cy="32" r="3" fill="#888" />
|
||||
<circle cx="24" cy="16" r="3" fill="#888" />
|
||||
<circle cx="40" cy="32" r="3" fill="#888" />
|
||||
<path d="M8 32 H24 V16 H40 V32" />
|
||||
</svg>
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
.line-style-selector {
|
||||
.line-style-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.line-style-label {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--bg-vanilla-400);
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.line-style-selector {
|
||||
.line-style-label {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { ToggleGroup, ToggleGroupItem } from '@signozhq/toggle-group';
|
||||
import { Typography } from 'antd';
|
||||
import { LineStyle } from 'lib/uPlotV2/config/types';
|
||||
|
||||
import './LineStyleSelector.styles.scss';
|
||||
|
||||
interface LineStyleSelectorProps {
|
||||
value: LineStyle;
|
||||
onChange: (value: LineStyle) => void;
|
||||
}
|
||||
|
||||
export function LineStyleSelector({
|
||||
value,
|
||||
onChange,
|
||||
}: LineStyleSelectorProps): JSX.Element {
|
||||
return (
|
||||
<section className="line-style-selector control-container">
|
||||
<Typography.Text className="section-heading">Line style</Typography.Text>
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={value}
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onValueChange={(newValue): void => {
|
||||
if (newValue) {
|
||||
onChange(newValue as LineStyle);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ToggleGroupItem value={LineStyle.Solid} aria-label="Solid" title="Solid">
|
||||
<svg
|
||||
className="line-style-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M8 24 L40 24" />
|
||||
</svg>
|
||||
<Typography.Text className="section-heading-small">Solid</Typography.Text>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value={LineStyle.Dashed}
|
||||
aria-label="Dashed"
|
||||
title="Dashed"
|
||||
>
|
||||
<svg
|
||||
className="line-style-icon"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
stroke="#888"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeDasharray="6 4"
|
||||
>
|
||||
<path d="M8 24 L40 24" />
|
||||
</svg>
|
||||
<Typography.Text className="section-heading-small">Dashed</Typography.Text>
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,52 +1,16 @@
|
||||
import {
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Dispatch, SetStateAction, useMemo } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import type { InputRef } from 'antd';
|
||||
import {
|
||||
AutoComplete,
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Switch,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { Typography } from 'antd';
|
||||
import { PrecisionOption, PrecisionOptionsEnum } from 'components/Graph/types';
|
||||
import TimePreference from 'components/TimePreferenceDropDown';
|
||||
import { PANEL_TYPES, PanelDisplay } from 'constants/queryBuilder';
|
||||
import {
|
||||
ItemsProps,
|
||||
PanelTypesWithData,
|
||||
} from 'container/DashboardContainer/PanelTypeSelectionModal/menuItems';
|
||||
import { PanelTypesWithData } from 'container/DashboardContainer/PanelTypeSelectionModal/menuItems';
|
||||
import { useDashboardVariables } from 'hooks/dashboard/useDashboardVariables';
|
||||
import useCreateAlerts from 'hooks/queryBuilder/useCreateAlerts';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import {
|
||||
FillMode,
|
||||
LineInterpolation,
|
||||
LineStyle,
|
||||
} from 'lib/uPlotV2/config/types';
|
||||
import {
|
||||
Antenna,
|
||||
Axis3D,
|
||||
ConciergeBell,
|
||||
Layers,
|
||||
LayoutDashboard,
|
||||
LineChart,
|
||||
Link,
|
||||
Paintbrush,
|
||||
Pencil,
|
||||
Plus,
|
||||
SlidersHorizontal,
|
||||
Spline,
|
||||
SquareArrowOutUpRight,
|
||||
} from 'lucide-react';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
import {
|
||||
ColumnUnit,
|
||||
@@ -55,11 +19,7 @@ import {
|
||||
Widgets,
|
||||
} from 'types/api/dashboard/getAll';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
import { ColumnUnitSelector } from './ColumnUnitSelector/ColumnUnitSelector';
|
||||
import SettingsSection from './components/SettingsSection/SettingsSection';
|
||||
import {
|
||||
panelTypeVsBucketConfig,
|
||||
panelTypeVsColumnUnitPreferences,
|
||||
@@ -80,32 +40,20 @@ import {
|
||||
panelTypeVsThreshold,
|
||||
panelTypeVsYAxisUnit,
|
||||
} from './constants';
|
||||
import ContextLinks from './ContextLinks';
|
||||
import DashboardYAxisUnitSelectorWrapper from './DashboardYAxisUnitSelectorWrapper';
|
||||
import { FillModeSelector } from './FillModeSelector';
|
||||
import LegendColors from './LegendColors/LegendColors';
|
||||
import { LineInterpolationSelector } from './LineInterpolationSelector';
|
||||
import { LineStyleSelector } from './LineStyleSelector';
|
||||
import ThresholdSelector from './Threshold/ThresholdSelector';
|
||||
import AlertsSection from './SettingSections/AlertsSection/AlertsSection';
|
||||
import AxesSection from './SettingSections/AxesSection/AxesSection';
|
||||
import ChartAppearanceSection from './SettingSections/ChartAppearanceSection/ChartAppearanceSection';
|
||||
import ContextLinksSection from './SettingSections/ContextLinksSection/ContextLinksSection';
|
||||
import FormattingUnitsSection from './SettingSections/FormattingUnitsSection/FormattingUnitsSection';
|
||||
import GeneralSettingsSection from './SettingSections/GeneralSettingsSection/GeneralSettingsSection';
|
||||
import HistogramBucketsSection from './SettingSections/HistogramBucketsSection/HistogramBucketsSection';
|
||||
import LegendSection from './SettingSections/LegendSection/LegendSection';
|
||||
import ThresholdsSection from './SettingSections/ThresholdsSection/ThresholdsSection';
|
||||
import VisualizationSettingsSection from './SettingSections/VisualizationSettingsSection/VisualizationSettingsSection';
|
||||
import { ThresholdProps } from './Threshold/types';
|
||||
import { timePreferance } from './timeItems';
|
||||
|
||||
import './RightContainer.styles.scss';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
|
||||
enum LogScale {
|
||||
LINEAR = 'linear',
|
||||
LOGARITHMIC = 'logarithmic',
|
||||
}
|
||||
|
||||
interface VariableOption {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
function RightContainer({
|
||||
description,
|
||||
setDescription,
|
||||
@@ -159,20 +107,10 @@ function RightContainer({
|
||||
isNewDashboard,
|
||||
}: RightContainerProps): JSX.Element {
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
const [inputValue, setInputValue] = useState(title);
|
||||
const [autoCompleteOpen, setAutoCompleteOpen] = useState(false);
|
||||
const [cursorPos, setCursorPos] = useState(0);
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
|
||||
const onChangeHandler = useCallback(
|
||||
(setFunc: Dispatch<SetStateAction<string>>, value: string) => {
|
||||
setFunc(value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const selectedGraphType =
|
||||
PanelTypesWithData.find((e) => e.name === selectedGraph)?.display || '';
|
||||
const selectedPanelDisplay = PanelTypesWithData.find(
|
||||
(e) => e.name === selectedGraph,
|
||||
)?.display as PanelDisplay;
|
||||
|
||||
const onCreateAlertsHandler = useCreateAlerts(selectedWidget, 'panelView');
|
||||
|
||||
@@ -201,16 +139,15 @@ function RightContainer({
|
||||
const allowFillMode = panelTypeVsFillMode[selectedGraph];
|
||||
const allowShowPoints = panelTypeVsShowPoints[selectedGraph];
|
||||
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
|
||||
const [graphTypes, setGraphTypes] = useState<ItemsProps[]>(PanelTypesWithData);
|
||||
|
||||
const dashboardVariableOptions = useMemo<VariableOption[]>(() => {
|
||||
return Object.entries(dashboardVariables).map(([, value]) => ({
|
||||
value: value.name || '',
|
||||
label: value.name || '',
|
||||
}));
|
||||
}, [dashboardVariables]);
|
||||
const decimapPrecisionOptions = useMemo(
|
||||
() => [
|
||||
{ label: '0 decimals', value: PrecisionOptionsEnum.ZERO },
|
||||
{ label: '1 decimal', value: PrecisionOptionsEnum.ONE },
|
||||
{ label: '2 decimals', value: PrecisionOptionsEnum.TWO },
|
||||
{ label: '3 decimals', value: PrecisionOptionsEnum.THREE },
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
const isAxisSectionVisible = useMemo(() => allowSoftMinMax || allowLogScale, [
|
||||
allowSoftMinMax,
|
||||
@@ -243,96 +180,6 @@ function RightContainer({
|
||||
[allowFillMode, allowLineStyle, allowLineInterpolation, allowShowPoints],
|
||||
);
|
||||
|
||||
const updateCursorAndDropdown = (value: string, pos: number): void => {
|
||||
setCursorPos(pos);
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
setAutoCompleteOpen(lastDollar !== -1 && pos >= lastDollar + 1);
|
||||
};
|
||||
|
||||
const onInputChange = (value: string): void => {
|
||||
setInputValue(value);
|
||||
onChangeHandler(setTitle, value);
|
||||
setTimeout(() => {
|
||||
const pos = inputRef.current?.input?.selectionStart ?? 0;
|
||||
updateCursorAndDropdown(value, pos);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const decimapPrecisionOptions = useMemo(() => {
|
||||
return [
|
||||
{ label: '0 decimals', value: PrecisionOptionsEnum.ZERO },
|
||||
{ label: '1 decimal', value: PrecisionOptionsEnum.ONE },
|
||||
{ label: '2 decimals', value: PrecisionOptionsEnum.TWO },
|
||||
{ label: '3 decimals', value: PrecisionOptionsEnum.THREE },
|
||||
];
|
||||
}, []);
|
||||
|
||||
const handleInputCursor = (): void => {
|
||||
const pos = inputRef.current?.input?.selectionStart ?? 0;
|
||||
updateCursorAndDropdown(inputValue, pos);
|
||||
};
|
||||
|
||||
const onSelect = (selectedValue: string): void => {
|
||||
const pos = cursorPos;
|
||||
const value = inputValue;
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
const textBeforeDollar = value.substring(0, lastDollar);
|
||||
const textAfterDollar = value.substring(lastDollar + 1);
|
||||
const match = textAfterDollar.match(/^([a-zA-Z0-9_.]*)/);
|
||||
const rest = textAfterDollar.substring(match ? match[1].length : 0);
|
||||
const newValue = `${textBeforeDollar}$${selectedValue}${rest}`;
|
||||
setInputValue(newValue);
|
||||
onChangeHandler(setTitle, newValue);
|
||||
setAutoCompleteOpen(false);
|
||||
setTimeout(() => {
|
||||
const newCursor = `${textBeforeDollar}$${selectedValue}`.length;
|
||||
inputRef.current?.input?.setSelectionRange(newCursor, newCursor);
|
||||
setCursorPos(newCursor);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const filterOption = (
|
||||
inputValue: string,
|
||||
option?: VariableOption,
|
||||
): boolean => {
|
||||
const pos = cursorPos;
|
||||
const value = inputValue;
|
||||
const lastDollar = value.lastIndexOf('$', pos - 1);
|
||||
if (lastDollar === -1) {
|
||||
return false;
|
||||
}
|
||||
const afterDollar = value.substring(lastDollar + 1, pos).toLowerCase();
|
||||
return option?.value.toLowerCase().startsWith(afterDollar) || false;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const queryContainsMetricsDataSource = currentQuery.builder.queryData.some(
|
||||
(query) => query.dataSource === DataSource.METRICS,
|
||||
);
|
||||
|
||||
if (queryContainsMetricsDataSource) {
|
||||
setGraphTypes((prev) =>
|
||||
prev.filter((graph) => graph.name !== PANEL_TYPES.LIST),
|
||||
);
|
||||
} else {
|
||||
setGraphTypes(PanelTypesWithData);
|
||||
}
|
||||
}, [currentQuery]);
|
||||
|
||||
const softMinHandler = useCallback(
|
||||
(value: number | null) => {
|
||||
setSoftMin(value);
|
||||
},
|
||||
[setSoftMin],
|
||||
);
|
||||
|
||||
const softMaxHandler = useCallback(
|
||||
(value: number | null) => {
|
||||
setSoftMax(value);
|
||||
},
|
||||
[setSoftMax],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="right-container">
|
||||
<section className="header">
|
||||
@@ -340,372 +187,120 @@ function RightContainer({
|
||||
<Typography.Text className="header-text">Panel Settings</Typography.Text>
|
||||
</section>
|
||||
|
||||
<SettingsSection title="General" defaultOpen icon={<Pencil size={14} />}>
|
||||
<section className="name-description control-container">
|
||||
<Typography.Text className="section-heading">Name</Typography.Text>
|
||||
<AutoComplete
|
||||
options={dashboardVariableOptions}
|
||||
value={inputValue}
|
||||
onChange={onInputChange}
|
||||
onSelect={onSelect}
|
||||
filterOption={filterOption}
|
||||
style={{ width: '100%' }}
|
||||
getPopupContainer={popupContainer}
|
||||
placeholder="Enter the panel name here..."
|
||||
open={autoCompleteOpen}
|
||||
>
|
||||
<Input
|
||||
rootClassName="name-input"
|
||||
ref={inputRef}
|
||||
onSelect={handleInputCursor}
|
||||
onClick={handleInputCursor}
|
||||
onBlur={(): void => setAutoCompleteOpen(false)}
|
||||
/>
|
||||
</AutoComplete>
|
||||
<Typography.Text className="section-heading">Description</Typography.Text>
|
||||
<TextArea
|
||||
placeholder="Enter the panel description here..."
|
||||
bordered
|
||||
allowClear
|
||||
value={description}
|
||||
onChange={(event): void =>
|
||||
onChangeHandler(setDescription, event.target.value)
|
||||
}
|
||||
rootClassName="description-input"
|
||||
/>
|
||||
</section>
|
||||
</SettingsSection>
|
||||
<GeneralSettingsSection
|
||||
title={title}
|
||||
setTitle={setTitle}
|
||||
description={description}
|
||||
setDescription={setDescription}
|
||||
dashboardVariables={dashboardVariables}
|
||||
/>
|
||||
|
||||
<section className="panel-config">
|
||||
<SettingsSection
|
||||
title="Visualization"
|
||||
defaultOpen
|
||||
icon={<LayoutDashboard size={14} />}
|
||||
>
|
||||
<section className="panel-type control-container">
|
||||
<Typography.Text className="section-heading">Panel Type</Typography.Text>
|
||||
<Select
|
||||
onChange={setGraphHandler}
|
||||
value={selectedGraph}
|
||||
className="panel-type-select"
|
||||
data-testid="panel-change-select"
|
||||
data-stacking-state={stackedBarChart ? 'true' : 'false'}
|
||||
>
|
||||
{graphTypes.map((item) => (
|
||||
<Option key={item.name} value={item.name}>
|
||||
<div className="select-option">
|
||||
<div className="icon">{item.icon}</div>
|
||||
<Typography.Text className="display">{item.display}</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</section>
|
||||
|
||||
{allowPanelTimePreference && (
|
||||
<section className="panel-time-preference control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Panel Time Preference
|
||||
</Typography.Text>
|
||||
<TimePreference
|
||||
{...{
|
||||
selectedTime,
|
||||
setSelectedTime,
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowStackingBarChart && (
|
||||
<section className="stack-chart control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Stack series
|
||||
</Typography.Text>
|
||||
<Switch
|
||||
checked={stackedBarChart}
|
||||
size="small"
|
||||
onChange={(checked): void => setStackedBarChart(checked)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowFillSpans && (
|
||||
<section className="fill-gaps toggle-card">
|
||||
<div className="toggle-card-text-container">
|
||||
<Typography className="section-heading">Fill gaps</Typography>
|
||||
<Typography.Text className="toggle-card-description">
|
||||
Fill gaps in data with 0 for continuity
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Switch
|
||||
checked={isFillSpans}
|
||||
size="small"
|
||||
onChange={(checked): void => setIsFillSpans(checked)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
<VisualizationSettingsSection
|
||||
selectedGraph={selectedGraph}
|
||||
setGraphHandler={setGraphHandler}
|
||||
selectedTime={selectedTime}
|
||||
setSelectedTime={setSelectedTime}
|
||||
stackedBarChart={stackedBarChart}
|
||||
setStackedBarChart={setStackedBarChart}
|
||||
isFillSpans={isFillSpans}
|
||||
setIsFillSpans={setIsFillSpans}
|
||||
allowPanelTimePreference={allowPanelTimePreference}
|
||||
allowStackingBarChart={allowStackingBarChart}
|
||||
allowFillSpans={allowFillSpans}
|
||||
/>
|
||||
|
||||
{isFormattingSectionVisible && (
|
||||
<SettingsSection
|
||||
title="Formatting & Units"
|
||||
icon={<SlidersHorizontal size={14} />}
|
||||
>
|
||||
{allowYAxisUnit && (
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
onSelect={setYAxisUnit}
|
||||
value={yAxisUnit || ''}
|
||||
fieldLabel={
|
||||
selectedGraphType === PanelDisplay.VALUE ||
|
||||
selectedGraphType === PanelDisplay.PIE
|
||||
? 'Unit'
|
||||
: 'Y Axis Unit'
|
||||
}
|
||||
// Only update the y-axis unit value automatically in create mode
|
||||
shouldUpdateYAxisUnit={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
|
||||
{allowDecimalPrecision && (
|
||||
<section className="decimal-precision-selector control-container">
|
||||
<Typography.Text className="typography">
|
||||
Decimal Precision
|
||||
</Typography.Text>
|
||||
<Select
|
||||
options={decimapPrecisionOptions}
|
||||
value={decimalPrecision}
|
||||
style={{ width: '100%' }}
|
||||
className="panel-type-select"
|
||||
defaultValue={PrecisionOptionsEnum.TWO}
|
||||
onChange={(val: PrecisionOption): void => setDecimalPrecision(val)}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowPanelColumnPreference && (
|
||||
<ColumnUnitSelector
|
||||
columnUnits={columnUnits}
|
||||
setColumnUnits={setColumnUnits}
|
||||
isNewDashboard={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
</SettingsSection>
|
||||
<FormattingUnitsSection
|
||||
selectedPanelDisplay={selectedPanelDisplay}
|
||||
yAxisUnit={yAxisUnit}
|
||||
setYAxisUnit={setYAxisUnit}
|
||||
isNewDashboard={isNewDashboard}
|
||||
decimalPrecision={decimalPrecision}
|
||||
setDecimalPrecision={setDecimalPrecision}
|
||||
columnUnits={columnUnits}
|
||||
setColumnUnits={setColumnUnits}
|
||||
allowYAxisUnit={allowYAxisUnit}
|
||||
allowDecimalPrecision={allowDecimalPrecision}
|
||||
allowPanelColumnPreference={allowPanelColumnPreference}
|
||||
decimapPrecisionOptions={decimapPrecisionOptions}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isChartAppearanceSectionVisible && (
|
||||
<SettingsSection title="Chart Appearance" icon={<Paintbrush size={14} />}>
|
||||
{allowFillMode && (
|
||||
<FillModeSelector value={fillMode} onChange={setFillMode} />
|
||||
)}
|
||||
{allowLineStyle && (
|
||||
<LineStyleSelector value={lineStyle} onChange={setLineStyle} />
|
||||
)}
|
||||
{allowLineInterpolation && (
|
||||
<LineInterpolationSelector
|
||||
value={lineInterpolation}
|
||||
onChange={setLineInterpolation}
|
||||
/>
|
||||
)}
|
||||
{allowShowPoints && (
|
||||
<section className="show-points toggle-card">
|
||||
<div className="toggle-card-text-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Show points
|
||||
</Typography.Text>
|
||||
<Typography.Text className="toggle-card-description">
|
||||
Display individual data points on the chart
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Switch size="small" checked={showPoints} onChange={setShowPoints} />
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
<ChartAppearanceSection
|
||||
fillMode={fillMode}
|
||||
setFillMode={setFillMode}
|
||||
lineStyle={lineStyle}
|
||||
setLineStyle={setLineStyle}
|
||||
lineInterpolation={lineInterpolation}
|
||||
setLineInterpolation={setLineInterpolation}
|
||||
showPoints={showPoints}
|
||||
setShowPoints={setShowPoints}
|
||||
allowFillMode={allowFillMode}
|
||||
allowLineStyle={allowLineStyle}
|
||||
allowLineInterpolation={allowLineInterpolation}
|
||||
allowShowPoints={allowShowPoints}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isAxisSectionVisible && (
|
||||
<SettingsSection title="Axes" icon={<Axis3D size={14} />}>
|
||||
{allowSoftMinMax && (
|
||||
<section className="soft-min-max">
|
||||
<section className="container">
|
||||
<Typography.Text className="text">Soft Min</Typography.Text>
|
||||
<InputNumber
|
||||
type="number"
|
||||
value={softMin}
|
||||
onChange={softMinHandler}
|
||||
rootClassName="input"
|
||||
/>
|
||||
</section>
|
||||
<section className="container">
|
||||
<Typography.Text className="text">Soft Max</Typography.Text>
|
||||
<InputNumber
|
||||
value={softMax}
|
||||
type="number"
|
||||
rootClassName="input"
|
||||
onChange={softMaxHandler}
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowLogScale && (
|
||||
<section className="log-scale control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Y Axis Scale
|
||||
</Typography.Text>
|
||||
<Select
|
||||
onChange={(value): void =>
|
||||
setIsLogScale(value === LogScale.LOGARITHMIC)
|
||||
}
|
||||
value={isLogScale ? LogScale.LOGARITHMIC : LogScale.LINEAR}
|
||||
style={{ width: '100%' }}
|
||||
className="panel-type-select"
|
||||
defaultValue={LogScale.LINEAR}
|
||||
>
|
||||
<Option value={LogScale.LINEAR}>
|
||||
<div className="select-option">
|
||||
<div className="icon">
|
||||
<LineChart size={16} />
|
||||
</div>
|
||||
<Typography.Text className="display">Linear</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value={LogScale.LOGARITHMIC}>
|
||||
<div className="select-option">
|
||||
<div className="icon">
|
||||
<Spline size={16} />
|
||||
</div>
|
||||
<Typography.Text className="display">Logarithmic</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
</Select>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
<AxesSection
|
||||
allowSoftMinMax={allowSoftMinMax}
|
||||
allowLogScale={allowLogScale}
|
||||
softMin={softMin}
|
||||
softMax={softMax}
|
||||
setSoftMin={setSoftMin}
|
||||
setSoftMax={setSoftMax}
|
||||
isLogScale={isLogScale}
|
||||
setIsLogScale={setIsLogScale}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isLegendSectionVisible && (
|
||||
<SettingsSection title="Legend" icon={<Layers size={14} />}>
|
||||
{allowLegendPosition && (
|
||||
<section className="legend-position control-container">
|
||||
<Typography.Text className="section-heading">Position</Typography.Text>
|
||||
<Select
|
||||
onChange={(value: LegendPosition): void => setLegendPosition(value)}
|
||||
value={legendPosition}
|
||||
style={{ width: '100%' }}
|
||||
className="panel-type-select"
|
||||
defaultValue={LegendPosition.BOTTOM}
|
||||
>
|
||||
<Option value={LegendPosition.BOTTOM}>
|
||||
<div className="select-option">
|
||||
<Typography.Text className="display">Bottom</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value={LegendPosition.RIGHT}>
|
||||
<div className="select-option">
|
||||
<Typography.Text className="display">Right</Typography.Text>
|
||||
</div>
|
||||
</Option>
|
||||
</Select>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{allowLegendColors && (
|
||||
<section className="legend-colors">
|
||||
<LegendColors
|
||||
customLegendColors={customLegendColors}
|
||||
setCustomLegendColors={setCustomLegendColors}
|
||||
queryResponse={queryResponse}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</SettingsSection>
|
||||
<LegendSection
|
||||
allowLegendPosition={allowLegendPosition}
|
||||
allowLegendColors={allowLegendColors}
|
||||
legendPosition={legendPosition}
|
||||
setLegendPosition={setLegendPosition}
|
||||
customLegendColors={customLegendColors}
|
||||
setCustomLegendColors={setCustomLegendColors}
|
||||
queryResponse={queryResponse}
|
||||
/>
|
||||
)}
|
||||
|
||||
{allowBucketConfig && (
|
||||
<SettingsSection title="Histogram / Buckets">
|
||||
<section className="bucket-config control-container">
|
||||
<Typography.Text className="section-heading">
|
||||
Number of buckets
|
||||
</Typography.Text>
|
||||
<InputNumber
|
||||
value={bucketCount || null}
|
||||
type="number"
|
||||
min={0}
|
||||
rootClassName="bucket-input"
|
||||
placeholder="Default: 30"
|
||||
onChange={(val): void => {
|
||||
setBucketCount(val || 0);
|
||||
}}
|
||||
/>
|
||||
<Typography.Text className="section-heading bucket-size-label">
|
||||
Bucket width
|
||||
</Typography.Text>
|
||||
<InputNumber
|
||||
value={bucketWidth || null}
|
||||
type="number"
|
||||
precision={2}
|
||||
placeholder="Default: Auto"
|
||||
step={0.1}
|
||||
min={0.0}
|
||||
rootClassName="bucket-input"
|
||||
onChange={(val): void => {
|
||||
setBucketWidth(val || 0);
|
||||
}}
|
||||
/>
|
||||
<section className="combine-hist">
|
||||
<Typography.Text className="section-heading">
|
||||
Merge all series into one
|
||||
</Typography.Text>
|
||||
<Switch
|
||||
checked={combineHistogram}
|
||||
size="small"
|
||||
onChange={(checked): void => setCombineHistogram(checked)}
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
</SettingsSection>
|
||||
<HistogramBucketsSection
|
||||
bucketCount={bucketCount}
|
||||
setBucketCount={setBucketCount}
|
||||
bucketWidth={bucketWidth}
|
||||
setBucketWidth={setBucketWidth}
|
||||
combineHistogram={combineHistogram}
|
||||
setCombineHistogram={setCombineHistogram}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{allowCreateAlerts && (
|
||||
<section className="alerts" onClick={onCreateAlertsHandler}>
|
||||
<div className="left-section">
|
||||
<ConciergeBell size={14} className="bell-icon" />
|
||||
<Typography.Text className="alerts-text">Alerts</Typography.Text>
|
||||
<SquareArrowOutUpRight size={10} className="info-icon" />
|
||||
</div>
|
||||
<Plus size={14} className="plus-icon" />
|
||||
</section>
|
||||
<AlertsSection onCreateAlertsHandler={onCreateAlertsHandler} />
|
||||
)}
|
||||
|
||||
{allowContextLinks && (
|
||||
<SettingsSection
|
||||
title="Context Links"
|
||||
icon={<Link size={14} />}
|
||||
defaultOpen={!!contextLinks.linksData.length}
|
||||
>
|
||||
<ContextLinks
|
||||
contextLinks={contextLinks}
|
||||
setContextLinks={setContextLinks}
|
||||
selectedWidget={selectedWidget}
|
||||
/>
|
||||
</SettingsSection>
|
||||
<ContextLinksSection
|
||||
contextLinks={contextLinks}
|
||||
setContextLinks={setContextLinks}
|
||||
selectedWidget={selectedWidget}
|
||||
/>
|
||||
)}
|
||||
|
||||
{allowThreshold && (
|
||||
<SettingsSection
|
||||
title="Thresholds"
|
||||
icon={<Antenna size={14} />}
|
||||
defaultOpen={!!thresholds.length}
|
||||
>
|
||||
<ThresholdSelector
|
||||
thresholds={thresholds}
|
||||
setThresholds={setThresholds}
|
||||
yAxisUnit={yAxisUnit}
|
||||
selectedGraph={selectedGraph}
|
||||
columnUnits={columnUnits}
|
||||
/>
|
||||
</SettingsSection>
|
||||
<ThresholdsSection
|
||||
thresholds={thresholds}
|
||||
setThresholds={setThresholds}
|
||||
yAxisUnit={yAxisUnit}
|
||||
selectedGraph={selectedGraph}
|
||||
columnUnits={columnUnits}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
usePatchRole,
|
||||
} from 'api/generated/services/role';
|
||||
import {
|
||||
AuthtypesPostableRoleDTO,
|
||||
RenderErrorResponseDTO,
|
||||
RoletypesPostableRoleDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { ErrorType } from 'api/generatedAPIInstance';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -114,7 +114,7 @@ function CreateRoleModal({
|
||||
data: { description: values.description || '' },
|
||||
});
|
||||
} else {
|
||||
const data: RoletypesPostableRoleDTO = {
|
||||
const data: AuthtypesPostableRoleDTO = {
|
||||
name: values.name,
|
||||
...(values.description ? { description: values.description } : {}),
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Pagination, Skeleton } from 'antd';
|
||||
import { useListRoles } from 'api/generated/services/role';
|
||||
import { RoletypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { AuthtypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -20,7 +20,7 @@ const PAGE_SIZE = 20;
|
||||
|
||||
type DisplayItem =
|
||||
| { type: 'section'; label: string; count?: number }
|
||||
| { type: 'role'; role: RoletypesRoleDTO };
|
||||
| { type: 'role'; role: AuthtypesRoleDTO };
|
||||
|
||||
interface RolesListingTableProps {
|
||||
searchQuery: string;
|
||||
@@ -187,7 +187,7 @@ function RolesListingTable({
|
||||
};
|
||||
|
||||
// todo: use table from periscope when its available for consumption
|
||||
const renderRow = (role: RoletypesRoleDTO): JSX.Element => (
|
||||
const renderRow = (role: AuthtypesRoleDTO): JSX.Element => (
|
||||
<div
|
||||
key={role.id}
|
||||
className={`roles-table-row ${
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { RoletypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { AuthtypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
const orgId = '019ba2bb-2fa1-7b24-8159-cfca08617ef9';
|
||||
|
||||
export const managedRoles: RoletypesRoleDTO[] = [
|
||||
export const managedRoles: AuthtypesRoleDTO[] = [
|
||||
{
|
||||
id: '019c24aa-2248-756f-9833-984f1ab63819',
|
||||
createdAt: new Date('2026-02-03T18:00:55.624356Z'),
|
||||
@@ -35,7 +35,7 @@ export const managedRoles: RoletypesRoleDTO[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const customRoles: RoletypesRoleDTO[] = [
|
||||
export const customRoles: AuthtypesRoleDTO[] = [
|
||||
{
|
||||
id: '019c24aa-3333-0001-aaaa-111111111111',
|
||||
createdAt: new Date('2026-02-10T10:30:00.000Z'),
|
||||
@@ -56,7 +56,7 @@ export const customRoles: RoletypesRoleDTO[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const allRoles: RoletypesRoleDTO[] = [...managedRoles, ...customRoles];
|
||||
export const allRoles: AuthtypesRoleDTO[] = [...managedRoles, ...customRoles];
|
||||
|
||||
export const listRolesSuccessResponse = {
|
||||
status: 'success',
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -22,7 +21,7 @@ func (provider *provider) addAuthDomainRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +38,7 @@ func (provider *provider) addAuthDomainRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,7 +55,7 @@ func (provider *provider) addAuthDomainRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +72,7 @@ func (provider *provider) addAuthDomainRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func (provider *provider) addDashboardRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (provider *provider) addDashboardRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func (provider *provider) addDashboardRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func (provider *provider) addDashboardRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ func (provider *provider) addFieldsRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func (provider *provider) addFieldsRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -22,7 +22,7 @@ func (provider *provider) addFlaggerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/gatewaytypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,7 +143,7 @@ func (provider *provider) addGatewayRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@@ -21,7 +22,7 @@ func (provider *provider) addGlobalRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleEditor),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/metricsexplorertypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -25,7 +25,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleEditor),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func (provider *provider) addMetricsExplorerRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@@ -21,7 +22,7 @@ func (provider *provider) addOrgRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -38,7 +39,7 @@ func (provider *provider) addOrgRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusConflict, http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -22,7 +22,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func (provider *provider) addPreferenceRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/promotetypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -21,7 +21,7 @@ func (provider *provider) addPromoteRoutes(router *mux.Router) error {
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleEditor),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleEditor),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func (provider *provider) addPromoteRoutes(router *mux.Router) error {
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/zeus"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -236,15 +235,15 @@ func (provider *provider) AddToRouter(router *mux.Router) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newSecuritySchemes(role types.Role) []handler.OpenAPISecurityScheme {
|
||||
func newSecuritySchemes(role authtypes.LegacyRole) []handler.OpenAPISecurityScheme {
|
||||
return []handler.OpenAPISecurityScheme{
|
||||
{Name: ctxtypes.AuthTypeAPIKey.StringValue(), Scopes: []string{role.String()}},
|
||||
{Name: ctxtypes.AuthTypeTokenizer.StringValue(), Scopes: []string{role.String()}},
|
||||
{Name: authtypes.IdentNProviderAPIkey.StringValue(), Scopes: []string{role.String()}},
|
||||
{Name: authtypes.IdentNProviderTokenizer.StringValue(), Scopes: []string{role.String()}},
|
||||
}
|
||||
}
|
||||
|
||||
func newAnonymousSecuritySchemes(scopes []string) []handler.OpenAPISecurityScheme {
|
||||
return []handler.OpenAPISecurityScheme{
|
||||
{Name: ctxtypes.AuthTypeAnonymous.StringValue(), Scopes: scopes},
|
||||
{Name: authtypes.IdentNProviderAnonymous.StringValue(), Scopes: scopes},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -446,7 +446,7 @@ func (provider *provider) addQuerierRoutes(router *mux.Router) error {
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -462,7 +462,7 @@ func (provider *provider) addQuerierRoutes(router *mux.Router) error {
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleViewer),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@@ -16,14 +15,14 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Tags: []string{"role"},
|
||||
Summary: "Create role",
|
||||
Description: "This endpoint creates a role",
|
||||
Request: new(roletypes.PostableRole),
|
||||
Request: new(authtypes.PostableRole),
|
||||
RequestContentType: "",
|
||||
Response: new(types.Identifiable),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -35,12 +34,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint lists all roles",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*roletypes.Role, 0),
|
||||
Response: make([]*authtypes.Role, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -52,12 +51,12 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint gets a role",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(roletypes.Role),
|
||||
Response: new(authtypes.Role),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -74,7 +73,7 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,14 +83,14 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
Tags: []string{"role"},
|
||||
Summary: "Patch role",
|
||||
Description: "This endpoint patches a role",
|
||||
Request: new(roletypes.PatchableRole),
|
||||
Request: new(authtypes.PatchableRole),
|
||||
RequestContentType: "",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -108,7 +107,7 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPatch).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -125,7 +124,7 @@ func (provider *provider) addRoleRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusNotImplemented, http.StatusUnavailableForLegalReasons},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/serviceaccounttypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -22,7 +23,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +40,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,7 +57,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +74,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,7 +91,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound, http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +108,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -124,7 +125,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +142,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -158,7 +159,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -175,7 +176,7 @@ func (provider *provider) addServiceAccountRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@@ -73,7 +72,7 @@ func (provider *provider) addSessionRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: []handler.OpenAPISecurityScheme{{Name: ctxtypes.AuthTypeTokenizer.StringValue()}},
|
||||
SecuritySchemes: []handler.OpenAPISecurityScheme{{Name: authtypes.IdentNProviderTokenizer.StringValue()}},
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@@ -15,14 +15,14 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Create invite",
|
||||
Description: "This endpoint creates an invite for a user",
|
||||
Request: new(types.PostableInvite),
|
||||
Request: new(usertypes.PostableInvite),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(types.Invite),
|
||||
Response: new(usertypes.Invite),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -32,13 +32,13 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Create bulk invite",
|
||||
Description: "This endpoint creates a bulk invite for a user",
|
||||
Request: new(types.PostableBulkInviteRequest),
|
||||
Request: new(usertypes.PostableBulkInviteRequest),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint gets an invite by token",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(types.Invite),
|
||||
Response: new(usertypes.Invite),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
@@ -72,7 +72,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,12 +84,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint lists all invites",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*types.Invite, 0),
|
||||
Response: make([]*usertypes.Invite, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -99,9 +99,9 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Accept invite",
|
||||
Description: "This endpoint accepts an invite by token",
|
||||
Request: new(types.PostableAcceptInvite),
|
||||
Request: new(usertypes.PostableAcceptInvite),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(types.User),
|
||||
Response: new(usertypes.User),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
@@ -116,14 +116,14 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Create api key",
|
||||
Description: "This endpoint creates an api key",
|
||||
Request: new(types.PostableAPIKey),
|
||||
Request: new(usertypes.PostableAPIKey),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(types.GettableAPIKey),
|
||||
Response: new(usertypes.GettableAPIKey),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusCreated,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -135,12 +135,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint lists all api keys",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*types.GettableAPIKey, 0),
|
||||
Response: make([]*usertypes.GettableAPIKey, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -150,14 +150,14 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Update api key",
|
||||
Description: "This endpoint updates an api key",
|
||||
Request: new(types.StorableAPIKey),
|
||||
Request: new(usertypes.StorableAPIKey),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,12 +186,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint lists all users",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: make([]*types.GettableUser, 0),
|
||||
Response: make([]*usertypes.User, 0),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -203,12 +203,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint returns the user I belong to",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(types.GettableUser),
|
||||
Response: new(usertypes.User),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: []handler.OpenAPISecurityScheme{{Name: ctxtypes.AuthTypeTokenizer.StringValue()}},
|
||||
SecuritySchemes: []handler.OpenAPISecurityScheme{{Name: authtypes.IdentNProviderTokenizer.StringValue()}},
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -220,12 +220,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint returns the user by id",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(types.GettableUser),
|
||||
Response: new(usertypes.User),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -235,14 +235,14 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Update user",
|
||||
Description: "This endpoint updates the user by id",
|
||||
Request: new(types.User),
|
||||
Request: new(usertypes.UpdatableUser),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(types.GettableUser),
|
||||
Response: new(usertypes.User),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodDelete).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -271,12 +271,12 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Description: "This endpoint returns the reset password token by id",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(types.ResetPasswordToken),
|
||||
Response: new(usertypes.ResetPasswordToken),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -286,7 +286,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Reset password",
|
||||
Description: "This endpoint resets the password by token",
|
||||
Request: new(types.PostableResetPassword),
|
||||
Request: new(usertypes.PostableResetPassword),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
@@ -303,14 +303,14 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Change password",
|
||||
Description: "This endpoint changes the password by id",
|
||||
Request: new(types.ChangePasswordRequest),
|
||||
Request: new(usertypes.ChangePasswordRequest),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPost).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -320,7 +320,7 @@ func (provider *provider) addUserRoutes(router *mux.Router) error {
|
||||
Tags: []string{"users"},
|
||||
Summary: "Forgot password",
|
||||
Description: "This endpoint initiates the forgot password flow by sending a reset password email",
|
||||
Request: new(types.PostableForgotPassword),
|
||||
Request: new(usertypes.PostableForgotPassword),
|
||||
RequestContentType: "application/json",
|
||||
Response: nil,
|
||||
ResponseContentType: "",
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/http/handler"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/zeustypes"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -22,7 +22,7 @@ func (provider *provider) addZeusRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func (provider *provider) addZeusRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func (provider *provider) addZeusRoutes(router *mux.Router) error {
|
||||
SuccessStatusCode: http.StatusNoContent,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound, http.StatusConflict},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
SecuritySchemes: newSecuritySchemes(authtypes.RoleAdmin),
|
||||
})).Methods(http.MethodPut).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
@@ -17,37 +16,6 @@ func NewStore(sqlstore sqlstore.SQLStore) authtypes.AuthNStore {
|
||||
return &store{sqlstore: sqlstore}
|
||||
}
|
||||
|
||||
func (store *store) GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx context.Context, email string, orgID valuer.UUID) (*types.User, *types.FactorPassword, error) {
|
||||
user := new(types.User)
|
||||
factorPassword := new(types.FactorPassword)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(user).
|
||||
Where("email = ?", email).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("status = ?", types.UserStatusActive.StringValue()).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "user with email %s in org %s not found", email, orgID)
|
||||
}
|
||||
|
||||
err = store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(factorPassword).
|
||||
Where("user_id = ?", user.ID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodePasswordNotFound, "user with email %s in org %s does not have password", email, orgID)
|
||||
}
|
||||
|
||||
return user, factorPassword, nil
|
||||
}
|
||||
|
||||
func (store *store) GetAuthDomainFromID(ctx context.Context, domainID valuer.UUID) (*authtypes.AuthDomain, error) {
|
||||
storableAuthDomain := new(authtypes.StorableAuthDomain)
|
||||
|
||||
|
||||
@@ -5,30 +5,31 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/authn"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
var _ authn.PasswordAuthN = (*AuthN)(nil)
|
||||
|
||||
type AuthN struct {
|
||||
store authtypes.AuthNStore
|
||||
userGetter user.Getter
|
||||
}
|
||||
|
||||
func New(store authtypes.AuthNStore) *AuthN {
|
||||
return &AuthN{store: store}
|
||||
func New(userGetter user.Getter) *AuthN {
|
||||
return &AuthN{userGetter: userGetter}
|
||||
}
|
||||
|
||||
func (a *AuthN) Authenticate(ctx context.Context, email string, password string, orgID valuer.UUID) (*authtypes.Identity, error) {
|
||||
user, factorPassword, err := a.store.GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx, email, orgID)
|
||||
user, factorPassword, err := a.userGetter.GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx, email, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !factorPassword.Equals(password) {
|
||||
return nil, errors.New(errors.TypeUnauthenticated, types.ErrCodeIncorrectPassword, "invalid email or password")
|
||||
return nil, errors.New(errors.TypeUnauthenticated, usertypes.ErrCodeIncorrectPassword, "invalid email or password")
|
||||
}
|
||||
|
||||
return authtypes.NewIdentity(user.ID, orgID, user.Email, user.Role), nil
|
||||
return authtypes.NewIdentity(user.ID, orgID, user.Email, user.Role, authtypes.IdentNProviderTokenizer), nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
)
|
||||
@@ -30,10 +29,10 @@ type AuthZ interface {
|
||||
ListObjects(context.Context, string, authtypes.Relation, authtypes.Typeable) ([]*authtypes.Object, error)
|
||||
|
||||
// Creates the role.
|
||||
Create(context.Context, valuer.UUID, *roletypes.Role) error
|
||||
Create(context.Context, valuer.UUID, *authtypes.Role) error
|
||||
|
||||
// Gets the role if it exists or creates one.
|
||||
GetOrCreate(context.Context, valuer.UUID, *roletypes.Role) (*roletypes.Role, error)
|
||||
GetOrCreate(context.Context, valuer.UUID, *authtypes.Role) (*authtypes.Role, error)
|
||||
|
||||
// Gets the objects associated with the given role and relation.
|
||||
GetObjects(context.Context, valuer.UUID, valuer.UUID, authtypes.Relation) ([]*authtypes.Object, error)
|
||||
@@ -42,7 +41,7 @@ type AuthZ interface {
|
||||
GetResources(context.Context) []*authtypes.Resource
|
||||
|
||||
// Patches the role.
|
||||
Patch(context.Context, valuer.UUID, *roletypes.Role) error
|
||||
Patch(context.Context, valuer.UUID, *authtypes.Role) error
|
||||
|
||||
// Patches the objects in authorization server associated with the given role and relation
|
||||
PatchObjects(context.Context, valuer.UUID, string, authtypes.Relation, []*authtypes.Object, []*authtypes.Object) error
|
||||
@@ -51,19 +50,19 @@ type AuthZ interface {
|
||||
Delete(context.Context, valuer.UUID, valuer.UUID) error
|
||||
|
||||
// Gets the role
|
||||
Get(context.Context, valuer.UUID, valuer.UUID) (*roletypes.Role, error)
|
||||
Get(context.Context, valuer.UUID, valuer.UUID) (*authtypes.Role, error)
|
||||
|
||||
// Gets the role by org_id and name
|
||||
GetByOrgIDAndName(context.Context, valuer.UUID, string) (*roletypes.Role, error)
|
||||
GetByOrgIDAndName(context.Context, valuer.UUID, string) (*authtypes.Role, error)
|
||||
|
||||
// Lists all the roles for the organization.
|
||||
List(context.Context, valuer.UUID) ([]*roletypes.Role, error)
|
||||
List(context.Context, valuer.UUID) ([]*authtypes.Role, error)
|
||||
|
||||
// Lists all the roles for the organization filtered by name
|
||||
ListByOrgIDAndNames(context.Context, valuer.UUID, []string) ([]*roletypes.Role, error)
|
||||
ListByOrgIDAndNames(context.Context, valuer.UUID, []string) ([]*authtypes.Role, error)
|
||||
|
||||
// Lists all the roles for the organization filtered by ids
|
||||
ListByOrgIDAndIDs(context.Context, valuer.UUID, []valuer.UUID) ([]*roletypes.Role, error)
|
||||
ListByOrgIDAndIDs(context.Context, valuer.UUID, []valuer.UUID) ([]*authtypes.Role, error)
|
||||
|
||||
// Grants a role to the subject based on role name.
|
||||
Grant(context.Context, valuer.UUID, []string, string) error
|
||||
@@ -75,7 +74,7 @@ type AuthZ interface {
|
||||
ModifyGrant(context.Context, valuer.UUID, []string, []string, string) error
|
||||
|
||||
// Bootstrap the managed roles.
|
||||
CreateManagedRoles(context.Context, valuer.UUID, []*roletypes.Role) error
|
||||
CreateManagedRoles(context.Context, valuer.UUID, []*authtypes.Role) error
|
||||
|
||||
// Bootstrap managed roles transactions and user assignments
|
||||
CreateManagedUserRoleTransactions(context.Context, valuer.UUID, valuer.UUID) error
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -14,11 +14,11 @@ type store struct {
|
||||
sqlstore sqlstore.SQLStore
|
||||
}
|
||||
|
||||
func NewSqlAuthzStore(sqlstore sqlstore.SQLStore) roletypes.Store {
|
||||
func NewSqlAuthzStore(sqlstore sqlstore.SQLStore) authtypes.RoleStore {
|
||||
return &store{sqlstore: sqlstore}
|
||||
}
|
||||
|
||||
func (store *store) Create(ctx context.Context, role *roletypes.StorableRole) error {
|
||||
func (store *store) Create(ctx context.Context, role *authtypes.StorableRole) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -32,8 +32,8 @@ func (store *store) Create(ctx context.Context, role *roletypes.StorableRole) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*roletypes.StorableRole, error) {
|
||||
role := new(roletypes.StorableRole)
|
||||
func (store *store) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*authtypes.StorableRole, error) {
|
||||
role := new(authtypes.StorableRole)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -43,14 +43,14 @@ func (store *store) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID)
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, roletypes.ErrCodeRoleNotFound, "role with id: %s doesn't exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, authtypes.ErrCodeRoleNotFound, "role with id: %s doesn't exist", id)
|
||||
}
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (store *store) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*roletypes.StorableRole, error) {
|
||||
role := new(roletypes.StorableRole)
|
||||
func (store *store) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*authtypes.StorableRole, error) {
|
||||
role := new(authtypes.StorableRole)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -60,14 +60,14 @@ func (store *store) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, na
|
||||
Where("name = ?", name).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, roletypes.ErrCodeRoleNotFound, "role with name: %s doesn't exist", name)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, authtypes.ErrCodeRoleNotFound, "role with name: %s doesn't exist", name)
|
||||
}
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*roletypes.StorableRole, error) {
|
||||
roles := make([]*roletypes.StorableRole, 0)
|
||||
func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*authtypes.StorableRole, error) {
|
||||
roles := make([]*authtypes.StorableRole, 0)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -82,8 +82,8 @@ func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*roletypes.S
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (store *store) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*roletypes.StorableRole, error) {
|
||||
roles := make([]*roletypes.StorableRole, 0)
|
||||
func (store *store) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*authtypes.StorableRole, error) {
|
||||
roles := make([]*authtypes.StorableRole, 0)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -99,7 +99,7 @@ func (store *store) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID,
|
||||
if len(roles) != len(names) {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(
|
||||
nil,
|
||||
roletypes.ErrCodeRoleNotFound,
|
||||
authtypes.ErrCodeRoleNotFound,
|
||||
"not all roles found for the provided names: %v", names,
|
||||
)
|
||||
}
|
||||
@@ -107,8 +107,8 @@ func (store *store) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID,
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (store *store) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.StorableRole, error) {
|
||||
roles := make([]*roletypes.StorableRole, 0)
|
||||
func (store *store) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*authtypes.StorableRole, error) {
|
||||
roles := make([]*authtypes.StorableRole, 0)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -124,7 +124,7 @@ func (store *store) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, id
|
||||
if len(roles) != len(ids) {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(
|
||||
nil,
|
||||
roletypes.ErrCodeRoleNotFound,
|
||||
authtypes.ErrCodeRoleNotFound,
|
||||
"not all roles found for the provided ids: %v", ids,
|
||||
)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (store *store) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, id
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (store *store) Update(ctx context.Context, orgID valuer.UUID, role *roletypes.StorableRole) error {
|
||||
func (store *store) Update(ctx context.Context, orgID valuer.UUID, role *authtypes.StorableRole) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -153,12 +153,12 @@ func (store *store) Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUI
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewDelete().
|
||||
Model(new(roletypes.StorableRole)).
|
||||
Model(new(authtypes.StorableRole)).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapNotFoundErrf(err, roletypes.ErrCodeRoleNotFound, "role with id %s doesn't exist", id)
|
||||
return store.sqlstore.WrapNotFoundErrf(err, authtypes.ErrCodeRoleNotFound, "role with id %s doesn't exist", id)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/authz/openfgaserver"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
@@ -19,7 +18,7 @@ import (
|
||||
|
||||
type provider struct {
|
||||
server *openfgaserver.Server
|
||||
store roletypes.Store
|
||||
store authtypes.RoleStore
|
||||
}
|
||||
|
||||
func NewProviderFactory(sqlstore sqlstore.SQLStore, openfgaSchema []openfgapkgtransformer.ModuleFile) factory.ProviderFactory[authz.AuthZ, authz.Config] {
|
||||
@@ -68,61 +67,61 @@ func (provider *provider) ListObjects(ctx context.Context, subject string, relat
|
||||
return provider.server.ListObjects(ctx, subject, relation, typeable)
|
||||
}
|
||||
|
||||
func (provider *provider) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*roletypes.Role, error) {
|
||||
func (provider *provider) Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*authtypes.Role, error) {
|
||||
storableRole, err := provider.store.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return roletypes.NewRoleFromStorableRole(storableRole), nil
|
||||
return authtypes.NewRoleFromStorableRole(storableRole), nil
|
||||
}
|
||||
|
||||
func (provider *provider) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*roletypes.Role, error) {
|
||||
func (provider *provider) GetByOrgIDAndName(ctx context.Context, orgID valuer.UUID, name string) (*authtypes.Role, error) {
|
||||
storableRole, err := provider.store.GetByOrgIDAndName(ctx, orgID, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return roletypes.NewRoleFromStorableRole(storableRole), nil
|
||||
return authtypes.NewRoleFromStorableRole(storableRole), nil
|
||||
}
|
||||
|
||||
func (provider *provider) List(ctx context.Context, orgID valuer.UUID) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) List(ctx context.Context, orgID valuer.UUID) ([]*authtypes.Role, error) {
|
||||
storableRoles, err := provider.store.List(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roles := make([]*roletypes.Role, len(storableRoles))
|
||||
roles := make([]*authtypes.Role, len(storableRoles))
|
||||
for idx, storableRole := range storableRoles {
|
||||
roles[idx] = roletypes.NewRoleFromStorableRole(storableRole)
|
||||
roles[idx] = authtypes.NewRoleFromStorableRole(storableRole)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) ListByOrgIDAndNames(ctx context.Context, orgID valuer.UUID, names []string) ([]*authtypes.Role, error) {
|
||||
storableRoles, err := provider.store.ListByOrgIDAndNames(ctx, orgID, names)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roles := make([]*roletypes.Role, len(storableRoles))
|
||||
roles := make([]*authtypes.Role, len(storableRoles))
|
||||
for idx, storable := range storableRoles {
|
||||
roles[idx] = roletypes.NewRoleFromStorableRole(storable)
|
||||
roles[idx] = authtypes.NewRoleFromStorableRole(storable)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*roletypes.Role, error) {
|
||||
func (provider *provider) ListByOrgIDAndIDs(ctx context.Context, orgID valuer.UUID, ids []valuer.UUID) ([]*authtypes.Role, error) {
|
||||
storableRoles, err := provider.store.ListByOrgIDAndIDs(ctx, orgID, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roles := make([]*roletypes.Role, len(storableRoles))
|
||||
roles := make([]*authtypes.Role, len(storableRoles))
|
||||
for idx, storable := range storableRoles {
|
||||
roles[idx] = roletypes.NewRoleFromStorableRole(storable)
|
||||
roles[idx] = authtypes.NewRoleFromStorableRole(storable)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
@@ -179,10 +178,10 @@ func (provider *provider) Revoke(ctx context.Context, orgID valuer.UUID, names [
|
||||
return provider.Write(ctx, nil, tuples)
|
||||
}
|
||||
|
||||
func (provider *provider) CreateManagedRoles(ctx context.Context, _ valuer.UUID, managedRoles []*roletypes.Role) error {
|
||||
func (provider *provider) CreateManagedRoles(ctx context.Context, _ valuer.UUID, managedRoles []*authtypes.Role) error {
|
||||
err := provider.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
for _, role := range managedRoles {
|
||||
err := provider.store.Create(ctx, roletypes.NewStorableRoleFromRole(role))
|
||||
err := provider.store.Create(ctx, authtypes.NewStorableRoleFromRole(role))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -199,15 +198,15 @@ 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, []string{roletypes.SigNozAdminRoleName}, authtypes.MustNewSubject(authtypes.TypeableUser, userID.String(), orgID, nil))
|
||||
return provider.Grant(ctx, orgID, []string{authtypes.SigNozAdminRoleName}, authtypes.MustNewSubject(authtypes.TypeableUser, userID.String(), orgID, nil))
|
||||
}
|
||||
|
||||
func (setter *provider) Create(_ context.Context, _ valuer.UUID, _ *roletypes.Role) error {
|
||||
return errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
func (setter *provider) Create(_ context.Context, _ valuer.UUID, _ *authtypes.Role) error {
|
||||
return errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) GetOrCreate(_ context.Context, _ valuer.UUID, _ *roletypes.Role) (*roletypes.Role, error) {
|
||||
return nil, errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
func (provider *provider) GetOrCreate(_ context.Context, _ valuer.UUID, _ *authtypes.Role) (*authtypes.Role, error) {
|
||||
return nil, errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) GetResources(_ context.Context) []*authtypes.Resource {
|
||||
@@ -215,19 +214,19 @@ func (provider *provider) GetResources(_ context.Context) []*authtypes.Resource
|
||||
}
|
||||
|
||||
func (provider *provider) GetObjects(ctx context.Context, orgID valuer.UUID, id valuer.UUID, relation authtypes.Relation) ([]*authtypes.Object, error) {
|
||||
return nil, errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
return nil, errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) Patch(_ context.Context, _ valuer.UUID, _ *roletypes.Role) error {
|
||||
return errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
func (provider *provider) Patch(_ context.Context, _ valuer.UUID, _ *authtypes.Role) error {
|
||||
return errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) PatchObjects(_ context.Context, _ valuer.UUID, _ string, _ authtypes.Relation, _, _ []*authtypes.Object) error {
|
||||
return errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
return errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) Delete(_ context.Context, _ valuer.UUID, _ valuer.UUID) error {
|
||||
return errors.Newf(errors.TypeUnsupported, roletypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
return errors.Newf(errors.TypeUnsupported, authtypes.ErrCodeRoleUnsupported, "not implemented")
|
||||
}
|
||||
|
||||
func (provider *provider) MustGetTypeables() []authtypes.Typeable {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -30,13 +29,13 @@ func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
req := new(roletypes.PostableRole)
|
||||
req := new(authtypes.PostableRole)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
role := roletypes.NewRole(req.Name, req.Description, roletypes.RoleTypeCustom, valuer.MustNewUUID(claims.OrgID))
|
||||
role := authtypes.NewRole(req.Name, req.Description, authtypes.RoleTypeCustom, valuer.MustNewUUID(claims.OrgID))
|
||||
err = handler.authz.Create(ctx, valuer.MustNewUUID(claims.OrgID), role)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
@@ -56,7 +55,7 @@ func (handler *handler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
id, ok := mux.Vars(r)["id"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, roletypes.ErrCodeRoleInvalidInput, "id is missing from the request"))
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, authtypes.ErrCodeRoleInvalidInput, "id is missing from the request"))
|
||||
return
|
||||
}
|
||||
roleID, err := valuer.NewUUID(id)
|
||||
@@ -84,7 +83,7 @@ func (handler *handler) GetObjects(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
id, ok := mux.Vars(r)["id"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, roletypes.ErrCodeRoleInvalidInput, "id is missing from the request"))
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, authtypes.ErrCodeRoleInvalidInput, "id is missing from the request"))
|
||||
return
|
||||
}
|
||||
roleID, err := valuer.NewUUID(id)
|
||||
@@ -95,7 +94,7 @@ func (handler *handler) GetObjects(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
relationStr, ok := mux.Vars(r)["relation"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, roletypes.ErrCodeRoleInvalidInput, "relation is missing from the request"))
|
||||
render.Error(rw, errors.New(errors.TypeInvalidInput, authtypes.ErrCodeRoleInvalidInput, "relation is missing from the request"))
|
||||
return
|
||||
}
|
||||
relation, err := authtypes.NewRelation(relationStr)
|
||||
@@ -150,7 +149,7 @@ func (handler *handler) Patch(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
req := new(roletypes.PatchableRole)
|
||||
req := new(authtypes.PatchableRole)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/sharder"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
const (
|
||||
apiKeyCrossOrgMessage string = "::API-KEY-CROSS-ORG::"
|
||||
)
|
||||
|
||||
type APIKey struct {
|
||||
store sqlstore.SQLStore
|
||||
uuid *authtypes.UUID
|
||||
headers []string
|
||||
logger *slog.Logger
|
||||
sharder sharder.Sharder
|
||||
sfGroup *singleflight.Group
|
||||
}
|
||||
|
||||
func NewAPIKey(store sqlstore.SQLStore, headers []string, logger *slog.Logger, sharder sharder.Sharder) *APIKey {
|
||||
return &APIKey{
|
||||
store: store,
|
||||
uuid: authtypes.NewUUID(),
|
||||
headers: headers,
|
||||
logger: logger,
|
||||
sharder: sharder,
|
||||
sfGroup: &singleflight.Group{},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *APIKey) Wrap(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var values []string
|
||||
var apiKeyToken string
|
||||
var apiKey types.StorableAPIKey
|
||||
|
||||
for _, header := range a.headers {
|
||||
values = append(values, r.Header.Get(header))
|
||||
}
|
||||
|
||||
ctx, err := a.uuid.ContextFromRequest(r.Context(), values...)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
apiKeyToken, ok := authtypes.UUIDFromContext(ctx)
|
||||
if !ok {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.
|
||||
store.
|
||||
BunDB().
|
||||
NewSelect().
|
||||
Model(&apiKey).
|
||||
Where("token = ?", apiKeyToken).
|
||||
Scan(r.Context())
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// allow the APIKey if expires_at is not set
|
||||
if apiKey.ExpiresAt.Before(time.Now()) && !apiKey.ExpiresAt.Equal(types.NEVER_EXPIRES) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// get user from db
|
||||
user := types.User{}
|
||||
err = a.store.BunDB().NewSelect().Model(&user).Where("id = ?", apiKey.UserID).Scan(r.Context())
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
jwt := authtypes.Claims{
|
||||
UserID: user.ID.String(),
|
||||
Role: apiKey.Role,
|
||||
Email: user.Email.String(),
|
||||
OrgID: user.OrgID.String(),
|
||||
}
|
||||
|
||||
ctx = authtypes.NewContextWithClaims(ctx, jwt)
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.sharder.IsMyOwnedKey(r.Context(), types.NewOrganizationKey(valuer.MustNewUUID(claims.OrgID))); err != nil {
|
||||
a.logger.ErrorContext(r.Context(), apiKeyCrossOrgMessage, "claims", claims, "error", err)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx = ctxtypes.SetAuthType(ctx, ctxtypes.AuthTypeAPIKey)
|
||||
|
||||
comment := ctxtypes.CommentFromContext(ctx)
|
||||
comment.Set("auth_type", ctxtypes.AuthTypeAPIKey.StringValue())
|
||||
comment.Set("user_id", claims.UserID)
|
||||
comment.Set("org_id", claims.OrgID)
|
||||
|
||||
r = r.WithContext(ctxtypes.NewContextWithComment(ctx, comment))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
lastUsedCtx := context.WithoutCancel(r.Context())
|
||||
_, _, _ = a.sfGroup.Do(apiKey.ID.StringValue(), func() (any, error) {
|
||||
apiKey.LastUsed = time.Now()
|
||||
_, err = a.
|
||||
store.
|
||||
BunDB().
|
||||
NewUpdate().
|
||||
Model(&apiKey).
|
||||
Column("last_used").
|
||||
Where("token = ?", apiKeyToken).
|
||||
Where("revoked = false").
|
||||
Exec(lastUsedCtx)
|
||||
if err != nil {
|
||||
a.logger.ErrorContext(lastUsedCtx, "failed to update last used of api key", "error", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/sharder"
|
||||
"github.com/SigNoz/signoz/pkg/tokenizer"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
const (
|
||||
authCrossOrgMessage string = "::AUTH-CROSS-ORG::"
|
||||
)
|
||||
|
||||
type AuthN struct {
|
||||
tokenizer tokenizer.Tokenizer
|
||||
headers []string
|
||||
sharder sharder.Sharder
|
||||
logger *slog.Logger
|
||||
sfGroup *singleflight.Group
|
||||
}
|
||||
|
||||
func NewAuthN(headers []string, sharder sharder.Sharder, tokenizer tokenizer.Tokenizer, logger *slog.Logger) *AuthN {
|
||||
return &AuthN{
|
||||
headers: headers,
|
||||
sharder: sharder,
|
||||
tokenizer: tokenizer,
|
||||
logger: logger,
|
||||
sfGroup: &singleflight.Group{},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AuthN) Wrap(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var values []string
|
||||
for _, header := range a.headers {
|
||||
values = append(values, r.Header.Get(header))
|
||||
}
|
||||
|
||||
ctx, err := a.contextFromRequest(r.Context(), values...)
|
||||
if err != nil {
|
||||
r = r.WithContext(ctx)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.sharder.IsMyOwnedKey(r.Context(), types.NewOrganizationKey(valuer.MustNewUUID(claims.OrgID))); err != nil {
|
||||
a.logger.ErrorContext(r.Context(), authCrossOrgMessage, "claims", claims, "error", err)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx = ctxtypes.SetAuthType(ctx, ctxtypes.AuthTypeTokenizer)
|
||||
|
||||
comment := ctxtypes.CommentFromContext(ctx)
|
||||
comment.Set("auth_type", ctxtypes.AuthTypeTokenizer.StringValue())
|
||||
comment.Set("tokenizer_provider", a.tokenizer.Config().Provider)
|
||||
comment.Set("user_id", claims.UserID)
|
||||
comment.Set("org_id", claims.OrgID)
|
||||
|
||||
r = r.WithContext(ctxtypes.NewContextWithComment(ctx, comment))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
accessToken, err := authtypes.AccessTokenFromContext(r.Context())
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
lastObservedAtCtx := context.WithoutCancel(r.Context())
|
||||
_, _, _ = a.sfGroup.Do(accessToken, func() (any, error) {
|
||||
if err := a.tokenizer.SetLastObservedAt(lastObservedAtCtx, accessToken, time.Now()); err != nil {
|
||||
a.logger.ErrorContext(lastObservedAtCtx, "failed to set last observed at", "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (a *AuthN) contextFromRequest(ctx context.Context, values ...string) (context.Context, error) {
|
||||
ctx, err := a.contextFromAccessToken(ctx, values...)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
accessToken, err := authtypes.AccessTokenFromContext(ctx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
authenticatedUser, err := a.tokenizer.GetIdentity(ctx, accessToken)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return authtypes.NewContextWithClaims(ctx, authenticatedUser.ToClaims()), nil
|
||||
}
|
||||
|
||||
func (a *AuthN) contextFromAccessToken(ctx context.Context, values ...string) (context.Context, error) {
|
||||
var value string
|
||||
for _, v := range values {
|
||||
if v != "" {
|
||||
value = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
return ctx, errors.New(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "missing authorization header")
|
||||
}
|
||||
|
||||
// parse from
|
||||
bearerToken, ok := parseBearerAuth(value)
|
||||
if !ok {
|
||||
// this will take care that if the value is not of type bearer token, directly use it
|
||||
bearerToken = value
|
||||
}
|
||||
|
||||
return authtypes.NewContextWithAccessToken(ctx, bearerToken), nil
|
||||
}
|
||||
|
||||
func parseBearerAuth(auth string) (string, bool) {
|
||||
const prefix = "Bearer "
|
||||
// Case insensitive prefix match
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return auth[len(prefix):], true
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -44,7 +43,7 @@ func (middleware *AuthZ) ViewAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
|
||||
commentCtx := ctxtypes.CommentFromContext(ctx)
|
||||
authtype, ok := commentCtx.Map()["auth_type"]
|
||||
if ok && authtype == ctxtypes.AuthTypeAPIKey.StringValue() {
|
||||
if ok && (authtype == authtypes.IdentNProviderAPIkey.StringValue()) {
|
||||
if err := claims.IsViewer(); err != nil {
|
||||
middleware.logger.WarnContext(ctx, authzDeniedMessage, "claims", claims)
|
||||
render.Error(rw, err)
|
||||
@@ -56,9 +55,9 @@ func (middleware *AuthZ) ViewAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
|
||||
selectors := []authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozEditorRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozViewerRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozEditorRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozViewerRoleName),
|
||||
}
|
||||
|
||||
err = middleware.authzService.CheckWithTupleCreation(
|
||||
@@ -96,7 +95,7 @@ func (middleware *AuthZ) EditAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
|
||||
commentCtx := ctxtypes.CommentFromContext(ctx)
|
||||
authtype, ok := commentCtx.Map()["auth_type"]
|
||||
if ok && authtype == ctxtypes.AuthTypeAPIKey.StringValue() {
|
||||
if ok && (authtype == authtypes.IdentNProviderAPIkey.StringValue()) {
|
||||
if err := claims.IsEditor(); err != nil {
|
||||
middleware.logger.WarnContext(ctx, authzDeniedMessage, "claims", claims)
|
||||
render.Error(rw, err)
|
||||
@@ -108,8 +107,8 @@ func (middleware *AuthZ) EditAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
|
||||
selectors := []authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozEditorRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozEditorRoleName),
|
||||
}
|
||||
|
||||
err = middleware.authzService.CheckWithTupleCreation(
|
||||
@@ -147,7 +146,7 @@ func (middleware *AuthZ) AdminAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
|
||||
commentCtx := ctxtypes.CommentFromContext(ctx)
|
||||
authtype, ok := commentCtx.Map()["auth_type"]
|
||||
if ok && authtype == ctxtypes.AuthTypeAPIKey.StringValue() {
|
||||
if ok && (authtype == authtypes.IdentNProviderAPIkey.StringValue()) {
|
||||
if err := claims.IsAdmin(); err != nil {
|
||||
middleware.logger.WarnContext(ctx, authzDeniedMessage, "claims", claims)
|
||||
render.Error(rw, err)
|
||||
@@ -159,7 +158,7 @@ func (middleware *AuthZ) AdminAccess(next http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
|
||||
selectors := []authtypes.Selector{
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, roletypes.SigNozAdminRoleName),
|
||||
authtypes.MustNewSelector(authtypes.TypeRole, authtypes.SigNozAdminRoleName),
|
||||
}
|
||||
|
||||
err = middleware.authzService.CheckWithTupleCreation(
|
||||
|
||||
75
pkg/http/middleware/identn.go
Normal file
75
pkg/http/middleware/identn.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/identn"
|
||||
"github.com/SigNoz/signoz/pkg/sharder"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
const (
|
||||
identityCrossOrgMessage string = "::IDENTITY-CROSS-ORG::"
|
||||
)
|
||||
|
||||
type IdentN struct {
|
||||
resolver identn.IdentNResolver
|
||||
sharder sharder.Sharder
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func NewIdentN(resolver identn.IdentNResolver, sharder sharder.Sharder, logger *slog.Logger) *IdentN {
|
||||
return &IdentN{
|
||||
resolver: resolver,
|
||||
sharder: sharder,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *IdentN) Wrap(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
idn := m.resolver.GetIdentN(r)
|
||||
if idn == nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if pre, ok := idn.(identn.IdentNWithPreHook); ok {
|
||||
r = pre.Pre(r)
|
||||
}
|
||||
|
||||
identity, err := idn.GetIdentity(r)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
claims := identity.ToClaims()
|
||||
if err := m.sharder.IsMyOwnedKey(ctx, types.NewOrganizationKey(valuer.MustNewUUID(claims.OrgID))); err != nil {
|
||||
m.logger.ErrorContext(ctx, identityCrossOrgMessage, "claims", claims, "error", err)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx = authtypes.NewContextWithClaims(ctx, claims)
|
||||
|
||||
comment := ctxtypes.CommentFromContext(ctx)
|
||||
comment.Set("identn_provider", claims.IdentNProvider)
|
||||
comment.Set("user_id", claims.UserID)
|
||||
comment.Set("org_id", claims.OrgID)
|
||||
ctx = ctxtypes.NewContextWithComment(ctx, comment)
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
if hook, ok := idn.(identn.IdentNWithPostHook); ok {
|
||||
hook.Post(context.WithoutCancel(r.Context()), r, claims)
|
||||
}
|
||||
})
|
||||
}
|
||||
131
pkg/identn/apikeyidentn/identn.go
Normal file
131
pkg/identn/apikeyidentn/identn.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package apikeyidentn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/identn"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
// todo: will move this in types layer with service account integration
|
||||
type apiKeyTokenKey struct{}
|
||||
|
||||
type resolver struct {
|
||||
store sqlstore.SQLStore
|
||||
headers []string
|
||||
settings factory.ScopedProviderSettings
|
||||
sfGroup *singleflight.Group
|
||||
}
|
||||
|
||||
func New(providerSettings factory.ProviderSettings, store sqlstore.SQLStore, headers []string) identn.IdentN {
|
||||
return &resolver{
|
||||
store: store,
|
||||
headers: headers,
|
||||
settings: factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/identn/apikeyidentn"),
|
||||
sfGroup: &singleflight.Group{},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resolver) Name() authtypes.IdentNProvider {
|
||||
return authtypes.IdentNProviderAPIkey
|
||||
}
|
||||
|
||||
func (r *resolver) Test(req *http.Request) bool {
|
||||
for _, header := range r.headers {
|
||||
if req.Header.Get(header) != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *resolver) Pre(req *http.Request) *http.Request {
|
||||
token := r.extractToken(req)
|
||||
if token == "" {
|
||||
return req
|
||||
}
|
||||
|
||||
ctx := context.WithValue(req.Context(), apiKeyTokenKey{}, token)
|
||||
return req.WithContext(ctx)
|
||||
}
|
||||
|
||||
func (r *resolver) GetIdentity(req *http.Request) (*authtypes.Identity, error) {
|
||||
ctx := req.Context()
|
||||
|
||||
apiKeyToken, ok := ctx.Value(apiKeyTokenKey{}).(string)
|
||||
if !ok || apiKeyToken == "" {
|
||||
return nil, errors.New(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "missing api key")
|
||||
}
|
||||
|
||||
var apiKey usertypes.StorableAPIKey
|
||||
err := r.store.
|
||||
BunDB().
|
||||
NewSelect().
|
||||
Model(&apiKey).
|
||||
Where("token = ?", apiKeyToken).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if apiKey.ExpiresAt.Before(time.Now()) && !apiKey.ExpiresAt.Equal(usertypes.NEVER_EXPIRES) {
|
||||
return nil, errors.New(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "api key has expired")
|
||||
}
|
||||
|
||||
var user usertypes.User
|
||||
err = r.store.
|
||||
BunDB().
|
||||
NewSelect().
|
||||
Model(&user).
|
||||
Where("id = ?", apiKey.UserID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
identity := authtypes.Identity{
|
||||
UserID: user.ID,
|
||||
Role: apiKey.Role,
|
||||
Email: user.Email,
|
||||
OrgID: user.OrgID,
|
||||
}
|
||||
return &identity, nil
|
||||
}
|
||||
|
||||
func (r *resolver) Post(ctx context.Context, _ *http.Request, _ authtypes.Claims) {
|
||||
apiKeyToken, ok := ctx.Value(apiKeyTokenKey{}).(string)
|
||||
if !ok || apiKeyToken == "" {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, _ = r.sfGroup.Do(apiKeyToken, func() (any, error) {
|
||||
_, err := r.store.
|
||||
BunDB().
|
||||
NewUpdate().
|
||||
Model(new(usertypes.StorableAPIKey)).
|
||||
Set("last_used = ?", time.Now()).
|
||||
Where("token = ?", apiKeyToken).
|
||||
Where("revoked = false").
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
r.settings.Logger().ErrorContext(ctx, "failed to update last used of api key", "error", err)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *resolver) extractToken(req *http.Request) string {
|
||||
for _, header := range r.headers {
|
||||
if v := req.Header.Get(header); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
43
pkg/identn/identn.go
Normal file
43
pkg/identn/identn.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package identn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
)
|
||||
|
||||
type IdentNResolver interface {
|
||||
// GetIdentN returns the first IdentN whose Test() returns true for the request.
|
||||
// Returns nil if no resolver matched.
|
||||
GetIdentN(r *http.Request) IdentN
|
||||
}
|
||||
|
||||
type IdentN interface {
|
||||
// Test checks if this identN can handle the request.
|
||||
// This should be a cheap check (e.g., header presence) with no I/O.
|
||||
Test(r *http.Request) bool
|
||||
|
||||
// GetIdentity returns the resolved identity.
|
||||
// Only called when Test() returns true.
|
||||
GetIdentity(r *http.Request) (*authtypes.Identity, error)
|
||||
|
||||
Name() authtypes.IdentNProvider
|
||||
}
|
||||
|
||||
// IdentNWithPreHook is optionally implemented by resolvers that need to
|
||||
// enrich the request before authentication (e.g., storing the access token
|
||||
// in context so downstream handlers can use it even on auth failure).
|
||||
type IdentNWithPreHook interface {
|
||||
IdentN
|
||||
|
||||
Pre(r *http.Request) *http.Request
|
||||
}
|
||||
|
||||
// IdentNWithPostHook is optionally implemented by resolvers that need
|
||||
// post-response side-effects (e.g., updating last_observed_at).
|
||||
type IdentNWithPostHook interface {
|
||||
IdentN
|
||||
|
||||
Post(ctx context.Context, r *http.Request, claims authtypes.Claims)
|
||||
}
|
||||
31
pkg/identn/resolver.go
Normal file
31
pkg/identn/resolver.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package identn
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
)
|
||||
|
||||
type identNResolver struct {
|
||||
identNs []IdentN
|
||||
settings factory.ScopedProviderSettings
|
||||
}
|
||||
|
||||
func NewIdentNResolver(providerSettings factory.ProviderSettings, identNs ...IdentN) IdentNResolver {
|
||||
return &identNResolver{
|
||||
identNs: identNs,
|
||||
settings: factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/identn"),
|
||||
}
|
||||
}
|
||||
|
||||
// GetIdentN returns the first IdentN whose Test() returns true.
|
||||
// Returns nil if no resolver matched.
|
||||
func (c *identNResolver) GetIdentN(r *http.Request) IdentN {
|
||||
for _, idn := range c.identNs {
|
||||
if idn.Test(r) {
|
||||
c.settings.Logger().DebugContext(r.Context(), "identN matched", "provider", idn.Name())
|
||||
return idn
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
103
pkg/identn/tokenizeridentn/identn.go
Normal file
103
pkg/identn/tokenizeridentn/identn.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package tokenizeridentn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/identn"
|
||||
"github.com/SigNoz/signoz/pkg/tokenizer"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
type resolver struct {
|
||||
tokenizer tokenizer.Tokenizer
|
||||
headers []string
|
||||
settings factory.ScopedProviderSettings
|
||||
sfGroup *singleflight.Group
|
||||
}
|
||||
|
||||
func New(providerSettings factory.ProviderSettings, tokenizer tokenizer.Tokenizer, headers []string) identn.IdentN {
|
||||
return &resolver{
|
||||
tokenizer: tokenizer,
|
||||
headers: headers,
|
||||
settings: factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/identn/tokenizeridentn"),
|
||||
sfGroup: &singleflight.Group{},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resolver) Name() authtypes.IdentNProvider {
|
||||
return authtypes.IdentNProviderTokenizer
|
||||
}
|
||||
|
||||
func (r *resolver) Test(req *http.Request) bool {
|
||||
for _, header := range r.headers {
|
||||
if req.Header.Get(header) != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *resolver) Pre(req *http.Request) *http.Request {
|
||||
accessToken := r.extractToken(req)
|
||||
if accessToken == "" {
|
||||
return req
|
||||
}
|
||||
|
||||
ctx := authtypes.NewContextWithAccessToken(req.Context(), accessToken)
|
||||
return req.WithContext(ctx)
|
||||
}
|
||||
|
||||
func (r *resolver) GetIdentity(req *http.Request) (*authtypes.Identity, error) {
|
||||
ctx := req.Context()
|
||||
|
||||
accessToken, err := authtypes.AccessTokenFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.tokenizer.GetIdentity(ctx, accessToken)
|
||||
}
|
||||
|
||||
func (r *resolver) Post(ctx context.Context, _ *http.Request, _ authtypes.Claims) {
|
||||
accessToken, err := authtypes.AccessTokenFromContext(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, _ = r.sfGroup.Do(accessToken, func() (any, error) {
|
||||
if err := r.tokenizer.SetLastObservedAt(ctx, accessToken, time.Now()); err != nil {
|
||||
r.settings.Logger().ErrorContext(ctx, "failed to set last observed at", "error", err)
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *resolver) extractToken(req *http.Request) string {
|
||||
var value string
|
||||
for _, header := range r.headers {
|
||||
if v := req.Header.Get(header); v != "" {
|
||||
value = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
accessToken, ok := r.parseBearerAuth(value)
|
||||
if !ok {
|
||||
return value
|
||||
}
|
||||
return accessToken
|
||||
}
|
||||
|
||||
func (r *resolver) parseBearerAuth(auth string) (string, bool) {
|
||||
const prefix = "Bearer "
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return "", false
|
||||
}
|
||||
return auth[len(prefix):], true
|
||||
}
|
||||
@@ -43,7 +43,7 @@ type Module interface {
|
||||
|
||||
Update(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, data dashboardtypes.UpdatableDashboard, diff int) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role types.Role, lock bool) error
|
||||
LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role authtypes.LegacyRole, lock bool) error
|
||||
|
||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/transition"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
@@ -109,7 +108,7 @@ func (handler *handler) Update(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
diff := 0
|
||||
// Allow multiple deletions for API key requests; enforce for others
|
||||
if authType, ok := ctxtypes.AuthTypeFromContext(ctx); ok && authType == ctxtypes.AuthTypeTokenizer {
|
||||
if claims.IdentNProvider == authtypes.IdentNProviderTokenizer.StringValue() {
|
||||
diff = 1
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return dashboard, nil
|
||||
}
|
||||
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role types.Role, lock bool) error {
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, role authtypes.LegacyRole, lock bool) error {
|
||||
dashboard, err := module.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/tokenizer"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -66,7 +67,7 @@ func (module *module) GetSessionContext(ctx context.Context, email valuer.Email,
|
||||
}
|
||||
|
||||
// filter out deleted users
|
||||
users = slices.DeleteFunc(users, func(user *types.User) bool { return user.ErrIfDeleted() != nil })
|
||||
users = slices.DeleteFunc(users, func(user *usertypes.User) bool { return user.ErrIfDeleted() != nil })
|
||||
|
||||
// Since email is a valuer, we can be sure that it is a valid email and we can split it to get the domain name.
|
||||
name := strings.Split(email.String(), "@")[1]
|
||||
@@ -144,7 +145,7 @@ func (module *module) CreateCallbackAuthNSession(ctx context.Context, authNProvi
|
||||
roleMapping := authDomain.AuthDomainConfig().RoleMapping
|
||||
role := roleMapping.NewRoleFromCallbackIdentity(callbackIdentity)
|
||||
|
||||
user, err := types.NewUser(callbackIdentity.Name, callbackIdentity.Email, role, callbackIdentity.OrgID, types.UserStatusActive)
|
||||
user, err := usertypes.NewUser(callbackIdentity.Name, callbackIdentity.Email, role, callbackIdentity.OrgID, usertypes.UserStatusActive)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -158,7 +159,7 @@ func (module *module) CreateCallbackAuthNSession(ctx context.Context, authNProvi
|
||||
return "", errors.WithAdditionalf(err, "root user can only authenticate via password")
|
||||
}
|
||||
|
||||
token, err := module.tokenizer.CreateToken(ctx, authtypes.NewIdentity(user.ID, user.OrgID, user.Email, user.Role), map[string]string{})
|
||||
token, err := module.tokenizer.CreateToken(ctx, authtypes.NewIdentity(user.ID, user.OrgID, user.Email, user.Role, authtypes.IdentNProviderTokenizer), map[string]string{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
traceFunnels "github.com/SigNoz/signoz/pkg/types/tracefunneltypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -30,7 +31,7 @@ func (module *module) Create(ctx context.Context, timestamp int64, name string,
|
||||
funnel.CreatedBy = userID.String()
|
||||
|
||||
// Set up the user relationship
|
||||
funnel.CreatedByUser = &types.User{
|
||||
funnel.CreatedByUser = &usertypes.StorableUser{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: userID,
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -68,7 +68,7 @@ func (c Config) Validate() error {
|
||||
if c.Root.Password == "" {
|
||||
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "user::root::password is required when root user is enabled")
|
||||
}
|
||||
if !types.IsPasswordValid(c.Root.Password) {
|
||||
if !usertypes.IsPasswordValid(c.Root.Password) {
|
||||
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "user::root::password does not meet password requirements")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,26 +6,30 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/flagger"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/featuretypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type getter struct {
|
||||
store types.UserStore
|
||||
store usertypes.UserStore
|
||||
flagger flagger.Flagger
|
||||
}
|
||||
|
||||
func NewGetter(store types.UserStore, flagger flagger.Flagger) user.Getter {
|
||||
func NewGetter(store usertypes.UserStore, flagger flagger.Flagger) user.Getter {
|
||||
return &getter{store: store, flagger: flagger}
|
||||
}
|
||||
|
||||
func (module *getter) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (*types.User, error) {
|
||||
return module.store.GetRootUserByOrgID(ctx, orgID)
|
||||
func (module *getter) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (*usertypes.User, error) {
|
||||
storable, err := module.store.GetRootUserByOrgID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return usertypes.NewUserFromStorable(storable), nil
|
||||
}
|
||||
|
||||
func (module *getter) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*types.User, error) {
|
||||
users, err := module.store.ListUsersByOrgID(ctx, orgID)
|
||||
func (module *getter) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*usertypes.User, error) {
|
||||
storableUsers, err := module.store.ListUsersByOrgID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,46 +39,46 @@ func (module *getter) ListByOrgID(ctx context.Context, orgID valuer.UUID) ([]*ty
|
||||
hideRootUsers := module.flagger.BooleanOrEmpty(ctx, flagger.FeatureHideRootUser, evalCtx)
|
||||
|
||||
if hideRootUsers {
|
||||
users = slices.DeleteFunc(users, func(user *types.User) bool { return user.IsRoot })
|
||||
storableUsers = slices.DeleteFunc(storableUsers, func(user *usertypes.StorableUser) bool { return user.IsRoot })
|
||||
}
|
||||
|
||||
return users, nil
|
||||
return usertypes.NewUsersFromStorables(storableUsers), nil
|
||||
}
|
||||
|
||||
func (module *getter) GetUsersByEmail(ctx context.Context, email valuer.Email) ([]*types.User, error) {
|
||||
users, err := module.store.GetUsersByEmail(ctx, email)
|
||||
func (module *getter) GetUsersByEmail(ctx context.Context, email valuer.Email) ([]*usertypes.User, error) {
|
||||
storableUsers, err := module.store.GetUsersByEmail(ctx, email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
return usertypes.NewUsersFromStorables(storableUsers), nil
|
||||
}
|
||||
|
||||
func (module *getter) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*types.User, error) {
|
||||
user, err := module.store.GetByOrgIDAndID(ctx, orgID, id)
|
||||
func (module *getter) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*usertypes.User, error) {
|
||||
storableUser, err := module.store.GetByOrgIDAndID(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return usertypes.NewUserFromStorable(storableUser), nil
|
||||
}
|
||||
|
||||
func (module *getter) Get(ctx context.Context, id valuer.UUID) (*types.User, error) {
|
||||
user, err := module.store.GetUser(ctx, id)
|
||||
func (module *getter) Get(ctx context.Context, id valuer.UUID) (*usertypes.User, error) {
|
||||
storableUser, err := module.store.GetUser(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return usertypes.NewUserFromStorable(storableUser), nil
|
||||
}
|
||||
|
||||
func (module *getter) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.Email, orgIDs []valuer.UUID) ([]*types.User, error) {
|
||||
users, err := module.store.ListUsersByEmailAndOrgIDs(ctx, email, orgIDs)
|
||||
func (module *getter) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.Email, orgIDs []valuer.UUID) ([]*usertypes.User, error) {
|
||||
storableUsers, err := module.store.ListUsersByEmailAndOrgIDs(ctx, email, orgIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
return usertypes.NewUsersFromStorables(storableUsers), nil
|
||||
}
|
||||
|
||||
func (module *getter) CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error) {
|
||||
@@ -95,7 +99,7 @@ func (module *getter) CountByOrgIDAndStatuses(ctx context.Context, orgID valuer.
|
||||
return counts, nil
|
||||
}
|
||||
|
||||
func (module *getter) GetFactorPasswordByUserID(ctx context.Context, userID valuer.UUID) (*types.FactorPassword, error) {
|
||||
func (module *getter) GetFactorPasswordByUserID(ctx context.Context, userID valuer.UUID) (*usertypes.FactorPassword, error) {
|
||||
factorPassword, err := module.store.GetPasswordByUserID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -103,3 +107,12 @@ func (module *getter) GetFactorPasswordByUserID(ctx context.Context, userID valu
|
||||
|
||||
return factorPassword, nil
|
||||
}
|
||||
|
||||
func (module *getter) GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx context.Context, email string, orgID valuer.UUID) (*usertypes.User, *usertypes.FactorPassword, error) {
|
||||
storableUser, factorPassword, err := module.store.GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx, email, orgID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return usertypes.NewUserFromStorable(storableUser), factorPassword, nil
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/http/binding"
|
||||
"github.com/SigNoz/signoz/pkg/http/render"
|
||||
root "github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ func (h *handler) AcceptInvite(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := new(types.PostableAcceptInvite)
|
||||
req := new(usertypes.PostableAcceptInvite)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
@@ -56,14 +56,14 @@ func (h *handler) CreateInvite(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req types.PostableInvite
|
||||
var req usertypes.PostableInvite
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
invites, err := h.module.CreateBulkInvite(ctx, valuer.MustNewUUID(claims.OrgID), valuer.MustNewUUID(claims.UserID), &types.PostableBulkInviteRequest{
|
||||
Invites: []types.PostableInvite{req},
|
||||
invites, err := h.module.CreateBulkInvite(ctx, valuer.MustNewUUID(claims.OrgID), valuer.MustNewUUID(claims.UserID), &usertypes.PostableBulkInviteRequest{
|
||||
Invites: []usertypes.PostableInvite{req},
|
||||
})
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
@@ -83,7 +83,7 @@ func (h *handler) CreateBulkInvite(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req types.PostableBulkInviteRequest
|
||||
var req usertypes.PostableBulkInviteRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@@ -214,7 +214,7 @@ func (h *handler) ListUsers(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// temp code - show only active users
|
||||
users = slices.DeleteFunc(users, func(user *types.User) bool { return user.Status != types.UserStatusActive })
|
||||
users = slices.DeleteFunc(users, func(user *usertypes.User) bool { return user.Status != usertypes.UserStatusActive })
|
||||
|
||||
render.Success(w, http.StatusOK, users)
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func (h *handler) UpdateUser(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var user types.User
|
||||
var user usertypes.User
|
||||
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
@@ -297,7 +297,7 @@ func (handler *handler) ResetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := new(types.PostableResetPassword)
|
||||
req := new(usertypes.PostableResetPassword)
|
||||
if err := json.NewDecoder(r.Body).Decode(req); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
@@ -316,7 +316,7 @@ func (handler *handler) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var req types.ChangePasswordRequest
|
||||
var req usertypes.ChangePasswordRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
@@ -335,7 +335,7 @@ func (h *handler) ForgotPassword(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := new(types.PostableForgotPassword)
|
||||
req := new(usertypes.PostableForgotPassword)
|
||||
if err := binding.JSON.BindBody(r.Body, req); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
@@ -360,13 +360,13 @@ func (h *handler) CreateAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
req := new(types.PostableAPIKey)
|
||||
req := new(usertypes.PostableAPIKey)
|
||||
if err := json.NewDecoder(r.Body).Decode(req); err != nil {
|
||||
render.Error(w, errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, "failed to decode api key"))
|
||||
return
|
||||
}
|
||||
|
||||
apiKey, err := types.NewStorableAPIKey(
|
||||
apiKey, err := usertypes.NewStorableAPIKey(
|
||||
req.Name,
|
||||
valuer.MustNewUUID(claims.UserID),
|
||||
req.Role,
|
||||
@@ -411,13 +411,13 @@ func (h *handler) ListAPIKeys(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// for backward compatibility
|
||||
if len(apiKeys) == 0 {
|
||||
render.Success(w, http.StatusOK, []types.GettableAPIKey{})
|
||||
render.Success(w, http.StatusOK, []usertypes.GettableAPIKey{})
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]*types.GettableAPIKey, len(apiKeys))
|
||||
result := make([]*usertypes.GettableAPIKey, len(apiKeys))
|
||||
for i, apiKey := range apiKeys {
|
||||
result[i] = types.NewGettableAPIKeyFromStorableAPIKey(apiKey)
|
||||
result[i] = usertypes.NewGettableAPIKeyFromStorableAPIKey(apiKey)
|
||||
}
|
||||
|
||||
render.Success(w, http.StatusOK, result)
|
||||
@@ -434,7 +434,7 @@ func (h *handler) UpdateAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
req := types.StorableAPIKey{}
|
||||
req := usertypes.StorableAPIKey{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(w, errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, "failed to decode api key"))
|
||||
return
|
||||
|
||||
@@ -19,13 +19,13 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/emailtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
store types.UserStore
|
||||
store usertypes.UserStore
|
||||
tokenizer tokenizer.Tokenizer
|
||||
emailing emailing.Emailing
|
||||
settings factory.ScopedProviderSettings
|
||||
@@ -36,7 +36,7 @@ type Module struct {
|
||||
}
|
||||
|
||||
// This module is a WIP, don't take inspiration from this.
|
||||
func NewModule(store types.UserStore, tokenizer tokenizer.Tokenizer, emailing emailing.Emailing, providerSettings factory.ProviderSettings, orgSetter organization.Setter, authz authz.AuthZ, analytics analytics.Analytics, config user.Config) root.Module {
|
||||
func NewModule(store usertypes.UserStore, tokenizer tokenizer.Tokenizer, emailing emailing.Emailing, providerSettings factory.ProviderSettings, orgSetter organization.Setter, authz authz.AuthZ, analytics analytics.Analytics, config user.Config) root.Module {
|
||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/modules/user/impluser")
|
||||
return &Module{
|
||||
store: store,
|
||||
@@ -50,9 +50,9 @@ func NewModule(store types.UserStore, tokenizer tokenizer.Tokenizer, emailing em
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Module) AcceptInvite(ctx context.Context, token string, password string) (*types.User, error) {
|
||||
func (m *Module) AcceptInvite(ctx context.Context, token string, password string) (*usertypes.User, error) {
|
||||
// get the user by reset password token
|
||||
user, err := m.store.GetUserByResetPasswordToken(ctx, token)
|
||||
storableUser, err := m.store.GetUserByResetPasswordToken(ctx, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -64,23 +64,25 @@ func (m *Module) AcceptInvite(ctx context.Context, token string, password string
|
||||
}
|
||||
|
||||
// query the user again
|
||||
user, err = m.store.GetByOrgIDAndID(ctx, user.OrgID, user.ID)
|
||||
storableUser, err = m.store.GetByOrgIDAndID(ctx, valuer.MustNewUUID(storableUser.OrgID), storableUser.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return usertypes.NewUserFromStorable(storableUser), nil
|
||||
}
|
||||
|
||||
func (m *Module) GetInviteByToken(ctx context.Context, token string) (*types.Invite, error) {
|
||||
func (m *Module) GetInviteByToken(ctx context.Context, token string) (*usertypes.Invite, error) {
|
||||
// get the user
|
||||
user, err := m.store.GetUserByResetPasswordToken(ctx, token)
|
||||
storableUser, err := m.store.GetUserByResetPasswordToken(ctx, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := usertypes.NewUserFromStorable(storableUser)
|
||||
|
||||
// create a dummy invite obj for backward compatibility
|
||||
invite := &types.Invite{
|
||||
invite := &usertypes.Invite{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: user.ID,
|
||||
},
|
||||
@@ -99,7 +101,7 @@ func (m *Module) GetInviteByToken(ctx context.Context, token string) (*types.Inv
|
||||
}
|
||||
|
||||
// CreateBulk implements invite.Module.
|
||||
func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, bulkInvites *types.PostableBulkInviteRequest) ([]*types.Invite, error) {
|
||||
func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, bulkInvites *usertypes.PostableBulkInviteRequest) ([]*usertypes.Invite, error) {
|
||||
creator, err := m.store.GetUser(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -110,17 +112,19 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
|
||||
for idx, invite := range bulkInvites.Invites {
|
||||
emails[idx] = invite.Email.StringValue()
|
||||
}
|
||||
users, err := m.store.GetUsersByEmailsOrgIDAndStatuses(ctx, orgID, emails, []string{types.UserStatusActive.StringValue(), types.UserStatusPendingInvite.StringValue()})
|
||||
storableUsers, err := m.store.GetUsersByEmailsOrgIDAndStatuses(ctx, orgID, emails, []string{usertypes.UserStatusActive.StringValue(), usertypes.UserStatusPendingInvite.StringValue()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := usertypes.NewUsersFromStorables(storableUsers)
|
||||
|
||||
if len(users) > 0 {
|
||||
if err := users[0].ErrIfRoot(); err != nil {
|
||||
return nil, errors.WithAdditionalf(err, "Cannot send invite to root user")
|
||||
}
|
||||
|
||||
if users[0].Status == types.UserStatusPendingInvite {
|
||||
if users[0].Status == usertypes.UserStatusPendingInvite {
|
||||
return nil, errors.Newf(errors.TypeAlreadyExists, errors.CodeAlreadyExists, "An invite already exists for this email: %s", users[0].Email.StringValue())
|
||||
}
|
||||
|
||||
@@ -128,21 +132,21 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
|
||||
}
|
||||
|
||||
type userWithResetToken struct {
|
||||
User *types.User
|
||||
ResetPasswordToken *types.ResetPasswordToken
|
||||
User *usertypes.User
|
||||
ResetPasswordToken *usertypes.ResetPasswordToken
|
||||
}
|
||||
|
||||
newUsersWithResetToken := make([]*userWithResetToken, len(bulkInvites.Invites))
|
||||
|
||||
if err := m.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
for idx, invite := range bulkInvites.Invites {
|
||||
role, err := types.NewRole(invite.Role.String())
|
||||
role, err := authtypes.NewLegacyRole(invite.Role.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a new user with pending invite status
|
||||
newUser, err := types.NewUser(invite.Name, invite.Email, role, orgID, types.UserStatusPendingInvite)
|
||||
newUser, err := usertypes.NewUser(invite.Name, invite.Email, role, orgID, usertypes.UserStatusPendingInvite)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -170,7 +174,7 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
|
||||
return nil, err
|
||||
}
|
||||
|
||||
invites := make([]*types.Invite, len(bulkInvites.Invites))
|
||||
invites := make([]*usertypes.Invite, len(bulkInvites.Invites))
|
||||
|
||||
// send password reset emails to all the invited users
|
||||
for idx, userWithToken := range newUsersWithResetToken {
|
||||
@@ -179,7 +183,7 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
|
||||
"invitee_role": userWithToken.User.Role,
|
||||
})
|
||||
|
||||
invite := &types.Invite{
|
||||
invite := &usertypes.Invite{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: userWithToken.User.ID,
|
||||
},
|
||||
@@ -219,16 +223,17 @@ func (m *Module) CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID
|
||||
return invites, nil
|
||||
}
|
||||
|
||||
func (m *Module) ListInvite(ctx context.Context, orgID string) ([]*types.Invite, error) {
|
||||
func (m *Module) ListInvite(ctx context.Context, orgID string) ([]*usertypes.Invite, error) {
|
||||
// find all the users with pending_invite status
|
||||
users, err := m.store.ListUsersByOrgID(ctx, valuer.MustNewUUID(orgID))
|
||||
storableUsers, err := m.store.ListUsersByOrgID(ctx, valuer.MustNewUUID(orgID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pendingUsers := slices.DeleteFunc(users, func(user *types.User) bool { return user.Status != types.UserStatusPendingInvite })
|
||||
pendingStorableUsers := slices.DeleteFunc(storableUsers, func(user *usertypes.StorableUser) bool { return user.Status != usertypes.UserStatusPendingInvite })
|
||||
pendingUsers := usertypes.NewUsersFromStorables(pendingStorableUsers)
|
||||
|
||||
var invites []*types.Invite
|
||||
var invites []*usertypes.Invite
|
||||
|
||||
for _, pUser := range pendingUsers {
|
||||
// get the reset password token
|
||||
@@ -238,7 +243,7 @@ func (m *Module) ListInvite(ctx context.Context, orgID string) ([]*types.Invite,
|
||||
}
|
||||
|
||||
// create a dummy invite obj for backward compatibility
|
||||
invite := &types.Invite{
|
||||
invite := &usertypes.Invite{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: pUser.ID,
|
||||
},
|
||||
@@ -259,17 +264,17 @@ func (m *Module) ListInvite(ctx context.Context, orgID string) ([]*types.Invite,
|
||||
return invites, nil
|
||||
}
|
||||
|
||||
func (module *Module) CreateUser(ctx context.Context, input *types.User, opts ...root.CreateUserOption) error {
|
||||
func (module *Module) CreateUser(ctx context.Context, input *usertypes.User, opts ...root.CreateUserOption) error {
|
||||
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, []string{roletypes.MustGetSigNozManagedRoleFromExistingRole(input.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.StringValue(), input.OrgID, nil))
|
||||
err := module.authz.Grant(ctx, input.OrgID, []string{authtypes.MustGetSigNozManagedRoleFromExistingRole(input.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, input.ID.StringValue(), input.OrgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.CreateUser(ctx, input); err != nil {
|
||||
if err := module.store.CreateUser(ctx, usertypes.NewStorableUser(input)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -284,19 +289,21 @@ func (module *Module) CreateUser(ctx context.Context, input *types.User, opts ..
|
||||
return err
|
||||
}
|
||||
|
||||
traitsOrProperties := types.NewTraitsFromUser(input)
|
||||
traitsOrProperties := usertypes.NewTraitsFromUser(input)
|
||||
module.analytics.IdentifyUser(ctx, input.OrgID.String(), input.ID.String(), traitsOrProperties)
|
||||
module.analytics.TrackUser(ctx, input.OrgID.String(), input.ID.String(), "User Created", traitsOrProperties)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Module) UpdateUser(ctx context.Context, orgID valuer.UUID, id string, user *types.User, updatedBy string) (*types.User, error) {
|
||||
existingUser, err := m.store.GetUser(ctx, valuer.MustNewUUID(id))
|
||||
func (m *Module) UpdateUser(ctx context.Context, orgID valuer.UUID, id string, user *usertypes.User, updatedBy string) (*usertypes.User, error) {
|
||||
existingStorableUser, err := m.store.GetUser(ctx, valuer.MustNewUUID(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingUser := usertypes.NewUserFromStorable(existingStorableUser)
|
||||
|
||||
if err := existingUser.ErrIfRoot(); err != nil {
|
||||
return nil, errors.WithAdditionalf(err, "cannot update root user")
|
||||
}
|
||||
@@ -314,13 +321,13 @@ func (m *Module) UpdateUser(ctx context.Context, orgID valuer.UUID, id string, u
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user.Role != "" && user.Role != existingUser.Role && requestor.Role != types.RoleAdmin {
|
||||
if user.Role != "" && user.Role != existingUser.Role && requestor.Role != authtypes.RoleAdmin {
|
||||
return nil, errors.New(errors.TypeForbidden, errors.CodeForbidden, "only admins can change roles")
|
||||
}
|
||||
|
||||
// Make sure that the request is not demoting the last admin user.
|
||||
if user.Role != "" && user.Role != existingUser.Role && existingUser.Role == types.RoleAdmin {
|
||||
adminUsers, err := m.store.GetActiveUsersByRoleAndOrgID(ctx, types.RoleAdmin, orgID)
|
||||
if user.Role != "" && user.Role != existingUser.Role && existingUser.Role == authtypes.RoleAdmin {
|
||||
adminUsers, err := m.store.GetActiveUsersByRoleAndOrgID(ctx, authtypes.RoleAdmin, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -333,8 +340,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,
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(existingUser.Role)},
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(existingUser.Role)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -350,12 +357,13 @@ func (m *Module) UpdateUser(ctx context.Context, orgID valuer.UUID, id string, u
|
||||
return existingUser, nil
|
||||
}
|
||||
|
||||
func (module *Module) UpdateAnyUser(ctx context.Context, orgID valuer.UUID, user *types.User) error {
|
||||
if err := module.store.UpdateUser(ctx, orgID, user); err != nil {
|
||||
func (module *Module) UpdateAnyUser(ctx context.Context, orgID valuer.UUID, user *usertypes.User) error {
|
||||
storableUser := usertypes.NewStorableUser(user)
|
||||
if err := module.store.UpdateUser(ctx, orgID, storableUser); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
traits := types.NewTraitsFromUser(user)
|
||||
traits := usertypes.NewTraitsFromUser(user)
|
||||
module.analytics.IdentifyUser(ctx, user.OrgID.String(), user.ID.String(), traits)
|
||||
module.analytics.TrackUser(ctx, user.OrgID.String(), user.ID.String(), "User Updated", traits)
|
||||
|
||||
@@ -367,11 +375,13 @@ func (module *Module) UpdateAnyUser(ctx context.Context, orgID valuer.UUID, user
|
||||
}
|
||||
|
||||
func (module *Module) DeleteUser(ctx context.Context, orgID valuer.UUID, id string, deletedBy string) error {
|
||||
user, err := module.store.GetUser(ctx, valuer.MustNewUUID(id))
|
||||
storableUser, err := module.store.GetUser(ctx, valuer.MustNewUUID(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := usertypes.NewUserFromStorable(storableUser)
|
||||
|
||||
if err := user.ErrIfRoot(); err != nil {
|
||||
return errors.WithAdditionalf(err, "cannot delete root user")
|
||||
}
|
||||
@@ -385,17 +395,17 @@ func (module *Module) DeleteUser(ctx context.Context, orgID valuer.UUID, id stri
|
||||
}
|
||||
|
||||
// don't allow to delete the last admin user
|
||||
adminUsers, err := module.store.GetActiveUsersByRoleAndOrgID(ctx, types.RoleAdmin, orgID)
|
||||
adminUsers, err := module.store.GetActiveUsersByRoleAndOrgID(ctx, authtypes.RoleAdmin, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(adminUsers) == 1 && user.Role == types.RoleAdmin {
|
||||
if len(adminUsers) == 1 && user.Role == authtypes.RoleAdmin {
|
||||
return errors.New(errors.TypeForbidden, errors.CodeForbidden, "cannot delete the last admin")
|
||||
}
|
||||
|
||||
// since revoke is idempotant multiple calls to revoke won't cause issues in case of retries
|
||||
err = module.authz.Revoke(ctx, orgID, []string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil))
|
||||
err = module.authz.Revoke(ctx, orgID, []string{authtypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)}, authtypes.MustNewSubject(authtypes.TypeableUser, id, orgID, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -412,12 +422,14 @@ func (module *Module) DeleteUser(ctx context.Context, orgID valuer.UUID, id stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *Module) GetOrCreateResetPasswordToken(ctx context.Context, userID valuer.UUID) (*types.ResetPasswordToken, error) {
|
||||
user, err := module.store.GetUser(ctx, userID)
|
||||
func (module *Module) GetOrCreateResetPasswordToken(ctx context.Context, userID valuer.UUID) (*usertypes.ResetPasswordToken, error) {
|
||||
storableUser, err := module.store.GetUser(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := usertypes.NewUserFromStorable(storableUser)
|
||||
|
||||
if err := user.ErrIfRoot(); err != nil {
|
||||
return nil, errors.WithAdditionalf(err, "cannot reset password for root user")
|
||||
}
|
||||
@@ -435,7 +447,7 @@ func (module *Module) GetOrCreateResetPasswordToken(ctx context.Context, userID
|
||||
|
||||
if password == nil {
|
||||
// if the user does not have a password, we need to create a new one (common for SSO/SAML users)
|
||||
password = types.MustGenerateFactorPassword(userID.String())
|
||||
password = usertypes.MustGenerateFactorPassword(userID.String())
|
||||
|
||||
if err := module.store.CreatePassword(ctx, password); err != nil {
|
||||
return nil, err
|
||||
@@ -461,7 +473,7 @@ func (module *Module) GetOrCreateResetPasswordToken(ctx context.Context, userID
|
||||
}
|
||||
|
||||
// create a new token
|
||||
resetPasswordToken, err := types.NewResetPasswordToken(password.ID, time.Now().Add(module.config.Password.Reset.MaxTokenLifetime))
|
||||
resetPasswordToken, err := usertypes.NewResetPasswordToken(password.ID, time.Now().Add(module.config.Password.Reset.MaxTokenLifetime))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -535,11 +547,13 @@ func (module *Module) UpdatePasswordByResetPasswordToken(ctx context.Context, to
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := module.store.GetUser(ctx, valuer.MustNewUUID(password.UserID))
|
||||
storableUser, err := module.store.GetUser(ctx, valuer.MustNewUUID(password.UserID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := usertypes.NewUserFromStorable(storableUser)
|
||||
|
||||
// handle deleted user
|
||||
if err := user.ErrIfDeleted(); err != nil {
|
||||
return errors.WithAdditionalf(err, "deleted users cannot reset their password")
|
||||
@@ -554,11 +568,11 @@ func (module *Module) UpdatePasswordByResetPasswordToken(ctx context.Context, to
|
||||
}
|
||||
|
||||
// since grant is idempotent, multiple calls won't cause issues in case of retries
|
||||
if user.Status == types.UserStatusPendingInvite {
|
||||
if user.Status == usertypes.UserStatusPendingInvite {
|
||||
if err = module.authz.Grant(
|
||||
ctx,
|
||||
user.OrgID,
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, user.ID.StringValue(), user.OrgID, nil),
|
||||
); err != nil {
|
||||
return err
|
||||
@@ -566,11 +580,11 @@ func (module *Module) UpdatePasswordByResetPasswordToken(ctx context.Context, to
|
||||
}
|
||||
|
||||
return module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if user.Status == types.UserStatusPendingInvite {
|
||||
if err := user.UpdateStatus(types.UserStatusActive); err != nil {
|
||||
if user.Status == usertypes.UserStatusPendingInvite {
|
||||
if err := user.UpdateStatus(usertypes.UserStatusActive); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := module.store.UpdateUser(ctx, user.OrgID, user); err != nil {
|
||||
if err := module.store.UpdateUser(ctx, user.OrgID, usertypes.NewStorableUser(user)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -588,11 +602,13 @@ func (module *Module) UpdatePasswordByResetPasswordToken(ctx context.Context, to
|
||||
}
|
||||
|
||||
func (module *Module) UpdatePassword(ctx context.Context, userID valuer.UUID, oldpasswd string, passwd string) error {
|
||||
user, err := module.store.GetUser(ctx, userID)
|
||||
storableUser, err := module.store.GetUser(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := usertypes.NewUserFromStorable(storableUser)
|
||||
|
||||
if err := user.ErrIfDeleted(); err != nil {
|
||||
return errors.WithAdditionalf(err, "cannot change password for deleted user")
|
||||
}
|
||||
@@ -607,7 +623,7 @@ func (module *Module) UpdatePassword(ctx context.Context, userID valuer.UUID, ol
|
||||
}
|
||||
|
||||
if !password.Equals(oldpasswd) {
|
||||
return errors.New(errors.TypeInvalidInput, types.ErrCodeIncorrectPassword, "old password is incorrect")
|
||||
return errors.New(errors.TypeInvalidInput, usertypes.ErrCodeIncorrectPassword, "old password is incorrect")
|
||||
}
|
||||
|
||||
if err := password.Update(passwd); err != nil {
|
||||
@@ -631,7 +647,7 @@ func (module *Module) UpdatePassword(ctx context.Context, userID valuer.UUID, ol
|
||||
return module.tokenizer.DeleteTokensByUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (module *Module) GetOrCreateUser(ctx context.Context, user *types.User, opts ...root.CreateUserOption) (*types.User, error) {
|
||||
func (module *Module) GetOrCreateUser(ctx context.Context, user *usertypes.User, opts ...root.CreateUserOption) (*usertypes.User, error) {
|
||||
existingUser, err := module.GetNonDeletedUserByEmailAndOrgID(ctx, user.Email, user.OrgID)
|
||||
if err != nil {
|
||||
if !errors.Ast(err, errors.TypeNotFound) {
|
||||
@@ -641,7 +657,7 @@ func (module *Module) GetOrCreateUser(ctx context.Context, user *types.User, opt
|
||||
|
||||
if existingUser != nil {
|
||||
// for users logging through SSO flow but are having status as pending_invite
|
||||
if existingUser.Status == types.UserStatusPendingInvite {
|
||||
if existingUser.Status == usertypes.UserStatusPendingInvite {
|
||||
// respect the role coming from the SSO
|
||||
existingUser.Update("", user.Role)
|
||||
// activate the user
|
||||
@@ -661,19 +677,19 @@ func (module *Module) GetOrCreateUser(ctx context.Context, user *types.User, opt
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (m *Module) CreateAPIKey(ctx context.Context, apiKey *types.StorableAPIKey) error {
|
||||
func (m *Module) CreateAPIKey(ctx context.Context, apiKey *usertypes.StorableAPIKey) error {
|
||||
return m.store.CreateAPIKey(ctx, apiKey)
|
||||
}
|
||||
|
||||
func (m *Module) UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *types.StorableAPIKey, updaterID valuer.UUID) error {
|
||||
func (m *Module) UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *usertypes.StorableAPIKey, updaterID valuer.UUID) error {
|
||||
return m.store.UpdateAPIKey(ctx, id, apiKey, updaterID)
|
||||
}
|
||||
|
||||
func (m *Module) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*types.StorableAPIKeyUser, error) {
|
||||
func (m *Module) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*usertypes.StorableAPIKeyUser, error) {
|
||||
return m.store.ListAPIKeys(ctx, orgID)
|
||||
}
|
||||
|
||||
func (m *Module) GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*types.StorableAPIKeyUser, error) {
|
||||
func (m *Module) GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*usertypes.StorableAPIKeyUser, error) {
|
||||
return m.store.GetAPIKey(ctx, orgID, id)
|
||||
}
|
||||
|
||||
@@ -681,18 +697,18 @@ func (m *Module) RevokeAPIKey(ctx context.Context, id, removedByUserID valuer.UU
|
||||
return m.store.RevokeAPIKey(ctx, id, removedByUserID)
|
||||
}
|
||||
|
||||
func (module *Module) CreateFirstUser(ctx context.Context, organization *types.Organization, name string, email valuer.Email, passwd string) (*types.User, error) {
|
||||
user, err := types.NewRootUser(name, email, organization.ID)
|
||||
func (module *Module) CreateFirstUser(ctx context.Context, organization *types.Organization, name string, email valuer.Email, passwd string) (*usertypes.User, error) {
|
||||
user, err := usertypes.NewRootUser(name, email, organization.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
password, err := types.NewFactorPassword(passwd, user.ID.StringValue())
|
||||
password, err := usertypes.NewFactorPassword(passwd, user.ID.StringValue())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
managedRoles := roletypes.NewManagedRoles(organization.ID)
|
||||
managedRoles := authtypes.NewManagedRoles(organization.ID)
|
||||
err = module.authz.CreateManagedUserRoleTransactions(ctx, organization.ID, user.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -726,12 +742,12 @@ func (module *Module) CreateFirstUser(ctx context.Context, organization *types.O
|
||||
|
||||
func (module *Module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||
stats := make(map[string]any)
|
||||
counts, err := module.store.CountByOrgIDAndStatuses(ctx, orgID, []string{types.UserStatusActive.StringValue(), types.UserStatusDeleted.StringValue(), types.UserStatusPendingInvite.StringValue()})
|
||||
counts, err := module.store.CountByOrgIDAndStatuses(ctx, orgID, []string{usertypes.UserStatusActive.StringValue(), usertypes.UserStatusDeleted.StringValue(), usertypes.UserStatusPendingInvite.StringValue()})
|
||||
if err == nil {
|
||||
stats["user.count"] = counts[types.UserStatusActive] + counts[types.UserStatusDeleted] + counts[types.UserStatusPendingInvite]
|
||||
stats["user.count.active"] = counts[types.UserStatusActive]
|
||||
stats["user.count.deleted"] = counts[types.UserStatusDeleted]
|
||||
stats["user.count.pending_invite"] = counts[types.UserStatusPendingInvite]
|
||||
stats["user.count"] = counts[usertypes.UserStatusActive] + counts[usertypes.UserStatusDeleted] + counts[usertypes.UserStatusPendingInvite]
|
||||
stats["user.count.active"] = counts[usertypes.UserStatusActive]
|
||||
stats["user.count.deleted"] = counts[usertypes.UserStatusDeleted]
|
||||
stats["user.count.pending_invite"] = counts[usertypes.UserStatusPendingInvite]
|
||||
}
|
||||
|
||||
count, err := module.store.CountAPIKeyByOrgID(ctx, orgID)
|
||||
@@ -743,14 +759,16 @@ func (module *Module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
|
||||
}
|
||||
|
||||
// this function restricts that only one non-deleted user email can exist for an org ID, if found more, it throws an error
|
||||
func (module *Module) GetNonDeletedUserByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) (*types.User, error) {
|
||||
existingUsers, err := module.store.GetUsersByEmailAndOrgID(ctx, email, orgID)
|
||||
func (module *Module) GetNonDeletedUserByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) (*usertypes.User, error) {
|
||||
existingStorableUsers, err := module.store.GetUsersByEmailAndOrgID(ctx, email, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingUsers := usertypes.NewUsersFromStorables(existingStorableUsers)
|
||||
|
||||
// filter out the deleted users
|
||||
existingUsers = slices.DeleteFunc(existingUsers, func(user *types.User) bool { return user.ErrIfDeleted() != nil })
|
||||
existingUsers = slices.DeleteFunc(existingUsers, func(user *usertypes.User) bool { return user.ErrIfDeleted() != nil })
|
||||
|
||||
if len(existingUsers) > 1 {
|
||||
return nil, errors.Newf(errors.TypeInternal, errors.CodeInternal, "Multiple non-deleted users found for email %s in org_id: %s", email.StringValue(), orgID.StringValue())
|
||||
@@ -764,10 +782,10 @@ func (module *Module) GetNonDeletedUserByEmailAndOrgID(ctx context.Context, emai
|
||||
|
||||
}
|
||||
|
||||
func (module *Module) createUserWithoutGrant(ctx context.Context, input *types.User, opts ...root.CreateUserOption) error {
|
||||
func (module *Module) createUserWithoutGrant(ctx context.Context, input *usertypes.User, opts ...root.CreateUserOption) error {
|
||||
createUserOpts := root.NewCreateUserOptions(opts...)
|
||||
if err := module.store.RunInTx(ctx, func(ctx context.Context) error {
|
||||
if err := module.store.CreateUser(ctx, input); err != nil {
|
||||
if err := module.store.CreateUser(ctx, usertypes.NewStorableUser(input)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -782,28 +800,28 @@ func (module *Module) createUserWithoutGrant(ctx context.Context, input *types.U
|
||||
return err
|
||||
}
|
||||
|
||||
traitsOrProperties := types.NewTraitsFromUser(input)
|
||||
traitsOrProperties := usertypes.NewTraitsFromUser(input)
|
||||
module.analytics.IdentifyUser(ctx, input.OrgID.String(), input.ID.String(), traitsOrProperties)
|
||||
module.analytics.TrackUser(ctx, input.OrgID.String(), input.ID.String(), "User Created", traitsOrProperties)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *Module) activatePendingUser(ctx context.Context, user *types.User) error {
|
||||
func (module *Module) activatePendingUser(ctx context.Context, user *usertypes.User) error {
|
||||
err := module.authz.Grant(
|
||||
ctx,
|
||||
user.OrgID,
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(user.Role)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, user.ID.StringValue(), user.OrgID, nil),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := user.UpdateStatus(types.UserStatusActive); err != nil {
|
||||
if err := user.UpdateStatus(usertypes.UserStatusActive); err != nil {
|
||||
return err
|
||||
}
|
||||
err = module.store.UpdateUser(ctx, user.OrgID, user)
|
||||
err = module.store.UpdateUser(ctx, user.OrgID, usertypes.NewStorableUser(user))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
settings factory.ScopedProviderSettings
|
||||
store types.UserStore
|
||||
store usertypes.UserStore
|
||||
module user.Module
|
||||
orgGetter organization.Getter
|
||||
authz authz.AuthZ
|
||||
@@ -27,7 +27,7 @@ type service struct {
|
||||
|
||||
func NewService(
|
||||
providerSettings factory.ProviderSettings,
|
||||
store types.UserStore,
|
||||
store usertypes.UserStore,
|
||||
module user.Module,
|
||||
orgGetter organization.Getter,
|
||||
authz authz.AuthZ,
|
||||
@@ -130,10 +130,11 @@ func (s *service) reconcileByName(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *service) reconcileRootUser(ctx context.Context, orgID valuer.UUID) error {
|
||||
existingRoot, err := s.store.GetRootUserByOrgID(ctx, orgID)
|
||||
existingStorableRoot, err := s.store.GetRootUserByOrgID(ctx, orgID)
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
existingRoot := usertypes.NewUserFromStorable(existingStorableRoot)
|
||||
|
||||
if existingRoot == nil {
|
||||
return s.createOrPromoteRootUser(ctx, orgID)
|
||||
@@ -156,11 +157,11 @@ func (s *service) createOrPromoteRootUser(ctx context.Context, orgID valuer.UUID
|
||||
return err
|
||||
}
|
||||
|
||||
if oldRole != types.RoleAdmin {
|
||||
if oldRole != authtypes.RoleAdmin {
|
||||
if err := s.authz.ModifyGrant(ctx,
|
||||
orgID,
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(oldRole)},
|
||||
[]string{roletypes.MustGetSigNozManagedRoleFromExistingRole(types.RoleAdmin)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(oldRole)},
|
||||
[]string{authtypes.MustGetSigNozManagedRoleFromExistingRole(authtypes.RoleAdmin)},
|
||||
authtypes.MustNewSubject(authtypes.TypeableUser, existingUser.ID.StringValue(), orgID, nil),
|
||||
); err != nil {
|
||||
return err
|
||||
@@ -171,12 +172,12 @@ func (s *service) createOrPromoteRootUser(ctx context.Context, orgID valuer.UUID
|
||||
}
|
||||
|
||||
// Create new root user
|
||||
newUser, err := types.NewRootUser(s.config.Email.String(), s.config.Email, orgID)
|
||||
newUser, err := usertypes.NewRootUser(s.config.Email.String(), s.config.Email, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
factorPassword, err := types.NewFactorPassword(s.config.Password, newUser.ID.StringValue())
|
||||
factorPassword, err := usertypes.NewFactorPassword(s.config.Password, newUser.ID.StringValue())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -184,7 +185,7 @@ func (s *service) createOrPromoteRootUser(ctx context.Context, orgID valuer.UUID
|
||||
return s.module.CreateUser(ctx, newUser, user.WithFactorPassword(factorPassword))
|
||||
}
|
||||
|
||||
func (s *service) updateExistingRootUser(ctx context.Context, orgID valuer.UUID, existingRoot *types.User) error {
|
||||
func (s *service) updateExistingRootUser(ctx context.Context, orgID valuer.UUID, existingRoot *usertypes.User) error {
|
||||
existingRoot.PromoteToRoot()
|
||||
|
||||
if existingRoot.Email != s.config.Email {
|
||||
@@ -204,7 +205,7 @@ func (s *service) setPassword(ctx context.Context, userID valuer.UUID) error {
|
||||
return err
|
||||
}
|
||||
|
||||
factorPassword, err := types.NewFactorPassword(s.config.Password, userID.StringValue())
|
||||
factorPassword, err := usertypes.NewFactorPassword(s.config.Password, userID.StringValue())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -21,11 +21,11 @@ type store struct {
|
||||
settings factory.ProviderSettings
|
||||
}
|
||||
|
||||
func NewStore(sqlstore sqlstore.SQLStore, settings factory.ProviderSettings) types.UserStore {
|
||||
func NewStore(sqlstore sqlstore.SQLStore, settings factory.ProviderSettings) usertypes.UserStore {
|
||||
return &store{sqlstore: sqlstore, settings: settings}
|
||||
}
|
||||
|
||||
func (store *store) CreatePassword(ctx context.Context, password *types.FactorPassword) error {
|
||||
func (store *store) CreatePassword(ctx context.Context, password *usertypes.FactorPassword) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -33,13 +33,13 @@ func (store *store) CreatePassword(ctx context.Context, password *types.FactorPa
|
||||
Model(password).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrPasswordAlreadyExists, "password for user %s already exists", password.UserID)
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, usertypes.ErrPasswordAlreadyExists, "password for user %s already exists", password.UserID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) CreateUser(ctx context.Context, user *types.User) error {
|
||||
func (store *store) CreateUser(ctx context.Context, user *usertypes.StorableUser) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -47,13 +47,13 @@ func (store *store) CreateUser(ctx context.Context, user *types.User) error {
|
||||
Model(user).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrUserAlreadyExists, "user with email %s already exists in org %s", user.Email, user.OrgID)
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, usertypes.ErrUserAlreadyExists, "user with email %s already exists in org %s", user.Email, user.OrgID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetUsersByEmail(ctx context.Context, email valuer.Email) ([]*types.User, error) {
|
||||
var users []*types.User
|
||||
func (store *store) GetUsersByEmail(ctx context.Context, email valuer.Email) ([]*usertypes.StorableUser, error) {
|
||||
var users []*usertypes.StorableUser
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -69,8 +69,8 @@ func (store *store) GetUsersByEmail(ctx context.Context, email valuer.Email) ([]
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (store *store) GetUser(ctx context.Context, id valuer.UUID) (*types.User, error) {
|
||||
user := new(types.User)
|
||||
func (store *store) GetUser(ctx context.Context, id valuer.UUID) (*usertypes.StorableUser, error) {
|
||||
user := new(usertypes.StorableUser)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -80,14 +80,14 @@ func (store *store) GetUser(ctx context.Context, id valuer.UUID) (*types.User, e
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "user with id %s does not exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "user with id %s does not exist", id)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (store *store) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*types.User, error) {
|
||||
user := new(types.User)
|
||||
func (store *store) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*usertypes.StorableUser, error) {
|
||||
user := new(usertypes.StorableUser)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -98,14 +98,14 @@ func (store *store) GetByOrgIDAndID(ctx context.Context, orgID valuer.UUID, id v
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "user with id %s does not exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "user with id %s does not exist", id)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (store *store) GetUsersByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) ([]*types.User, error) {
|
||||
var users []*types.User
|
||||
func (store *store) GetUsersByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) ([]*usertypes.StorableUser, error) {
|
||||
var users []*usertypes.StorableUser
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -122,8 +122,8 @@ func (store *store) GetUsersByEmailAndOrgID(ctx context.Context, email valuer.Em
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (store *store) GetActiveUsersByRoleAndOrgID(ctx context.Context, role types.Role, orgID valuer.UUID) ([]*types.User, error) {
|
||||
var users []*types.User
|
||||
func (store *store) GetActiveUsersByRoleAndOrgID(ctx context.Context, role authtypes.LegacyRole, orgID valuer.UUID) ([]*usertypes.StorableUser, error) {
|
||||
var users []*usertypes.StorableUser
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -132,7 +132,7 @@ func (store *store) GetActiveUsersByRoleAndOrgID(ctx context.Context, role types
|
||||
Model(&users).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("role = ?", role).
|
||||
Where("status = ?", types.UserStatusActive.StringValue()).
|
||||
Where("status = ?", usertypes.UserStatusActive.StringValue()).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -141,7 +141,7 @@ func (store *store) GetActiveUsersByRoleAndOrgID(ctx context.Context, role types
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (store *store) UpdateUser(ctx context.Context, orgID valuer.UUID, user *types.User) error {
|
||||
func (store *store) UpdateUser(ctx context.Context, orgID valuer.UUID, user *usertypes.StorableUser) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -157,13 +157,13 @@ func (store *store) UpdateUser(ctx context.Context, orgID valuer.UUID, user *typ
|
||||
Where("id = ?", user.ID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "user does not exist in org: %s", orgID)
|
||||
return store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "user does not exist in org: %s", orgID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) ListUsersByOrgID(ctx context.Context, orgID valuer.UUID) ([]*types.GettableUser, error) {
|
||||
users := []*types.User{}
|
||||
func (store *store) ListUsersByOrgID(ctx context.Context, orgID valuer.UUID) ([]*usertypes.StorableUser, error) {
|
||||
users := []*usertypes.StorableUser{}
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -191,7 +191,7 @@ func (store *store) DeleteUser(ctx context.Context, orgID string, id string) err
|
||||
|
||||
// get the password id
|
||||
|
||||
var password types.FactorPassword
|
||||
var password usertypes.FactorPassword
|
||||
err = tx.NewSelect().
|
||||
Model(&password).
|
||||
Where("user_id = ?", id).
|
||||
@@ -202,7 +202,7 @@ func (store *store) DeleteUser(ctx context.Context, orgID string, id string) err
|
||||
|
||||
// delete reset password request
|
||||
_, err = tx.NewDelete().
|
||||
Model(new(types.ResetPasswordToken)).
|
||||
Model(new(usertypes.ResetPasswordToken)).
|
||||
Where("password_id = ?", password.ID.String()).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -211,7 +211,7 @@ func (store *store) DeleteUser(ctx context.Context, orgID string, id string) err
|
||||
|
||||
// delete factor password
|
||||
_, err = tx.NewDelete().
|
||||
Model(new(types.FactorPassword)).
|
||||
Model(new(usertypes.FactorPassword)).
|
||||
Where("user_id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -220,7 +220,7 @@ func (store *store) DeleteUser(ctx context.Context, orgID string, id string) err
|
||||
|
||||
// delete api keys
|
||||
_, err = tx.NewDelete().
|
||||
Model(&types.StorableAPIKey{}).
|
||||
Model(&usertypes.StorableAPIKey{}).
|
||||
Where("user_id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -247,7 +247,7 @@ func (store *store) DeleteUser(ctx context.Context, orgID string, id string) err
|
||||
|
||||
// delete user
|
||||
_, err = tx.NewDelete().
|
||||
Model(new(types.User)).
|
||||
Model(new(usertypes.StorableUser)).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
@@ -275,7 +275,7 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
|
||||
// get the password id
|
||||
|
||||
var password types.FactorPassword
|
||||
var password usertypes.FactorPassword
|
||||
err = tx.NewSelect().
|
||||
Model(&password).
|
||||
Where("user_id = ?", id).
|
||||
@@ -286,7 +286,7 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
|
||||
// delete reset password request
|
||||
_, err = tx.NewDelete().
|
||||
Model(new(types.ResetPasswordToken)).
|
||||
Model(new(usertypes.ResetPasswordToken)).
|
||||
Where("password_id = ?", password.ID.String()).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -295,7 +295,7 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
|
||||
// delete factor password
|
||||
_, err = tx.NewDelete().
|
||||
Model(new(types.FactorPassword)).
|
||||
Model(new(usertypes.FactorPassword)).
|
||||
Where("user_id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -304,7 +304,7 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
|
||||
// delete api keys
|
||||
_, err = tx.NewDelete().
|
||||
Model(&types.StorableAPIKey{}).
|
||||
Model(&usertypes.StorableAPIKey{}).
|
||||
Where("user_id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -332,8 +332,8 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
// soft delete user
|
||||
now := time.Now()
|
||||
_, err = tx.NewUpdate().
|
||||
Model(new(types.User)).
|
||||
Set("status = ?", types.UserStatusDeleted).
|
||||
Model(new(usertypes.StorableUser)).
|
||||
Set("status = ?", usertypes.UserStatusDeleted).
|
||||
Set("deleted_at = ?", now).
|
||||
Set("updated_at = ?", now).
|
||||
Where("org_id = ?", orgID).
|
||||
@@ -351,7 +351,7 @@ func (store *store) SoftDeleteUser(ctx context.Context, orgID string, id string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) CreateResetPasswordToken(ctx context.Context, resetPasswordToken *types.ResetPasswordToken) error {
|
||||
func (store *store) CreateResetPasswordToken(ctx context.Context, resetPasswordToken *usertypes.ResetPasswordToken) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -359,14 +359,14 @@ func (store *store) CreateResetPasswordToken(ctx context.Context, resetPasswordT
|
||||
Model(resetPasswordToken).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrResetPasswordTokenAlreadyExists, "reset password token for password %s already exists", resetPasswordToken.PasswordID)
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, usertypes.ErrResetPasswordTokenAlreadyExists, "reset password token for password %s already exists", resetPasswordToken.PasswordID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetPassword(ctx context.Context, id valuer.UUID) (*types.FactorPassword, error) {
|
||||
password := new(types.FactorPassword)
|
||||
func (store *store) GetPassword(ctx context.Context, id valuer.UUID) (*usertypes.FactorPassword, error) {
|
||||
password := new(usertypes.FactorPassword)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -376,14 +376,14 @@ func (store *store) GetPassword(ctx context.Context, id valuer.UUID) (*types.Fac
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password with id: %s does not exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodePasswordNotFound, "password with id: %s does not exist", id)
|
||||
}
|
||||
|
||||
return password, nil
|
||||
}
|
||||
|
||||
func (store *store) GetPasswordByUserID(ctx context.Context, userID valuer.UUID) (*types.FactorPassword, error) {
|
||||
password := new(types.FactorPassword)
|
||||
func (store *store) GetPasswordByUserID(ctx context.Context, userID valuer.UUID) (*usertypes.FactorPassword, error) {
|
||||
password := new(usertypes.FactorPassword)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -393,13 +393,13 @@ func (store *store) GetPasswordByUserID(ctx context.Context, userID valuer.UUID)
|
||||
Where("user_id = ?", userID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password for user %s does not exist", userID)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodePasswordNotFound, "password for user %s does not exist", userID)
|
||||
}
|
||||
return password, nil
|
||||
}
|
||||
|
||||
func (store *store) GetResetPasswordTokenByPasswordID(ctx context.Context, passwordID valuer.UUID) (*types.ResetPasswordToken, error) {
|
||||
resetPasswordToken := new(types.ResetPasswordToken)
|
||||
func (store *store) GetResetPasswordTokenByPasswordID(ctx context.Context, passwordID valuer.UUID) (*usertypes.ResetPasswordToken, error) {
|
||||
resetPasswordToken := new(usertypes.ResetPasswordToken)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -409,7 +409,7 @@ func (store *store) GetResetPasswordTokenByPasswordID(ctx context.Context, passw
|
||||
Where("password_id = ?", passwordID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrResetPasswordTokenNotFound, "reset password token for password %s does not exist", passwordID)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrResetPasswordTokenNotFound, "reset password token for password %s does not exist", passwordID)
|
||||
}
|
||||
|
||||
return resetPasswordToken, nil
|
||||
@@ -417,7 +417,7 @@ func (store *store) GetResetPasswordTokenByPasswordID(ctx context.Context, passw
|
||||
|
||||
func (store *store) DeleteResetPasswordTokenByPasswordID(ctx context.Context, passwordID valuer.UUID) error {
|
||||
_, err := store.sqlstore.BunDBCtx(ctx).NewDelete().
|
||||
Model(&types.ResetPasswordToken{}).
|
||||
Model(&usertypes.ResetPasswordToken{}).
|
||||
Where("password_id = ?", passwordID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
@@ -427,8 +427,8 @@ func (store *store) DeleteResetPasswordTokenByPasswordID(ctx context.Context, pa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetResetPasswordToken(ctx context.Context, token string) (*types.ResetPasswordToken, error) {
|
||||
resetPasswordRequest := new(types.ResetPasswordToken)
|
||||
func (store *store) GetResetPasswordToken(ctx context.Context, token string) (*usertypes.ResetPasswordToken, error) {
|
||||
resetPasswordRequest := new(usertypes.ResetPasswordToken)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -438,38 +438,38 @@ func (store *store) GetResetPasswordToken(ctx context.Context, token string) (*t
|
||||
Where("token = ?", token).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrResetPasswordTokenNotFound, "reset password token does not exist")
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrResetPasswordTokenNotFound, "reset password token does not exist")
|
||||
}
|
||||
|
||||
return resetPasswordRequest, nil
|
||||
}
|
||||
|
||||
func (store *store) UpdatePassword(ctx context.Context, factorPassword *types.FactorPassword) error {
|
||||
func (store *store) UpdatePassword(ctx context.Context, factorPassword *usertypes.FactorPassword) error {
|
||||
_, err := store.sqlstore.BunDBCtx(ctx).
|
||||
NewUpdate().
|
||||
Model(factorPassword).
|
||||
Where("user_id = ?", factorPassword.UserID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password for user %s does not exist", factorPassword.UserID)
|
||||
return store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodePasswordNotFound, "password for user %s does not exist", factorPassword.UserID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- API KEY ---
|
||||
func (store *store) CreateAPIKey(ctx context.Context, apiKey *types.StorableAPIKey) error {
|
||||
func (store *store) CreateAPIKey(ctx context.Context, apiKey *usertypes.StorableAPIKey) error {
|
||||
_, err := store.sqlstore.BunDB().NewInsert().
|
||||
Model(apiKey).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrAPIKeyAlreadyExists, "API key with token: %s already exists", apiKey.Token)
|
||||
return store.sqlstore.WrapAlreadyExistsErrf(err, usertypes.ErrAPIKeyAlreadyExists, "API key with token: %s already exists", apiKey.Token)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *types.StorableAPIKey, updaterID valuer.UUID) error {
|
||||
func (store *store) UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *usertypes.StorableAPIKey, updaterID valuer.UUID) error {
|
||||
apiKey.UpdatedBy = updaterID.String()
|
||||
apiKey.UpdatedAt = time.Now()
|
||||
_, err := store.sqlstore.BunDB().NewUpdate().
|
||||
@@ -479,13 +479,13 @@ func (store *store) UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *ty
|
||||
Where("revoked = false").
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return store.sqlstore.WrapNotFoundErrf(err, types.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
return store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*types.StorableAPIKeyUser, error) {
|
||||
orgUserAPIKeys := new(types.OrgUserAPIKey)
|
||||
func (store *store) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*usertypes.StorableAPIKeyUser, error) {
|
||||
orgUserAPIKeys := new(usertypes.OrgUserAPIKey)
|
||||
|
||||
if err := store.sqlstore.BunDB().NewSelect().
|
||||
Model(orgUserAPIKeys).
|
||||
@@ -502,7 +502,7 @@ func (store *store) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*type
|
||||
}
|
||||
|
||||
// Flatten the API keys from all users
|
||||
var allAPIKeys []*types.StorableAPIKeyUser
|
||||
var allAPIKeys []*usertypes.StorableAPIKeyUser
|
||||
for _, user := range orgUserAPIKeys.Users {
|
||||
if user.APIKeys != nil {
|
||||
allAPIKeys = append(allAPIKeys, user.APIKeys...)
|
||||
@@ -520,7 +520,7 @@ func (store *store) ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*type
|
||||
func (store *store) RevokeAPIKey(ctx context.Context, id, revokedByUserID valuer.UUID) error {
|
||||
updatedAt := time.Now().Unix()
|
||||
_, err := store.sqlstore.BunDB().NewUpdate().
|
||||
Model(&types.StorableAPIKey{}).
|
||||
Model(&usertypes.StorableAPIKey{}).
|
||||
Set("revoked = ?", true).
|
||||
Set("updated_by = ?", revokedByUserID).
|
||||
Set("updated_at = ?", updatedAt).
|
||||
@@ -532,8 +532,8 @@ func (store *store) RevokeAPIKey(ctx context.Context, id, revokedByUserID valuer
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*types.StorableAPIKeyUser, error) {
|
||||
apiKey := new(types.OrgUserAPIKey)
|
||||
func (store *store) GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*usertypes.StorableAPIKeyUser, error) {
|
||||
apiKey := new(usertypes.OrgUserAPIKey)
|
||||
if err := store.sqlstore.BunDB().NewSelect().
|
||||
Model(apiKey).
|
||||
Relation("Users").
|
||||
@@ -545,25 +545,25 @@ func (store *store) GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*type
|
||||
Relation("Users.APIKeys.CreatedByUser").
|
||||
Relation("Users.APIKeys.UpdatedByUser").
|
||||
Scan(ctx); err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
}
|
||||
|
||||
// flatten the API keys
|
||||
flattenedAPIKeys := []*types.StorableAPIKeyUser{}
|
||||
flattenedAPIKeys := []*usertypes.StorableAPIKeyUser{}
|
||||
for _, user := range apiKey.Users {
|
||||
if user.APIKeys != nil {
|
||||
flattenedAPIKeys = append(flattenedAPIKeys, user.APIKeys...)
|
||||
}
|
||||
}
|
||||
if len(flattenedAPIKeys) == 0 {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(errors.New(errors.TypeNotFound, errors.CodeNotFound, "API key with id: %s does not exist"), types.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(errors.New(errors.TypeNotFound, errors.CodeNotFound, "API key with id: %s does not exist"), usertypes.ErrAPIKeyNotFound, "API key with id: %s does not exist", id)
|
||||
}
|
||||
|
||||
return flattenedAPIKeys[0], nil
|
||||
}
|
||||
|
||||
func (store *store) CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error) {
|
||||
user := new(types.User)
|
||||
user := new(usertypes.StorableUser)
|
||||
|
||||
count, err := store.
|
||||
sqlstore.
|
||||
@@ -580,7 +580,7 @@ func (store *store) CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64,
|
||||
}
|
||||
|
||||
func (store *store) CountByOrgIDAndStatuses(ctx context.Context, orgID valuer.UUID, statuses []string) (map[valuer.String]int64, error) {
|
||||
user := new(types.User)
|
||||
user := new(usertypes.StorableUser)
|
||||
var results []struct {
|
||||
Status valuer.String `bun:"status"`
|
||||
Count int64 `bun:"count"`
|
||||
@@ -610,7 +610,7 @@ func (store *store) CountByOrgIDAndStatuses(ctx context.Context, orgID valuer.UU
|
||||
}
|
||||
|
||||
func (store *store) CountAPIKeyByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error) {
|
||||
apiKey := new(types.StorableAPIKey)
|
||||
apiKey := new(usertypes.StorableAPIKey)
|
||||
|
||||
count, err := store.
|
||||
sqlstore.
|
||||
@@ -633,8 +633,8 @@ func (store *store) RunInTx(ctx context.Context, cb func(ctx context.Context) er
|
||||
})
|
||||
}
|
||||
|
||||
func (store *store) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (*types.User, error) {
|
||||
user := new(types.User)
|
||||
func (store *store) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (*usertypes.StorableUser, error) {
|
||||
user := new(usertypes.StorableUser)
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
@@ -644,13 +644,13 @@ func (store *store) GetRootUserByOrgID(ctx context.Context, orgID valuer.UUID) (
|
||||
Where("is_root = ?", true).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "root user for org %s not found", orgID)
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "root user for org %s not found", orgID)
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (store *store) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.Email, orgIDs []valuer.UUID) ([]*types.User, error) {
|
||||
users := []*types.User{}
|
||||
func (store *store) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.Email, orgIDs []valuer.UUID) ([]*usertypes.StorableUser, error) {
|
||||
users := []*usertypes.StorableUser{}
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
@@ -666,8 +666,8 @@ func (store *store) ListUsersByEmailAndOrgIDs(ctx context.Context, email valuer.
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (store *store) GetUserByResetPasswordToken(ctx context.Context, token string) (*types.User, error) {
|
||||
user := new(types.User)
|
||||
func (store *store) GetUserByResetPasswordToken(ctx context.Context, token string) (*usertypes.StorableUser, error) {
|
||||
user := new(usertypes.StorableUser)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -679,14 +679,14 @@ func (store *store) GetUserByResetPasswordToken(ctx context.Context, token strin
|
||||
Where("reset_password_token.token = ?", token).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrCodeUserNotFound, "user not found for reset password token")
|
||||
return nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "user not found for reset password token")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (store *store) GetUsersByEmailsOrgIDAndStatuses(ctx context.Context, orgID valuer.UUID, emails []string, statuses []string) ([]*types.User, error) {
|
||||
users := []*types.User{}
|
||||
func (store *store) GetUsersByEmailsOrgIDAndStatuses(ctx context.Context, orgID valuer.UUID, emails []string, statuses []string) ([]*usertypes.StorableUser, error) {
|
||||
users := []*usertypes.StorableUser{}
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
@@ -703,3 +703,34 @@ func (store *store) GetUsersByEmailsOrgIDAndStatuses(ctx context.Context, orgID
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (store *store) GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx context.Context, email string, orgID valuer.UUID) (*usertypes.StorableUser, *usertypes.FactorPassword, error) {
|
||||
user := new(usertypes.StorableUser)
|
||||
factorPassword := new(usertypes.FactorPassword)
|
||||
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(user).
|
||||
Where("email = ?", email).
|
||||
Where("org_id = ?", orgID).
|
||||
Where("status = ?", usertypes.UserStatusActive.StringValue()).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodeUserNotFound, "user with email %s in org %s not found", email, orgID)
|
||||
}
|
||||
|
||||
err = store.
|
||||
sqlstore.
|
||||
BunDBCtx(ctx).
|
||||
NewSelect().
|
||||
Model(factorPassword).
|
||||
Where("user_id = ?", user.ID).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, store.sqlstore.WrapNotFoundErrf(err, usertypes.ErrCodePasswordNotFound, "user with email %s in org %s does not have password", email, orgID)
|
||||
}
|
||||
|
||||
return user, factorPassword, nil
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type createUserOptions struct {
|
||||
FactorPassword *types.FactorPassword
|
||||
FactorPassword *usertypes.FactorPassword
|
||||
}
|
||||
|
||||
type CreateUserOption func(*createUserOptions)
|
||||
|
||||
func WithFactorPassword(factorPassword *types.FactorPassword) CreateUserOption {
|
||||
func WithFactorPassword(factorPassword *usertypes.FactorPassword) CreateUserOption {
|
||||
return func(o *createUserOptions) {
|
||||
o.FactorPassword = factorPassword
|
||||
}
|
||||
|
||||
@@ -6,22 +6,23 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type Module interface {
|
||||
// Creates the organization and the first user of that organization.
|
||||
CreateFirstUser(ctx context.Context, organization *types.Organization, name string, email valuer.Email, password string) (*types.User, error)
|
||||
CreateFirstUser(ctx context.Context, organization *types.Organization, name string, email valuer.Email, password string) (*usertypes.User, error)
|
||||
|
||||
// Creates a user and sends an analytics event.
|
||||
CreateUser(ctx context.Context, user *types.User, opts ...CreateUserOption) error
|
||||
CreateUser(ctx context.Context, user *usertypes.User, opts ...CreateUserOption) error
|
||||
|
||||
// Get or create a user. If a user with the same email and orgID already exists, it returns the existing user.
|
||||
GetOrCreateUser(ctx context.Context, user *types.User, opts ...CreateUserOption) (*types.User, error)
|
||||
GetOrCreateUser(ctx context.Context, user *usertypes.User, opts ...CreateUserOption) (*usertypes.User, error)
|
||||
|
||||
// Get or Create a reset password token for a user. If the password does not exist, a new one is randomly generated and inserted. The function
|
||||
// is idempotent and can be called multiple times.
|
||||
GetOrCreateResetPasswordToken(ctx context.Context, userID valuer.UUID) (*types.ResetPasswordToken, error)
|
||||
GetOrCreateResetPasswordToken(ctx context.Context, userID valuer.UUID) (*usertypes.ResetPasswordToken, error)
|
||||
|
||||
// Updates password of a user using a reset password token. It also deletes all reset password tokens for the user.
|
||||
// This is used to reset the password of a user when they forget their password.
|
||||
@@ -33,48 +34,48 @@ type Module interface {
|
||||
// Initiate forgot password flow for a user
|
||||
ForgotPassword(ctx context.Context, orgID valuer.UUID, email valuer.Email, frontendBaseURL string) error
|
||||
|
||||
UpdateUser(ctx context.Context, orgID valuer.UUID, id string, user *types.User, updatedBy string) (*types.User, error)
|
||||
UpdateUser(ctx context.Context, orgID valuer.UUID, id string, user *usertypes.User, updatedBy string) (*usertypes.User, error)
|
||||
|
||||
// UpdateAnyUser updates a user and persists the changes to the database along with the analytics and identity deletion.
|
||||
UpdateAnyUser(ctx context.Context, orgID valuer.UUID, user *types.User) error
|
||||
UpdateAnyUser(ctx context.Context, orgID valuer.UUID, user *usertypes.User) error
|
||||
DeleteUser(ctx context.Context, orgID valuer.UUID, id string, deletedBy string) error
|
||||
|
||||
// invite
|
||||
CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, bulkInvites *types.PostableBulkInviteRequest) ([]*types.Invite, error)
|
||||
ListInvite(ctx context.Context, orgID string) ([]*types.Invite, error)
|
||||
AcceptInvite(ctx context.Context, token string, password string) (*types.User, error)
|
||||
GetInviteByToken(ctx context.Context, token string) (*types.Invite, error)
|
||||
CreateBulkInvite(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, bulkInvites *usertypes.PostableBulkInviteRequest) ([]*usertypes.Invite, error)
|
||||
ListInvite(ctx context.Context, orgID string) ([]*usertypes.Invite, error)
|
||||
AcceptInvite(ctx context.Context, token string, password string) (*usertypes.User, error)
|
||||
GetInviteByToken(ctx context.Context, token string) (*usertypes.Invite, error)
|
||||
|
||||
// API KEY
|
||||
CreateAPIKey(ctx context.Context, apiKey *types.StorableAPIKey) error
|
||||
UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *types.StorableAPIKey, updaterID valuer.UUID) error
|
||||
ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*types.StorableAPIKeyUser, error)
|
||||
CreateAPIKey(ctx context.Context, apiKey *usertypes.StorableAPIKey) error
|
||||
UpdateAPIKey(ctx context.Context, id valuer.UUID, apiKey *usertypes.StorableAPIKey, updaterID valuer.UUID) error
|
||||
ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*usertypes.StorableAPIKeyUser, error)
|
||||
RevokeAPIKey(ctx context.Context, id, removedByUserID valuer.UUID) error
|
||||
GetAPIKey(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*types.StorableAPIKeyUser, error)
|
||||
GetAPIKey(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*usertypes.StorableAPIKeyUser, error)
|
||||
|
||||
GetNonDeletedUserByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) (*types.User, error)
|
||||
GetNonDeletedUserByEmailAndOrgID(ctx context.Context, email valuer.Email, orgID valuer.UUID) (*usertypes.User, error)
|
||||
|
||||
statsreporter.StatsCollector
|
||||
}
|
||||
|
||||
type Getter interface {
|
||||
// Get root user by org id.
|
||||
GetRootUserByOrgID(context.Context, valuer.UUID) (*types.User, error)
|
||||
GetRootUserByOrgID(context.Context, valuer.UUID) (*usertypes.User, error)
|
||||
|
||||
// Get gets the users based on the given id
|
||||
ListByOrgID(context.Context, valuer.UUID) ([]*types.User, error)
|
||||
ListByOrgID(context.Context, valuer.UUID) ([]*usertypes.User, error)
|
||||
|
||||
// Get users by email.
|
||||
GetUsersByEmail(context.Context, valuer.Email) ([]*types.User, error)
|
||||
GetUsersByEmail(context.Context, valuer.Email) ([]*usertypes.User, error)
|
||||
|
||||
// Get user by orgID and id.
|
||||
GetByOrgIDAndID(context.Context, valuer.UUID, valuer.UUID) (*types.User, error)
|
||||
GetByOrgIDAndID(context.Context, valuer.UUID, valuer.UUID) (*usertypes.User, error)
|
||||
|
||||
// Get user by id.
|
||||
Get(context.Context, valuer.UUID) (*types.User, error)
|
||||
Get(context.Context, valuer.UUID) (*usertypes.User, error)
|
||||
|
||||
// List users by email and org ids.
|
||||
ListUsersByEmailAndOrgIDs(context.Context, valuer.Email, []valuer.UUID) ([]*types.User, error)
|
||||
ListUsersByEmailAndOrgIDs(context.Context, valuer.Email, []valuer.UUID) ([]*usertypes.User, error)
|
||||
|
||||
// Count users by org id.
|
||||
CountByOrgID(context.Context, valuer.UUID) (int64, error)
|
||||
@@ -83,7 +84,10 @@ type Getter interface {
|
||||
CountByOrgIDAndStatuses(context.Context, valuer.UUID, []string) (map[valuer.String]int64, error)
|
||||
|
||||
// Get factor password by user id.
|
||||
GetFactorPasswordByUserID(context.Context, valuer.UUID) (*types.FactorPassword, error)
|
||||
GetFactorPasswordByUserID(context.Context, valuer.UUID) (*usertypes.FactorPassword, error)
|
||||
|
||||
// Get Active User and FactorPassword by email and org id.
|
||||
GetActiveUserAndFactorPasswordByEmailAndOrgID(ctx context.Context, email string, orgID valuer.UUID) (*usertypes.User, *usertypes.FactorPassword, error)
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
|
||||
@@ -73,6 +73,7 @@ import (
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/ruletypes"
|
||||
traceFunnels "github.com/SigNoz/signoz/pkg/types/tracefunneltypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/query-service/app/integrations/messagingQueues/kafka"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/app/logparsingpipeline"
|
||||
@@ -2034,7 +2035,7 @@ func (aH *APIHandler) registerUser(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req types.PostableRegisterOrgAndAdmin
|
||||
var req usertypes.PostableRegisterOrgAndAdmin
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(w, err)
|
||||
return
|
||||
|
||||
@@ -196,13 +196,12 @@ func (s *Server) createPublicServer(api *APIHandler, web web.Web) (*http.Server,
|
||||
}),
|
||||
otelmux.WithPublicEndpoint(),
|
||||
))
|
||||
r.Use(middleware.NewAuthN([]string{"Authorization", "Sec-WebSocket-Protocol"}, s.signoz.Sharder, s.signoz.Tokenizer, s.signoz.Instrumentation.Logger()).Wrap)
|
||||
r.Use(middleware.NewIdentN(s.signoz.IdentNResolver, s.signoz.Sharder, s.signoz.Instrumentation.Logger()).Wrap)
|
||||
r.Use(middleware.NewTimeout(s.signoz.Instrumentation.Logger(),
|
||||
s.config.APIServer.Timeout.ExcludedRoutes,
|
||||
s.config.APIServer.Timeout.Default,
|
||||
s.config.APIServer.Timeout.Max,
|
||||
).Wrap)
|
||||
r.Use(middleware.NewAPIKey(s.signoz.SQLStore, []string{"SIGNOZ-API-KEY"}, s.signoz.Instrumentation.Logger(), s.signoz.Sharder).Wrap)
|
||||
r.Use(middleware.NewLogging(s.signoz.Instrumentation.Logger(), s.config.APIServer.Logging.ExcludedRoutes).Wrap)
|
||||
r.Use(middleware.NewComment().Wrap)
|
||||
|
||||
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/authn/passwordauthn/emailpasswordauthn"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
)
|
||||
|
||||
func NewAuthNs(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
emailPasswordAuthN := emailpasswordauthn.New(store)
|
||||
func NewAuthNs(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing, userGetter user.Getter) (map[authtypes.AuthNProvider]authn.AuthN, error) {
|
||||
emailPasswordAuthN := emailpasswordauthn.New(userGetter)
|
||||
|
||||
googleCallbackAuthN, err := googlecallbackauthn.New(ctx, store, providerSettings)
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/session"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/zeus"
|
||||
"github.com/swaggest/jsonschema-go"
|
||||
"github.com/swaggest/openapi-go"
|
||||
@@ -82,8 +82,8 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta
|
||||
|
||||
reflector.SpecSchema().SetTitle("SigNoz")
|
||||
reflector.SpecSchema().SetDescription("OpenTelemetry-Native Logs, Metrics and Traces in a single pane")
|
||||
reflector.SpecSchema().SetAPIKeySecurity(ctxtypes.AuthTypeAPIKey.StringValue(), "SigNoz-Api-Key", openapi.InHeader, "API Keys")
|
||||
reflector.SpecSchema().SetHTTPBearerTokenSecurity(ctxtypes.AuthTypeTokenizer.StringValue(), "Tokenizer", "Tokens generated by the tokenizer")
|
||||
reflector.SpecSchema().SetAPIKeySecurity(authtypes.IdentNProviderAPIkey.StringValue(), "SigNoz-Api-Key", openapi.InHeader, "API Keys")
|
||||
reflector.SpecSchema().SetHTTPBearerTokenSecurity(authtypes.IdentNProviderTokenizer.StringValue(), "Tokenizer", "Tokens generated by the tokenizer")
|
||||
|
||||
collector := handler.NewOpenAPICollector(reflector)
|
||||
|
||||
|
||||
@@ -16,11 +16,15 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/flagger"
|
||||
"github.com/SigNoz/signoz/pkg/gateway"
|
||||
"github.com/SigNoz/signoz/pkg/identn"
|
||||
"github.com/SigNoz/signoz/pkg/identn/apikeyidentn"
|
||||
"github.com/SigNoz/signoz/pkg/identn/tokenizeridentn"
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user/impluser"
|
||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||
"github.com/SigNoz/signoz/pkg/querier"
|
||||
@@ -65,6 +69,7 @@ type SigNoz struct {
|
||||
Sharder sharder.Sharder
|
||||
StatsReporter statsreporter.StatsReporter
|
||||
Tokenizer pkgtokenizer.Tokenizer
|
||||
IdentNResolver identn.IdentNResolver
|
||||
Authz authz.AuthZ
|
||||
Modules Modules
|
||||
Handlers Handlers
|
||||
@@ -86,7 +91,7 @@ func New(
|
||||
sqlSchemaProviderFactories func(sqlstore.SQLStore) factory.NamedMap[factory.ProviderFactory[sqlschema.SQLSchema, sqlschema.Config]],
|
||||
sqlstoreProviderFactories factory.NamedMap[factory.ProviderFactory[sqlstore.SQLStore, sqlstore.Config]],
|
||||
telemetrystoreProviderFactories factory.NamedMap[factory.ProviderFactory[telemetrystore.TelemetryStore, telemetrystore.Config]],
|
||||
authNsCallback func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing) (map[authtypes.AuthNProvider]authn.AuthN, error),
|
||||
authNsCallback func(ctx context.Context, providerSettings factory.ProviderSettings, store authtypes.AuthNStore, licensing licensing.Licensing, userGetter user.Getter) (map[authtypes.AuthNProvider]authn.AuthN, error),
|
||||
authzCallback func(context.Context, sqlstore.SQLStore, licensing.Licensing, dashboard.Module) factory.ProviderFactory[authz.AuthZ, authz.Config],
|
||||
dashboardModuleCallback func(sqlstore.SQLStore, factory.ProviderSettings, analytics.Analytics, organization.Getter, queryparser.QueryParser, querier.Querier, licensing.Licensing) dashboard.Module,
|
||||
gatewayProviderFactory func(licensing.Licensing) factory.ProviderFactory[gateway.Gateway, gateway.Config],
|
||||
@@ -349,7 +354,7 @@ func New(
|
||||
|
||||
// Initialize authns
|
||||
store := sqlauthnstore.NewStore(sqlstore)
|
||||
authNs, err := authNsCallback(ctx, providerSettings, store, licensing)
|
||||
authNs, err := authNsCallback(ctx, providerSettings, store, licensing, userGetter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -390,6 +395,11 @@ func New(
|
||||
// Initialize all modules
|
||||
modules := NewModules(sqlstore, tokenizer, emailing, providerSettings, orgGetter, alertmanager, analytics, querier, telemetrystore, telemetryMetadataStore, authNs, authz, cache, queryParser, config, dashboard, userGetter)
|
||||
|
||||
// Initialize identN resolver
|
||||
tokenizeridentN := tokenizeridentn.New(providerSettings, tokenizer, []string{"Authorization", "Sec-WebSocket-Protocol"})
|
||||
apikeyIdentN := apikeyidentn.New(providerSettings, sqlstore, []string{"SIGNOZ-API-KEY"})
|
||||
identNResolver := identn.NewIdentNResolver(providerSettings, tokenizeridentN, apikeyIdentN)
|
||||
|
||||
userService := impluser.NewService(providerSettings, impluser.NewStore(sqlstore, providerSettings), modules.User, orgGetter, authz, config.User.Root)
|
||||
|
||||
// Initialize the querier handler via callback (allows EE to decorate with anomaly detection)
|
||||
@@ -468,6 +478,7 @@ func New(
|
||||
Emailing: emailing,
|
||||
Sharder: sharder,
|
||||
Tokenizer: tokenizer,
|
||||
IdentNResolver: identNResolver,
|
||||
Authz: authz,
|
||||
Modules: modules,
|
||||
Handlers: handlers,
|
||||
|
||||
@@ -2,9 +2,11 @@ package sqlmigration
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
@@ -16,12 +18,12 @@ type funnel struct {
|
||||
types.Identifiable // funnel id
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
Name string `json:"funnel_name" bun:"name,type:text,notnull"` // funnel name
|
||||
Description string `json:"description" bun:"description,type:text"` // funnel description
|
||||
OrgID valuer.UUID `json:"org_id" bun:"org_id,type:varchar,notnull"`
|
||||
Steps []funnelStep `json:"steps" bun:"steps,type:text,notnull"`
|
||||
Tags string `json:"tags" bun:"tags,type:text"`
|
||||
CreatedByUser *types.User `json:"user" bun:"rel:belongs-to,join:created_by=id"`
|
||||
Name string `json:"funnel_name" bun:"name,type:text,notnull"` // funnel name
|
||||
Description string `json:"description" bun:"description,type:text"` // funnel description
|
||||
OrgID valuer.UUID `json:"org_id" bun:"org_id,type:varchar,notnull"`
|
||||
Steps []funnelStep `json:"steps" bun:"steps,type:text,notnull"`
|
||||
Tags string `json:"tags" bun:"tags,type:text"`
|
||||
CreatedByUser *usertypes.StorableUser `json:"user" bun:"rel:belongs-to,join:created_by=id"`
|
||||
}
|
||||
|
||||
type funnelStep struct {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlschema"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
@@ -54,7 +54,7 @@ func (migration *addManagedRoles) Up(ctx context.Context, db *bun.DB) error {
|
||||
return err
|
||||
}
|
||||
|
||||
managedRoles := []*roletypes.StorableRole{}
|
||||
managedRoles := []*authtypes.StorableRole{}
|
||||
for _, orgIDStr := range orgIDs {
|
||||
orgID, err := valuer.NewUUID(orgIDStr)
|
||||
if err != nil {
|
||||
@@ -62,20 +62,20 @@ func (migration *addManagedRoles) Up(ctx context.Context, db *bun.DB) error {
|
||||
}
|
||||
|
||||
// signoz admin
|
||||
signozAdminRole := roletypes.NewRole(roletypes.SigNozAdminRoleName, roletypes.SigNozAdminRoleDescription, roletypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, roletypes.NewStorableRoleFromRole(signozAdminRole))
|
||||
signozAdminRole := authtypes.NewRole(authtypes.SigNozAdminRoleName, authtypes.SigNozAdminRoleDescription, authtypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, authtypes.NewStorableRoleFromRole(signozAdminRole))
|
||||
|
||||
// signoz editor
|
||||
signozEditorRole := roletypes.NewRole(roletypes.SigNozEditorRoleName, roletypes.SigNozEditorRoleDescription, roletypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, roletypes.NewStorableRoleFromRole(signozEditorRole))
|
||||
signozEditorRole := authtypes.NewRole(authtypes.SigNozEditorRoleName, authtypes.SigNozEditorRoleDescription, authtypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, authtypes.NewStorableRoleFromRole(signozEditorRole))
|
||||
|
||||
// signoz viewer
|
||||
signozViewerRole := roletypes.NewRole(roletypes.SigNozViewerRoleName, roletypes.SigNozViewerRoleDescription, roletypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, roletypes.NewStorableRoleFromRole(signozViewerRole))
|
||||
signozViewerRole := authtypes.NewRole(authtypes.SigNozViewerRoleName, authtypes.SigNozViewerRoleDescription, authtypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, authtypes.NewStorableRoleFromRole(signozViewerRole))
|
||||
|
||||
// signoz anonymous
|
||||
signozAnonymousRole := roletypes.NewRole(roletypes.SigNozAnonymousRoleName, roletypes.SigNozAnonymousRoleDescription, roletypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, roletypes.NewStorableRoleFromRole(signozAnonymousRole))
|
||||
signozAnonymousRole := authtypes.NewRole(authtypes.SigNozAnonymousRoleName, authtypes.SigNozAnonymousRoleDescription, authtypes.RoleTypeManaged, orgID)
|
||||
managedRoles = append(managedRoles, authtypes.NewStorableRoleFromRole(signozAnonymousRole))
|
||||
}
|
||||
|
||||
if len(managedRoles) > 0 {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/roletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/oklog/ulid/v2"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/dialect"
|
||||
@@ -83,7 +83,7 @@ func (migration *addAnonymousPublicDashboardTransaction) Up(ctx context.Context,
|
||||
INSERT INTO tuple (store, object_type, object_id, relation, _user, user_type, ulid, inserted_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (store, object_type, object_id, relation, _user) DO NOTHING`,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role:organization/"+orgID+"/role/"+roletypes.SigNozAnonymousRoleName+"#assignee", "userset", tupleID, now,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role:organization/"+orgID+"/role/"+authtypes.SigNozAnonymousRoleName+"#assignee", "userset", tupleID, now,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -102,7 +102,7 @@ func (migration *addAnonymousPublicDashboardTransaction) Up(ctx context.Context,
|
||||
INSERT INTO changelog (store, object_type, object_id, relation, _user, operation, ulid, inserted_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (store, ulid, object_type) DO NOTHING`,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role:organization/"+orgID+"/role/"+roletypes.SigNozAnonymousRoleName+"#assignee", "TUPLE_OPERATION_WRITE", tupleID, now,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role:organization/"+orgID+"/role/"+authtypes.SigNozAnonymousRoleName+"#assignee", "TUPLE_OPERATION_WRITE", tupleID, now,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -113,7 +113,7 @@ func (migration *addAnonymousPublicDashboardTransaction) Up(ctx context.Context,
|
||||
INSERT INTO tuple (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation, user_type, ulid, inserted_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation) DO NOTHING`,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role", "organization/"+orgID+"/role/"+roletypes.SigNozAnonymousRoleName, "assignee", "userset", tupleID, now,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role", "organization/"+orgID+"/role/"+authtypes.SigNozAnonymousRoleName, "assignee", "userset", tupleID, now,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -132,7 +132,7 @@ func (migration *addAnonymousPublicDashboardTransaction) Up(ctx context.Context,
|
||||
INSERT INTO changelog (store, object_type, object_id, relation, user_object_type, user_object_id, user_relation, operation, ulid, inserted_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (store, ulid, object_type) DO NOTHING`,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role", "organization/"+orgID+"/role/"+roletypes.SigNozAnonymousRoleName, "assignee", 0, tupleID, now,
|
||||
storeID, "metaresource", "organization/"+orgID+"/public-dashboard/*", "read", "role", "organization/"+orgID+"/role/"+authtypes.SigNozAnonymousRoleName, "assignee", 0, tupleID, now,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -41,6 +41,13 @@ type Column struct {
|
||||
Default string
|
||||
}
|
||||
|
||||
func (column *Column) Equals(other *Column) bool {
|
||||
return column.Name == other.Name &&
|
||||
column.DataType == other.DataType &&
|
||||
column.Nullable == other.Nullable &&
|
||||
column.Default == other.Default
|
||||
}
|
||||
|
||||
func (column *Column) ToDefinitionSQL(fmter SQLFormatter) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
@@ -129,3 +136,53 @@ func (column *Column) ToSetNotNullSQL(fmter SQLFormatter, tableName TableName) [
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
func (column *Column) ToDropNotNullSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ALTER COLUMN "...)
|
||||
sql = fmter.AppendIdent(sql, string(column.Name))
|
||||
sql = append(sql, " DROP NOT NULL"...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
func (column *Column) ToSetDefaultSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ALTER COLUMN "...)
|
||||
sql = fmter.AppendIdent(sql, string(column.Name))
|
||||
sql = append(sql, " SET DEFAULT "...)
|
||||
sql = append(sql, column.Default...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
func (column *Column) ToDropDefaultSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ALTER COLUMN "...)
|
||||
sql = fmter.AppendIdent(sql, string(column.Name))
|
||||
sql = append(sql, " DROP DEFAULT"...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
func (column *Column) ToSetDataTypeSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ALTER COLUMN "...)
|
||||
sql = fmter.AppendIdent(sql, string(column.Name))
|
||||
sql = append(sql, " SET DATA TYPE "...)
|
||||
sql = append(sql, fmter.SQLDataTypeOf(column.DataType)...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ type Constraint interface {
|
||||
|
||||
// The SQL representation of the constraint.
|
||||
ToDropSQL(fmter SQLFormatter, tableName TableName) []byte
|
||||
|
||||
// The SQL representation of the constraint.
|
||||
ToCreateSQL(fmter SQLFormatter, tableName TableName) []byte
|
||||
}
|
||||
|
||||
type PrimaryKeyConstraint struct {
|
||||
@@ -139,6 +142,27 @@ func (constraint *PrimaryKeyConstraint) ToDropSQL(fmter SQLFormatter, tableName
|
||||
return sql
|
||||
}
|
||||
|
||||
func (constraint *PrimaryKeyConstraint) ToCreateSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ADD CONSTRAINT "...)
|
||||
sql = fmter.AppendIdent(sql, constraint.Name(tableName))
|
||||
sql = append(sql, " PRIMARY KEY ("...)
|
||||
|
||||
for i, column := range constraint.ColumnNames {
|
||||
if i > 0 {
|
||||
sql = append(sql, ", "...)
|
||||
}
|
||||
sql = fmter.AppendIdent(sql, string(column))
|
||||
}
|
||||
|
||||
sql = append(sql, ")"...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
type ForeignKeyConstraint struct {
|
||||
ReferencingColumnName ColumnName
|
||||
ReferencedTableName TableName
|
||||
@@ -220,6 +244,24 @@ func (constraint *ForeignKeyConstraint) ToDropSQL(fmter SQLFormatter, tableName
|
||||
return sql
|
||||
}
|
||||
|
||||
func (constraint *ForeignKeyConstraint) ToCreateSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
sql = append(sql, "ALTER TABLE "...)
|
||||
sql = fmter.AppendIdent(sql, string(tableName))
|
||||
sql = append(sql, " ADD CONSTRAINT "...)
|
||||
sql = fmter.AppendIdent(sql, constraint.Name(tableName))
|
||||
sql = append(sql, " FOREIGN KEY ("...)
|
||||
sql = fmter.AppendIdent(sql, string(constraint.ReferencingColumnName))
|
||||
sql = append(sql, ") REFERENCES "...)
|
||||
sql = fmter.AppendIdent(sql, string(constraint.ReferencedTableName))
|
||||
sql = append(sql, " ("...)
|
||||
sql = fmter.AppendIdent(sql, string(constraint.ReferencedColumnName))
|
||||
sql = append(sql, ")"...)
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
// Do not use this constraint type. Instead create an index with the `UniqueIndex` type.
|
||||
// The main difference between a Unique Index and a Unique Constraint is mostly semantic, with a constraint focusing more on data integrity, while an index focuses on performance.
|
||||
// We choose to create unique indices because of sqlite. Dropping a unique index is directly supported whilst dropping a unique constraint requires a recreation of the table with the constraint removed.
|
||||
@@ -323,3 +365,7 @@ func (constraint *UniqueConstraint) ToDropSQL(fmter SQLFormatter, tableName Tabl
|
||||
|
||||
return sql
|
||||
}
|
||||
|
||||
func (constraint *UniqueConstraint) ToCreateSQL(fmter SQLFormatter, tableName TableName) []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package sqlschema
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
@@ -27,12 +28,18 @@ type Index interface {
|
||||
// Add name to the index. This is typically used to override the autogenerated name because the database might have a different name.
|
||||
Named(name string) Index
|
||||
|
||||
// Returns true if the index is named. A named index is not autogenerated
|
||||
IsNamed() bool
|
||||
|
||||
// The type of the index.
|
||||
Type() IndexType
|
||||
|
||||
// The columns that the index is applied to.
|
||||
Columns() []ColumnName
|
||||
|
||||
// Equals returns true if the index is equal to the other index.
|
||||
Equals(other Index) bool
|
||||
|
||||
// The SQL representation of the index.
|
||||
ToCreateSQL(fmter SQLFormatter) []byte
|
||||
|
||||
@@ -76,6 +83,10 @@ func (index *UniqueIndex) Named(name string) Index {
|
||||
}
|
||||
}
|
||||
|
||||
func (index *UniqueIndex) IsNamed() bool {
|
||||
return index.name != ""
|
||||
}
|
||||
|
||||
func (*UniqueIndex) Type() IndexType {
|
||||
return IndexTypeUnique
|
||||
}
|
||||
@@ -84,6 +95,14 @@ func (index *UniqueIndex) Columns() []ColumnName {
|
||||
return index.ColumnNames
|
||||
}
|
||||
|
||||
func (index *UniqueIndex) Equals(other Index) bool {
|
||||
if other.Type() != IndexTypeUnique {
|
||||
return false
|
||||
}
|
||||
|
||||
return index.Name() == other.Name() && slices.Equal(index.Columns(), other.Columns())
|
||||
}
|
||||
|
||||
func (index *UniqueIndex) ToCreateSQL(fmter SQLFormatter) []byte {
|
||||
sql := []byte{}
|
||||
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
package sqlschema
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var _ SQLOperator = (*Operator)(nil)
|
||||
|
||||
type OperatorSupport struct {
|
||||
DropConstraint bool
|
||||
ColumnIfNotExistsExists bool
|
||||
AlterColumnSetNotNull bool
|
||||
// Support for creating and dropping constraints.
|
||||
SCreateAndDropConstraint bool
|
||||
|
||||
// Support for `IF EXISTS` and `IF NOT EXISTS` in `ALTER TABLE ADD COLUMN` and `ALTER TABLE DROP COLUMN`.
|
||||
SAlterTableAddAndDropColumnIfNotExistsAndExists bool
|
||||
|
||||
// Support for altering columns such as `ALTER TABLE ALTER COLUMN SET NOT NULL`.
|
||||
SAlterTableAlterColumnSetAndDrop bool
|
||||
}
|
||||
|
||||
type Operator struct {
|
||||
@@ -25,9 +35,115 @@ func (operator *Operator) CreateTable(table *Table) [][]byte {
|
||||
}
|
||||
|
||||
func (operator *Operator) RenameTable(table *Table, newName TableName) [][]byte {
|
||||
sqls := [][]byte{table.ToRenameSQL(operator.fmter, newName)}
|
||||
sql := table.ToRenameSQL(operator.fmter, newName)
|
||||
table.Name = newName
|
||||
return sqls
|
||||
|
||||
return [][]byte{sql}
|
||||
}
|
||||
|
||||
func (operator *Operator) AlterTable(oldTable *Table, oldTableUniqueConstraints []*UniqueConstraint, newTable *Table) [][]byte {
|
||||
// The following has to be done in order:
|
||||
// - Drop constraints
|
||||
// - Drop columns (some columns might be part of constraints therefore this depends on Step 1)
|
||||
// - Add columns, then modify columns
|
||||
// - Rename table
|
||||
// - Add constraints (some constraints might be part of columns therefore this depends on Step 3, constraint names also depend on table name which is changed in Step 4)
|
||||
// - Create unique indices from unique constraints for the new table
|
||||
|
||||
sql := [][]byte{}
|
||||
|
||||
// Drop primary key constraint if it is in the old table but not in the new table.
|
||||
if oldTable.PrimaryKeyConstraint != nil && newTable.PrimaryKeyConstraint == nil {
|
||||
sql = append(sql, operator.DropConstraint(oldTable, oldTableUniqueConstraints, oldTable.PrimaryKeyConstraint)...)
|
||||
}
|
||||
|
||||
// Drop primary key constraint if it is in the old table and the new table but they are different.
|
||||
if oldTable.PrimaryKeyConstraint != nil && newTable.PrimaryKeyConstraint != nil && !oldTable.PrimaryKeyConstraint.Equals(newTable.PrimaryKeyConstraint) {
|
||||
sql = append(sql, operator.DropConstraint(oldTable, oldTableUniqueConstraints, oldTable.PrimaryKeyConstraint)...)
|
||||
}
|
||||
|
||||
// Drop foreign key constraints that are in the old table but not in the new table.
|
||||
for _, fkConstraint := range oldTable.ForeignKeyConstraints {
|
||||
if index := operator.findForeignKeyConstraint(newTable, fkConstraint); index == -1 {
|
||||
sql = append(sql, operator.DropConstraint(oldTable, oldTableUniqueConstraints, fkConstraint)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Drop all unique constraints.
|
||||
for _, uniqueConstraint := range oldTableUniqueConstraints {
|
||||
sql = append(sql, operator.DropConstraint(oldTable, oldTableUniqueConstraints, uniqueConstraint)...)
|
||||
}
|
||||
|
||||
// Reduce number of drops for engines with no SCreateAndDropConstraint.
|
||||
if !operator.support.SCreateAndDropConstraint && len(sql) > 0 {
|
||||
// Do not send the unique constraints to recreate table. We will change them to indexes at the end.
|
||||
sql = operator.RecreateTable(oldTable, nil)
|
||||
}
|
||||
|
||||
// Drop columns that are in the old table but not in the new table.
|
||||
for _, column := range oldTable.Columns {
|
||||
if index := operator.findColumnByName(newTable, column.Name); index == -1 {
|
||||
sql = append(sql, operator.DropColumn(oldTable, column)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Add columns that are in the new table but not in the old table.
|
||||
for _, column := range newTable.Columns {
|
||||
if index := operator.findColumnByName(oldTable, column.Name); index == -1 {
|
||||
sql = append(sql, operator.AddColumn(oldTable, oldTableUniqueConstraints, column, nil)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Modify columns that are in the new table and in the old table
|
||||
alterColumnSQLs := [][]byte{}
|
||||
for _, column := range newTable.Columns {
|
||||
alterColumnSQLs = append(alterColumnSQLs, operator.AlterColumn(oldTable, oldTableUniqueConstraints, column)...)
|
||||
}
|
||||
|
||||
// Reduce number of drops for engines with no SAlterTableAlterColumnSetAndDrop.
|
||||
if !operator.support.SAlterTableAlterColumnSetAndDrop && len(alterColumnSQLs) > 0 {
|
||||
// Do not send the unique constraints to recreate table. We will change them to indexes at the end.
|
||||
sql = append(sql, operator.RecreateTable(oldTable, nil)...)
|
||||
}
|
||||
|
||||
if operator.support.SAlterTableAlterColumnSetAndDrop && len(alterColumnSQLs) > 0 {
|
||||
sql = append(sql, alterColumnSQLs...)
|
||||
}
|
||||
|
||||
// Check if the name has changed
|
||||
if oldTable.Name != newTable.Name {
|
||||
sql = append(sql, operator.RenameTable(oldTable, newTable.Name)...)
|
||||
}
|
||||
|
||||
// If the old table does not have a primary key constraint and the new table does, we need to create it.
|
||||
if oldTable.PrimaryKeyConstraint == nil {
|
||||
if newTable.PrimaryKeyConstraint != nil {
|
||||
sql = append(sql, operator.CreateConstraint(oldTable, oldTableUniqueConstraints, newTable.PrimaryKeyConstraint)...)
|
||||
}
|
||||
}
|
||||
|
||||
if oldTable.PrimaryKeyConstraint != nil {
|
||||
if !oldTable.PrimaryKeyConstraint.Equals(newTable.PrimaryKeyConstraint) {
|
||||
sql = append(sql, operator.CreateConstraint(oldTable, oldTableUniqueConstraints, newTable.PrimaryKeyConstraint)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Create foreign key constraints that are in the new table but not in the old table.
|
||||
for _, fkConstraint := range newTable.ForeignKeyConstraints {
|
||||
if index := operator.findForeignKeyConstraint(oldTable, fkConstraint); index == -1 {
|
||||
sql = append(sql, operator.CreateConstraint(oldTable, oldTableUniqueConstraints, fkConstraint)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Create indices for the new table.
|
||||
for _, uniqueConstraint := range oldTableUniqueConstraints {
|
||||
sql = append(sql, uniqueConstraint.ToIndex(oldTable.Name).ToCreateSQL(operator.fmter))
|
||||
}
|
||||
|
||||
// Remove duplicate SQLs.
|
||||
return slices.CompactFunc(sql, func(a, b []byte) bool {
|
||||
return string(a) == string(b)
|
||||
})
|
||||
}
|
||||
|
||||
func (operator *Operator) RecreateTable(table *Table, uniqueConstraints []*UniqueConstraint) [][]byte {
|
||||
@@ -64,16 +180,23 @@ func (operator *Operator) AddColumn(table *Table, uniqueConstraints []*UniqueCon
|
||||
table.Columns = append(table.Columns, column)
|
||||
|
||||
sqls := [][]byte{
|
||||
column.ToAddSQL(operator.fmter, table.Name, operator.support.ColumnIfNotExistsExists),
|
||||
column.ToAddSQL(operator.fmter, table.Name, operator.support.SAlterTableAddAndDropColumnIfNotExistsAndExists),
|
||||
}
|
||||
|
||||
if !column.Nullable {
|
||||
if val == nil {
|
||||
val = column.DataType.z
|
||||
}
|
||||
// If the value is not nil, always try to update the column.
|
||||
if val != nil {
|
||||
sqls = append(sqls, column.ToUpdateSQL(operator.fmter, table.Name, val))
|
||||
}
|
||||
|
||||
if operator.support.AlterColumnSetNotNull {
|
||||
// If the column is not nullable and does not have a default value and no value is provided, we need to set something.
|
||||
// So we set it to the zero value of the column's data type.
|
||||
if !column.Nullable && column.Default == "" && val == nil {
|
||||
sqls = append(sqls, column.ToUpdateSQL(operator.fmter, table.Name, column.DataType.z))
|
||||
}
|
||||
|
||||
// If the column is not nullable, we need to set it to not null.
|
||||
if !column.Nullable {
|
||||
if operator.support.SAlterTableAlterColumnSetAndDrop {
|
||||
sqls = append(sqls, column.ToSetNotNullSQL(operator.fmter, table.Name))
|
||||
} else {
|
||||
sqls = append(sqls, operator.RecreateTable(table, uniqueConstraints)...)
|
||||
@@ -83,6 +206,62 @@ func (operator *Operator) AddColumn(table *Table, uniqueConstraints []*UniqueCon
|
||||
return sqls
|
||||
}
|
||||
|
||||
func (operator *Operator) AlterColumn(table *Table, uniqueConstraints []*UniqueConstraint, column *Column) [][]byte {
|
||||
index := operator.findColumnByName(table, column.Name)
|
||||
// If the column does not exist, we do not need to alter it.
|
||||
if index == -1 {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
oldColumn := table.Columns[index]
|
||||
// If the column is the same, we do not need to alter it.
|
||||
if oldColumn.Equals(column) {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
sqls := [][]byte{}
|
||||
var recreateTable bool
|
||||
|
||||
if oldColumn.DataType != column.DataType {
|
||||
if operator.support.SAlterTableAlterColumnSetAndDrop {
|
||||
sqls = append(sqls, column.ToSetDataTypeSQL(operator.fmter, table.Name))
|
||||
} else {
|
||||
recreateTable = true
|
||||
}
|
||||
}
|
||||
|
||||
if oldColumn.Nullable != column.Nullable {
|
||||
if operator.support.SAlterTableAlterColumnSetAndDrop {
|
||||
if column.Nullable {
|
||||
sqls = append(sqls, column.ToDropNotNullSQL(operator.fmter, table.Name))
|
||||
} else {
|
||||
sqls = append(sqls, column.ToSetNotNullSQL(operator.fmter, table.Name))
|
||||
}
|
||||
} else {
|
||||
recreateTable = true
|
||||
}
|
||||
}
|
||||
|
||||
if oldColumn.Default != column.Default {
|
||||
if operator.support.SAlterTableAlterColumnSetAndDrop {
|
||||
if column.Default != "" {
|
||||
sqls = append(sqls, column.ToSetDefaultSQL(operator.fmter, table.Name))
|
||||
} else {
|
||||
sqls = append(sqls, column.ToDropDefaultSQL(operator.fmter, table.Name))
|
||||
}
|
||||
} else {
|
||||
recreateTable = true
|
||||
}
|
||||
}
|
||||
|
||||
table.Columns[index] = column
|
||||
if recreateTable {
|
||||
sqls = append(sqls, operator.RecreateTable(table, uniqueConstraints)...)
|
||||
}
|
||||
|
||||
return sqls
|
||||
}
|
||||
|
||||
func (operator *Operator) DropColumn(table *Table, column *Column) [][]byte {
|
||||
index := operator.findColumnByName(table, column.Name)
|
||||
// If the column does not exist, we do not need to drop it.
|
||||
@@ -92,7 +271,48 @@ func (operator *Operator) DropColumn(table *Table, column *Column) [][]byte {
|
||||
|
||||
table.Columns = append(table.Columns[:index], table.Columns[index+1:]...)
|
||||
|
||||
return [][]byte{column.ToDropSQL(operator.fmter, table.Name, operator.support.ColumnIfNotExistsExists)}
|
||||
return [][]byte{column.ToDropSQL(operator.fmter, table.Name, operator.support.SAlterTableAddAndDropColumnIfNotExistsAndExists)}
|
||||
}
|
||||
|
||||
func (operator *Operator) CreateConstraint(table *Table, uniqueConstraints []*UniqueConstraint, constraint Constraint) [][]byte {
|
||||
if constraint == nil {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
if reflect.ValueOf(constraint).IsNil() {
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
if constraint.Type() == ConstraintTypeForeignKey {
|
||||
// Constraint already exists as foreign key constraint.
|
||||
if table.ForeignKeyConstraints != nil {
|
||||
for _, fkConstraint := range table.ForeignKeyConstraints {
|
||||
if constraint.Equals(fkConstraint) {
|
||||
return [][]byte{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.ForeignKeyConstraints = append(table.ForeignKeyConstraints, constraint.(*ForeignKeyConstraint))
|
||||
}
|
||||
|
||||
sqls := [][]byte{}
|
||||
if constraint.Type() == ConstraintTypePrimaryKey {
|
||||
if operator.support.SCreateAndDropConstraint {
|
||||
if table.PrimaryKeyConstraint != nil {
|
||||
// TODO(grandwizard28): this is a hack to drop the primary key constraint.
|
||||
// We need to find a better way to do this.
|
||||
sqls = append(sqls, table.PrimaryKeyConstraint.ToDropSQL(operator.fmter, table.Name))
|
||||
}
|
||||
}
|
||||
table.PrimaryKeyConstraint = constraint.(*PrimaryKeyConstraint)
|
||||
}
|
||||
|
||||
if operator.support.SCreateAndDropConstraint {
|
||||
return append(sqls, constraint.ToCreateSQL(operator.fmter, table.Name))
|
||||
}
|
||||
|
||||
return operator.RecreateTable(table, uniqueConstraints)
|
||||
}
|
||||
|
||||
func (operator *Operator) DropConstraint(table *Table, uniqueConstraints []*UniqueConstraint, constraint Constraint) [][]byte {
|
||||
@@ -105,20 +325,48 @@ func (operator *Operator) DropConstraint(table *Table, uniqueConstraints []*Uniq
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
if operator.support.DropConstraint {
|
||||
if operator.support.SCreateAndDropConstraint {
|
||||
return [][]byte{uniqueConstraints[uniqueConstraintIndex].ToDropSQL(operator.fmter, table.Name)}
|
||||
}
|
||||
|
||||
return operator.RecreateTable(table, append(uniqueConstraints[:uniqueConstraintIndex], uniqueConstraints[uniqueConstraintIndex+1:]...))
|
||||
var copyOfUniqueConstraints []*UniqueConstraint
|
||||
copyOfUniqueConstraints = append(copyOfUniqueConstraints, uniqueConstraints[:uniqueConstraintIndex]...)
|
||||
copyOfUniqueConstraints = append(copyOfUniqueConstraints, uniqueConstraints[uniqueConstraintIndex+1:]...)
|
||||
|
||||
return operator.RecreateTable(table, copyOfUniqueConstraints)
|
||||
}
|
||||
|
||||
if operator.support.DropConstraint {
|
||||
if operator.support.SCreateAndDropConstraint {
|
||||
return [][]byte{toDropConstraint.ToDropSQL(operator.fmter, table.Name)}
|
||||
}
|
||||
|
||||
return operator.RecreateTable(table, uniqueConstraints)
|
||||
}
|
||||
|
||||
func (operator *Operator) DiffIndices(oldIndices []Index, newIndices []Index) [][]byte {
|
||||
sqls := [][]byte{}
|
||||
|
||||
for i, oldIndex := range oldIndices {
|
||||
if index := operator.findIndex(newIndices, oldIndex); index == -1 {
|
||||
sqls = append(sqls, oldIndex.ToDropSQL(operator.fmter))
|
||||
continue
|
||||
}
|
||||
|
||||
if oldIndex.IsNamed() {
|
||||
sqls = append(sqls, oldIndex.ToDropSQL(operator.fmter))
|
||||
sqls = append(sqls, newIndices[i].ToCreateSQL(operator.fmter))
|
||||
}
|
||||
}
|
||||
|
||||
for _, newIndex := range newIndices {
|
||||
if index := operator.findIndex(oldIndices, newIndex); index == -1 {
|
||||
sqls = append(sqls, newIndex.ToCreateSQL(operator.fmter))
|
||||
}
|
||||
}
|
||||
|
||||
return sqls
|
||||
}
|
||||
|
||||
func (*Operator) findColumnByName(table *Table, columnName ColumnName) int {
|
||||
for i, column := range table.Columns {
|
||||
if column.Name == columnName {
|
||||
@@ -142,3 +390,27 @@ func (*Operator) findUniqueConstraint(uniqueConstraints []*UniqueConstraint, con
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func (*Operator) findForeignKeyConstraint(table *Table, constraint Constraint) int {
|
||||
if constraint.Type() != ConstraintTypeForeignKey {
|
||||
return -1
|
||||
}
|
||||
|
||||
for i, fkConstraint := range table.ForeignKeyConstraints {
|
||||
if fkConstraint.Equals(constraint) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func (*Operator) findIndex(indices []Index, index Index) int {
|
||||
for i, inputIndex := range indices {
|
||||
if index.Equals(inputIndex) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package sqlschema
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/uptrace/bun/schema"
|
||||
@@ -54,9 +55,8 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
column *Column
|
||||
val any
|
||||
uniqueConstraints []*UniqueConstraint
|
||||
support OperatorSupport
|
||||
expectedSQLs [][]byte
|
||||
expectedTable *Table
|
||||
expected map[OperatorSupport][][]byte
|
||||
}{
|
||||
{
|
||||
name: "NullableNoDefault_DoesNotExist",
|
||||
@@ -68,19 +68,21 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
},
|
||||
column: &Column{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
val: nil,
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "name" TEXT`),
|
||||
},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "name" TEXT`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "name" TEXT`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -94,21 +96,21 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
},
|
||||
column: &Column{Name: "name", DataType: DataTypeBigInt, Nullable: true, Default: ""},
|
||||
val: nil,
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NotNullableNoDefaultNoVal_DoesNotExist",
|
||||
name: "TextNotNullableNoDefaultNoVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -117,25 +119,32 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
},
|
||||
column: &Column{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
val: nil,
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "name" TEXT`),
|
||||
[]byte(`UPDATE "users" SET "name" = ''`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL`),
|
||||
},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "name" TEXT`),
|
||||
[]byte(`UPDATE "users" SET "name" = ''`),
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name") SELECT "id", "name" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "name" TEXT`),
|
||||
[]byte(`UPDATE "users" SET "name" = ''`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NotNullableNoDefault_DoesNotExist",
|
||||
name: "IntegerNotNullableNoDefaultNoVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -143,81 +152,154 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
val: int64(100),
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 100`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "num" SET NOT NULL`),
|
||||
},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NotNullableNoDefault_DoesNotExist_AlterColumnSetNotNullFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
val: int64(100),
|
||||
uniqueConstraints: []*UniqueConstraint{
|
||||
{ColumnNames: []ColumnName{"name"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 100`),
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL, "num" INTEGER NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name", "num") SELECT "id", "name", "num" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_name" ON "users" ("name")`),
|
||||
},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MismatchingDataType_DoesExist_AlterColumnSetNotNullFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "name", DataType: DataTypeBigInt, Nullable: false, Default: ""},
|
||||
val: nil,
|
||||
support: OperatorSupport{
|
||||
ColumnIfNotExistsExists: true,
|
||||
AlterColumnSetNotNull: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 0`),
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "num" INTEGER NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "num") SELECT "id", "num" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 0`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "num" SET NOT NULL`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IntegerNotNullableNoDefaultVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
val: int64(100),
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "num", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 100`),
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "num" INTEGER NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "num") SELECT "id", "num" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "num" INTEGER`),
|
||||
[]byte(`UPDATE "users" SET "num" = 100`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "num" SET NOT NULL`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "BooleanNotNullableNoDefaultValNoVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "is_admin", DataType: DataTypeBoolean, Nullable: false, Default: ""},
|
||||
val: nil,
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "is_admin", DataType: DataTypeBoolean, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "is_admin" BOOLEAN`),
|
||||
// Set to the zero value
|
||||
[]byte(`UPDATE "users" SET "is_admin" = FALSE`),
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "is_admin" BOOLEAN NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "is_admin") SELECT "id", "is_admin" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "is_admin" BOOLEAN`),
|
||||
// Set to the zero value
|
||||
[]byte(`UPDATE "users" SET "is_admin" = FALSE`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "is_admin" SET NOT NULL`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "BooleanNullableDefaultVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "is_admin", DataType: DataTypeBoolean, Nullable: true, Default: "TRUE"},
|
||||
val: nil,
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "is_admin", DataType: DataTypeBoolean, Nullable: true, Default: "TRUE"},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "is_admin" BOOLEAN DEFAULT TRUE`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "is_admin" BOOLEAN DEFAULT TRUE`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "TimestampNullableDefaultValAndVal_DoesNotExist",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
column: &Column{Name: "created_at", DataType: DataTypeTimestamp, Nullable: true, Default: "CURRENT_TIMESTAMP"},
|
||||
val: time.Time{},
|
||||
expectedTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "created_at", DataType: DataTypeTimestamp, Nullable: true, Default: "CURRENT_TIMESTAMP"},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP`),
|
||||
[]byte(`UPDATE "users" SET "created_at" = '0001-01-01 00:00:00+00:00'`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP`),
|
||||
[]byte(`UPDATE "users" SET "created_at" = '0001-01-01 00:00:00+00:00'`),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -226,11 +308,15 @@ func TestOperatorAddColumn(t *testing.T) {
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
fmter := NewFormatter(schema.NewNopFormatter().Dialect())
|
||||
operator := NewOperator(fmter, testCase.support)
|
||||
|
||||
actuals := operator.AddColumn(testCase.table, testCase.uniqueConstraints, testCase.column, testCase.val)
|
||||
assert.Equal(t, testCase.expectedSQLs, actuals)
|
||||
assert.Equal(t, testCase.expectedTable, testCase.table)
|
||||
for support, expectedSQLs := range testCase.expected {
|
||||
operator := NewOperator(fmter, support)
|
||||
clonedTable := testCase.table.Clone()
|
||||
|
||||
actuals := operator.AddColumn(clonedTable, testCase.uniqueConstraints, testCase.column, testCase.val)
|
||||
assert.Equal(t, expectedSQLs, actuals)
|
||||
assert.Equal(t, testCase.expectedTable, clonedTable)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -246,7 +332,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
expectedTable *Table
|
||||
}{
|
||||
{
|
||||
name: "PrimaryKeyConstraint_DoesExist_DropConstraintTrue",
|
||||
name: "PrimaryKeyConstraint_DoesExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -260,7 +346,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "pk_users"`),
|
||||
@@ -273,7 +359,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PrimaryKeyConstraint_DoesNotExist_DropConstraintTrue",
|
||||
name: "PrimaryKeyConstraint_DoesNotExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -284,7 +370,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -295,7 +381,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PrimaryKeyConstraintDifferentName_DoesExist_DropConstraintTrue",
|
||||
name: "PrimaryKeyConstraintDifferentName_DoesExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -310,7 +396,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "pk_users_different_name"`),
|
||||
@@ -323,7 +409,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PrimaryKeyConstraint_DoesExist_DropConstraintFalse",
|
||||
name: "PrimaryKeyConstraint_DoesExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -337,7 +423,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL)`),
|
||||
@@ -353,7 +439,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PrimaryKeyConstraint_DoesNotExist_DropConstraintFalse",
|
||||
name: "PrimaryKeyConstraint_DoesNotExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -364,7 +450,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -375,7 +461,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UniqueConstraint_DoesExist_DropConstraintTrue",
|
||||
name: "UniqueConstraint_DoesExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -390,7 +476,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"name"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "uq_users_name"`),
|
||||
@@ -404,7 +490,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UniqueConstraint_DoesNotExist_DropConstraintTrue",
|
||||
name: "UniqueConstraint_DoesNotExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -419,7 +505,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -431,7 +517,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UniqueConstraint_DoesExist_DropConstraintFalse",
|
||||
name: "UniqueConstraint_DoesExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -446,7 +532,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"name"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL)`),
|
||||
@@ -463,7 +549,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UniqueConstraint_DoesNotExist_DropConstraintFalse",
|
||||
name: "UniqueConstraint_DoesNotExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -478,7 +564,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -490,7 +576,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraint_DoesExist_DropConstraintTrue",
|
||||
name: "ForeignKeyConstraint_DoesExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -506,7 +592,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "fk_users_org_id"`),
|
||||
@@ -521,7 +607,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraintDifferentName_DoesExist_DropConstraintTrue",
|
||||
name: "ForeignKeyConstraintDifferentName_DoesExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -537,7 +623,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "my_fk"`),
|
||||
@@ -552,7 +638,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraint_DoesNotExist_DropConstraintTrue",
|
||||
name: "ForeignKeyConstraint_DoesNotExist_SCreateAndDropConstraintTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -569,7 +655,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: true,
|
||||
SCreateAndDropConstraint: true,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -584,7 +670,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraint_DoesExist_DropConstraintFalse",
|
||||
name: "ForeignKeyConstraint_DoesExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -600,7 +686,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "org_id" INTEGER NOT NULL)`),
|
||||
@@ -620,7 +706,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraintDifferentName_DoesExist_DropConstraintFalse",
|
||||
name: "ForeignKeyConstraintDifferentName_DoesExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -636,7 +722,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "org_id" INTEGER NOT NULL)`),
|
||||
@@ -656,7 +742,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ForeignKeyConstraint_DoesNotExist_DropConstraintFalse",
|
||||
name: "ForeignKeyConstraint_DoesNotExist_SCreateAndDropConstraintFalse",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
@@ -673,7 +759,7 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
support: OperatorSupport{
|
||||
DropConstraint: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
},
|
||||
expectedSQLs: [][]byte{},
|
||||
expectedTable: &Table{
|
||||
@@ -700,3 +786,363 @@ func TestOperatorDropConstraint(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOperatorAlterTable(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
table *Table
|
||||
uniqueConstraints []*UniqueConstraint
|
||||
newTable *Table
|
||||
expected map[OperatorSupport][][]byte
|
||||
}{
|
||||
{
|
||||
name: "NoOperation",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "RenameTable",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users_new",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" RENAME TO "users_new"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" RENAME TO "users_new"`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AddColumn_NullableNoDefault_SAlterTableAddAndDropColumnIfNotExistsAndExistsTrue",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
{Name: "age", DataType: DataTypeInteger, Nullable: true, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "age" INTEGER`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "age" INTEGER`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CreatePrimaryKeyConstraint",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{
|
||||
ColumnNames: []ColumnName{"id"},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, CONSTRAINT "pk_users" PRIMARY KEY ("id"))`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id") SELECT "id" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" ADD CONSTRAINT "pk_users" PRIMARY KEY ("id")`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DropPrimaryKeyConstraint_AlterColumnNullable",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
// first drop to remove the primary key constraint
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name") SELECT "id", "name" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// second drop to make the column nullable
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name") SELECT "id", "name" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "pk_users"`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DropForeignKeyConstraint_DropColumn",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "org_id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{
|
||||
{ReferencingColumnName: "org_id", ReferencedTableName: "orgs", ReferencedColumnName: "id"},
|
||||
},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
// first drop to remove the foreign key constraint
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "org_id" INTEGER NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "org_id") SELECT "id", "org_id" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// second drop to remove the column
|
||||
[]byte(`ALTER TABLE "users" DROP COLUMN "org_id"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
// first drop to remove the foreign key constraint
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "fk_users_org_id"`),
|
||||
// second drop to remove the column
|
||||
[]byte(`ALTER TABLE "users" DROP COLUMN IF EXISTS "org_id"`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DropMultipleConstraints",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
{Name: "age", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "org_id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "team_id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"id"}},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{
|
||||
{ReferencingColumnName: "org_id", ReferencedTableName: "orgs", ReferencedColumnName: "id"},
|
||||
{ReferencingColumnName: "team_id", ReferencedTableName: "teams", ReferencedColumnName: "id"},
|
||||
},
|
||||
},
|
||||
uniqueConstraints: []*UniqueConstraint{
|
||||
{ColumnNames: []ColumnName{"name", "age"}},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
{Name: "age", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "org_id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "team_id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{
|
||||
{ReferencingColumnName: "team_id", ReferencedTableName: "teams", ReferencedColumnName: "id"},
|
||||
},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL, "age" INTEGER NOT NULL, "org_id" INTEGER NOT NULL, "team_id" INTEGER NOT NULL, CONSTRAINT "fk_users_team_id" FOREIGN KEY ("team_id") REFERENCES "teams" ("id"))`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name", "age", "org_id", "team_id") SELECT "id", "name", "age", "org_id", "team_id" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_name_age" ON "users" ("name", "age")`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "pk_users"`),
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "fk_users_org_id"`),
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "uq_users_name_age"`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_name_age" ON "users" ("name", "age")`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DropUniqueConstraints_AlterMultipleColumns",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: true, Default: ""},
|
||||
{Name: "age", DataType: DataTypeInteger, Nullable: true, Default: ""},
|
||||
{Name: "email", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"id"}},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{
|
||||
{ReferencingColumnName: "org_id", ReferencedTableName: "orgs", ReferencedColumnName: "id"},
|
||||
},
|
||||
},
|
||||
uniqueConstraints: []*UniqueConstraint{
|
||||
{ColumnNames: []ColumnName{"email"}},
|
||||
{name: "my_name_constraint", ColumnNames: []ColumnName{"name"}},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
{Name: "name", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
{Name: "age", DataType: DataTypeInteger, Nullable: false, Default: "0"},
|
||||
{Name: "email", DataType: DataTypeInteger, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"id"}},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{
|
||||
{ReferencingColumnName: "org_id", ReferencedTableName: "orgs", ReferencedColumnName: "id"},
|
||||
},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
// first drop to remove unique constraint
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT, "age" INTEGER, "email" INTEGER NOT NULL, CONSTRAINT "pk_users" PRIMARY KEY ("id"), CONSTRAINT "fk_users_org_id" FOREIGN KEY ("org_id") REFERENCES "orgs" ("id"))`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name", "age", "email") SELECT "id", "name", "age", "email" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// second drop to change all columns
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" INTEGER NOT NULL, "name" TEXT NOT NULL, "age" INTEGER NOT NULL DEFAULT 0, "email" INTEGER NOT NULL, CONSTRAINT "pk_users" PRIMARY KEY ("id"), CONSTRAINT "fk_users_org_id" FOREIGN KEY ("org_id") REFERENCES "orgs" ("id"))`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id", "name", "age", "email") SELECT "id", "name", "age", "email" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// create unique index for the constraint
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_email" ON "users" ("email")`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_name" ON "users" ("name")`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "uq_users_email"`),
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "my_name_constraint"`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "age" SET NOT NULL`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "age" SET DEFAULT 0`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_email" ON "users" ("email")`),
|
||||
[]byte(`CREATE UNIQUE INDEX IF NOT EXISTS "uq_users_name" ON "users" ("name")`),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ChangePrimaryKeyConstraint",
|
||||
table: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"id"}},
|
||||
},
|
||||
newTable: &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "uuid", DataType: DataTypeText, Nullable: false, Default: ""},
|
||||
},
|
||||
PrimaryKeyConstraint: &PrimaryKeyConstraint{ColumnNames: []ColumnName{"uuid"}},
|
||||
ForeignKeyConstraints: []*ForeignKeyConstraint{},
|
||||
},
|
||||
expected: map[OperatorSupport][][]byte{
|
||||
{SCreateAndDropConstraint: false, SAlterTableAddAndDropColumnIfNotExistsAndExists: false, SAlterTableAlterColumnSetAndDrop: false}: {
|
||||
// first drop to remove the primary key constraint
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("id" TEXT NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("id") SELECT "id" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// drop the column
|
||||
[]byte(`ALTER TABLE "users" DROP COLUMN "id"`),
|
||||
// add the column
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN "uuid" TEXT`),
|
||||
[]byte(`UPDATE "users" SET "uuid" = ''`),
|
||||
// second drop to make it non-nullable
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("uuid" TEXT NOT NULL)`),
|
||||
[]byte(`INSERT INTO "users__temp" ("uuid") SELECT "uuid" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
// third drop to add the primary key constraint
|
||||
[]byte(`CREATE TABLE IF NOT EXISTS "users__temp" ("uuid" TEXT NOT NULL, CONSTRAINT "pk_users" PRIMARY KEY ("uuid"))`),
|
||||
[]byte(`INSERT INTO "users__temp" ("uuid") SELECT "uuid" FROM "users"`),
|
||||
[]byte(`DROP TABLE IF EXISTS "users"`),
|
||||
[]byte(`ALTER TABLE "users__temp" RENAME TO "users"`),
|
||||
},
|
||||
{SCreateAndDropConstraint: true, SAlterTableAddAndDropColumnIfNotExistsAndExists: true, SAlterTableAlterColumnSetAndDrop: true}: {
|
||||
[]byte(`ALTER TABLE "users" DROP CONSTRAINT IF EXISTS "pk_users"`),
|
||||
[]byte(`ALTER TABLE "users" DROP COLUMN IF EXISTS "id"`),
|
||||
[]byte(`ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "uuid" TEXT`),
|
||||
[]byte(`UPDATE "users" SET "uuid" = ''`),
|
||||
[]byte(`ALTER TABLE "users" ALTER COLUMN "uuid" SET NOT NULL`),
|
||||
[]byte(`ALTER TABLE "users" ADD CONSTRAINT "pk_users" PRIMARY KEY ("uuid")`),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
fmter := NewFormatter(schema.NewNopFormatter().Dialect())
|
||||
for support, sqls := range testCase.expected {
|
||||
operator := NewOperator(fmter, support)
|
||||
clonedTable := testCase.table.Clone()
|
||||
|
||||
actuals := operator.AlterTable(clonedTable, testCase.uniqueConstraints, testCase.newTable)
|
||||
assert.Equal(t, sqls, actuals)
|
||||
assert.EqualValues(t, testCase.newTable, clonedTable)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ func New(ctx context.Context, providerSettings factory.ProviderSettings, config
|
||||
settings: settings,
|
||||
sqlstore: sqlstore,
|
||||
operator: sqlschema.NewOperator(fmter, sqlschema.OperatorSupport{
|
||||
DropConstraint: false,
|
||||
ColumnIfNotExistsExists: false,
|
||||
AlterColumnSetNotNull: false,
|
||||
SCreateAndDropConstraint: false,
|
||||
SAlterTableAddAndDropColumnIfNotExistsAndExists: false,
|
||||
SAlterTableAlterColumnSetAndDrop: false,
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func (provider *provider) GetTable(ctx context.Context, tableName sqlschema.Tabl
|
||||
BunDB().
|
||||
NewRaw("SELECT sql FROM sqlite_master WHERE type IN (?) AND tbl_name = ? AND sql IS NOT NULL", bun.In([]string{"table"}), string(tableName)).
|
||||
Scan(ctx, &sql); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, provider.sqlstore.WrapNotFoundErrf(err, errors.CodeNotFound, "table (%s) not found", tableName)
|
||||
}
|
||||
|
||||
table, uniqueConstraints, err := parseCreateTable(sql, provider.fmter)
|
||||
@@ -73,7 +73,7 @@ func (provider *provider) GetIndices(ctx context.Context, tableName sqlschema.Ta
|
||||
BunDB().
|
||||
QueryContext(ctx, "SELECT * FROM PRAGMA_index_list(?)", string(tableName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, provider.sqlstore.WrapNotFoundErrf(err, errors.CodeNotFound, "no indices for table (%s) found", tableName)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -115,10 +115,16 @@ func (provider *provider) GetIndices(ctx context.Context, tableName sqlschema.Ta
|
||||
}
|
||||
|
||||
if unique {
|
||||
indices = append(indices, (&sqlschema.UniqueIndex{
|
||||
index := &sqlschema.UniqueIndex{
|
||||
TableName: tableName,
|
||||
ColumnNames: columns,
|
||||
}).Named(name).(*sqlschema.UniqueIndex))
|
||||
}
|
||||
|
||||
if index.Name() == name {
|
||||
indices = append(indices, index)
|
||||
} else {
|
||||
indices = append(indices, index.Named(name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,10 @@ type SQLOperator interface {
|
||||
// Returns a list of SQL statements to rename a table.
|
||||
RenameTable(*Table, TableName) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to recreate a table.
|
||||
// Returns a list of SQL statements to alter the input table to the new table. It converts all unique constraints to unique indices and drops the unique constraints.
|
||||
AlterTable(*Table, []*UniqueConstraint, *Table) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to recreate a table. In recreating the table, it converts all unqiue constraints to indices and copies data from the old table.
|
||||
RecreateTable(*Table, []*UniqueConstraint) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to create an index.
|
||||
@@ -47,11 +50,21 @@ type SQLOperator interface {
|
||||
// If the column is not nullable, the column is added with the input value, then the column is made non-nullable.
|
||||
AddColumn(*Table, []*UniqueConstraint, *Column, any) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to alter a column.
|
||||
AlterColumn(*Table, []*UniqueConstraint, *Column) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to drop a column from a table.
|
||||
DropColumn(*Table, *Column) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to create a constraint on a table.
|
||||
CreateConstraint(*Table, []*UniqueConstraint, Constraint) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to drop a constraint from a table.
|
||||
DropConstraint(*Table, []*UniqueConstraint, Constraint) [][]byte
|
||||
|
||||
// Returns a list of SQL statements to get the difference between the input indices and the output indices. If the input indices are named,
|
||||
// they are dropped and recreated with autogenerated names.
|
||||
DiffIndices([]Index, []Index) [][]byte
|
||||
}
|
||||
|
||||
type SQLFormatter interface {
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||
"github.com/SigNoz/signoz/pkg/tokenizer"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/usertypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/SigNoz/signoz/pkg/version"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@@ -175,7 +175,7 @@ func (provider *provider) Report(ctx context.Context) error {
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
traits := types.NewTraitsFromUser(user)
|
||||
traits := usertypes.NewTraitsFromUser(user)
|
||||
if maxLastObservedAt, ok := maxLastObservedAtPerUserID[user.ID]; ok {
|
||||
traits["auth_token.last_observed_at.max.time"] = maxLastObservedAt.UTC()
|
||||
traits["auth_token.last_observed_at.max.time_unix"] = maxLastObservedAt.Unix()
|
||||
|
||||
@@ -2,7 +2,7 @@ package jwttokenizer
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
@@ -10,10 +10,10 @@ var _ jwt.ClaimsValidator = (*Claims)(nil)
|
||||
|
||||
type Claims struct {
|
||||
jwt.RegisteredClaims
|
||||
UserID string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Role types.Role `json:"role"`
|
||||
OrgID string `json:"orgId"`
|
||||
UserID string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Role authtypes.LegacyRole `json:"role"`
|
||||
OrgID string `json:"orgId"`
|
||||
}
|
||||
|
||||
func (c *Claims) Validate() error {
|
||||
|
||||
@@ -125,7 +125,7 @@ func (provider *provider) GetIdentity(ctx context.Context, accessToken string) (
|
||||
return nil, errors.Newf(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "claim role mismatch")
|
||||
}
|
||||
|
||||
return authtypes.NewIdentity(valuer.MustNewUUID(claims.UserID), valuer.MustNewUUID(claims.OrgID), valuer.MustNewEmail(claims.Email), claims.Role), nil
|
||||
return authtypes.NewIdentity(valuer.MustNewUUID(claims.UserID), valuer.MustNewUUID(claims.OrgID), valuer.MustNewEmail(claims.Email), claims.Role, authtypes.IdentNProviderTokenizer), nil
|
||||
}
|
||||
|
||||
func (provider *provider) DeleteToken(ctx context.Context, accessToken string) error {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user