mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 10:49:03 +08:00
chore: add migration for pat to add default values (#7492)
* chore: add migration for pat to add default values * fix: minor changes * fix: don't panic in GetClickhouseColumnName * fix: use new function for pat * fix: address minor comments * fix: address comments * fix: remove generatepat * fix: minor changes * fix: remove extra check --------- Co-authored-by: Vibhu Pandey <vibhupandey28@gmail.com>
This commit is contained in:
parent
eb9385840f
commit
07a244f569
@ -4,6 +4,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
eeTypes "github.com/SigNoz/signoz/ee/types"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
@ -24,7 +25,7 @@ func (p *Pat) Wrap(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
var values []string
|
var values []string
|
||||||
var patToken string
|
var patToken string
|
||||||
var pat types.StorablePersonalAccessToken
|
var pat eeTypes.StorablePersonalAccessToken
|
||||||
|
|
||||||
for _, header := range p.headers {
|
for _, header := range p.headers {
|
||||||
values = append(values, r.Header.Get(header))
|
values = append(values, r.Header.Get(header))
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/ee/query-service/constants"
|
"github.com/SigNoz/signoz/ee/query-service/constants"
|
||||||
"github.com/SigNoz/signoz/ee/query-service/model"
|
eeTypes "github.com/SigNoz/signoz/ee/types"
|
||||||
"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"
|
||||||
"github.com/SigNoz/signoz/pkg/query-service/dao"
|
"github.com/SigNoz/signoz/pkg/query-service/dao"
|
||||||
@ -135,19 +135,12 @@ func (ah *APIHandler) getOrCreateCloudIntegrationPAT(ctx context.Context, orgId
|
|||||||
zap.String("cloudProvider", cloudProvider),
|
zap.String("cloudProvider", cloudProvider),
|
||||||
)
|
)
|
||||||
|
|
||||||
newPAT := model.PAT{
|
newPAT := eeTypes.NewGettablePAT(
|
||||||
StorablePersonalAccessToken: types.StorablePersonalAccessToken{
|
integrationPATName,
|
||||||
Token: generatePATToken(),
|
baseconstants.ViewerGroup,
|
||||||
UserID: integrationUser.ID,
|
integrationUser.ID,
|
||||||
Name: integrationPATName,
|
0,
|
||||||
Role: baseconstants.ViewerGroup,
|
)
|
||||||
ExpiresAt: 0,
|
|
||||||
TimeAuditable: types.TimeAuditable{
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
UpdatedAt: time.Now(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
integrationPAT, err := ah.AppDao().CreatePAT(ctx, orgId, newPAT)
|
integrationPAT, err := ah.AppDao().CreatePAT(ctx, orgId, newPAT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", basemodel.InternalError(fmt.Errorf(
|
return "", basemodel.InternalError(fmt.Errorf(
|
||||||
|
@ -2,31 +2,21 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/ee/query-service/model"
|
"github.com/SigNoz/signoz/ee/query-service/model"
|
||||||
|
"github.com/SigNoz/signoz/ee/types"
|
||||||
|
eeTypes "github.com/SigNoz/signoz/ee/types"
|
||||||
"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/types"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generatePATToken() string {
|
|
||||||
// Generate a 32-byte random token.
|
|
||||||
token := make([]byte, 32)
|
|
||||||
rand.Read(token)
|
|
||||||
// Encode the token in base64.
|
|
||||||
encodedToken := base64.StdEncoding.EncodeToString(token)
|
|
||||||
return encodedToken
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
|
func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
@ -43,31 +33,18 @@ func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
|
|||||||
}, nil)
|
}, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pat := model.PAT{
|
pat := eeTypes.NewGettablePAT(
|
||||||
StorablePersonalAccessToken: types.StorablePersonalAccessToken{
|
req.Name,
|
||||||
Name: req.Name,
|
req.Role,
|
||||||
Role: req.Role,
|
user.ID,
|
||||||
ExpiresAt: req.ExpiresInDays,
|
req.ExpiresInDays,
|
||||||
},
|
)
|
||||||
}
|
|
||||||
err = validatePATRequest(pat)
|
err = validatePATRequest(pat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
RespondError(w, model.BadRequest(err), nil)
|
RespondError(w, model.BadRequest(err), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// All the PATs are associated with the user creating the PAT.
|
|
||||||
pat.UserID = user.ID
|
|
||||||
pat.CreatedAt = time.Now()
|
|
||||||
pat.UpdatedAt = time.Now()
|
|
||||||
pat.LastUsed = 0
|
|
||||||
pat.Token = generatePATToken()
|
|
||||||
|
|
||||||
if pat.ExpiresAt != 0 {
|
|
||||||
// convert expiresAt to unix timestamp from days
|
|
||||||
pat.ExpiresAt = time.Now().Unix() + (pat.ExpiresAt * 24 * 60 * 60)
|
|
||||||
}
|
|
||||||
|
|
||||||
zap.L().Info("Got Create PAT request", zap.Any("pat", pat))
|
zap.L().Info("Got Create PAT request", zap.Any("pat", pat))
|
||||||
var apierr basemodel.BaseApiError
|
var apierr basemodel.BaseApiError
|
||||||
if pat, apierr = ah.AppDao().CreatePAT(ctx, user.OrgID, pat); apierr != nil {
|
if pat, apierr = ah.AppDao().CreatePAT(ctx, user.OrgID, pat); apierr != nil {
|
||||||
@ -78,7 +55,7 @@ func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
|
|||||||
ah.Respond(w, &pat)
|
ah.Respond(w, &pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validatePATRequest(req model.PAT) error {
|
func validatePATRequest(req types.GettablePAT) error {
|
||||||
if req.Role == "" || (req.Role != baseconstants.ViewerGroup && req.Role != baseconstants.EditorGroup && req.Role != baseconstants.AdminGroup) {
|
if req.Role == "" || (req.Role != baseconstants.ViewerGroup && req.Role != baseconstants.EditorGroup && req.Role != baseconstants.AdminGroup) {
|
||||||
return fmt.Errorf("valid role is required")
|
return fmt.Errorf("valid role is required")
|
||||||
}
|
}
|
||||||
@ -94,7 +71,7 @@ func validatePATRequest(req model.PAT) error {
|
|||||||
func (ah *APIHandler) updatePAT(w http.ResponseWriter, r *http.Request) {
|
func (ah *APIHandler) updatePAT(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
req := model.PAT{}
|
req := types.GettablePAT{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
RespondError(w, model.BadRequest(err), nil)
|
RespondError(w, model.BadRequest(err), nil)
|
||||||
return
|
return
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/ee/query-service/model"
|
|
||||||
"github.com/SigNoz/signoz/ee/types"
|
"github.com/SigNoz/signoz/ee/types"
|
||||||
basedao "github.com/SigNoz/signoz/pkg/query-service/dao"
|
basedao "github.com/SigNoz/signoz/pkg/query-service/dao"
|
||||||
baseint "github.com/SigNoz/signoz/pkg/query-service/interfaces"
|
baseint "github.com/SigNoz/signoz/pkg/query-service/interfaces"
|
||||||
@ -36,11 +35,11 @@ type ModelDao interface {
|
|||||||
DeleteDomain(ctx context.Context, id uuid.UUID) basemodel.BaseApiError
|
DeleteDomain(ctx context.Context, id uuid.UUID) basemodel.BaseApiError
|
||||||
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 model.PAT) (model.PAT, basemodel.BaseApiError)
|
CreatePAT(ctx context.Context, orgID string, p types.GettablePAT) (types.GettablePAT, basemodel.BaseApiError)
|
||||||
UpdatePAT(ctx context.Context, orgID string, p model.PAT, id string) basemodel.BaseApiError
|
UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id string) basemodel.BaseApiError
|
||||||
GetPAT(ctx context.Context, pat string) (*model.PAT, basemodel.BaseApiError)
|
GetPAT(ctx context.Context, pat string) (*types.GettablePAT, basemodel.BaseApiError)
|
||||||
GetPATByID(ctx context.Context, orgID string, id string) (*model.PAT, basemodel.BaseApiError)
|
GetPATByID(ctx context.Context, orgID string, id string) (*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) ([]model.PAT, 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 string, userID string) basemodel.BaseApiError
|
||||||
}
|
}
|
||||||
|
@ -6,41 +6,47 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/ee/query-service/model"
|
"github.com/SigNoz/signoz/ee/query-service/model"
|
||||||
|
"github.com/SigNoz/signoz/ee/types"
|
||||||
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
ossTypes "github.com/SigNoz/signoz/pkg/types"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *modelDao) CreatePAT(ctx context.Context, orgID string, p model.PAT) (model.PAT, 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
|
||||||
_, err := m.DB().NewInsert().
|
_, err := m.DB().NewInsert().
|
||||||
Model(&p.StorablePersonalAccessToken).
|
Model(&p.StorablePersonalAccessToken).
|
||||||
Returning("id").
|
|
||||||
Exec(ctx)
|
Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("Failed to insert PAT in db, err: %v", zap.Error(err))
|
zap.L().Error("Failed to insert PAT in db, err: %v", zap.Error(err))
|
||||||
return model.PAT{}, model.InternalError(fmt.Errorf("PAT insertion failed"))
|
return types.GettablePAT{}, model.InternalError(fmt.Errorf("PAT insertion failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
createdByUser, _ := m.GetUser(ctx, p.UserID)
|
createdByUser, _ := m.GetUser(ctx, p.UserID)
|
||||||
if createdByUser == nil {
|
if createdByUser == nil {
|
||||||
p.CreatedByUser = model.User{
|
p.CreatedByUser = types.PatUser{
|
||||||
NotFound: true,
|
NotFound: true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.CreatedByUser = model.User{
|
p.CreatedByUser = types.PatUser{
|
||||||
Id: createdByUser.ID,
|
User: ossTypes.User{
|
||||||
Name: createdByUser.Name,
|
ID: createdByUser.ID,
|
||||||
Email: createdByUser.Email,
|
Name: createdByUser.Name,
|
||||||
CreatedAt: createdByUser.CreatedAt.Unix(),
|
Email: createdByUser.Email,
|
||||||
ProfilePictureURL: createdByUser.ProfilePictureURL,
|
TimeAuditable: ossTypes.TimeAuditable{
|
||||||
NotFound: false,
|
CreatedAt: createdByUser.CreatedAt,
|
||||||
|
UpdatedAt: createdByUser.UpdatedAt,
|
||||||
|
},
|
||||||
|
ProfilePictureURL: createdByUser.ProfilePictureURL,
|
||||||
|
},
|
||||||
|
NotFound: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) UpdatePAT(ctx context.Context, orgID string, p model.PAT, id string) basemodel.BaseApiError {
|
func (m *modelDao) UpdatePAT(ctx context.Context, orgID string, p types.GettablePAT, id string) 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").
|
||||||
@ -55,7 +61,7 @@ func (m *modelDao) UpdatePAT(ctx context.Context, orgID string, p model.PAT, id
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) ListPATs(ctx context.Context, orgID string) ([]model.PAT, basemodel.BaseApiError) {
|
func (m *modelDao) ListPATs(ctx context.Context, orgID string) ([]types.GettablePAT, basemodel.BaseApiError) {
|
||||||
pats := []types.StorablePersonalAccessToken{}
|
pats := []types.StorablePersonalAccessToken{}
|
||||||
|
|
||||||
if err := m.DB().NewSelect().
|
if err := m.DB().NewSelect().
|
||||||
@ -68,41 +74,51 @@ func (m *modelDao) ListPATs(ctx context.Context, orgID string) ([]model.PAT, bas
|
|||||||
return nil, model.InternalError(fmt.Errorf("failed to fetch PATs"))
|
return nil, model.InternalError(fmt.Errorf("failed to fetch PATs"))
|
||||||
}
|
}
|
||||||
|
|
||||||
patsWithUsers := []model.PAT{}
|
patsWithUsers := []types.GettablePAT{}
|
||||||
for i := range pats {
|
for i := range pats {
|
||||||
patWithUser := model.PAT{
|
patWithUser := types.GettablePAT{
|
||||||
StorablePersonalAccessToken: pats[i],
|
StorablePersonalAccessToken: pats[i],
|
||||||
}
|
}
|
||||||
|
|
||||||
createdByUser, _ := m.GetUser(ctx, pats[i].UserID)
|
createdByUser, _ := m.GetUser(ctx, pats[i].UserID)
|
||||||
if createdByUser == nil {
|
if createdByUser == nil {
|
||||||
patWithUser.CreatedByUser = model.User{
|
patWithUser.CreatedByUser = types.PatUser{
|
||||||
NotFound: true,
|
NotFound: true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
patWithUser.CreatedByUser = model.User{
|
patWithUser.CreatedByUser = types.PatUser{
|
||||||
Id: createdByUser.ID,
|
User: ossTypes.User{
|
||||||
Name: createdByUser.Name,
|
ID: createdByUser.ID,
|
||||||
Email: createdByUser.Email,
|
Name: createdByUser.Name,
|
||||||
CreatedAt: createdByUser.CreatedAt.Unix(),
|
Email: createdByUser.Email,
|
||||||
ProfilePictureURL: createdByUser.ProfilePictureURL,
|
TimeAuditable: ossTypes.TimeAuditable{
|
||||||
NotFound: false,
|
CreatedAt: createdByUser.CreatedAt,
|
||||||
|
UpdatedAt: createdByUser.UpdatedAt,
|
||||||
|
},
|
||||||
|
ProfilePictureURL: createdByUser.ProfilePictureURL,
|
||||||
|
},
|
||||||
|
NotFound: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedByUser, _ := m.GetUser(ctx, pats[i].UpdatedByUserID)
|
updatedByUser, _ := m.GetUser(ctx, pats[i].UpdatedByUserID)
|
||||||
if updatedByUser == nil {
|
if updatedByUser == nil {
|
||||||
patWithUser.UpdatedByUser = model.User{
|
patWithUser.UpdatedByUser = types.PatUser{
|
||||||
NotFound: true,
|
NotFound: true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
patWithUser.UpdatedByUser = model.User{
|
patWithUser.UpdatedByUser = types.PatUser{
|
||||||
Id: updatedByUser.ID,
|
User: ossTypes.User{
|
||||||
Name: updatedByUser.Name,
|
ID: updatedByUser.ID,
|
||||||
Email: updatedByUser.Email,
|
Name: updatedByUser.Name,
|
||||||
CreatedAt: updatedByUser.CreatedAt.Unix(),
|
Email: updatedByUser.Email,
|
||||||
ProfilePictureURL: updatedByUser.ProfilePictureURL,
|
TimeAuditable: ossTypes.TimeAuditable{
|
||||||
NotFound: false,
|
CreatedAt: updatedByUser.CreatedAt,
|
||||||
|
UpdatedAt: updatedByUser.UpdatedAt,
|
||||||
|
},
|
||||||
|
ProfilePictureURL: updatedByUser.ProfilePictureURL,
|
||||||
|
},
|
||||||
|
NotFound: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +144,7 @@ func (m *modelDao) RevokePAT(ctx context.Context, orgID string, id string, userI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) GetPAT(ctx context.Context, token string) (*model.PAT, basemodel.BaseApiError) {
|
func (m *modelDao) GetPAT(ctx context.Context, token string) (*types.GettablePAT, basemodel.BaseApiError) {
|
||||||
pats := []types.StorablePersonalAccessToken{}
|
pats := []types.StorablePersonalAccessToken{}
|
||||||
|
|
||||||
if err := m.DB().NewSelect().
|
if err := m.DB().NewSelect().
|
||||||
@ -146,14 +162,14 @@ func (m *modelDao) GetPAT(ctx context.Context, token string) (*model.PAT, basemo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patWithUser := model.PAT{
|
patWithUser := types.GettablePAT{
|
||||||
StorablePersonalAccessToken: pats[0],
|
StorablePersonalAccessToken: pats[0],
|
||||||
}
|
}
|
||||||
|
|
||||||
return &patWithUser, nil
|
return &patWithUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id string) (*model.PAT, basemodel.BaseApiError) {
|
func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id string) (*types.GettablePAT, basemodel.BaseApiError) {
|
||||||
pats := []types.StorablePersonalAccessToken{}
|
pats := []types.StorablePersonalAccessToken{}
|
||||||
|
|
||||||
if err := m.DB().NewSelect().
|
if err := m.DB().NewSelect().
|
||||||
@ -172,7 +188,7 @@ func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id string) (*mo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patWithUser := model.PAT{
|
patWithUser := types.GettablePAT{
|
||||||
StorablePersonalAccessToken: pats[0],
|
StorablePersonalAccessToken: pats[0],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,8 +196,8 @@ func (m *modelDao) GetPATByID(ctx context.Context, orgID string, id string) (*mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
func (m *modelDao) GetUserByPAT(ctx context.Context, orgID string, token string) (*types.GettableUser, basemodel.BaseApiError) {
|
func (m *modelDao) GetUserByPAT(ctx context.Context, orgID string, token string) (*ossTypes.GettableUser, basemodel.BaseApiError) {
|
||||||
users := []types.GettableUser{}
|
users := []ossTypes.GettableUser{}
|
||||||
|
|
||||||
if err := m.DB().NewSelect().
|
if err := m.DB().NewSelect().
|
||||||
Model(&users).
|
Model(&users).
|
||||||
|
@ -1,25 +1,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "github.com/SigNoz/signoz/pkg/types"
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Id string `json:"id" db:"id"`
|
|
||||||
Name string `json:"name" db:"name"`
|
|
||||||
Email string `json:"email" db:"email"`
|
|
||||||
CreatedAt int64 `json:"createdAt" db:"created_at"`
|
|
||||||
ProfilePictureURL string `json:"profilePictureURL" db:"profile_picture_url"`
|
|
||||||
NotFound bool `json:"notFound"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreatePATRequestBody struct {
|
type CreatePATRequestBody struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
ExpiresInDays int64 `json:"expiresInDays"`
|
ExpiresInDays int64 `json:"expiresInDays"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PAT struct {
|
|
||||||
CreatedByUser User `json:"createdByUser"`
|
|
||||||
UpdatedByUser User `json:"updatedByUser"`
|
|
||||||
|
|
||||||
types.StorablePersonalAccessToken
|
|
||||||
}
|
|
||||||
|
@ -2,6 +2,7 @@ package postgressqlstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
@ -209,3 +210,11 @@ func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.I
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
||||||
|
query := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT %s, ALTER COLUMN %s SET NOT NULL", table, column, defaultValue, column)
|
||||||
|
if _, err := bun.ExecContext(ctx, query); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
73
ee/types/personal_access_token.go
Normal file
73
ee/types/personal_access_token.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GettablePAT struct {
|
||||||
|
CreatedByUser PatUser `json:"createdByUser"`
|
||||||
|
UpdatedByUser PatUser `json:"updatedByUser"`
|
||||||
|
|
||||||
|
StorablePersonalAccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
type PatUser struct {
|
||||||
|
types.User
|
||||||
|
NotFound bool `json:"notFound"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGettablePAT(name, role, userID string, expiresAt int64) GettablePAT {
|
||||||
|
return GettablePAT{
|
||||||
|
StorablePersonalAccessToken: NewStorablePersonalAccessToken(name, role, userID, expiresAt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StorablePersonalAccessToken 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:''"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStorablePersonalAccessToken(name, role, userID string, expiresAt int64) StorablePersonalAccessToken {
|
||||||
|
now := time.Now()
|
||||||
|
if expiresAt != 0 {
|
||||||
|
// convert expiresAt to unix timestamp from days
|
||||||
|
expiresAt = now.Unix() + (expiresAt * 24 * 60 * 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a 32-byte random token.
|
||||||
|
token := make([]byte, 32)
|
||||||
|
rand.Read(token)
|
||||||
|
// Encode the token in base64.
|
||||||
|
encodedToken := base64.StdEncoding.EncodeToString(token)
|
||||||
|
|
||||||
|
return StorablePersonalAccessToken{
|
||||||
|
Token: encodedToken,
|
||||||
|
Name: name,
|
||||||
|
Role: role,
|
||||||
|
UserID: userID,
|
||||||
|
ExpiresAt: expiresAt,
|
||||||
|
LastUsed: 0,
|
||||||
|
Revoked: false,
|
||||||
|
UpdatedByUserID: "",
|
||||||
|
TimeAuditable: types.TimeAuditable{
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -64,6 +64,7 @@ func NewSQLMigrationProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedM
|
|||||||
sqlmigration.NewUpdatePipelines(sqlstore),
|
sqlmigration.NewUpdatePipelines(sqlstore),
|
||||||
sqlmigration.NewDropLicensesSitesFactory(sqlstore),
|
sqlmigration.NewDropLicensesSitesFactory(sqlstore),
|
||||||
sqlmigration.NewUpdateInvitesFactory(sqlstore),
|
sqlmigration.NewUpdateInvitesFactory(sqlstore),
|
||||||
|
sqlmigration.NewUpdatePatFactory(sqlstore),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
@ -50,12 +49,14 @@ func (migration *addAlertmanager) Up(ctx context.Context, db *bun.DB) error {
|
|||||||
|
|
||||||
defer tx.Rollback() //nolint:errcheck
|
defer tx.Rollback() //nolint:errcheck
|
||||||
|
|
||||||
if _, err := tx.
|
if exists, err := migration.store.Dialect().ColumnExists(ctx, tx, "notification_channels", "deleted"); err != nil {
|
||||||
NewDropColumn().
|
return err
|
||||||
Table("notification_channels").
|
} else if exists {
|
||||||
ColumnExpr("deleted").
|
if _, err := tx.
|
||||||
Exec(ctx); err != nil {
|
NewDropColumn().
|
||||||
if !strings.Contains(err.Error(), "no such column") {
|
Table("notification_channels").
|
||||||
|
ColumnExpr("deleted").
|
||||||
|
Exec(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
pkg/sqlmigration/020_pat_update.go
Normal file
68
pkg/sqlmigration/020_pat_update.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package sqlmigration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
"github.com/uptrace/bun/migrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type updatePat struct {
|
||||||
|
store sqlstore.SQLStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdatePatFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||||
|
return factory.NewProviderFactory(factory.MustNewName("update_pat"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) {
|
||||||
|
return newUpdatePat(ctx, ps, c, sqlstore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUpdatePat(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) {
|
||||||
|
return &updatePat{
|
||||||
|
store: store,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updatePat) Register(migrations *migrate.Migrations) error {
|
||||||
|
if err := migrations.Register(migration.Up, migration.Down); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updatePat) Up(ctx context.Context, db *bun.DB) error {
|
||||||
|
|
||||||
|
// begin transaction
|
||||||
|
tx, err := db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
for _, column := range []string{"last_used", "expires_at"} {
|
||||||
|
if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", column, "INTEGER", "0"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "revoked", "BOOLEAN", "false"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "updated_by_user_id", "TEXT", "''"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (migration *updatePat) Down(ctx context.Context, db *bun.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -2,6 +2,7 @@ package sqlitesqlstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
@ -201,3 +202,23 @@ func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.I
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
||||||
|
if _, err := bun.NewAddColumn().Table(table).ColumnExpr(fmt.Sprintf("%s_new %s NOT NULL DEFAULT %s ", column, columnType, defaultValue)).Exec(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := bun.NewUpdate().Table(table).Set(fmt.Sprintf("%s_new = %s", column, column)).Where("1=1").Exec(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := bun.NewDropColumn().Table(table).ColumnExpr(column).Exec(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := bun.ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME COLUMN %s_new TO %s", table, column, column)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -39,6 +39,7 @@ type SQLStoreHook interface {
|
|||||||
type SQLDialect interface {
|
type SQLDialect interface {
|
||||||
MigrateIntToTimestamp(context.Context, bun.IDB, string, string) error
|
MigrateIntToTimestamp(context.Context, bun.IDB, string, string) error
|
||||||
MigrateIntToBoolean(context.Context, bun.IDB, string, string) error
|
MigrateIntToBoolean(context.Context, bun.IDB, string, string) error
|
||||||
|
AddNotNullDefaultToColumn(context.Context, bun.IDB, string, string, string, string) error
|
||||||
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)
|
||||||
|
@ -32,3 +32,7 @@ func (dialect *dialect) RenameColumn(ctx context.Context, bun bun.IDB, table str
|
|||||||
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{}, cb func(context.Context) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/uptrace/bun"
|
|
||||||
)
|
|
||||||
|
|
||||||
type StorablePersonalAccessToken struct {
|
|
||||||
bun.BaseModel `bun:"table:personal_access_tokens"`
|
|
||||||
|
|
||||||
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:''"`
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user