Skip to content

Commit

Permalink
merge with master
Browse files Browse the repository at this point in the history
  • Loading branch information
almostinf committed May 17, 2024
2 parents 2c933d6 + 1ac8c36 commit 68e38a5
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 41 deletions.
12 changes: 9 additions & 3 deletions api/controller/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ func GetContactById(database moira.Database, contactID string) (*dto.Contact, *a
}

// CreateContact creates new notification contact for current user.
func CreateContact(dataBase moira.Database, contact *dto.Contact, userLogin, teamID string) *api.ErrorResponse {
func CreateContact(dataBase moira.Database, auth *api.Authorization, contact *dto.Contact, userLogin, teamID string) *api.ErrorResponse {
if userLogin != "" && teamID != "" {
return api.ErrorInternalServer(fmt.Errorf("CreateContact: cannot create contact when both userLogin and teamID specified"))
}

// Only admins are allowed to create contacts for other users
if !auth.IsAdmin(userLogin) || contact.User == "" {
contact.User = userLogin
}

contactData := moira.ContactData{
ID: contact.ID,
Name: contact.Name,
User: userLogin,
User: contact.User,
Team: teamID,
Type: contact.Type,
Value: contact.Value,
Expand All @@ -78,7 +84,7 @@ func CreateContact(dataBase moira.Database, contact *dto.Contact, userLogin, tea
if err := dataBase.SaveContact(&contactData); err != nil {
return api.ErrorInternalServer(err)
}
contact.User = userLogin
contact.User = contactData.User
contact.ID = contactData.ID
contact.TeamID = contactData.Team
return nil
Expand Down
87 changes: 75 additions & 12 deletions api/controller/contact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func TestCreateContact(t *testing.T) {
defer mockCtrl.Finish()
const userLogin = "user"
const teamID = "team"
auth := &api.Authorization{Enabled: false}

Convey("Create for user", t, func() {
Convey("Success", func() {
Expand All @@ -121,7 +122,7 @@ func TestCreateContact(t *testing.T) {
Type: "mail",
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, contact, userLogin, "")
err := CreateContact(dataBase, auth, contact, userLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, userLogin)
})
Expand All @@ -140,7 +141,7 @@ func TestCreateContact(t *testing.T) {
}
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, database.ErrNil)
dataBase.EXPECT().SaveContact(&expectedContact).Return(nil)
err := CreateContact(dataBase, &contact, userLogin, "")
err := CreateContact(dataBase, auth, &contact, userLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, userLogin)
So(contact.ID, ShouldResemble, contact.ID)
Expand All @@ -153,7 +154,7 @@ func TestCreateContact(t *testing.T) {
Type: "mail",
}
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, nil)
err := CreateContact(dataBase, contact, userLogin, "")
err := CreateContact(dataBase, auth, contact, userLogin, "")
So(err, ShouldResemble, api.ErrorInvalidRequest(fmt.Errorf("contact with this ID already exists")))
})

Expand All @@ -165,7 +166,7 @@ func TestCreateContact(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, err)
expected := CreateContact(dataBase, contact, userLogin, "")
expected := CreateContact(dataBase, auth, contact, userLogin, "")
So(expected, ShouldResemble, api.ErrorInternalServer(err))
})

Expand All @@ -176,7 +177,7 @@ func TestCreateContact(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().SaveContact(gomock.Any()).Return(err)
expected := CreateContact(dataBase, contact, userLogin, "")
expected := CreateContact(dataBase, auth, contact, userLogin, "")
So(expected, ShouldResemble, &api.ErrorResponse{
ErrorText: err.Error(),
HTTPStatusCode: http.StatusInternalServerError,
Expand All @@ -193,7 +194,7 @@ func TestCreateContact(t *testing.T) {
Type: "mail",
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, contact, "", teamID)
err := CreateContact(dataBase, auth, contact, "", teamID)
So(err, ShouldBeNil)
So(contact.TeamID, ShouldResemble, teamID)
})
Expand All @@ -212,7 +213,7 @@ func TestCreateContact(t *testing.T) {
}
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, database.ErrNil)
dataBase.EXPECT().SaveContact(&expectedContact).Return(nil)
err := CreateContact(dataBase, &contact, "", teamID)
err := CreateContact(dataBase, auth, &contact, "", teamID)
So(err, ShouldBeNil)
So(contact.TeamID, ShouldResemble, teamID)
So(contact.ID, ShouldResemble, contact.ID)
Expand All @@ -234,7 +235,7 @@ func TestCreateContact(t *testing.T) {
}
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, database.ErrNil)
dataBase.EXPECT().SaveContact(&expectedContact).Return(nil)
err := CreateContact(dataBase, &contact, "", teamID)
err := CreateContact(dataBase, auth, &contact, "", teamID)
So(err, ShouldBeNil)
So(contact.TeamID, ShouldResemble, teamID)
So(contact.Name, ShouldResemble, expectedContact.Name)
Expand All @@ -247,7 +248,7 @@ func TestCreateContact(t *testing.T) {
Type: "mail",
}
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, nil)
err := CreateContact(dataBase, contact, "", teamID)
err := CreateContact(dataBase, auth, contact, "", teamID)
So(err, ShouldResemble, api.ErrorInvalidRequest(fmt.Errorf("contact with this ID already exists")))
})

