diff --git a/ocs/go.mod b/ocs/go.mod index 7f4c4a43b..aa67387a1 100644 --- a/ocs/go.mod +++ b/ocs/go.mod @@ -10,6 +10,7 @@ require ( github.com/cs3org/reva v1.2.1-0.20200826162318-c0f54e1f37ea github.com/go-chi/chi v4.1.2+incompatible github.com/go-chi/render v1.0.1 + github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.2 // indirect github.com/micro/cli/v2 v2.1.2 github.com/micro/go-micro/v2 v2.9.1 @@ -17,9 +18,12 @@ require ( github.com/openzipkin/zipkin-go v0.2.2 github.com/owncloud/ocis/accounts v0.0.0-20200918125107-fcca9faa81c8 github.com/owncloud/ocis/ocis-pkg v0.0.0-20200918114005-1a0ddd2190ee + github.com/owncloud/ocis/settings v0.0.0-20200918114005-1a0ddd2190ee github.com/owncloud/ocis/store v0.0.0-20200918125107-fcca9faa81c8 + github.com/prometheus/client_golang v1.7.1 github.com/restic/calens v0.2.0 github.com/spf13/viper v1.7.0 + github.com/stretchr/testify v1.6.1 go.opencensus.io v0.22.4 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect google.golang.org/protobuf v1.25.0 diff --git a/ocs/go.sum b/ocs/go.sum index a0ec560f8..77b0bb99d 100644 --- a/ocs/go.sum +++ b/ocs/go.sum @@ -834,6 +834,7 @@ github.com/ikawaha/kagome.ipadic v1.1.2/go.mod h1:DPSBbU0czaJhAb/5uKQZHMc9MTVRpD github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -1226,6 +1227,7 @@ github.com/owncloud/ocis-pkg/v2 v2.3.0/go.mod h1:FSzIvhx9HcZcq4jgNaDowNvM7PTX/XC github.com/owncloud/ocis-pkg/v2 v2.4.0 h1:/3ZOd4txtwjiNKJA9iLT9BjrJw5YgHSX13fQR4BYfGY= github.com/owncloud/ocis-pkg/v2 v2.4.0/go.mod h1:FSzIvhx9HcZcq4jgNaDowNvM7PTX/XCyoMvyfzidUpE= github.com/owncloud/ocis-pkg/v2 v2.4.1-0.20200828095914-d3b859484b2b/go.mod h1:WdcVM54z0X7aQzS8eyGl7S5sjEMVBtLpfpzsPX3Z+Pw= +github.com/owncloud/ocis-pkg/v2 v2.4.1-0.20200902134813-1e87c6173ada h1:iVknnuT/z8QCAeBpHEcbI/AiQ9FOBvF5aOAFT3TIM+I= github.com/owncloud/ocis-pkg/v2 v2.4.1-0.20200902134813-1e87c6173ada/go.mod h1:WdcVM54z0X7aQzS8eyGl7S5sjEMVBtLpfpzsPX3Z+Pw= github.com/owncloud/ocis-proxy v0.7.1-0.20200904132806-fcceec602fcb/go.mod h1:zFwhh9GFzPCiHBPM4zyWzxA7d78fYMbLOPB977mGUzk= github.com/owncloud/ocis-reva v0.13.0/go.mod h1:cTcLFOO/tg4/GyYygi/VVXFjZAQWE3YxlyfhZ/vcAj4= @@ -1233,6 +1235,7 @@ github.com/owncloud/ocis-settings v0.0.0-20200522101320-46ea31026363/go.mod h1:/ github.com/owncloud/ocis-settings v0.0.0-20200629120229-69693c5f8f43 h1:IekDKhkoaOhUnpIHSG5d02hGMOW5u4tZEEfxVC1KGgk= github.com/owncloud/ocis-settings v0.0.0-20200629120229-69693c5f8f43/go.mod h1:AeXZVHKEU+9Xt4+/lkHE5rx+sJH2if9dIrUGLhe+JOY= github.com/owncloud/ocis-settings v0.3.2-0.20200827193534-8caf098e6537/go.mod h1:vRge9QDkOsc6j76gPBmZs1Z5uOPrV4DIkZCgZCEFwBA= +github.com/owncloud/ocis-settings v0.3.2-0.20200828091056-47af10a0e872 h1:VGWM/eLIxXY6BJLDuzpdjSVa73Dj5S8pfUtT9Sb5Ono= github.com/owncloud/ocis-settings v0.3.2-0.20200828091056-47af10a0e872/go.mod h1:vRge9QDkOsc6j76gPBmZs1Z5uOPrV4DIkZCgZCEFwBA= github.com/owncloud/ocis-settings v0.3.2-0.20200828130413-0cc0f5bf26fe h1:kiU5lz12R0LNJE1/zI2vxesZPWm6BvSO7hvZC8yOoAc= github.com/owncloud/ocis-settings v0.3.2-0.20200828130413-0cc0f5bf26fe/go.mod h1:vRge9QDkOsc6j76gPBmZs1Z5uOPrV4DIkZCgZCEFwBA= @@ -2089,6 +2092,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= diff --git a/ocs/pkg/server/http/svc_test.go b/ocs/pkg/server/http/svc_test.go index afb0b562d..b18dd98ce 100644 --- a/ocs/pkg/server/http/svc_test.go +++ b/ocs/pkg/server/http/svc_test.go @@ -1,1706 +1,1669 @@ package http -// -//import ( -// "context" -// "encoding/base64" -// "encoding/json" -// "encoding/xml" -// "fmt" -// "io/ioutil" -// "log" -// "net/http" -// "net/http/httptest" -// "net/url" -// "path/filepath" -// "strings" -// "testing" -// -// "github.com/golang/protobuf/ptypes/empty" -// "github.com/owncloud/ocis/ocs/pkg/config" -// svc "github.com/owncloud/ocis/ocs/pkg/service/v0" -// ocisLog "github.com/owncloud/ocis/ocis-pkg/log" -// "github.com/stretchr/testify/assert" -// -// "github.com/owncloud/ocis/ocis-pkg/service/grpc" -// -// accountsCmd "github.com/owncloud/ocis/accounts/pkg/command" -// accountsCfg "github.com/owncloud/ocis/accounts/pkg/config" -// accountsProto "github.com/owncloud/ocis/accounts/pkg/proto/v0" -// accountsSvc "github.com/owncloud/ocis/accounts/pkg/service/v0" -// -// "github.com/micro/go-micro/v2/client" -// settings "github.com/owncloud/ocis/settings/pkg/proto/v0" -//) -// -//var service = grpc.Service{} -// -//var mockedRoleAssignment = map[string]string{} -// -//var ocsVersions = []string{"v1.php", "v2.php"} -// -//var formats = []string{"json", "xml"} -// -//const dataPath = "./accounts-store" -// -//var DefaultUsers = []string{ -// "4c510ada-c86b-4815-8820-42cdf82c3d51", -// "820ba2a1-3f54-4538-80a4-2d73007e30bf", -// "932b4540-8d16-481e-8ef4-588e4b6b151c", -// "bc596f3c-c955-4328-80a0-60d018b4ad57", -// "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", -// "058bff95-6708-4fe5-91e4-9ea3d377588b", -//} -// -//func getFormatString(format string) string { -// if format == "json" { -// return "?format=json" -// } else if format == "xml" { -// return "" -// } else { -// panic("Invalid format received") -// } -//} -// -//type Quota struct { -// Free int64 `json:"free" xml:"free"` -// Used int64 `json:"used" xml:"used"` -// Total int64 `json:"total" xml:"total"` -// Relative float32 `json:"relative" xml:"relative"` -// Definition string `json:"definition" xml:"definition"` -//} -// -//type User struct { -// Enabled string `json:"enabled" xml:"enabled"` -// ID string `json:"id" xml:"id"` -// Username string `json:"username" xml:"username"` -// Email string `json:"email" xml:"email"` -// Password string `json:"-" xml:"-"` -// Quota Quota `json:"quota" xml:"quota"` -// UIDNumber int `json:"uidnumber" xml:"uidnumber"` -// GIDNumber int `json:"gidnumber" xml:"gidnumber"` -// Displayname string `json:"displayname" xml:"displayname"` -//} -// -//func (u *User) getUserRequestString() string { -// res := url.Values{} -// -// if u.Password != "" { -// res.Add("password", u.Password) -// } -// -// if u.ID != "" { -// res.Add("userid", u.ID) -// } -// -// if u.Username != "" { -// res.Add("username", u.Username) -// } -// -// if u.Email != "" { -// res.Add("email", u.Email) -// } -// -// if u.Displayname != "" { -// res.Add("displayname", u.Displayname) -// } -// -// if u.UIDNumber != 0 { -// res.Add("uidnumber", fmt.Sprint(u.UIDNumber)) -// } -// -// if u.GIDNumber != 0 { -// res.Add("gidnumber", fmt.Sprint(u.GIDNumber)) -// } -// -// return res.Encode() -//} -// -//type Meta struct { -// Status string `json:"status" xml:"status"` -// StatusCode int `json:"statuscode" xml:"statuscode"` -// Message string `json:"message" xml:"message"` -//} -// -//func (m *Meta) Success(ocsVersion string) bool { -// if !(ocsVersion == "v1.php" || ocsVersion == "v2.php") { -// return false -// } -// if m.Status != "ok" { -// return false -// } -// if ocsVersion == "v1.php" && m.StatusCode != 100 { -// return false -// } else if ocsVersion == "v2.php" && m.StatusCode != 200 { -// return false -// } else { -// return true -// } -//} -// -//type SingleUserResponse struct { -// Ocs struct { -// Meta Meta `json:"meta" xml:"meta"` -// Data User `json:"data" xml:"data"` -// } `json:"ocs" xml:"ocs"` -//} -// -//type GetUsersResponse struct { -// Ocs struct { -// Meta Meta `json:"meta" xml:"meta"` -// Data struct { -// Users []string `json:"users" xml:"users>element"` -// } `json:"data" xml:"data"` -// } `json:"ocs" xml:"ocs"` -//} -// -//type EmptyResponse struct { -// Ocs struct { -// Meta Meta `json:"meta" xml:"meta"` -// Data struct { -// } `json:"data" xml:"data"` -// } `json:"ocs" xml:"ocs"` -//} -// -//type GetUsersGroupsResponse struct { -// Ocs struct { -// Meta Meta `json:"meta" xml:"meta"` -// Data struct { -// Groups []string `json:"groups" xml:"groups>element"` -// } `json:"data" xml:"data"` -// } `json:"ocs" xml:"ocs"` -//} -// -//func assertStatusCode(t *testing.T, statusCode int, res *httptest.ResponseRecorder, ocsVersion string) { -// if ocsVersion == "v1.php" { -// assert.Equal(t, 200, res.Code) -// } else { -// assert.Equal(t, statusCode, res.Code) -// } -//} -// -//func assertResponseMeta(t *testing.T, expected, actual Meta) { -// assert.Equal(t, expected.Status, actual.Status, "The status of response doesn't matches") -// assert.Equal(t, expected.StatusCode, actual.StatusCode, "The Status code of response doesn't matches") -// assert.Equal(t, expected.Message, actual.Message, "The Message of response doesn't matches") -//} -// -//func assertUserSame(t *testing.T, expected, actual User, quotaAvailable bool) { -// if expected.ID == "" { -// // Check the auto generated userId -// assert.Regexp( -// t, -// "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", -// actual.ID, "the userid is not a valid uuid", -// ) -// } else { -// assert.Equal(t, expected.ID, actual.ID, "UserId doesn't match for user %v", expected.Username) -// } -// assert.Equal(t, expected.Username, actual.Username, "Username doesn't match for user %v", expected.Username) -// assert.Equal(t, expected.Email, actual.Email, "email doesn't match for user %v", expected.Username) -// assert.Equal(t, expected.Enabled, actual.Enabled, "enabled doesn't match for user %v", expected.Username) -// assert.Equal(t, expected.Displayname, actual.Displayname, "displayname doesn't match for user %v", expected.Username) -// if quotaAvailable { -// assert.NotZero(t, actual.Quota.Free) -// assert.NotZero(t, actual.Quota.Used) -// assert.NotZero(t, actual.Quota.Total) -// assert.Equal(t, "default", actual.Quota.Definition) -// } else { -// assert.Equal(t, expected.Quota, actual.Quota, "Quota match for user %v", expected.Username) -// } -// -// // FIXME: gidnumber and Uidnumber are always 0 -// // https://github.com/owncloud/ocis/ocs/issues/45 -// assert.Equal(t, 0, actual.UIDNumber, "UidNumber doesn't match for user %v", expected.Username) -// assert.Equal(t, 0, actual.GIDNumber, "GIDNumber doesn't match for user %v", expected.Username) -// -//} -// -//func deleteAccount(t *testing.T, id string) (*empty.Empty, error) { -// client := service.Client() -// cl := accountsProto.NewAccountsService("com.owncloud.api.accounts", client) -// -// req := &accountsProto.DeleteAccountRequest{Id: id} -// res, err := cl.DeleteAccount(context.Background(), req) -// return res, err -//} -// -//func buildRoleServiceMock() settings.RoleService { -// return settings.MockRoleService{ -// AssignRoleToUserFunc: func(ctx context.Context, req *settings.AssignRoleToUserRequest, opts ...client.CallOption) (res *settings.AssignRoleToUserResponse, err error) { -// mockedRoleAssignment[req.AccountUuid] = req.RoleId -// return &settings.AssignRoleToUserResponse{ -// Assignment: &settings.UserRoleAssignment{ -// AccountUuid: req.AccountUuid, -// RoleId: req.RoleId, -// }, -// }, nil -// }, -// } -//} -// -//func init() { -// service = grpc.NewService( -// grpc.Namespace("com.owncloud.api"), -// grpc.Name("accounts"), -// grpc.Address("localhost:9180"), -// ) -// -// c := &accountsCfg.Config{ -// Server: accountsCfg.Server{ -// AccountsDataPath: dataPath, -// }, -// Log: accountsCfg.Log{ -// Level: "info", -// Pretty: true, -// Color: true, -// }, -// } -// -// var hdlr *accountsSvc.Service -// var err error -// -// if hdlr, err = accountsSvc.New( -// accountsSvc.Logger(accountsCmd.NewLogger(c)), -// accountsSvc.Config(c), -// accountsSvc.RoleService(buildRoleServiceMock())); err != nil { -// log.Fatalf("Could not create new service") -// } -// -// hdlr.Client = mockClient{} -// -// err = accountsProto.RegisterAccountsServiceHandler(service.Server(), hdlr) -// if err != nil { -// log.Fatal("could not register the Accounts handler") -// } -// err = accountsProto.RegisterGroupsServiceHandler(service.Server(), hdlr) -// if err != nil { -// log.Fatal("could not register the Groups handler") -// } -// -// err = service.Server().Start() -// if err != nil { -// log.Fatalf("could not start server: %v", err) -// } -//} -// -//func cleanUp(t *testing.T) { -// datastore := filepath.Join(dataPath, "accounts") -// -// files, err := ioutil.ReadDir(datastore) -// if err != nil { -// log.Fatal(err) -// } -// -// for _, f := range files { -// found := false -// for _, defUser := range DefaultUsers { -// if f.Name() == defUser { -// found = true -// break -// } -// } -// -// if !found { -// deleteAccount(t, f.Name()) -// } -// } -//} -// -//func sendRequest(method, endpoint, body, auth string) (*httptest.ResponseRecorder, error) { -// var reader = strings.NewReader(body) -// req, err := http.NewRequest(method, endpoint, reader) -// if err != nil { -// return nil, err -// } -// req.Header.Set("Content-Type", "application/x-www-form-urlencoded") -// -// if auth != "" { -// req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) -// } -// -// rr := httptest.NewRecorder() -// -// service := getService() -// service.ServeHTTP(rr, req) -// -// return rr, nil -//} -// -//func getService() svc.Service { -// c := &config.Config{ -// HTTP: config.HTTP{ -// Root: "/", -// Addr: "localhost:9110", -// Namespace: "com.owncloud.web", -// }, -// TokenManager: config.TokenManager{ -// JWTSecret: "HELLO-secret", -// }, -// Log: config.Log{ -// Level: "debug", -// }, -// } -// -// var logger ocisLog.Logger -// -// svc := svc.NewService( -// svc.Logger(logger), -// svc.Config(c), -// ) -// -// return svc -//} -// -//func createUser(u User) error { -// _, err := sendRequest( -// "POST", -// "/v1.php/cloud/users?format=json", -// u.getUserRequestString(), -// "admin:admin", -// ) -// -// if err != nil { -// return err -// } -// return nil -//} -// -//func TestCreateUser(t *testing.T) { -// testData := []struct { -// user User -// err *Meta -// }{ -// // A simple user -// { -// User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "ErnestRutherFord", -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User with Uid and Gid defined -// { -// User{ -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// UIDNumber: 20027, -// GIDNumber: 30000, -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User with different username and Id -// { -// User{ -// Enabled: "true", -// Username: "niels", -// ID: "bohr", -// Email: "bohr@example.com", -// Displayname: "Niels Bohr", -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User withoutl password -// // https://github.com/owncloud/ocis/ocs/issues/50 -// { -// User{ -// Enabled: "true", -// Username: "john", -// ID: "john", -// Email: "john@example.com", -// Displayname: "John Dalton", -// }, -// nil, -// }, -// -// // User with special character in username -// // https://github.com/owncloud/ocis/ocs/issues/49 -// { -// User{ -// Enabled: "true", -// Username: "schrödinger", -// ID: "schrödinger", -// Email: "schrödinger@example.com", -// Displayname: "Erwin Schrödinger", -// Password: "newPassword", -// }, -// &Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "preferred_name 'schrödinger' must be at least the local part of an email", -// }, -// }, -// -// // User with different userid and email -// { -// User{ -// Enabled: "true", -// Username: "planck", -// ID: "planck", -// Email: "max@example.com", -// Displayname: "Max Planck", -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User with different userid and email and username -// { -// User{ -// Enabled: "true", -// Username: "hisenberg", -// ID: "hberg", -// Email: "werner@example.com", -// Displayname: "Werner Hisenberg", -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User without displayname -// { -// User{ -// Enabled: "true", -// Username: "oppenheimer", -// ID: "oppenheimer", -// Email: "robert@example.com", -// Password: "newPassword", -// }, -// nil, -// }, -// -// // User wit invalid email -// { -// User{ -// Enabled: "true", -// Username: "chadwick", -// ID: "chadwick", -// Email: "not_a_email", -// Password: "newPassword", -// }, -// &Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "mail 'not_a_email' must be a valid email", -// }, -// }, -// -// // User without email -// { -// User{ -// Enabled: "true", -// Username: "chadwick", -// ID: "chadwick", -// Password: "newPassword", -// }, -// &Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "mail '' must be a valid email", -// }, -// }, -// -// // User without username -// { -// User{ -// Enabled: "true", -// ID: "chadwick", -// Email: "james@example.com", -// Password: "newPassword", -// }, -// &Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "preferred_name '' must be at least the local part of an email", -// }, -// }, -// -// // User without userid -// { -// User{ -// Enabled: "true", -// Username: "chadwick", -// Email: "james@example.com", -// Password: "newPassword", -// }, -// nil, -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// for _, data := range testData { -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "POST", -// fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), -// data.user.getUserRequestString(), -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response SingleUserResponse -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// if data.err == nil { -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// assertStatusCode(t, 200, res, ocsVersion) -// assertUserSame(t, data.user, response.Ocs.Data, false) -// } else { -// assertStatusCode(t, 400, res, ocsVersion) -// assertResponseMeta(t, *data.err, response.Ocs.Meta) -// } -// -// var id string -// if data.user.ID != "" { -// id = data.user.ID -// } else { -// id = response.Ocs.Data.ID -// } -// -// res, err = sendRequest( -// "GET", -// "/v1.php/cloud/users?format=json", -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var usersResponse GetUsersResponse -// if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { -// t.Fatal(err) -// } -// -// assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") -// -// if data.err == nil { -// assert.Contains(t, usersResponse.Ocs.Data.Users, id) -// } else { -// assert.NotContains(t, usersResponse.Ocs.Data.Users, data.user.ID) -// } -// } -// cleanUp(t) -// } -// } -//} -// -//func TestGetUsers(t *testing.T) { -// users := []User{ -// { -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// }, -// { -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// for _, user := range users { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// } -// -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response GetUsersResponse -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// for _, user := range users { -// assert.Contains(t, response.Ocs.Data.Users, user.Username) -// } -// cleanUp(t) -// } -// } -//} -// -//func TestGetUsersDefaultUsers(t *testing.T) { -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response GetUsersResponse -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// for _, user := range DefaultUsers { -// assert.Contains(t, response.Ocs.Data.Users, user) -// } -// cleanUp(t) -// } -// } -//} -// -//func TestGetUser(t *testing.T) { -// users := []User{ -// { -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// }, -// { -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// -// for _, user := range users { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// } -// formatpart := getFormatString(format) -// for _, user := range users { -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user.ID, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response SingleUserResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to pass but it failed") -// assertUserSame(t, user, response.Ocs.Data, true) -// } -// cleanUp(t) -// } -// } -//} -// -//func TestGetUserInvalidId(t *testing.T) { -// invalidUsers := []string{ -// "1", -// "invalid", -// "3434234233", -// "1am41validUs3r", -// "_-@@--$$__", -// } -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, user := range invalidUsers { -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/user/%s%s", ocsVersion, user, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response SingleUserResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 404, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "the response was expected to fail but passed") -// assertResponseMeta(t, Meta{ -// Status: "error", -// StatusCode: 998, -// Message: "not found", -// }, response.Ocs.Meta) -// cleanUp(t) -// } -// } -// } -//} -//func TestDeleteUser(t *testing.T) { -// users := []User{ -// { -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// }, -// { -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// for _, user := range users { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// } -// -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "DELETE", -// fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// assert.Empty(t, response.Ocs.Data) -// -// // Check deleted user doesn't exist and the other user does -// res, err = sendRequest( -// "GET", -// "/v1.php/cloud/users?format=json", -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var usersResponse GetUsersResponse -// if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { -// t.Fatal(err) -// } -// -// assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") -// assert.Contains(t, usersResponse.Ocs.Data.Users, "thomson") -// assert.NotContains(t, usersResponse.Ocs.Data.Users, "rutherford") -// -// cleanUp(t) -// } -// } -//} -// -//func TestDeleteUserInvalidId(t *testing.T) { -// -// invalidUsers := []string{ -// "1", -// "invalid", -// "3434234233", -// "1am41validUs3r", -// "_-@@--$$__", -// } -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// for _, user := range invalidUsers { -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "DELETE", -// fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 404, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was not expected to be successful but was") -// assert.Empty(t, response.Ocs.Data) -// -// assertResponseMeta(t, Meta{ -// Status: "error", -// StatusCode: 998, -// Message: "The requested user could not be found", -// }, response.Ocs.Meta) -// } -// } -// } -//} -// -//func TestUpdateUser(t *testing.T) { -// user := User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// } -// -// testData := []struct { -// UpdateKey string -// UpdateValue string -// Error *Meta -// }{ -// { -// "displayname", -// "James Chadwick", -// nil, -// }, -// { -// "display", -// "Neils Bohr", -// nil, -// }, -// { -// "email", -// "ford@user.org", -// nil, -// }, -// // Invalid email doesn't gives error -// // https://github.com/owncloud/ocis/ocs/issues/46 -// { -// "email", -// "not_a_valid_email", -// nil, -// }, -// { -// "password", -// "strongpass1234", -// nil, -// }, -// { -// "username", -// "e_rutherford", -// nil, -// }, -// // Empty values doesn't gives error -// // https://github.com/owncloud/ocis/ocs/issues/51 -// { -// "email", -// "", -// nil, -// }, -// { -// "username", -// "", -// nil, -// }, -// { -// "password", -// "", -// nil, -// }, -// -// // Invalid Keys -// { -// "invalid_key", -// "validvalue", -// &Meta{ -// Status: "error", -// StatusCode: 103, -// Message: "unknown key 'invalid_key'", -// }, -// }, -// { -// "12345", -// "validvalue", -// &Meta{ -// Status: "error", -// StatusCode: 103, -// Message: "unknown key '12345'", -// }, -// }, -// { -// "", -// "validvalue", -// &Meta{ -// Status: "error", -// StatusCode: 103, -// Message: "unknown key ''", -// }, -// }, -// { -// "", -// "", -// &Meta{ -// Status: "error", -// StatusCode: 103, -// Message: "unknown key ''", -// }, -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, data := range testData { -// err := createUser(user) -// if err != nil { -// t.Fatalf("Failed while creating user: %v", err) -// } -// -// params := url.Values{} -// -// params.Add("key", data.UpdateKey) -// params.Add("value", data.UpdateValue) -// -// res, err := sendRequest( -// "PUT", -// fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), -// params.Encode(), -// "admin:admin", -// ) -// -// updatedUser := user -// switch data.UpdateKey { -// case "username": -// updatedUser.Username = data.UpdateValue -// case "email": -// updatedUser.Email = data.UpdateValue -// case "displayname": -// updatedUser.Displayname = data.UpdateValue -// case "display": -// updatedUser.Displayname = data.UpdateValue -// } -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response struct { -// Ocs struct { -// Meta Meta `json:"meta" xml:"meta"` -// } `json:"ocs" xml:"ocs"` -// } -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// if data.Error != nil { -// assertResponseMeta(t, *data.Error, response.Ocs.Meta) -// assertStatusCode(t, 400, res, ocsVersion) -// } else { -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but failed") -// assertStatusCode(t, 200, res, ocsVersion) -// } -// -// // Check deleted user doesn't exist and the other user does -// res, err = sendRequest( -// "GET", -// "/v1.php/cloud/users/rutherford?format=json", -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var usersResponse SingleUserResponse -// if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { -// t.Fatal(err) -// } -// -// assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") -// if data.Error == nil { -// assertUserSame(t, updatedUser, usersResponse.Ocs.Data, true) -// } else { -// assertUserSame(t, user, usersResponse.Ocs.Data, true) -// } -// cleanUp(t) -// } -// } -// } -//} -// -//// This is a bug demonstration test for endpoint '/cloud/user' -//// Link to the issue: https://github.com/owncloud/ocis/ocs/issues/52 -//func TestGetSingleUser(t *testing.T) { -// user := User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// Password: "password", -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%v/cloud/user%v", ocsVersion, formatpart), -// "", -// fmt.Sprintf("%v:%v", user.Username, user.Password), -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// log.Println(err) -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 400, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be a failure but was not") -// assertResponseMeta(t, Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "missing user in context", -// }, response.Ocs.Meta) -// assert.Empty(t, response.Ocs.Data) -// cleanUp(t) -// } -// } -//} -// -//// This is a bug demonstration test for endpoint '/cloud/user' -//// Link to the issue: https://github.com/owncloud/ocis/ocs/issues/53 -// -//func TestGetUserSigningKey(t *testing.T) { -// user := User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// Password: "password", -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// -// formatpart := getFormatString(format) -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%v/cloud/user/signing-key%v", ocsVersion, formatpart), -// "", -// fmt.Sprintf("%v:%v", user.Username, user.Password), -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// log.Println(err) -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 400, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be a failure but was not") -// assertResponseMeta(t, Meta{ -// Status: "error", -// StatusCode: 400, -// Message: "missing user in context", -// }, response.Ocs.Meta) -// assert.Empty(t, response.Ocs.Data) -// cleanUp(t) -// } -// } -//} -// -//func AddUserToGroup(userid, groupid string) error { -// res, err := sendRequest( -// "POST", -// fmt.Sprintf("/v2.php/cloud/users/%s/groups", userid), -// fmt.Sprintf("groupid=%v", groupid), -// "admin:admin", -// ) -// if err != nil { -// return err -// } -// if res.Code != 200 { -// return fmt.Errorf("Failed while adding the user to group") -// } -// return nil -//} -// -//func TestListUsersGroupNewUsers(t *testing.T) { -// users := []User{ -// { -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// }, -// { -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, user := range users { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response GetUsersGroupsResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// assert.Empty(t, response.Ocs.Data.Groups) -// -// cleanUp(t) -// } -// } -// } -//} -// -//func TestListUsersGroupDefaultUsers(t *testing.T) { -// DefaultGroups := map[string][]string{ -// "4c510ada-c86b-4815-8820-42cdf82c3d51": { -// "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", -// "6040aa17-9c64-4fef-9bd0-77234d71bad0", -// "dd58e5ec-842e-498b-8800-61f2ec6f911f", -// "262982c1-2362-4afa-bfdf-8cbfef64a06e", -// }, -// "820ba2a1-3f54-4538-80a4-2d73007e30bf": { -// "34f38767-c937-4eb6-b847-1c175829a2a0", -// }, -// "932b4540-8d16-481e-8ef4-588e4b6b151c": { -// "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", -// "a1726108-01f8-4c30-88df-2b1a9d1cba1a", -// "167cbee2-0518-455a-bfb2-031fe0621e5d", -// "262982c1-2362-4afa-bfdf-8cbfef64a06e", -// }, -// "bc596f3c-c955-4328-80a0-60d018b4ad57": { -// "34f38767-c937-4eb6-b847-1c175829a2a0", -// }, -// "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c": { -// "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", -// "7b87fd49-286e-4a5f-bafd-c535d5dd997a", -// "cedc21aa-4072-4614-8676-fa9165f598ff", -// "262982c1-2362-4afa-bfdf-8cbfef64a06e", -// }, -// "058bff95-6708-4fe5-91e4-9ea3d377588b": { -// "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, user := range DefaultUsers { -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response GetUsersGroupsResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// -// assert.Equal(t, DefaultGroups[user], response.Ocs.Data.Groups) -// } -// } -// } -// cleanUp(t) -//} -// -//func TestGetGroupForUserInvalidUserId(t *testing.T) { -// -// invalidUsers := []string{ -// "1", -// "invalid", -// "3434234233", -// "1am41validUs3r", -// "_-@@--$$__", -// } -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, user := range invalidUsers { -// res, err := sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), -// "", -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 404, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// assertResponseMeta(t, Meta{ -// Status: "error", -// StatusCode: 998, -// Message: "The requested user could not be found", -// }, response.Ocs.Meta) -// -// assert.Empty(t, response.Ocs.Data) -// } -// } -// } -//} -// -//func TestAddUsersToGroupsNewUsers(t *testing.T) { -// users := []User{ -// { -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// }, -// { -// Enabled: "true", -// Username: "thomson", -// ID: "thomson", -// Email: "thomson@example.com", -// Displayname: "J. J. Thomson", -// }, -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, user := range users { -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// -// // group id for Physics lover -// groupid := "262982c1-2362-4afa-bfdf-8cbfef64a06e" -// -// res, err := sendRequest( -// "POST", -// fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), -// "groupid="+groupid, -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 200, res, ocsVersion) -// assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") -// assert.Empty(t, response.Ocs.Data) -// -// // Check the user is in the group -// res, err = sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), -// "", -// "admin:admin", -// ) -// if err != nil { -// t.Fatal(err) -// } -// var grpResponse GetUsersGroupsResponse -// if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { -// t.Fatal(err) -// } -// assert.Contains(t, grpResponse.Ocs.Data.Groups, groupid) -// -// cleanUp(t) -// } -// } -// } -//} -// -//// Issue: https://github.com/owncloud/ocis/ocs/issues/55 Incorrect message when adding user to non existing group -//func TestAddUsersToGroupInvalidGroup(t *testing.T) { -// user := User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// } -// err := createUser(user) -// if err != nil { -// t.Fatal(err) -// } -// -// invalidGroups := []string{ -// "1", -// "invalid", -// "3434234233", -// "1am41validUs3r", -// "_-@@--$$__", -// "c7fbe8c4-139b-4376-b307-cf0a8c2d0d9c", -// } -// -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// for _, groupid := range invalidGroups { -// res, err := sendRequest( -// "POST", -// fmt.Sprintf("/%s/cloud/users/rutherford/groups%s", ocsVersion, formatpart), -// "groupid="+groupid, -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 404, res, ocsVersion) -// assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be fail but was successful") -// assertResponseMeta(t, Meta{ -// "error", -// 998, -// "The requested user could not be found", -// }, response.Ocs.Meta) -// assert.Empty(t, response.Ocs.Data) -// } -// } -// } -// cleanUp(t) -//} -// -//// Issue: https://github.com/owncloud/ocis/ocs/issues/57 - cannot remove user from group -//func TestRemoveUserFromGroup(t *testing.T) { -// user := User{ -// Enabled: "true", -// Username: "rutherford", -// ID: "rutherford", -// Email: "rutherford@example.com", -// Displayname: "Ernest RutherFord", -// } -// -// groups := []string{ -// "7b87fd49-286e-4a5f-bafd-c535d5dd997a", // radium-lovers -// "cedc21aa-4072-4614-8676-fa9165f598ff", // polonium-lovers -// "262982c1-2362-4afa-bfdf-8cbfef64a06e", // physics-lovers -// } -// -// var err error -// for _, ocsVersion := range ocsVersions { -// for _, format := range formats { -// formatpart := getFormatString(format) -// -// err = createUser(user) -// if err != nil { -// t.Fatalf("Failed while creating new user: %v", err) -// } -// for _, group := range groups { -// err := AddUserToGroup(user.ID, group) -// if err != nil { -// t.Fatalf("Failed while creating new user: %v", err) -// } -// } -// -// // Remove user from one group -// res, err := sendRequest( -// "DELETE", -// fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), -// "groupid="+groups[0], -// "admin:admin", -// ) -// -// if err != nil { -// t.Fatal(err) -// } -// -// var response EmptyResponse -// if format == "json" { -// if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { -// t.Fatal(err) -// } -// } else { -// if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { -// t.Fatal(err) -// } -// } -// -// assertStatusCode(t, 500, res, ocsVersion) -// assertResponseMeta(t, Meta{ -// "error", -// 996, -// "{\"id\":\".\",\"code\":500,\"detail\":\"could not clean up group id: invalid id .\",\"status\":\"Internal Server Error\"}", -// }, response.Ocs.Meta) -// assert.Empty(t, response.Ocs.Data) -// -// // Check the users are correctly added to group -// res, err = sendRequest( -// "GET", -// fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), -// "", -// "admin:admin", -// ) -// if err != nil { -// t.Fatal(err) -// } -// var grpResponse GetUsersGroupsResponse -// if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { -// t.Fatal(err) -// } -// -// // Change this line once the issue is fixed -// // assert.NotContains(t, grpResponse.Ocs.Data.Groups, groups[0]) -// assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[0]) -// assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[1]) -// assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[2]) -// cleanUp(t) -// } -// } -//} -// -//type mockClient struct{} -// -//func (c mockClient) Init(option ...client.Option) error { -// return nil -//} -// -//func (c mockClient) Options() client.Options { -// return client.Options{} -//} -// -//func (c mockClient) NewMessage(topic string, msg interface{}, opts ...client.MessageOption) client.Message { -// return nil -//} -// -//func (c mockClient) NewRequest(service, endpoint string, req interface{}, reqOpts ...client.RequestOption) client.Request { -// return nil -//} -// -//func (c mockClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { -// return nil -//} -// -//func (c mockClient) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) { -// return nil, nil -//} -// -//func (c mockClient) Publish(ctx context.Context, msg client.Message, opts ...client.PublishOption) error { -// return nil -//} -// -//func (c mockClient) String() string { -// return "ClientMock" -//} + +import ( + "context" + "encoding/base64" + "encoding/json" + "encoding/xml" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/http/httptest" + "net/url" + "path/filepath" + "strings" + "testing" + + "github.com/golang/protobuf/ptypes/empty" + ocisLog "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/owncloud/ocis/ocs/pkg/config" + svc "github.com/owncloud/ocis/ocs/pkg/service/v0" + "github.com/stretchr/testify/assert" + + "github.com/owncloud/ocis/ocis-pkg/service/grpc" + + accountsCmd "github.com/owncloud/ocis/accounts/pkg/command" + accountsCfg "github.com/owncloud/ocis/accounts/pkg/config" + accountsProto "github.com/owncloud/ocis/accounts/pkg/proto/v0" + accountsSvc "github.com/owncloud/ocis/accounts/pkg/service/v0" + + "github.com/micro/go-micro/v2/client" + settings "github.com/owncloud/ocis/settings/pkg/proto/v0" +) + +var service = grpc.Service{} + +var mockedRoleAssignment = map[string]string{} + +var ocsVersions = []string{"v1.php", "v2.php"} + +var formats = []string{"json", "xml"} + +const dataPath = "./accounts-store" + +var DefaultUsers = []string{ + "4c510ada-c86b-4815-8820-42cdf82c3d51", + "820ba2a1-3f54-4538-80a4-2d73007e30bf", + "932b4540-8d16-481e-8ef4-588e4b6b151c", + "bc596f3c-c955-4328-80a0-60d018b4ad57", + "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + "058bff95-6708-4fe5-91e4-9ea3d377588b", +} + +func getFormatString(format string) string { + if format == "json" { + return "?format=json" + } else if format == "xml" { + return "" + } else { + panic("Invalid format received") + } +} + +type Quota struct { + Free int64 `json:"free" xml:"free"` + Used int64 `json:"used" xml:"used"` + Total int64 `json:"total" xml:"total"` + Relative float32 `json:"relative" xml:"relative"` + Definition string `json:"definition" xml:"definition"` +} + +type User struct { + Enabled string `json:"enabled" xml:"enabled"` + ID string `json:"id" xml:"id"` + Username string `json:"username" xml:"username"` + Email string `json:"email" xml:"email"` + Password string `json:"-" xml:"-"` + Quota Quota `json:"quota" xml:"quota"` + UIDNumber int `json:"uidnumber" xml:"uidnumber"` + GIDNumber int `json:"gidnumber" xml:"gidnumber"` + Displayname string `json:"displayname" xml:"displayname"` +} + +func (u *User) getUserRequestString() string { + res := url.Values{} + + if u.Password != "" { + res.Add("password", u.Password) + } + + if u.ID != "" { + res.Add("userid", u.ID) + } + + if u.Username != "" { + res.Add("username", u.Username) + } + + if u.Email != "" { + res.Add("email", u.Email) + } + + if u.Displayname != "" { + res.Add("displayname", u.Displayname) + } + + if u.UIDNumber != 0 { + res.Add("uidnumber", fmt.Sprint(u.UIDNumber)) + } + + if u.GIDNumber != 0 { + res.Add("gidnumber", fmt.Sprint(u.GIDNumber)) + } + + return res.Encode() +} + +type Meta struct { + Status string `json:"status" xml:"status"` + StatusCode int `json:"statuscode" xml:"statuscode"` + Message string `json:"message" xml:"message"` +} + +func (m *Meta) Success(ocsVersion string) bool { + if !(ocsVersion == "v1.php" || ocsVersion == "v2.php") { + return false + } + if m.Status != "ok" { + return false + } + if ocsVersion == "v1.php" && m.StatusCode != 100 { + return false + } else if ocsVersion == "v2.php" && m.StatusCode != 200 { + return false + } else { + return true + } +} + +type SingleUserResponse struct { + Ocs struct { + Meta Meta `json:"meta" xml:"meta"` + Data User `json:"data" xml:"data"` + } `json:"ocs" xml:"ocs"` +} + +type GetUsersResponse struct { + Ocs struct { + Meta Meta `json:"meta" xml:"meta"` + Data struct { + Users []string `json:"users" xml:"users>element"` + } `json:"data" xml:"data"` + } `json:"ocs" xml:"ocs"` +} + +type EmptyResponse struct { + Ocs struct { + Meta Meta `json:"meta" xml:"meta"` + Data struct { + } `json:"data" xml:"data"` + } `json:"ocs" xml:"ocs"` +} + +type GetUsersGroupsResponse struct { + Ocs struct { + Meta Meta `json:"meta" xml:"meta"` + Data struct { + Groups []string `json:"groups" xml:"groups>element"` + } `json:"data" xml:"data"` + } `json:"ocs" xml:"ocs"` +} + +func assertStatusCode(t *testing.T, statusCode int, res *httptest.ResponseRecorder, ocsVersion string) { + if ocsVersion == "v1.php" { + assert.Equal(t, 200, res.Code) + } else { + assert.Equal(t, statusCode, res.Code) + } +} + +func assertResponseMeta(t *testing.T, expected, actual Meta) { + assert.Equal(t, expected.Status, actual.Status, "The status of response doesn't matches") + assert.Equal(t, expected.StatusCode, actual.StatusCode, "The Status code of response doesn't matches") + assert.Equal(t, expected.Message, actual.Message, "The Message of response doesn't matches") +} + +func assertUserSame(t *testing.T, expected, actual User, quotaAvailable bool) { + if expected.ID == "" { + // Check the auto generated userId + assert.Regexp( + t, + "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", + actual.ID, "the userid is not a valid uuid", + ) + } else { + assert.Equal(t, expected.ID, actual.ID, "UserId doesn't match for user %v", expected.Username) + } + assert.Equal(t, expected.Username, actual.Username, "Username doesn't match for user %v", expected.Username) + assert.Equal(t, expected.Email, actual.Email, "email doesn't match for user %v", expected.Username) + assert.Equal(t, expected.Enabled, actual.Enabled, "enabled doesn't match for user %v", expected.Username) + assert.Equal(t, expected.Displayname, actual.Displayname, "displayname doesn't match for user %v", expected.Username) + if quotaAvailable { + assert.NotZero(t, actual.Quota.Free) + assert.NotZero(t, actual.Quota.Used) + assert.NotZero(t, actual.Quota.Total) + assert.Equal(t, "default", actual.Quota.Definition) + } else { + assert.Equal(t, expected.Quota, actual.Quota, "Quota match for user %v", expected.Username) + } + + // FIXME: gidnumber and Uidnumber are always 0 + // https://github.com/owncloud/ocis/ocs/issues/45 + assert.Equal(t, 0, actual.UIDNumber, "UidNumber doesn't match for user %v", expected.Username) + assert.Equal(t, 0, actual.GIDNumber, "GIDNumber doesn't match for user %v", expected.Username) + +} + +func deleteAccount(t *testing.T, id string) (*empty.Empty, error) { + client := service.Client() + cl := accountsProto.NewAccountsService("com.owncloud.api.accounts", client) + + req := &accountsProto.DeleteAccountRequest{Id: id} + res, err := cl.DeleteAccount(context.Background(), req) + return res, err +} + +func buildRoleServiceMock() settings.RoleService { + return settings.MockRoleService{ + AssignRoleToUserFunc: func(ctx context.Context, req *settings.AssignRoleToUserRequest, opts ...client.CallOption) (res *settings.AssignRoleToUserResponse, err error) { + mockedRoleAssignment[req.AccountUuid] = req.RoleId + return &settings.AssignRoleToUserResponse{ + Assignment: &settings.UserRoleAssignment{ + AccountUuid: req.AccountUuid, + RoleId: req.RoleId, + }, + }, nil + }, + } +} + +func init() { + service = grpc.NewService( + grpc.Namespace("com.owncloud.api"), + grpc.Name("accounts"), + grpc.Address("localhost:9180"), + ) + + c := &accountsCfg.Config{ + Server: accountsCfg.Server{ + AccountsDataPath: dataPath, + }, + Log: accountsCfg.Log{ + Level: "info", + Pretty: true, + Color: true, + }, + } + + var hdlr *accountsSvc.Service + var err error + + if hdlr, err = accountsSvc.New( + accountsSvc.Logger(accountsCmd.NewLogger(c)), + accountsSvc.Config(c), + accountsSvc.RoleService(buildRoleServiceMock())); err != nil { + log.Fatalf("Could not create new service") + } + + err = accountsProto.RegisterAccountsServiceHandler(service.Server(), hdlr) + if err != nil { + log.Fatal("could not register the Accounts handler") + } + err = accountsProto.RegisterGroupsServiceHandler(service.Server(), hdlr) + if err != nil { + log.Fatal("could not register the Groups handler") + } + + err = service.Server().Start() + if err != nil { + log.Fatalf("could not start server: %v", err) + } +} + +func cleanUp(t *testing.T) { + datastore := filepath.Join(dataPath, "accounts") + + files, err := ioutil.ReadDir(datastore) + if err != nil { + log.Fatal(err) + } + + for _, f := range files { + found := false + for _, defUser := range DefaultUsers { + if f.Name() == defUser { + found = true + break + } + } + + if !found { + deleteAccount(t, f.Name()) + } + } +} + +func sendRequest(method, endpoint, body, auth string) (*httptest.ResponseRecorder, error) { + var reader = strings.NewReader(body) + req, err := http.NewRequest(method, endpoint, reader) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + if auth != "" { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) + } + + rr := httptest.NewRecorder() + + service := getService() + service.ServeHTTP(rr, req) + + return rr, nil +} + +func getService() svc.Service { + c := &config.Config{ + HTTP: config.HTTP{ + Root: "/", + Addr: "localhost:9110", + }, + TokenManager: config.TokenManager{ + JWTSecret: "HELLO-secret", + }, + Log: config.Log{ + Level: "debug", + }, + } + + var logger ocisLog.Logger + + svc := svc.NewService( + svc.Logger(logger), + svc.Config(c), + ) + + return svc +} + +func createUser(u User) error { + _, err := sendRequest( + "POST", + "/v1.php/cloud/users?format=json", + u.getUserRequestString(), + "admin:admin", + ) + + if err != nil { + return err + } + return nil +} + +func TestCreateUser(t *testing.T) { + testData := []struct { + user User + err *Meta + }{ + // A simple user + { + User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "ErnestRutherFord", + Password: "newPassword", + }, + nil, + }, + + // User with Uid and Gid defined + { + User{ + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + UIDNumber: 20027, + GIDNumber: 30000, + Password: "newPassword", + }, + nil, + }, + + // User with different username and Id + { + User{ + Enabled: "true", + Username: "niels", + ID: "bohr", + Email: "bohr@example.com", + Displayname: "Niels Bohr", + Password: "newPassword", + }, + nil, + }, + + // User withoutl password + // https://github.com/owncloud/ocis/ocs/issues/50 + { + User{ + Enabled: "true", + Username: "john", + ID: "john", + Email: "john@example.com", + Displayname: "John Dalton", + }, + nil, + }, + + // User with special character in username + // https://github.com/owncloud/ocis/ocs/issues/49 + { + User{ + Enabled: "true", + Username: "schrödinger", + ID: "schrödinger", + Email: "schrödinger@example.com", + Displayname: "Erwin Schrödinger", + Password: "newPassword", + }, + &Meta{ + Status: "error", + StatusCode: 400, + Message: "preferred_name 'schrödinger' must be at least the local part of an email", + }, + }, + + // User with different userid and email + { + User{ + Enabled: "true", + Username: "planck", + ID: "planck", + Email: "max@example.com", + Displayname: "Max Planck", + Password: "newPassword", + }, + nil, + }, + + // User with different userid and email and username + { + User{ + Enabled: "true", + Username: "hisenberg", + ID: "hberg", + Email: "werner@example.com", + Displayname: "Werner Hisenberg", + Password: "newPassword", + }, + nil, + }, + + // User without displayname + { + User{ + Enabled: "true", + Username: "oppenheimer", + ID: "oppenheimer", + Email: "robert@example.com", + Password: "newPassword", + }, + nil, + }, + + // User wit invalid email + { + User{ + Enabled: "true", + Username: "chadwick", + ID: "chadwick", + Email: "not_a_email", + Password: "newPassword", + }, + &Meta{ + Status: "error", + StatusCode: 400, + Message: "mail 'not_a_email' must be a valid email", + }, + }, + + // User without email + { + User{ + Enabled: "true", + Username: "chadwick", + ID: "chadwick", + Password: "newPassword", + }, + &Meta{ + Status: "error", + StatusCode: 400, + Message: "mail '' must be a valid email", + }, + }, + + // User without username + { + User{ + Enabled: "true", + ID: "chadwick", + Email: "james@example.com", + Password: "newPassword", + }, + &Meta{ + Status: "error", + StatusCode: 400, + Message: "preferred_name '' must be at least the local part of an email", + }, + }, + + // User without userid + { + User{ + Enabled: "true", + Username: "chadwick", + Email: "james@example.com", + Password: "newPassword", + }, + nil, + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + for _, data := range testData { + formatpart := getFormatString(format) + res, err := sendRequest( + "POST", + fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), + data.user.getUserRequestString(), + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response SingleUserResponse + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + if data.err == nil { + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + assertStatusCode(t, 200, res, ocsVersion) + assertUserSame(t, data.user, response.Ocs.Data, false) + } else { + assertStatusCode(t, 400, res, ocsVersion) + assertResponseMeta(t, *data.err, response.Ocs.Meta) + } + + var id string + if data.user.ID != "" { + id = data.user.ID + } else { + id = response.Ocs.Data.ID + } + + res, err = sendRequest( + "GET", + "/v1.php/cloud/users?format=json", + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var usersResponse GetUsersResponse + if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { + t.Fatal(err) + } + + assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") + + if data.err == nil { + assert.Contains(t, usersResponse.Ocs.Data.Users, id) + } else { + assert.NotContains(t, usersResponse.Ocs.Data.Users, data.user.ID) + } + } + cleanUp(t) + } + } +} + +func TestGetUsers(t *testing.T) { + users := []User{ + { + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + }, + { + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + for _, user := range users { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + } + + formatpart := getFormatString(format) + res, err := sendRequest( + "GET", + fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response GetUsersResponse + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + for _, user := range users { + assert.Contains(t, response.Ocs.Data.Users, user.Username) + } + cleanUp(t) + } + } +} + +func TestGetUsersDefaultUsers(t *testing.T) { + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + res, err := sendRequest( + "GET", + fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response GetUsersResponse + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + for _, user := range DefaultUsers { + assert.Contains(t, response.Ocs.Data.Users, user) + } + cleanUp(t) + } + } +} + +func TestGetUser(t *testing.T) { + users := []User{ + { + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + }, + { + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + + for _, user := range users { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + } + formatpart := getFormatString(format) + for _, user := range users { + res, err := sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user.ID, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response SingleUserResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to pass but it failed") + assertUserSame(t, user, response.Ocs.Data, true) + } + cleanUp(t) + } + } +} + +func TestGetUserInvalidId(t *testing.T) { + invalidUsers := []string{ + "1", + "invalid", + "3434234233", + "1am41validUs3r", + "_-@@--$$__", + } + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, user := range invalidUsers { + res, err := sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/user/%s%s", ocsVersion, user, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response SingleUserResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 404, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "the response was expected to fail but passed") + assertResponseMeta(t, Meta{ + Status: "error", + StatusCode: 998, + Message: "not found", + }, response.Ocs.Meta) + cleanUp(t) + } + } + } +} +func TestDeleteUser(t *testing.T) { + users := []User{ + { + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + }, + { + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + for _, user := range users { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + } + + formatpart := getFormatString(format) + res, err := sendRequest( + "DELETE", + fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + assert.Empty(t, response.Ocs.Data) + + // Check deleted user doesn't exist and the other user does + res, err = sendRequest( + "GET", + "/v1.php/cloud/users?format=json", + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var usersResponse GetUsersResponse + if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { + t.Fatal(err) + } + + assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") + assert.Contains(t, usersResponse.Ocs.Data.Users, "thomson") + assert.NotContains(t, usersResponse.Ocs.Data.Users, "rutherford") + + cleanUp(t) + } + } +} + +func TestDeleteUserInvalidId(t *testing.T) { + + invalidUsers := []string{ + "1", + "invalid", + "3434234233", + "1am41validUs3r", + "_-@@--$$__", + } + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + for _, user := range invalidUsers { + formatpart := getFormatString(format) + res, err := sendRequest( + "DELETE", + fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 404, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was not expected to be successful but was") + assert.Empty(t, response.Ocs.Data) + + assertResponseMeta(t, Meta{ + Status: "error", + StatusCode: 998, + Message: "The requested user could not be found", + }, response.Ocs.Meta) + } + } + } +} + +func TestUpdateUser(t *testing.T) { + user := User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + } + + testData := []struct { + UpdateKey string + UpdateValue string + Error *Meta + }{ + { + "displayname", + "James Chadwick", + nil, + }, + { + "display", + "Neils Bohr", + nil, + }, + { + "email", + "ford@user.org", + nil, + }, + // Invalid email doesn't gives error + // https://github.com/owncloud/ocis/ocs/issues/46 + { + "email", + "not_a_valid_email", + nil, + }, + { + "password", + "strongpass1234", + nil, + }, + { + "username", + "e_rutherford", + nil, + }, + // Empty values doesn't gives error + // https://github.com/owncloud/ocis/ocs/issues/51 + { + "email", + "", + nil, + }, + { + "username", + "", + nil, + }, + { + "password", + "", + nil, + }, + + // Invalid Keys + { + "invalid_key", + "validvalue", + &Meta{ + Status: "error", + StatusCode: 103, + Message: "unknown key 'invalid_key'", + }, + }, + { + "12345", + "validvalue", + &Meta{ + Status: "error", + StatusCode: 103, + Message: "unknown key '12345'", + }, + }, + { + "", + "validvalue", + &Meta{ + Status: "error", + StatusCode: 103, + Message: "unknown key ''", + }, + }, + { + "", + "", + &Meta{ + Status: "error", + StatusCode: 103, + Message: "unknown key ''", + }, + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, data := range testData { + err := createUser(user) + if err != nil { + t.Fatalf("Failed while creating user: %v", err) + } + + params := url.Values{} + + params.Add("key", data.UpdateKey) + params.Add("value", data.UpdateValue) + + res, err := sendRequest( + "PUT", + fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), + params.Encode(), + "admin:admin", + ) + + updatedUser := user + switch data.UpdateKey { + case "username": + updatedUser.Username = data.UpdateValue + case "email": + updatedUser.Email = data.UpdateValue + case "displayname": + updatedUser.Displayname = data.UpdateValue + case "display": + updatedUser.Displayname = data.UpdateValue + } + + if err != nil { + t.Fatal(err) + } + + var response struct { + Ocs struct { + Meta Meta `json:"meta" xml:"meta"` + } `json:"ocs" xml:"ocs"` + } + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + if data.Error != nil { + assertResponseMeta(t, *data.Error, response.Ocs.Meta) + assertStatusCode(t, 400, res, ocsVersion) + } else { + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but failed") + assertStatusCode(t, 200, res, ocsVersion) + } + + // Check deleted user doesn't exist and the other user does + res, err = sendRequest( + "GET", + "/v1.php/cloud/users/rutherford?format=json", + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var usersResponse SingleUserResponse + if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { + t.Fatal(err) + } + + assert.True(t, usersResponse.Ocs.Meta.Success("v1.php"), "The response was expected to be successful but was not") + if data.Error == nil { + assertUserSame(t, updatedUser, usersResponse.Ocs.Data, true) + } else { + assertUserSame(t, user, usersResponse.Ocs.Data, true) + } + cleanUp(t) + } + } + } +} + +// This is a bug demonstration test for endpoint '/cloud/user' +// Link to the issue: https://github.com/owncloud/ocis/ocs/issues/52 +func TestGetSingleUser(t *testing.T) { + user := User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + Password: "password", + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + + formatpart := getFormatString(format) + res, err := sendRequest( + "GET", + fmt.Sprintf("/%v/cloud/user%v", ocsVersion, formatpart), + "", + fmt.Sprintf("%v:%v", user.Username, user.Password), + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + log.Println(err) + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 400, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be a failure but was not") + assertResponseMeta(t, Meta{ + Status: "error", + StatusCode: 400, + Message: "missing user in context", + }, response.Ocs.Meta) + assert.Empty(t, response.Ocs.Data) + cleanUp(t) + } + } +} + +// This is a bug demonstration test for endpoint '/cloud/user' +// Link to the issue: https://github.com/owncloud/ocis/ocs/issues/53 + +func TestGetUserSigningKey(t *testing.T) { + user := User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + Password: "password", + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + + formatpart := getFormatString(format) + res, err := sendRequest( + "GET", + fmt.Sprintf("/%v/cloud/user/signing-key%v", ocsVersion, formatpart), + "", + fmt.Sprintf("%v:%v", user.Username, user.Password), + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + log.Println(err) + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 400, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be a failure but was not") + assertResponseMeta(t, Meta{ + Status: "error", + StatusCode: 400, + Message: "missing user in context", + }, response.Ocs.Meta) + assert.Empty(t, response.Ocs.Data) + cleanUp(t) + } + } +} + +func AddUserToGroup(userid, groupid string) error { + res, err := sendRequest( + "POST", + fmt.Sprintf("/v2.php/cloud/users/%s/groups", userid), + fmt.Sprintf("groupid=%v", groupid), + "admin:admin", + ) + if err != nil { + return err + } + if res.Code != 200 { + return fmt.Errorf("Failed while adding the user to group") + } + return nil +} + +func TestListUsersGroupNewUsers(t *testing.T) { + users := []User{ + { + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + }, + { + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, user := range users { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + + res, err := sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response GetUsersGroupsResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + assert.Empty(t, response.Ocs.Data.Groups) + + cleanUp(t) + } + } + } +} + +func TestListUsersGroupDefaultUsers(t *testing.T) { + DefaultGroups := map[string][]string{ + "4c510ada-c86b-4815-8820-42cdf82c3d51": { + "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", + "6040aa17-9c64-4fef-9bd0-77234d71bad0", + "dd58e5ec-842e-498b-8800-61f2ec6f911f", + "262982c1-2362-4afa-bfdf-8cbfef64a06e", + }, + "820ba2a1-3f54-4538-80a4-2d73007e30bf": { + "34f38767-c937-4eb6-b847-1c175829a2a0", + }, + "932b4540-8d16-481e-8ef4-588e4b6b151c": { + "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", + "a1726108-01f8-4c30-88df-2b1a9d1cba1a", + "167cbee2-0518-455a-bfb2-031fe0621e5d", + "262982c1-2362-4afa-bfdf-8cbfef64a06e", + }, + "bc596f3c-c955-4328-80a0-60d018b4ad57": { + "34f38767-c937-4eb6-b847-1c175829a2a0", + }, + "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c": { + "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", + "7b87fd49-286e-4a5f-bafd-c535d5dd997a", + "cedc21aa-4072-4614-8676-fa9165f598ff", + "262982c1-2362-4afa-bfdf-8cbfef64a06e", + }, + "058bff95-6708-4fe5-91e4-9ea3d377588b": { + "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, user := range DefaultUsers { + res, err := sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response GetUsersGroupsResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + + assert.Equal(t, DefaultGroups[user], response.Ocs.Data.Groups) + } + } + } + cleanUp(t) +} + +func TestGetGroupForUserInvalidUserId(t *testing.T) { + + invalidUsers := []string{ + "1", + "invalid", + "3434234233", + "1am41validUs3r", + "_-@@--$$__", + } + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, user := range invalidUsers { + res, err := sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), + "", + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 404, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + assertResponseMeta(t, Meta{ + Status: "error", + StatusCode: 998, + Message: "The requested user could not be found", + }, response.Ocs.Meta) + + assert.Empty(t, response.Ocs.Data) + } + } + } +} + +func TestAddUsersToGroupsNewUsers(t *testing.T) { + users := []User{ + { + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + }, + { + Enabled: "true", + Username: "thomson", + ID: "thomson", + Email: "thomson@example.com", + Displayname: "J. J. Thomson", + }, + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, user := range users { + err := createUser(user) + if err != nil { + t.Fatal(err) + } + + // group id for Physics lover + groupid := "262982c1-2362-4afa-bfdf-8cbfef64a06e" + + res, err := sendRequest( + "POST", + fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), + "groupid="+groupid, + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 200, res, ocsVersion) + assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be successful but was not") + assert.Empty(t, response.Ocs.Data) + + // Check the user is in the group + res, err = sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), + "", + "admin:admin", + ) + if err != nil { + t.Fatal(err) + } + var grpResponse GetUsersGroupsResponse + if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { + t.Fatal(err) + } + assert.Contains(t, grpResponse.Ocs.Data.Groups, groupid) + + cleanUp(t) + } + } + } +} + +// Issue: https://github.com/owncloud/ocis/ocs/issues/55 Incorrect message when adding user to non existing group +func TestAddUsersToGroupInvalidGroup(t *testing.T) { + user := User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + } + err := createUser(user) + if err != nil { + t.Fatal(err) + } + + invalidGroups := []string{ + "1", + "invalid", + "3434234233", + "1am41validUs3r", + "_-@@--$$__", + "c7fbe8c4-139b-4376-b307-cf0a8c2d0d9c", + } + + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + for _, groupid := range invalidGroups { + res, err := sendRequest( + "POST", + fmt.Sprintf("/%s/cloud/users/rutherford/groups%s", ocsVersion, formatpart), + "groupid="+groupid, + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 404, res, ocsVersion) + assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be fail but was successful") + assertResponseMeta(t, Meta{ + "error", + 998, + "The requested user could not be found", + }, response.Ocs.Meta) + assert.Empty(t, response.Ocs.Data) + } + } + } + cleanUp(t) +} + +// Issue: https://github.com/owncloud/ocis/ocs/issues/57 - cannot remove user from group +func TestRemoveUserFromGroup(t *testing.T) { + user := User{ + Enabled: "true", + Username: "rutherford", + ID: "rutherford", + Email: "rutherford@example.com", + Displayname: "Ernest RutherFord", + } + + groups := []string{ + "7b87fd49-286e-4a5f-bafd-c535d5dd997a", // radium-lovers + "cedc21aa-4072-4614-8676-fa9165f598ff", // polonium-lovers + "262982c1-2362-4afa-bfdf-8cbfef64a06e", // physics-lovers + } + + var err error + for _, ocsVersion := range ocsVersions { + for _, format := range formats { + formatpart := getFormatString(format) + + err = createUser(user) + if err != nil { + t.Fatalf("Failed while creating new user: %v", err) + } + for _, group := range groups { + err := AddUserToGroup(user.ID, group) + if err != nil { + t.Fatalf("Failed while creating new user: %v", err) + } + } + + // Remove user from one group + res, err := sendRequest( + "DELETE", + fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), + "groupid="+groups[0], + "admin:admin", + ) + + if err != nil { + t.Fatal(err) + } + + var response EmptyResponse + if format == "json" { + if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { + t.Fatal(err) + } + } else { + if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { + t.Fatal(err) + } + } + + assertStatusCode(t, 500, res, ocsVersion) + assertResponseMeta(t, Meta{ + "error", + 996, + "{\"id\":\".\",\"code\":500,\"detail\":\"could not clean up group id: invalid id .\",\"status\":\"Internal Server Error\"}", + }, response.Ocs.Meta) + assert.Empty(t, response.Ocs.Data) + + // Check the users are correctly added to group + res, err = sendRequest( + "GET", + fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), + "", + "admin:admin", + ) + if err != nil { + t.Fatal(err) + } + var grpResponse GetUsersGroupsResponse + if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { + t.Fatal(err) + } + + // Change this line once the issue is fixed + // assert.NotContains(t, grpResponse.Ocs.Data.Groups, groups[0]) + assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[0]) + assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[1]) + assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[2]) + cleanUp(t) + } + } +}