From 68f06ac1648714ec7c3f6ab0c114d763cea818ce Mon Sep 17 00:00:00 2001 From: Adphi Date: Tue, 16 Oct 2018 11:02:04 +0200 Subject: [PATCH] #6 Add method creating user only with username and email --- auth.go | 1 + client.go | 1 + example.config.yml | 3 ++- gonextcloud_test.go | 33 +++++++++++++++++++++++++++++++++ groups.go | 11 +++++++++++ types/group.go | 11 +++++++++++ types/responses.go | 35 ++++++++++++++++++++++++++++------- types/user.go | 8 +++++++- users.go | 36 ++++++++++++++++++++++++++++++++++++ 9 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 types/group.go diff --git a/auth.go b/auth.go index 3231917..440a1f2 100644 --- a/auth.go +++ b/auth.go @@ -27,6 +27,7 @@ func (c *Client) Login(username string, password string) error { res.JSON(&r) // No need to check for Ocs.Meta.StatusCode as capabilities are always returned c.capabilities = &r.Ocs.Data.Capabilities + c.version = &r.Ocs.Data.Version // Check if authentication failed if !c.loggedIn() { e := types.APIError{Message: "authentication failed"} diff --git a/client.go b/client.go index 4c1990b..563bfd1 100644 --- a/client.go +++ b/client.go @@ -14,6 +14,7 @@ type Client struct { session *req.Session headers map[string]string capabilities *types.Capabilities + version *types.Version } // NewClient create a new Client from the Nextcloud Instance URL diff --git a/example.config.yml b/example.config.yml index d1cc996..fad120a 100644 --- a/example.config.yml +++ b/example.config.yml @@ -4,4 +4,5 @@ password: mypassword app-name: testapp share-folder: /Documents not-existing-user: this-user-should-not-exist -not-existing-group: this-group-should-not-exist \ No newline at end of file +not-existing-group: this-group-should-not-exist +email: my@mail.com \ No newline at end of file diff --git a/gonextcloud_test.go b/gonextcloud_test.go index dcf0321..45d9cdd 100644 --- a/gonextcloud_test.go +++ b/gonextcloud_test.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "os" + "strings" "testing" ) @@ -19,6 +20,7 @@ type Config struct { ShareFolder string `yaml:"share-folder"` NotExistingUser string `yaml:"not-existing-user"` NotExistingGroup string `yaml:"not-existing-group"` + Email string `yaml:"email"` } const password = "somecomplicatedpassword" @@ -544,6 +546,37 @@ func TestGroupFolders(t *testing.T) { } } +func TestUserCreateWithoutPassword(t *testing.T) { + c = nil + if err := initClient(); err != nil { + t.Fatal(err) + } + err := c.UserCreateWithoutPassword(config.NotExistingUser, config.Email, strings.Title(config.NotExistingUser)) + assert.NoError(t, err) + err = c.UserDelete(config.NotExistingUser) + assert.NoError(t, err) +} + +func TestUserListDetails(t *testing.T) { + c = nil + if err := initClient(); err != nil { + t.Fatal(err) + } + us, err := c.UserListDetails() + assert.NoError(t, err) + assert.Contains(t, us, config.Login) +} + +func TestGroupListDetails(t *testing.T) { + c = nil + if err := initClient(); err != nil { + t.Fatal(err) + } + gs, err := c.GroupListDetails() + assert.NoError(t, err) + assert.NotEmpty(t, gs) +} + // LoadConfig loads the test configuration func LoadConfig() error { f, err := os.Open("./config.yml") diff --git a/groups.go b/groups.go index b4c603b..6f8c2a2 100644 --- a/groups.go +++ b/groups.go @@ -17,6 +17,17 @@ func (c *Client) GroupList() ([]string, error) { return r.Ocs.Data.Groups, nil } +//GroupListDetails lists the Nextcloud groups +func (c *Client) GroupListDetails() ([]types.Group, error) { + res, err := c.baseRequest(http.MethodGet, routes.groups, nil, "details") + if err != nil { + return nil, err + } + var r types.GroupListDetailsResponse + res.JSON(&r) + return r.Ocs.Data.Groups, nil +} + //GroupUsers list the group's users func (c *Client) GroupUsers(name string) ([]string, error) { res, err := c.baseRequest(http.MethodGet, routes.groups, nil, name) diff --git a/types/group.go b/types/group.go new file mode 100644 index 0000000..7fb81b9 --- /dev/null +++ b/types/group.go @@ -0,0 +1,11 @@ +package types + +//Group +type Group struct { + ID string `json:"id"` + Displayname string `json:"displayname"` + UserCount int `json:"usercount"` + Disabled int `json:"disabled"` + CanAdd bool `json:"canAdd"` + CanRemove bool `json:"canRemove"` +} diff --git a/types/responses.go b/types/responses.go index 970379e..1646f42 100644 --- a/types/responses.go +++ b/types/responses.go @@ -27,6 +27,15 @@ type UserListResponse struct { } `json:"ocs"` } +type UserListDetailsResponse struct { + Ocs struct { + Meta Meta `json:"meta"` + Data struct { + Users map[string]User `json:"users"` + } `json:"data"` + } `json:"ocs"` +} + //UserResponse type UserResponse struct { Ocs struct { @@ -53,6 +62,16 @@ type GroupListResponse struct { } `json:"ocs"` } +//GroupListDetailsResponse +type GroupListDetailsResponse struct { + Ocs struct { + Meta Meta `json:"meta"` + Data struct { + Groups []Group `json:"groups"` + } `json:"data"` + } `json:"ocs"` +} + //AppListResponse type AppListResponse struct { Ocs struct { @@ -76,18 +95,20 @@ type CapabilitiesResponse struct { Ocs struct { Meta Meta `json:"meta"` Data struct { - Version struct { - Major int `json:"major"` - Minor int `json:"minor"` - Micro int `json:"micro"` - String string `json:"string"` - Edition string `json:"edition"` - } `json:"version"` + Version Version `json:"version"` Capabilities Capabilities `json:"capabilities"` } `json:"data"` } `json:"ocs"` } +type Version struct { + Major int `json:"major"` + Minor int `json:"minor"` + Micro int `json:"micro"` + String string `json:"string"` + Edition string `json:"edition"` +} + type MonitoringResponse struct { Ocs struct { Meta Meta `json:"meta"` diff --git a/types/user.go b/types/user.go index 3af5a80..67cb8ec 100644 --- a/types/user.go +++ b/types/user.go @@ -18,5 +18,11 @@ type User struct { Website string `json:"website"` Twitter string `json:"twitter"` Groups []string `json:"groups"` - Language string `json:"language"` + Language string `json:"language,omitempty"` + + StorageLocation string `json:"storageLocation,omitempty"` + LastLogin int64 `json:"lastLogin,omitempty"` + Backend string `json:"backend,omitempty"` + Subadmin []interface{} `json:"subadmin,omitempty"` + Locale string `json:"locale,omitempty"` } diff --git a/users.go b/users.go index 070ed39..3e440c7 100644 --- a/users.go +++ b/users.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/fatih/structs" req "github.com/levigross/grequests" + "github.com/pkg/errors" "gitlab.adphi.fr/partitio/Nextcloud-Partitio/gonextcloud/types" "net/http" "path" @@ -24,6 +25,18 @@ func (c *Client) UserList() ([]string, error) { return r.Ocs.Data.Users, nil } +//UserListDetails return a map of user with details +func (c *Client) UserListDetails() (map[string]types.User, error) { + res, err := c.baseRequest(http.MethodGet, routes.users, nil, "details") + //res, err := c.session.Get(u.String(), nil) + if err != nil { + return nil, err + } + var r types.UserListDetailsResponse + res.JSON(&r) + return r.Ocs.Data.Users, nil +} + // User return the details about the specified user func (c *Client) User(name string) (*types.User, error) { if name == "" { @@ -77,6 +90,29 @@ func (c *Client) UserCreate(username string, password string, user *types.User) return c.UserUpdate(user) } +// UserCreateWithoutPassword create a user without provisioning a password, the email address must be provided to send +// an init password email +func (c *Client) UserCreateWithoutPassword(username, email, displayName string) error { + if c.version.Major < 14 { + return errors.New("unsupported method: requires Nextcloud 14+") + } + if username == "" || email == "" { + return errors.New("username and email cannot be empty") + } + ro := &req.RequestOptions{ + Data: map[string]string{ + "userid": username, + "email": email, + "displayName": displayName, + }, + } + + if err := c.userBaseRequest(http.MethodPost, ro); err != nil { + return err + } + return nil +} + //UserDelete delete the user func (c *Client) UserDelete(name string) error { return c.userBaseRequest(http.MethodDelete, nil, name)