mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
chore: create ResourceNotificationMessage and AsNotifier (#15301)
Closes https://github.com/coder/coder/issues/15213 This PR enables sending notifications without requiring the auth system context, instead using a new auth notifier context.
This commit is contained in:
+2
-2
@@ -916,8 +916,8 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
|
||||
return xerrors.Errorf("failed to instantiate notification manager: %w", err)
|
||||
}
|
||||
|
||||
// nolint:gocritic // TODO: create own role.
|
||||
notificationsManager.Run(dbauthz.AsSystemRestricted(ctx))
|
||||
// nolint:gocritic // We need to run the manager in a notifier context.
|
||||
notificationsManager.Run(dbauthz.AsNotifier(ctx))
|
||||
|
||||
// Run report generator to distribute periodic reports.
|
||||
notificationReportGenerator := reports.NewReportGenerator(ctx, logger.Named("notifications.report_generator"), options.Database, options.NotificationsEnqueuer, quartz.NewReal())
|
||||
|
||||
Generated
+2
@@ -12265,6 +12265,7 @@ const docTemplate = `{
|
||||
"group_member",
|
||||
"idpsync_settings",
|
||||
"license",
|
||||
"notification_message",
|
||||
"notification_preference",
|
||||
"notification_template",
|
||||
"oauth2_app",
|
||||
@@ -12298,6 +12299,7 @@ const docTemplate = `{
|
||||
"ResourceGroupMember",
|
||||
"ResourceIdpsyncSettings",
|
||||
"ResourceLicense",
|
||||
"ResourceNotificationMessage",
|
||||
"ResourceNotificationPreference",
|
||||
"ResourceNotificationTemplate",
|
||||
"ResourceOauth2App",
|
||||
|
||||
Generated
+2
@@ -11073,6 +11073,7 @@
|
||||
"group_member",
|
||||
"idpsync_settings",
|
||||
"license",
|
||||
"notification_message",
|
||||
"notification_preference",
|
||||
"notification_template",
|
||||
"oauth2_app",
|
||||
@@ -11106,6 +11107,7 @@
|
||||
"ResourceGroupMember",
|
||||
"ResourceIdpsyncSettings",
|
||||
"ResourceLicense",
|
||||
"ResourceNotificationMessage",
|
||||
"ResourceNotificationPreference",
|
||||
"ResourceNotificationTemplate",
|
||||
"ResourceOauth2App",
|
||||
|
||||
@@ -264,6 +264,23 @@ var (
|
||||
Scope: rbac.ScopeAll,
|
||||
}.WithCachedASTValue()
|
||||
|
||||
subjectNotifier = rbac.Subject{
|
||||
FriendlyName: "Notifier",
|
||||
ID: uuid.Nil.String(),
|
||||
Roles: rbac.Roles([]rbac.Role{
|
||||
{
|
||||
Identifier: rbac.RoleIdentifier{Name: "notifier"},
|
||||
DisplayName: "Notifier",
|
||||
Site: rbac.Permissions(map[string][]policy.Action{
|
||||
rbac.ResourceNotificationMessage.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
|
||||
}),
|
||||
Org: map[string][]rbac.Permission{},
|
||||
User: []rbac.Permission{},
|
||||
},
|
||||
}),
|
||||
Scope: rbac.ScopeAll,
|
||||
}.WithCachedASTValue()
|
||||
|
||||
subjectSystemRestricted = rbac.Subject{
|
||||
FriendlyName: "System",
|
||||
ID: uuid.Nil.String(),
|
||||
@@ -287,6 +304,7 @@ var (
|
||||
rbac.ResourceWorkspace.Type: {policy.ActionUpdate, policy.ActionDelete, policy.ActionWorkspaceStart, policy.ActionWorkspaceStop, policy.ActionSSH},
|
||||
rbac.ResourceWorkspaceProxy.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
|
||||
rbac.ResourceDeploymentConfig.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
|
||||
rbac.ResourceNotificationMessage.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
|
||||
rbac.ResourceNotificationPreference.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
|
||||
rbac.ResourceNotificationTemplate.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
|
||||
rbac.ResourceCryptoKey.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
|
||||
@@ -327,6 +345,12 @@ func AsKeyReader(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, authContextKey{}, subjectCryptoKeyReader)
|
||||
}
|
||||
|
||||
// AsNotifier returns a context with an actor that has permissions required for
|
||||
// creating/reading/updating/deleting notifications.
|
||||
func AsNotifier(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, authContextKey{}, subjectNotifier)
|
||||
}
|
||||
|
||||
// AsSystemRestricted returns a context with an actor that has permissions
|
||||
// required for various system operations (login, logout, metrics cache).
|
||||
func AsSystemRestricted(ctx context.Context) context.Context {
|
||||
@@ -950,7 +974,7 @@ func (q *querier) AcquireLock(ctx context.Context, id int64) error {
|
||||
}
|
||||
|
||||
func (q *querier) AcquireNotificationMessages(ctx context.Context, arg database.AcquireNotificationMessagesParams) ([]database.AcquireNotificationMessagesRow, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceNotificationMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.AcquireNotificationMessages(ctx, arg)
|
||||
@@ -1001,14 +1025,14 @@ func (q *querier) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg databa
|
||||
}
|
||||
|
||||
func (q *querier) BulkMarkNotificationMessagesFailed(ctx context.Context, arg database.BulkMarkNotificationMessagesFailedParams) (int64, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceNotificationMessage); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return q.db.BulkMarkNotificationMessagesFailed(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg database.BulkMarkNotificationMessagesSentParams) (int64, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceNotificationMessage); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return q.db.BulkMarkNotificationMessagesSent(ctx, arg)
|
||||
@@ -1185,7 +1209,7 @@ func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Contex
|
||||
}
|
||||
|
||||
func (q *querier) DeleteOldNotificationMessages(ctx context.Context) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceNotificationMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.DeleteOldNotificationMessages(ctx)
|
||||
@@ -1307,7 +1331,7 @@ func (q *querier) DeleteWorkspaceAgentPortSharesByTemplate(ctx context.Context,
|
||||
}
|
||||
|
||||
func (q *querier) EnqueueNotificationMessage(ctx context.Context, arg database.EnqueueNotificationMessageParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceNotificationMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.EnqueueNotificationMessage(ctx, arg)
|
||||
@@ -1321,7 +1345,7 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error {
|
||||
}
|
||||
|
||||
func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.FetchNewMessageMetadataParams) (database.FetchNewMessageMetadataRow, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceNotificationMessage); err != nil {
|
||||
return database.FetchNewMessageMetadataRow{}, err
|
||||
}
|
||||
return q.db.FetchNewMessageMetadata(ctx, arg)
|
||||
@@ -1686,7 +1710,7 @@ func (q *querier) GetLogoURL(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
func (q *querier) GetNotificationMessagesByStatus(ctx context.Context, arg database.GetNotificationMessagesByStatusParams) ([]database.NotificationMessage, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceNotificationMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetNotificationMessagesByStatus(ctx, arg)
|
||||
|
||||
@@ -2888,40 +2888,33 @@ func (s *MethodTestSuite) TestSystemFunctions() {
|
||||
|
||||
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)
|
||||
s.Run("AcquireNotificationMessages", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.AcquireNotificationMessagesParams{}).Asserts(rbac.ResourceNotificationMessage, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("BulkMarkNotificationMessagesFailed", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
check.Args(database.BulkMarkNotificationMessagesFailedParams{}).Asserts(rbac.ResourceSystem, policy.ActionUpdate)
|
||||
s.Run("BulkMarkNotificationMessagesFailed", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.BulkMarkNotificationMessagesFailedParams{}).Asserts(rbac.ResourceNotificationMessage, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("BulkMarkNotificationMessagesSent", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
check.Args(database.BulkMarkNotificationMessagesSentParams{}).Asserts(rbac.ResourceSystem, policy.ActionUpdate)
|
||||
s.Run("BulkMarkNotificationMessagesSent", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.BulkMarkNotificationMessagesSentParams{}).Asserts(rbac.ResourceNotificationMessage, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("DeleteOldNotificationMessages", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete)
|
||||
s.Run("DeleteOldNotificationMessages", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args().Asserts(rbac.ResourceNotificationMessage, policy.ActionDelete)
|
||||
}))
|
||||
s.Run("EnqueueNotificationMessage", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
s.Run("EnqueueNotificationMessage", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.EnqueueNotificationMessageParams{
|
||||
Method: database.NotificationMethodWebhook,
|
||||
Payload: []byte("{}"),
|
||||
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
|
||||
}).Asserts(rbac.ResourceNotificationMessage, policy.ActionCreate)
|
||||
}))
|
||||
s.Run("FetchNewMessageMetadata", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
u := dbgen.User(s.T(), db, database.User{})
|
||||
check.Args(database.FetchNewMessageMetadataParams{UserID: u.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead)
|
||||
check.Args(database.FetchNewMessageMetadataParams{UserID: u.ID}).Asserts(rbac.ResourceNotificationMessage, policy.ActionRead)
|
||||
}))
|
||||
s.Run("GetNotificationMessagesByStatus", s.Subtest(func(db database.Store, check *expects) {
|
||||
// TODO: update this test once we have a specific role for notifications
|
||||
s.Run("GetNotificationMessagesByStatus", s.Subtest(func(_ database.Store, check *expects) {
|
||||
check.Args(database.GetNotificationMessagesByStatusParams{
|
||||
Status: database.NotificationMessageStatusLeased,
|
||||
Limit: 10,
|
||||
}).Asserts(rbac.ResourceSystem, policy.ActionRead)
|
||||
}).Asserts(rbac.ResourceNotificationMessage, policy.ActionRead)
|
||||
}))
|
||||
|
||||
// Notification templates
|
||||
|
||||
@@ -71,7 +71,7 @@ func TestBasicNotificationRoundtrip(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
method := database.NotificationMethodSmtp
|
||||
@@ -135,7 +135,7 @@ func TestSMTPDispatch(t *testing.T) {
|
||||
// SETUP
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -197,7 +197,7 @@ func TestWebhookDispatch(t *testing.T) {
|
||||
// SETUP
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -281,7 +281,7 @@ func TestBackpressure(t *testing.T) {
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitShort))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitShort))
|
||||
|
||||
const method = database.NotificationMethodWebhook
|
||||
cfg := defaultNotificationsConfig(method)
|
||||
@@ -407,7 +407,7 @@ func TestRetries(t *testing.T) {
|
||||
|
||||
const maxAttempts = 3
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -501,7 +501,7 @@ func TestExpiredLeaseIsRequeued(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -521,7 +521,7 @@ func TestExpiredLeaseIsRequeued(t *testing.T) {
|
||||
noopInterceptor := newNoopStoreSyncer(store)
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
mgrCtx, cancelManagerCtx := context.WithCancel(dbauthz.AsSystemRestricted(context.Background()))
|
||||
mgrCtx, cancelManagerCtx := context.WithCancel(dbauthz.AsNotifier(context.Background()))
|
||||
t.Cleanup(cancelManagerCtx)
|
||||
|
||||
mgr, err := notifications.NewManager(cfg, noopInterceptor, defaultHelpers(), createMetrics(), logger.Named("manager"))
|
||||
@@ -626,7 +626,7 @@ func TestNotifierPaused(t *testing.T) {
|
||||
// Setup.
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -1081,7 +1081,7 @@ func TestNotificationTemplates_Golden(t *testing.T) {
|
||||
}()
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
|
||||
// smtp config shared between client and server
|
||||
smtpConfig := codersdk.NotificationsEmailConfig{
|
||||
@@ -1160,12 +1160,14 @@ func TestNotificationTemplates_Golden(t *testing.T) {
|
||||
// as appearance changes are enterprise features and we do not want to mix those
|
||||
// can't use the api
|
||||
if tc.appName != "" {
|
||||
err = (*db).UpsertApplicationName(ctx, "Custom Application")
|
||||
// nolint:gocritic // Unit test.
|
||||
err = (*db).UpsertApplicationName(dbauthz.AsSystemRestricted(ctx), "Custom Application")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if tc.logoURL != "" {
|
||||
err = (*db).UpsertLogoURL(ctx, "https://custom.application/logo.png")
|
||||
// nolint:gocritic // Unit test.
|
||||
err = (*db).UpsertLogoURL(dbauthz.AsSystemRestricted(ctx), "https://custom.application/logo.png")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -1248,7 +1250,7 @@ func TestNotificationTemplates_Golden(t *testing.T) {
|
||||
}()
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
|
||||
// Spin up the mock webhook server
|
||||
var body []byte
|
||||
@@ -1376,7 +1378,7 @@ func TestDisabledBeforeEnqueue(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -1412,7 +1414,7 @@ func TestDisabledAfterEnqueue(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -1469,7 +1471,7 @@ func TestCustomNotificationMethod(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
@@ -1573,7 +1575,7 @@ func TestNotificationsTemplates(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
api := coderdtest.New(t, createOpts(t))
|
||||
|
||||
// GIVEN: the first user (owner) and a regular member
|
||||
@@ -1610,7 +1612,7 @@ func TestNotificationDuplicates(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint:gocritic // Unit test.
|
||||
ctx := dbauthz.AsSystemRestricted(testutil.Context(t, testutil.WaitSuperLong))
|
||||
ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong))
|
||||
store, _ := dbtestutil.NewDB(t)
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
|
||||
@@ -129,6 +129,16 @@ var (
|
||||
Type: "license",
|
||||
}
|
||||
|
||||
// ResourceNotificationMessage
|
||||
// Valid Actions
|
||||
// - "ActionCreate" :: create notification messages
|
||||
// - "ActionDelete" :: delete notification messages
|
||||
// - "ActionRead" :: read notification messages
|
||||
// - "ActionUpdate" :: update notification messages
|
||||
ResourceNotificationMessage = Object{
|
||||
Type: "notification_message",
|
||||
}
|
||||
|
||||
// ResourceNotificationPreference
|
||||
// Valid Actions
|
||||
// - "ActionRead" :: read notification preferences
|
||||
@@ -318,6 +328,7 @@ func AllResources() []Objecter {
|
||||
ResourceGroupMember,
|
||||
ResourceIdpsyncSettings,
|
||||
ResourceLicense,
|
||||
ResourceNotificationMessage,
|
||||
ResourceNotificationPreference,
|
||||
ResourceNotificationTemplate,
|
||||
ResourceOauth2App,
|
||||
|
||||
@@ -262,6 +262,14 @@ var RBACPermissions = map[string]PermissionDefinition{
|
||||
ActionDelete: actDef(""),
|
||||
},
|
||||
},
|
||||
"notification_message": {
|
||||
Actions: map[Action]ActionDefinition{
|
||||
ActionCreate: actDef("create notification messages"),
|
||||
ActionRead: actDef("read notification messages"),
|
||||
ActionUpdate: actDef("update notification messages"),
|
||||
ActionDelete: actDef("delete notification messages"),
|
||||
},
|
||||
},
|
||||
"notification_template": {
|
||||
Actions: map[Action]ActionDefinition{
|
||||
ActionRead: actDef("read notification templates"),
|
||||
|
||||
@@ -647,6 +647,21 @@ func TestRolePermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "NotificationMessages",
|
||||
Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
|
||||
Resource: rbac.ResourceNotificationMessage,
|
||||
AuthorizeMap: map[bool][]hasAuthSubjects{
|
||||
true: {owner},
|
||||
false: {
|
||||
memberMe, orgMemberMe, otherOrgMember,
|
||||
orgAdmin, otherOrgAdmin,
|
||||
orgAuditor, otherOrgAuditor,
|
||||
templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin,
|
||||
userAdmin, orgUserAdmin, otherOrgUserAdmin,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Notification preferences are currently not organization-scoped
|
||||
// Any owner/admin may access any users' preferences
|
||||
|
||||
+2
-2
@@ -878,8 +878,8 @@ func (api *API) notifyUsersOfTemplateDeprecation(ctx context.Context, template d
|
||||
|
||||
for userID := range users {
|
||||
_, err = api.NotificationsEnqueuer.Enqueue(
|
||||
//nolint:gocritic // We need the system auth context to be able to send the deprecation notification.
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
//nolint:gocritic // We need the notifier auth context to be able to send the deprecation notification.
|
||||
dbauthz.AsNotifier(ctx),
|
||||
userID,
|
||||
notifications.TemplateTemplateDeprecated,
|
||||
map[string]string{
|
||||
|
||||
+2
-2
@@ -298,8 +298,8 @@ func (api *API) postRequestOneTimePasscode(rw http.ResponseWriter, r *http.Reque
|
||||
|
||||
func (api *API) notifyUserRequestedOneTimePasscode(ctx context.Context, user database.User, passcode string) error {
|
||||
_, err := api.NotificationsEnqueuer.Enqueue(
|
||||
//nolint:gocritic // We need the system auth context to be able to send the user their one-time passcode.
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
//nolint:gocritic // We need the notifier auth context to be able to send the user their one-time passcode.
|
||||
dbauthz.AsNotifier(ctx),
|
||||
user.ID,
|
||||
notifications.TemplateUserRequestedOneTimePasscode,
|
||||
map[string]string{"one_time_passcode": passcode},
|
||||
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
ResourceGroupMember RBACResource = "group_member"
|
||||
ResourceIdpsyncSettings RBACResource = "idpsync_settings"
|
||||
ResourceLicense RBACResource = "license"
|
||||
ResourceNotificationMessage RBACResource = "notification_message"
|
||||
ResourceNotificationPreference RBACResource = "notification_preference"
|
||||
ResourceNotificationTemplate RBACResource = "notification_template"
|
||||
ResourceOauth2App RBACResource = "oauth2_app"
|
||||
@@ -72,6 +73,7 @@ var RBACResourceActions = map[RBACResource][]RBACAction{
|
||||
ResourceGroupMember: {ActionRead},
|
||||
ResourceIdpsyncSettings: {ActionRead, ActionUpdate},
|
||||
ResourceLicense: {ActionCreate, ActionDelete, ActionRead},
|
||||
ResourceNotificationMessage: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
ResourceNotificationPreference: {ActionRead, ActionUpdate},
|
||||
ResourceNotificationTemplate: {ActionRead, ActionUpdate},
|
||||
ResourceOauth2App: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
|
||||
Generated
+5
@@ -193,6 +193,7 @@ Status Code **200**
|
||||
| `resource_type` | `group_member` |
|
||||
| `resource_type` | `idpsync_settings` |
|
||||
| `resource_type` | `license` |
|
||||
| `resource_type` | `notification_message` |
|
||||
| `resource_type` | `notification_preference` |
|
||||
| `resource_type` | `notification_template` |
|
||||
| `resource_type` | `oauth2_app` |
|
||||
@@ -353,6 +354,7 @@ Status Code **200**
|
||||
| `resource_type` | `group_member` |
|
||||
| `resource_type` | `idpsync_settings` |
|
||||
| `resource_type` | `license` |
|
||||
| `resource_type` | `notification_message` |
|
||||
| `resource_type` | `notification_preference` |
|
||||
| `resource_type` | `notification_template` |
|
||||
| `resource_type` | `oauth2_app` |
|
||||
@@ -513,6 +515,7 @@ Status Code **200**
|
||||
| `resource_type` | `group_member` |
|
||||
| `resource_type` | `idpsync_settings` |
|
||||
| `resource_type` | `license` |
|
||||
| `resource_type` | `notification_message` |
|
||||
| `resource_type` | `notification_preference` |
|
||||
| `resource_type` | `notification_template` |
|
||||
| `resource_type` | `oauth2_app` |
|
||||
@@ -642,6 +645,7 @@ Status Code **200**
|
||||
| `resource_type` | `group_member` |
|
||||
| `resource_type` | `idpsync_settings` |
|
||||
| `resource_type` | `license` |
|
||||
| `resource_type` | `notification_message` |
|
||||
| `resource_type` | `notification_preference` |
|
||||
| `resource_type` | `notification_template` |
|
||||
| `resource_type` | `oauth2_app` |
|
||||
@@ -901,6 +905,7 @@ Status Code **200**
|
||||
| `resource_type` | `group_member` |
|
||||
| `resource_type` | `idpsync_settings` |
|
||||
| `resource_type` | `license` |
|
||||
| `resource_type` | `notification_message` |
|
||||
| `resource_type` | `notification_preference` |
|
||||
| `resource_type` | `notification_template` |
|
||||
| `resource_type` | `oauth2_app` |
|
||||
|
||||
Generated
+1
@@ -4491,6 +4491,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
|
||||
| `group_member` |
|
||||
| `idpsync_settings` |
|
||||
| `license` |
|
||||
| `notification_message` |
|
||||
| `notification_preference` |
|
||||
| `notification_template` |
|
||||
| `oauth2_app` |
|
||||
|
||||
@@ -70,6 +70,12 @@ export const RBACResourceActions: Partial<
|
||||
delete: "delete license",
|
||||
read: "read licenses",
|
||||
},
|
||||
notification_message: {
|
||||
create: "create notification messages",
|
||||
delete: "delete notification messages",
|
||||
read: "read notification messages",
|
||||
update: "update notification messages",
|
||||
},
|
||||
notification_preference: {
|
||||
read: "read notification preferences",
|
||||
update: "update notification preferences",
|
||||
|
||||
Generated
+2
-2
@@ -2198,8 +2198,8 @@ export type RBACAction = "application_connect" | "assign" | "create" | "delete"
|
||||
export const RBACActions: RBACAction[] = ["application_connect", "assign", "create", "delete", "read", "read_personal", "ssh", "start", "stop", "update", "update_personal", "use", "view_insights"]
|
||||
|
||||
// From codersdk/rbacresources_gen.go
|
||||
export type RBACResource = "*" | "api_key" | "assign_org_role" | "assign_role" | "audit_log" | "crypto_key" | "debug_info" | "deployment_config" | "deployment_stats" | "file" | "group" | "group_member" | "idpsync_settings" | "license" | "notification_preference" | "notification_template" | "oauth2_app" | "oauth2_app_code_token" | "oauth2_app_secret" | "organization" | "organization_member" | "provisioner_daemon" | "provisioner_keys" | "replicas" | "system" | "tailnet_coordinator" | "template" | "user" | "workspace" | "workspace_dormant" | "workspace_proxy"
|
||||
export const RBACResources: RBACResource[] = ["*", "api_key", "assign_org_role", "assign_role", "audit_log", "crypto_key", "debug_info", "deployment_config", "deployment_stats", "file", "group", "group_member", "idpsync_settings", "license", "notification_preference", "notification_template", "oauth2_app", "oauth2_app_code_token", "oauth2_app_secret", "organization", "organization_member", "provisioner_daemon", "provisioner_keys", "replicas", "system", "tailnet_coordinator", "template", "user", "workspace", "workspace_dormant", "workspace_proxy"]
|
||||
export type RBACResource = "*" | "api_key" | "assign_org_role" | "assign_role" | "audit_log" | "crypto_key" | "debug_info" | "deployment_config" | "deployment_stats" | "file" | "group" | "group_member" | "idpsync_settings" | "license" | "notification_message" | "notification_preference" | "notification_template" | "oauth2_app" | "oauth2_app_code_token" | "oauth2_app_secret" | "organization" | "organization_member" | "provisioner_daemon" | "provisioner_keys" | "replicas" | "system" | "tailnet_coordinator" | "template" | "user" | "workspace" | "workspace_dormant" | "workspace_proxy"
|
||||
export const RBACResources: RBACResource[] = ["*", "api_key", "assign_org_role", "assign_role", "audit_log", "crypto_key", "debug_info", "deployment_config", "deployment_stats", "file", "group", "group_member", "idpsync_settings", "license", "notification_message", "notification_preference", "notification_template", "oauth2_app", "oauth2_app_code_token", "oauth2_app_secret", "organization", "organization_member", "provisioner_daemon", "provisioner_keys", "replicas", "system", "tailnet_coordinator", "template", "user", "workspace", "workspace_dormant", "workspace_proxy"]
|
||||
|
||||
// From codersdk/audit.go
|
||||
export type ResourceType = "api_key" | "convert_login" | "custom_role" | "git_ssh_key" | "group" | "health_settings" | "license" | "notifications_settings" | "oauth2_provider_app" | "oauth2_provider_app_secret" | "organization" | "template" | "template_version" | "user" | "workspace" | "workspace_build" | "workspace_proxy"
|
||||
|
||||
Reference in New Issue
Block a user