From 2da6c261cff620992c4dd6a82883883da2dd4d21 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 22:18:01 +0900 Subject: [PATCH 01/27] feat: add repository --- infra/mock/mock_auth.go | 44 +++++++-------- infra/mock/mock_comment.go | 112 ++++++++++++++++--------------------- infra/mock/mock_post.go | 90 +++++++++++++---------------- infra/mock/mock_user.go | 70 ++++++++++++----------- repository/user.go | 1 + 5 files changed, 145 insertions(+), 172 deletions(-) diff --git a/infra/mock/mock_auth.go b/infra/mock/mock_auth.go index 62f9e23..074c9b7 100644 --- a/infra/mock/mock_auth.go +++ b/infra/mock/mock_auth.go @@ -1,65 +1,59 @@ // Code generated by MockGen. DO NOT EDIT. // Source: auth.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" + reflect "reflect" ) -// MockAuth is a mock of Auth interface. +// MockAuth is a mock of Auth interface type MockAuth struct { ctrl *gomock.Controller recorder *MockAuthMockRecorder } -// MockAuthMockRecorder is the mock recorder for MockAuth. +// MockAuthMockRecorder is the mock recorder for MockAuth type MockAuthMockRecorder struct { mock *MockAuth } -// NewMockAuth creates a new mock instance. +// NewMockAuth creates a new mock instance func NewMockAuth(ctrl *gomock.Controller) *MockAuth { mock := &MockAuth{ctrl: ctrl} mock.recorder = &MockAuthMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAuth) EXPECT() *MockAuthMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockAuth) EXPECT() *MockAuthMockRecorder { + return _m.recorder } -// Authenticate mocks base method. -func (m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Authenticate", ctx, token) +// Authenticate mocks base method +func (_m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { + ret := _m.ctrl.Call(_m, "Authenticate", ctx, token) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// Authenticate indicates an expected call of Authenticate. -func (mr *MockAuthMockRecorder) Authenticate(ctx, token interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), ctx, token) +// Authenticate indicates an expected call of Authenticate +func (_mr *MockAuthMockRecorder) Authenticate(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), arg0, arg1) } -// GetIconURL mocks base method. -func (m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetIconURL", ctx, uid) +// GetIconURL mocks base method +func (_m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { + ret := _m.ctrl.Call(_m, "GetIconURL", ctx, uid) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetIconURL indicates an expected call of GetIconURL. -func (mr *MockAuthMockRecorder) GetIconURL(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), ctx, uid) +// GetIconURL indicates an expected call of GetIconURL +func (_mr *MockAuthMockRecorder) GetIconURL(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), arg0, arg1) } diff --git a/infra/mock/mock_comment.go b/infra/mock/mock_comment.go index 47998c9..0faeb1e 100644 --- a/infra/mock/mock_comment.go +++ b/infra/mock/mock_comment.go @@ -1,123 +1,109 @@ // Code generated by MockGen. DO NOT EDIT. // Source: comment.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockComment is a mock of Comment interface. +// MockComment is a mock of Comment interface type MockComment struct { ctrl *gomock.Controller recorder *MockCommentMockRecorder } -// MockCommentMockRecorder is the mock recorder for MockComment. +// MockCommentMockRecorder is the mock recorder for MockComment type MockCommentMockRecorder struct { mock *MockComment } -// NewMockComment creates a new mock instance. +// NewMockComment creates a new mock instance func NewMockComment(ctrl *gomock.Controller) *MockComment { mock := &MockComment{ctrl: ctrl} mock.recorder = &MockCommentMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockComment) EXPECT() *MockCommentMockRecorder { - return m.recorder -} - -// Delete mocks base method. -func (m *MockComment) Delete(ctx context.Context, comment *entity.Comment) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", ctx, comment) - ret0, _ := ret[0].(error) - return ret0 +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockComment) EXPECT() *MockCommentMockRecorder { + return _m.recorder } -// Delete indicates an expected call of Delete. -func (mr *MockCommentMockRecorder) Delete(ctx, comment interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockComment)(nil).Delete), ctx, comment) -} - -// FindByID mocks base method. -func (m *MockComment) FindByID(ctx context.Context, postID, commentID int) (*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, postID, commentID) +// FindByID mocks base method +func (_m *MockComment) FindByID(ctx context.Context, postID int, commentID int) (*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, postID, commentID) ret0, _ := ret[0].(*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockCommentMockRecorder) FindByID(ctx, postID, commentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), ctx, postID, commentID) +// FindByID indicates an expected call of FindByID +func (_mr *MockCommentMockRecorder) FindByID(arg0, arg1, arg2 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), arg0, arg1, arg2) } -// FindByPostID mocks base method. -func (m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByPostID", ctx, postID) +// FindByUserID mocks base method +func (_m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByPostID indicates an expected call of FindByPostID. -func (mr *MockCommentMockRecorder) FindByPostID(ctx, postID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), ctx, postID) +// FindByUserID indicates an expected call of FindByUserID +func (_mr *MockCommentMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), arg0, arg1) } -// FindByUserID mocks base method. -func (m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) +// FindByPostID mocks base method +func (_m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByPostID", ctx, postID) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID. -func (mr *MockCommentMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), ctx, uid) +// FindByPostID indicates an expected call of FindByPostID +func (_mr *MockCommentMockRecorder) FindByPostID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), arg0, arg1) +} + +// Insert mocks base method +func (_m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, comment) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert +func (_mr *MockCommentMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), arg0, arg1) } -// Insert mocks base method. -func (m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, comment) +// Update mocks base method +func (_m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { + ret := _m.ctrl.Call(_m, "Update", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockCommentMockRecorder) Insert(ctx, comment interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), ctx, comment) +// Update indicates an expected call of Update +func (_mr *MockCommentMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), arg0, arg1) } -// Update mocks base method. -func (m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, comment) +// Delete mocks base method +func (_m *MockComment) Delete(ctx context.Context, comment *entity.Comment) error { + ret := _m.ctrl.Call(_m, "Delete", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockCommentMockRecorder) Update(ctx, comment interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), ctx, comment) +// Delete indicates an expected call of Delete +func (_mr *MockCommentMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Delete", reflect.TypeOf((*MockComment)(nil).Delete), arg0, arg1) } diff --git a/infra/mock/mock_post.go b/infra/mock/mock_post.go index 3290bd4..d41f455 100644 --- a/infra/mock/mock_post.go +++ b/infra/mock/mock_post.go @@ -1,109 +1,97 @@ // Code generated by MockGen. DO NOT EDIT. // Source: post.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockPost is a mock of Post interface. +// MockPost is a mock of Post interface type MockPost struct { ctrl *gomock.Controller recorder *MockPostMockRecorder } -// MockPostMockRecorder is the mock recorder for MockPost. +// MockPostMockRecorder is the mock recorder for MockPost type MockPostMockRecorder struct { mock *MockPost } -// NewMockPost creates a new mock instance. +// NewMockPost creates a new mock instance func NewMockPost(ctrl *gomock.Controller) *MockPost { mock := &MockPost{ctrl: ctrl} mock.recorder = &MockPostMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPost) EXPECT() *MockPostMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockPost) EXPECT() *MockPostMockRecorder { + return _m.recorder } -// FindByID mocks base method. -func (m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, postID) - ret0, _ := ret[0].(*entity.Post) +// GetAll mocks base method +func (_m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { + ret := _m.ctrl.Call(_m, "GetAll", ctx) + ret0, _ := ret[0].([]*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockPostMockRecorder) FindByID(ctx, postID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), ctx, postID) +// GetAll indicates an expected call of GetAll +func (_mr *MockPostMockRecorder) GetAll(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), arg0) } -// FindByUserID mocks base method. -func (m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) - ret0, _ := ret[0].([]*entity.Post) +// FindByID mocks base method +func (_m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, postID) + ret0, _ := ret[0].(*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID. -func (mr *MockPostMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), ctx, uid) +// FindByID indicates an expected call of FindByID +func (_mr *MockPostMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), arg0, arg1) } -// GetAll mocks base method. -func (m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAll", ctx) +// FindByUserID mocks base method +func (_m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { + ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) ret0, _ := ret[0].([]*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetAll indicates an expected call of GetAll. -func (mr *MockPostMockRecorder) GetAll(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), ctx) +// FindByUserID indicates an expected call of FindByUserID +func (_mr *MockPostMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), arg0, arg1) } -// Insert mocks base method. -func (m *MockPost) Insert(ctx context.Context, post *entity.Post) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, post) +// Insert mocks base method +func (_m *MockPost) Insert(ctx context.Context, post *entity.Post) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockPostMockRecorder) Insert(ctx, post interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), ctx, post) +// Insert indicates an expected call of Insert +func (_mr *MockPostMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), arg0, arg1) } -// Update mocks base method. -func (m *MockPost) Update(ctx context.Context, post *entity.Post) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, post) +// Update mocks base method +func (_m *MockPost) Update(ctx context.Context, post *entity.Post) error { + ret := _m.ctrl.Call(_m, "Update", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockPostMockRecorder) Update(ctx, post interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), ctx, post) +// Update indicates an expected call of Update +func (_mr *MockPostMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), arg0, arg1) } diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index a6102e6..12ea6f9 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -1,79 +1,83 @@ // Code generated by MockGen. DO NOT EDIT. // Source: user.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockUser is a mock of User interface. +// MockUser is a mock of User interface type MockUser struct { ctrl *gomock.Controller recorder *MockUserMockRecorder } -// MockUserMockRecorder is the mock recorder for MockUser. +// MockUserMockRecorder is the mock recorder for MockUser type MockUserMockRecorder struct { mock *MockUser } -// NewMockUser creates a new mock instance. +// NewMockUser creates a new mock instance func NewMockUser(ctrl *gomock.Controller) *MockUser { mock := &MockUser{ctrl: ctrl} mock.recorder = &MockUserMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUser) EXPECT() *MockUserMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockUser) EXPECT() *MockUserMockRecorder { + return _m.recorder } -// FindByID mocks base method. -func (m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, uid) +// FindByID mocks base method +func (_m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, uid) ret0, _ := ret[0].(*entity.User) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockUserMockRecorder) FindByID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), ctx, uid) +// FindByID indicates an expected call of FindByID +func (_mr *MockUserMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), arg0, arg1) +} + +// Insert mocks base method +func (_m *MockUser) Insert(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, user) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert +func (_mr *MockUserMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), arg0, arg1) } -// Insert mocks base method. -func (m *MockUser) Insert(ctx context.Context, user *entity.User) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, user) +// Update mocks base method +func (_m *MockUser) Update(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Update", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockUserMockRecorder) Insert(ctx, user interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), ctx, user) +// Update indicates an expected call of Update +func (_mr *MockUserMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), arg0, arg1) } -// Update mocks base method. -func (m *MockUser) Update(ctx context.Context, user *entity.User) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, user) +// Delete mocks base method +func (_m *MockUser) Delete(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Delete", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockUserMockRecorder) Update(ctx, user interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), ctx, user) +// Delete indicates an expected call of Delete +func (_mr *MockUserMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Delete", reflect.TypeOf((*MockUser)(nil).Delete), arg0, arg1) } diff --git a/repository/user.go b/repository/user.go index 965598c..2ca8d94 100644 --- a/repository/user.go +++ b/repository/user.go @@ -13,4 +13,5 @@ type User interface { FindByID(ctx context.Context, uid string) (user *entity.User, err error) Insert(ctx context.Context, user *entity.User) error Update(ctx context.Context, user *entity.User) error + Delete(ctx context.Context, user *entity.User) error } From 463b58103437b6c93545ae7c3f4a3b99a6d51484 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 22:52:51 +0900 Subject: [PATCH 02/27] =?UTF-8?q?feat:=20infra=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user.go | 31 ++++++++++++++++++- infra/user_test.go | 76 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/infra/user.go b/infra/user.go index 49b7523..9960c2f 100644 --- a/infra/user.go +++ b/infra/user.go @@ -81,7 +81,7 @@ func (r *UserRepository) Insert(ctx context.Context, user *entity.User) error { } } -// Update は該当ユーザーをDBに保存する +// Update は該当ユーザーのデータを更新するDBに保存する func (r *UserRepository) Update(ctx context.Context, user *entity.User) error { select { case <-ctx.Done(): @@ -107,6 +107,35 @@ func (r *UserRepository) Update(ctx context.Context, user *entity.User) error { } } +// Delete は該当ユーザIDを満たすユーザをDBから削除します +func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // 該当ユーザの存在確認 + gotUser, err := r.FindByID(ctx, user.ID) + if err != nil { + return entity.NewErrorNotFound("user") + } + + // IDとTwitterIDはユニークなので、それらを比較する + if user.TwitterID != gotUser.TwitterID { + return entity.ErrIsNotAuthor + } + + userDTO := &UserDTO{ + ID: user.ID, + TwitterID: user.TwitterID, + } + + if _, err := r.dbMap.Delete(userDTO); err != nil { + return err + } + return nil + } +} + // UserDTO はDBとやり取りするためのDataTransferObject type UserDTO struct { ID string `db:"id"` diff --git a/infra/user_test.go b/infra/user_test.go index 8e979b3..50116d2 100644 --- a/infra/user_test.go +++ b/infra/user_test.go @@ -4,9 +4,7 @@ import ( "context" "errors" "testing" - "time" - "github.com/go-gorp/gorp" "github.com/google/go-cmp/cmp" "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" ) @@ -125,7 +123,7 @@ func TestUserRepository_Update(t *testing.T) { t.Fatalf(err.Error()) } dbMap.AddTableWithName(UserDTO{}, "users") - truncateUser(t, dbMap) + truncateTable(t, dbMap, "users") userDTOs := []*UserDTO{ { ID: "existing-id", @@ -187,25 +185,65 @@ func TestUserRepository_Update(t *testing.T) { } } -func truncateUser(t *testing.T, dbMap *gorp.DbMap) { - t.Helper() - - // databaseを初期化する - if _, err := dbMap.Exec("SET FOREIGN_KEY_CHECKS = 0"); err != nil { - t.Fatal(err) +func TestUserRepository_Delete(t *testing.T) { + dbMap, err := NewDB() + if err != nil { + t.Fatalf(err.Error()) } - // タイミングの問題でTruncateが失敗することがあるので成功するまで試みる - for i := 0; i < 5; i++ { - _, err := dbMap.Exec("TRUNCATE TABLE users") - if err == nil { - break - } - if i == 4 { + dbMap.AddTableWithName(UserDTO{}, "users") + truncateTable(t, dbMap, "users") + userDTOs := []*UserDTO{ + { + ID: "existing-id", + Name: "existingUser", + Profile: "existing", + TwitterID: "existing", + }, + { + ID: "existing-id2", + Name: "existingUser2", + Profile: "existing2", + TwitterID: "existing2", + }, + } + for _, userDTO := range userDTOs { + if err := dbMap.Insert(userDTO); err != nil { t.Fatal(err) } - time.Sleep(time.Second * 1) } - if _, err := dbMap.Exec("SET FOREIGN_KEY_CHECKS = 1"); err != nil { - t.Fatal(err) + + userRepo := NewUserRepository(dbMap) + + tests := []struct { + name string + user *entity.User + wantErr error + }{ + { + name: "ユーザーIDが存在しないならErrNotFound", + user: entity.NewUser("new-id", "existingUser", "existing", "existing", ""), + wantErr: entity.NewErrorNotFound("user"), + }, + { + name: "ユーザIDとTwitterIDが合致指定ない場合、削除せずに終わる", + user: entity.NewUser("existing-id", "existingUser", "existing", "existing2", ""), + wantErr: entity.ErrIsNotAuthor, + }, + { + name: "正しくユーザーを削除できる", + user: entity.NewUser("existing-id", "existingUser", "existing", "existing", ""), + wantErr: nil, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + err := userRepo.Delete(context.Background(), tt.user) + + if !errors.Is(err, tt.wantErr) { + t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) + return + } + }) } } From 83088aa7012ac24990e5ba6e85f49dee87425e56 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 22:57:03 +0900 Subject: [PATCH 03/27] =?UTF-8?q?feat:=20usecase=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usecase/user.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/usecase/user.go b/usecase/user.go index d2b71c7..ee44acb 100644 --- a/usecase/user.go +++ b/usecase/user.go @@ -88,3 +88,11 @@ func (u *UserUseCase) Update(ctx context.Context, user *entity.User) error { } return nil } + +// Delete は引数のuserエンティティをもとにユーザを削除します +func (u *UserUseCase) Delete(ctx context.Context, user *entity.User) error { + if err := u.userRepo.Delete(ctx, user); err != nil { + return fmt.Errorf("failed Delete user: %w", err) + } + return nil +} From a401727ee6160a37104360c5a41be024d84b4303 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 23:56:17 +0900 Subject: [PATCH 04/27] =?UTF-8?q?fix:=20infra=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user.go | 5 ++++- infra/user_test.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/infra/user.go b/infra/user.go index 9960c2f..15a2cfb 100644 --- a/infra/user.go +++ b/infra/user.go @@ -36,7 +36,7 @@ func (r *UserRepository) FindByID(ctx context.Context, uid string) (user *entity err = r.dbMap.SelectOne(&userDTO, "SELECT * FROM users WHERE id = ?", uid) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, entity.ErrUserNotFound + return nil, entity.NewErrorNotFound("user") } return nil, err } @@ -113,6 +113,9 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { case <-ctx.Done(): return ctx.Err() default: + if err := user.IsValid(); err != nil { + return err + } // 該当ユーザの存在確認 gotUser, err := r.FindByID(ctx, user.ID) if err != nil { diff --git a/infra/user_test.go b/infra/user_test.go index 50116d2..0568488 100644 --- a/infra/user_test.go +++ b/infra/user_test.go @@ -43,7 +43,7 @@ func TestUserRepository_FindByID(t *testing.T) { name: "存在しないユーザーの場合はErrNoRows", userID: "not-existing-id", wantUser: nil, - wantErr: entity.ErrUserNotFound, + wantErr: entity.NewErrorNotFound("user"), }, } for _, tt := range tests { From 61d389da81821468fa3fed0c997444f2917c49e7 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 23:56:31 +0900 Subject: [PATCH 05/27] =?UTF-8?q?feat:=20controller=E3=81=AE=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/post_test.go | 4 +- controller/user.go | 63 ++++++++++++++---- controller/user_test.go | 140 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 184 insertions(+), 23 deletions(-) diff --git a/controller/post_test.go b/controller/post_test.go index 710eee1..6a3fa1e 100644 --- a/controller/post_test.go +++ b/controller/post_test.go @@ -58,7 +58,7 @@ func TestPostController_GetAll(t *testing.T) { `, }, { - name: "1つも投稿が存在しないならErrUserNotFound", + name: "1つも投稿が存在しないならErrNewErrorNotFound", prepareMockPost: func(ctx context.Context, post *mock.MockPost) { post.EXPECT().GetAll(ctx).Return(nil, entity.NewErrorNotFound("post")) }, @@ -134,7 +134,7 @@ func TestPostController_Get(t *testing.T) { wantCode: http.StatusOK, }, { - name: "存在しない投稿IDならErrUserNotFound", + name: "存在しない投稿IDならErrNewErrorNotFound", postID: "0", prepareMockPost: func(ctx context.Context, post *mock.MockPost) { post.EXPECT().FindByID(ctx, 0).Return(&entity.Post{ diff --git a/controller/user.go b/controller/user.go index a23cdcc..b6eaad3 100644 --- a/controller/user.go +++ b/controller/user.go @@ -32,8 +32,9 @@ func (ctrl *UserController) Get(c echo.Context) error { user, err := ctrl.uc.Get(c.Request().Context(), userID) if err != nil { - if errors.Is(err, entity.ErrUserNotFound) { - return echo.NewHTTPError(http.StatusNotFound, entity.ErrUserNotFound.Error()) + errNF := &entity.ErrNotFound{} + if errors.As(err, errNF) { + return echo.NewHTTPError(http.StatusNotFound, errNF.Error()) } logger.Errorf("Unexpected error GET/user/{userID}: %s", err.Error()) @@ -107,14 +108,13 @@ func (ctrl *UserController) Create(c echo.Context) error { user.ID = userID if err := ctrl.uc.Create(c.Request().Context(), user); err != nil { - if errors.Is(err, entity.ErrDuplicatedUser) { - return echo.NewHTTPError(http.StatusBadRequest, entity.ErrDuplicatedUser.Error()) - } - if errors.Is(err, entity.ErrDuplicatedTwitterID) { - return echo.NewHTTPError(http.StatusBadRequest, entity.ErrDuplicatedTwitterID.Error()) + errDup := &entity.ErrDuplicated{} + if errors.As(err, errDup) { + return echo.NewHTTPError(http.StatusBadRequest, errDup.Error()) } - if errors.Is(err, entity.ErrEmptyUserName) { - return echo.NewHTTPError(http.StatusBadRequest, entity.ErrEmptyUserName.Error()) + errEmpty := &entity.ErrEmpty{} + if errors.As(err, errEmpty) { + return echo.NewHTTPError(http.StatusBadRequest, errEmpty.Error()) } logger.Errorf("Unexpected error POST/user: %s", err.Error()) return echo.NewHTTPError(http.StatusInternalServerError) @@ -139,11 +139,14 @@ func (ctrl *UserController) Update(c echo.Context) error { user.ID = userID if err := ctrl.uc.Update(c.Request().Context(), user); err != nil { - if errors.Is(err, entity.ErrUserNotFound) { - return echo.NewHTTPError(http.StatusNotFound, entity.ErrUserNotFound.Error()) + errNF := &entity.ErrNotFound{} + if errors.As(err, errNF) { + return echo.NewHTTPError(http.StatusNotFound, errNF.Error()) } - if errors.Is(err, entity.ErrEmptyUserName) { - return echo.NewHTTPError(http.StatusBadRequest, entity.ErrEmptyUserName.Error()) + + errEmpty := &entity.ErrEmpty{} + if errors.As(err, errEmpty) { + return echo.NewHTTPError(http.StatusBadRequest, errEmpty.Error()) } errDup := &entity.ErrDuplicated{} if errors.As(err, errDup) { @@ -159,3 +162,37 @@ func (ctrl *UserController) Update(c echo.Context) error { return c.NoContent(http.StatusOK) } + +// Delete は DELETE /user/{userID} のHandler +func (ctrl *UserController) Delete(c echo.Context) error { + logger := log.New() + + user := &entity.User{} + if err := c.Bind(user); err != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + + var ok bool + user.ID, ok = c.Get("userID").(string) + if !ok { + logger.Errorf("Failed type assertion of userID: %#v", c.Get("userID")) + return echo.NewHTTPError(http.StatusInternalServerError) + } + + if err := ctrl.uc.Delete(c.Request().Context(), user); err != nil { + errEmpty := &entity.ErrEmpty{} + if errors.As(err, errEmpty) { + return echo.NewHTTPError(http.StatusBadRequest, errEmpty.Error()) + } + errNF := &entity.ErrNotFound{} + if errors.As(err, errNF) { + return echo.NewHTTPError(http.StatusNotFound, errNF.Error()) + } + if errors.Is(err, entity.ErrIsNotAuthor) { + return echo.NewHTTPError(http.StatusForbidden, err.Error()) + } + logger.Errorf("Unexpected error PUT/user: %s", err.Error()) + return echo.NewHTTPError(http.StatusInternalServerError) + } + return c.NoContent(http.StatusOK) +} diff --git a/controller/user_test.go b/controller/user_test.go index 815f155..e964b06 100644 --- a/controller/user_test.go +++ b/controller/user_test.go @@ -49,12 +49,12 @@ func TestUserController_Get(t *testing.T) { }, }, { - name: "存在しないユーザーIDならErrUserNotFound", + name: "存在しないユーザーIDならErrNewErrorNotFound", userID: "invalid-user-id", prepareMockUser: func(user *mock.MockUser) { user.EXPECT().FindByID(gomock.Any(), "invalid-user-id").Return( nil, - entity.ErrUserNotFound, + entity.NewErrorNotFound("user"), ) }, prepareMockAuth: func(auth *mock.MockAuth) {}, @@ -312,7 +312,7 @@ func TestUserController_GetPosts(t *testing.T) { `, }, { - name: "1つも投稿が存在しないならErrUserNotFound", + name: "1つも投稿が存在しないならErrNewErrorNotFound", userID: "user-id2", prepareMockPost: func(ctx context.Context, uid string, post *mock.MockPost) { post.EXPECT().FindByUserID(ctx, uid).Return(nil, entity.NewErrorNotFound("post")) @@ -449,7 +449,7 @@ func TestUserController_Create(t *testing.T) { user.EXPECT().Insert( gomock.Any(), entity.NewUser("user-id", "username", "profile", "twitter", ""), - ).Return(entity.ErrDuplicatedUser) + ).Return(entity.NewErrorDuplicated("user ID")) }, wantErr: true, wantCode: 400, @@ -466,7 +466,7 @@ func TestUserController_Create(t *testing.T) { user.EXPECT().Insert( gomock.Any(), entity.NewUser("user-id", "username", "profile", "twitter", ""), - ).Return(entity.ErrDuplicatedTwitterID) + ).Return(entity.NewErrorDuplicated("user TwitterID")) }, wantErr: true, wantCode: 400, @@ -580,7 +580,7 @@ func TestUserController_Update(t *testing.T) { wantCode: 400, }, { - name: "存在しないユーザーIDならErrUserNotFound", + name: "存在しないユーザーIDならErrNewErrorNotFound", userID: "invalid-user-id", body: `{ "name":"username", @@ -590,7 +590,7 @@ func TestUserController_Update(t *testing.T) { prepareMockUser: func(user *mock.MockUser) { user.EXPECT().FindByID(gomock.Any(), "invalid-user-id").Return( nil, - entity.ErrUserNotFound, + entity.NewErrorNotFound("user"), ) }, prepareMockAuth: func(auth *mock.MockAuth) {}, @@ -622,7 +622,7 @@ func TestUserController_Update(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := echo.New() - req := httptest.NewRequest("POST", "/", strings.NewReader(tt.body)) + req := httptest.NewRequest("PUT", "/", strings.NewReader(tt.body)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) @@ -656,3 +656,127 @@ func TestUserController_Update(t *testing.T) { }) } } + +func TestUserController_Delete(t *testing.T) { + tests := []struct { + name string + userID string + body string + prepareMockUser func(user *mock.MockUser) + prepareMockAuth func(auth *mock.MockAuth) + wantErr bool + wantCode int + }{ + { + name: "正しくユーザーを削除できる", + userID: "user-id", + body: `{ + "name":"name", + "profile":"profile", + "twitter_id":"twitter" + }`, + prepareMockUser: func(user *mock.MockUser) { + user.EXPECT().Delete( + gomock.Any(), + entity.NewUser("user-id", "name", "profile", "twitter", ""), + ).Return(nil) + }, + wantErr: false, + wantCode: 200, + }, + { + name: "不正なbodyならBadRequest", + userID: "user-id", + body: `{ + "aaa":"test" + }`, + prepareMockUser: func(user *mock.MockUser) { + user.EXPECT().Delete( + gomock.Any(), + entity.NewUser("user-id", "", "", "", ""), + ).Return(entity.NewUser("user-id", "", "", "", "").IsValid()) + }, + wantErr: true, + wantCode: 400, + }, + { + name: "bodyがJSON形式でないならBadRequest", + userID: "user-id", + body: `aaaaa`, + prepareMockUser: func(user *mock.MockUser) {}, + wantErr: true, + wantCode: 400, + }, + { + name: "存在しないユーザーIDならErrNewErrorNotFound", + userID: "invalid-user-id", + body: `{ + "name":"username", + "profile":"profile", + "twitter_id":"twitter" + }`, + prepareMockUser: func(user *mock.MockUser) { + user.EXPECT().Delete( + gomock.Any(), + entity.NewUser("invalid-user-id", "username", "profile", "twitter", ""), + ).Return(entity.NewErrorNotFound("user")) + }, + prepareMockAuth: func(auth *mock.MockAuth) {}, + wantErr: true, + wantCode: 404, + }, + { + name: "別のユーザが削除しようとしているならErrIsNotAuthorでStatusForbidden", + userID: "user-id2", + body: `{ + "name":"name", + "profile":"profile", + "twitter_id":"twitter" + }`, + prepareMockUser: func(user *mock.MockUser) { + user.EXPECT().Delete( + gomock.Any(), + entity.NewUser("user-id2", "name", "profile", "twitter", ""), + ).Return(entity.ErrIsNotAuthor) + }, + wantErr: true, + wantCode: http.StatusForbidden, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := echo.New() + req := httptest.NewRequest("DELETE", "/", strings.NewReader(tt.body)) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + c.Set("userID", tt.userID) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + userRepo := mock.NewMockUser(ctrl) + tt.prepareMockUser(userRepo) + authRepo := mock.NewMockAuth(ctrl) + postRepo := mock.NewMockPost(ctrl) + commentRepo := mock.NewMockComment(ctrl) + + con := NewUserController(usecase.NewUserUseCase(userRepo, authRepo, postRepo, commentRepo)) + err := con.Delete(c) + + if (err != nil) != tt.wantErr { + t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) + } + + if he, ok := err.(*echo.HTTPError); ok { + if he.Code != tt.wantCode { + t.Errorf("code = %d, want = %d", he.Code, tt.wantCode) + } + } else { + if rec.Code != tt.wantCode { + t.Errorf("code = %d, want = %d", rec.Code, tt.wantCode) + } + } + }) + } +} From 8d9c3d29e7b05d2bae200d5e84845885689a1518 Mon Sep 17 00:00:00 2001 From: task4233 Date: Fri, 26 Mar 2021 23:57:17 +0900 Subject: [PATCH 06/27] =?UTF-8?q?feat:=20main.go=E3=81=AB=E3=83=8F?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=83=A9=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 91b47ed..43e193a 100644 --- a/main.go +++ b/main.go @@ -62,6 +62,7 @@ func main() { user.GET("/:userID", userController.Get) user.POST("", userController.Create, authMiddleware.Authenticate) user.PUT("", userController.Update, authMiddleware.Authenticate) + user.DELETE("", userController.Delete, authMiddleware.Authenticate) user.GET("/:userID/post", userController.GetPosts) user.GET("/:userID/comment", userController.GetComments) From c3cf5376a44d502c7d60f6a344b02de68dd91bb4 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 17:34:26 +0900 Subject: [PATCH 07/27] =?UTF-8?q?feat(main.go):=20DELETE=20/api/v1/post/{p?= =?UTF-8?q?ostID}=E3=81=AE=E3=83=AB=E3=83=BC=E3=83=86=E3=82=A3=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 43e193a..3bbb2dc 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,7 @@ func main() { post.POST("", postController.Create, authMiddleware.Authenticate) post.GET("/:postID", postController.Get) post.PUT("/:postID", postController.Update, authMiddleware.Authenticate) + post.DELETE("/:postID", postController.Delete, authMiddleware.Authenticate) comment := v1.Group("/post/:postID/comment") comment.GET("", commentController.GetByPostID) From a1b4eec85b499ff33878f32328cfe0a6b7586597 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 18:23:32 +0900 Subject: [PATCH 08/27] =?UTF-8?q?feat(controler/comment.go):=20Delete?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/post.go | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/controller/post.go b/controller/post.go index ed1e206..cc146f8 100644 --- a/controller/post.go +++ b/controller/post.go @@ -97,7 +97,7 @@ func (ctrl *PostController) Create(c echo.Context) error { return c.JSON(http.StatusCreated, post) } -// Update は Post /post/{postID}のハンドラです +// Update は PUT /post/{postID}のハンドラです func (ctrl *PostController) Update(c echo.Context) error { logger := log.New() @@ -132,7 +132,39 @@ func (ctrl *PostController) Update(c echo.Context) error { return echo.NewHTTPError(http.StatusForbidden, errNF.Error()) } - logger.Errorf("error POST /post: %s", err.Error()) + logger.Errorf("error PUT /post/{postID}: %s", err.Error()) + return echo.NewHTTPError(http.StatusInternalServerError) + } + + return c.NoContent(http.StatusOK) +} + +// Delete は DELETE /post/{postID}のハンドラです +func (ctrl *PostController) Delete(c echo.Context) error { + logger := log.New() + + if userID, ok := c.Get("userID").(string); !ok { + logger.Errorf("Failed type assertion of userID: %#v", c.Get("userID")) + return echo.NewHTTPError(http.StatusInternalServerError) + } + + if postID, err := strconv.Atoi(c.Param("postID")); err != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + + ctx := c.Request().Context() + if err := ctrl.uc.Delete(ctx, userID, postID); err != nil { + if errors.Is(err, entity.ErrIsNotAuthor) { + logger.Errorf("forbidden update occurs: %s", err.Error()) + return echo.NewHTTPError(http.StatusForbidden, err.Error()) + } + errNF := &entity.ErrNotFound{} + if errors.As(err, errNF) { + logger.Errorf("forbidden update occurs: %s", err.Error()) + return echo.NewHTTPError(http.StatusForbidden, errNF.Error()) + } + + logger.Errorf("error DELETE /post/{postID}: %s", err.Error()) return echo.NewHTTPError(http.StatusInternalServerError) } From b3e6cc0128e8a047272024f0f96e2e6907cc5f7d Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 19:35:26 +0900 Subject: [PATCH 09/27] =?UTF-8?q?feat(usecase/post.go):=20delete=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usecase/post.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/usecase/post.go b/usecase/post.go index 762a531..2a93a39 100644 --- a/usecase/post.go +++ b/usecase/post.go @@ -56,3 +56,11 @@ func (p *PostUsecase) Update(ctx context.Context, post *entity.Post) error { } return nil } + +// Delete は引数のIDをもとに投稿を削除します. +func (p *PostUsecase) Delete(ctx context.Context, userID string, postID int) error { + if err := p.postRepo.Delete(ctx, userID, postID); err != nil { + return fmt.Errorf("failed Update Post: %w", err) + } + return nil +} From c38633967e9b4d05314da6659926d3879d0af1e2 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 19:36:05 +0900 Subject: [PATCH 10/27] =?UTF-8?q?feat(infra/post.go):=20DB=E3=81=8B?= =?UTF-8?q?=E3=82=89Post=E3=82=92=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/mock/mock_auth.go | 44 +++++++++------- infra/mock/mock_comment.go | 86 +++++++++++++++++------------- infra/mock/mock_post.go | 104 +++++++++++++++++++++++-------------- infra/mock/mock_user.go | 58 ++++++++++++--------- infra/post.go | 31 +++++++++++ repository/post.go | 1 + 6 files changed, 204 insertions(+), 120 deletions(-) diff --git a/infra/mock/mock_auth.go b/infra/mock/mock_auth.go index 074c9b7..62f9e23 100644 --- a/infra/mock/mock_auth.go +++ b/infra/mock/mock_auth.go @@ -1,59 +1,65 @@ // Code generated by MockGen. DO NOT EDIT. // Source: auth.go +// Package mock is a generated GoMock package. package mock import ( context "context" - gomock "github.com/golang/mock/gomock" reflect "reflect" + + gomock "github.com/golang/mock/gomock" ) -// MockAuth is a mock of Auth interface +// MockAuth is a mock of Auth interface. type MockAuth struct { ctrl *gomock.Controller recorder *MockAuthMockRecorder } -// MockAuthMockRecorder is the mock recorder for MockAuth +// MockAuthMockRecorder is the mock recorder for MockAuth. type MockAuthMockRecorder struct { mock *MockAuth } -// NewMockAuth creates a new mock instance +// NewMockAuth creates a new mock instance. func NewMockAuth(ctrl *gomock.Controller) *MockAuth { mock := &MockAuth{ctrl: ctrl} mock.recorder = &MockAuthMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use -func (_m *MockAuth) EXPECT() *MockAuthMockRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAuth) EXPECT() *MockAuthMockRecorder { + return m.recorder } -// Authenticate mocks base method -func (_m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { - ret := _m.ctrl.Call(_m, "Authenticate", ctx, token) +// Authenticate mocks base method. +func (m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Authenticate", ctx, token) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// Authenticate indicates an expected call of Authenticate -func (_mr *MockAuthMockRecorder) Authenticate(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), arg0, arg1) +// Authenticate indicates an expected call of Authenticate. +func (mr *MockAuthMockRecorder) Authenticate(ctx, token interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), ctx, token) } -// GetIconURL mocks base method -func (_m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { - ret := _m.ctrl.Call(_m, "GetIconURL", ctx, uid) +// GetIconURL mocks base method. +func (m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetIconURL", ctx, uid) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetIconURL indicates an expected call of GetIconURL -func (_mr *MockAuthMockRecorder) GetIconURL(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), arg0, arg1) +// GetIconURL indicates an expected call of GetIconURL. +func (mr *MockAuthMockRecorder) GetIconURL(ctx, uid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), ctx, uid) } diff --git a/infra/mock/mock_comment.go b/infra/mock/mock_comment.go index 0faeb1e..662958a 100644 --- a/infra/mock/mock_comment.go +++ b/infra/mock/mock_comment.go @@ -1,99 +1,111 @@ // Code generated by MockGen. DO NOT EDIT. // Source: comment.go +// Package mock is a generated GoMock package. package mock import ( context "context" + reflect "reflect" + gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" - reflect "reflect" ) -// MockComment is a mock of Comment interface +// MockComment is a mock of Comment interface. type MockComment struct { ctrl *gomock.Controller recorder *MockCommentMockRecorder } -// MockCommentMockRecorder is the mock recorder for MockComment +// MockCommentMockRecorder is the mock recorder for MockComment. type MockCommentMockRecorder struct { mock *MockComment } -// NewMockComment creates a new mock instance +// NewMockComment creates a new mock instance. func NewMockComment(ctrl *gomock.Controller) *MockComment { mock := &MockComment{ctrl: ctrl} mock.recorder = &MockCommentMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use -func (_m *MockComment) EXPECT() *MockCommentMockRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockComment) EXPECT() *MockCommentMockRecorder { + return m.recorder } -// FindByID mocks base method -func (_m *MockComment) FindByID(ctx context.Context, postID int, commentID int) (*entity.Comment, error) { - ret := _m.ctrl.Call(_m, "FindByID", ctx, postID, commentID) +// FindByID mocks base method. +func (m *MockComment) FindByID(ctx context.Context, postID, commentID int) (*entity.Comment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, postID, commentID) ret0, _ := ret[0].(*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID -func (_mr *MockCommentMockRecorder) FindByID(arg0, arg1, arg2 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), arg0, arg1, arg2) +// FindByID indicates an expected call of FindByID. +func (mr *MockCommentMockRecorder) FindByID(ctx, postID, commentID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), ctx, postID, commentID) } -// FindByUserID mocks base method -func (_m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { - ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) +// FindByPostID mocks base method. +func (m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByPostID", ctx, postID) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID -func (_mr *MockCommentMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), arg0, arg1) +// FindByPostID indicates an expected call of FindByPostID. +func (mr *MockCommentMockRecorder) FindByPostID(ctx, postID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), ctx, postID) } -// FindByPostID mocks base method -func (_m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { - ret := _m.ctrl.Call(_m, "FindByPostID", ctx, postID) +// FindByUserID mocks base method. +func (m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByPostID indicates an expected call of FindByPostID -func (_mr *MockCommentMockRecorder) FindByPostID(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), arg0, arg1) +// FindByUserID indicates an expected call of FindByUserID. +func (mr *MockCommentMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), ctx, uid) } -// Insert mocks base method -func (_m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { - ret := _m.ctrl.Call(_m, "Insert", ctx, comment) +// Insert mocks base method. +func (m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert -func (_mr *MockCommentMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), arg0, arg1) +// Insert indicates an expected call of Insert. +func (mr *MockCommentMockRecorder) Insert(ctx, comment interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), ctx, comment) } -// Update mocks base method -func (_m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { - ret := _m.ctrl.Call(_m, "Update", ctx, comment) +// Update mocks base method. +func (m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update -func (_mr *MockCommentMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), arg0, arg1) +// Update indicates an expected call of Update. +func (mr *MockCommentMockRecorder) Update(ctx, comment interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), ctx, comment) } // Delete mocks base method diff --git a/infra/mock/mock_post.go b/infra/mock/mock_post.go index d41f455..a89246f 100644 --- a/infra/mock/mock_post.go +++ b/infra/mock/mock_post.go @@ -1,97 +1,123 @@ // Code generated by MockGen. DO NOT EDIT. // Source: post.go +// Package mock is a generated GoMock package. package mock import ( context "context" + reflect "reflect" + gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" - reflect "reflect" ) -// MockPost is a mock of Post interface +// MockPost is a mock of Post interface. type MockPost struct { ctrl *gomock.Controller recorder *MockPostMockRecorder } -// MockPostMockRecorder is the mock recorder for MockPost +// MockPostMockRecorder is the mock recorder for MockPost. type MockPostMockRecorder struct { mock *MockPost } -// NewMockPost creates a new mock instance +// NewMockPost creates a new mock instance. func NewMockPost(ctrl *gomock.Controller) *MockPost { mock := &MockPost{ctrl: ctrl} mock.recorder = &MockPostMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use -func (_m *MockPost) EXPECT() *MockPostMockRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPost) EXPECT() *MockPostMockRecorder { + return m.recorder } -// GetAll mocks base method -func (_m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { - ret := _m.ctrl.Call(_m, "GetAll", ctx) - ret0, _ := ret[0].([]*entity.Post) +// Delete mocks base method. +func (m *MockPost) Delete(ctx context.Context, userID string, postID int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, userID, postID) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockPostMockRecorder) Delete(ctx, userID, postID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPost)(nil).Delete), ctx, userID, postID) +} + +// FindByID mocks base method. +func (m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, postID) + ret0, _ := ret[0].(*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetAll indicates an expected call of GetAll -func (_mr *MockPostMockRecorder) GetAll(arg0 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), arg0) +// FindByID indicates an expected call of FindByID. +func (mr *MockPostMockRecorder) FindByID(ctx, postID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), ctx, postID) } -// FindByID mocks base method -func (_m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { - ret := _m.ctrl.Call(_m, "FindByID", ctx, postID) - ret0, _ := ret[0].(*entity.Post) +// FindByUserID mocks base method. +func (m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) + ret0, _ := ret[0].([]*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID -func (_mr *MockPostMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), arg0, arg1) +// FindByUserID indicates an expected call of FindByUserID. +func (mr *MockPostMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), ctx, uid) } -// FindByUserID mocks base method -func (_m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { - ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) +// GetAll mocks base method. +func (m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAll", ctx) ret0, _ := ret[0].([]*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID -func (_mr *MockPostMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), arg0, arg1) +// GetAll indicates an expected call of GetAll. +func (mr *MockPostMockRecorder) GetAll(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), ctx) } -// Insert mocks base method -func (_m *MockPost) Insert(ctx context.Context, post *entity.Post) error { - ret := _m.ctrl.Call(_m, "Insert", ctx, post) +// Insert mocks base method. +func (m *MockPost) Insert(ctx context.Context, post *entity.Post) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert -func (_mr *MockPostMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), arg0, arg1) +// Insert indicates an expected call of Insert. +func (mr *MockPostMockRecorder) Insert(ctx, post interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), ctx, post) } -// Update mocks base method -func (_m *MockPost) Update(ctx context.Context, post *entity.Post) error { - ret := _m.ctrl.Call(_m, "Update", ctx, post) +// Update mocks base method. +func (m *MockPost) Update(ctx context.Context, post *entity.Post) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update -func (_mr *MockPostMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), arg0, arg1) +// Update indicates an expected call of Update. +func (mr *MockPostMockRecorder) Update(ctx, post interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), ctx, post) } diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index 12ea6f9..c3b1500 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -1,73 +1,81 @@ // Code generated by MockGen. DO NOT EDIT. // Source: user.go +// Package mock is a generated GoMock package. package mock import ( context "context" + reflect "reflect" + gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" - reflect "reflect" ) -// MockUser is a mock of User interface +// MockUser is a mock of User interface. type MockUser struct { ctrl *gomock.Controller recorder *MockUserMockRecorder } -// MockUserMockRecorder is the mock recorder for MockUser +// MockUserMockRecorder is the mock recorder for MockUser. type MockUserMockRecorder struct { mock *MockUser } -// NewMockUser creates a new mock instance +// NewMockUser creates a new mock instance. func NewMockUser(ctrl *gomock.Controller) *MockUser { mock := &MockUser{ctrl: ctrl} mock.recorder = &MockUserMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use -func (_m *MockUser) EXPECT() *MockUserMockRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUser) EXPECT() *MockUserMockRecorder { + return m.recorder } -// FindByID mocks base method -func (_m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { - ret := _m.ctrl.Call(_m, "FindByID", ctx, uid) +// FindByID mocks base method. +func (m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, uid) ret0, _ := ret[0].(*entity.User) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID -func (_mr *MockUserMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), arg0, arg1) +// FindByID indicates an expected call of FindByID. +func (mr *MockUserMockRecorder) FindByID(ctx, uid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), ctx, uid) } -// Insert mocks base method -func (_m *MockUser) Insert(ctx context.Context, user *entity.User) error { - ret := _m.ctrl.Call(_m, "Insert", ctx, user) +// Insert mocks base method. +func (m *MockUser) Insert(ctx context.Context, user *entity.User) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert -func (_mr *MockUserMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), arg0, arg1) +// Insert indicates an expected call of Insert. +func (mr *MockUserMockRecorder) Insert(ctx, user interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), ctx, user) } -// Update mocks base method -func (_m *MockUser) Update(ctx context.Context, user *entity.User) error { - ret := _m.ctrl.Call(_m, "Update", ctx, user) +// Update mocks base method. +func (m *MockUser) Update(ctx context.Context, user *entity.User) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update -func (_mr *MockUserMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), arg0, arg1) +// Update indicates an expected call of Update. +func (mr *MockUserMockRecorder) Update(ctx, user interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), ctx, user) } // Delete mocks base method diff --git a/infra/post.go b/infra/post.go index 8948837..51b4e62 100644 --- a/infra/post.go +++ b/infra/post.go @@ -202,6 +202,37 @@ func (p *PostRepository) Update(ctx context.Context, post *entity.Post) error { return nil } +// Delete は引数で渡したIDの投稿を削除します +// 投稿の所有者以外が削除する場合、削除は行われません +func (p *PostRepository) Delete(ctx context.Context, userID string, postID int) error { + select { + // echoのリクエストが途切れた場合は早めにリソースを開放するために処理を中断する + case <-ctx.Done(): + return ctx.Err() + default: + // 該当するポストがあるか確認 + getPost, err := p.FindByID(ctx, postID) + if err != nil { + return entity.NewErrorNotFound("post") + } + + // 所有者でなければ削除処理は行わない + if getPost.UserID != userID { + return entity.ErrIsNotAuthor + } + + postDTO := &PostInsertDTO{ + ID: postID, + } + + if _, err := p.dbMap.Delete(postDTO); err != nil { + return err + } + } + + return nil +} + // PostDTO はDBとやりとりするためのDataTransferObjectです // ref: migrations/20210319141439-CreatePosts.sql type PostDTO struct { diff --git a/repository/post.go b/repository/post.go index 342c859..4c0aa3b 100644 --- a/repository/post.go +++ b/repository/post.go @@ -15,4 +15,5 @@ type Post interface { FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) Insert(ctx context.Context, post *entity.Post) error Update(ctx context.Context, post *entity.Post) error + Delete(ctx context.Context, userID string, postID int) error } From 3abff64dbce9b16bd21393a194b35cffe683a7ad Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 21:49:55 +0900 Subject: [PATCH 11/27] =?UTF-8?q?refactor(post=20delete):=20ID=E3=82=92ent?= =?UTF-8?q?ity.Post=E3=81=AB=E3=81=BE=E3=81=A8=E3=82=81=E3=81=A6=E6=B8=A1?= =?UTF-8?q?=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/post.go | 9 ++++++--- infra/mock/mock_post.go | 8 ++++---- infra/post.go | 8 ++++---- repository/post.go | 2 +- usecase/post.go | 6 +++--- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/controller/post.go b/controller/post.go index cc146f8..cbc775e 100644 --- a/controller/post.go +++ b/controller/post.go @@ -143,17 +143,20 @@ func (ctrl *PostController) Update(c echo.Context) error { func (ctrl *PostController) Delete(c echo.Context) error { logger := log.New() - if userID, ok := c.Get("userID").(string); !ok { + post := &entity.Post{} + var ok bool + if post.UserID, ok = c.Get("userID").(string); !ok { logger.Errorf("Failed type assertion of userID: %#v", c.Get("userID")) return echo.NewHTTPError(http.StatusInternalServerError) } - if postID, err := strconv.Atoi(c.Param("postID")); err != nil { + var err error + if post.ID, err = strconv.Atoi(c.Param("postID")); err != nil { return echo.NewHTTPError(http.StatusBadRequest) } ctx := c.Request().Context() - if err := ctrl.uc.Delete(ctx, userID, postID); err != nil { + if err := ctrl.uc.Delete(ctx, post); err != nil { if errors.Is(err, entity.ErrIsNotAuthor) { logger.Errorf("forbidden update occurs: %s", err.Error()) return echo.NewHTTPError(http.StatusForbidden, err.Error()) diff --git a/infra/mock/mock_post.go b/infra/mock/mock_post.go index a89246f..bd4fe8f 100644 --- a/infra/mock/mock_post.go +++ b/infra/mock/mock_post.go @@ -36,17 +36,17 @@ func (m *MockPost) EXPECT() *MockPostMockRecorder { } // Delete mocks base method. -func (m *MockPost) Delete(ctx context.Context, userID string, postID int) error { +func (m *MockPost) Delete(ctx context.Context, post *entity.Post) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", ctx, userID, postID) + ret := m.ctrl.Call(m, "Delete", ctx, post) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockPostMockRecorder) Delete(ctx, userID, postID interface{}) *gomock.Call { +func (mr *MockPostMockRecorder) Delete(ctx, post interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPost)(nil).Delete), ctx, userID, postID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPost)(nil).Delete), ctx, post) } // FindByID mocks base method. diff --git a/infra/post.go b/infra/post.go index 51b4e62..cdd4464 100644 --- a/infra/post.go +++ b/infra/post.go @@ -204,25 +204,25 @@ func (p *PostRepository) Update(ctx context.Context, post *entity.Post) error { // Delete は引数で渡したIDの投稿を削除します // 投稿の所有者以外が削除する場合、削除は行われません -func (p *PostRepository) Delete(ctx context.Context, userID string, postID int) error { +func (p *PostRepository) Delete(ctx context.Context, post *entity.Post) error { select { // echoのリクエストが途切れた場合は早めにリソースを開放するために処理を中断する case <-ctx.Done(): return ctx.Err() default: // 該当するポストがあるか確認 - getPost, err := p.FindByID(ctx, postID) + getPost, err := p.FindByID(ctx, post.ID) if err != nil { return entity.NewErrorNotFound("post") } // 所有者でなければ削除処理は行わない - if getPost.UserID != userID { + if getPost.UserID != post.UserID { return entity.ErrIsNotAuthor } postDTO := &PostInsertDTO{ - ID: postID, + ID: post.ID, } if _, err := p.dbMap.Delete(postDTO); err != nil { diff --git a/repository/post.go b/repository/post.go index 4c0aa3b..cc7152f 100644 --- a/repository/post.go +++ b/repository/post.go @@ -15,5 +15,5 @@ type Post interface { FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) Insert(ctx context.Context, post *entity.Post) error Update(ctx context.Context, post *entity.Post) error - Delete(ctx context.Context, userID string, postID int) error + Delete(ctx context.Context, post *entity.Post) error } diff --git a/usecase/post.go b/usecase/post.go index 2a93a39..7106222 100644 --- a/usecase/post.go +++ b/usecase/post.go @@ -57,9 +57,9 @@ func (p *PostUsecase) Update(ctx context.Context, post *entity.Post) error { return nil } -// Delete は引数のIDをもとに投稿を削除します. -func (p *PostUsecase) Delete(ctx context.Context, userID string, postID int) error { - if err := p.postRepo.Delete(ctx, userID, postID); err != nil { +// Delete は引数のpostエンティティをもとに投稿を削除します. +func (p *PostUsecase) Delete(ctx context.Context, post *entity.Post) error { + if err := p.postRepo.Delete(ctx, post); err != nil { return fmt.Errorf("failed Update Post: %w", err) } return nil From e1b90a55d8b7217d210b8fffe7e93babad45e742 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 21:52:11 +0900 Subject: [PATCH 12/27] =?UTF-8?q?refactor(post):=20delete=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/post_test.go | 87 +++++++++++++++++++++++++++++ infra/post_test.go | 121 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) diff --git a/controller/post_test.go b/controller/post_test.go index 6a3fa1e..593dc3e 100644 --- a/controller/post_test.go +++ b/controller/post_test.go @@ -447,3 +447,90 @@ func TestPostController_Update(t *testing.T) { }) } } + +func TestPostController_Delete(t *testing.T) { + tests := []struct { + name string + userID string + postID string + prepareMockPost func(ctx context.Context, post *mock.MockPost) + wantErr bool + wantCode int + }{ + { + name: "正しく投稿を削除できる", + userID: "user-id", + postID: "1", + prepareMockPost: func(ctx context.Context, post *mock.MockPost) { + post.EXPECT().Delete(ctx, &entity.Post{ + ID: 1, + UserID: "user-id", + }).Return(nil) + }, + wantErr: false, + wantCode: 200, + }, + { + name: "存在しないポストならばErrNotFound", + userID: "user-id", + postID: "100", + prepareMockPost: func(ctx context.Context, post *mock.MockPost) { + post.EXPECT().Delete(ctx, &entity.Post{ + ID: 100, + UserID: "user-id", + }).Return(entity.NewErrorNotFound("post")) + }, + wantErr: true, + wantCode: http.StatusForbidden, + }, + { + name: "ユーザーに削除権限がないならばErrIsNotAuthor", + userID: "other-user-id", + postID: "1", + prepareMockPost: func(ctx context.Context, post *mock.MockPost) { + post.EXPECT().Delete(ctx, &entity.Post{ + ID: 1, + UserID: "other-user-id", + }).Return(entity.ErrIsNotAuthor) + }, + wantErr: true, + wantCode: http.StatusForbidden, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := echo.New() + req := httptest.NewRequest("DELETE", "/", nil) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + c.SetParamNames("postID") + c.SetParamValues(tt.postID) + c.Set("userID", tt.userID) + + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + postRepo := mock.NewMockPost(ctrl) + tt.prepareMockPost(ctx, postRepo) + userRepo := mock.NewMockUser(ctrl) + + con := NewPostController(usecase.NewPostUsecase(postRepo, userRepo)) + err := con.Delete(c) + + if (err != nil) != tt.wantErr { + t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) + } + + if he, ok := err.(*echo.HTTPError); ok { + if he.Code != tt.wantCode { + t.Errorf("code = %d, want = %d", he.Code, tt.wantCode) + } + } else { + if rec.Code != tt.wantCode { + t.Errorf("code = %d, want = %d", rec.Code, tt.wantCode) + } + } + }) + } +} diff --git a/infra/post_test.go b/infra/post_test.go index 5d023ff..cbeea34 100644 --- a/infra/post_test.go +++ b/infra/post_test.go @@ -590,3 +590,124 @@ func TestPostRepository_Update(t *testing.T) { }) } } + +func TestPostRepository_Delete(t *testing.T) { + dbMap, err := NewDB() + if err != nil { + t.Fatalf(err.Error()) + } + + dbMap.AddTableWithName(UserDTO{}, "users") + truncateTable(t, dbMap, "users") + + preparedUsers := []*UserDTO{ + { + ID: "user-id", + Name: "test user", + Profile: "test profile", + TwitterID: "twitter", + }, + { + ID: "user-id2", + Name: "test user2", + Profile: "test profile2", + TwitterID: "twitter2", + }, + } + + for _, user := range preparedUsers { + if err := dbMap.Insert(user); err != nil { + t.Fatal(err) + } + } + + dbMap.AddTableWithName(PostDTO{}, "posts").SetKeys(true, "id") + dbMap.AddTableWithName(PostInsertDTO{}, "posts").SetKeys(true, "id") + truncateTable(t, dbMap, "posts") + + validPosts := []*PostInsertDTO{ + { + ID: 1, + UserID: "user-id", + Title: "test title", + Code: "package main\n\nimport \"fmt\"\n\nfunc main(){fmt.Println(\"This is test.\")}", + Language: "Go", + Content: "Test code", + Source: "github.com", + }, + { + ID: 2, + UserID: "user-id2", + Title: "test title", + Code: "package main\n\nimport \"fmt\"\n\nfunc main(){fmt.Println(\"This is test.\")}", + Language: "Go", + Content: "Test code", + Source: "github.com", + }, + { + ID: 3, + UserID: "user-id", + Title: "test title", + Code: "package main\n\nimport \"fmt\"\n\nfunc main(){fmt.Println(\"This is test.\")}", + Language: "Go", + Content: "Test code", + Source: "github.com", + }, + } + // デフォルトの投稿追加 + for _, post := range validPosts { + if err := dbMap.Insert(post); err != nil { + t.Fatal(err) + } + } + + postRepo := NewPostRepository(dbMap) + + tests := []struct { + name string + post *entity.Post + wantErr error + }{ + { + name: "正常に削除できる", + post: &entity.Post{ + ID: 1, + UserID: "user-id", + }, + wantErr: nil, + }, + { + name: `存在しないPostならErrNotFound`, + post: &entity.Post{ + ID: 100, + UserID: "user-id", + }, + wantErr: entity.NewErrorNotFound("post"), + }, + { + name: "投稿元のユーザ以外が削除するとエラー", + post: &entity.Post{ + ID: 3, + UserID: "user-id100", + }, + wantErr: entity.ErrIsNotAuthor, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + err := postRepo.Delete(ctx, tt.post) + + if err == nil || tt.wantErr == nil { + if err == tt.wantErr { + return + } + // どちらかがnilの場合は%vを使う + t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) + } else if err.Error() != tt.wantErr.Error() { + t.Errorf("error = %s, wantErr = %s", err.Error(), tt.wantErr.Error()) + } + }) + } +} From 7a5edb9c665f19d2eb70ee8c04c5b4aa3c341409 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Fri, 26 Mar 2021 22:16:40 +0900 Subject: [PATCH 13/27] =?UTF-8?q?fix(migrations):=20FOREIGN=20KEY=E3=81=AE?= =?UTF-8?q?ON=20DELETE=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/post_test.go | 17 +---------------- migrations/20210319141439-CreatePosts.sql | 2 +- migrations/20210319143039-CreateComments.sql | 4 ++-- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/infra/post_test.go b/infra/post_test.go index cbeea34..1459e10 100644 --- a/infra/post_test.go +++ b/infra/post_test.go @@ -607,12 +607,6 @@ func TestPostRepository_Delete(t *testing.T) { Profile: "test profile", TwitterID: "twitter", }, - { - ID: "user-id2", - Name: "test user2", - Profile: "test profile2", - TwitterID: "twitter2", - }, } for _, user := range preparedUsers { @@ -637,15 +631,6 @@ func TestPostRepository_Delete(t *testing.T) { }, { ID: 2, - UserID: "user-id2", - Title: "test title", - Code: "package main\n\nimport \"fmt\"\n\nfunc main(){fmt.Println(\"This is test.\")}", - Language: "Go", - Content: "Test code", - Source: "github.com", - }, - { - ID: 3, UserID: "user-id", Title: "test title", Code: "package main\n\nimport \"fmt\"\n\nfunc main(){fmt.Println(\"This is test.\")}", @@ -687,7 +672,7 @@ func TestPostRepository_Delete(t *testing.T) { { name: "投稿元のユーザ以外が削除するとエラー", post: &entity.Post{ - ID: 3, + ID: 2, UserID: "user-id100", }, wantErr: entity.ErrIsNotAuthor, diff --git a/migrations/20210319141439-CreatePosts.sql b/migrations/20210319141439-CreatePosts.sql index a47d328..304d49d 100644 --- a/migrations/20210319141439-CreatePosts.sql +++ b/migrations/20210319141439-CreatePosts.sql @@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS posts ( source VARCHAR(2048), created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - FOREIGN KEY (user_id) REFERENCES users (id) + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); -- +migrate Down DROP TABLE IF EXISTS posts; diff --git a/migrations/20210319143039-CreateComments.sql b/migrations/20210319143039-CreateComments.sql index 83baa8f..ac95ae8 100644 --- a/migrations/20210319143039-CreateComments.sql +++ b/migrations/20210319143039-CreateComments.sql @@ -12,8 +12,8 @@ CREATE TABLE IF NOT EXISTS comments ( created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id, post_id), - FOREIGN KEY (post_id) REFERENCES posts (id), - FOREIGN KEY (user_id) REFERENCES users (id) + FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); -- +migrate Down DROP TABLE IF EXISTS comments; From 643582a678ccc069a23793e73b630120963ce049 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe <49514648+hiroyaonoe@users.noreply.github.com> Date: Fri, 26 Mar 2021 23:06:48 +0900 Subject: [PATCH 14/27] Update usecase/post.go typo Co-authored-by: Takashi MIMA --- usecase/post.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usecase/post.go b/usecase/post.go index 7106222..fe88357 100644 --- a/usecase/post.go +++ b/usecase/post.go @@ -60,7 +60,7 @@ func (p *PostUsecase) Update(ctx context.Context, post *entity.Post) error { // Delete は引数のpostエンティティをもとに投稿を削除します. func (p *PostUsecase) Delete(ctx context.Context, post *entity.Post) error { if err := p.postRepo.Delete(ctx, post); err != nil { - return fmt.Errorf("failed Update Post: %w", err) + return fmt.Errorf("failed Delete Post: %w", err) } return nil } From acb6ec39a9dadcd177076d2a5e55a8b782707d01 Mon Sep 17 00:00:00 2001 From: task4233 Date: Sat, 27 Mar 2021 00:57:47 +0900 Subject: [PATCH 15/27] =?UTF-8?q?fix:=20=E5=BF=85=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E3=81=84bind=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/user.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/controller/user.go b/controller/user.go index b6eaad3..1657769 100644 --- a/controller/user.go +++ b/controller/user.go @@ -167,19 +167,16 @@ func (ctrl *UserController) Update(c echo.Context) error { func (ctrl *UserController) Delete(c echo.Context) error { logger := log.New() - user := &entity.User{} - if err := c.Bind(user); err != nil { - return echo.NewHTTPError(http.StatusBadRequest) - } - - var ok bool - user.ID, ok = c.Get("userID").(string) + userID, ok := c.Get("userID").(string) if !ok { logger.Errorf("Failed type assertion of userID: %#v", c.Get("userID")) return echo.NewHTTPError(http.StatusInternalServerError) } - if err := ctrl.uc.Delete(c.Request().Context(), user); err != nil { + if err := ctrl.uc.Delete( + c.Request().Context(), + entity.NewUser(userID, "", "", "", ""), + ); err != nil { errEmpty := &entity.ErrEmpty{} if errors.As(err, errEmpty) { return echo.NewHTTPError(http.StatusBadRequest, errEmpty.Error()) From f12363ebde11f22898dd7e9d25f3c3a029053755 Mon Sep 17 00:00:00 2001 From: task4233 Date: Sat, 27 Mar 2021 00:58:51 +0900 Subject: [PATCH 16/27] =?UTF-8?q?fix:=20body=E3=82=92=E5=8F=97=E3=81=91?= =?UTF-8?q?=E5=8F=96=E3=82=89=E3=81=AA=E3=81=84=E3=81=AE=E3=81=A7Validatio?= =?UTF-8?q?n=E3=82=92=E6=9B=B8=E3=81=91=E3=82=8B=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E3=81=8C=E3=81=AA=E3=81=84=E3=81=9F=E3=82=81=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/infra/user.go b/infra/user.go index 15a2cfb..4931f2b 100644 --- a/infra/user.go +++ b/infra/user.go @@ -113,9 +113,6 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { case <-ctx.Done(): return ctx.Err() default: - if err := user.IsValid(); err != nil { - return err - } // 該当ユーザの存在確認 gotUser, err := r.FindByID(ctx, user.ID) if err != nil { From b1165ecb5176c80f56f716cab021b5251fb6643b Mon Sep 17 00:00:00 2001 From: task4233 Date: Sat, 27 Mar 2021 01:29:14 +0900 Subject: [PATCH 17/27] =?UTF-8?q?fix:=20=E5=BF=85=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=83=90=E3=83=AA=E3=83=87=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/infra/user.go b/infra/user.go index 4931f2b..7774228 100644 --- a/infra/user.go +++ b/infra/user.go @@ -114,19 +114,13 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { return ctx.Err() default: // 該当ユーザの存在確認 - gotUser, err := r.FindByID(ctx, user.ID) + _, err := r.FindByID(ctx, user.ID) if err != nil { return entity.NewErrorNotFound("user") } - // IDとTwitterIDはユニークなので、それらを比較する - if user.TwitterID != gotUser.TwitterID { - return entity.ErrIsNotAuthor - } - userDTO := &UserDTO{ - ID: user.ID, - TwitterID: user.TwitterID, + ID: user.ID, } if _, err := r.dbMap.Delete(userDTO); err != nil { From be2e7f49cdfc43746cacecb5c7b0258b77b44478 Mon Sep 17 00:00:00 2001 From: task4233 Date: Sat, 27 Mar 2021 01:36:03 +0900 Subject: [PATCH 18/27] =?UTF-8?q?fix:=20=E3=83=90=E3=83=AA=E3=83=87?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E5=89=8A=E9=99=A4=E3=81=AB?= =?UTF-8?q?=E5=BF=9C=E3=81=98=E3=81=A6=E5=BF=85=E8=A6=81=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/infra/user_test.go b/infra/user_test.go index 0568488..0cf597c 100644 --- a/infra/user_test.go +++ b/infra/user_test.go @@ -221,17 +221,12 @@ func TestUserRepository_Delete(t *testing.T) { }{ { name: "ユーザーIDが存在しないならErrNotFound", - user: entity.NewUser("new-id", "existingUser", "existing", "existing", ""), + user: entity.NewUser("new-id", "", "", "", ""), wantErr: entity.NewErrorNotFound("user"), }, - { - name: "ユーザIDとTwitterIDが合致指定ない場合、削除せずに終わる", - user: entity.NewUser("existing-id", "existingUser", "existing", "existing2", ""), - wantErr: entity.ErrIsNotAuthor, - }, { name: "正しくユーザーを削除できる", - user: entity.NewUser("existing-id", "existingUser", "existing", "existing", ""), + user: entity.NewUser("existing-id", "", "", "", ""), wantErr: nil, }, } From d5bba343a8fb6a6f11a760f47079f83deab06fd9 Mon Sep 17 00:00:00 2001 From: task4233 Date: Sat, 27 Mar 2021 23:39:24 +0900 Subject: [PATCH 19/27] =?UTF-8?q?feat:=20transaction.go=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 ++ infra/transaction.go | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 infra/transaction.go diff --git a/go.mod b/go.mod index d48ef6d..fe3419e 100644 --- a/go.mod +++ b/go.mod @@ -29,5 +29,6 @@ require ( google.golang.org/api v0.43.0 google.golang.org/genproto v0.0.0-20210324141432-3032e8ff099e // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/gorp.v1 v1.7.2 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index a089f8e..cf05b71 100644 --- a/go.sum +++ b/go.sum @@ -647,6 +647,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/infra/transaction.go b/infra/transaction.go new file mode 100644 index 0000000..f523bad --- /dev/null +++ b/infra/transaction.go @@ -0,0 +1,20 @@ +package infra + +import ( + "context" + + "github.com/go-gorp/gorp" +) + +// ref: https://qiita.com/miya-masa/items/316256924a1f0d7374bb#%E8%A7%A3%E6%B1%BA%E6%A1%88%EF%BC%92-%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AB%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%81%99%E3%82%8B +var txKey = struct{}{} + +// TransactionDAO はTransactionに関するDataAccessObjectです +type TransactionDAO interface { +} + +// getTx はcontextからトランザクションを取得する +func getTx(ctx context.Context) (TransactionDAO, bool) { + tx, ok := ctx.Value(&txKey).(*gorp.Transaction) + return tx, ok +} From f72b5f962f4dbe6dd98cbc72becdfa7c0cfc894c Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 21:42:46 +0900 Subject: [PATCH 20/27] =?UTF-8?q?feat:=20=E3=83=88=E3=83=A9=E3=83=B3?= =?UTF-8?q?=E3=82=B6=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E3=81=99=E3=82=8B=E5=BF=85=E8=A6=81=E3=81=8C=E3=81=82?= =?UTF-8?q?=E3=82=8B=E3=81=9F=E3=82=81=E3=80=81=E7=AE=A1=E7=90=86=E3=81=99?= =?UTF-8?q?=E3=82=8B=E6=A7=8B=E9=80=A0=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/transaction.go | 5 ++++- infra/user.go | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/infra/transaction.go b/infra/transaction.go index f523bad..ae12fdf 100644 --- a/infra/transaction.go +++ b/infra/transaction.go @@ -6,11 +6,14 @@ import ( "github.com/go-gorp/gorp" ) -// ref: https://qiita.com/miya-masa/items/316256924a1f0d7374bb#%E8%A7%A3%E6%B1%BA%E6%A1%88%EF%BC%92-%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AB%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%81%99%E3%82%8B +// ref: https://qiita.com/miya-masa/items/316256924a1f0d7374bb var txKey = struct{}{} // TransactionDAO はTransactionに関するDataAccessObjectです +// gorp.dbMapで利用するメソッドをここにインタフェースとして追加しておきます type TransactionDAO interface { + // ref: https://pkg.go.dev/github.com/go-gorp/gorp#DbMap.Delete + Delete(list ...interface{}) (int64, error) } // getTx はcontextからトランザクションを取得する diff --git a/infra/user.go b/infra/user.go index 7774228..af06c5a 100644 --- a/infra/user.go +++ b/infra/user.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "errors" + "fmt" "strings" "github.com/VividCortex/mysqlerr" @@ -113,6 +114,7 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { case <-ctx.Done(): return ctx.Err() default: + // ユーザの存在確認は参照のみなのでトランザクションには入れない // 該当ユーザの存在確認 _, err := r.FindByID(ctx, user.ID) if err != nil { @@ -123,13 +125,44 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { ID: user.ID, } - if _, err := r.dbMap.Delete(userDTO); err != nil { + // トランザクションオブジェクトをctxから取得する + dao, ok := getTx(ctx) + if !ok { + // 見つからなかったら、dbMapをそのまま設定する + dao = r.dbMap + } + if _, err := dao.Delete(userDTO); err != nil { return err } + return nil } } +// DoInTx はトランザクションの中でDBにアクセスするためのラッパー関数です +func (r *UserRepository) DoInTx(ctx context.Context, f func(ctx context.Context) (interface{}, error)) (interface{}, error) { + tx, err := r.dbMap.Begin() + if err != nil { + return nil, fmt.Errorf("failed dbMap.Begin(): %w", err) + } + + // トランザクションをctxに埋め込む + ctx = context.WithValue(ctx, &txKey, tx) + // 中身の処理を実行する + v, err := f(ctx) + if err != nil { + _ = tx.Rollback() + return v, fmt.Errorf("rollbacked: %w", err) + } + + // コミット時に失敗してもロールバック + if err := tx.Commit(); err != nil { + _ = tx.Rollback() + return v, fmt.Errorf("failed to commit: rollbacked: %w", err) + } + return v, nil +} + // UserDTO はDBとやり取りするためのDataTransferObject type UserDTO struct { ID string `db:"id"` From b877b0d7ec77fc2b95aac5014cde0cd003d4011f Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 21:47:02 +0900 Subject: [PATCH 21/27] =?UTF-8?q?feat:=20usecase=E3=81=A7DoInTx=E3=82=92?= =?UTF-8?q?=E5=88=A9=E7=94=A8=E3=81=99=E3=82=8B=E5=BF=85=E8=A6=81=E3=81=8C?= =?UTF-8?q?=E3=81=82=E3=82=8B=E3=81=9F=E3=82=81=E3=80=81repository?= =?UTF-8?q?=E3=81=A8mock=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/mock/mock_auth.go | 44 +++++++-------- infra/mock/mock_comment.go | 86 +++++++++++++---------------- infra/mock/mock_post.go | 110 ++++++++++++++++--------------------- infra/mock/mock_user.go | 71 +++++++++++++----------- repository/user.go | 1 + 5 files changed, 143 insertions(+), 169 deletions(-) diff --git a/infra/mock/mock_auth.go b/infra/mock/mock_auth.go index 62f9e23..074c9b7 100644 --- a/infra/mock/mock_auth.go +++ b/infra/mock/mock_auth.go @@ -1,65 +1,59 @@ // Code generated by MockGen. DO NOT EDIT. // Source: auth.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" + reflect "reflect" ) -// MockAuth is a mock of Auth interface. +// MockAuth is a mock of Auth interface type MockAuth struct { ctrl *gomock.Controller recorder *MockAuthMockRecorder } -// MockAuthMockRecorder is the mock recorder for MockAuth. +// MockAuthMockRecorder is the mock recorder for MockAuth type MockAuthMockRecorder struct { mock *MockAuth } -// NewMockAuth creates a new mock instance. +// NewMockAuth creates a new mock instance func NewMockAuth(ctrl *gomock.Controller) *MockAuth { mock := &MockAuth{ctrl: ctrl} mock.recorder = &MockAuthMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAuth) EXPECT() *MockAuthMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockAuth) EXPECT() *MockAuthMockRecorder { + return _m.recorder } -// Authenticate mocks base method. -func (m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Authenticate", ctx, token) +// Authenticate mocks base method +func (_m *MockAuth) Authenticate(ctx context.Context, token string) (string, error) { + ret := _m.ctrl.Call(_m, "Authenticate", ctx, token) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// Authenticate indicates an expected call of Authenticate. -func (mr *MockAuthMockRecorder) Authenticate(ctx, token interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), ctx, token) +// Authenticate indicates an expected call of Authenticate +func (_mr *MockAuthMockRecorder) Authenticate(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Authenticate", reflect.TypeOf((*MockAuth)(nil).Authenticate), arg0, arg1) } -// GetIconURL mocks base method. -func (m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetIconURL", ctx, uid) +// GetIconURL mocks base method +func (_m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) { + ret := _m.ctrl.Call(_m, "GetIconURL", ctx, uid) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetIconURL indicates an expected call of GetIconURL. -func (mr *MockAuthMockRecorder) GetIconURL(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), ctx, uid) +// GetIconURL indicates an expected call of GetIconURL +func (_mr *MockAuthMockRecorder) GetIconURL(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), arg0, arg1) } diff --git a/infra/mock/mock_comment.go b/infra/mock/mock_comment.go index 662958a..0faeb1e 100644 --- a/infra/mock/mock_comment.go +++ b/infra/mock/mock_comment.go @@ -1,111 +1,99 @@ // Code generated by MockGen. DO NOT EDIT. // Source: comment.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockComment is a mock of Comment interface. +// MockComment is a mock of Comment interface type MockComment struct { ctrl *gomock.Controller recorder *MockCommentMockRecorder } -// MockCommentMockRecorder is the mock recorder for MockComment. +// MockCommentMockRecorder is the mock recorder for MockComment type MockCommentMockRecorder struct { mock *MockComment } -// NewMockComment creates a new mock instance. +// NewMockComment creates a new mock instance func NewMockComment(ctrl *gomock.Controller) *MockComment { mock := &MockComment{ctrl: ctrl} mock.recorder = &MockCommentMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockComment) EXPECT() *MockCommentMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockComment) EXPECT() *MockCommentMockRecorder { + return _m.recorder } -// FindByID mocks base method. -func (m *MockComment) FindByID(ctx context.Context, postID, commentID int) (*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, postID, commentID) +// FindByID mocks base method +func (_m *MockComment) FindByID(ctx context.Context, postID int, commentID int) (*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, postID, commentID) ret0, _ := ret[0].(*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockCommentMockRecorder) FindByID(ctx, postID, commentID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), ctx, postID, commentID) +// FindByID indicates an expected call of FindByID +func (_mr *MockCommentMockRecorder) FindByID(arg0, arg1, arg2 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockComment)(nil).FindByID), arg0, arg1, arg2) } -// FindByPostID mocks base method. -func (m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByPostID", ctx, postID) +// FindByUserID mocks base method +func (_m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByPostID indicates an expected call of FindByPostID. -func (mr *MockCommentMockRecorder) FindByPostID(ctx, postID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), ctx, postID) +// FindByUserID indicates an expected call of FindByUserID +func (_mr *MockCommentMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), arg0, arg1) } -// FindByUserID mocks base method. -func (m *MockComment) FindByUserID(ctx context.Context, uid string) ([]*entity.Comment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) +// FindByPostID mocks base method +func (_m *MockComment) FindByPostID(ctx context.Context, postID int) ([]*entity.Comment, error) { + ret := _m.ctrl.Call(_m, "FindByPostID", ctx, postID) ret0, _ := ret[0].([]*entity.Comment) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID. -func (mr *MockCommentMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockComment)(nil).FindByUserID), ctx, uid) +// FindByPostID indicates an expected call of FindByPostID +func (_mr *MockCommentMockRecorder) FindByPostID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByPostID", reflect.TypeOf((*MockComment)(nil).FindByPostID), arg0, arg1) } -// Insert mocks base method. -func (m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, comment) +// Insert mocks base method +func (_m *MockComment) Insert(ctx context.Context, comment *entity.Comment) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockCommentMockRecorder) Insert(ctx, comment interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), ctx, comment) +// Insert indicates an expected call of Insert +func (_mr *MockCommentMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockComment)(nil).Insert), arg0, arg1) } -// Update mocks base method. -func (m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, comment) +// Update mocks base method +func (_m *MockComment) Update(ctx context.Context, comment *entity.Comment) error { + ret := _m.ctrl.Call(_m, "Update", ctx, comment) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockCommentMockRecorder) Update(ctx, comment interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), ctx, comment) +// Update indicates an expected call of Update +func (_mr *MockCommentMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockComment)(nil).Update), arg0, arg1) } // Delete mocks base method diff --git a/infra/mock/mock_post.go b/infra/mock/mock_post.go index bd4fe8f..24ade8e 100644 --- a/infra/mock/mock_post.go +++ b/infra/mock/mock_post.go @@ -1,123 +1,109 @@ // Code generated by MockGen. DO NOT EDIT. // Source: post.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockPost is a mock of Post interface. +// MockPost is a mock of Post interface type MockPost struct { ctrl *gomock.Controller recorder *MockPostMockRecorder } -// MockPostMockRecorder is the mock recorder for MockPost. +// MockPostMockRecorder is the mock recorder for MockPost type MockPostMockRecorder struct { mock *MockPost } -// NewMockPost creates a new mock instance. +// NewMockPost creates a new mock instance func NewMockPost(ctrl *gomock.Controller) *MockPost { mock := &MockPost{ctrl: ctrl} mock.recorder = &MockPostMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPost) EXPECT() *MockPostMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockPost) EXPECT() *MockPostMockRecorder { + return _m.recorder } -// Delete mocks base method. -func (m *MockPost) Delete(ctx context.Context, post *entity.Post) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", ctx, post) - ret0, _ := ret[0].(error) - return ret0 +// GetAll mocks base method +func (_m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { + ret := _m.ctrl.Call(_m, "GetAll", ctx) + ret0, _ := ret[0].([]*entity.Post) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// Delete indicates an expected call of Delete. -func (mr *MockPostMockRecorder) Delete(ctx, post interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPost)(nil).Delete), ctx, post) +// GetAll indicates an expected call of GetAll +func (_mr *MockPostMockRecorder) GetAll(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), arg0) } -// FindByID mocks base method. -func (m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, postID) +// FindByID mocks base method +func (_m *MockPost) FindByID(ctx context.Context, postID int) (*entity.Post, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, postID) ret0, _ := ret[0].(*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockPostMockRecorder) FindByID(ctx, postID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), ctx, postID) +// FindByID indicates an expected call of FindByID +func (_mr *MockPostMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockPost)(nil).FindByID), arg0, arg1) } -// FindByUserID mocks base method. -func (m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByUserID", ctx, uid) +// FindByUserID mocks base method +func (_m *MockPost) FindByUserID(ctx context.Context, uid string) ([]*entity.Post, error) { + ret := _m.ctrl.Call(_m, "FindByUserID", ctx, uid) ret0, _ := ret[0].([]*entity.Post) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByUserID indicates an expected call of FindByUserID. -func (mr *MockPostMockRecorder) FindByUserID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), ctx, uid) +// FindByUserID indicates an expected call of FindByUserID +func (_mr *MockPostMockRecorder) FindByUserID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByUserID", reflect.TypeOf((*MockPost)(nil).FindByUserID), arg0, arg1) } -// GetAll mocks base method. -func (m *MockPost) GetAll(ctx context.Context) ([]*entity.Post, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAll", ctx) - ret0, _ := ret[0].([]*entity.Post) - ret1, _ := ret[1].(error) - return ret0, ret1 +// Insert mocks base method +func (_m *MockPost) Insert(ctx context.Context, post *entity.Post) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, post) + ret0, _ := ret[0].(error) + return ret0 } -// GetAll indicates an expected call of GetAll. -func (mr *MockPostMockRecorder) GetAll(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockPost)(nil).GetAll), ctx) +// Insert indicates an expected call of Insert +func (_mr *MockPostMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), arg0, arg1) } -// Insert mocks base method. -func (m *MockPost) Insert(ctx context.Context, post *entity.Post) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, post) +// Update mocks base method +func (_m *MockPost) Update(ctx context.Context, post *entity.Post) error { + ret := _m.ctrl.Call(_m, "Update", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockPostMockRecorder) Insert(ctx, post interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockPost)(nil).Insert), ctx, post) +// Update indicates an expected call of Update +func (_mr *MockPostMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), arg0, arg1) } -// Update mocks base method. -func (m *MockPost) Update(ctx context.Context, post *entity.Post) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, post) +// Delete mocks base method +func (_m *MockPost) Delete(ctx context.Context, post *entity.Post) error { + ret := _m.ctrl.Call(_m, "Delete", ctx, post) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockPostMockRecorder) Update(ctx, post interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockPost)(nil).Update), ctx, post) +// Delete indicates an expected call of Delete +func (_mr *MockPostMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Delete", reflect.TypeOf((*MockPost)(nil).Delete), arg0, arg1) } diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index c3b1500..dc5a1d7 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -1,81 +1,73 @@ // Code generated by MockGen. DO NOT EDIT. // Source: user.go -// Package mock is a generated GoMock package. package mock import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" + reflect "reflect" ) -// MockUser is a mock of User interface. +// MockUser is a mock of User interface type MockUser struct { ctrl *gomock.Controller recorder *MockUserMockRecorder } -// MockUserMockRecorder is the mock recorder for MockUser. +// MockUserMockRecorder is the mock recorder for MockUser type MockUserMockRecorder struct { mock *MockUser } -// NewMockUser creates a new mock instance. +// NewMockUser creates a new mock instance func NewMockUser(ctrl *gomock.Controller) *MockUser { mock := &MockUser{ctrl: ctrl} mock.recorder = &MockUserMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUser) EXPECT() *MockUserMockRecorder { - return m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *MockUser) EXPECT() *MockUserMockRecorder { + return _m.recorder } -// FindByID mocks base method. -func (m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindByID", ctx, uid) +// FindByID mocks base method +func (_m *MockUser) FindByID(ctx context.Context, uid string) (*entity.User, error) { + ret := _m.ctrl.Call(_m, "FindByID", ctx, uid) ret0, _ := ret[0].(*entity.User) ret1, _ := ret[1].(error) return ret0, ret1 } -// FindByID indicates an expected call of FindByID. -func (mr *MockUserMockRecorder) FindByID(ctx, uid interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), ctx, uid) +// FindByID indicates an expected call of FindByID +func (_mr *MockUserMockRecorder) FindByID(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "FindByID", reflect.TypeOf((*MockUser)(nil).FindByID), arg0, arg1) } -// Insert mocks base method. -func (m *MockUser) Insert(ctx context.Context, user *entity.User) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Insert", ctx, user) +// Insert mocks base method +func (_m *MockUser) Insert(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Insert", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Insert indicates an expected call of Insert. -func (mr *MockUserMockRecorder) Insert(ctx, user interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), ctx, user) +// Insert indicates an expected call of Insert +func (_mr *MockUserMockRecorder) Insert(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Insert", reflect.TypeOf((*MockUser)(nil).Insert), arg0, arg1) } -// Update mocks base method. -func (m *MockUser) Update(ctx context.Context, user *entity.User) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, user) +// Update mocks base method +func (_m *MockUser) Update(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Update", ctx, user) ret0, _ := ret[0].(error) return ret0 } -// Update indicates an expected call of Update. -func (mr *MockUserMockRecorder) Update(ctx, user interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), ctx, user) +// Update indicates an expected call of Update +func (_mr *MockUserMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Update", reflect.TypeOf((*MockUser)(nil).Update), arg0, arg1) } // Delete mocks base method @@ -89,3 +81,16 @@ func (_m *MockUser) Delete(ctx context.Context, user *entity.User) error { func (_mr *MockUserMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Delete", reflect.TypeOf((*MockUser)(nil).Delete), arg0, arg1) } + +// DoInTx mocks base method +func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context) (interface{}, error)) (interface{}, error) { + ret := _m.ctrl.Call(_m, "DoInTx", ctx, f) + ret0, _ := ret[0].(interface{}) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DoInTx indicates an expected call of DoInTx +func (_mr *MockUserMockRecorder) DoInTx(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "DoInTx", reflect.TypeOf((*MockUser)(nil).DoInTx), arg0, arg1) +} diff --git a/repository/user.go b/repository/user.go index 2ca8d94..16a120e 100644 --- a/repository/user.go +++ b/repository/user.go @@ -14,4 +14,5 @@ type User interface { Insert(ctx context.Context, user *entity.User) error Update(ctx context.Context, user *entity.User) error Delete(ctx context.Context, user *entity.User) error + DoInTx(ctx context.Context, f func(ctx context.Context) (interface{}, error)) (interface{}, error) } From 8f9d51afd976485c2eb1630951469f54d1fd89f2 Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 21:52:40 +0900 Subject: [PATCH 22/27] =?UTF-8?q?fix:=20DoInTx=E3=81=AE=E8=BF=94=E3=82=8A?= =?UTF-8?q?=E5=80=A4=E8=A8=AD=E8=A8=88=E3=81=8C=E8=AA=A4=E3=81=A3=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=9F=E3=81=9F=E3=82=81=E3=80=81=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/mock/mock_user.go | 7 +++---- infra/transaction.go | 3 ++- infra/user.go | 14 +++++++------- repository/user.go | 4 +++- usecase/user.go | 1 + 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index dc5a1d7..2bcad6c 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -83,11 +83,10 @@ func (_mr *MockUserMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { } // DoInTx mocks base method -func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context) (interface{}, error)) (interface{}, error) { +func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context) error) error { ret := _m.ctrl.Call(_m, "DoInTx", ctx, f) - ret0, _ := ret[0].(interface{}) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret0, _ := ret[0].(error) + return ret0 } // DoInTx indicates an expected call of DoInTx diff --git a/infra/transaction.go b/infra/transaction.go index ae12fdf..7b0b04d 100644 --- a/infra/transaction.go +++ b/infra/transaction.go @@ -10,7 +10,8 @@ import ( var txKey = struct{}{} // TransactionDAO はTransactionに関するDataAccessObjectです -// gorp.dbMapで利用するメソッドをここにインタフェースとして追加しておきます +// gorp.dbMapで利用するメソッドをここにインタフェースとして定義することで、 +// infraではgorpに依存しないような設計となっています type TransactionDAO interface { // ref: https://pkg.go.dev/github.com/go-gorp/gorp#DbMap.Delete Delete(list ...interface{}) (int64, error) diff --git a/infra/user.go b/infra/user.go index af06c5a..d6ee613 100644 --- a/infra/user.go +++ b/infra/user.go @@ -139,28 +139,28 @@ func (r *UserRepository) Delete(ctx context.Context, user *entity.User) error { } } -// DoInTx はトランザクションの中でDBにアクセスするためのラッパー関数です -func (r *UserRepository) DoInTx(ctx context.Context, f func(ctx context.Context) (interface{}, error)) (interface{}, error) { +// DoInTx はUserRepository内でトランザクションの中でDBにアクセスするためのラッパー関数です +func (r *UserRepository) DoInTx(ctx context.Context, f func(ctx context.Context) error) error { tx, err := r.dbMap.Begin() if err != nil { - return nil, fmt.Errorf("failed dbMap.Begin(): %w", err) + return fmt.Errorf("failed dbMap.Begin(): %w", err) } // トランザクションをctxに埋め込む ctx = context.WithValue(ctx, &txKey, tx) // 中身の処理を実行する - v, err := f(ctx) + err := f(ctx) if err != nil { _ = tx.Rollback() - return v, fmt.Errorf("rollbacked: %w", err) + return fmt.Errorf("rollbacked: %w", err) } // コミット時に失敗してもロールバック if err := tx.Commit(); err != nil { _ = tx.Rollback() - return v, fmt.Errorf("failed to commit: rollbacked: %w", err) + return fmt.Errorf("failed to commit: rollbacked: %w", err) } - return v, nil + return nil } // UserDTO はDBとやり取りするためのDataTransferObject diff --git a/repository/user.go b/repository/user.go index 16a120e..1ffa0ec 100644 --- a/repository/user.go +++ b/repository/user.go @@ -14,5 +14,7 @@ type User interface { Insert(ctx context.Context, user *entity.User) error Update(ctx context.Context, user *entity.User) error Delete(ctx context.Context, user *entity.User) error - DoInTx(ctx context.Context, f func(ctx context.Context) (interface{}, error)) (interface{}, error) + // FindByIDのときは返り値を持ってしまうので、全体のinfraのrepositoryを管理する + // 親みたいなものがあるとよかったかもしれない + DoInTx(ctx context.Context, f func(ctx context.Context) error) error } diff --git a/usecase/user.go b/usecase/user.go index ee44acb..dec34b0 100644 --- a/usecase/user.go +++ b/usecase/user.go @@ -91,6 +91,7 @@ func (u *UserUseCase) Update(ctx context.Context, user *entity.User) error { // Delete は引数のuserエンティティをもとにユーザを削除します func (u *UserUseCase) Delete(ctx context.Context, user *entity.User) error { + u.userRepo.DoInTx(ctx, u.userRepo.Delete(ctx, user)) if err := u.userRepo.Delete(ctx, user); err != nil { return fmt.Errorf("failed Delete user: %w", err) } From 1366d3188148be0f6b7b9890277a9e7876514f0a Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 22:09:52 +0900 Subject: [PATCH 23/27] =?UTF-8?q?feat:=20firebase.Delete=E3=82=92auth?= =?UTF-8?q?=E3=81=AB=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/auth.go | 9 +++++++++ infra/mock/mock_auth.go | 13 +++++++++++++ infra/mock/mock_user.go | 2 +- repository/auth.go | 7 ++++++- repository/user.go | 2 +- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/infra/auth.go b/infra/auth.go index cef1661..acf8a79 100644 --- a/infra/auth.go +++ b/infra/auth.go @@ -5,6 +5,7 @@ import ( "fmt" "firebase.google.com/go/auth" + "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" ) // AuthRepository は認証情報の永続化と再構成のためのリポジトリです @@ -36,3 +37,11 @@ func (a *AuthRepository) GetIconURL(ctx context.Context, uid string) (iconURL st iconURL = user.PhotoURL return } + +// Delete はuserIDからuserを削除します +func (a *AuthRepository) Delete(ctx context.Context, user *entity.User) error { + if err := a.firebase.DeleteUser(ctx, user.ID); err != nil { + return fmt.Errorf("failed firebase.DeleteUser: %w", err) + } + return nil +} diff --git a/infra/mock/mock_auth.go b/infra/mock/mock_auth.go index 074c9b7..bc12303 100644 --- a/infra/mock/mock_auth.go +++ b/infra/mock/mock_auth.go @@ -6,6 +6,7 @@ package mock import ( context "context" gomock "github.com/golang/mock/gomock" + entity "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" reflect "reflect" ) @@ -57,3 +58,15 @@ func (_m *MockAuth) GetIconURL(ctx context.Context, uid string) (string, error) func (_mr *MockAuthMockRecorder) GetIconURL(arg0, arg1 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetIconURL", reflect.TypeOf((*MockAuth)(nil).GetIconURL), arg0, arg1) } + +// Delete mocks base method +func (_m *MockAuth) Delete(ctx context.Context, user *entity.User) error { + ret := _m.ctrl.Call(_m, "Delete", ctx, user) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete +func (_mr *MockAuthMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Delete", reflect.TypeOf((*MockAuth)(nil).Delete), arg0, arg1) +} diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index 2bcad6c..bc3b920 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -83,7 +83,7 @@ func (_mr *MockUserMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { } // DoInTx mocks base method -func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context) error) error { +func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context, *entity.User) error) error { ret := _m.ctrl.Call(_m, "DoInTx", ctx, f) ret0, _ := ret[0].(error) return ret0 diff --git a/repository/auth.go b/repository/auth.go index c4acfdb..e78b703 100644 --- a/repository/auth.go +++ b/repository/auth.go @@ -2,10 +2,15 @@ package repository -import "context" +import ( + "context" + + "github.com/openhacku-saboten/OmnisCode-backend/domain/entity" +) // Auth はFirebase Authentication関連の操作を表すインターフェース type Auth interface { Authenticate(ctx context.Context, token string) (uid string, err error) GetIconURL(ctx context.Context, uid string) (iconURL string, err error) + Delete(ctx context.Context, user *entity.User) error } diff --git a/repository/user.go b/repository/user.go index 1ffa0ec..c4d61f7 100644 --- a/repository/user.go +++ b/repository/user.go @@ -16,5 +16,5 @@ type User interface { Delete(ctx context.Context, user *entity.User) error // FindByIDのときは返り値を持ってしまうので、全体のinfraのrepositoryを管理する // 親みたいなものがあるとよかったかもしれない - DoInTx(ctx context.Context, f func(ctx context.Context) error) error + DoInTx(ctx context.Context, f func(ctx context.Context, user *entity.User) error) error } From 11a3c11e316a28808287ad7e8f31fb19be36e8e8 Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 22:17:51 +0900 Subject: [PATCH 24/27] =?UTF-8?q?feat:=20transaction=E3=82=92=E6=84=8F?= =?UTF-8?q?=E8=AD=98=E3=81=97=E3=81=9F=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89?= =?UTF-8?q?=E3=82=92usecase=E5=B1=A4=E3=81=AB=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usecase/user.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/usecase/user.go b/usecase/user.go index dec34b0..66eceed 100644 --- a/usecase/user.go +++ b/usecase/user.go @@ -91,9 +91,23 @@ func (u *UserUseCase) Update(ctx context.Context, user *entity.User) error { // Delete は引数のuserエンティティをもとにユーザを削除します func (u *UserUseCase) Delete(ctx context.Context, user *entity.User) error { - u.userRepo.DoInTx(ctx, u.userRepo.Delete(ctx, user)) - if err := u.userRepo.Delete(ctx, user); err != nil { - return fmt.Errorf("failed Delete user: %w", err) + if err := u.userRepo.DoInTx(ctx, u.deleteFlow(ctx, user)); err != nil { + return fmt.Errorf("failed userRepo.DoInTx: %w", err) } return nil } + +func (u *UserUseCase) deleteFlow(ctx context.Context, user *entity.User) func(context.Context, *entity.User) error { + return func(ctx context.Context, user *entity.User) error { + // DBから削除 + if err := u.userRepo.Delete(ctx, user); err != nil { + return fmt.Errorf("failed Delete user in DB: %w", err) + } + + // Firebaseから削除 + if err := u.authRepo.Delete(ctx, user); err != nil { + return fmt.Errorf("failed Delete user in firebase: %w", err) + } + return nil + } +} From 091edda9916327ba50c61aad3d59ed58eaf3652d Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 22:27:52 +0900 Subject: [PATCH 25/27] =?UTF-8?q?fix:=20DoInTx=E3=81=AB=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E3=81=AE=E3=81=AA=E3=81=84=E8=A6=81=E7=B4=A0=E3=82=92=E6=8C=81?= =?UTF-8?q?=E3=81=9F=E3=81=9B=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/mock/mock_user.go | 2 +- infra/user.go | 2 +- repository/user.go | 2 +- usecase/user.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/infra/mock/mock_user.go b/infra/mock/mock_user.go index bc3b920..2bcad6c 100644 --- a/infra/mock/mock_user.go +++ b/infra/mock/mock_user.go @@ -83,7 +83,7 @@ func (_mr *MockUserMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { } // DoInTx mocks base method -func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context, *entity.User) error) error { +func (_m *MockUser) DoInTx(ctx context.Context, f func(context.Context) error) error { ret := _m.ctrl.Call(_m, "DoInTx", ctx, f) ret0, _ := ret[0].(error) return ret0 diff --git a/infra/user.go b/infra/user.go index d6ee613..ab67ff3 100644 --- a/infra/user.go +++ b/infra/user.go @@ -149,7 +149,7 @@ func (r *UserRepository) DoInTx(ctx context.Context, f func(ctx context.Context) // トランザクションをctxに埋め込む ctx = context.WithValue(ctx, &txKey, tx) // 中身の処理を実行する - err := f(ctx) + err = f(ctx) if err != nil { _ = tx.Rollback() return fmt.Errorf("rollbacked: %w", err) diff --git a/repository/user.go b/repository/user.go index c4d61f7..1ffa0ec 100644 --- a/repository/user.go +++ b/repository/user.go @@ -16,5 +16,5 @@ type User interface { Delete(ctx context.Context, user *entity.User) error // FindByIDのときは返り値を持ってしまうので、全体のinfraのrepositoryを管理する // 親みたいなものがあるとよかったかもしれない - DoInTx(ctx context.Context, f func(ctx context.Context, user *entity.User) error) error + DoInTx(ctx context.Context, f func(ctx context.Context) error) error } diff --git a/usecase/user.go b/usecase/user.go index 66eceed..dd4d8dd 100644 --- a/usecase/user.go +++ b/usecase/user.go @@ -97,8 +97,8 @@ func (u *UserUseCase) Delete(ctx context.Context, user *entity.User) error { return nil } -func (u *UserUseCase) deleteFlow(ctx context.Context, user *entity.User) func(context.Context, *entity.User) error { - return func(ctx context.Context, user *entity.User) error { +func (u *UserUseCase) deleteFlow(ctx context.Context, user *entity.User) func(context.Context) error { + return func(ctx context.Context) error { // DBから削除 if err := u.userRepo.Delete(ctx, user); err != nil { return fmt.Errorf("failed Delete user in DB: %w", err) From c64ee4f648d1e35ab4d36b08e1e120b4f56637e6 Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 22:31:43 +0900 Subject: [PATCH 26/27] =?UTF-8?q?remove:=20firebase=E3=81=8C=E9=96=A2?= =?UTF-8?q?=E3=82=8F=E3=81=A3=E3=81=A6=E3=81=84=E3=82=8B=E3=81=AE=E3=81=A7?= =?UTF-8?q?controller=E3=81=AEdelete=E3=82=92=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/user_test.go | 85 ----------------------------------------- 1 file changed, 85 deletions(-) diff --git a/controller/user_test.go b/controller/user_test.go index c6c9cfd..815f155 100644 --- a/controller/user_test.go +++ b/controller/user_test.go @@ -656,88 +656,3 @@ func TestUserController_Update(t *testing.T) { }) } } - -func TestUserController_Delete(t *testing.T) { - tests := []struct { - name string - userID string - prepareMockUser func(user *mock.MockUser) - prepareMockAuth func(auth *mock.MockAuth) - wantErr bool - wantCode int - }{ - { - name: "正しくユーザーを削除できる", - userID: "user-id", - prepareMockUser: func(user *mock.MockUser) { - user.EXPECT().Delete( - gomock.Any(), - entity.NewUser("user-id", "", "", "", ""), - ).Return(nil) - }, - wantErr: false, - wantCode: 200, - }, - { - name: "存在しないユーザーIDならErrNewErrorNotFound", - userID: "invalid-user-id", - prepareMockUser: func(user *mock.MockUser) { - user.EXPECT().Delete( - gomock.Any(), - entity.NewUser("invalid-user-id", "", "", "", ""), - ).Return(entity.NewErrorNotFound("user")) - }, - prepareMockAuth: func(auth *mock.MockAuth) {}, - wantErr: true, - wantCode: 404, - }, - { - name: "別のユーザが削除しようとしているならErrIsNotAuthorでStatusForbidden", - userID: "user-id2", - prepareMockUser: func(user *mock.MockUser) { - user.EXPECT().Delete( - gomock.Any(), - entity.NewUser("user-id2", "", "", "", ""), - ).Return(entity.ErrIsNotAuthor) - }, - wantErr: true, - wantCode: http.StatusForbidden, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - e := echo.New() - req := httptest.NewRequest("DELETE", "/", nil) - req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - c.Set("userID", tt.userID) - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - userRepo := mock.NewMockUser(ctrl) - tt.prepareMockUser(userRepo) - authRepo := mock.NewMockAuth(ctrl) - postRepo := mock.NewMockPost(ctrl) - commentRepo := mock.NewMockComment(ctrl) - - con := NewUserController(usecase.NewUserUseCase(userRepo, authRepo, postRepo, commentRepo)) - err := con.Delete(c) - - if (err != nil) != tt.wantErr { - t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) - } - - if he, ok := err.(*echo.HTTPError); ok { - if he.Code != tt.wantCode { - t.Errorf("code = %d, want = %d", he.Code, tt.wantCode) - } - } else { - if rec.Code != tt.wantCode { - t.Errorf("code = %d, want = %d", rec.Code, tt.wantCode) - } - } - }) - } -} From a9d6fb8009186f68d1c6f116aae403360985278a Mon Sep 17 00:00:00 2001 From: task4233 Date: Mon, 29 Mar 2021 23:16:11 +0900 Subject: [PATCH 27/27] =?UTF-8?q?fix:=20golint=E3=81=AB=E5=BE=93=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=80=81=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0=E3=81=97=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E9=83=A8=E5=88=86=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/user.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/infra/user.go b/infra/user.go index ab67ff3..18ddd8a 100644 --- a/infra/user.go +++ b/infra/user.go @@ -151,13 +151,17 @@ func (r *UserRepository) DoInTx(ctx context.Context, f func(ctx context.Context) // 中身の処理を実行する err = f(ctx) if err != nil { - _ = tx.Rollback() + if errRollback := tx.Rollback(); errRollback != nil { + return fmt.Errorf("failed rollback: %w", err) + } return fmt.Errorf("rollbacked: %w", err) } // コミット時に失敗してもロールバック if err := tx.Commit(); err != nil { - _ = tx.Rollback() + if errRollback := tx.Rollback(); errRollback != nil { + return fmt.Errorf("failed rollback: %w", err) + } return fmt.Errorf("failed to commit: rollbacked: %w", err) } return nil