Skip to content

Commit

Permalink
Merge pull request #376 from traPtitech/feat/unique-event-on-same-time
Browse files Browse the repository at this point in the history
重複したイベント/部屋の作成禁止
  • Loading branch information
ras0q authored Jun 19, 2023
2 parents 80f4a6e + f47d40f commit 01e2de3
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 72 deletions.
4 changes: 2 additions & 2 deletions infra/db/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ func setupRepoWithUserGroup(t *testing.T, repo string) (*GormRepository, *assert
func setupRepoWithUserRoom(t *testing.T, repo string) (*GormRepository, *assert.Assertions, *require.Assertions, *User, *Room) {
t.Helper()
r, assert, require := setupRepo(t, repo)
room, user := mustMakeRoom(t, r, "here")
room, user := mustMakeRoom(t, r, "here_"+random.AlphaNumeric(10))
return r, assert, require, user, room
}

func setupRepoWithUserGroupRoomEvent(t *testing.T, repo string) (*GormRepository, *assert.Assertions, *require.Assertions, *User, *Group, *Room, *Event) {
t.Helper()
r, assert, require := setupRepo(t, repo)

event, group, room, user := mustMakeEvent(t, r, "event")
event, group, room, user := mustMakeEvent(t, r, "event-"+random.AlphaNumeric(10))
return r, assert, require, user, group, room, event
}

Expand Down
58 changes: 31 additions & 27 deletions infra/db/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/go-sql-driver/mysql"
"github.com/gofrs/uuid"
"github.com/jinzhu/copier"
"github.com/traPtitech/knoQ/domain"
"github.com/traPtitech/knoQ/utils/random"
"gorm.io/gorm"
Expand All @@ -15,24 +14,26 @@ import (
func Test_createEvent(t *testing.T) {
r, assert, require, user, room := setupRepoWithUserRoom(t, common)

params := WriteEventParams{
CreatedBy: user.ID,
WriteEventParams: domain.WriteEventParams{
Name: "first event",
GroupID: mustNewUUIDV4(t),
RoomID: room.ID,
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
AllowTogether: true,
Admins: []uuid.UUID{user.ID},
Tags: []domain.EventTagParams{
{Name: "go", Locked: true}, {Name: "golang"},
newParams := func() WriteEventParams {
return WriteEventParams{
CreatedBy: user.ID,
WriteEventParams: domain.WriteEventParams{
Name: "event-" + random.AlphaNumeric(10),
GroupID: mustNewUUIDV4(t),
RoomID: room.ID,
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
AllowTogether: true,
Admins: []uuid.UUID{user.ID},
Tags: []domain.EventTagParams{
{Name: "go", Locked: true}, {Name: "golang"},
},
},
},
}
}

t.Run("create event", func(t *testing.T) {
event, err := createEvent(r.db, params)
event, err := createEvent(r.db, newParams())
require.NoError(err)
assert.NotNil(event.ID)

Expand All @@ -46,36 +47,28 @@ func Test_createEvent(t *testing.T) {
_, err := createOrGetTag(r.db, "Go")
require.NoError(err)

var p WriteEventParams
require.NoError(copier.Copy(&p, &params))

p := newParams()
p.Tags = append(p.Tags, domain.EventTagParams{Name: "Go"})
_, err = createEvent(r.db, p)
require.NoError(err)
})

t.Run("wrong time", func(t *testing.T) {
var p WriteEventParams
require.NoError(copier.Copy(&p, &params))

p := newParams()
p.TimeStart = time.Now().Add(10 * time.Minute)
_, err := createEvent(r.db, p)
assert.ErrorIs(err, ErrTimeConsistency)
})

t.Run("wrong room time", func(t *testing.T) {
var p WriteEventParams
require.NoError(copier.Copy(&p, &params))

p := newParams()
p.AllowTogether = false
_, err := createEvent(r.db, p)
assert.ErrorIs(err, ErrTimeConsistency)
})

t.Run("create event with place", func(t *testing.T) {
var p WriteEventParams
require.NoError(copier.Copy(&p, &params))

p := newParams()
p.RoomID = uuid.Nil
p.Place = "instant room"
event, err := createEvent(r.db.Debug(), p)
Expand All @@ -86,6 +79,17 @@ func Test_createEvent(t *testing.T) {
assert.NotEqual(uuid.Nil, e.RoomID)
assert.Equal(p.Place, e.Room.Place)
})

t.Run("cannot create event with same name, time", func(t *testing.T) {
p := newParams()
_, err := createEvent(r.db, p)
require.NoError(err)

_, err = createEvent(r.db, p)
var me *mysql.MySQLError
require.ErrorAs(err, &me)
assert.Equal(uint16(1062), me.Number)
})
}

func Test_updateEvent(t *testing.T) {
Expand Down
23 changes: 16 additions & 7 deletions infra/db/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,24 @@ func (e *Event) BeforeSave(tx *gorm.DB) (err error) {
}

if e.RoomID == uuid.Nil {
if e.Room.Place != "" {
e.Room.Verified = false
e.Room.TimeStart = e.TimeStart
e.Room.TimeEnd = e.TimeEnd
e.Room.CreatedByRefer = e.CreatedByRefer
e.Room.Admins = ConvSEventAdminToSRoomAdmin(e.Admins)
} else {
if e.Room.Place == "" {
return NewValueError(ErrRoomUndefined, "roomID", "place")
}

if err := tx.
Where(&Room{Place: e.Room.Place, TimeStart: e.TimeStart, TimeEnd: e.TimeEnd}).
First(&e.Room).
Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
e.Room.Verified = false
e.Room.TimeStart = e.TimeStart
e.Room.TimeEnd = e.TimeEnd
e.Room.CreatedByRefer = e.CreatedByRefer
e.Room.Admins = ConvSEventAdminToSRoomAdmin(e.Admins)
} else {
return err
}
}
}

// 時間整合性
Expand Down
12 changes: 6 additions & 6 deletions infra/db/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ type RoomAdmin struct {
//go:generate go run github.com/fuji8/gotypeconverter/cmd/gotypeconverter@latest -s []*Room -d []*domain.Room -o converter.go .
type Room struct {
ID uuid.UUID `gorm:"type:char(36);primaryKey"`
Place string `gorm:"type:varchar(32);"`
Place string `gorm:"type:varchar(32); uniqueIndex:idx_place_time_start_time_end"`
Verified bool
TimeStart time.Time `gorm:"type:DATETIME; index"`
TimeEnd time.Time `gorm:"type:DATETIME; index"`
TimeStart time.Time `gorm:"type:DATETIME; index; uniqueIndex:idx_place_time_start_time_end"`
TimeEnd time.Time `gorm:"type:DATETIME; index; uniqueIndex:idx_place_time_start_time_end"`
Events []Event `gorm:"->; constraint:-"` // readOnly
Admins []RoomAdmin
CreatedByRefer uuid.UUID `gorm:"type:char(36);" cvt:"CreatedBy, <-"`
Expand Down Expand Up @@ -173,14 +173,14 @@ type EventAttendee struct {
//go:generate go run github.com/fuji8/gotypeconverter/cmd/gotypeconverter@latest -s []*Event -d []*domain.Event -o converter.go .
type Event struct {
ID uuid.UUID `gorm:"type:char(36); primaryKey"`
Name string `gorm:"type:varchar(32); not null"`
Name string `gorm:"type:varchar(32); not null; uniqueIndex:idx_name_time_start_time_end"`
Description string `gorm:"type:TEXT"`
GroupID uuid.UUID `gorm:"type:char(36); not null; index"`
Group Group `gorm:"->; foreignKey:GroupID; constraint:-"`
RoomID uuid.UUID `gorm:"type:char(36); not null; index"`
Room Room `gorm:"foreignKey:RoomID; constraint:OnDelete:CASCADE;" cvt:"write:Place"`
TimeStart time.Time `gorm:"type:DATETIME; index"`
TimeEnd time.Time `gorm:"type:DATETIME; index"`
TimeStart time.Time `gorm:"type:DATETIME; index; uniqueIndex:idx_name_time_start_time_end"`
TimeEnd time.Time `gorm:"type:DATETIME; index; uniqueIndex:idx_name_time_start_time_end"`
CreatedByRefer uuid.UUID `gorm:"type:char(36); not null" cvt:"CreatedBy, <-"`
CreatedBy User `gorm:"->; foreignKey:CreatedByRefer; constraint:OnDelete:CASCADE;" cvt:"->"`
Admins []EventAdmin
Expand Down
77 changes: 47 additions & 30 deletions infra/db/room_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,88 @@ import (

"github.com/go-sql-driver/mysql"
"github.com/gofrs/uuid"
"github.com/jinzhu/copier"
"github.com/traPtitech/knoQ/domain"
"github.com/traPtitech/traQ/utils/random"
)

func Test_createRoom(t *testing.T) {
r, assert, require, user := setupRepoWithUser(t, common)

params := CreateRoomParams{
CreatedBy: user.ID,
Verified: false,
WriteRoomParams: domain.WriteRoomParams{
Place: "create room",
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
Admins: []uuid.UUID{user.ID},
},
newParams := func() CreateRoomParams {
return CreateRoomParams{
CreatedBy: user.ID,
Verified: false,
WriteRoomParams: domain.WriteRoomParams{
Place: "create room_" + random.AlphaNumeric(10),
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
Admins: []uuid.UUID{user.ID},
},
}
}

t.Run("create room", func(t *testing.T) {
room, err := createRoom(r.db, params)
room, err := createRoom(r.db, newParams())
require.NoError(err)
assert.NotNil(room.ID)
})

t.Run("wrong time", func(t *testing.T) {
var p CreateRoomParams
require.NoError(copier.Copy(&p, &params))

p.TimeStart = time.Now().Add(10 * time.Minute)
p := newParams()
p.TimeStart, p.TimeEnd = p.TimeEnd, p.TimeStart
_, err := createRoom(r.db, p)
assert.ErrorIs(err, ErrTimeConsistency)
})

t.Run("cannot create room with same place, time", func(t *testing.T) {
p := newParams()
_, err := createRoom(r.db, p)
require.NoError(err)

_, err = createRoom(r.db, p)
var me *mysql.MySQLError
require.ErrorAs(err, &me)
assert.Equal(uint16(1062), me.Number)
})
}

func Test_updateRoom(t *testing.T) {
r, assert, require, user, room := setupRepoWithUserRoom(t, common)

params := UpdateRoomParams{
CreatedBy: user.ID,
WriteRoomParams: domain.WriteRoomParams{
Place: "update room",
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
Admins: []uuid.UUID{user.ID},
},
newParams := func() UpdateRoomParams {
return UpdateRoomParams{
CreatedBy: user.ID,
WriteRoomParams: domain.WriteRoomParams{
Place: "update room_" + random.AlphaNumeric(10),
TimeStart: time.Now(),
TimeEnd: time.Now().Add(1 * time.Minute),
Admins: []uuid.UUID{user.ID},
},
}
}

t.Run("update room", func(t *testing.T) {
_, err := updateRoom(r.db, room.ID, params)
p := newParams()
_, err := updateRoom(r.db, room.ID, p)
require.NoError(err)

ro, err := getRoom(roomFullPreload(r.db), room.ID)
require.NoError(err)

assert.Equal(params.Place, ro.Place)
assert.Equal(p.Place, ro.Place)
})

t.Run("update room with verified", func(t *testing.T) {
var p CreateRoomParams
require.NoError(copier.Copy(&p, &params))
p.Verified = true
_p := newParams()
p := CreateRoomParams{
WriteRoomParams: _p.WriteRoomParams,
Verified: true,
CreatedBy: _p.CreatedBy,
}
ro, err := createRoom(r.db, p)
require.NoError(err)

_, err = updateRoom(r.db, ro.ID, params)
_, err = updateRoom(r.db, ro.ID, newParams())
require.NoError(err)

roo, err := getRoom(r.db, ro.ID)
Expand All @@ -79,7 +96,7 @@ func Test_updateRoom(t *testing.T) {
})

t.Run("update random roomID", func(t *testing.T) {
_, err := updateRoom(r.db, mustNewUUIDV4(t), params)
_, err := updateRoom(r.db, mustNewUUIDV4(t), newParams())
var me *mysql.MySQLError
require.ErrorAs(err, &me)
assert.Equal(uint16(1452), me.Number)
Expand Down
2 changes: 2 additions & 0 deletions migration/current.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ func Migrations() []*gormigrate.Migration {
v10(),
v11(),
v12(),
v13(),
v14(),
}
}
Loading

0 comments on commit 01e2de3

Please sign in to comment.