mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 23:47:12 +00:00
* chore: update auth * chore: password changes * chore: make changes in oss code * chore: login * chore: get to a running state * fix: migration inital commit * fix: signoz cloud intgtn tests * fix: minor fixes * chore: sso code fixed with org domain * fix: tests * fix: ee auth api's * fix: changes in name * fix: return user in login api * fix: address comments * fix: validate password * fix: handle get domain by email properly * fix: move authomain to usermodule * fix: use displayname instead of hname * fix: rename back endpoints * fix: update telemetry * fix: correct errors * fix: test and fix the invite endpoints * fix: delete all things related to user in store * fix: address issues * fix: ee delete invite * fix: rename func * fix: update user and update role * fix: update role * fix: login and invite changes * fix: return org name in users response * fix: update user role * fix: nil check * fix: getinvite and update role * fix: sso * fix: getinvite use sso ctx * fix: use correct sourceurl * fix: getsourceurl from req payload * fix: update created_at * fix: fix reset password * fix: sso signup and token password change * fix: don't delete last admin * fix: reset password and migration * fix: migration * fix: reset password for sso users * fix: clean up invite * fix: migration * fix: update claims and store code * fix: use correct error * fix: proper nil checks * fix: make migration multitenant * fix: address comments * fix: minor fixes * fix: test * fix: rename reset password --------- Co-authored-by: Vikrant Gupta <vikrant@signoz.io>
477 lines
14 KiB
Go
477 lines
14 KiB
Go
package impluser
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
|
"github.com/SigNoz/signoz/pkg/types"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
)
|
|
|
|
type Store struct {
|
|
sqlstore sqlstore.SQLStore
|
|
}
|
|
|
|
func NewStore(sqlstore sqlstore.SQLStore) types.UserStore {
|
|
return &Store{sqlstore: sqlstore}
|
|
}
|
|
|
|
// CreateBulkInvite implements types.InviteStore.
|
|
func (s *Store) CreateBulkInvite(ctx context.Context, invites []*types.Invite) error {
|
|
_, err := s.sqlstore.BunDB().NewInsert().
|
|
Model(&invites).
|
|
Exec(ctx)
|
|
|
|
if err != nil {
|
|
return s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrInviteAlreadyExists, "invite with email: %s already exists in org: %s", invites[0].Email, invites[0].OrgID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete implements types.InviteStore.
|
|
func (s *Store) DeleteInvite(ctx context.Context, orgID string, id valuer.UUID) error {
|
|
_, err := s.sqlstore.BunDB().NewDelete().
|
|
Model(&types.Invite{}).
|
|
Where("org_id = ?", orgID).
|
|
Where("id = ?", id).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapNotFoundErrf(err, types.ErrInviteNotFound, "invite with id: %s does not exist in org: %s", id.StringValue(), orgID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetInviteByEmailInOrg implements types.InviteStore.
|
|
func (s *Store) GetInviteByEmailInOrg(ctx context.Context, orgID string, email string) (*types.Invite, error) {
|
|
invite := new(types.Invite)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(invite).
|
|
Where("email = ?", email).
|
|
Where("org_id = ?", orgID).
|
|
Scan(ctx)
|
|
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrInviteNotFound, "invite with email: %s does not exist in org: %s", email, orgID)
|
|
}
|
|
|
|
return invite, nil
|
|
}
|
|
|
|
func (s *Store) GetInviteByToken(ctx context.Context, token string) (*types.GettableInvite, error) {
|
|
invite := new(types.Invite)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(invite).
|
|
Where("token = ?", token).
|
|
Scan(ctx)
|
|
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrInviteNotFound, "invite with token: %s does not exist", token)
|
|
}
|
|
|
|
orgName, err := s.getOrgNameByID(ctx, invite.OrgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
gettableInvite := &types.GettableInvite{
|
|
Invite: *invite,
|
|
Organization: orgName,
|
|
}
|
|
|
|
return gettableInvite, nil
|
|
}
|
|
|
|
func (s *Store) ListInvite(ctx context.Context, orgID string) ([]*types.Invite, error) {
|
|
invites := new([]*types.Invite)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(invites).
|
|
Where("org_id = ?", orgID).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrInviteNotFound, "invite with org id: %s does not exist", orgID)
|
|
}
|
|
return *invites, nil
|
|
}
|
|
|
|
func (s *Store) CreatePassword(ctx context.Context, password *types.FactorPassword) (*types.FactorPassword, error) {
|
|
_, err := s.sqlstore.BunDB().NewInsert().
|
|
Model(password).
|
|
Exec(ctx)
|
|
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrPasswordAlreadyExists, "password with user id: %s already exists", password.UserID)
|
|
}
|
|
|
|
return password, nil
|
|
}
|
|
|
|
func (s *Store) CreateUserWithPassword(ctx context.Context, user *types.User, password *types.FactorPassword) (*types.User, error) {
|
|
tx, err := s.sqlstore.BunDB().BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to start transaction")
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
if _, err := tx.NewInsert().
|
|
Model(user).
|
|
Exec(ctx); err != nil {
|
|
return nil, s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrUserAlreadyExists, "user with email: %s already exists in org: %s", user.Email, user.OrgID)
|
|
}
|
|
|
|
password.UserID = user.ID.StringValue()
|
|
if _, err := tx.NewInsert().
|
|
Model(password).
|
|
Exec(ctx); err != nil {
|
|
return nil, s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrPasswordAlreadyExists, "password with email: %s already exists in org: %s", user.Email, user.OrgID)
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to commit transaction")
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (s *Store) CreateUser(ctx context.Context, user *types.User) error {
|
|
_, err := s.sqlstore.BunDB().NewInsert().
|
|
Model(user).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrUserAlreadyExists, "user with email: %s already exists in org: %s", user.Email, user.OrgID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) GetDefaultOrgID(ctx context.Context) (string, error) {
|
|
org := new(types.Organization)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(org).
|
|
Limit(1).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return "", s.sqlstore.WrapNotFoundErrf(err, types.ErrOrganizationNotFound, "default org does not exist")
|
|
}
|
|
return org.ID.String(), nil
|
|
}
|
|
|
|
// this is temporary function, we plan to remove this in the next PR.
|
|
func (s *Store) getOrgNameByID(ctx context.Context, orgID string) (string, error) {
|
|
org := new(types.Organization)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(org).
|
|
Where("id = ?", orgID).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return "", s.sqlstore.WrapNotFoundErrf(err, types.ErrOrganizationNotFound, "org with id: %s does not exist", orgID)
|
|
}
|
|
return org.DisplayName, nil
|
|
}
|
|
|
|
func (s *Store) GetUserByID(ctx context.Context, orgID string, id string) (*types.GettableUser, error) {
|
|
user := new(types.User)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(user).
|
|
Where("org_id = ?", orgID).
|
|
Where("id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "user with id: %s does not exist in org: %s", id, orgID)
|
|
}
|
|
|
|
// remove this in next PR
|
|
orgName, err := s.getOrgNameByID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &types.GettableUser{User: *user, Organization: orgName}, nil
|
|
}
|
|
|
|
func (s *Store) GetUserByEmailInOrg(ctx context.Context, orgID string, email string) (*types.GettableUser, error) {
|
|
user := new(types.User)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(user).
|
|
Where("org_id = ?", orgID).
|
|
Where("email = ?", email).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "user with email: %s does not exist in org: %s", email, orgID)
|
|
}
|
|
|
|
// remove this in next PR
|
|
orgName, err := s.getOrgNameByID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &types.GettableUser{User: *user, Organization: orgName}, nil
|
|
}
|
|
|
|
func (s *Store) GetUsersByEmail(ctx context.Context, email string) ([]*types.GettableUser, error) {
|
|
users := new([]*types.User)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(users).
|
|
Where("email = ?", email).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "user with email: %s does not exist", email)
|
|
}
|
|
|
|
// remove this in next PR
|
|
usersWithOrg := []*types.GettableUser{}
|
|
for _, user := range *users {
|
|
orgName, err := s.getOrgNameByID(ctx, user.OrgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usersWithOrg = append(usersWithOrg, &types.GettableUser{User: *user, Organization: orgName})
|
|
}
|
|
return usersWithOrg, nil
|
|
}
|
|
|
|
func (s *Store) GetUsersByRoleInOrg(ctx context.Context, orgID string, role types.Role) ([]*types.GettableUser, error) {
|
|
users := new([]*types.User)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(users).
|
|
Where("org_id = ?", orgID).
|
|
Where("role = ?", role).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "user with role: %s does not exist in org: %s", role, orgID)
|
|
}
|
|
|
|
// remove this in next PR
|
|
orgName, err := s.getOrgNameByID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usersWithOrg := []*types.GettableUser{}
|
|
for _, user := range *users {
|
|
usersWithOrg = append(usersWithOrg, &types.GettableUser{User: *user, Organization: orgName})
|
|
}
|
|
return usersWithOrg, nil
|
|
}
|
|
|
|
func (s *Store) UpdateUser(ctx context.Context, orgID string, id string, user *types.User) (*types.User, error) {
|
|
user.UpdatedAt = time.Now()
|
|
_, err := s.sqlstore.BunDB().NewUpdate().
|
|
Model(user).
|
|
Column("display_name").
|
|
Column("role").
|
|
Column("updated_at").
|
|
Where("id = ?", id).
|
|
Where("org_id = ?", orgID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "user with id: %s does not exist in org: %s", id, orgID)
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (s *Store) ListUsers(ctx context.Context, orgID string) ([]*types.GettableUser, error) {
|
|
users := []*types.User{}
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(&users).
|
|
Where("org_id = ?", orgID).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrUserNotFound, "users with org id: %s does not exist", orgID)
|
|
}
|
|
|
|
// remove this in next PR
|
|
orgName, err := s.getOrgNameByID(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usersWithOrg := []*types.GettableUser{}
|
|
for _, user := range users {
|
|
usersWithOrg = append(usersWithOrg, &types.GettableUser{User: *user, Organization: orgName})
|
|
}
|
|
return usersWithOrg, nil
|
|
}
|
|
|
|
func (s *Store) DeleteUser(ctx context.Context, orgID string, id string) error {
|
|
|
|
tx, err := s.sqlstore.BunDB().BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to start transaction")
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
// get the password id
|
|
|
|
var password types.FactorPassword
|
|
err = tx.NewSelect().
|
|
Model(&password).
|
|
Where("user_id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil && err != sql.ErrNoRows {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to delete password")
|
|
}
|
|
|
|
// delete reset password request
|
|
_, err = tx.NewDelete().
|
|
Model(new(types.ResetPasswordRequest)).
|
|
Where("password_id = ?", password.ID.String()).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to delete reset password request")
|
|
}
|
|
|
|
// delete factor password
|
|
_, err = tx.NewDelete().
|
|
Model(new(types.FactorPassword)).
|
|
Where("user_id = ?", id).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to delete factor password")
|
|
}
|
|
|
|
// delete user
|
|
_, err = tx.NewDelete().
|
|
Model(new(types.User)).
|
|
Where("org_id = ?", orgID).
|
|
Where("id = ?", id).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to delete user")
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to commit transaction")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) CreateResetPasswordToken(ctx context.Context, resetPasswordRequest *types.ResetPasswordRequest) error {
|
|
_, err := s.sqlstore.BunDB().NewInsert().
|
|
Model(resetPasswordRequest).
|
|
Exec(ctx)
|
|
|
|
if err != nil {
|
|
return s.sqlstore.WrapAlreadyExistsErrf(err, types.ErrResetPasswordTokenAlreadyExists, "reset password token with password id: %s already exists", resetPasswordRequest.PasswordID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) GetPasswordByID(ctx context.Context, id string) (*types.FactorPassword, error) {
|
|
password := new(types.FactorPassword)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(password).
|
|
Where("id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password with id: %s does not exist", id)
|
|
}
|
|
return password, nil
|
|
}
|
|
|
|
func (s *Store) GetPasswordByUserID(ctx context.Context, id string) (*types.FactorPassword, error) {
|
|
password := new(types.FactorPassword)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(password).
|
|
Where("user_id = ?", id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password with user id: %s does not exist", id)
|
|
}
|
|
return password, nil
|
|
}
|
|
|
|
func (s *Store) GetResetPasswordByPasswordID(ctx context.Context, passwordID string) (*types.ResetPasswordRequest, error) {
|
|
resetPasswordRequest := new(types.ResetPasswordRequest)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(resetPasswordRequest).
|
|
Where("password_id = ?", passwordID).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrResetPasswordTokenNotFound, "reset password token with password id: %s does not exist", passwordID)
|
|
}
|
|
return resetPasswordRequest, nil
|
|
}
|
|
|
|
func (s *Store) GetResetPassword(ctx context.Context, token string) (*types.ResetPasswordRequest, error) {
|
|
resetPasswordRequest := new(types.ResetPasswordRequest)
|
|
err := s.sqlstore.BunDB().NewSelect().
|
|
Model(resetPasswordRequest).
|
|
Where("token = ?", token).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, s.sqlstore.WrapNotFoundErrf(err, types.ErrResetPasswordTokenNotFound, "reset password token with token: %s does not exist", token)
|
|
}
|
|
return resetPasswordRequest, nil
|
|
}
|
|
|
|
func (s *Store) UpdatePasswordAndDeleteResetPasswordEntry(ctx context.Context, userID string, password string) error {
|
|
tx, err := s.sqlstore.BunDB().BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to start transaction")
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
factorPassword := &types.FactorPassword{
|
|
UserID: userID,
|
|
Password: password,
|
|
TimeAuditable: types.TimeAuditable{
|
|
UpdatedAt: time.Now(),
|
|
},
|
|
}
|
|
_, err = tx.NewUpdate().
|
|
Model(factorPassword).
|
|
Column("password").
|
|
Column("updated_at").
|
|
Where("user_id = ?", userID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password with user id: %s does not exist", userID)
|
|
}
|
|
|
|
_, err = tx.NewDelete().
|
|
Model(&types.ResetPasswordRequest{}).
|
|
Where("password_id = ?", userID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapNotFoundErrf(err, types.ErrResetPasswordTokenNotFound, "reset password token with password id: %s does not exist", userID)
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to commit transaction")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) UpdatePassword(ctx context.Context, userID string, password string) error {
|
|
factorPassword := &types.FactorPassword{
|
|
UserID: userID,
|
|
Password: password,
|
|
TimeAuditable: types.TimeAuditable{
|
|
UpdatedAt: time.Now(),
|
|
},
|
|
}
|
|
_, err := s.sqlstore.BunDB().NewUpdate().
|
|
Model(factorPassword).
|
|
Column("password").
|
|
Column("updated_at").
|
|
Where("user_id = ?", userID).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return s.sqlstore.WrapNotFoundErrf(err, types.ErrPasswordNotFound, "password with user id: %s does not exist", userID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) GetDomainByName(ctx context.Context, name string) (*types.StorableOrgDomain, error) {
|
|
return nil, errors.New(errors.TypeUnsupported, errors.CodeUnsupported, "not supported")
|
|
}
|