mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-19 22:09:08 +08:00
feat(sqlmigration): update the user related tables according to new schema (#7518)
* feat(sqlmigration): update the alertmanager tables * feat(sqlmigration): update the alertmanager tables * feat(sqlmigration): make the preference package multi tenant * feat(preference): address nit pick comments * feat(preference): added the cascade delete for preferences * feat(sqlmigration): update apdex and TTL status tables (#7481) * feat(sqlmigration): update the apdex and ttl tables * feat(sqlmigration): register the new migration and rename table * feat(sqlmigration): fix the ttl queries * feat(sqlmigration): update the TTL and apdex tables * feat(sqlmigration): update the TTL and apdex tables * feat(sqlmigration): fix the reset password and pat tables (#7482) * feat(sqlmigration): fix the reset password and pat tables * feat(sqlmigration): revert PAT changes * feat(sqlmigration): register and rename the new migration * feat(sqlmigration): handle updates for user tables * feat(sqlmigration): remove unwanted changes
This commit is contained in:
parent
0116eb20ab
commit
6a143efd2c
@ -10,9 +10,12 @@ import (
|
|||||||
"github.com/SigNoz/signoz/ee/query-service/model"
|
"github.com/SigNoz/signoz/ee/query-service/model"
|
||||||
"github.com/SigNoz/signoz/ee/types"
|
"github.com/SigNoz/signoz/ee/types"
|
||||||
eeTypes "github.com/SigNoz/signoz/ee/types"
|
eeTypes "github.com/SigNoz/signoz/ee/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
|
"github.com/SigNoz/signoz/pkg/http/render"
|
||||||
"github.com/SigNoz/signoz/pkg/query-service/auth"
|
"github.com/SigNoz/signoz/pkg/query-service/auth"
|
||||||
baseconstants "github.com/SigNoz/signoz/pkg/query-service/constants"
|
baseconstants "github.com/SigNoz/signoz/pkg/query-service/constants"
|
||||||
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@ -93,7 +96,12 @@ func (ah *APIHandler) updatePAT(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.UpdatedByUserID = user.ID
|
req.UpdatedByUserID = user.ID
|
||||||
id := mux.Vars(r)["id"]
|
idStr := mux.Vars(r)["id"]
|
||||||
|
id, err := valuer.NewUUID(idStr)
|
||||||
|
if err != nil {
|
||||||
|
render.Error(w, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid uuid-v7"))
|
||||||
|
return
|
||||||
|
}
|
||||||
req.UpdatedAt = time.Now()
|
req.UpdatedAt = time.Now()
|
||||||
zap.L().Info("Got Update PAT request", zap.Any("pat", req))
|
zap.L().Info("Got Update PAT request", zap.Any("pat", req))
|
||||||
var apierr basemodel.BaseApiError
|
var apierr basemodel.BaseApiError
|
||||||
@ -126,7 +134,12 @@ func (ah *APIHandler) getPATs(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func (ah *APIHandler) revokePAT(w http.ResponseWriter, r *http.Request) {
|
func (ah *APIHandler) revokePAT(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
id := mux.Vars(r)["id"]
|
idStr := mux.Vars(r)["id"]
|
||||||
|
id, err := valuer.NewUUID(idStr)
|
||||||
|
if err != nil {
|
||||||
|
render.Error(w, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is not a valid uuid-v7"))
|
||||||
|
return
|
||||||
|
}
|
||||||
user, err := auth.GetUserFromReqContext(r.Context())
|
user, err := auth.GetUserFromReqContext(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
RespondError(w, &model.ApiError{
|
RespondError(w, &model.ApiError{
|
||||||
@ -136,7 +149,7 @@ func (ah *APIHandler) revokePAT(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
zap.L().Info("Revoke PAT with id", zap.String("id", id))
|
zap.L().Info("Revoke PAT with id", zap.String("id", id.StringValue()))
|
||||||
if apierr := ah.AppDao().RevokePAT(ctx, user.OrgID, id, user.ID); apierr != nil {
|
if apierr := ah.AppDao().RevokePAT(ctx, user.OrgID, id, user.ID); apierr != nil {
|
||||||
RespondError(w, apierr, nil)
|
RespondError(w, apierr, nil)
|
||||||
return
|
return
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
||||||
ossTypes "github.com/SigNoz/signoz/pkg/types"
|
ossTypes "github.com/SigNoz/signoz/pkg/types"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
@ -36,10 +37,10 @@ type ModelDao interface {
|
|||||||
GetDomainByEmail(ctx context.Context, email string) (*types.GettableOrgDomain, basemodel.BaseApiError)
|
GetDomainByEmail(ctx context.Context, email string) (*types.GettableOrgDomain, basemodel.BaseApiError)
|
||||||
|
|
||||||
CreatePAT(ctx context.Context, orgID string, p types.GettablePAT) (types.GettablePAT, basemodel.BaseApiError)
|
CreatePAT(ctx context.Context, orgID string, p types.GettablePAT) (types.GettablePAT, basemodel.BaseApiError)
|
||||||
UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id string) basemodel.BaseApiError
|
UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id valuer.UUID) basemodel.BaseApiError
|
||||||
GetPAT(ctx context.Context, pat string) (*types.GettablePAT, basemodel.BaseApiError)
|
GetPAT(ctx context.Context, pat string) (*types.GettablePAT, basemodel.BaseApiError)
|
||||||
GetPATByID(ctx context.Context, orgID string, id string) (*types.GettablePAT, basemodel.BaseApiError)
|
GetPATByID(ctx context.Context, orgID string, id valuer.UUID) (*types.GettablePAT, basemodel.BaseApiError)
|
||||||
GetUserByPAT(ctx context.Context, orgID string, token string) (*ossTypes.GettableUser, basemodel.BaseApiError)
|
GetUserByPAT(ctx context.Context, orgID string, token string) (*ossTypes.GettableUser, basemodel.BaseApiError)
|
||||||
ListPATs(ctx context.Context, orgID string) ([]types.GettablePAT, basemodel.BaseApiError)
|
ListPATs(ctx context.Context, orgID string) ([]types.GettablePAT, basemodel.BaseApiError)
|
||||||
RevokePAT(ctx context.Context, orgID string, id string, userID string) basemodel.BaseApiError
|
RevokePAT(ctx context.Context, orgID string, id valuer.UUID, userID string) basemodel.BaseApiError
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,14 @@ import (
|
|||||||
"github.com/SigNoz/signoz/ee/types"
|
"github.com/SigNoz/signoz/ee/types"
|
||||||
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
||||||
ossTypes "github.com/SigNoz/signoz/pkg/types"
|
ossTypes "github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *modelDao) CreatePAT(ctx context.Context, orgID string, p types.GettablePAT) (types.GettablePAT, basemodel.BaseApiError) {
|
func (m *modelDao) CreatePAT(ctx context.Context, orgID string, p types.GettablePAT) (types.GettablePAT, basemodel.BaseApiError) {
|
||||||
p.StorablePersonalAccessToken.OrgID = orgID
|
p.StorablePersonalAccessToken.OrgID = orgID
|
||||||
|
p.StorablePersonalAccessToken.ID = valuer.GenerateUUID()
|
||||||
_, err := m.DB().NewInsert().
|
_, err := m.DB().NewInsert().
|
||||||
Model(&p.StorablePersonalAccessToken).
|
Model(&p.StorablePersonalAccessToken).
|
||||||
Exec(ctx)
|
Exec(ctx)
|
||||||
@ -46,11 +48,11 @@ func (m *modelDao) CreatePAT(ctx context.Context, orgID string, p types.Gettable
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id string) basemodel.BaseApiError {
|
func (m *modelDao) UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id valuer.UUID) basemodel.BaseApiError {
|
||||||
_, err := m.DB().NewUpdate().
|
_, err := m.DB().NewUpdate().
|
||||||
Model(&p.StorablePersonalAccessToken).
|
Model(&p.StorablePersonalAccessToken).
|
||||||
Column("role", "name", "updated_at", "updated_by_user_id").
|
Column("role", "name", "updated_at", "updated_by_user_id").
|
||||||
Where("id = ?", id).
|
Where("id = ?", id.StringValue()).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
Where("revoked = false").
|
Where("revoked = false").
|
||||||
Exec(ctx)
|
Exec(ctx)
|
||||||
@ -127,14 +129,14 @@ func (m *modelDao) ListPATs(ctx context.Context, orgID string) ([]types.Gettable
|
|||||||
return patsWithUsers, nil
|
return patsWithUsers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) RevokePAT(ctx context.Context, orgID string, id string, userID string) basemodel.BaseApiError {
|
func (m *modelDao) RevokePAT(ctx context.Context, orgID string, id valuer.UUID, userID string) basemodel.BaseApiError {
|
||||||
updatedAt := time.Now().Unix()
|
updatedAt := time.Now().Unix()
|
||||||
_, err := m.DB().NewUpdate().
|
_, err := m.DB().NewUpdate().
|
||||||
Model(&types.StorablePersonalAccessToken{}).
|
Model(&types.StorablePersonalAccessToken{}).
|
||||||
Set("revoked = ?", true).
|
Set("revoked = ?", true).
|
||||||
Set("updated_by_user_id = ?", userID).
|
Set("updated_by_user_id = ?", userID).
|
||||||
Set("updated_at = ?", updatedAt).
|
Set("updated_at = ?", updatedAt).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id.StringValue()).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
Exec(ctx)
|
Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -169,12 +171,12 @@ func (m *modelDao) GetPAT(ctx context.Context, token string) (*types.GettablePAT
|
|||||||
return &patWithUser, nil
|
return &patWithUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id string) (*types.GettablePAT, basemodel.BaseApiError) {
|
func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id valuer.UUID) (*types.GettablePAT, basemodel.BaseApiError) {
|
||||||
pats := []types.StorablePersonalAccessToken{}
|
pats := []types.StorablePersonalAccessToken{}
|
||||||
|
|
||||||
if err := m.DB().NewSelect().
|
if err := m.DB().NewSelect().
|
||||||
Model(&pats).
|
Model(&pats).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id.StringValue()).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
Where("revoked = false").
|
Where("revoked = false").
|
||||||
Scan(ctx); err != nil {
|
Scan(ctx); err != nil {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
@ -192,7 +193,10 @@ func (dialect *dialect) TableExists(ctx context.Context, bun bun.IDB, table inte
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, references []string, cb func(context.Context) error) error {
|
||||||
|
if len(references) == 0 {
|
||||||
|
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot run migration without reference")
|
||||||
|
}
|
||||||
exists, err := dialect.TableExists(ctx, bun, newModel)
|
exists, err := dialect.TableExists(ctx, bun, newModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -201,12 +205,25 @@ func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.I
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bun.
|
var fkReferences []string
|
||||||
|
for _, reference := range references {
|
||||||
|
if reference == Org && !slices.Contains(fkReferences, OrgReference) {
|
||||||
|
fkReferences = append(fkReferences, OrgReference)
|
||||||
|
} else if reference == User && !slices.Contains(fkReferences, UserReference) {
|
||||||
|
fkReferences = append(fkReferences, UserReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createTable := bun.
|
||||||
NewCreateTable().
|
NewCreateTable().
|
||||||
IfNotExists().
|
IfNotExists().
|
||||||
Model(newModel).
|
Model(newModel)
|
||||||
Exec(ctx)
|
|
||||||
|
|
||||||
|
for _, fk := range fkReferences {
|
||||||
|
createTable = createTable.ForeignKey(fk)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = createTable.Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,11 +29,10 @@ func NewGettablePAT(name, role, userID string, expiresAt int64) GettablePAT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StorablePersonalAccessToken struct {
|
type StorablePersonalAccessToken struct {
|
||||||
bun.BaseModel `bun:"table:personal_access_tokens"`
|
bun.BaseModel `bun:"table:personal_access_token"`
|
||||||
|
types.Identifiable
|
||||||
types.TimeAuditable
|
types.TimeAuditable
|
||||||
OrgID string `json:"orgId" bun:"org_id,type:text,notnull"`
|
OrgID string `json:"orgId" bun:"org_id,type:text,notnull"`
|
||||||
ID int `json:"id" bun:"id,pk,autoincrement"`
|
|
||||||
Role string `json:"role" bun:"role,type:text,notnull,default:'ADMIN'"`
|
Role string `json:"role" bun:"role,type:text,notnull,default:'ADMIN'"`
|
||||||
UserID string `json:"userId" bun:"user_id,type:text,notnull"`
|
UserID string `json:"userId" bun:"user_id,type:text,notnull"`
|
||||||
Token string `json:"token" bun:"token,type:text,notnull,unique"`
|
Token string `json:"token" bun:"token,type:text,notnull,unique"`
|
||||||
@ -69,5 +69,8 @@ func NewStorablePersonalAccessToken(name, role, userID string, expiresAt int64)
|
|||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
},
|
},
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,6 +329,9 @@ func CreateResetPasswordToken(ctx context.Context, userId string) (*types.ResetP
|
|||||||
}
|
}
|
||||||
|
|
||||||
req := &types.ResetPasswordRequest{
|
req := &types.ResetPasswordRequest{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
UserID: userId,
|
UserID: userId,
|
||||||
Token: token,
|
Token: token,
|
||||||
}
|
}
|
||||||
|
@ -317,6 +317,7 @@ func createTelemetry() {
|
|||||||
|
|
||||||
getLogsInfoInLastHeartBeatInterval, _ := telemetry.reader.GetLogsInfoInLastHeartBeatInterval(ctx, HEART_BEAT_DURATION)
|
getLogsInfoInLastHeartBeatInterval, _ := telemetry.reader.GetLogsInfoInLastHeartBeatInterval(ctx, HEART_BEAT_DURATION)
|
||||||
|
|
||||||
|
// TODO update this post bootstrap decision
|
||||||
traceTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.TraceTTL})
|
traceTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.TraceTTL})
|
||||||
metricsTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.MetricsTTL})
|
metricsTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.MetricsTTL})
|
||||||
logsTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.LogsTTL})
|
logsTTL, _ := telemetry.reader.GetTTL(ctx, "", &model.GetTTLParams{Type: constants.LogsTTL})
|
||||||
|
@ -68,6 +68,7 @@ func NewSQLMigrationProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedM
|
|||||||
sqlmigration.NewUpdateAlertmanagerFactory(sqlstore),
|
sqlmigration.NewUpdateAlertmanagerFactory(sqlstore),
|
||||||
sqlmigration.NewUpdatePreferencesFactory(sqlstore),
|
sqlmigration.NewUpdatePreferencesFactory(sqlstore),
|
||||||
sqlmigration.NewUpdateApdexTtlFactory(sqlstore),
|
sqlmigration.NewUpdateApdexTtlFactory(sqlstore),
|
||||||
|
sqlmigration.NewUpdateResetPasswordFactory(sqlstore),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func (migration *updateInvites) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
err = migration.
|
err = migration.
|
||||||
store.
|
store.
|
||||||
Dialect().
|
Dialect().
|
||||||
RenameTableAndModifyModel(ctx, tx, new(existingInvite), new(newInvite), func(ctx context.Context) error {
|
RenameTableAndModifyModel(ctx, tx, new(existingInvite), new(newInvite), []string{OrgReference}, func(ctx context.Context) error {
|
||||||
existingInvites := make([]*existingInvite, 0)
|
existingInvites := make([]*existingInvite, 0)
|
||||||
err = tx.
|
err = tx.
|
||||||
NewSelect().
|
NewSelect().
|
||||||
|
@ -110,7 +110,7 @@ func (migration *updateAlertmanager) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
err = migration.
|
err = migration.
|
||||||
store.
|
store.
|
||||||
Dialect().
|
Dialect().
|
||||||
RenameTableAndModifyModel(ctx, tx, new(existingChannel), new(newChannel), func(ctx context.Context) error {
|
RenameTableAndModifyModel(ctx, tx, new(existingChannel), new(newChannel), []string{OrgReference}, func(ctx context.Context) error {
|
||||||
existingChannels := make([]*existingChannel, 0)
|
existingChannels := make([]*existingChannel, 0)
|
||||||
err = tx.
|
err = tx.
|
||||||
NewSelect().
|
NewSelect().
|
||||||
|
@ -94,7 +94,7 @@ func (migration *updateApdexTtl) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
err = migration.
|
err = migration.
|
||||||
store.
|
store.
|
||||||
Dialect().
|
Dialect().
|
||||||
RenameTableAndModifyModel(ctx, tx, new(existingApdexSettings), new(newApdexSettings), func(ctx context.Context) error {
|
RenameTableAndModifyModel(ctx, tx, new(existingApdexSettings), new(newApdexSettings), []string{OrgReference}, func(ctx context.Context) error {
|
||||||
existingApdexSettings := make([]*existingApdexSettings, 0)
|
existingApdexSettings := make([]*existingApdexSettings, 0)
|
||||||
err = tx.
|
err = tx.
|
||||||
NewSelect().
|
NewSelect().
|
||||||
@ -133,7 +133,7 @@ func (migration *updateApdexTtl) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
err = migration.
|
err = migration.
|
||||||
store.
|
store.
|
||||||
Dialect().
|
Dialect().
|
||||||
RenameTableAndModifyModel(ctx, tx, new(existingTTLStatus), new(newTTLStatus), func(ctx context.Context) error {
|
RenameTableAndModifyModel(ctx, tx, new(existingTTLStatus), new(newTTLStatus), []string{OrgReference}, func(ctx context.Context) error {
|
||||||
existingTTLStatus := make([]*existingTTLStatus, 0)
|
existingTTLStatus := make([]*existingTTLStatus, 0)
|
||||||
err = tx.
|
err = tx.
|
||||||
NewSelect().
|
NewSelect().
|
||||||
|
200
pkg/sqlmigration/024_update_reset_password.go
Normal file
200
pkg/sqlmigration/024_update_reset_password.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package sqlmigration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
"github.com/uptrace/bun/migrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type updateResetPassword struct {
|
||||||
|
store sqlstore.SQLStore
|
||||||
|
}
|
||||||
|
|
||||||
|
type existingResetPasswordRequest struct {
|
||||||
|
bun.BaseModel `bun:"table:reset_password_request"`
|
||||||
|
ID int `bun:"id,pk,autoincrement" json:"id"`
|
||||||
|
Token string `bun:"token,type:text,notnull" json:"token"`
|
||||||
|
UserID string `bun:"user_id,type:text,notnull" json:"userId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newResetPasswordRequest struct {
|
||||||
|
bun.BaseModel `bun:"table:reset_password_request_new"`
|
||||||
|
types.Identifiable
|
||||||
|
Token string `bun:"token,type:text,notnull" json:"token"`
|
||||||
|
UserID string `bun:"user_id,type:text,notnull" json:"userId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type existingPersonalAccessToken struct {
|
||||||
|
bun.BaseModel `bun:"table:personal_access_tokens"`
|
||||||
|
types.TimeAuditable
|
||||||
|
OrgID string `json:"orgId" bun:"org_id,type:text,notnull"`
|
||||||
|
ID int `json:"id" bun:"id,pk,autoincrement"`
|
||||||
|
Role string `json:"role" bun:"role,type:text,notnull,default:'ADMIN'"`
|
||||||
|
UserID string `json:"userId" bun:"user_id,type:text,notnull"`
|
||||||
|
Token string `json:"token" bun:"token,type:text,notnull,unique"`
|
||||||
|
Name string `json:"name" bun:"name,type:text,notnull"`
|
||||||
|
ExpiresAt int64 `json:"expiresAt" bun:"expires_at,notnull,default:0"`
|
||||||
|
LastUsed int64 `json:"lastUsed" bun:"last_used,notnull,default:0"`
|
||||||
|
Revoked bool `json:"revoked" bun:"revoked,notnull,default:false"`
|
||||||
|
UpdatedByUserID string `json:"updatedByUserId" bun:"updated_by_user_id,type:text,notnull,default:''"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newPersonalAccessToken struct {
|
||||||
|
bun.BaseModel `bun:"table:personal_access_token"`
|
||||||
|
types.Identifiable
|
||||||
|
types.TimeAuditable
|
||||||
|
OrgID string `json:"orgId" bun:"org_id,type:text,notnull"`
|
||||||
|
Role string `json:"role" bun:"role,type:text,notnull,default:'ADMIN'"`
|
||||||
|
UserID string `json:"userId" bun:"user_id,type:text,notnull"`
|
||||||
|
Token string `json:"token" bun:"token,type:text,notnull,unique"`
|
||||||
|
Name string `json:"name" bun:"name,type:text,notnull"`
|
||||||
|
ExpiresAt int64 `json:"expiresAt" bun:"expires_at,notnull,default:0"`
|
||||||
|
LastUsed int64 `json:"lastUsed" bun:"last_used,notnull,default:0"`
|
||||||
|
Revoked bool `json:"revoked" bun:"revoked,notnull,default:false"`
|
||||||
|
UpdatedByUserID string `json:"updatedByUserId" bun:"updated_by_user_id,type:text,notnull,default:''"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateResetPasswordFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||||
|
return factory.
|
||||||
|
NewProviderFactory(
|
||||||
|
factory.MustNewName("update_reset_password"),
|
||||||
|
func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
||||||
|
return newUpdateResetPassword(ctx, ps, c, sqlstore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUpdateResetPassword(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) {
|
||||||
|
return &updateResetPassword{store: store}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateResetPassword) Register(migrations *migrate.Migrations) error {
|
||||||
|
if err := migrations.
|
||||||
|
Register(migration.Up, migration.Down); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateResetPassword) Up(ctx context.Context, db *bun.DB) error {
|
||||||
|
tx, err := db.
|
||||||
|
BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
err = migration.store.Dialect().UpdatePrimaryKey(ctx, tx, new(existingResetPasswordRequest), new(newResetPasswordRequest), UserReference, func(ctx context.Context) error {
|
||||||
|
existingResetPasswordRequests := make([]*existingResetPasswordRequest, 0)
|
||||||
|
err = tx.
|
||||||
|
NewSelect().
|
||||||
|
Model(&existingResetPasswordRequests).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && len(existingResetPasswordRequests) > 0 {
|
||||||
|
newResetPasswordRequests := migration.
|
||||||
|
CopyExistingResetPasswordRequestsToNewResetPasswordRequests(existingResetPasswordRequests)
|
||||||
|
_, err = tx.
|
||||||
|
NewInsert().
|
||||||
|
Model(&newResetPasswordRequests).
|
||||||
|
Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migration.store.Dialect().RenameTableAndModifyModel(ctx, tx, new(existingPersonalAccessToken), new(newPersonalAccessToken), []string{OrgReference, UserReference}, func(ctx context.Context) error {
|
||||||
|
existingPersonalAccessTokens := make([]*existingPersonalAccessToken, 0)
|
||||||
|
err = tx.
|
||||||
|
NewSelect().
|
||||||
|
Model(&existingPersonalAccessTokens).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && len(existingPersonalAccessTokens) > 0 {
|
||||||
|
newPersonalAccessTokens := migration.
|
||||||
|
CopyExistingPATsToNewPATs(existingPersonalAccessTokens)
|
||||||
|
_, err = tx.NewInsert().Model(&newPersonalAccessTokens).Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateResetPassword) Down(context.Context, *bun.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateResetPassword) CopyExistingResetPasswordRequestsToNewResetPasswordRequests(existingPasswordRequests []*existingResetPasswordRequest) []*newResetPasswordRequest {
|
||||||
|
newResetPasswordRequests := make([]*newResetPasswordRequest, 0)
|
||||||
|
for _, request := range existingPasswordRequests {
|
||||||
|
newResetPasswordRequests = append(newResetPasswordRequests, &newResetPasswordRequest{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
|
Token: request.Token,
|
||||||
|
UserID: request.UserID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return newResetPasswordRequests
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updateResetPassword) CopyExistingPATsToNewPATs(existingPATs []*existingPersonalAccessToken) []*newPersonalAccessToken {
|
||||||
|
newPATs := make([]*newPersonalAccessToken, 0)
|
||||||
|
for _, pat := range existingPATs {
|
||||||
|
newPATs = append(newPATs, &newPersonalAccessToken{
|
||||||
|
Identifiable: types.Identifiable{
|
||||||
|
ID: valuer.GenerateUUID(),
|
||||||
|
},
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: pat.CreatedAt,
|
||||||
|
UpdatedAt: pat.UpdatedAt,
|
||||||
|
},
|
||||||
|
Role: pat.Role,
|
||||||
|
Name: pat.Name,
|
||||||
|
ExpiresAt: pat.ExpiresAt,
|
||||||
|
LastUsed: pat.LastUsed,
|
||||||
|
UserID: pat.UserID,
|
||||||
|
Token: pat.Token,
|
||||||
|
Revoked: pat.Revoked,
|
||||||
|
UpdatedByUserID: pat.UpdatedByUserID,
|
||||||
|
OrgID: pat.OrgID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return newPATs
|
||||||
|
}
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
@ -183,7 +184,10 @@ func (dialect *dialect) TableExists(ctx context.Context, bun bun.IDB, table inte
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, references []string, cb func(context.Context) error) error {
|
||||||
|
if len(references) == 0 {
|
||||||
|
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot run migration without reference")
|
||||||
|
}
|
||||||
exists, err := dialect.TableExists(ctx, bun, newModel)
|
exists, err := dialect.TableExists(ctx, bun, newModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -192,13 +196,25 @@ func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.I
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bun.
|
var fkReferences []string
|
||||||
|
for _, reference := range references {
|
||||||
|
if reference == Org && !slices.Contains(fkReferences, OrgReference) {
|
||||||
|
fkReferences = append(fkReferences, OrgReference)
|
||||||
|
} else if reference == User && !slices.Contains(fkReferences, UserReference) {
|
||||||
|
fkReferences = append(fkReferences, UserReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createTable := bun.
|
||||||
NewCreateTable().
|
NewCreateTable().
|
||||||
IfNotExists().
|
IfNotExists().
|
||||||
Model(newModel).
|
Model(newModel)
|
||||||
ForeignKey(`("org_id") REFERENCES "organizations" ("id")`).
|
|
||||||
Exec(ctx)
|
|
||||||
|
|
||||||
|
for _, fk := range fkReferences {
|
||||||
|
createTable = createTable.ForeignKey(fk)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = createTable.Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ type SQLDialect interface {
|
|||||||
GetColumnType(context.Context, bun.IDB, string, string) (string, error)
|
GetColumnType(context.Context, bun.IDB, string, string) (string, error)
|
||||||
ColumnExists(context.Context, bun.IDB, string, string) (bool, error)
|
ColumnExists(context.Context, bun.IDB, string, string) (bool, error)
|
||||||
RenameColumn(context.Context, bun.IDB, string, string, string) (bool, error)
|
RenameColumn(context.Context, bun.IDB, string, string, string) (bool, error)
|
||||||
RenameTableAndModifyModel(context.Context, bun.IDB, interface{}, interface{}, func(context.Context) error) error
|
RenameTableAndModifyModel(context.Context, bun.IDB, interface{}, interface{}, []string, func(context.Context) error) error
|
||||||
UpdatePrimaryKey(context.Context, bun.IDB, interface{}, interface{}, string, func(context.Context) error) error
|
UpdatePrimaryKey(context.Context, bun.IDB, interface{}, interface{}, string, func(context.Context) error) error
|
||||||
AddPrimaryKey(context.Context, bun.IDB, interface{}, interface{}, string, func(context.Context) error) error
|
AddPrimaryKey(context.Context, bun.IDB, interface{}, interface{}, string, func(context.Context) error) error
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func (dialect *dialect) RenameColumn(ctx context.Context, bun bun.IDB, table str
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, cb func(context.Context) error) error {
|
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, references []string, cb func(context.Context) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ type User struct {
|
|||||||
|
|
||||||
type ResetPasswordRequest struct {
|
type ResetPasswordRequest struct {
|
||||||
bun.BaseModel `bun:"table:reset_password_request"`
|
bun.BaseModel `bun:"table:reset_password_request"`
|
||||||
ID int `bun:"id,pk,autoincrement" json:"id"`
|
Identifiable
|
||||||
Token string `bun:"token,type:text,notnull" json:"token"`
|
Token string `bun:"token,type:text,notnull" json:"token"`
|
||||||
UserID string `bun:"user_id,type:text,notnull" json:"userId"`
|
UserID string `bun:"user_id,type:text,notnull" json:"userId"`
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user