mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-07-11 08:08:16 -04:00
refactor code into separate files (#29)
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
committed by
GitHub
parent
5934026799
commit
2efcd929c1
@@ -1,4 +1,4 @@
|
||||
package svc
|
||||
package cs3
|
||||
|
||||
import (
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
@@ -15,7 +15,8 @@ func newConn(endpoint string) (*grpc.ClientConn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func getGatewayServiceClient(endpoint string) (gateway.GatewayAPIClient, error) {
|
||||
// GetGatewayServiceClient returns a new cs3 gateway client
|
||||
func GetGatewayServiceClient(endpoint string) (gateway.GatewayAPIClient, error) {
|
||||
conn, err := newConn(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -23,8 +24,3 @@ func getGatewayServiceClient(endpoint string) (gateway.GatewayAPIClient, error)
|
||||
|
||||
return gateway.NewGatewayAPIClient(conn), nil
|
||||
}
|
||||
|
||||
// GetClient returns a gateway client to talk to reva
|
||||
func (g Graph) GetClient() (gateway.GatewayAPIClient, error) {
|
||||
return getGatewayServiceClient(g.config.Reva.Address)
|
||||
}
|
||||
@@ -1,20 +1,13 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/owncloud/ocis-graph/pkg/service/v0/errorcode"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/owncloud/ocis-graph/pkg/config"
|
||||
"github.com/owncloud/ocis-graph/pkg/cs3"
|
||||
"github.com/owncloud/ocis-pkg/v2/log"
|
||||
"github.com/owncloud/ocis-pkg/v2/oidc"
|
||||
msgraph "github.com/yaegashi/msgraph.go/v1.0"
|
||||
"gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
// Graph defines implements the business logic for Service.
|
||||
@@ -29,238 +22,9 @@ func (g Graph) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
g.mux.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// UserCtx middleware is used to load an User object from
|
||||
// the URL parameters passed through as the request. In case
|
||||
// the User could not be found, we stop here and return a 404.
|
||||
func (g Graph) UserCtx(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var user *ldap.Entry
|
||||
var err error
|
||||
|
||||
userID := chi.URLParam(r, "userID")
|
||||
if userID == "" {
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
filter := fmt.Sprintf("(entryuuid=%s)", userID)
|
||||
user, err = g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read user %s", userID)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), userIDKey, user)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// GroupCtx middleware is used to load an User object from
|
||||
// the URL parameters passed through as the request. In case
|
||||
// the User could not be found, we stop here and return a 404.
|
||||
func (g Graph) GroupCtx(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
groupID := chi.URLParam(r, "groupID")
|
||||
if groupID == "" {
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
filter := fmt.Sprintf("(entryuuid=%s)", groupID)
|
||||
group, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNGroups, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read group %s", groupID)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), groupIDKey, group)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// GetMe implements the Service interface.
|
||||
func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
claims := oidc.FromContext(r.Context())
|
||||
g.logger.Info().Interface("Claims", claims).Msg("Claims in /me")
|
||||
|
||||
filter := fmt.Sprintf("(uid=%s)", claims.PreferredUsername)
|
||||
user, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read user %s", claims.PreferredUsername)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
me := createUserModelFromLDAP(user)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, me)
|
||||
}
|
||||
|
||||
// GetUsers implements the Service interface.
|
||||
func (g Graph) GetUsers(w http.ResponseWriter, r *http.Request) {
|
||||
con, err := g.initLdap()
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed to initialize ldap")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := g.ldapSearch(con, "(objectclass=*)", g.config.Ldap.BaseDNUsers)
|
||||
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed search ldap with filter: '(objectclass=*)'")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var users []*msgraph.User
|
||||
|
||||
for _, user := range result.Entries {
|
||||
users = append(
|
||||
users,
|
||||
createUserModelFromLDAP(
|
||||
user,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, &listResponse{Value: users})
|
||||
}
|
||||
|
||||
// GetUser implements the Service interface.
|
||||
func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value(userIDKey).(*ldap.Entry)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, createUserModelFromLDAP(user))
|
||||
}
|
||||
|
||||
// GetGroups implements the Service interface.
|
||||
func (g Graph) GetGroups(w http.ResponseWriter, r *http.Request) {
|
||||
con, err := g.initLdap()
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed to initialize ldap")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := g.ldapSearch(con, "(objectclass=*)", g.config.Ldap.BaseDNGroups)
|
||||
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed search ldap with filter: '(objectclass=*)'")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var groups []*msgraph.Group
|
||||
|
||||
for _, group := range result.Entries {
|
||||
groups = append(
|
||||
groups,
|
||||
createGroupModelFromLDAP(
|
||||
group,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, &listResponse{Value: groups})
|
||||
}
|
||||
|
||||
// GetGroup implements the Service interface.
|
||||
func (g Graph) GetGroup(w http.ResponseWriter, r *http.Request) {
|
||||
group := r.Context().Value(groupIDKey).(*ldap.Entry)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, createGroupModelFromLDAP(group))
|
||||
}
|
||||
|
||||
func (g Graph) ldapGetSingleEntry(baseDn string, filter string) (*ldap.Entry, error) {
|
||||
conn, err := g.initLdap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := g.ldapSearch(conn, filter, baseDn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(result.Entries) == 0 {
|
||||
return nil, errors.New("resource not found")
|
||||
}
|
||||
return result.Entries[0], nil
|
||||
}
|
||||
|
||||
func (g Graph) initLdap() (*ldap.Conn, error) {
|
||||
g.logger.Info().Msgf("Dialing ldap %s://%s", g.config.Ldap.Network, g.config.Ldap.Address)
|
||||
con, err := ldap.Dial(g.config.Ldap.Network, g.config.Ldap.Address)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := con.Bind(g.config.Ldap.UserName, g.config.Ldap.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return con, nil
|
||||
}
|
||||
|
||||
func (g Graph) ldapSearch(con *ldap.Conn, filter string, baseDN string) (*ldap.SearchResult, error) {
|
||||
search := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.NeverDerefAliases,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
filter,
|
||||
[]string{"dn",
|
||||
"uid",
|
||||
"givenname",
|
||||
"mail",
|
||||
"displayname",
|
||||
"entryuuid",
|
||||
"sn",
|
||||
"cn",
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
return con.Search(search)
|
||||
}
|
||||
|
||||
func createUserModelFromLDAP(entry *ldap.Entry) *msgraph.User {
|
||||
displayName := entry.GetAttributeValue("displayname")
|
||||
givenName := entry.GetAttributeValue("givenname")
|
||||
mail := entry.GetAttributeValue("mail")
|
||||
surName := entry.GetAttributeValue("sn")
|
||||
id := entry.GetAttributeValue("entryuuid")
|
||||
return &msgraph.User{
|
||||
DisplayName: &displayName,
|
||||
GivenName: &givenName,
|
||||
Surname: &surName,
|
||||
Mail: &mail,
|
||||
DirectoryObject: msgraph.DirectoryObject{
|
||||
Entity: msgraph.Entity{
|
||||
ID: &id,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createGroupModelFromLDAP(entry *ldap.Entry) *msgraph.Group {
|
||||
id := entry.GetAttributeValue("entryuuid")
|
||||
displayName := entry.GetAttributeValue("cn")
|
||||
|
||||
return &msgraph.Group{
|
||||
DisplayName: &displayName,
|
||||
DirectoryObject: msgraph.DirectoryObject{
|
||||
Entity: msgraph.Entity{
|
||||
ID: &id,
|
||||
},
|
||||
},
|
||||
}
|
||||
// GetClient returns a gateway client to talk to reva
|
||||
func (g Graph) GetClient() (gateway.GatewayAPIClient, error) {
|
||||
return cs3.GetGatewayServiceClient(g.config.Reva.Address)
|
||||
}
|
||||
|
||||
// The key type is unexported to prevent collisions with context keys defined in
|
||||
|
||||
77
pkg/service/v0/groups.go
Normal file
77
pkg/service/v0/groups.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/owncloud/ocis-graph/pkg/service/v0/errorcode"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/render"
|
||||
msgraph "github.com/yaegashi/msgraph.go/v1.0"
|
||||
"gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
// GroupCtx middleware is used to load an User object from
|
||||
// the URL parameters passed through as the request. In case
|
||||
// the User could not be found, we stop here and return a 404.
|
||||
func (g Graph) GroupCtx(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
groupID := chi.URLParam(r, "groupID")
|
||||
if groupID == "" {
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
filter := fmt.Sprintf("(entryuuid=%s)", groupID)
|
||||
group, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNGroups, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read group %s", groupID)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), groupIDKey, group)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// GetGroups implements the Service interface.
|
||||
func (g Graph) GetGroups(w http.ResponseWriter, r *http.Request) {
|
||||
con, err := g.initLdap()
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed to initialize ldap")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := g.ldapSearch(con, "(objectclass=*)", g.config.Ldap.BaseDNGroups)
|
||||
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed search ldap with filter: '(objectclass=*)'")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var groups []*msgraph.Group
|
||||
|
||||
for _, group := range result.Entries {
|
||||
groups = append(
|
||||
groups,
|
||||
createGroupModelFromLDAP(
|
||||
group,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, &listResponse{Value: groups})
|
||||
}
|
||||
|
||||
// GetGroup implements the Service interface.
|
||||
func (g Graph) GetGroup(w http.ResponseWriter, r *http.Request) {
|
||||
group := r.Context().Value(groupIDKey).(*ldap.Entry)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, createGroupModelFromLDAP(group))
|
||||
}
|
||||
94
pkg/service/v0/ldap.go
Normal file
94
pkg/service/v0/ldap.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
msgraph "github.com/yaegashi/msgraph.go/v1.0"
|
||||
"gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
func (g Graph) ldapGetSingleEntry(baseDn string, filter string) (*ldap.Entry, error) {
|
||||
conn, err := g.initLdap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := g.ldapSearch(conn, filter, baseDn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(result.Entries) == 0 {
|
||||
return nil, errors.New("resource not found")
|
||||
}
|
||||
return result.Entries[0], nil
|
||||
}
|
||||
|
||||
func (g Graph) initLdap() (*ldap.Conn, error) {
|
||||
g.logger.Info().Msgf("Dialing ldap %s://%s", g.config.Ldap.Network, g.config.Ldap.Address)
|
||||
con, err := ldap.Dial(g.config.Ldap.Network, g.config.Ldap.Address)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := con.Bind(g.config.Ldap.UserName, g.config.Ldap.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return con, nil
|
||||
}
|
||||
|
||||
func (g Graph) ldapSearch(con *ldap.Conn, filter string, baseDN string) (*ldap.SearchResult, error) {
|
||||
search := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.NeverDerefAliases,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
filter,
|
||||
[]string{"dn",
|
||||
"uid",
|
||||
"givenname",
|
||||
"mail",
|
||||
"displayname",
|
||||
"entryuuid",
|
||||
"sn",
|
||||
"cn",
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
return con.Search(search)
|
||||
}
|
||||
|
||||
func createUserModelFromLDAP(entry *ldap.Entry) *msgraph.User {
|
||||
displayName := entry.GetAttributeValue("displayname")
|
||||
givenName := entry.GetAttributeValue("givenname")
|
||||
mail := entry.GetAttributeValue("mail")
|
||||
surName := entry.GetAttributeValue("sn")
|
||||
id := entry.GetAttributeValue("entryuuid")
|
||||
return &msgraph.User{
|
||||
DisplayName: &displayName,
|
||||
GivenName: &givenName,
|
||||
Surname: &surName,
|
||||
Mail: &mail,
|
||||
DirectoryObject: msgraph.DirectoryObject{
|
||||
Entity: msgraph.Entity{
|
||||
ID: &id,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createGroupModelFromLDAP(entry *ldap.Entry) *msgraph.Group {
|
||||
id := entry.GetAttributeValue("entryuuid")
|
||||
displayName := entry.GetAttributeValue("cn")
|
||||
|
||||
return &msgraph.Group{
|
||||
DisplayName: &displayName,
|
||||
DirectoryObject: msgraph.DirectoryObject{
|
||||
Entity: msgraph.Entity{
|
||||
ID: &id,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
100
pkg/service/v0/users.go
Normal file
100
pkg/service/v0/users.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/owncloud/ocis-graph/pkg/service/v0/errorcode"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/owncloud/ocis-pkg/v2/oidc"
|
||||
msgraph "github.com/yaegashi/msgraph.go/v1.0"
|
||||
"gopkg.in/ldap.v3"
|
||||
)
|
||||
|
||||
// UserCtx middleware is used to load an User object from
|
||||
// the URL parameters passed through as the request. In case
|
||||
// the User could not be found, we stop here and return a 404.
|
||||
func (g Graph) UserCtx(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var user *ldap.Entry
|
||||
var err error
|
||||
|
||||
userID := chi.URLParam(r, "userID")
|
||||
if userID == "" {
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
filter := fmt.Sprintf("(entryuuid=%s)", userID)
|
||||
user, err = g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read user %s", userID)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), userIDKey, user)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// GetMe implements the Service interface.
|
||||
func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
claims := oidc.FromContext(r.Context())
|
||||
g.logger.Info().Interface("Claims", claims).Msg("Claims in /me")
|
||||
|
||||
filter := fmt.Sprintf("(uid=%s)", claims.PreferredUsername)
|
||||
user, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter)
|
||||
if err != nil {
|
||||
g.logger.Info().Err(err).Msgf("Failed to read user %s", claims.PreferredUsername)
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
me := createUserModelFromLDAP(user)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, me)
|
||||
}
|
||||
|
||||
// GetUsers implements the Service interface.
|
||||
func (g Graph) GetUsers(w http.ResponseWriter, r *http.Request) {
|
||||
con, err := g.initLdap()
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed to initialize ldap")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := g.ldapSearch(con, "(objectclass=*)", g.config.Ldap.BaseDNUsers)
|
||||
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Msg("Failed search ldap with filter: '(objectclass=*)'")
|
||||
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var users []*msgraph.User
|
||||
|
||||
for _, user := range result.Entries {
|
||||
users = append(
|
||||
users,
|
||||
createUserModelFromLDAP(
|
||||
user,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, &listResponse{Value: users})
|
||||
}
|
||||
|
||||
// GetUser implements the Service interface.
|
||||
func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.Context().Value(userIDKey).(*ldap.Entry)
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, createUserModelFromLDAP(user))
|
||||
}
|
||||
Reference in New Issue
Block a user