chore: build
This commit is contained in:
@@ -15,6 +15,7 @@ func (d *Database) MigrateAddTelegramColumns() {
|
||||
migrations := []string{
|
||||
`ALTER TABLE clients ADD COLUMN IF NOT EXISTS telegram_chat_id BIGINT`,
|
||||
`ALTER TABLE users ADD COLUMN IF NOT EXISTS telegram_chat_id BIGINT`,
|
||||
`ALTER TABLE clients ADD COLUMN IF NOT EXISTS two_fa_enabled BOOLEAN NOT NULL DEFAULT FALSE`,
|
||||
}
|
||||
for _, q := range migrations {
|
||||
if err := d.GDB.Exec(q).Error; err != nil {
|
||||
@@ -108,6 +109,45 @@ func (d *Database) DeleteUserTelegramChatID(username string) error {
|
||||
return d.GDB.Model(&models.User{}).Where("username = ?", username).Update("telegram_chat_id", nil).Error
|
||||
}
|
||||
|
||||
// GetAllLinkedTelegramAccounts retourne tous les comptes ayant un telegram_chat_id non-null.
|
||||
func (d *Database) GetAllLinkedTelegramAccounts() ([]struct {
|
||||
ChatID int64
|
||||
Username string
|
||||
Role string
|
||||
}, error) {
|
||||
type row struct {
|
||||
ChatID int64 `gorm:"column:telegram_chat_id"`
|
||||
Username string `gorm:"column:username"`
|
||||
Role string `gorm:"column:role"`
|
||||
}
|
||||
|
||||
var results []row
|
||||
|
||||
var clients []row
|
||||
if err := d.GDB.Raw(`SELECT telegram_chat_id, username, 'client' AS role FROM clients WHERE telegram_chat_id IS NOT NULL`).Scan(&clients).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = append(results, clients...)
|
||||
|
||||
var users []row
|
||||
if err := d.GDB.Raw(`SELECT telegram_chat_id, username, role FROM users WHERE telegram_chat_id IS NOT NULL`).Scan(&users).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = append(results, users...)
|
||||
|
||||
out := make([]struct {
|
||||
ChatID int64
|
||||
Username string
|
||||
Role string
|
||||
}, len(results))
|
||||
for i, r := range results {
|
||||
out[i].ChatID = r.ChatID
|
||||
out[i].Username = r.Username
|
||||
out[i].Role = r.Role
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetUserByTelegramChatID retrouve un utilisateur (clients + users) par chat_id
|
||||
func (d *Database) GetUserByTelegramChatID(chatID int64) (username, role string, err error) {
|
||||
var clientResult struct {
|
||||
@@ -127,3 +167,36 @@ func (d *Database) GetUserByTelegramChatID(chatID int64) (username, role string,
|
||||
|
||||
return "", "", fmt.Errorf("aucun compte lié à ce chat_id")
|
||||
}
|
||||
|
||||
// ── 2FA sessions ─────────────────────────────────────────────────────────────
|
||||
|
||||
const twoFASessionTTL = 5 * time.Minute
|
||||
|
||||
type twoFASessionData struct {
|
||||
Username string `json:"username"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func Store2FASession(sessionToken, username, code string) error {
|
||||
data, err := json.Marshal(twoFASessionData{Username: username, Code: code})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return Redis.Set(RedisCtx, "2fa:session:"+sessionToken, data, twoFASessionTTL).Err()
|
||||
}
|
||||
|
||||
// Verify2FASession valide le code et retourne le username. GETDEL = atomique (anti-replay).
|
||||
func Verify2FASession(sessionToken, code string) (string, error) {
|
||||
val, err := Redis.GetDel(RedisCtx, "2fa:session:"+sessionToken).Bytes()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("session invalide ou expirée")
|
||||
}
|
||||
var d twoFASessionData
|
||||
if err := json.Unmarshal(val, &d); err != nil {
|
||||
return "", fmt.Errorf("données corrompues")
|
||||
}
|
||||
if d.Code != code {
|
||||
return "", fmt.Errorf("code incorrect")
|
||||
}
|
||||
return d.Username, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user