Expand All @@ -259,7 +260,7 @@ func TestCreateContact(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().GetContact(contact.ID).Return(moira.ContactData{}, err)
expected := CreateContact(dataBase, contact, "", teamID)
expected := CreateContact(dataBase, auth, contact, "", teamID)
So(expected, ShouldResemble, api.ErrorInternalServer(err))
})

Expand All @@ -270,7 +271,7 @@ func TestCreateContact(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().SaveContact(gomock.Any()).Return(err)
expected := CreateContact(dataBase, contact, "", teamID)
expected := CreateContact(dataBase, auth, contact, "", teamID)
So(expected, ShouldResemble, &api.ErrorResponse{
ErrorText: err.Error(),
HTTPStatusCode: http.StatusInternalServerError,
Expand All @@ -284,11 +285,73 @@ func TestCreateContact(t *testing.T) {
Value: "[email protected]",
Type: "mail",
}
err := CreateContact(dataBase, contact, userLogin, teamID)
err := CreateContact(dataBase, auth, contact, userLogin, teamID)
So(err, ShouldResemble, api.ErrorInternalServer(fmt.Errorf("CreateContact: cannot create contact when both userLogin and teamID specified")))
})
}

func TestAdminsCreatesContact(t *testing.T) {
mockCtrl := gomock.NewController(t)
dataBase := mock_moira_alert.NewMockDatabase(mockCtrl)
defer mockCtrl.Finish()
const userLogin = "user"
const adminLogin = "admin"
auth := &api.Authorization{
Enabled: true,
AdminList: map[string]struct{}{adminLogin: {}},
}

Convey("Create for user", t, func() {
Convey("The same user", func() {
contact := &dto.Contact{
Value: "[email protected]",
Type: "mail",
User: userLogin,
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, auth, contact, userLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, userLogin)
})

Convey("The same user by admin", func() {
contact := &dto.Contact{
Value: "[email protected]",
Type: "mail",
User: adminLogin,
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, auth, contact, adminLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, adminLogin)
})

Convey("Non admin can not create contact for other user", func() {
contact := &dto.Contact{
Value: "[email protected]",
Type: "mail",
User: adminLogin,
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, auth, contact, userLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, userLogin)
})

Convey("Admin can create contact for other user", func() {
contact := &dto.Contact{
Value: "[email protected]",
Type: "mail",
User: userLogin,
}
dataBase.EXPECT().SaveContact(gomock.Any()).Return(nil)
err := CreateContact(dataBase, auth, contact, adminLogin, "")
So(err, ShouldBeNil)
So(contact.User, ShouldResemble, userLogin)
})
})
}

