update
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
pkgcrypto "github.com/gochat/gochat/pkg/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gorm.io/driver/sqlite"
|
||||
@@ -24,7 +25,6 @@ type AgentHandlerTestSuite struct {
|
||||
suite.Suite
|
||||
db *gorm.DB
|
||||
handler *AgentHandler
|
||||
mailer *fakeProfileConfirmationMailer
|
||||
account *model.Account
|
||||
user *model.User
|
||||
}
|
||||
@@ -40,8 +40,6 @@ func (s *AgentHandlerTestSuite) SetupSuite() {
|
||||
|
||||
agentRepo := repository.NewAgentRepo(db)
|
||||
svc := service.NewAgentService(agentRepo, db)
|
||||
s.mailer = &fakeProfileConfirmationMailer{}
|
||||
svc.SetConfirmationMailer(s.mailer)
|
||||
s.handler = NewAgentHandler(svc)
|
||||
|
||||
s.account = &model.Account{Name: "test-agent-account"}
|
||||
@@ -61,7 +59,6 @@ func (s *AgentHandlerTestSuite) SetupTest() {
|
||||
// Don't delete users — we need the inviter user to persist
|
||||
// Only delete agent users (not the inviter)
|
||||
s.db.Exec("DELETE FROM users WHERE id != ?", s.user.ID)
|
||||
s.mailer.Reset()
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TearDownSuite() {
|
||||
@@ -186,10 +183,20 @@ func (s *AgentHandlerTestSuite) TestCreateAgent() {
|
||||
assert.NotContains(s.T(), data, "invited_by")
|
||||
assert.NotContains(s.T(), data, "inviter_id")
|
||||
assert.NotContains(s.T(), data, "account_user_id")
|
||||
temporaryPassword, ok := data["temporary_password"].(string)
|
||||
s.Require().True(ok)
|
||||
assert.Len(s.T(), temporaryPassword, 16)
|
||||
assert.Equal(s.T(), "no-store", w.Header().Get("Cache-Control"))
|
||||
|
||||
var membership model.AccountUser
|
||||
s.Require().NoError(s.db.Where("account_id = ? AND user_id = ?", s.account.ID, uint(data["id"].(float64))).First(&membership).Error)
|
||||
assert.Equal(s.T(), s.user.ID, membership.InvitedBy)
|
||||
|
||||
var createdUser model.User
|
||||
s.Require().NoError(s.db.First(&createdUser, uint(data["id"].(float64))).Error)
|
||||
assert.NotNil(s.T(), createdUser.ConfirmedAt)
|
||||
assert.True(s.T(), pkgcrypto.CheckPassword(temporaryPassword, createdUser.PasswordDigest))
|
||||
assert.True(s.T(), pkgcrypto.CheckPassword(temporaryPassword, createdUser.Password))
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestCreateAgentChatwootFrontendPayload() {
|
||||
@@ -218,27 +225,63 @@ func (s *AgentHandlerTestSuite) TestCreateAgentChatwootFrontendPayload() {
|
||||
assert.NotContains(s.T(), data, "data")
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestCreateAgentSendsWorkspaceInvitation() {
|
||||
req := service.CreateAgentRequest{Email: "invite-mail@test.com", Name: "Invite Mail", Role: "agent"}
|
||||
func (s *AgentHandlerTestSuite) TestCreateAgentDoesNotRequireInvitationEmail() {
|
||||
req := service.CreateAgentRequest{Email: "direct-login@test.com", Name: "Direct Login", Role: "agent"}
|
||||
w, c := s.makeRequest("POST", "/api/v1/accounts/1/agents", req, s.account.ID, s.user.ID)
|
||||
s.handler.Create(c)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code, w.Body.String())
|
||||
s.Require().Len(s.mailer.calls, 1)
|
||||
mail := s.mailer.calls[0]
|
||||
assert.Equal(s.T(), "invitation", mail.Kind)
|
||||
assert.Equal(s.T(), "invite-mail@test.com", mail.ToEmail)
|
||||
assert.Equal(s.T(), "You're invited to join test-agent-account", mail.Heading)
|
||||
assert.Equal(s.T(), "Inviter Admin invited you to join the test-agent-account workspace on Chatwoot.", mail.IntroText)
|
||||
assert.Equal(s.T(), "Accept invitation", mail.ActionText)
|
||||
assert.Contains(s.T(), mail.ActionURL, "/app/auth/password/edit?reset_password_token=")
|
||||
assert.NotEmpty(s.T(), mail.ResetPasswordToken)
|
||||
var data map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
temporaryPassword, ok := data["temporary_password"].(string)
|
||||
s.Require().True(ok)
|
||||
assert.Regexp(s.T(), `[A-Z]`, temporaryPassword)
|
||||
assert.Regexp(s.T(), `[a-z]`, temporaryPassword)
|
||||
assert.Regexp(s.T(), `[0-9]`, temporaryPassword)
|
||||
assert.Regexp(s.T(), `[!@#$%]`, temporaryPassword)
|
||||
|
||||
var invited model.User
|
||||
s.Require().NoError(s.db.Where("email = ?", "invite-mail@test.com").First(&invited).Error)
|
||||
assert.NotEmpty(s.T(), invited.ResetPasswordToken)
|
||||
assert.NotEqual(s.T(), mail.ResetPasswordToken, invited.ResetPasswordToken)
|
||||
assert.NotNil(s.T(), invited.ResetPasswordSentAt)
|
||||
var created model.User
|
||||
s.Require().NoError(s.db.Where("email = ?", "direct-login@test.com").First(&created).Error)
|
||||
assert.Empty(s.T(), created.ResetPasswordToken)
|
||||
assert.Nil(s.T(), created.ResetPasswordSentAt)
|
||||
assert.NotNil(s.T(), created.ConfirmedAt)
|
||||
assert.True(s.T(), pkgcrypto.CheckPassword(temporaryPassword, created.PasswordDigest))
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestResetPasswordReturnsNewTemporaryPassword() {
|
||||
req := service.CreateAgentRequest{Email: "reset-agent@test.com", Name: "Reset Agent", Role: "agent"}
|
||||
createResponse, createContext := s.makeRequest("POST", "/api/v1/accounts/1/agents", req, s.account.ID, s.user.ID)
|
||||
s.handler.Create(createContext)
|
||||
s.Require().Equal(http.StatusOK, createResponse.Code)
|
||||
var created map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(createResponse.Body.Bytes(), &created))
|
||||
agentID := uint(created["id"].(float64))
|
||||
initialPassword := created["temporary_password"].(string)
|
||||
|
||||
w, c := s.makeRequest("POST", fmt.Sprintf("/api/v1/accounts/1/agents/%d/reset_password", agentID), nil, s.account.ID, s.user.ID)
|
||||
s.handler.ResetPassword(c)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code, w.Body.String())
|
||||
assert.Equal(s.T(), "no-store", w.Header().Get("Cache-Control"))
|
||||
var data map[string]string
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
newPassword := data["temporary_password"]
|
||||
assert.Len(s.T(), newPassword, 16)
|
||||
assert.NotEqual(s.T(), initialPassword, newPassword)
|
||||
|
||||
var user model.User
|
||||
s.Require().NoError(s.db.First(&user, agentID).Error)
|
||||
assert.True(s.T(), pkgcrypto.CheckPassword(newPassword, user.PasswordDigest))
|
||||
assert.False(s.T(), pkgcrypto.CheckPassword(initialPassword, user.PasswordDigest))
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestResetPasswordIsScopedToAccount() {
|
||||
otherAccount := &model.Account{Name: "other-reset-account"}
|
||||
s.Require().NoError(s.db.Create(otherAccount).Error)
|
||||
|
||||
w, c := s.makeRequest("POST", fmt.Sprintf("/api/v1/accounts/%d/agents/%d/reset_password", otherAccount.ID, s.user.ID), nil, otherAccount.ID, s.user.ID)
|
||||
s.handler.ResetPassword(c)
|
||||
assert.Equal(s.T(), http.StatusNotFound, w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestCreateAgentDefaultsBlankNameFromEmail() {
|
||||
@@ -467,7 +510,12 @@ func (s *AgentHandlerTestSuite) TestBulkCreate() {
|
||||
s.handler.BulkCreate(c)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
assert.Empty(s.T(), w.Body.String())
|
||||
var data []map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
s.Require().Len(data, 3)
|
||||
for _, agent := range data {
|
||||
assert.NotEmpty(s.T(), agent["temporary_password"])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestBulkCreateValidation() {
|
||||
@@ -477,7 +525,7 @@ func (s *AgentHandlerTestSuite) TestBulkCreateValidation() {
|
||||
w, c := s.makeRequest("POST", "/api/v1/accounts/1/agents/bulk_create", req, s.account.ID, s.user.ID)
|
||||
s.handler.BulkCreate(c)
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
assert.Empty(s.T(), w.Body.String())
|
||||
assert.JSONEq(s.T(), `[]`, w.Body.String())
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestBulkCreateSkipsInvalidEmailsAndClearsOnboardingStep() {
|
||||
@@ -489,7 +537,10 @@ func (s *AgentHandlerTestSuite) TestBulkCreateSkipsInvalidEmailsAndClearsOnboard
|
||||
s.handler.BulkCreate(c)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
assert.Empty(s.T(), w.Body.String())
|
||||
var data []map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &data))
|
||||
s.Require().Len(data, 1)
|
||||
assert.NotEmpty(s.T(), data[0]["temporary_password"])
|
||||
|
||||
var validUser model.User
|
||||
s.Require().NoError(s.db.Where("email = ?", "valid-bulk@test.com").First(&validUser).Error)
|
||||
@@ -521,7 +572,11 @@ func (s *AgentHandlerTestSuite) TestBulkCreateSkipsDuplicates() {
|
||||
s.handler.BulkCreate(c2)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w2.Code)
|
||||
assert.Empty(s.T(), w2.Body.String())
|
||||
var data []map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w2.Body.Bytes(), &data))
|
||||
s.Require().Len(data, 1)
|
||||
assert.Equal(s.T(), "new@test.com", data[0]["email"])
|
||||
assert.NotEmpty(s.T(), data[0]["temporary_password"])
|
||||
}
|
||||
|
||||
func (s *AgentHandlerTestSuite) TestListAfterCreate() {
|
||||
|
||||
Reference in New Issue
Block a user