mirror of
https://gitlab.bertha.cloud/partitio/Nextcloud-Partitio/gonextcloud
synced 2024-11-21 19:26:24 +00:00
#1 Implements Notifications API
This commit is contained in:
parent
4a1bec45bf
commit
75e83977e4
5
Makefile
5
Makefile
@ -5,7 +5,7 @@ GO_FILES := $(shell find . -name '*.go' | grep -v _test.go)
|
||||
|
||||
.PHONY: all dep build clean test coverage coverhtml lint
|
||||
|
||||
all: build
|
||||
all: dep lint test race coverage
|
||||
|
||||
lint: ## Lint the files
|
||||
@golint -set_exit_status ${PKG_LIST}
|
||||
@ -28,5 +28,8 @@ dep: ## Get the dependencies
|
||||
@mkdir -p vendor
|
||||
@govendor add +external
|
||||
|
||||
push: dep lint test coverage ## Push to git repository
|
||||
@git push origin master
|
||||
|
||||
help: ## Display this help screen
|
||||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
@ -478,6 +478,9 @@ func TestUserCreateWithoutPassword(t *testing.T) {
|
||||
if err := initClient(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.version.Major < 14 {
|
||||
t.SkipNow()
|
||||
}
|
||||
// Nextcloud does not seems to like recreating a deleted user
|
||||
err := c.UserCreateWithoutPassword(config.NotExistingUser, config.Email, strings.Title(config.NotExistingUser))
|
||||
assert.NoError(t, err)
|
||||
|
83
notifications.go
Normal file
83
notifications.go
Normal file
@ -0,0 +1,83 @@
|
||||
package gonextcloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
req "github.com/levigross/grequests"
|
||||
"gitlab.adphi.fr/partitio/Nextcloud-Partitio/gonextcloud/types"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//NotificationsList returns all the notifications
|
||||
func (c *Client) NotificationsList() ([]types.Notification, error) {
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := c.baseRequest(http.MethodGet, routes.notifications, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var r types.NotificationsListResponse
|
||||
res.JSON(&r)
|
||||
return r.Ocs.Data, nil
|
||||
}
|
||||
|
||||
//Notifications returns the notification corresponding to the id
|
||||
func (c *Client) Notifications(id int) (types.Notification, error) {
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
return types.Notification{}, err
|
||||
}
|
||||
res, err := c.baseRequest(http.MethodGet, routes.notifications, nil, strconv.Itoa(id))
|
||||
if err != nil {
|
||||
return types.Notification{}, err
|
||||
}
|
||||
var r types.NotificationResponse
|
||||
res.JSON(&r)
|
||||
return r.Ocs.Data, nil
|
||||
}
|
||||
|
||||
//NotificationsDelete deletes the notification corresponding to the id
|
||||
func (c *Client) NotificationsDelete(id int) error {
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := c.baseRequest(http.MethodDelete, routes.notifications, nil, strconv.Itoa(id))
|
||||
return err
|
||||
}
|
||||
|
||||
//NotificationsDeleteAll deletes all notifications
|
||||
func (c *Client) NotificationsDeleteAll() error {
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := c.baseRequest(http.MethodDelete, routes.notifications, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
//NotificationsCreate creates a notification (if the user is an admin)
|
||||
func (c *Client) NotificationsCreate(userID, title, message string) error {
|
||||
if err := c.adminNotificationsAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
ro := &req.RequestOptions{
|
||||
Data: map[string]string{
|
||||
"shortMessage": title,
|
||||
"longMessage": message,
|
||||
},
|
||||
}
|
||||
_, err := c.baseRequest(http.MethodPost, routes.adminNotifications, ro, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) adminNotificationsAvailable() error {
|
||||
if len(c.capabilities.Notifications.AdminNotifications) == 0 {
|
||||
return errors.New("'admin notifications' not available on this instance")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c *Client) notificationsAvailable() error {
|
||||
if len(c.capabilities.Notifications.OcsEndpoints) == 0 {
|
||||
return errors.New("notifications not available on this instance")
|
||||
}
|
||||
return nil
|
||||
}
|
90
notifications_test.go
Normal file
90
notifications_test.go
Normal file
@ -0,0 +1,90 @@
|
||||
package gonextcloud
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
notificationID int
|
||||
createdID int
|
||||
title = "Short Message"
|
||||
message = "Longer notification message"
|
||||
tests = []struct {
|
||||
string
|
||||
test
|
||||
}{
|
||||
{
|
||||
"notificationCreate",
|
||||
func(t *testing.T) {
|
||||
err := c.NotificationsCreate(config.Login, title, message)
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
}, {
|
||||
"notificationDelete",
|
||||
func(t *testing.T) {
|
||||
// Get created Notification ID
|
||||
ns, err := c.NotificationsList()
|
||||
if err != nil {
|
||||
t.SkipNow()
|
||||
}
|
||||
for _, n := range ns {
|
||||
if n.Subject == title {
|
||||
createdID = n.NotificationID
|
||||
break
|
||||
}
|
||||
}
|
||||
if createdID == 0 {
|
||||
t.SkipNow()
|
||||
}
|
||||
err = c.NotificationsDelete(createdID)
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestNotificationsList(t *testing.T) {
|
||||
c = nil
|
||||
if err := initClient(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
t.SkipNow()
|
||||
}
|
||||
ns, err := c.NotificationsList()
|
||||
assert.NoError(t, err)
|
||||
if len(ns) > 0 {
|
||||
notificationID = ns[0].NotificationID
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotifications(t *testing.T) {
|
||||
if notificationID == 0 {
|
||||
t.SkipNow()
|
||||
}
|
||||
c = nil
|
||||
if err := initClient(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := c.notificationsAvailable(); err != nil {
|
||||
t.SkipNow()
|
||||
}
|
||||
n, err := c.Notifications(notificationID)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, n)
|
||||
}
|
||||
|
||||
// Disable due to very long response time
|
||||
//func TestNotificationsAdmin(t *testing.T) {
|
||||
// c = nil
|
||||
// if err := initClient(); err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// if err := c.adminNotificationsAvailable(); err != nil {
|
||||
// t.SkipNow()
|
||||
// }
|
||||
// for _, test := range tests {
|
||||
// t.Run(test.string, test.test)
|
||||
// }
|
||||
//}
|
36
routes.go
36
routes.go
@ -4,14 +4,16 @@ import "net/url"
|
||||
|
||||
// Routes references the available routes
|
||||
type Routes struct {
|
||||
capabilities *url.URL
|
||||
users *url.URL
|
||||
groups *url.URL
|
||||
apps *url.URL
|
||||
monitor *url.URL
|
||||
shares *url.URL
|
||||
groupfolders *url.URL
|
||||
appsConfig *url.URL
|
||||
capabilities *url.URL
|
||||
users *url.URL
|
||||
groups *url.URL
|
||||
apps *url.URL
|
||||
monitor *url.URL
|
||||
shares *url.URL
|
||||
groupfolders *url.URL
|
||||
appsConfig *url.URL
|
||||
notifications *url.URL
|
||||
adminNotifications *url.URL
|
||||
}
|
||||
|
||||
const badRequest = 998
|
||||
@ -19,13 +21,15 @@ const badRequest = 998
|
||||
var (
|
||||
apiPath = &url.URL{Path: "/ocs/v2.php"}
|
||||
routes = Routes{
|
||||
capabilities: &url.URL{Path: apiPath.Path + "/cloud/capabilities"},
|
||||
users: &url.URL{Path: apiPath.Path + "/cloud/users"},
|
||||
groups: &url.URL{Path: apiPath.Path + "/cloud/groups"},
|
||||
apps: &url.URL{Path: apiPath.Path + "/cloud/apps"},
|
||||
monitor: &url.URL{Path: apiPath.Path + "/apps/serverinfo/api/v1/info"},
|
||||
shares: &url.URL{Path: apiPath.Path + "/apps/files_sharing/api/v1/shares"},
|
||||
groupfolders: &url.URL{Path: "apps/groupfolders/folders"},
|
||||
appsConfig: &url.URL{Path: apiPath.Path + "/apps/provisioning_api/api/v1/config/apps"},
|
||||
capabilities: &url.URL{Path: apiPath.Path + "/cloud/capabilities"},
|
||||
users: &url.URL{Path: apiPath.Path + "/cloud/users"},
|
||||
groups: &url.URL{Path: apiPath.Path + "/cloud/groups"},
|
||||
apps: &url.URL{Path: apiPath.Path + "/cloud/apps"},
|
||||
monitor: &url.URL{Path: apiPath.Path + "/apps/serverinfo/api/v1/info"},
|
||||
shares: &url.URL{Path: apiPath.Path + "/apps/files_sharing/api/v1/shares"},
|
||||
groupfolders: &url.URL{Path: "/apps/groupfolders/folders"},
|
||||
appsConfig: &url.URL{Path: apiPath.Path + "/apps/provisioning_api/api/v1/config/apps"},
|
||||
notifications: &url.URL{Path: apiPath.Path + "/apps/notifications/api/v2/notifications"},
|
||||
adminNotifications: &url.URL{Path: apiPath.Path + "/apps/admin_notifications/api/v2/notifications"},
|
||||
}
|
||||
)
|
||||
|
@ -12,6 +12,17 @@ type Capabilities struct {
|
||||
Activity struct {
|
||||
Apiv2 []string `json:"apiv2"`
|
||||
} `json:"activity"`
|
||||
Ocm struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
APIVersion string `json:"apiVersion"`
|
||||
EndPoint string `json:"endPoint"`
|
||||
ShareTypes []struct {
|
||||
Name string `json:"name"`
|
||||
Protocols struct {
|
||||
Webdav string `json:"webdav"`
|
||||
} `json:"protocols"`
|
||||
} `json:"shareTypes"`
|
||||
} `json:"ocm"`
|
||||
Dav struct {
|
||||
Chunking string `json:"chunking"`
|
||||
} `json:"dav"`
|
||||
@ -43,7 +54,8 @@ type Capabilities struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
} `json:"expire_date"`
|
||||
} `json:"group"`
|
||||
Federation struct {
|
||||
DefaultPermissions int `json:"default_permissions"`
|
||||
Federation struct {
|
||||
Outgoing bool `json:"outgoing"`
|
||||
Incoming bool `json:"incoming"`
|
||||
ExpireDate struct {
|
||||
@ -64,8 +76,9 @@ type Capabilities struct {
|
||||
} `json:"sharebymail"`
|
||||
} `json:"files_sharing"`
|
||||
Notifications struct {
|
||||
OcsEndpoints []string `json:"ocs-endpoints"`
|
||||
Push []string `json:"push"`
|
||||
OcsEndpoints []string `json:"ocs-endpoints"`
|
||||
Push []string `json:"push"`
|
||||
AdminNotifications []string `json:"admin-notifications"`
|
||||
} `json:"notifications"`
|
||||
PasswordPolicy struct {
|
||||
MinLength int `json:"minLength"`
|
||||
@ -92,4 +105,9 @@ type Capabilities struct {
|
||||
Undelete bool `json:"undelete"`
|
||||
Versioning bool `json:"versioning"`
|
||||
} `json:"files"`
|
||||
Registration struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
APIRoot string `json:"apiRoot"`
|
||||
APILevel string `json:"apiLevel"`
|
||||
} `json:"registration"`
|
||||
}
|
||||
|
21
types/notification.go
Normal file
21
types/notification.go
Normal file
@ -0,0 +1,21 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
type Notification struct {
|
||||
NotificationID int `json:"notification_id"`
|
||||
App string `json:"app"`
|
||||
User string `json:"user"`
|
||||
Datetime time.Time `json:"datetime"`
|
||||
ObjectType string `json:"object_type"`
|
||||
ObjectID string `json:"object_id"`
|
||||
Subject string `json:"subject"`
|
||||
Message string `json:"message"`
|
||||
Link string `json:"link"`
|
||||
SubjectRich string `json:"subjectRich"`
|
||||
SubjectRichParameters []interface{} `json:"subjectRichParameters"`
|
||||
MessageRich string `json:"messageRich"`
|
||||
MessageRichParameters []interface{} `json:"messageRichParameters"`
|
||||
Icon string `json:"icon"`
|
||||
Actions []interface{} `json:"actions"`
|
||||
}
|
@ -168,3 +168,17 @@ type GroupFoldersResponse struct {
|
||||
Data GroupFolderBadFormatGroups `json:"data"`
|
||||
} `json:"ocs"`
|
||||
}
|
||||
|
||||
type NotificationsListResponse struct {
|
||||
Ocs struct {
|
||||
Meta Meta `json:"meta"`
|
||||
Data []Notification `json:"data"`
|
||||
} `json:"ocs"`
|
||||
}
|
||||
|
||||
type NotificationResponse struct {
|
||||
Ocs struct {
|
||||
Meta Meta `json:"meta"`
|
||||
Data Notification `json:"data"`
|
||||
} `json:"ocs"`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user