login fix
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
type UserRepository interface {
|
||||
GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error)
|
||||
GetUserByID(uid int) (models.UserInfo, error)
|
||||
SetInitialPassword(userid int, password string) error
|
||||
Login(user models.User) (models.UserInfo, error)
|
||||
FindUserID(authname, contactno string, configid int) (int, error)
|
||||
UpdateStaff(user models.User) error
|
||||
@@ -391,3 +392,46 @@ func (r *userRepository) GetLocationStatus(locationid int) string {
|
||||
func (r *userRepository) DeleteUser(userid int) error {
|
||||
return r.db.Table("app_users").Where("userid = ?", userid).Delete(&models.User{}).Error
|
||||
}
|
||||
|
||||
// SetInitialPassword writes the first password on an account that has none.
|
||||
//
|
||||
// ── Why this is a separate call and not `UpdateStaff` ───────────────────────
|
||||
//
|
||||
// It is the one write that MUST work without a session, and that is the whole
|
||||
// difficulty. A brand-new account — `createtenantlocation` spawns branch logins
|
||||
// with an empty password — signs in, is told to set one, and at that moment has
|
||||
// no token and no way to get one. The console was doing this through
|
||||
// `PUT /users/update`, which sits behind the session guard, so the call came
|
||||
// back "a session token is required; sign in again" and the account could never
|
||||
// be used. Sign-in needs a password; setting the password needed a sign-in.
|
||||
//
|
||||
// `/users/update` could not simply be opened up: it writes whatever struct it
|
||||
// is handed, so an unauthenticated caller could edit any field of any user.
|
||||
// This can do exactly one thing, to exactly one kind of account.
|
||||
//
|
||||
// ── What makes it safe to expose ────────────────────────────────────────────
|
||||
//
|
||||
// The empty-password check IS the authorisation. An account with a password set
|
||||
// is refused, so this can never overwrite a credential — it is a setup call,
|
||||
// never a reset. There is no "forgot password" flow on this backend and this
|
||||
// must not become one by accident: a reset needs proof of identity, and nothing
|
||||
// here has any.
|
||||
//
|
||||
// The check and the write are one statement, so two callers racing cannot both
|
||||
// see an empty password and both set one. Postgres decides, not this process.
|
||||
func (r *userRepository) SetInitialPassword(userid int, password string) error {
|
||||
result := r.db.Table("app_users").
|
||||
Where("userid = ? AND (password IS NULL OR TRIM(password) = '')", userid).
|
||||
Update("password", password)
|
||||
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
// One message for "no such user" and "already has a password". They
|
||||
// must not be distinguishable, or this becomes a way to ask whether a
|
||||
// given userid exists and whether it has been set up.
|
||||
return errors.New("that account cannot have its password set here — it may already have one")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user