ResetPassword Table and all CRUD methods. (#1916)
This commit is contained in:
parent
7ce9a60c85
commit
f46487b015
@ -8,6 +8,8 @@ const (
|
||||
ActivationPath = "activationPath"
|
||||
// PasswordRecoveryPath is key for path which handles password recovery
|
||||
PasswordRecoveryPath = "passwordRecoveryPath"
|
||||
// CancelPasswordRecoveryPath is key for path which handles let us know sequence
|
||||
CancelPasswordRecoveryPath = "cancelPasswordRecoveryPath"
|
||||
// SignInPath is key for sign in server route
|
||||
SignInPath = "signInPath"
|
||||
)
|
||||
@ -26,9 +28,10 @@ func (*AccountActivationEmail) Subject() string { return "Activate your email" }
|
||||
|
||||
// ForgotPasswordEmail is mailservice template with reset password data
|
||||
type ForgotPasswordEmail struct {
|
||||
Origin string
|
||||
UserName string
|
||||
ResetLink string
|
||||
Origin string
|
||||
UserName string
|
||||
ResetLink string
|
||||
CancelPasswordRecoveryLink string
|
||||
}
|
||||
|
||||
// Template returns email template name
|
||||
|
@ -112,14 +112,15 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types
|
||||
return false, fmt.Errorf("%s is not found", email)
|
||||
}
|
||||
|
||||
recoveryToken, err := service.GeneratePasswordRecoveryToken(p.Context, user.ID, user.Email)
|
||||
recoveryToken, err := service.GeneratePasswordRecoveryToken(p.Context, user.ID)
|
||||
if err != nil {
|
||||
return false, errors.New("failed to generate password recovery token")
|
||||
}
|
||||
|
||||
rootObject := p.Info.RootValue.(map[string]interface{})
|
||||
origin := rootObject["origin"].(string)
|
||||
link := origin + rootObject[PasswordRecoveryPath].(string) + recoveryToken
|
||||
passwordRecoveryLink := origin + rootObject[PasswordRecoveryPath].(string) + recoveryToken
|
||||
cancelPasswordRecoveryLink := origin + rootObject[CancelPasswordRecoveryPath].(string) + recoveryToken
|
||||
userName := user.ShortName
|
||||
if user.ShortName == "" {
|
||||
userName = user.FullName
|
||||
@ -131,9 +132,10 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types
|
||||
p.Context,
|
||||
[]post.Address{{Address: user.Email, Name: userName}},
|
||||
&ForgotPasswordEmail{
|
||||
Origin: origin,
|
||||
ResetLink: link,
|
||||
UserName: userName,
|
||||
Origin: origin,
|
||||
ResetLink: passwordRecoveryLink,
|
||||
CancelPasswordRecoveryLink: cancelPasswordRecoveryLink,
|
||||
UserName: userName,
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
@ -502,7 +502,8 @@ func TestGraphqlQuery(t *testing.T) {
|
||||
|
||||
})
|
||||
|
||||
rootObject[consoleql.PasswordRecoveryPath] = "?activationToken="
|
||||
rootObject[consoleql.PasswordRecoveryPath] = "?token="
|
||||
rootObject[consoleql.CancelPasswordRecoveryPath] = "?token="
|
||||
query := fmt.Sprintf("query {forgotPassword(email: \"%s\")}", user.Email)
|
||||
|
||||
result := testQuery(t, query)
|
||||
|
@ -94,6 +94,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, mail
|
||||
if server.config.StaticDir != "" {
|
||||
mux.Handle("/activation/", http.HandlerFunc(server.accountActivationHandler))
|
||||
mux.Handle("/password-recovery/", http.HandlerFunc(server.passwordRecoveryHandler))
|
||||
mux.Handle("/cancel-password-recovery/", http.HandlerFunc(server.cancelPasswordRecoveryHandler))
|
||||
mux.Handle("/registrationToken/", http.HandlerFunc(server.createRegistrationTokenHandler))
|
||||
mux.Handle("/usage-report/", http.HandlerFunc(server.bucketUsageReportHandler))
|
||||
mux.Handle("/static/", http.StripPrefix("/static", fs))
|
||||
@ -251,22 +252,27 @@ func (s *Server) passwordRecoveryHandler(w http.ResponseWriter, req *http.Reques
|
||||
err := req.ParseForm()
|
||||
if err != nil {
|
||||
s.serveError(w, req)
|
||||
s.log.Debug(err.Error())
|
||||
}
|
||||
|
||||
password := req.FormValue("password")
|
||||
passwordRepeat := req.FormValue("passwordRepeat")
|
||||
if strings.Compare(password, passwordRepeat) != 0 {
|
||||
s.serveError(w, req)
|
||||
s.log.Debug(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.service.ResetPassword(context.Background(), recoveryToken, password)
|
||||
if err != nil {
|
||||
s.log.Debug(err.Error())
|
||||
s.serveError(w, req)
|
||||
}
|
||||
http.ServeFile(w, req, filepath.Join(s.config.StaticDir, "static", "resetPassword", "success.html"))
|
||||
default:
|
||||
t, err := template.ParseFiles(filepath.Join(s.config.StaticDir, "static", "resetPassword", "resetPassword.html"))
|
||||
if err != nil {
|
||||
s.log.Debug(err.Error())
|
||||
s.serveError(w, req)
|
||||
}
|
||||
|
||||
@ -277,6 +283,18 @@ func (s *Server) passwordRecoveryHandler(w http.ResponseWriter, req *http.Reques
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) cancelPasswordRecoveryHandler(w http.ResponseWriter, req *http.Request) {
|
||||
recoveryToken := req.URL.Query().Get("token")
|
||||
if len(recoveryToken) == 0 {
|
||||
http.Redirect(w, req, "https://storjlabs.atlassian.net/servicedesk/customer/portals", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// No need to check error as we anyway redirect user to support page
|
||||
_ = s.service.RevokeResetPasswordToken(context.Background(), recoveryToken)
|
||||
|
||||
http.Redirect(w, req, "https://storjlabs.atlassian.net/servicedesk/customer/portals", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) serveError(w http.ResponseWriter, req *http.Request) {
|
||||
http.ServeFile(w, req, filepath.Join(s.config.StaticDir, "static", "errors", "404.html"))
|
||||
}
|
||||
@ -305,6 +323,7 @@ func (s *Server) grapqlHandler(w http.ResponseWriter, req *http.Request) {
|
||||
rootObject["origin"] = s.config.ExternalAddress
|
||||
rootObject[consoleql.ActivationPath] = "activation/?token="
|
||||
rootObject[consoleql.PasswordRecoveryPath] = "password-recovery/?token="
|
||||
rootObject[consoleql.CancelPasswordRecoveryPath] = "cancel-password-recovery/?token="
|
||||
rootObject[consoleql.SignInPath] = "login"
|
||||
|
||||
result := graphql.Do(graphql.Params{
|
||||
|
@ -23,6 +23,8 @@ type DB interface {
|
||||
BucketUsage() accounting.BucketUsage
|
||||
// RegistrationTokens is a getter for RegistrationTokens repository
|
||||
RegistrationTokens() RegistrationTokens
|
||||
// ResetPasswordTokens is a getter for ResetPasswordTokens repository
|
||||
ResetPasswordTokens() ResetPasswordTokens
|
||||
// UsageRollups is a getter for UsageRollups repository
|
||||
UsageRollups() UsageRollups
|
||||
|
||||
|
70
satellite/console/resetpasswordtoken.go
Normal file
70
satellite/console/resetpasswordtoken.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"time"
|
||||
|
||||
"github.com/skyrings/skyring-common/tools/uuid"
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
// ResetPasswordTokens is interface for working with reset password tokens
|
||||
type ResetPasswordTokens interface {
|
||||
// Create creates new reset password token
|
||||
Create(ctx context.Context, ownerID uuid.UUID) (*ResetPasswordToken, error)
|
||||
// GetBySecret retrieves ResetPasswordToken with given secret
|
||||
GetBySecret(ctx context.Context, secret ResetPasswordSecret) (*ResetPasswordToken, error)
|
||||
// GetByOwnerID retrieves ResetPasswordToken by ownerID
|
||||
GetByOwnerID(ctx context.Context, ownerID uuid.UUID) (*ResetPasswordToken, error)
|
||||
// Delete deletes ResetPasswordToken by ResetPasswordSecret
|
||||
Delete(ctx context.Context, secret ResetPasswordSecret) error
|
||||
}
|
||||
|
||||
// ResetPasswordSecret stores secret of registration token
|
||||
type ResetPasswordSecret [32]byte
|
||||
|
||||
// ResetPasswordToken describing reset password model in the database
|
||||
type ResetPasswordToken struct {
|
||||
// Secret is PK of the table and keeps unique value for reset password token
|
||||
Secret ResetPasswordSecret
|
||||
// OwnerID stores current token owner ID
|
||||
OwnerID *uuid.UUID
|
||||
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
// NewResetPasswordSecret creates new reset password secret
|
||||
func NewResetPasswordSecret() (ResetPasswordSecret, error) {
|
||||
var b [32]byte
|
||||
|
||||
_, err := rand.Read(b[:])
|
||||
if err != nil {
|
||||
return b, errs.New("error creating registration secret")
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// String implements Stringer
|
||||
func (secret ResetPasswordSecret) String() string {
|
||||
return base64.URLEncoding.EncodeToString(secret[:])
|
||||
}
|
||||
|
||||
// ResetPasswordSecretFromBase64 creates new reset password secret from base64 string
|
||||
func ResetPasswordSecretFromBase64(s string) (ResetPasswordSecret, error) {
|
||||
var secret ResetPasswordSecret
|
||||
|
||||
b, err := base64.URLEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return secret, err
|
||||
}
|
||||
|
||||
copy(secret[:], b)
|
||||
|
||||
return secret, nil
|
||||
}
|
89
satellite/console/resetpasswordtoken_test.go
Normal file
89
satellite/console/resetpasswordtoken_test.go
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package console_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
||||
)
|
||||
|
||||
func TestNewRegistrationSecret(t *testing.T) {
|
||||
// testing constants
|
||||
const (
|
||||
// for user
|
||||
shortName = "lastName"
|
||||
email = "email@ukr.net"
|
||||
pass = "123456"
|
||||
userFullName = "name"
|
||||
)
|
||||
|
||||
satellitedbtest.Run(t, func(t *testing.T, db satellite.DB) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
users := db.Console().Users()
|
||||
rptokens := db.Console().ResetPasswordTokens()
|
||||
|
||||
var owner *console.User
|
||||
var rptoken *console.ResetPasswordToken
|
||||
|
||||
t.Run("Insert reset password token successfully", func(t *testing.T) {
|
||||
var err error
|
||||
owner, err = users.Insert(ctx, &console.User{
|
||||
FullName: userFullName,
|
||||
ShortName: shortName,
|
||||
Email: email,
|
||||
PasswordHash: []byte(pass),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, owner)
|
||||
|
||||
rptoken, err = rptokens.Create(ctx, owner.ID)
|
||||
assert.NotNil(t, rptoken)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Get reset password token successfully", func(t *testing.T) {
|
||||
tokenBySecret, err := rptokens.GetBySecret(ctx, rptoken.Secret)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, rptoken.Secret, tokenBySecret.Secret)
|
||||
assert.Equal(t, rptoken.CreatedAt, tokenBySecret.CreatedAt)
|
||||
assert.Equal(t, rptoken.OwnerID, tokenBySecret.OwnerID)
|
||||
})
|
||||
|
||||
t.Run("Get reset password token by UUID and Secret equal", func(t *testing.T) {
|
||||
tokenBySecret, err := rptokens.GetBySecret(ctx, rptoken.Secret)
|
||||
assert.NoError(t, err)
|
||||
|
||||
tokenByUUID, err := rptokens.GetByOwnerID(ctx, *rptoken.OwnerID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tokenByUUID.Secret, tokenBySecret.Secret)
|
||||
assert.Equal(t, tokenByUUID.CreatedAt, tokenBySecret.CreatedAt)
|
||||
assert.Equal(t, tokenByUUID.OwnerID, tokenBySecret.OwnerID)
|
||||
})
|
||||
|
||||
t.Run("Successful base64 encoding", func(t *testing.T) {
|
||||
base64token := rptoken.Secret.String()
|
||||
assert.NotEmpty(t, base64token)
|
||||
})
|
||||
|
||||
t.Run("Successful base64 decoding", func(t *testing.T) {
|
||||
base64token := rptoken.Secret.String()
|
||||
assert.NotEmpty(t, base64token)
|
||||
|
||||
secretFromString, err := console.ResetPasswordSecretFromBase64(base64token)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, rptoken.Secret, secretFromString)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
@ -151,16 +151,23 @@ func (s *Service) GenerateActivationToken(ctx context.Context, id uuid.UUID, ema
|
||||
}
|
||||
|
||||
// GeneratePasswordRecoveryToken - is a method for generating password recovery token
|
||||
func (s *Service) GeneratePasswordRecoveryToken(ctx context.Context, id uuid.UUID, email string) (token string, err error) {
|
||||
func (s *Service) GeneratePasswordRecoveryToken(ctx context.Context, id uuid.UUID) (token string, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
claims := &consoleauth.Claims{
|
||||
ID: id,
|
||||
Email: email,
|
||||
Expiration: time.Now().Add(time.Hour),
|
||||
resetPasswordToken, err := s.store.ResetPasswordTokens().GetByOwnerID(ctx, id)
|
||||
if err == nil {
|
||||
err := s.store.ResetPasswordTokens().Delete(ctx, resetPasswordToken.Secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return s.createToken(claims)
|
||||
resetPasswordToken, err = s.store.ResetPasswordTokens().Create(ctx, id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resetPasswordToken.Secret.String(), nil
|
||||
}
|
||||
|
||||
// ActivateAccount - is a method for activating user account after registration
|
||||
@ -211,17 +218,16 @@ func (s *Service) ActivateAccount(ctx context.Context, activationToken string) (
|
||||
func (s *Service) ResetPassword(ctx context.Context, resetPasswordToken, password string) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
token, err := consoleauth.FromBase64URLString(resetPasswordToken)
|
||||
secret, err := ResetPasswordSecretFromBase64(resetPasswordToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
token, err := s.store.ResetPasswordTokens().GetBySecret(ctx, secret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := s.authenticate(token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := s.store.Users().Get(ctx, claims.ID)
|
||||
user, err := s.store.Users().Get(ctx, *token.OwnerID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -230,7 +236,7 @@ func (s *Service) ResetPassword(ctx context.Context, resetPasswordToken, passwor
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Since(claims.Expiration) > 0 {
|
||||
if time.Since(token.CreatedAt) > tokenExpirationTime {
|
||||
return errs.New(passwordRecoveryTokenIsExpiredErrMsg)
|
||||
}
|
||||
|
||||
@ -240,7 +246,25 @@ func (s *Service) ResetPassword(ctx context.Context, resetPasswordToken, passwor
|
||||
}
|
||||
|
||||
user.PasswordHash = hash
|
||||
return s.store.Users().Update(ctx, user)
|
||||
|
||||
err = s.store.Users().Update(ctx, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.store.ResetPasswordTokens().Delete(ctx, token.Secret)
|
||||
}
|
||||
|
||||
// RevokeResetPasswordToken - is a method to revoke reset password token
|
||||
func (s *Service) RevokeResetPasswordToken(ctx context.Context, resetPasswordToken string) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
secret, err := ResetPasswordSecretFromBase64(resetPasswordToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return s.store.ResetPasswordTokens().Delete(ctx, secret)
|
||||
}
|
||||
|
||||
// Token authenticates User by credentials and returns auth token
|
||||
|
@ -51,6 +51,11 @@ func (db *ConsoleDB) RegistrationTokens() console.RegistrationTokens {
|
||||
return ®istrationTokens{db.methods}
|
||||
}
|
||||
|
||||
// ResetPasswordTokens is a getter for ResetPasswordTokens repository
|
||||
func (db *ConsoleDB) ResetPasswordTokens() console.ResetPasswordTokens {
|
||||
return &resetPasswordTokens{db.methods}
|
||||
}
|
||||
|
||||
// UsageRollups is a getter for console.UsageRollups repository
|
||||
func (db *ConsoleDB) UsageRollups() console.UsageRollups {
|
||||
return &usagerollups{db.db}
|
||||
|
@ -519,3 +519,26 @@ read one (
|
||||
where registration_token.owner_id = ?
|
||||
)
|
||||
update registration_token ( where registration_token.secret = ? )
|
||||
|
||||
//--- satellite reset password token ---//
|
||||
|
||||
model reset_password_token (
|
||||
key secret
|
||||
unique owner_id
|
||||
|
||||
field secret blob
|
||||
field owner_id blob ( updatable )
|
||||
|
||||
field created_at timestamp ( autoinsert )
|
||||
)
|
||||
|
||||
create reset_password_token ( )
|
||||
read one (
|
||||
select reset_password_token
|
||||
where reset_password_token.secret = ?
|
||||
)
|
||||
read one (
|
||||
select reset_password_token
|
||||
where reset_password_token.owner_id = ?
|
||||
)
|
||||
delete reset_password_token ( where reset_password_token.secret = ? )
|
||||
|
@ -400,6 +400,13 @@ CREATE TABLE registration_tokens (
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret bytea NOT NULL,
|
||||
owner_id bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE serial_numbers (
|
||||
id serial NOT NULL,
|
||||
serial_number bytea NOT NULL,
|
||||
@ -650,6 +657,13 @@ CREATE TABLE registration_tokens (
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret BLOB NOT NULL,
|
||||
owner_id BLOB NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE serial_numbers (
|
||||
id INTEGER NOT NULL,
|
||||
serial_number BLOB NOT NULL,
|
||||
@ -2757,6 +2771,75 @@ func (f RegistrationToken_CreatedAt_Field) value() interface{} {
|
||||
|
||||
func (RegistrationToken_CreatedAt_Field) _Column() string { return "created_at" }
|
||||
|
||||
type ResetPasswordToken struct {
|
||||
Secret []byte
|
||||
OwnerId []byte
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (ResetPasswordToken) _Table() string { return "reset_password_tokens" }
|
||||
|
||||
type ResetPasswordToken_Update_Fields struct {
|
||||
OwnerId ResetPasswordToken_OwnerId_Field
|
||||
}
|
||||
|
||||
type ResetPasswordToken_Secret_Field struct {
|
||||
_set bool
|
||||
_null bool
|
||||
_value []byte
|
||||
}
|
||||
|
||||
func ResetPasswordToken_Secret(v []byte) ResetPasswordToken_Secret_Field {
|
||||
return ResetPasswordToken_Secret_Field{_set: true, _value: v}
|
||||
}
|
||||
|
||||
func (f ResetPasswordToken_Secret_Field) value() interface{} {
|
||||
if !f._set || f._null {
|
||||
return nil
|
||||
}
|
||||
return f._value
|
||||
}
|
||||
|
||||
func (ResetPasswordToken_Secret_Field) _Column() string { return "secret" }
|
||||
|
||||
type ResetPasswordToken_OwnerId_Field struct {
|
||||
_set bool
|
||||
_null bool
|
||||
_value []byte
|
||||
}
|
||||
|
||||
func ResetPasswordToken_OwnerId(v []byte) ResetPasswordToken_OwnerId_Field {
|
||||
return ResetPasswordToken_OwnerId_Field{_set: true, _value: v}
|
||||
}
|
||||
|
||||
func (f ResetPasswordToken_OwnerId_Field) value() interface{} {
|
||||
if !f._set || f._null {
|
||||
return nil
|
||||
}
|
||||
return f._value
|
||||
}
|
||||
|
||||
func (ResetPasswordToken_OwnerId_Field) _Column() string { return "owner_id" }
|
||||
|
||||
type ResetPasswordToken_CreatedAt_Field struct {
|
||||
_set bool
|
||||
_null bool
|
||||
_value time.Time
|
||||
}
|
||||
|
||||
func ResetPasswordToken_CreatedAt(v time.Time) ResetPasswordToken_CreatedAt_Field {
|
||||
return ResetPasswordToken_CreatedAt_Field{_set: true, _value: v}
|
||||
}
|
||||
|
||||
func (f ResetPasswordToken_CreatedAt_Field) value() interface{} {
|
||||
if !f._set || f._null {
|
||||
return nil
|
||||
}
|
||||
return f._value
|
||||
}
|
||||
|
||||
func (ResetPasswordToken_CreatedAt_Field) _Column() string { return "created_at" }
|
||||
|
||||
type SerialNumber struct {
|
||||
Id int
|
||||
SerialNumber []byte
|
||||
@ -4132,6 +4215,30 @@ func (obj *postgresImpl) Create_RegistrationToken(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Create_ResetPasswordToken(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
__now := obj.db.Hooks.Now().UTC()
|
||||
__secret_val := reset_password_token_secret.value()
|
||||
__owner_id_val := reset_password_token_owner_id.value()
|
||||
__created_at_val := __now
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("INSERT INTO reset_password_tokens ( secret, owner_id, created_at ) VALUES ( ?, ?, ? ) RETURNING reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at")
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __secret_val, __owner_id_val, __created_at_val)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, __secret_val, __owner_id_val, __created_at_val).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Get_Irreparabledb_By_Segmentpath(ctx context.Context,
|
||||
irreparabledb_segmentpath Irreparabledb_Segmentpath_Field) (
|
||||
irreparabledb *Irreparabledb, err error) {
|
||||
@ -5102,6 +5209,48 @@ func (obj *postgresImpl) Get_RegistrationToken_By_OwnerId(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Get_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at FROM reset_password_tokens WHERE reset_password_tokens.secret = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_secret.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, __values...).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Get_ResetPasswordToken_By_OwnerId(ctx context.Context,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at FROM reset_password_tokens WHERE reset_password_tokens.owner_id = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_owner_id.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, __values...).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Update_Irreparabledb_By_Segmentpath(ctx context.Context,
|
||||
irreparabledb_segmentpath Irreparabledb_Segmentpath_Field,
|
||||
update Irreparabledb_Update_Fields) (
|
||||
@ -5846,6 +5995,32 @@ func (obj *postgresImpl) Delete_CertRecord_By_Id(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *postgresImpl) Delete_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
deleted bool, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("DELETE FROM reset_password_tokens WHERE reset_password_tokens.secret = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_secret.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
__res, err := obj.driver.Exec(__stmt, __values...)
|
||||
if err != nil {
|
||||
return false, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err := __res.RowsAffected()
|
||||
if err != nil {
|
||||
return false, obj.makeErr(err)
|
||||
}
|
||||
|
||||
return __count > 0, nil
|
||||
|
||||
}
|
||||
|
||||
func (impl postgresImpl) isConstraintError(err error) (
|
||||
constraint string, ok bool) {
|
||||
if e, ok := err.(*pq.Error); ok {
|
||||
@ -5924,6 +6099,16 @@ func (obj *postgresImpl) deleteAll(ctx context.Context) (count int64, err error)
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err = __res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
count += __count
|
||||
__res, err = obj.driver.Exec("DELETE FROM reset_password_tokens;")
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err = __res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
@ -6549,6 +6734,33 @@ func (obj *sqlite3Impl) Create_RegistrationToken(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Create_ResetPasswordToken(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
__now := obj.db.Hooks.Now().UTC()
|
||||
__secret_val := reset_password_token_secret.value()
|
||||
__owner_id_val := reset_password_token_owner_id.value()
|
||||
__created_at_val := __now
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("INSERT INTO reset_password_tokens ( secret, owner_id, created_at ) VALUES ( ?, ?, ? )")
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __secret_val, __owner_id_val, __created_at_val)
|
||||
|
||||
__res, err := obj.driver.Exec(__stmt, __secret_val, __owner_id_val, __created_at_val)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
__pk, err := __res.LastInsertId()
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return obj.getLastResetPasswordToken(ctx, __pk)
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Get_Irreparabledb_By_Segmentpath(ctx context.Context,
|
||||
irreparabledb_segmentpath Irreparabledb_Segmentpath_Field) (
|
||||
irreparabledb *Irreparabledb, err error) {
|
||||
@ -7519,6 +7731,48 @@ func (obj *sqlite3Impl) Get_RegistrationToken_By_OwnerId(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Get_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at FROM reset_password_tokens WHERE reset_password_tokens.secret = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_secret.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, __values...).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Get_ResetPasswordToken_By_OwnerId(ctx context.Context,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at FROM reset_password_tokens WHERE reset_password_tokens.owner_id = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_owner_id.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, __values...).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Update_Irreparabledb_By_Segmentpath(ctx context.Context,
|
||||
irreparabledb_segmentpath Irreparabledb_Segmentpath_Field,
|
||||
update Irreparabledb_Update_Fields) (
|
||||
@ -8343,6 +8597,32 @@ func (obj *sqlite3Impl) Delete_CertRecord_By_Id(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) Delete_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
deleted bool, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("DELETE FROM reset_password_tokens WHERE reset_password_tokens.secret = ?")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, reset_password_token_secret.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
__res, err := obj.driver.Exec(__stmt, __values...)
|
||||
if err != nil {
|
||||
return false, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err := __res.RowsAffected()
|
||||
if err != nil {
|
||||
return false, obj.makeErr(err)
|
||||
}
|
||||
|
||||
return __count > 0, nil
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) getLastIrreparabledb(ctx context.Context,
|
||||
pk int64) (
|
||||
irreparabledb *Irreparabledb, err error) {
|
||||
@ -8613,6 +8893,24 @@ func (obj *sqlite3Impl) getLastRegistrationToken(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (obj *sqlite3Impl) getLastResetPasswordToken(ctx context.Context,
|
||||
pk int64) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT reset_password_tokens.secret, reset_password_tokens.owner_id, reset_password_tokens.created_at FROM reset_password_tokens WHERE _rowid_ = ?")
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, pk)
|
||||
|
||||
reset_password_token = &ResetPasswordToken{}
|
||||
err = obj.driver.QueryRow(__stmt, pk).Scan(&reset_password_token.Secret, &reset_password_token.OwnerId, &reset_password_token.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return reset_password_token, nil
|
||||
|
||||
}
|
||||
|
||||
func (impl sqlite3Impl) isConstraintError(err error) (
|
||||
constraint string, ok bool) {
|
||||
if e, ok := err.(sqlite3.Error); ok {
|
||||
@ -8696,6 +8994,16 @@ func (obj *sqlite3Impl) deleteAll(ctx context.Context) (count int64, err error)
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err = __res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
count += __count
|
||||
__res, err = obj.driver.Exec("DELETE FROM reset_password_tokens;")
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
}
|
||||
|
||||
__count, err = __res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, obj.makeErr(err)
|
||||
@ -9151,6 +9459,18 @@ func (rx *Rx) Create_RegistrationToken(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func (rx *Rx) Create_ResetPasswordToken(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
var tx *Tx
|
||||
if tx, err = rx.getTx(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return tx.Create_ResetPasswordToken(ctx, reset_password_token_secret, reset_password_token_owner_id)
|
||||
|
||||
}
|
||||
|
||||
func (rx *Rx) Create_SerialNumber(ctx context.Context,
|
||||
serial_number_serial_number SerialNumber_SerialNumber_Field,
|
||||
serial_number_bucket_id SerialNumber_BucketId_Field,
|
||||
@ -9285,6 +9605,16 @@ func (rx *Rx) Delete_Project_By_Id(ctx context.Context,
|
||||
return tx.Delete_Project_By_Id(ctx, project_id)
|
||||
}
|
||||
|
||||
func (rx *Rx) Delete_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
deleted bool, err error) {
|
||||
var tx *Tx
|
||||
if tx, err = rx.getTx(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return tx.Delete_ResetPasswordToken_By_Secret(ctx, reset_password_token_secret)
|
||||
}
|
||||
|
||||
func (rx *Rx) Delete_SerialNumber_By_ExpiresAt_LessOrEqual(ctx context.Context,
|
||||
serial_number_expires_at_less_or_equal SerialNumber_ExpiresAt_Field) (
|
||||
count int64, err error) {
|
||||
@ -9471,6 +9801,26 @@ func (rx *Rx) Get_RegistrationToken_By_Secret(ctx context.Context,
|
||||
return tx.Get_RegistrationToken_By_Secret(ctx, registration_token_secret)
|
||||
}
|
||||
|
||||
func (rx *Rx) Get_ResetPasswordToken_By_OwnerId(ctx context.Context,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
var tx *Tx
|
||||
if tx, err = rx.getTx(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return tx.Get_ResetPasswordToken_By_OwnerId(ctx, reset_password_token_owner_id)
|
||||
}
|
||||
|
||||
func (rx *Rx) Get_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error) {
|
||||
var tx *Tx
|
||||
if tx, err = rx.getTx(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return tx.Get_ResetPasswordToken_By_Secret(ctx, reset_password_token_secret)
|
||||
}
|
||||
|
||||
func (rx *Rx) Get_StoragenodeStorageTally_By_Id(ctx context.Context,
|
||||
storagenode_storage_tally_id StoragenodeStorageTally_Id_Field) (
|
||||
storagenode_storage_tally *StoragenodeStorageTally, err error) {
|
||||
@ -9794,6 +10144,11 @@ type Methods interface {
|
||||
optional RegistrationToken_Create_Fields) (
|
||||
registration_token *RegistrationToken, err error)
|
||||
|
||||
Create_ResetPasswordToken(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error)
|
||||
|
||||
Create_SerialNumber(ctx context.Context,
|
||||
serial_number_serial_number SerialNumber_SerialNumber_Field,
|
||||
serial_number_bucket_id SerialNumber_BucketId_Field,
|
||||
@ -9852,6 +10207,10 @@ type Methods interface {
|
||||
project_id Project_Id_Field) (
|
||||
deleted bool, err error)
|
||||
|
||||
Delete_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
deleted bool, err error)
|
||||
|
||||
Delete_SerialNumber_By_ExpiresAt_LessOrEqual(ctx context.Context,
|
||||
serial_number_expires_at_less_or_equal SerialNumber_ExpiresAt_Field) (
|
||||
count int64, err error)
|
||||
@ -9929,6 +10288,14 @@ type Methods interface {
|
||||
registration_token_secret RegistrationToken_Secret_Field) (
|
||||
registration_token *RegistrationToken, err error)
|
||||
|
||||
Get_ResetPasswordToken_By_OwnerId(ctx context.Context,
|
||||
reset_password_token_owner_id ResetPasswordToken_OwnerId_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error)
|
||||
|
||||
Get_ResetPasswordToken_By_Secret(ctx context.Context,
|
||||
reset_password_token_secret ResetPasswordToken_Secret_Field) (
|
||||
reset_password_token *ResetPasswordToken, err error)
|
||||
|
||||
Get_StoragenodeStorageTally_By_Id(ctx context.Context,
|
||||
storagenode_storage_tally_id StoragenodeStorageTally_Id_Field) (
|
||||
storagenode_storage_tally *StoragenodeStorageTally, err error)
|
||||
|
@ -128,6 +128,13 @@ CREATE TABLE registration_tokens (
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret bytea NOT NULL,
|
||||
owner_id bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE serial_numbers (
|
||||
id serial NOT NULL,
|
||||
serial_number bytea NOT NULL,
|
||||
|
@ -128,6 +128,13 @@ CREATE TABLE registration_tokens (
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret BLOB NOT NULL,
|
||||
owner_id BLOB NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE serial_numbers (
|
||||
id INTEGER NOT NULL,
|
||||
serial_number BLOB NOT NULL,
|
||||
|
@ -361,6 +361,47 @@ func (m *lockedRegistrationTokens) UpdateOwner(ctx context.Context, secret conso
|
||||
return m.db.UpdateOwner(ctx, secret, ownerID)
|
||||
}
|
||||
|
||||
// ResetPasswordTokens is a getter for ResetPasswordTokens repository
|
||||
func (m *lockedConsole) ResetPasswordTokens() console.ResetPasswordTokens {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedResetPasswordTokens{m.Locker, m.db.ResetPasswordTokens()}
|
||||
}
|
||||
|
||||
// lockedResetPasswordTokens implements locking wrapper for console.ResetPasswordTokens
|
||||
type lockedResetPasswordTokens struct {
|
||||
sync.Locker
|
||||
db console.ResetPasswordTokens
|
||||
}
|
||||
|
||||
// Create creates new reset password token
|
||||
func (m *lockedResetPasswordTokens) Create(ctx context.Context, ownerID uuid.UUID) (*console.ResetPasswordToken, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Create(ctx, ownerID)
|
||||
}
|
||||
|
||||
// Delete deletes ResetPasswordToken by ResetPasswordSecret
|
||||
func (m *lockedResetPasswordTokens) Delete(ctx context.Context, secret console.ResetPasswordSecret) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Delete(ctx, secret)
|
||||
}
|
||||
|
||||
// GetByOwnerID retrieves ResetPasswordToken by ownerID
|
||||
func (m *lockedResetPasswordTokens) GetByOwnerID(ctx context.Context, ownerID uuid.UUID) (*console.ResetPasswordToken, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetByOwnerID(ctx, ownerID)
|
||||
}
|
||||
|
||||
// GetBySecret retrieves ResetPasswordToken with given secret
|
||||
func (m *lockedResetPasswordTokens) GetBySecret(ctx context.Context, secret console.ResetPasswordSecret) (*console.ResetPasswordToken, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetBySecret(ctx, secret)
|
||||
}
|
||||
|
||||
// UsageRollups is a getter for UsageRollups repository
|
||||
func (m *lockedConsole) UsageRollups() console.UsageRollups {
|
||||
m.Lock()
|
||||
|
@ -620,6 +620,19 @@ func (db *DB) PostgresMigration() *migrate.Migration {
|
||||
`ALTER TABLE storagenode_storage_tallies DROP COLUMN created_at`,
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "Added new table to store reset password tokens",
|
||||
Version: 19,
|
||||
Action: migrate.SQL{`
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret bytea NOT NULL,
|
||||
owner_id bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
101
satellite/satellitedb/resetpasstokens.go
Normal file
101
satellite/satellitedb/resetpasstokens.go
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package satellitedb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/skyrings/skyring-common/tools/uuid"
|
||||
|
||||
"storj.io/storj/satellite/console"
|
||||
dbx "storj.io/storj/satellite/satellitedb/dbx"
|
||||
)
|
||||
|
||||
type resetPasswordTokens struct {
|
||||
db dbx.Methods
|
||||
}
|
||||
|
||||
// Create creates new reset password token
|
||||
func (rpt *resetPasswordTokens) Create(ctx context.Context, ownerID uuid.UUID) (*console.ResetPasswordToken, error) {
|
||||
secret, err := console.NewResetPasswordSecret()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resToken, err := rpt.db.Create_ResetPasswordToken(
|
||||
ctx,
|
||||
dbx.ResetPasswordToken_Secret(secret[:]),
|
||||
dbx.ResetPasswordToken_OwnerId(ownerID[:]),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resetPasswordTokenFromDBX(resToken)
|
||||
}
|
||||
|
||||
// GetBySecret retrieves ResetPasswordToken with given Secret
|
||||
func (rpt *resetPasswordTokens) GetBySecret(ctx context.Context, secret console.ResetPasswordSecret) (*console.ResetPasswordToken, error) {
|
||||
resToken, err := rpt.db.Get_ResetPasswordToken_By_Secret(
|
||||
ctx,
|
||||
dbx.ResetPasswordToken_Secret(secret[:]),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resetPasswordTokenFromDBX(resToken)
|
||||
}
|
||||
|
||||
// GetByOwnerID retrieves ResetPasswordToken by ownerID
|
||||
func (rpt *resetPasswordTokens) GetByOwnerID(ctx context.Context, ownerID uuid.UUID) (*console.ResetPasswordToken, error) {
|
||||
resToken, err := rpt.db.Get_ResetPasswordToken_By_OwnerId(
|
||||
ctx,
|
||||
dbx.ResetPasswordToken_OwnerId(ownerID[:]),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resetPasswordTokenFromDBX(resToken)
|
||||
}
|
||||
|
||||
// Delete deletes ResetPasswordToken by ResetPasswordSecret
|
||||
func (rpt *resetPasswordTokens) Delete(ctx context.Context, secret console.ResetPasswordSecret) error {
|
||||
_, err := rpt.db.Delete_ResetPasswordToken_By_Secret(
|
||||
ctx,
|
||||
dbx.ResetPasswordToken_Secret(secret[:]),
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// resetPasswordTokenFromDBX is used for creating ResetPasswordToken entity from autogenerated dbx.ResetPasswordToken struct
|
||||
func resetPasswordTokenFromDBX(resetToken *dbx.ResetPasswordToken) (*console.ResetPasswordToken, error) {
|
||||
if resetToken == nil {
|
||||
return nil, errors.New("token parameter is nil")
|
||||
}
|
||||
|
||||
var secret [32]byte
|
||||
|
||||
copy(secret[:], resetToken.Secret)
|
||||
|
||||
result := &console.ResetPasswordToken{
|
||||
Secret: secret,
|
||||
OwnerID: nil,
|
||||
CreatedAt: resetToken.CreatedAt,
|
||||
}
|
||||
|
||||
if resetToken.OwnerId != nil {
|
||||
ownerID, err := bytesToUUID(resetToken.OwnerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result.OwnerID = &ownerID
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
242
satellite/satellitedb/testdata/postgres.v19.sql
vendored
Normal file
242
satellite/satellitedb/testdata/postgres.v19.sql
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
-- Copied from the corresponding version of dbx generated schema
|
||||
CREATE TABLE accounting_rollups (
|
||||
id bigserial NOT NULL,
|
||||
node_id bytea NOT NULL,
|
||||
start_time timestamp with time zone NOT NULL,
|
||||
put_total bigint NOT NULL,
|
||||
get_total bigint NOT NULL,
|
||||
get_audit_total bigint NOT NULL,
|
||||
get_repair_total bigint NOT NULL,
|
||||
put_repair_total bigint NOT NULL,
|
||||
at_rest_total double precision NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE accounting_timestamps (
|
||||
name text NOT NULL,
|
||||
value timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( name )
|
||||
);
|
||||
CREATE TABLE bucket_bandwidth_rollups (
|
||||
bucket_name bytea NOT NULL,
|
||||
project_id bytea NOT NULL,
|
||||
interval_start timestamp NOT NULL,
|
||||
interval_seconds integer NOT NULL,
|
||||
action integer NOT NULL,
|
||||
inline bigint NOT NULL,
|
||||
allocated bigint NOT NULL,
|
||||
settled bigint NOT NULL,
|
||||
PRIMARY KEY ( bucket_name, project_id, interval_start, action )
|
||||
);
|
||||
CREATE TABLE bucket_storage_tallies (
|
||||
bucket_name bytea NOT NULL,
|
||||
project_id bytea NOT NULL,
|
||||
interval_start timestamp NOT NULL,
|
||||
inline bigint NOT NULL,
|
||||
remote bigint NOT NULL,
|
||||
remote_segments_count integer NOT NULL,
|
||||
inline_segments_count integer NOT NULL,
|
||||
object_count integer NOT NULL,
|
||||
metadata_size bigint NOT NULL,
|
||||
PRIMARY KEY ( bucket_name, project_id, interval_start )
|
||||
);
|
||||
CREATE TABLE bucket_usages (
|
||||
id bytea NOT NULL,
|
||||
bucket_id bytea NOT NULL,
|
||||
rollup_end_time timestamp with time zone NOT NULL,
|
||||
remote_stored_data bigint NOT NULL,
|
||||
inline_stored_data bigint NOT NULL,
|
||||
remote_segments integer NOT NULL,
|
||||
inline_segments integer NOT NULL,
|
||||
objects integer NOT NULL,
|
||||
metadata_size bigint NOT NULL,
|
||||
repair_egress bigint NOT NULL,
|
||||
get_egress bigint NOT NULL,
|
||||
audit_egress bigint NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE bwagreements (
|
||||
serialnum text NOT NULL,
|
||||
storage_node_id bytea NOT NULL,
|
||||
uplink_id bytea NOT NULL,
|
||||
action bigint NOT NULL,
|
||||
total bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
expires_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( serialnum )
|
||||
);
|
||||
CREATE TABLE certRecords (
|
||||
publickey bytea NOT NULL,
|
||||
id bytea NOT NULL,
|
||||
update_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE injuredsegments (
|
||||
path text NOT NULL,
|
||||
data bytea NOT NULL,
|
||||
attempted timestamp,
|
||||
PRIMARY KEY ( path )
|
||||
);
|
||||
CREATE TABLE irreparabledbs (
|
||||
segmentpath bytea NOT NULL,
|
||||
segmentdetail bytea NOT NULL,
|
||||
pieces_lost_count bigint NOT NULL,
|
||||
seg_damaged_unix_sec bigint NOT NULL,
|
||||
repair_attempt_count bigint NOT NULL,
|
||||
PRIMARY KEY ( segmentpath )
|
||||
);
|
||||
CREATE TABLE nodes (
|
||||
id bytea NOT NULL,
|
||||
address text NOT NULL,
|
||||
protocol integer NOT NULL,
|
||||
type integer NOT NULL,
|
||||
email text NOT NULL,
|
||||
wallet text NOT NULL,
|
||||
free_bandwidth bigint NOT NULL,
|
||||
free_disk bigint NOT NULL,
|
||||
major bigint NOT NULL,
|
||||
minor bigint NOT NULL,
|
||||
patch bigint NOT NULL,
|
||||
hash text NOT NULL,
|
||||
timestamp timestamp with time zone NOT NULL,
|
||||
release boolean NOT NULL,
|
||||
latency_90 bigint NOT NULL,
|
||||
audit_success_count bigint NOT NULL,
|
||||
total_audit_count bigint NOT NULL,
|
||||
audit_success_ratio double precision NOT NULL,
|
||||
uptime_success_count bigint NOT NULL,
|
||||
total_uptime_count bigint NOT NULL,
|
||||
uptime_ratio double precision NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
last_contact_success timestamp with time zone NOT NULL,
|
||||
last_contact_failure timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE projects (
|
||||
id bytea NOT NULL,
|
||||
name text NOT NULL,
|
||||
description text NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE registration_tokens (
|
||||
secret bytea NOT NULL,
|
||||
owner_id bytea,
|
||||
project_limit integer NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE TABLE serial_numbers (
|
||||
id serial NOT NULL,
|
||||
serial_number bytea NOT NULL,
|
||||
bucket_id bytea NOT NULL,
|
||||
expires_at timestamp NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE storagenode_bandwidth_rollups (
|
||||
storagenode_id bytea NOT NULL,
|
||||
interval_start timestamp NOT NULL,
|
||||
interval_seconds integer NOT NULL,
|
||||
action integer NOT NULL,
|
||||
allocated bigint NOT NULL,
|
||||
settled bigint NOT NULL,
|
||||
PRIMARY KEY ( storagenode_id, interval_start, action )
|
||||
);
|
||||
CREATE TABLE storagenode_storage_tallies (
|
||||
id bigserial NOT NULL,
|
||||
node_id bytea NOT NULL,
|
||||
interval_end_time timestamp with time zone NOT NULL,
|
||||
data_total double precision NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE users (
|
||||
id bytea NOT NULL,
|
||||
full_name text NOT NULL,
|
||||
short_name text,
|
||||
email text NOT NULL,
|
||||
password_hash bytea NOT NULL,
|
||||
status integer NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( id )
|
||||
);
|
||||
CREATE TABLE api_keys (
|
||||
id bytea NOT NULL,
|
||||
project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE,
|
||||
key bytea NOT NULL,
|
||||
name text NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( id ),
|
||||
UNIQUE ( key ),
|
||||
UNIQUE ( name, project_id )
|
||||
);
|
||||
CREATE TABLE project_members (
|
||||
member_id bytea NOT NULL REFERENCES users( id ) ON DELETE CASCADE,
|
||||
project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( member_id, project_id )
|
||||
);
|
||||
CREATE TABLE used_serials (
|
||||
serial_number_id integer NOT NULL REFERENCES serial_numbers( id ) ON DELETE CASCADE,
|
||||
storage_node_id bytea NOT NULL,
|
||||
PRIMARY KEY ( serial_number_id, storage_node_id )
|
||||
);
|
||||
CREATE TABLE reset_password_tokens (
|
||||
secret bytea NOT NULL,
|
||||
owner_id bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ( secret ),
|
||||
UNIQUE ( owner_id )
|
||||
);
|
||||
CREATE INDEX bucket_name_project_id_interval_start_interval_seconds ON bucket_bandwidth_rollups ( bucket_name, project_id, interval_start, interval_seconds );
|
||||
CREATE UNIQUE INDEX bucket_id_rollup ON bucket_usages ( bucket_id, rollup_end_time );
|
||||
CREATE UNIQUE INDEX serial_number ON serial_numbers ( serial_number );
|
||||
CREATE INDEX serial_numbers_expires_at_index ON serial_numbers ( expires_at );
|
||||
CREATE INDEX storagenode_id_interval_start_interval_seconds ON storagenode_bandwidth_rollups ( storagenode_id, interval_start, interval_seconds );
|
||||
|
||||
---
|
||||
|
||||
INSERT INTO "accounting_rollups"("id", "node_id", "start_time", "put_total", "get_total", "get_audit_total", "get_repair_total", "put_repair_total", "at_rest_total") VALUES (1, E'\\367M\\177\\251]t/\\022\\256\\214\\265\\025\\224\\204:\\217\\212\\0102<\\321\\374\\020&\\271Qc\\325\\261\\354\\246\\233'::bytea, '2019-02-09 00:00:00+00', 1000, 2000, 3000, 4000, 0, 5000);
|
||||
|
||||
INSERT INTO "accounting_timestamps" VALUES ('LastAtRestTally', '0001-01-01 00:00:00+00');
|
||||
INSERT INTO "accounting_timestamps" VALUES ('LastRollup', '0001-01-01 00:00:00+00');
|
||||
INSERT INTO "accounting_timestamps" VALUES ('LastBandwidthTally', '0001-01-01 00:00:00+00');
|
||||
|
||||
INSERT INTO "nodes"("id", "address", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure") VALUES (E'\\153\\313\\233\\074\\327\\177\\136\\070\\346\\001', '127.0.0.1:55516', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 5, 0, 0, 5, 0, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch');
|
||||
INSERT INTO "nodes"("id", "address", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure") VALUES (E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n', '127.0.0.1:55518', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 0, 1, 3, 3, 1, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch');
|
||||
INSERT INTO "nodes"("id", "address", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure") VALUES (E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014', '127.0.0.1:55517', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 0, 1, 0, 0, 1, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch');
|
||||
|
||||
|
||||
INSERT INTO "projects"("id", "name", "description", "created_at") VALUES (E'\\022\\217/\\014\\376!K\\023\\276\\031\\311}m\\236\\205\\300'::bytea, 'ProjectName', 'projects description', '2019-02-14 08:28:24.254934+00');
|
||||
INSERT INTO "api_keys"("id", "project_id", "key", "name", "created_at") VALUES (E'\\334/\\302;\\225\\355O\\323\\276f\\247\\354/6\\241\\033'::bytea, E'\\022\\217/\\014\\376!K\\023\\276\\031\\311}m\\236\\205\\300'::bytea, E'\\000]\\326N \\343\\270L\\327\\027\\337\\242\\240\\322mOl\\0318\\251.P I'::bytea, 'key 2', '2019-02-14 08:28:24.267934+00');
|
||||
|
||||
INSERT INTO "users"("id", "full_name", "short_name", "email", "password_hash", "status", "created_at") VALUES (E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, 'Noahson', 'William', '1email1@ukr.net', E'some_readable_hash'::bytea, 1, '2019-02-14 08:28:24.614594+00');
|
||||
INSERT INTO "projects"("id", "name", "description", "created_at") VALUES (E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea, 'projName1', 'Test project 1', '2019-02-14 08:28:24.636949+00');
|
||||
INSERT INTO "project_members"("member_id", "project_id", "created_at") VALUES (E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea, '2019-02-14 08:28:24.677953+00');
|
||||
|
||||
INSERT INTO "bwagreements"("serialnum", "storage_node_id", "action", "total", "created_at", "expires_at", "uplink_id") VALUES ('8fc0ceaa-984c-4d52-bcf4-b5429e1e35e812FpiifDbcJkePa12jxjDEutKrfLmwzT7sz2jfVwpYqgtM8B74c', E'\\245Z[/\\333\\022\\011\\001\\036\\003\\204\\005\\032.\\206\\333E\\261\\342\\227=y,}aRaH6\\240\\370\\000'::bytea, 1, 666, '2019-02-14 15:09:54.420181+00', '2019-02-14 16:09:54+00', E'\\253Z+\\374eFm\\245$\\036\\206\\335\\247\\263\\350x\\\\\\304+\\364\\343\\364+\\276fIJQ\\361\\014\\232\\000'::bytea);
|
||||
INSERT INTO "irreparabledbs" ("segmentpath", "segmentdetail", "pieces_lost_count", "seg_damaged_unix_sec", "repair_attempt_count") VALUES ('\x49616d5365676d656e746b6579696e666f30', '\x49616d5365676d656e7464657461696c696e666f30', 10, 1550159554, 10);
|
||||
|
||||
INSERT INTO "injuredsegments" ("path", "data") VALUES ('0', '\x0a0130120100');
|
||||
INSERT INTO "injuredsegments" ("path", "data") VALUES ('here''s/a/great/path', '\x0a136865726527732f612f67726561742f70617468120a0102030405060708090a');
|
||||
INSERT INTO "injuredsegments" ("path", "data") VALUES ('yet/another/cool/path', '\x0a157965742f616e6f746865722f636f6f6c2f70617468120a0102030405060708090a');
|
||||
INSERT INTO "injuredsegments" ("path", "data") VALUES ('so/many/iconic/paths/to/choose/from', '\x0a23736f2f6d616e792f69636f6e69632f70617468732f746f2f63686f6f73652f66726f6d120a0102030405060708090a');
|
||||
|
||||
INSERT INTO "certrecords" VALUES (E'0Y0\\023\\006\\007*\\206H\\316=\\002\\001\\006\\010*\\206H\\316=\\003\\001\\007\\003B\\000\\004\\360\\267\\227\\377\\253u\\222\\337Y\\324C:GQ\\010\\277v\\010\\315D\\271\\333\\337.\\203\\023=C\\343\\014T%6\\027\\362?\\214\\326\\017U\\334\\000\\260\\224\\260J\\221\\304\\331F\\304\\221\\236zF,\\325\\326l\\215\\306\\365\\200\\022', E'L\\301|\\200\\247}F|1\\320\\232\\037n\\335\\241\\206\\244\\242\\207\\204.\\253\\357\\326\\352\\033Dt\\202`\\022\\325', '2019-02-14 08:07:31.335028+00');
|
||||
|
||||
INSERT INTO "bucket_usages" ("id", "bucket_id", "rollup_end_time", "remote_stored_data", "inline_stored_data", "remote_segments", "inline_segments", "objects", "metadata_size", "repair_egress", "get_egress", "audit_egress") VALUES (E'\\153\\313\\233\\074\\327\\177\\136\\070\\346\\001",'::bytea, E'\\366\\146\\032\\321\\316\\161\\070\\133\\302\\271",'::bytea, '2019-03-06 08:28:24.677953+00', 10, 11, 12, 13, 14, 15, 16, 17, 18);
|
||||
|
||||
INSERT INTO "registration_tokens" ("secret", "owner_id", "project_limit", "created_at") VALUES (E'\\070\\127\\144\\013\\332\\344\\102\\376\\306\\056\\303\\130\\106\\132\\321\\276\\321\\274\\170\\264\\054\\333\\221\\116\\154\\221\\335\\070\\220\\146\\344\\216'::bytea, null, 1, '2019-02-14 08:28:24.677953+00');
|
||||
|
||||
INSERT INTO "serial_numbers" ("id", "serial_number", "bucket_id", "expires_at") VALUES (1, E'0123456701234567'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014/testbucket'::bytea, '2019-03-06 08:28:24.677953+00');
|
||||
INSERT INTO "used_serials" ("serial_number_id", "storage_node_id") VALUES (1, E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n');
|
||||
|
||||
INSERT INTO "storagenode_bandwidth_rollups" ("storagenode_id", "interval_start", "interval_seconds", "action", "allocated", "settled") VALUES (E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n', '2019-03-06 08:00:00.000000+00', 3600, 1, 1024, 2024);
|
||||
INSERT INTO "storagenode_storage_tallies" VALUES (1, E'\\3510\\323\\225"~\\036<\\342\\330m\\0253Jhr\\246\\233K\\246#\\2303\\351\\256\\275j\\212UM\\362\\207', '2019-02-14 08:16:57.812849+00', 1000);
|
||||
|
||||
INSERT INTO "bucket_bandwidth_rollups" ("bucket_name", "project_id", "interval_start", "interval_seconds", "action", "inline", "allocated", "settled") VALUES (E'testbucket'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea,'2019-03-06 08:00:00.000000+00', 3600, 1, 1024, 2024, 3024);
|
||||
INSERT INTO "bucket_storage_tallies" ("bucket_name", "project_id", "interval_start", "inline", "remote", "remote_segments_count", "inline_segments_count", "object_count", "metadata_size") VALUES (E'testbucket'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea,'2019-03-06 08:00:00.000000+00', 4024, 5024, 0, 0, 0, 0);
|
||||
|
||||
-- NEW DATA --
|
||||
|
||||
INSERT INTO "reset_password_tokens" ("secret", "owner_id", "created_at") VALUES (E'\\070\\127\\144\\013\\332\\344\\102\\376\\306\\056\\303\\130\\106\\132\\321\\276\\321\\274\\170\\264\\054\\333\\221\\116\\154\\221\\335\\070\\220\\146\\344\\216'::bytea, E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, '2019-05-08 08:28:24.677953+00');
|
@ -532,7 +532,8 @@ To reset your password, click the following link and follow the instructions. &#
|
||||
<div style="mso-line-height-rule: exactly;mso-text-raise: 4px;">
|
||||
<p class="size-16" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 16px;line-height: 24px;" lang="x-size-16"><span class="font-montserrat">Didn’t request this change?
<br /></span></p>
|
||||
<p class="size-16" style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 16px;line-height: 24px;" lang="x-size-16"><span class="font-montserrat">If you didn’t request a new password
|
||||
<a href="mailto:support@storj.io" style="color: #2683ff; text-decoration: none; font-weight: bold">let us know</a><br /></span></p>
|
||||
<a href="{{ .CancelPasswordRecoveryLink }}" style="color: #2683ff; text-decoration: none; font-weight: bold">let us know</a><br /></span></p>
|
||||
<p style="Margin-top: 0;Margin-bottom: 0;font-family: montserrat,dejavu sans,verdana,sans-serif;font-size: 12px;line-height: 24px;" lang="x-size-16"><span class="font-montserrat">Please Note: After clicking on «Let us Know» we will automatically deactivate this reset password link and redirect you to our Support Desk.
<br /></span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
66
web/satellite/static/resetPassword/success.css
Normal file
66
web/satellite/static/resetPassword/success.css
Normal file
@ -0,0 +1,66 @@
|
||||
/*Copyright (C) 2019 Storj Labs, Inc.*/
|
||||
/*See LICENSE for copying information.*/
|
||||
|
||||
.container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.container__title {
|
||||
font-family: 'font', sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
}
|
||||
|
||||
.container__info {
|
||||
width: 566px;
|
||||
text-align: center;
|
||||
font-family: 'font', sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.container__button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #2683FF;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
width: 216px;
|
||||
height: 48px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.container__button p {
|
||||
font-family: 'font', sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.container__button:hover {
|
||||
box-shadow: 0px 4px 20px rgba(35, 121, 236, 0.4);
|
||||
}
|
34
web/satellite/static/resetPassword/success.html
Normal file
34
web/satellite/static/resetPassword/success.html
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user