func TestUpdateContact(t *testing.T) {
mockCtrl := gomock.NewController(t)
dataBase := mock_moira_alert.NewMockDatabase(mockCtrl)
Expand Down
7 changes: 5 additions & 2 deletions api/controller/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func GetUserSubscriptions(database moira.Database, userLogin string) (*dto.Subsc
}

// CreateSubscription create or update subscription.
func CreateSubscription(dataBase moira.Database, userLogin, teamID string, subscription *dto.Subscription) *api.ErrorResponse {
func CreateSubscription(dataBase moira.Database, auth *api.Authorization, userLogin, teamID string, subscription *dto.Subscription) *api.ErrorResponse {
if userLogin != "" && teamID != "" {
return api.ErrorInternalServer(fmt.Errorf("CreateSubscription: cannot create subscription when both userLogin and teamID specified"))
}
Expand All @@ -56,7 +56,10 @@ func CreateSubscription(dataBase moira.Database, userLogin, teamID string, subsc
}
}

subscription.User = userLogin
// Only admins are allowed to create subscriptions for other users
if !auth.IsAdmin(userLogin) || subscription.User == "" {
subscription.User = userLogin
}
subscription.TeamID = teamID
data := moira.SubscriptionData(*subscription)
if err := dataBase.SaveSubscription(&data); err != nil {
Expand Down
77 changes: 66 additions & 11 deletions api/controller/subscription_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,13 @@ func TestCreateSubscription(t *testing.T) {
dataBase := mock_moira_alert.NewMockDatabase(mockCtrl)
const login = "user"
const teamID = "testTeam"
auth := &api.Authorization{Enabled: false}

Convey("Create for user", t, func() {
Convey("Success create", func() {
subscription := dto.Subscription{ID: ""}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, login, "", &subscription)
err := CreateSubscription(dataBase, auth, login, "", &subscription)
So(err, ShouldBeNil)
})

Expand All @@ -191,7 +192,7 @@ func TestCreateSubscription(t *testing.T) {
}
dataBase.EXPECT().GetSubscription(sub.ID).Return(moira.SubscriptionData{}, database.ErrNil)
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, login, "", sub)
err := CreateSubscription(dataBase, auth, login, "", sub)
So(err, ShouldBeNil)
So(sub.User, ShouldResemble, login)
So(sub.ID, ShouldResemble, sub.ID)
Expand All @@ -202,7 +203,7 @@ func TestCreateSubscription(t *testing.T) {
ID: uuid.Must(uuid.NewV4()).String(),
}
dataBase.EXPECT().GetSubscription(subscription.ID).Return(moira.SubscriptionData{}, nil)
err := CreateSubscription(dataBase, login, "", subscription)
err := CreateSubscription(dataBase, auth, login, "", subscription)
So(err, ShouldResemble, api.ErrorInvalidRequest(fmt.Errorf("subscription with this ID already exists")))
})

Expand All @@ -212,23 +213,23 @@ func TestCreateSubscription(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().GetSubscription(subscription.ID).Return(moira.SubscriptionData{}, err)
expected := CreateSubscription(dataBase, login, "", subscription)
expected := CreateSubscription(dataBase, auth, login, "", subscription)
So(expected, ShouldResemble, api.ErrorInternalServer(err))
})

Convey("Error save subscription", func() {
subscription := dto.Subscription{ID: ""}
expected := fmt.Errorf("oooops! Can not create subscription")
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(expected)
err := CreateSubscription(dataBase, login, "", &subscription)
err := CreateSubscription(dataBase, auth, login, "", &subscription)
So(err, ShouldResemble, api.ErrorInternalServer(expected))
})
})
Convey("Create for team", t, func() {
Convey("Success create", func() {
subscription := dto.Subscription{ID: ""}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, "", teamID, &subscription)
err := CreateSubscription(dataBase, auth, "", teamID, &subscription)
So(err, ShouldBeNil)
})

Expand All @@ -238,7 +239,7 @@ func TestCreateSubscription(t *testing.T) {
}
dataBase.EXPECT().GetSubscription(sub.ID).Return(moira.SubscriptionData{}, database.ErrNil)
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, "", teamID, sub)
err := CreateSubscription(dataBase, auth, "", teamID, sub)
So(err, ShouldBeNil)
So(sub.TeamID, ShouldResemble, teamID)
So(sub.ID, ShouldResemble, sub.ID)
Expand All @@ -249,7 +250,7 @@ func TestCreateSubscription(t *testing.T) {
ID: uuid.Must(uuid.NewV4()).String(),
}
dataBase.EXPECT().GetSubscription(subscription.ID).Return(moira.SubscriptionData{}, nil)
err := CreateSubscription(dataBase, "", teamID, subscription)
err := CreateSubscription(dataBase, auth, "", teamID, subscription)
So(err, ShouldResemble, api.ErrorInvalidRequest(fmt.Errorf("subscription with this ID already exists")))
})

