From 56b489dcee92b6b05b96ec721f532fb41e8df773 Mon Sep 17 00:00:00 2001 From: almostinf Date: Tue, 10 Sep 2024 13:37:12 +0300 Subject: [PATCH] remove new changes in api --- api/controller/contact.go | 13 +- api/controller/contact_test.go | 6 +- api/controller/emergency_contact.go | 115 ---- api/controller/emergency_contact_test.go | 341 ------------ api/controller/team.go | 22 +- api/controller/team_test.go | 54 +- api/controller/user.go | 20 +- api/controller/user_test.go | 100 +--- api/dto/contact.go | 13 +- api/dto/emergency_contact.go | 73 --- api/dto/emergency_contact_test.go | 43 -- api/dto/team.go | 7 +- api/dto/user.go | 5 +- api/handler/contact.go | 8 +- api/handler/emergency_contact.go | 185 ------- api/handler/emergency_contact_test.go | 665 ----------------------- api/handler/handler.go | 4 - api/handler/team.go | 1 - api/handler/team_emergency_contact.go | 53 -- 19 files changed, 63 insertions(+), 1665 deletions(-) delete mode 100644 api/controller/emergency_contact.go delete mode 100644 api/controller/emergency_contact_test.go delete mode 100644 api/dto/emergency_contact.go delete mode 100644 api/dto/emergency_contact_test.go delete mode 100644 api/handler/emergency_contact.go delete mode 100644 api/handler/emergency_contact_test.go delete mode 100644 api/handler/team_emergency_contact.go diff --git a/api/controller/contact.go b/api/controller/contact.go index d325ac844..4874624be 100644 --- a/api/controller/contact.go +++ b/api/controller/contact.go @@ -15,11 +15,8 @@ import ( "github.com/moira-alert/moira/database" ) -var ( - // errNotAllowedContactType means that this type of contact is not allowed to be created. - errNotAllowedContactType = errors.New("cannot create contact with not allowed contact type") - errNotPermittedStr = "you are not permitted" -) +// ErrNotAllowedContactType means that this type of contact is not allowed to be created. +var ErrNotAllowedContactType = errors.New("cannot create contact with not allowed contact type") // GetAllContacts gets all moira contacts. func GetAllContacts(database moira.Database) (*dto.ContactList, *api.ErrorResponse) { @@ -61,7 +58,7 @@ func CreateContact( teamID string, ) *api.ErrorResponse { if !isAllowedToUseContactType(auth, userLogin, contact.Type) { - return api.ErrorInvalidRequest(errNotAllowedContactType) + return api.ErrorInvalidRequest(ErrNotAllowedContactType) } // Only admins are allowed to create contacts for other users @@ -110,7 +107,7 @@ func UpdateContact( contactData moira.ContactData, ) (dto.Contact, *api.ErrorResponse) { if !isAllowedToUseContactType(auth, contactDTO.User, contactDTO.Type) { - return contactDTO, api.ErrorInvalidRequest(errNotAllowedContactType) + return contactDTO, api.ErrorInvalidRequest(ErrNotAllowedContactType) } contactData.Type = contactDTO.Type @@ -247,7 +244,7 @@ func CheckUserPermissionsForContact( return contactData, nil } - return moira.ContactData{}, api.ErrorForbidden(errNotPermittedStr) + return moira.ContactData{}, api.ErrorForbidden("you are not permitted") } func isContactExists(dataBase moira.Database, contactID string) (bool, error) { diff --git a/api/controller/contact_test.go b/api/controller/contact_test.go index f3a388bc2..8c398b528 100644 --- a/api/controller/contact_test.go +++ b/api/controller/contact_test.go @@ -188,7 +188,7 @@ func TestCreateContact(t *testing.T) { Value: contactValue, Type: notAllowedContactType, } - expectedErr := api.ErrorInvalidRequest(errNotAllowedContactType) + expectedErr := api.ErrorInvalidRequest(ErrNotAllowedContactType) err := CreateContact(dataBase, auth, contact, userLogin, "") So(err, ShouldResemble, expectedErr) }) @@ -319,7 +319,7 @@ func TestCreateContact(t *testing.T) { Value: contactValue, Type: notAllowedContactType, } - expectedErr := api.ErrorInvalidRequest(errNotAllowedContactType) + expectedErr := api.ErrorInvalidRequest(ErrNotAllowedContactType) err := CreateContact(dataBase, auth, contact, "", teamID) So(err, ShouldResemble, expectedErr) }) @@ -524,7 +524,7 @@ func TestUpdateContact(t *testing.T) { Value: contactValue, Type: notAllowedContactType, } - expectedErr := api.ErrorInvalidRequest(errNotAllowedContactType) + expectedErr := api.ErrorInvalidRequest(ErrNotAllowedContactType) contactID := uuid.Must(uuid.NewV4()).String() expectedContact, err := UpdateContact(dataBase, auth, contactDTO, moira.ContactData{ID: contactID, User: userLogin}) So(err, ShouldResemble, expectedErr) diff --git a/api/controller/emergency_contact.go b/api/controller/emergency_contact.go deleted file mode 100644 index 11ca281fc..000000000 --- a/api/controller/emergency_contact.go +++ /dev/null @@ -1,115 +0,0 @@ -package controller - -import ( - "errors" - "fmt" - - "github.com/moira-alert/moira" - "github.com/moira-alert/moira/api" - "github.com/moira-alert/moira/api/dto" - moiradb "github.com/moira-alert/moira/database" -) - -// ErrEmptyEmergencyContactID error occurring when user did not specify contact id. -var ErrEmptyEmergencyContactID = errors.New("emergency contact id can not be empty") - -// GetEmergencyContacts a method for obtaining all emergency contacts. -func GetEmergencyContacts(database moira.Database) (*dto.EmergencyContactList, *api.ErrorResponse) { - emergencyContacts, err := database.GetEmergencyContacts() - if err != nil { - return nil, api.ErrorInternalServer(err) - } - - return dto.FromEmergencyContacts(emergencyContacts), nil -} - -// GetEmergencyContact a method for obtaining a specific emergency contact. -func GetEmergencyContact(database moira.Database, contactID string) (*dto.EmergencyContact, *api.ErrorResponse) { - emergencyContact, err := database.GetEmergencyContact(contactID) - if err != nil { - if errors.Is(err, moiradb.ErrNil) { - return nil, api.ErrorNotFound(fmt.Sprintf("emergency contact with ID '%s' does not exists", contactID)) - } - - return nil, api.ErrorInternalServer(err) - } - - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - return &emergencyContactDTO, nil -} - -func verifyEmergencyContactAccess( - database moira.Database, - auth *api.Authorization, - emergencyContact moira.EmergencyContact, - userLogin string, -) *api.ErrorResponse { - contact, err := database.GetContact(emergencyContact.ContactID) - if err != nil { - return api.ErrorInternalServer(err) - } - - // Only admins are allowed to create an emergency contacts for other users - if !auth.IsAdmin(userLogin) && contact.User != "" && contact.User != userLogin { - return api.ErrorInvalidRequest(fmt.Errorf("cannot create an emergency contact using someone else's contact_id '%s'", emergencyContact.ContactID)) - } - - return nil -} - -// CreateEmergencyContact a method for creating emergency contact. -func CreateEmergencyContact( - database moira.Database, - auth *api.Authorization, - emergencyContactDTO *dto.EmergencyContact, - userLogin string, -) (dto.SaveEmergencyContactResponse, *api.ErrorResponse) { - if emergencyContactDTO == nil { - return dto.SaveEmergencyContactResponse{}, nil - } - - emergencyContact := moira.EmergencyContact(*emergencyContactDTO) - if emergencyContact.ContactID == "" { - return dto.SaveEmergencyContactResponse{}, api.ErrorInvalidRequest(ErrEmptyEmergencyContactID) - } - - if err := verifyEmergencyContactAccess(database, auth, emergencyContact, userLogin); err != nil { - return dto.SaveEmergencyContactResponse{}, err - } - - if err := database.SaveEmergencyContact(emergencyContact); err != nil { - return dto.SaveEmergencyContactResponse{}, api.ErrorInternalServer(err) - } - - return dto.SaveEmergencyContactResponse{ - ContactID: emergencyContact.ContactID, - }, nil -} - -// UpdateEmergencyContact a method to update the emergency contact. -func UpdateEmergencyContact(database moira.Database, contactID string, emergencyContactDTO *dto.EmergencyContact) (dto.SaveEmergencyContactResponse, *api.ErrorResponse) { - if emergencyContactDTO == nil { - return dto.SaveEmergencyContactResponse{}, nil - } - - emergencyContact := moira.EmergencyContact(*emergencyContactDTO) - emergencyContact.ContactID = contactID - - if err := database.SaveEmergencyContact(emergencyContact); err != nil { - return dto.SaveEmergencyContactResponse{}, api.ErrorInternalServer(err) - } - - return dto.SaveEmergencyContactResponse{ - ContactID: emergencyContact.ContactID, - }, nil -} - -// RemoveEmergencyContact a method to delete the emergency contact. -func RemoveEmergencyContact(database moira.Database, contactID string) *api.ErrorResponse { - if err := database.RemoveEmergencyContact(contactID); err != nil { - return api.ErrorInternalServer(err) - } - - return nil -} diff --git a/api/controller/emergency_contact_test.go b/api/controller/emergency_contact_test.go deleted file mode 100644 index 07dfc8b37..000000000 --- a/api/controller/emergency_contact_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package controller - -import ( - "errors" - "fmt" - "testing" - - "github.com/moira-alert/moira" - "github.com/moira-alert/moira/api" - "github.com/moira-alert/moira/api/dto" - moiradb "github.com/moira-alert/moira/database" - mock_moira_alert "github.com/moira-alert/moira/mock/moira-alert" - . "github.com/smartystreets/goconvey/convey" - "go.uber.org/mock/gomock" -) - -var ( - testContactID = "test-contact-id" - testContactID2 = "test-contact-id2" - - testEmergencyContact = moira.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - testEmergencyContact2 = moira.EmergencyContact{ - ContactID: testContactID2, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeRedisDisconnected}, - } - - testEmergencyContactDTO = dto.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - testEmergencyContact2DTO = dto.EmergencyContact{ - ContactID: testContactID2, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeRedisDisconnected}, - } -) - -func TestGetEmergencyContacts(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - Convey("Test GetEmergencyContacts", t, func() { - Convey("With nil response from database", func() { - database.EXPECT().GetEmergencyContacts().Return(nil, nil) - expectedEmergencyContactList := &dto.EmergencyContactList{ - List: make([]dto.EmergencyContact, 0), - } - - emergencyContactList, err := GetEmergencyContacts(database) - So(err, ShouldBeNil) - So(emergencyContactList, ShouldResemble, expectedEmergencyContactList) - }) - - Convey("With some saved emergency contacts in database", func() { - database.EXPECT().GetEmergencyContacts().Return([]*moira.EmergencyContact{&testEmergencyContact, &testEmergencyContact2}, nil) - expectedEmergencyContactList := &dto.EmergencyContactList{ - List: []dto.EmergencyContact{testEmergencyContactDTO, testEmergencyContact2DTO}, - } - - emergencyContactList, err := GetEmergencyContacts(database) - So(err, ShouldBeNil) - So(emergencyContactList, ShouldResemble, expectedEmergencyContactList) - }) - }) -} - -func TestGetEmergencyContact(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - Convey("Test GetEmergencyContact", t, func() { - Convey("With unexisted emergency contact", func() { - database.EXPECT().GetEmergencyContact(testContactID).Return(moira.EmergencyContact{}, moiradb.ErrNil) - - emergencyContact, err := GetEmergencyContact(database, testContactID) - So(err, ShouldResemble, api.ErrorNotFound(fmt.Sprintf("emergency contact with ID '%s' does not exists", testContactID))) - So(emergencyContact, ShouldBeNil) - }) - - Convey("With undefined db error", func() { - expectedErr := errors.New("test-error") - database.EXPECT().GetEmergencyContact(testContactID).Return(moira.EmergencyContact{}, expectedErr) - - emergencyContact, err := GetEmergencyContact(database, testContactID) - So(err, ShouldResemble, api.ErrorInternalServer(expectedErr)) - So(emergencyContact, ShouldBeNil) - }) - - Convey("Successfully get emergency contact", func() { - database.EXPECT().GetEmergencyContact(testContactID).Return(testEmergencyContact, nil) - - emergencyContact, err := GetEmergencyContact(database, testContactID) - So(err, ShouldBeNil) - So(emergencyContact, ShouldResemble, &testEmergencyContactDTO) - }) - }) -} - -func TestVerifyEmergencyContactAccess(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - const ( - admin = "admin" - user = "user" - ) - - contact := moira.ContactData{ - ID: testContactID, - User: user, - } - - Convey("Test verifyEmergencyContactAccess", t, func() { - Convey("With disabled auth and admin", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: false, - } - - database.EXPECT().GetContact(testContactID).Return(contact, nil) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, admin) - So(err, ShouldResemble, api.ErrorInvalidRequest(fmt.Errorf("cannot create an emergency contact using someone else's contact_id '%s'", testContactID))) - }) - - Convey("With disabled auth and user", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: false, - } - - database.EXPECT().GetContact(testContactID).Return(contact, nil) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, user) - So(err, ShouldBeNil) - }) - - Convey("With enabled auth and admin", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: true, - } - - database.EXPECT().GetContact(testContactID).Return(contact, nil) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, admin) - So(err, ShouldBeNil) - }) - - Convey("With enabled auth and user", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: true, - } - - database.EXPECT().GetContact(testContactID).Return(contact, nil) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, user) - So(err, ShouldBeNil) - }) - - Convey("With database error", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: true, - } - - dbErr := errors.New("get contact error") - database.EXPECT().GetContact(testContactID).Return(moira.ContactData{}, dbErr) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, user) - So(err, ShouldResemble, api.ErrorInternalServer(dbErr)) - }) - - Convey("With empty userLogin", func() { - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: true, - } - - database.EXPECT().GetContact(testContactID).Return(contact, nil) - - err := verifyEmergencyContactAccess(database, auth, testEmergencyContact, user) - So(err, ShouldBeNil) - }) - }) -} - -func TestCreateEmergencyContact(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - const ( - admin = "admin" - user = "user" - ) - - contact := moira.ContactData{ - ID: testContactID, - User: user, - } - - auth := &api.Authorization{ - AdminList: map[string]struct{}{ - admin: {}, - }, - Enabled: true, - } - - Convey("Test CreateEmergencyContact", t, func() { - Convey("With nil emergency contact dto", func() { - response, err := CreateEmergencyContact(database, auth, nil, user) - So(err, ShouldBeNil) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - - Convey("With empty emergency contact id", func() { - emergencyContactDTO := dto.EmergencyContact{} - response, err := CreateEmergencyContact(database, auth, &emergencyContactDTO, user) - So(err, ShouldResemble, api.ErrorInvalidRequest(ErrEmptyEmergencyContactID)) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - - Convey("With get contact database error", func() { - dbErr := errors.New("get contact error") - database.EXPECT().GetContact(testContactID).Return(moira.ContactData{}, dbErr) - - response, err := CreateEmergencyContact(database, auth, &testEmergencyContactDTO, user) - So(err, ShouldResemble, api.ErrorInternalServer(dbErr)) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - - Convey("With save emergency contact database error", func() { - dbErr := errors.New("create emergency contact error") - database.EXPECT().GetContact(testContactID).Return(contact, nil) - database.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(dbErr) - - response, err := CreateEmergencyContact(database, auth, &testEmergencyContactDTO, user) - So(err, ShouldResemble, api.ErrorInternalServer(dbErr)) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - - Convey("Without any errors", func() { - database.EXPECT().GetContact(testContactID).Return(contact, nil) - database.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - - response, err := CreateEmergencyContact(database, auth, &testEmergencyContactDTO, user) - So(err, ShouldBeNil) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - }) - }) - }) -} - -func TestUpdateEmergencyContact(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - Convey("Test UpdateEmergencyContact", t, func() { - Convey("With nil emergency contact dto", func() { - response, err := UpdateEmergencyContact(database, testContactID, nil) - So(err, ShouldBeNil) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - - Convey("With empty contact id", func() { - emergencyContactDTO := dto.EmergencyContact{ - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - database.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - - response, err := UpdateEmergencyContact(database, testContactID, &emergencyContactDTO) - So(err, ShouldBeNil) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - }) - }) - - Convey("With full filled emergency contact dto", func() { - database.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - - response, err := UpdateEmergencyContact(database, testContactID, &testEmergencyContactDTO) - So(err, ShouldBeNil) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - }) - }) - - Convey("With database error", func() { - dbErr := errors.New("update emergency contact error") - database.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(dbErr) - - response, err := UpdateEmergencyContact(database, testContactID, &testEmergencyContactDTO) - So(err, ShouldResemble, api.ErrorInternalServer(dbErr)) - So(response, ShouldResemble, dto.SaveEmergencyContactResponse{}) - }) - }) -} - -func TestRemoveEmergencyContact(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - defer mockCtrl.Finish() - - Convey("Test RemoveEmergencyContact", t, func() { - Convey("Successfully removed emergency contact", func() { - database.EXPECT().RemoveEmergencyContact(testContactID).Return(nil) - - err := RemoveEmergencyContact(database, testContactID) - So(err, ShouldBeNil) - }) - - Convey("With database error", func() { - dbErr := errors.New("remove emergency contact error") - database.EXPECT().RemoveEmergencyContact(testContactID).Return(dbErr) - - err := RemoveEmergencyContact(database, testContactID) - So(err, ShouldResemble, api.ErrorInternalServer(dbErr)) - }) - }) -} diff --git a/api/controller/team.go b/api/controller/team.go index a170a773c..3c35ac0e2 100644 --- a/api/controller/team.go +++ b/api/controller/team.go @@ -428,10 +428,9 @@ func CheckUserPermissionsForTeam( // GetTeamSettings gets team contacts and subscriptions. func GetTeamSettings(database moira.Database, teamID string) (dto.TeamSettings, *api.ErrorResponse) { teamSettings := dto.TeamSettings{ - TeamID: teamID, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + TeamID: teamID, + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), } subscriptionIDs, err := database.GetTeamSubscriptionIDs(teamID) @@ -443,13 +442,11 @@ func GetTeamSettings(database moira.Database, teamID string) (dto.TeamSettings, if err != nil { return dto.TeamSettings{}, api.ErrorInternalServer(err) } - for _, subscription := range subscriptions { if subscription != nil { teamSettings.Subscriptions = append(teamSettings.Subscriptions, *subscription) } } - contactIDs, err := database.GetTeamContactIDs(teamID) if err != nil { return dto.TeamSettings{}, api.ErrorInternalServer(err) @@ -459,23 +456,10 @@ func GetTeamSettings(database moira.Database, teamID string) (dto.TeamSettings, if err != nil { return dto.TeamSettings{}, api.ErrorInternalServer(err) } - for _, contact := range contacts { if contact != nil { teamSettings.Contacts = append(teamSettings.Contacts, *contact) } } - - emergencyContacts, err := database.GetEmergencyContactsByIDs(contactIDs) - if err != nil { - return dto.TeamSettings{}, api.ErrorInternalServer(err) - } - - for _, emergencyContact := range emergencyContacts { - if emergencyContact != nil { - teamSettings.EmergencyContacts = append(teamSettings.EmergencyContacts, dto.EmergencyContact(*emergencyContact)) - } - } - return teamSettings, nil } diff --git a/api/controller/team_test.go b/api/controller/team_test.go index eb167b913..0eb937e4f 100644 --- a/api/controller/team_test.go +++ b/api/controller/team_test.go @@ -642,38 +642,30 @@ func TestGetTeamSettings(t *testing.T) { subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} contacts := []*moira.ContactData{{ID: contactIDs[0]}, {ID: contactIDs[1]}} - emergencyContacts := []*moira.EmergencyContact{{ContactID: contactIDs[0]}, {ContactID: contactIDs[1]}} - database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(subscriptionIDs, nil) database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) database.EXPECT().GetTeamContactIDs(teamID).Return(contactIDs, nil) database.EXPECT().GetContacts(contactIDs).Return(contacts, nil) - database.EXPECT().GetEmergencyContactsByIDs(contactIDs).Return(emergencyContacts, nil) - settings, err := GetTeamSettings(database, teamID) So(err, ShouldBeNil) So(settings, ShouldResemble, dto.TeamSettings{ - TeamID: teamID, - Contacts: []moira.ContactData{*contacts[0], *contacts[1]}, - Subscriptions: []moira.SubscriptionData{*subscriptions[0], *subscriptions[1]}, - EmergencyContacts: []dto.EmergencyContact{dto.EmergencyContact(*emergencyContacts[0]), dto.EmergencyContact(*emergencyContacts[1])}, + TeamID: teamID, + Contacts: []moira.ContactData{*contacts[0], *contacts[1]}, + Subscriptions: []moira.SubscriptionData{*subscriptions[0], *subscriptions[1]}, }) }) Convey("No contacts and subscriptions", t, func() { - database.EXPECT().GetTeamSubscriptionIDs(teamID).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return([]*moira.SubscriptionData{}, nil) - database.EXPECT().GetTeamContactIDs(teamID).Return([]string{}, nil) - database.EXPECT().GetContacts([]string{}).Return([]*moira.ContactData{}, nil) - database.EXPECT().GetEmergencyContactsByIDs([]string{}).Return([]*moira.EmergencyContact{}, nil) - + database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) + database.EXPECT().GetTeamContactIDs(teamID).Return(make([]string, 0), nil) + database.EXPECT().GetContacts(make([]string, 0)).Return(make([]*moira.ContactData, 0), nil) settings, err := GetTeamSettings(database, teamID) So(err, ShouldBeNil) So(settings, ShouldResemble, dto.TeamSettings{ - TeamID: teamID, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + TeamID: teamID, + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), }) }) @@ -681,62 +673,36 @@ func TestGetTeamSettings(t *testing.T) { Convey("GetTeamSubscriptionIDs", func() { expected := fmt.Errorf("can not read ids") database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(nil, expected) - settings, err := GetTeamSettings(database, teamID) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldResemble, dto.TeamSettings{}) }) - Convey("GetSubscriptions", func() { expected := fmt.Errorf("can not read subscriptions") database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(make([]string, 0), nil) database.EXPECT().GetSubscriptions(make([]string, 0)).Return(nil, expected) - settings, err := GetTeamSettings(database, teamID) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldResemble, dto.TeamSettings{}) }) - Convey("GetTeamContactIDs", func() { expected := fmt.Errorf("can not read contact ids") database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(make([]string, 0), nil) database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) database.EXPECT().GetTeamContactIDs(teamID).Return(nil, expected) - settings, err := GetTeamSettings(database, teamID) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldResemble, dto.TeamSettings{}) }) - Convey("GetContacts", func() { expected := fmt.Errorf("can not read contacts") subscriptionIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(subscriptionIDs, nil) database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) database.EXPECT().GetTeamContactIDs(teamID).Return(contactIDs, nil) database.EXPECT().GetContacts(contactIDs).Return(nil, expected) - settings, err := GetTeamSettings(database, teamID) - - So(err, ShouldResemble, api.ErrorInternalServer(expected)) - So(settings, ShouldResemble, dto.TeamSettings{}) - }) - - Convey("GetEmergencyContacts", func() { - expected := fmt.Errorf("can not read emergency contacts") - subscriptionIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} - contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - contacts := []*moira.ContactData{{ID: contactIDs[0]}, {ID: contactIDs[1]}} - - database.EXPECT().GetTeamSubscriptionIDs(teamID).Return(subscriptionIDs, nil) - database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) - database.EXPECT().GetTeamContactIDs(teamID).Return(contactIDs, nil) - database.EXPECT().GetContacts(contactIDs).Return(contacts, nil) - database.EXPECT().GetEmergencyContactsByIDs(contactIDs).Return(nil, expected) - settings, err := GetTeamSettings(database, teamID) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldResemble, dto.TeamSettings{}) diff --git a/api/controller/user.go b/api/controller/user.go index bea7a77c8..0b3d969d6 100644 --- a/api/controller/user.go +++ b/api/controller/user.go @@ -14,9 +14,8 @@ func GetUserSettings(database moira.Database, userLogin string, auth *api.Author AuthEnabled: auth.IsEnabled(), Role: auth.GetRole(userLogin), }, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), } subscriptionIDs, err := database.GetUserSubscriptionIDs(userLogin) @@ -28,13 +27,11 @@ func GetUserSettings(database moira.Database, userLogin string, auth *api.Author if err != nil { return nil, api.ErrorInternalServer(err) } - for _, subscription := range subscriptions { if subscription != nil { userSettings.Subscriptions = append(userSettings.Subscriptions, *subscription) } } - contactIDs, err := database.GetUserContactIDs(userLogin) if err != nil { return nil, api.ErrorInternalServer(err) @@ -44,23 +41,10 @@ func GetUserSettings(database moira.Database, userLogin string, auth *api.Author if err != nil { return nil, api.ErrorInternalServer(err) } - for _, contact := range contacts { if contact != nil { userSettings.Contacts = append(userSettings.Contacts, *contact) } } - - emergencyContacts, err := database.GetEmergencyContactsByIDs(contactIDs) - if err != nil { - return nil, api.ErrorInternalServer(err) - } - - for _, emergencyContact := range emergencyContacts { - if emergencyContact != nil { - userSettings.EmergencyContacts = append(userSettings.EmergencyContacts, dto.EmergencyContact(*emergencyContact)) - } - } - return userSettings, nil } diff --git a/api/controller/user_test.go b/api/controller/user_test.go index 24800464e..23f913927 100644 --- a/api/controller/user_test.go +++ b/api/controller/user_test.go @@ -23,42 +23,32 @@ func TestGetUserSettings(t *testing.T) { Convey("Success get user data", t, func() { subscriptionIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} - contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} contacts := []*moira.ContactData{{ID: contactIDs[0]}, {ID: contactIDs[1]}} - - emergencyContacts := []*moira.EmergencyContact{{ContactID: contactIDs[0]}, {ContactID: contactIDs[1]}} - database.EXPECT().GetUserSubscriptionIDs(login).Return(subscriptionIDs, nil) database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) database.EXPECT().GetUserContactIDs(login).Return(contactIDs, nil) database.EXPECT().GetContacts(contactIDs).Return(contacts, nil) - database.EXPECT().GetEmergencyContactsByIDs(contactIDs).Return(emergencyContacts, nil) - settings, err := GetUserSettings(database, login, auth) So(err, ShouldBeNil) So(settings, ShouldResemble, &dto.UserSettings{ - User: dto.User{Login: login}, - Contacts: []moira.ContactData{*contacts[0], *contacts[1]}, - Subscriptions: []moira.SubscriptionData{*subscriptions[0], *subscriptions[1]}, - EmergencyContacts: []dto.EmergencyContact{dto.EmergencyContact(*emergencyContacts[0]), dto.EmergencyContact(*emergencyContacts[1])}, + User: dto.User{Login: login}, + Contacts: []moira.ContactData{*contacts[0], *contacts[1]}, + Subscriptions: []moira.SubscriptionData{*subscriptions[0], *subscriptions[1]}, }) }) - Convey("No contacts, subscriptions and emergency contacts", t, func() { - database.EXPECT().GetUserSubscriptionIDs(login).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return([]*moira.SubscriptionData{}, nil) - database.EXPECT().GetUserContactIDs(login).Return([]string{}, nil) - database.EXPECT().GetContacts([]string{}).Return([]*moira.ContactData{}, nil) - database.EXPECT().GetEmergencyContactsByIDs([]string{}).Return([]*moira.EmergencyContact{}, nil) - + Convey("No contacts and subscriptions", t, func() { + database.EXPECT().GetUserSubscriptionIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) + database.EXPECT().GetUserContactIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetContacts(make([]string, 0)).Return(make([]*moira.ContactData, 0), nil) settings, err := GetUserSettings(database, login, auth) So(err, ShouldBeNil) So(settings, ShouldResemble, &dto.UserSettings{ - User: dto.User{Login: login}, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + User: dto.User{Login: login}, + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), }) }) @@ -67,36 +57,30 @@ func TestGetUserSettings(t *testing.T) { authFull := &api.Authorization{Enabled: true, AdminList: map[string]struct{}{adminLogin: {}}} Convey("User is not admin", func() { - database.EXPECT().GetUserSubscriptionIDs(login).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return([]*moira.SubscriptionData{}, nil) - database.EXPECT().GetUserContactIDs(login).Return([]string{}, nil) - database.EXPECT().GetContacts([]string{}).Return([]*moira.ContactData{}, nil) - database.EXPECT().GetEmergencyContactsByIDs([]string{}).Return([]*moira.EmergencyContact{}, nil) - + database.EXPECT().GetUserSubscriptionIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) + database.EXPECT().GetUserContactIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetContacts(make([]string, 0)).Return(make([]*moira.ContactData, 0), nil) settings, err := GetUserSettings(database, login, authFull) So(err, ShouldBeNil) So(settings, ShouldResemble, &dto.UserSettings{ - User: dto.User{Login: login, Role: api.RoleUser, AuthEnabled: true}, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + User: dto.User{Login: login, Role: api.RoleUser, AuthEnabled: true}, + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), }) }) Convey("User is admin", func() { - database.EXPECT().GetUserSubscriptionIDs(adminLogin).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return([]*moira.SubscriptionData{}, nil) - database.EXPECT().GetUserContactIDs(adminLogin).Return([]string{}, nil) - database.EXPECT().GetContacts([]string{}).Return([]*moira.ContactData{}, nil) - database.EXPECT().GetEmergencyContactsByIDs([]string{}).Return([]*moira.EmergencyContact{}, nil) - + database.EXPECT().GetUserSubscriptionIDs(adminLogin).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) + database.EXPECT().GetUserContactIDs(adminLogin).Return(make([]string, 0), nil) + database.EXPECT().GetContacts(make([]string, 0)).Return(make([]*moira.ContactData, 0), nil) settings, err := GetUserSettings(database, adminLogin, authFull) So(err, ShouldBeNil) So(settings, ShouldResemble, &dto.UserSettings{ - User: dto.User{Login: adminLogin, Role: api.RoleAdmin, AuthEnabled: true}, - Contacts: make([]moira.ContactData, 0), - Subscriptions: make([]moira.SubscriptionData, 0), - EmergencyContacts: make([]dto.EmergencyContact, 0), + User: dto.User{Login: adminLogin, Role: api.RoleAdmin, AuthEnabled: true}, + Contacts: make([]moira.ContactData, 0), + Subscriptions: make([]moira.SubscriptionData, 0), }) }) }) @@ -105,63 +89,37 @@ func TestGetUserSettings(t *testing.T) { Convey("GetUserSubscriptionIDs", func() { expected := fmt.Errorf("can not read ids") database.EXPECT().GetUserSubscriptionIDs(login).Return(nil, expected) - settings, err := GetUserSettings(database, login, auth) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldBeNil) }) - Convey("GetSubscriptions", func() { expected := fmt.Errorf("can not read subscriptions") - database.EXPECT().GetUserSubscriptionIDs(login).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return(nil, expected) - + database.EXPECT().GetUserSubscriptionIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(nil, expected) settings, err := GetUserSettings(database, login, auth) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldBeNil) }) - Convey("GetUserContactIDs", func() { expected := fmt.Errorf("can not read contact ids") - database.EXPECT().GetUserSubscriptionIDs(login).Return([]string{}, nil) - database.EXPECT().GetSubscriptions([]string{}).Return([]*moira.SubscriptionData{}, nil) + database.EXPECT().GetUserSubscriptionIDs(login).Return(make([]string, 0), nil) + database.EXPECT().GetSubscriptions(make([]string, 0)).Return(make([]*moira.SubscriptionData, 0), nil) database.EXPECT().GetUserContactIDs(login).Return(nil, expected) - settings, err := GetUserSettings(database, login, auth) So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldBeNil) }) - Convey("GetContacts", func() { expected := fmt.Errorf("can not read contacts") subscriptionIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - database.EXPECT().GetUserSubscriptionIDs(login).Return(subscriptionIDs, nil) database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) database.EXPECT().GetUserContactIDs(login).Return(contactIDs, nil) database.EXPECT().GetContacts(contactIDs).Return(nil, expected) - - settings, err := GetUserSettings(database, login, auth) - So(err, ShouldResemble, api.ErrorInternalServer(expected)) - So(settings, ShouldBeNil) - }) - - Convey("GetEmergencyContacts", func() { - expected := fmt.Errorf("can not read emergency contacts") - subscriptionIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - subscriptions := []*moira.SubscriptionData{{ID: subscriptionIDs[0]}, {ID: subscriptionIDs[1]}} - contactIDs := []string{uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String()} - contacts := []*moira.ContactData{{ID: contactIDs[0]}, {ID: contactIDs[1]}} - - database.EXPECT().GetUserSubscriptionIDs(login).Return(subscriptionIDs, nil) - database.EXPECT().GetSubscriptions(subscriptionIDs).Return(subscriptions, nil) - database.EXPECT().GetUserContactIDs(login).Return(contactIDs, nil) - database.EXPECT().GetContacts(contactIDs).Return(contacts, nil) - database.EXPECT().GetEmergencyContactsByIDs(contactIDs).Return(nil, expected) settings, err := GetUserSettings(database, login, auth) - So(err, ShouldResemble, api.ErrorInternalServer(expected)) So(settings, ShouldBeNil) }) diff --git a/api/dto/contact.go b/api/dto/contact.go index 70d717d81..376b190c5 100644 --- a/api/dto/contact.go +++ b/api/dto/contact.go @@ -2,18 +2,12 @@ package dto import ( - "errors" "fmt" "net/http" "github.com/moira-alert/moira" ) -var ( - errEmptyContactType = errors.New("contact type can not be empty") - errUserLoginAndTeamIDFilledIn = errors.New("contact cannot have both the user field and the team_id field filled in") -) - type ContactList struct { List []*moira.ContactData `json:"list"` } @@ -37,16 +31,13 @@ func (*Contact) Render(w http.ResponseWriter, r *http.Request) error { func (contact *Contact) Bind(r *http.Request) error { if contact.Type == "" { - return errEmptyContactType + return fmt.Errorf("contact type can not be empty") } - if contact.Value == "" { return fmt.Errorf("contact value of type %s can not be empty", contact.Type) } - if contact.User != "" && contact.TeamID != "" { - return errUserLoginAndTeamIDFilledIn + return fmt.Errorf("contact cannot have both the user field and the team_id field filled in") } - return nil } diff --git a/api/dto/emergency_contact.go b/api/dto/emergency_contact.go deleted file mode 100644 index 3202075e6..000000000 --- a/api/dto/emergency_contact.go +++ /dev/null @@ -1,73 +0,0 @@ -package dto - -import ( - "errors" - "fmt" - "net/http" - - "github.com/moira-alert/moira" -) - -// ErrEmptyEmergencyTypes means that the user has not specified any emergency types. -var ErrEmptyEmergencyTypes = errors.New("emergency types can not be empty") - -// EmergencyContact is the DTO structure for contacts to which notifications will go in the event of special internal Moira problems. -type EmergencyContact struct { - ContactID string `json:"contact_id" example:"1dd38765-c5be-418d-81fa-7a5f879c2315"` - EmergencyTypes []moira.EmergencyContactType `json:"emergency_types" example:"notifier_off"` -} - -// Render is a function that implements chi Renderer interface for EmergencyContact. -func (*EmergencyContact) Render(w http.ResponseWriter, r *http.Request) error { - return nil -} - -// Bind is a method that implements Binder interface from chi and checks that validity of data in request. -func (emergencyContact *EmergencyContact) Bind(r *http.Request) error { - if len(emergencyContact.EmergencyTypes) == 0 { - return ErrEmptyEmergencyTypes - } - - for _, emergencyType := range emergencyContact.EmergencyTypes { - if !emergencyType.IsValid() { - return fmt.Errorf("'%s' emergency type doesn't exist", emergencyType) - } - } - - return nil -} - -// EmergencyContactList is the DTO structure for list of contacts to which notifications will go in the event of special internal Moira problems. -type EmergencyContactList struct { - List []EmergencyContact `json:"list"` -} - -// Render is a function that implements chi Renderer interface for EmergencyContactList. -func (*EmergencyContactList) Render(w http.ResponseWriter, r *http.Request) error { - return nil -} - -// FromEmergencyContacts a method that converts emergency contacts to dto emergency ccontact list. -func FromEmergencyContacts(emergencyContacts []*moira.EmergencyContact) *EmergencyContactList { - emergencyContactsDTO := &EmergencyContactList{ - List: make([]EmergencyContact, 0, len(emergencyContacts)), - } - - for _, emergencyContact := range emergencyContacts { - if emergencyContact != nil { - emergencyContactsDTO.List = append(emergencyContactsDTO.List, EmergencyContact(*emergencyContact)) - } - } - - return emergencyContactsDTO -} - -// SaveEmergencyContactResponse is the DTO structure which is returned in the methods of saving contact. -type SaveEmergencyContactResponse struct { - ContactID string `json:"contact_id" example:"1dd38765-c5be-418d-81fa-7a5f879c2315"` -} - -// Render is a function that implements chi Renderer interface for SaveEmergencyContactResponse. -func (SaveEmergencyContactResponse) Render(w http.ResponseWriter, r *http.Request) error { - return nil -} diff --git a/api/dto/emergency_contact_test.go b/api/dto/emergency_contact_test.go deleted file mode 100644 index 2d47bde2d..000000000 --- a/api/dto/emergency_contact_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package dto - -import ( - "testing" - - "github.com/moira-alert/moira" - . "github.com/smartystreets/goconvey/convey" -) - -var ( - testContactID = "test-contact-id" - - testEmergencyContact = moira.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } -) - -func TestFromEmergencyContacts(t *testing.T) { - Convey("Test FromEmergencyContacts", t, func() { - Convey("With nil emergency contacts", func() { - expectedEmergencyContactList := &EmergencyContactList{ - List: make([]EmergencyContact, 0), - } - emergencyContactList := FromEmergencyContacts(nil) - So(emergencyContactList, ShouldResemble, expectedEmergencyContactList) - }) - - Convey("With some emergency contacts", func() { - expectedEmergencyContactList := &EmergencyContactList{ - List: []EmergencyContact{ - EmergencyContact(testEmergencyContact), - }, - } - emergencyContacts := []*moira.EmergencyContact{ - &testEmergencyContact, - nil, - } - emergencyContactList := FromEmergencyContacts(emergencyContacts) - So(emergencyContactList, ShouldResemble, expectedEmergencyContactList) - }) - }) -} diff --git a/api/dto/team.go b/api/dto/team.go index 16a1a242b..9b08cb7ee 100644 --- a/api/dto/team.go +++ b/api/dto/team.go @@ -96,10 +96,9 @@ func (TeamMembers) Render(w http.ResponseWriter, r *http.Request) error { } type TeamSettings struct { - TeamID string `json:"team_id" example:"d5d98eb3-ee18-4f75-9364-244f67e23b54"` - Contacts []moira.ContactData `json:"contacts"` - Subscriptions []moira.SubscriptionData `json:"subscriptions"` - EmergencyContacts []EmergencyContact `json:"emergency_contacts"` + TeamID string `json:"team_id" example:"d5d98eb3-ee18-4f75-9364-244f67e23b54"` + Contacts []moira.ContactData `json:"contacts"` + Subscriptions []moira.SubscriptionData `json:"subscriptions"` } func (TeamSettings) Render(w http.ResponseWriter, r *http.Request) error { diff --git a/api/dto/user.go b/api/dto/user.go index 634a55074..e86438486 100644 --- a/api/dto/user.go +++ b/api/dto/user.go @@ -10,9 +10,8 @@ import ( type UserSettings struct { User - Contacts []moira.ContactData `json:"contacts"` - Subscriptions []moira.SubscriptionData `json:"subscriptions"` - EmergencyContacts []EmergencyContact `json:"emergency_contacts"` + Contacts []moira.ContactData `json:"contacts"` + Subscriptions []moira.SubscriptionData `json:"subscriptions"` } func (*UserSettings) Render(w http.ResponseWriter, r *http.Request) error { diff --git a/api/handler/contact.go b/api/handler/contact.go index fef5a9ca6..ba31d1f2d 100644 --- a/api/handler/contact.go +++ b/api/handler/contact.go @@ -81,7 +81,7 @@ func getContactById(writer http.ResponseWriter, request *http.Request) { // nolint: gofmt,goimports // -// @summary Creates a new contact for the current user +// @summary Creates a new contact notification for the current user // @id create-new-contact // @tags contact // @accept json @@ -131,9 +131,8 @@ func contactFilter(next http.Handler) http.Handler { // nolint: gofmt,goimports // -// @summary Updates an existing contact to the values passed in the request body +// @summary Updates an existing notification contact to the values passed in the request body // @id update-contact -// @tags contact // @accept json // @produce json // @param contactID path string true "ID of the contact to update" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) @@ -145,6 +144,7 @@ func contactFilter(next http.Handler) http.Handler { // @failure 422 {object} api.ErrorRenderExample "Render error" // @failure 500 {object} api.ErrorInternalServerExample "Internal server error" // @router /contact/{contactID} [put] +// @tags contact func updateContact(writer http.ResponseWriter, request *http.Request) { contactDTO := dto.Contact{} if err := render.Bind(request, &contactDTO); err != nil { @@ -195,13 +195,13 @@ func removeContact(writer http.ResponseWriter, request *http.Request) { // @id send-test-contact-notification // @accept json // @produce json -// @tags contact // @param contactID path string true "The ID of the target contact" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) // @success 200 "Test successful" // @failure 403 {object} api.ErrorForbiddenExample "Forbidden" // @failure 404 {object} api.ErrorNotFoundExample "Resource not found" // @failure 500 {object} api.ErrorInternalServerExample "Internal server error" // @router /contact/{contactID}/test [post] +// @tags contact func sendTestContactNotification(writer http.ResponseWriter, request *http.Request) { contactID := middleware.GetContactID(request) err := controller.SendTestContactNotification(database, contactID) diff --git a/api/handler/emergency_contact.go b/api/handler/emergency_contact.go deleted file mode 100644 index 72681f4e4..000000000 --- a/api/handler/emergency_contact.go +++ /dev/null @@ -1,185 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/go-chi/chi" - "github.com/go-chi/render" - "github.com/moira-alert/moira/api" - "github.com/moira-alert/moira/api/controller" - "github.com/moira-alert/moira/api/dto" - "github.com/moira-alert/moira/api/middleware" -) - -func emergencyContact(router chi.Router) { - router.With(middleware.AdminOnlyMiddleware()).Get("/", getEmergencyContacts) - router.Post("/", createEmergencyContact) - router.Route("/{contactId}", func(router chi.Router) { - router.Use(middleware.ContactContext) - router.Use(emergencyContactFilter) - router.Use(contactFilter) - router.Get("/", getEmergencyContactByID) - router.Put("/", updateEmergencyContact) - router.Delete("/", removeEmergencyContact) - }) -} - -// nolint: gofmt,goimports -// -// @summary Gets all Moira emergency contacts -// @id get-all-emergency-contacts -// @tags emergency-contact -// @produce json -// @success 200 {object} dto.EmergencyContactList "Contacts fetched successfully" -// @failure 422 {object} api.ErrorRenderExample "Render error" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /emergency-contact [get] -func getEmergencyContacts(writer http.ResponseWriter, request *http.Request) { - emergencyContacts, err := controller.GetEmergencyContacts(database) - if err != nil { - render.Render(writer, request, err) //nolint - return - } - - if err := render.Render(writer, request, emergencyContacts); err != nil { - render.Render(writer, request, api.ErrorRender(err)) //nolint - return - } -} - -// nolint: gofmt,goimports -// -// @summary Get emergency contact by it's contact ID -// @id get-emergency-contact-by-id -// @tags emergency-contact -// @produce json -// @param contactID path string true "Contact ID" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) -// @success 200 {object} dto.EmergencyContact "Successfully received contact" -// @failure 403 {object} api.ErrorForbiddenExample "Forbidden" -// @failure 404 {object} api.ErrorNotFoundExample "Resource not found" -// @failure 422 {object} api.ErrorRenderExample "Render error" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /emergency-contact/{contactID} [get] -func getEmergencyContactByID(writer http.ResponseWriter, request *http.Request) { - contactID := middleware.GetContactID(request) - - emergencyContact, err := controller.GetEmergencyContact(database, contactID) - if err != nil { - render.Render(writer, request, err) //nolint - return - } - - if err := render.Render(writer, request, emergencyContact); err != nil { - render.Render(writer, request, api.ErrorRender(err)) //nolint - return - } -} - -// nolint: gofmt,goimports -// -// @summary Creates a new emergency contact for the current user -// @id create-emergency-contact -// @tags emergency-contact -// @accept json -// @produce json -// @param emergency-contact body dto.EmergencyContact true "Emergency contact data" -// @success 200 {object} dto.SaveEmergencyContactResponse "Emergency contact created successfully" -// @failure 400 {object} api.ErrorInvalidRequestExample "Bad request from client" -// @failure 422 {object} api.ErrorRenderExample "Render error" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /emergency-contact [post] -func createEmergencyContact(writer http.ResponseWriter, request *http.Request) { - emergencyContactDTO := &dto.EmergencyContact{} - if err := render.Bind(request, emergencyContactDTO); err != nil { - render.Render(writer, request, api.ErrorInvalidRequest(err)) //nolint - return - } - - userLogin := middleware.GetLogin(request) - auth := middleware.GetAuth(request) - - response, err := controller.CreateEmergencyContact(database, auth, emergencyContactDTO, userLogin) - if err != nil { - render.Render(writer, request, err) //nolint - return - } - - if err := render.Render(writer, request, response); err != nil { - render.Render(writer, request, api.ErrorRender(err)) //nolint - return - } -} - -// nolint: gofmt,goimports -// -// @summary Updates an existing contact to the values passed in the request body -// @id update-emergency-contact -// @tags emergency-contact -// @accept json -// @produce json -// @param contactID path string true "ID of the contact to update" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) -// @param emergency-contact body dto.EmergencyContact true "Updated emergency contact data" -// @success 200 {object} dto.SaveEmergencyContactResponse "Updated emergency contact" -// @failure 400 {object} api.ErrorInvalidRequestExample "Bad request from client" -// @failure 403 {object} api.ErrorForbiddenExample "Forbidden" -// @failure 404 {object} api.ErrorNotFoundExample "Resource not found" -// @failure 422 {object} api.ErrorRenderExample "Render error" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /emergency-contact/{contactID} [put] -func updateEmergencyContact(writer http.ResponseWriter, request *http.Request) { - emergencyContactDTO := &dto.EmergencyContact{} - if err := render.Bind(request, emergencyContactDTO); err != nil { - render.Render(writer, request, api.ErrorInvalidRequest(err)) //nolint - return - } - - contactID := middleware.GetContactID(request) - - response, err := controller.UpdateEmergencyContact(database, contactID, emergencyContactDTO) - if err != nil { - render.Render(writer, request, err) //nolint - return - } - - if err := render.Render(writer, request, response); err != nil { - render.Render(writer, request, api.ErrorRender(err)) //nolint - return - } -} - -// nolint: gofmt,goimports -// -// @summary Deletes emergency contact for the current user -// @id remove-emergency-contact -// @accept json -// @produce json -// @tags emergency-contact -// @param contactID path string true "ID of the emergency contact to remove" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) -// @success 200 "Emergency contact has been deleted" -// @failure 400 {object} api.ErrorInvalidRequestExample "Bad request from client" -// @failure 403 {object} api.ErrorForbiddenExample "Forbidden" -// @failure 404 {object} api.ErrorNotFoundExample "Resource not found" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /emergency-contact/{contactID} [delete] -func removeEmergencyContact(writer http.ResponseWriter, request *http.Request) { - contactID := middleware.GetContactID(request) - - if err := controller.RemoveEmergencyContact(database, contactID); err != nil { - render.Render(writer, request, err) //nolint - return - } -} - -// emergencyContactFilter is middleware for check emergency contact existence. -func emergencyContactFilter(next http.Handler) http.Handler { - return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - contactID := middleware.GetContactID(request) - - if _, err := controller.GetEmergencyContact(database, contactID); err != nil { - render.Render(writer, request, err) //nolint - return - } - - next.ServeHTTP(writer, request) - }) -} diff --git a/api/handler/emergency_contact_test.go b/api/handler/emergency_contact_test.go deleted file mode 100644 index 48b77830a..000000000 --- a/api/handler/emergency_contact_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package handler - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/moira-alert/moira" - "github.com/moira-alert/moira/api" - "github.com/moira-alert/moira/api/controller" - "github.com/moira-alert/moira/api/dto" - "github.com/moira-alert/moira/api/middleware" - moiradb "github.com/moira-alert/moira/database" - mock_moira_alert "github.com/moira-alert/moira/mock/moira-alert" - . "github.com/smartystreets/goconvey/convey" - "go.uber.org/mock/gomock" -) - -var ( - testContactID = "test-contact-id" - testContactID2 = "test-contact-id2" - - testEmergencyContact = moira.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - testEmergencyContact2 = moira.EmergencyContact{ - ContactID: testContactID2, - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeRedisDisconnected}, - } - - login = "testLogin" - - testContact = moira.ContactData{ - ID: testContactID, - User: login, - } -) - -func TestGetEmergencyContacts(t *testing.T) { - Convey("Test getEmergencyContacts", t, func() { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - responseWriter := httptest.NewRecorder() - mockDb := mock_moira_alert.NewMockDatabase(mockCtrl) - - Convey("Successfully get emergency contacts", func() { - mockDb.EXPECT().GetEmergencyContacts().Return([]*moira.EmergencyContact{ - &testEmergencyContact, - &testEmergencyContact2, - }, nil) - database = mockDb - - expectedEmergencyContactList := &dto.EmergencyContactList{ - List: []dto.EmergencyContact{ - dto.EmergencyContact(testEmergencyContact), - dto.EmergencyContact(testEmergencyContact2), - }, - } - - testRequest := httptest.NewRequest(http.MethodGet, "/emergency-contact", nil) - - getEmergencyContacts(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, _ := io.ReadAll(response.Body) - contents := string(contentBytes) - actual := &dto.EmergencyContactList{} - err := json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedEmergencyContactList) - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Internal server error from database", func() { - dbErr := errors.New("get emergency contacts error") - mockDb.EXPECT().GetEmergencyContacts().Return(nil, dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - - testRequest := httptest.NewRequest(http.MethodGet, "/emergency-contact", nil) - - getEmergencyContacts(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, _ := io.ReadAll(response.Body) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err := json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - }) -} - -func TestGetEmergencyContactByID(t *testing.T) { - Convey("Test getEmergencyContactByID", t, func() { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - responseWriter := httptest.NewRecorder() - mockDb := mock_moira_alert.NewMockDatabase(mockCtrl) - - Convey("Successfully get emergency contact by id", func() { - mockDb.EXPECT().GetEmergencyContact(testContactID).Return(testEmergencyContact, nil) - database = mockDb - - expectedEmergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - testRequest := httptest.NewRequest(http.MethodGet, "/emergency-contact/"+testContactID, nil) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - - getEmergencyContactByID(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &dto.EmergencyContact{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, &expectedEmergencyContactDTO) - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Not found error from database", func() { - dbErr := moiradb.ErrNil - mockDb.EXPECT().GetEmergencyContact(testContactID).Return(moira.EmergencyContact{}, dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Resource not found", - ErrorText: fmt.Sprintf("emergency contact with ID '%s' does not exists", testContactID), - } - - testRequest := httptest.NewRequest(http.MethodGet, "/emergency-contact/"+testContactID, nil) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - - getEmergencyContactByID(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusNotFound) - }) - - Convey("Internal error from database", func() { - dbErr := errors.New("get emergency contact error") - mockDb.EXPECT().GetEmergencyContact(testContactID).Return(moira.EmergencyContact{}, dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - - testRequest := httptest.NewRequest(http.MethodGet, "/emergency-contact/"+testContactID, nil) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - - getEmergencyContactByID(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - }) -} - -func TestCreateEmergencyContact(t *testing.T) { - Convey("Test createEmergencyContact", t, func() { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - responseWriter := httptest.NewRecorder() - mockDb := mock_moira_alert.NewMockDatabase(mockCtrl) - - auth := &api.Authorization{ - Enabled: true, - AdminList: map[string]struct{}{login: {}}, - } - - Convey("Successfully create emergency contact", func() { - emergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - - expectedResponse := &dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - } - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - mockDb.EXPECT().GetContact(testContactID).Return(testContact, nil) - mockDb.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &dto.SaveEmergencyContactResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedResponse) - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Try to create emergency contact without contact id", func() { - emergencyContact := moira.EmergencyContact{ - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Invalid request", - ErrorText: controller.ErrEmptyEmergencyContactID.Error(), - } - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusBadRequest) - }) - - Convey("Try to create emergency contact without emergency types", func() { - emergencyContact := moira.EmergencyContact{ - ContactID: testContactID, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Invalid request", - ErrorText: dto.ErrEmptyEmergencyTypes.Error(), - } - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusBadRequest) - }) - - Convey("Try to create emergency contact with invalid emergency type", func() { - emergencyContact := moira.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{ - "notifier_on", - }, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Invalid request", - ErrorText: "'notifier_on' emergency type doesn't exist", - } - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusBadRequest) - }) - - Convey("Internal server error with get contact database error", func() { - emergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - dbErr := errors.New("get contact error") - - mockDb.EXPECT().GetContact(testContactID).Return(moira.ContactData{}, dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - - Convey("Internal server error with save emergency contact database error", func() { - emergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - dbErr := errors.New("save emergency contact error") - - mockDb.EXPECT().GetContact(testContactID).Return(testContact, nil) - mockDb.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact", bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), LoginKey, login)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), AuthKey, auth)) - testRequest.Header.Add("content-type", "application/json") - - createEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - }) -} - -func TestUpdateEmergencyContact(t *testing.T) { - Convey("Test updateEmergencyContact", t, func() { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - responseWriter := httptest.NewRecorder() - mockDb := mock_moira_alert.NewMockDatabase(mockCtrl) - - Convey("Successfully update emergency contact", func() { - emergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - - expectedResponse := &dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - } - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - mockDb.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPut, "/emergency-contact/"+testContactID, bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - testRequest.Header.Add("content-type", "application/json") - - updateEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &dto.SaveEmergencyContactResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedResponse) - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Successfully update emergency contact without contact id in dto", func() { - emergencyContact := moira.EmergencyContact{ - EmergencyTypes: []moira.EmergencyContactType{moira.EmergencyTypeNotifierOff}, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - expectedResponse := &dto.SaveEmergencyContactResponse{ - ContactID: testContactID, - } - - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - mockDb.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(nil) - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPut, "/emergency-contact/"+testContactID, bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - testRequest.Header.Add("content-type", "application/json") - - updateEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &dto.SaveEmergencyContactResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedResponse) - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Invalid Request without emergency types in dto", func() { - emergencyContact := moira.EmergencyContact{ - ContactID: testContactID, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - expectedErr := &api.ErrorResponse{ - StatusText: "Invalid request", - ErrorText: dto.ErrEmptyEmergencyTypes.Error(), - } - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPut, "/emergency-contact/"+testContactID, bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - testRequest.Header.Add("content-type", "application/json") - - updateEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusBadRequest) - }) - - Convey("Invalid Request with undefined emergency type in dto", func() { - emergencyContact := moira.EmergencyContact{ - ContactID: testContactID, - EmergencyTypes: []moira.EmergencyContactType{ - "notifier_on", - }, - } - emergencyContactDTO := dto.EmergencyContact(emergencyContact) - - expectedErr := &api.ErrorResponse{ - StatusText: "Invalid request", - ErrorText: "'notifier_on' emergency type doesn't exist", - } - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPut, "/emergency-contact/"+testContactID, bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - testRequest.Header.Add("content-type", "application/json") - - updateEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusBadRequest) - }) - - Convey("Internal Server Error with database error", func() { - emergencyContactDTO := dto.EmergencyContact(testEmergencyContact) - - dbErr := errors.New("update emergency contact error") - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - jsonEmergencyContact, err := json.Marshal(emergencyContactDTO) - So(err, ShouldBeNil) - - mockDb.EXPECT().SaveEmergencyContact(testEmergencyContact).Return(dbErr) - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPut, "/emergency-contact/"+testContactID, bytes.NewBuffer(jsonEmergencyContact)) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - testRequest.Header.Add("content-type", "application/json") - - updateEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - }) -} - -func TestRemoveEmergencyContact(t *testing.T) { - Convey("Test removeEmergencyContact", t, func() { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - responseWriter := httptest.NewRecorder() - mockDb := mock_moira_alert.NewMockDatabase(mockCtrl) - - Convey("Successfully remove emergency contact", func() { - mockDb.EXPECT().RemoveEmergencyContact(testContactID).Return(nil) - database = mockDb - - testRequest := httptest.NewRequest(http.MethodPost, "/emergency-contact/"+testContactID, http.NoBody) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - - removeEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - - So(response.StatusCode, ShouldEqual, http.StatusOK) - }) - - Convey("Internal server error with remove emergency contact", func() { - dbErr := errors.New("remove emergency contact error") - mockDb.EXPECT().RemoveEmergencyContact(testContactID).Return(dbErr) - database = mockDb - - expectedErr := &api.ErrorResponse{ - StatusText: "Internal Server Error", - ErrorText: dbErr.Error(), - } - - testRequest := httptest.NewRequest(http.MethodDelete, "/emergency-contact/"+testContactID, http.NoBody) - testRequest = testRequest.WithContext(middleware.SetContextValueForTest(testRequest.Context(), ContactIDKey, testContactID)) - - removeEmergencyContact(responseWriter, testRequest) - - response := responseWriter.Result() - defer response.Body.Close() - contentBytes, err := io.ReadAll(response.Body) - So(err, ShouldBeNil) - contents := string(contentBytes) - actual := &api.ErrorResponse{} - err = json.Unmarshal([]byte(contents), actual) - So(err, ShouldBeNil) - - So(actual, ShouldResemble, expectedErr) - So(response.StatusCode, ShouldEqual, http.StatusInternalServerError) - }) - }) -} diff --git a/api/handler/handler.go b/api/handler/handler.go index da7875d4d..27647a8c3 100644 --- a/api/handler/handler.go +++ b/api/handler/handler.go @@ -59,9 +59,6 @@ func NewHandler( // @tag.name contact // @tag.description APIs for working with Moira contacts. For more details, see // - // @tag.name emergency-contact - // @tag.description APIs for working with Moira emergency contacts - // // @tag.name config // @tag.description View Moira's runtime configuration. For more details, see // @@ -118,7 +115,6 @@ func NewHandler( contact(router) contactEvents(router) }) - router.Route("/emergency-contact", emergencyContact) router.Get("/swagger/*", httpSwagger.Handler( httpSwagger.URL("/api/swagger/doc.json"), )) diff --git a/api/handler/team.go b/api/handler/team.go index be09b766e..294c09817 100644 --- a/api/handler/team.go +++ b/api/handler/team.go @@ -29,7 +29,6 @@ func teams(router chi.Router) { router.Get("/settings", getTeamSettings) router.Route("/subscriptions", teamSubscription) router.Route("/contacts", teamContact) - router.Route("/emergency-contacts", teamEmergencyContact) }) } diff --git a/api/handler/team_emergency_contact.go b/api/handler/team_emergency_contact.go deleted file mode 100644 index 07c222371..000000000 --- a/api/handler/team_emergency_contact.go +++ /dev/null @@ -1,53 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/go-chi/chi" - "github.com/go-chi/render" - "github.com/moira-alert/moira/api" - "github.com/moira-alert/moira/api/controller" - "github.com/moira-alert/moira/api/dto" - "github.com/moira-alert/moira/api/middleware" -) - -func teamEmergencyContact(router chi.Router) { - router.Post("/", createTeamEmergencyContact) -} - -// nolint: gofmt,goimports -// -// @summary Create team emergency contact -// @id create-team-emergency-contact -// @tags teamEmergencyContact -// @accept json -// @produce json -// @param teamID path string true "The ID of team" default(bcba82f5-48cf-44c0-b7d6-e1d32c64a88c) -// @param emergency-contact body dto.EmergencyContact true "Emergency contact data" -// @success 200 {object} dto.SaveEmergencyContactResponse "Team emergency contact created successfully" -// @failure 400 {object} api.ErrorInvalidRequestExample "Bad request from client" -// @failure 403 {object} api.ErrorForbiddenExample "Forbidden" -// @failure 404 {object} api.ErrorNotFoundExample "Resource not found" -// @failure 422 {object} api.ErrorRenderExample "Render error" -// @failure 500 {object} api.ErrorInternalServerExample "Internal server error" -// @router /teams/{teamID}/emergency-contacts [post] -func createTeamEmergencyContact(writer http.ResponseWriter, request *http.Request) { - emergencyContactDTO := &dto.EmergencyContact{} - if err := render.Bind(request, emergencyContactDTO); err != nil { - render.Render(writer, request, api.ErrorInvalidRequest(err)) //nolint:errcheck - return - } - - auth := middleware.GetAuth(request) - - response, err := controller.CreateEmergencyContact(database, auth, emergencyContactDTO, "") - if err != nil { - render.Render(writer, request, err) //nolint:errcheck - return - } - - if err := render.Render(writer, request, response); err != nil { - render.Render(writer, request, api.ErrorRender(err)) //nolint:errcheck - return - } -}