@@ -57,11 +57,11 @@ func GetUserByUsername(db *sql.DB, uname string) (*models.User, error) {
5757
5858 // query the database for a user matching the provided username and scan the result into the user struct
5959 err := db .QueryRow (`
60- SELECT id, uname, pword, uhash, fname, lname, email, phone, role, totp_secret, totp_enabled, notify_email, notify_sms, created, updated
60+ SELECT id, uname, pword, uhash, fname, lname, email, phone, role, totp_secret, totp_salt, totp_enabled, notify_email, notify_sms, created, updated
6161 FROM kppn_users WHERE uname = ?` , uname ,
6262 ).Scan (
6363 & u .ID , & u .UName , & u .PWord , & u .UHash , & u .FName , & u .LName ,
64- & u .Email , & u .Phone , & u .Role , & u .TOTPSecret , & u .TOTPEnabled ,
64+ & u .Email , & u .Phone , & u .Role , & u .TOTPSecret , & u .TOTPSalt , & u . TOTPEnabled ,
6565 & u .NotifyEmail , & u .NotifySMS , & u .Created , & u .Updated ,
6666 )
6767 if err == sql .ErrNoRows {
@@ -84,11 +84,11 @@ func GetUserByID(db *sql.DB, id int64) (*models.User, error) {
8484
8585 // query the database for a user matching the provided ID and scan the result into the user struct
8686 err := db .QueryRow (`
87- SELECT id, uname, pword, uhash, fname, lname, email, phone, role, totp_secret, totp_enabled, notify_email, notify_sms, created, updated
87+ SELECT id, uname, pword, uhash, fname, lname, email, phone, role, totp_secret, totp_salt, totp_enabled, notify_email, notify_sms, created, updated
8888 FROM kppn_users WHERE id = ?` , id ,
8989 ).Scan (
9090 & u .ID , & u .UName , & u .PWord , & u .UHash , & u .FName , & u .LName ,
91- & u .Email , & u .Phone , & u .Role , & u .TOTPSecret , & u .TOTPEnabled ,
91+ & u .Email , & u .Phone , & u .Role , & u .TOTPSecret , & u .TOTPSalt , & u . TOTPEnabled ,
9292 & u .NotifyEmail , & u .NotifySMS , & u .Created , & u .Updated ,
9393 )
9494 if err == sql .ErrNoRows {
@@ -202,6 +202,24 @@ func SetTOTPSecret(db *sql.DB, id int64, secret string) error {
202202 return err
203203}
204204
205+ // SetTOTPSalt stores the per-user salt used for TOTP secret key derivation.
206+ func SetTOTPSalt (db * sql.DB , id int64 , salt string ) error {
207+ _ , err := db .Exec (`UPDATE kppn_users SET totp_salt=?, updated=datetime('now') WHERE id=?` , salt , id )
208+ if err != nil {
209+ logger .Error ("SetTOTPSalt: failed for user %d: %v" , id , err )
210+ }
211+ return err
212+ }
213+
214+ // UpdateTOTPSecret replaces the stored TOTP secret without touching the enabled flag.
215+ func UpdateTOTPSecret (db * sql.DB , id int64 , secret string ) error {
216+ _ , err := db .Exec (`UPDATE kppn_users SET totp_secret=?, updated=datetime('now') WHERE id=?` , secret , id )
217+ if err != nil {
218+ logger .Error ("UpdateTOTPSecret: failed for user %d: %v" , id , err )
219+ }
220+ return err
221+ }
222+
205223// EnableTOTP activates TOTP for the user (secret must already be stored).
206224func EnableTOTP (db * sql.DB , id int64 ) error {
207225 _ , err := db .Exec (`UPDATE kppn_users SET totp_enabled=1, updated=datetime('now') WHERE id=?` , id )
0 commit comments