141 lines
6.3 KiB
Go
141 lines
6.3 KiB
Go
package repository
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/wmms/wmms/internal/model"
|
|
"github.com/wmms/wmms/pkg/database"
|
|
)
|
|
|
|
func TestUserOrganizationReplacement(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
ids []int64
|
|
def string
|
|
active int
|
|
valid bool
|
|
}{
|
|
{"deduplicates", []int64{2, 2}, "2", 1, true},
|
|
{"disabled", []int64{2}, "2", 0, false},
|
|
{"missing", []int64{9}, "9", 0, false},
|
|
{"default outside set", []int64{2}, "3", 1, false},
|
|
{"nonempty without default", []int64{2}, "null", 1, false},
|
|
{"invalid id", []int64{-1}, "null", 0, false},
|
|
{"revoke all", []int64{}, "null", 0, true},
|
|
{"empty with default", []int64{}, "2", 0, false},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
db, mock, _ := sqlmock.New()
|
|
defer db.Close()
|
|
mock.ExpectBegin()
|
|
tx, _ := db.Begin()
|
|
if tc.name != "invalid id" {
|
|
mock.ExpectQuery("SELECT organization_id, is_default FROM user_organizations").WithArgs(int64(7)).WillReturnRows(sqlmock.NewRows([]string{"organization_id", "is_default"}).AddRow(1, true))
|
|
mock.ExpectQuery("SELECT EXISTS").WithArgs(int64(7)).WillReturnRows(sqlmock.NewRows([]string{"admin"}).AddRow(false))
|
|
if len(tc.ids) > 0 && tc.name != "default outside set" && tc.name != "nonempty without default" {
|
|
mock.ExpectQuery("SELECT id, status FROM organizations").WithArgs(tc.ids[0]).WillReturnRows(func() *sqlmock.Rows {
|
|
rows := sqlmock.NewRows([]string{"id", "status"})
|
|
if tc.active > 0 {
|
|
rows.AddRow(tc.ids[0], "active")
|
|
}
|
|
return rows
|
|
}())
|
|
}
|
|
}
|
|
if tc.valid {
|
|
mock.ExpectExec("DELETE FROM user_organizations").WithArgs(int64(7)).WillReturnResult(sqlmock.NewResult(0, 1))
|
|
if len(tc.ids) > 0 {
|
|
mock.ExpectExec("INSERT INTO user_organizations").WithArgs(int64(7), int64(2), true).WillReturnResult(sqlmock.NewResult(0, 1))
|
|
}
|
|
mock.ExpectExec("INSERT INTO organization_audit_logs").WithArgs(int64(99), nil, "organization_access_changed", sqlmock.AnyArg(), sqlmock.AnyArg()).WillReturnResult(sqlmock.NewResult(1, 1))
|
|
}
|
|
err := replaceUserOrganizationsTx(tx, 7, model.UserOrganizationInput{OrganizationIDs: &tc.ids, DefaultOrganizationID: json.RawMessage(tc.def), ActorUserID: 99}, false)
|
|
if tc.valid && err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !tc.valid && !errors.Is(err, ErrInvalidOrganizations) {
|
|
t.Fatalf("want invalid organizations, got %v", err)
|
|
}
|
|
mock.ExpectRollback()
|
|
_ = tx.Rollback()
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserOrganizationOmittedPreservesAccess(t *testing.T) {
|
|
db, mock, _ := sqlmock.New()
|
|
defer db.Close()
|
|
mock.ExpectBegin()
|
|
tx, _ := db.Begin()
|
|
if err := replaceUserOrganizationsTx(tx, 7, model.UserOrganizationInput{ActorUserID: 99}, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
mock.ExpectRollback()
|
|
_ = tx.Rollback()
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestUserOrganizationDefaultChangeAuditsOriginalDefault(t *testing.T) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
mock.ExpectBegin()
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
mock.ExpectQuery("SELECT organization_id, is_default FROM user_organizations").WithArgs(int64(7)).WillReturnRows(sqlmock.NewRows([]string{"organization_id", "is_default"}).AddRow(1, false).AddRow(2, true))
|
|
mock.ExpectQuery("SELECT EXISTS").WithArgs(int64(7)).WillReturnRows(sqlmock.NewRows([]string{"admin"}).AddRow(false))
|
|
mock.ExpectQuery("SELECT id, status FROM organizations").WithArgs(int64(1), int64(2)).WillReturnRows(sqlmock.NewRows([]string{"id", "status"}).AddRow(1, "active").AddRow(2, "active"))
|
|
mock.ExpectExec("DELETE FROM user_organizations").WithArgs(int64(7)).WillReturnResult(sqlmock.NewResult(0, 2))
|
|
mock.ExpectExec("INSERT INTO user_organizations").WithArgs(int64(7), int64(1), true).WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectExec("INSERT INTO user_organizations").WithArgs(int64(7), int64(2), false).WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectExec("INSERT INTO organization_audit_logs").WithArgs(int64(99), nil, "organization_access_changed", `{"user_id":7,"organization_ids":[1,2],"default_organization_id":2}`, `{"user_id":7,"organization_ids":[1,2],"default_organization_id":1}`).WillReturnResult(sqlmock.NewResult(1, 1))
|
|
if err := replaceUserOrganizationsTx(tx, 7, model.UserOrganizationInput{DefaultOrganizationID: json.RawMessage("1"), ActorUserID: 99}, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
mock.ExpectRollback()
|
|
_ = tx.Rollback()
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestUserOrganizationAuditFailureRollsBackUserAndRoles(t *testing.T) {
|
|
db, mock, _ := sqlmock.New()
|
|
defer db.Close()
|
|
database.DB = db
|
|
defer func() { database.DB = nil }()
|
|
mock.ExpectBegin()
|
|
mock.ExpectQuery("SELECT COUNT.*FROM roles").WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
mock.ExpectQuery("SELECT id FROM roles WHERE code").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
|
mock.ExpectQuery("SELECT COUNT.*FROM user_roles WHERE user_id").WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
|
mock.ExpectQuery("SELECT id FROM users WHERE id.*FOR UPDATE").WithArgs(int64(7)).WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(7))
|
|
mock.ExpectExec("UPDATE users").WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectExec("DELETE FROM user_roles").WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectExec("INSERT INTO user_roles").WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectQuery("SELECT organization_id, is_default FROM user_organizations").WillReturnRows(sqlmock.NewRows([]string{"organization_id", "is_default"}).AddRow(2, true))
|
|
mock.ExpectQuery("SELECT EXISTS").WillReturnRows(sqlmock.NewRows([]string{"admin"}).AddRow(false))
|
|
mock.ExpectExec("DELETE FROM user_organizations").WillReturnResult(sqlmock.NewResult(0, 1))
|
|
mock.ExpectExec("INSERT INTO organization_audit_logs").WillReturnError(errors.New("audit unavailable"))
|
|
mock.ExpectRollback()
|
|
ids := []int64{}
|
|
err := NewUserRepository().Update(&model.User{ID: 7}, []int64{2}, model.UserOrganizationInput{OrganizationIDs: &ids, DefaultOrganizationID: json.RawMessage("null"), ActorUserID: 99})
|
|
if err == nil || err.Error() != "audit unavailable" {
|
|
t.Fatalf("got %v", err)
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|