Skip to content

feat: add notification preferences database & audit support #14100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Self-review, appeasing CI
Signed-off-by: Danny Kopping <danny@coder.com>
  • Loading branch information
dannykopping committed Aug 5, 2024
commit ee77df8c7d3ff87fecef08af0430dae5e5dbba3b
39 changes: 39 additions & 0 deletions coderd/database/dbauthz/dbauthz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"cdr.dev/slog"

"github.com/coder/coder/v2/coderd/database/db2sdk"
"github.com/coder/coder/v2/coderd/notifications"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/codersdk"

Expand Down Expand Up @@ -2561,6 +2562,10 @@ func (s *MethodTestSuite) TestSystemFunctions() {
AgentID: uuid.New(),
}).Asserts(tpl, policy.ActionCreate)
}))
}

func (s *MethodTestSuite) TestNotifications() {
// System functions
s.Run("AcquireNotificationMessages", s.Subtest(func(db database.Store, check *expects) {
// TODO: update this test once we have a specific role for notifications
check.Args(database.AcquireNotificationMessagesParams{}).Asserts(rbac.ResourceSystem, policy.ActionUpdate)
Expand Down Expand Up @@ -2596,6 +2601,40 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Limit: 10,
}).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))

// Notification templates
s.Run("GetNotificationTemplateById", s.Subtest(func(db database.Store, check *expects) {
user := dbgen.User(s.T(), db, database.User{})
check.Args(user.ID).Asserts(rbac.ResourceNotificationTemplate, policy.ActionRead).
Errors(dbmem.ErrUnimplemented)
}))
s.Run("GetNotificationTemplatesByKind", s.Subtest(func(db database.Store, check *expects) {
check.Args(database.NotificationTemplateKindSystem).
Asserts(rbac.ResourceNotificationTemplate, policy.ActionRead).
Errors(dbmem.ErrUnimplemented)
}))
s.Run("UpdateNotificationTemplateMethodById", s.Subtest(func(db database.Store, check *expects) {
check.Args(database.UpdateNotificationTemplateMethodByIdParams{
Method: database.NullNotificationMethod{NotificationMethod: database.NotificationMethodWebhook, Valid: true},
ID: notifications.TemplateWorkspaceDormant,
}).Asserts(rbac.ResourceNotificationTemplate, policy.ActionUpdate).
Errors(dbmem.ErrUnimplemented)
}))

// Notification preferences
s.Run("GetUserNotificationPreferences", s.Subtest(func(db database.Store, check *expects) {
user := dbgen.User(s.T(), db, database.User{})
check.Args(user.ID).
Asserts(rbac.ResourceNotificationPreference.WithOwner(user.ID.String()), policy.ActionRead)
}))
s.Run("UpdateUserNotificationPreferences", s.Subtest(func(db database.Store, check *expects) {
user := dbgen.User(s.T(), db, database.User{})
check.Args(database.UpdateUserNotificationPreferencesParams{
UserID: user.ID,
NotificationTemplateIds: []uuid.UUID{notifications.TemplateWorkspaceAutoUpdated, notifications.TemplateWorkspaceDeleted},
Disableds: []bool{true, false},
}).Asserts(rbac.ResourceNotificationPreference.WithOwner(user.ID.String()), policy.ActionUpdate)
}))
}

func (s *MethodTestSuite) TestOAuth2ProviderApps() {
Expand Down
4 changes: 2 additions & 2 deletions coderd/rbac/object_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions coderd/rbac/policy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ var RBACPermissions = map[string]PermissionDefinition{
},
"notification_preference": {
Actions: map[Action]ActionDefinition{
ActionRead: actDef("read own notification preferences"),
ActionUpdate: actDef("update own notification preferences"),
ActionRead: actDef("read notification preferences"),
ActionUpdate: actDef("update notification preferences"),
},
},
}
39 changes: 25 additions & 14 deletions coderd/rbac/roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ func TestRolePermissions(t *testing.T) {
},
},
{
// Any owner/admin across may access any users' preferences
// Members may not access other members' preferences
Name: "NotificationPreferencesOwn",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationPreference.WithOwner(currentUser.String()),
Expand All @@ -605,6 +607,7 @@ func TestRolePermissions(t *testing.T) {
},
},
{
// Any owner/admin may access notification templates
Name: "NotificationTemplates",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationTemplate,
Expand All @@ -618,6 +621,23 @@ func TestRolePermissions(t *testing.T) {
},
},
},
{
// Notification preferences are currently not organization-scoped
// Any owner/admin may access any users' preferences
// Members may not access other members' preferences
Name: "NotificationPreferencesOtherUser",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationPreference.InOrg(orgID).WithOwner(uuid.NewString()), // some other user
AuthorizeMap: map[bool][]hasAuthSubjects{
true: {orgAdmin, owner},
false: {
memberMe, templateAdmin, orgUserAdmin, userAdmin,
orgAuditor, orgTemplateAdmin,
otherOrgMember, otherOrgAuditor, otherOrgUserAdmin, otherOrgTemplateAdmin,
otherOrgAdmin, orgMemberMe,
},
},
},
// AnyOrganization tests
{
Name: "CreateOrgMember",
Expand Down Expand Up @@ -659,6 +679,9 @@ func TestRolePermissions(t *testing.T) {
},
},
{
// Notification preferences are currently not organization-scoped
// Any owner/admin across any organization may access any users' preferences
// Members may access their own preferences
Name: "NotificationPreferencesAnyOrg",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationPreference.AnyOrganization().WithOwner(currentUser.String()),
Expand All @@ -672,20 +695,8 @@ func TestRolePermissions(t *testing.T) {
},
},
{
Name: "NotificationPreferencesOtherUser",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationPreference.InOrg(orgID).WithOwner(uuid.NewString()), // some other user
AuthorizeMap: map[bool][]hasAuthSubjects{
true: {orgAdmin, owner},
false: {
memberMe, templateAdmin, orgUserAdmin, userAdmin,
orgAuditor, orgTemplateAdmin,
otherOrgMember, otherOrgAuditor, otherOrgUserAdmin, otherOrgTemplateAdmin,
otherOrgAdmin, orgMemberMe,
},
},
},
{
// Notification templates are currently not organization-scoped
// Any owner/admin across any organization may access notification templates
Name: "NotificationTemplateAnyOrg",
Actions: []policy.Action{policy.ActionRead, policy.ActionUpdate},
Resource: rbac.ResourceNotificationPreference.AnyOrganization(),
Expand Down
4 changes: 2 additions & 2 deletions site/src/api/rbacresources_gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export const RBACResourceActions: Partial<
read: "read licenses",
},
notification_preference: {
read: "read own notification preferences",
update: "update own notification preferences",
read: "read notification preferences",
update: "update notification preferences",
},
notification_template: {
read: "read notification templates",
Expand Down