Expand All @@ -259,25 +260,79 @@ func TestCreateSubscription(t *testing.T) {
}
err := fmt.Errorf("oooops! Can not write contact")
dataBase.EXPECT().GetSubscription(subscription.ID).Return(moira.SubscriptionData{}, err)
expected := CreateSubscription(dataBase, "", teamID, subscription)
expected := CreateSubscription(dataBase, auth, "", teamID, subscription)
So(expected, ShouldResemble, api.ErrorInternalServer(err))
})

Convey("Error save subscription", func() {
subscription := dto.Subscription{ID: ""}
expected := fmt.Errorf("oooops! Can not create subscription")
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(expected)
err := CreateSubscription(dataBase, "", teamID, &subscription)
err := CreateSubscription(dataBase, auth, "", teamID, &subscription)
So(err, ShouldResemble, api.ErrorInternalServer(expected))
})
})
Convey("Error on create with both: userLogin and teamID specified", t, func() {
subscription := &dto.Subscription{}
err := CreateSubscription(dataBase, login, teamID, subscription)
err := CreateSubscription(dataBase, auth, login, teamID, subscription)
So(err, ShouldResemble, api.ErrorInternalServer(fmt.Errorf("CreateSubscription: cannot create subscription when both userLogin and teamID specified")))
})
}

func TestAdminsCreatesSubscription(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
dataBase := mock_moira_alert.NewMockDatabase(mockCtrl)
const userLogin = "user"
const adminLogin = "admin"
auth := &api.Authorization{
Enabled: true,
AdminList: map[string]struct{}{adminLogin: {}},
}

Convey("Create for user", t, func() {
Convey("For same user", func() {
subscription := dto.Subscription{
User: userLogin,
}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, auth, userLogin, "", &subscription)
So(err, ShouldBeNil)
So(subscription.User, ShouldEqual, userLogin)
})

Convey("For same admin", func() {
subscription := dto.Subscription{
User: adminLogin,
}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, auth, adminLogin, "", &subscription)
So(err, ShouldBeNil)
So(subscription.User, ShouldEqual, adminLogin)
})

Convey("User can not create subscription for other user", func() {
subscription := dto.Subscription{
User: adminLogin,
}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, auth, userLogin, "", &subscription)
So(err, ShouldBeNil)
So(subscription.User, ShouldEqual, userLogin)
})

Convey("Admin can create subscription for other user", func() {
subscription := dto.Subscription{
User: userLogin,
}
dataBase.EXPECT().SaveSubscription(gomock.Any()).Return(nil)
err := CreateSubscription(dataBase, auth, adminLogin, "", &subscription)
So(err, ShouldBeNil)
So(subscription.User, ShouldEqual, userLogin)
})
})
}

func TestCheckUserPermissionsForSubscription(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
Expand Down
Loading

0 comments on commit 68e38a5

Please sign in to comment.