feat(profile): align mfa payloads
This commit is contained in:
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/gochat/gochat/internal/auth"
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
pkgcrypto "github.com/gochat/gochat/pkg/crypto"
|
||||
"github.com/gochat/gochat/pkg/response"
|
||||
)
|
||||
|
||||
@@ -107,6 +108,11 @@ func (s *MFAHandlerTestSuite) setupRouter(userID uint) {
|
||||
mfaGroup.POST("/verify", s.handler.VerifyMFA)
|
||||
mfaGroup.POST("/disable", s.handler.DisableMFA)
|
||||
}
|
||||
r.GET("/api/v1/profile/mfa", s.handler.ProfileMFAStatus)
|
||||
r.POST("/api/v1/profile/mfa", s.handler.ProfileEnableMFA)
|
||||
r.DELETE("/api/v1/profile/mfa", s.handler.ProfileDisableMFA)
|
||||
r.POST("/api/v1/profile/mfa/verify", s.handler.ProfileVerifyMFA)
|
||||
r.POST("/api/v1/profile/mfa/backup_codes", s.handler.ProfileBackupCodes)
|
||||
|
||||
s.router = r
|
||||
}
|
||||
@@ -213,7 +219,7 @@ func generateTOTPFromKey(key []byte, timeCounter int64, cfg auth.TOTPConfig) str
|
||||
truncated := (int32(hash[offset]&0x7f) << 24) |
|
||||
(int32(hash[offset+1]&0xff) << 16) |
|
||||
(int32(hash[offset+2]&0xff) << 8) |
|
||||
(int32(hash[offset+3]&0xff))
|
||||
(int32(hash[offset+3] & 0xff))
|
||||
|
||||
// Modulo 10^digits
|
||||
mod := int32(math.Pow10(cfg.Digits))
|
||||
@@ -660,5 +666,58 @@ func (s *MFAHandlerTestSuite) TestStatus_Unauthorized_NoUserID() {
|
||||
s.Equal(response.ErrUnauthorized, respStruct.Error.Code)
|
||||
}
|
||||
|
||||
func (s *MFAHandlerTestSuite) TestProfileMFA_StatusUsesChatwootRawPayload() {
|
||||
w := s.doRequest(http.MethodGet, "/api/v1/profile/mfa", "")
|
||||
s.Equal(http.StatusOK, w.Code)
|
||||
|
||||
var payload map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &payload))
|
||||
s.Equal(true, payload["feature_available"])
|
||||
s.Equal(false, payload["enabled"])
|
||||
s.Equal(false, payload["backup_codes_generated"])
|
||||
s.NotContains(payload, "data")
|
||||
}
|
||||
|
||||
func (s *MFAHandlerTestSuite) TestProfileMFA_EnableVerifyBackupAndDisableUseFrontendPayloads() {
|
||||
passwordHash, err := pkgcrypto.HashPassword("current-password")
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.db.Model(&model.User{}).Where("id = ?", s.userID).Updates(map[string]interface{}{
|
||||
"password": passwordHash,
|
||||
"password_digest": passwordHash,
|
||||
}).Error)
|
||||
|
||||
enableRec := s.doRequest(http.MethodPost, "/api/v1/profile/mfa", "")
|
||||
s.Equal(http.StatusOK, enableRec.Code)
|
||||
var enablePayload map[string]string
|
||||
s.Require().NoError(json.Unmarshal(enableRec.Body.Bytes(), &enablePayload))
|
||||
s.NotEmpty(enablePayload["secret"])
|
||||
s.Contains(enablePayload["provisioning_url"], "otpauth://totp/")
|
||||
|
||||
code := s.generateValidTOTPCode(enablePayload["secret"])
|
||||
verifyRec := s.doRequest(http.MethodPost, "/api/v1/profile/mfa/verify", jsonBody(map[string]interface{}{"otp_code": code}))
|
||||
s.Equal(http.StatusOK, verifyRec.Code)
|
||||
var verifyPayload struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
BackupCodes []string `json:"backup_codes"`
|
||||
}
|
||||
s.Require().NoError(json.Unmarshal(verifyRec.Body.Bytes(), &verifyPayload))
|
||||
s.True(verifyPayload.Enabled)
|
||||
s.Len(verifyPayload.BackupCodes, 10)
|
||||
|
||||
backupRec := s.doRequest(http.MethodPost, "/api/v1/profile/mfa/backup_codes", jsonBody(map[string]interface{}{"otp_code": code}))
|
||||
s.Equal(http.StatusOK, backupRec.Code)
|
||||
var backupPayload struct {
|
||||
BackupCodes []string `json:"backup_codes"`
|
||||
}
|
||||
s.Require().NoError(json.Unmarshal(backupRec.Body.Bytes(), &backupPayload))
|
||||
s.Len(backupPayload.BackupCodes, 10)
|
||||
|
||||
disableRec := s.doRequest(http.MethodDelete, "/api/v1/profile/mfa", jsonBody(map[string]interface{}{"password": "current-password", "otp_code": code}))
|
||||
s.Equal(http.StatusOK, disableRec.Code)
|
||||
var disablePayload map[string]bool
|
||||
s.Require().NoError(json.Unmarshal(disableRec.Body.Bytes(), &disablePayload))
|
||||
s.False(disablePayload["enabled"])
|
||||
}
|
||||
|
||||
// Ensure unused import warning doesn't cause issues
|
||||
var _ = assert.Equal
|
||||
var _ = assert.Equal
|
||||
|
||||
Reference in New Issue
Block a user