Skip to content

Commit

Permalink
feat: Allow sending notifications via admin route (#4279)
Browse files Browse the repository at this point in the history
  • Loading branch information
taratatach authored Jan 4, 2024
2 parents 49ec815 + ddfe488 commit f4ced11
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 1 deletion.
64 changes: 64 additions & 0 deletions docs/admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,70 @@ Content-Type: application/zip
Content-Disposition: attachment; filename="alice.cozy.localhost - part001.zip"
```

### POST /instances/:domain/notifications

This endpoint allows to send a notification via the notification center. Both
the notification declaration and its properties need to be passed in the body.
These notifications cannot use templates defined in cozy-stack though so their
e-mail content must be provided directly (at least in HTML).

When the request is successful, the generated notification object is returned.

```http
POST /instances/alice.cozy.localhost/notifications HTTP/1.1
Authorization: Bearer ...
Content-Type: application/json
```

```json
{
"notification": {
"category": "account-balance",
"category_id": "my-bank",
"title": "Your account balance is not OK",
"message": "Warning: we have detected a negative balance in your my-bank",
"priority": "high",
"state": "-1",
"preferred_channels": ["mobile"],
"content": "Hello,\r\nWe have detected a negative balance in your my-bank account.",
"content_html": "<html>\r\n\t<body>\r\n\t<p>Hello,<br/>We have detected a negative balance in your my-bank account.</p>\r\n\t</body>\r\n\t</html>"
},
"properties": {
"description": "Alert the user when its account balance is negative",
"collapsible": true,
"multiple": true,
"stateful": true,
"default_priority": "high"
}
}
```

#### Response

```http
HTTP/1.1 201 Created
Content-Type: application/json
```

```json
{
"_id": "c57a548c-7602-11e7-933b-6f27603d27da",
"_rev": "1-1f2903f9a867",
"source_id": "cozy/cli//account-balance/my-bank",
"originator": "cli",
"category": "account-balance",
"category_id": "my-bank",
"created_at": "2024-01-04T15:23:01.832Z",
"last_sent": "2024-01-04T15:23:01.832Z",
"title": "Your account balance is not OK",
"message": "Warning: we have detected a negative balance in your my-bank",
"priority": "high",
"state": "-1",
"content": "Hello,\r\nWe have detected a negative balance in your my-bank account.",
"contentHTML": "<html>\r\n\t<body>\r\n\t<p>Hello,<br/>We have detected a negative balance in your my-bank account.</p>\r\n\t</body>\r\n\t</html>"
}
```

## Contexts

### GET /instances/contexts
Expand Down
2 changes: 1 addition & 1 deletion docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ This endpoint can be used to push a new notification to the user.
Notifications fields are:

- `category` (string): name of the notification category
- `category_id` (string): category name if the category is multiple
- `category_id` (string): name of the notification sub-category if relevant (optional)
- `title` (string): title of the notification
- `message` (string): message of of the notification (optional)
- `priority` (string): priority of the notification (`high` or `normal`), sent
Expand Down
11 changes: 11 additions & 0 deletions model/notification/center/notification_center.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ func PushStack(domain string, category string, n *notification.Notification) err
return makePush(inst, p, n)
}

// PushCLI creates and sends a new notification where the source is a CLI
// client which provides both the notification content and its properties.
func PushCLI(domain string, p *notification.Properties, n *notification.Notification) error {
inst, err := lifecycle.GetInstance(domain)
if err != nil {
return err
}
n.Originator = "cli"
return makePush(inst, p, n)
}

// Push creates and sends a new notification in database. This method verifies
// the permissions associated with this creation in order to check that it is
// granted to create a notification and to extract its source.
Expand Down
31 changes: 31 additions & 0 deletions web/instances/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/cozy/cozy-stack/model/app"
"github.com/cozy/cozy-stack/model/instance"
"github.com/cozy/cozy-stack/model/instance/lifecycle"
"github.com/cozy/cozy-stack/model/notification"
"github.com/cozy/cozy-stack/model/notification/center"
"github.com/cozy/cozy-stack/model/oauth"
"github.com/cozy/cozy-stack/model/session"
"github.com/cozy/cozy-stack/model/sharing"
Expand Down Expand Up @@ -604,6 +606,34 @@ func diskUsage(c echo.Context) error {
return c.JSON(http.StatusOK, result)
}

func sendNotification(c echo.Context) error {
domain := c.Param("domain")
instance, err := lifecycle.GetInstance(domain)
if err != nil {
return err
}

m := map[string]json.RawMessage{}
if err := json.NewDecoder(c.Request().Body).Decode(&m); err != nil {
return err
}

p := &notification.Properties{}
if err := json.Unmarshal(m["properties"], &p); err != nil {
return err
}

n := &notification.Notification{}
if err := json.Unmarshal(m["notification"], &n); err != nil {
return err
}

if err := center.PushCLI(instance.DomainName(), p, n); err != nil {
return err
}
return c.JSON(http.StatusCreated, n)
}

func showPrefix(c echo.Context) error {
domain := c.Param("domain")

Expand Down Expand Up @@ -730,6 +760,7 @@ func Routes(router *echo.Group) {
router.GET("/:domain/prefix", showPrefix)
router.GET("/:domain/swift-prefix", getSwiftBucketName)
router.GET("/:domain/sharings/:sharing-id/unxor/:doc-id", unxorID)
router.POST("/:domain/notifications", sendNotification)

// Config
router.POST("/redis", rebuildRedis)
Expand Down

0 comments on commit f4ced11

Please sign in to comment.