diff --git a/services/graph/pkg/service/v0/service.go b/services/graph/pkg/service/v0/service.go index 8ce2d93a24..bfc287b4fc 100644 --- a/services/graph/pkg/service/v0/service.go +++ b/services/graph/pkg/service/v0/service.go @@ -270,6 +270,11 @@ func NewService(opts ...Option) (Graph, error) { }) }) + _ = chi.Walk(m, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + return svc, nil } diff --git a/services/idp/pkg/service/v0/service.go b/services/idp/pkg/service/v0/service.go index 82b8d41277..ca60923eff 100644 --- a/services/idp/pkg/service/v0/service.go +++ b/services/idp/pkg/service/v0/service.go @@ -238,6 +238,11 @@ func (idp *IDP) initMux(ctx context.Context, r []server.WithRoutes, h http.Handl idp.mux.Get("/signin/v1/identifier/index.html", idp.Index()) idp.mux.Mount("/", gm) + + _ = chi.Walk(idp.mux, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) } // ServeHTTP implements the Service interface. diff --git a/services/ocs/pkg/command/server.go b/services/ocs/pkg/command/server.go index 6b6ab26a46..7c3b6c989b 100644 --- a/services/ocs/pkg/command/server.go +++ b/services/ocs/pkg/command/server.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/owncloud/ocis/v2/ocis-pkg/config/configlog" - ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" "github.com/owncloud/ocis/v2/ocis-pkg/version" "github.com/owncloud/ocis/v2/services/ocs/pkg/config/parser" "github.com/owncloud/ocis/v2/services/ocs/pkg/logging" @@ -34,10 +33,6 @@ func Server(cfg *config.Config) *cli.Command { if err != nil { return err } - err = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...) - if err != nil { - return err - } var ( gr = run.Group{} diff --git a/services/ocs/pkg/config/config.go b/services/ocs/pkg/config/config.go index e413040544..1de8f60aa3 100644 --- a/services/ocs/pkg/config/config.go +++ b/services/ocs/pkg/config/config.go @@ -19,21 +19,7 @@ type Config struct { HTTP HTTP `yaml:"http"` - TokenManager *TokenManager `yaml:"token_manager"` - Reva *shared.Reva `yaml:"reva"` - GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"` - - IdentityManagement IdentityManagement `yaml:"identity_management"` - - AccountBackend string `yaml:"-"` // we only support cs3 backend, no need to have this configurable - MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;OCS_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary to access resources from other services."` + TokenManager *TokenManager `yaml:"token_manager"` Context context.Context `yaml:"-"` } - -// IdentityManagement keeps track of the OIDC address. This is because Reva requisite of uniqueness for users -// is based in the combination of IDP hostname + UserID. For more information see: -// https://github.com/cs3org/reva/blob/4fd0229f13fae5bc9684556a82dbbd0eced65ef9/pkg/storage/utils/decomposedfs/node/node.go#L856-L865 -type IdentityManagement struct { - Address string `yaml:"address" env:"OCIS_URL;OCIS_OIDC_ISSUER;OCS_IDM_ADDRESS" desc:"URL of the OIDC issuer. It defaults to URL of the builtin IDP."` -} diff --git a/services/ocs/pkg/config/defaults/defaultconfig.go b/services/ocs/pkg/config/defaults/defaultconfig.go index 30dc68871b..9b04fb99f8 100644 --- a/services/ocs/pkg/config/defaults/defaultconfig.go +++ b/services/ocs/pkg/config/defaults/defaultconfig.go @@ -3,7 +3,6 @@ package defaults import ( "strings" - "github.com/owncloud/ocis/v2/ocis-pkg/shared" "github.com/owncloud/ocis/v2/services/ocs/pkg/config" ) @@ -36,11 +35,6 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "ocs", }, - AccountBackend: "cs3", - Reva: shared.DefaultRevaConfig(), - IdentityManagement: config.IdentityManagement{ - Address: "https://localhost:9200", - }, } } @@ -78,15 +72,6 @@ func EnsureDefaults(cfg *config.Config) { cfg.CacheStore = &config.CacheStore{} } - if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { - cfg.Reva = &shared.Reva{ - Address: cfg.Commons.Reva.Address, - TLS: cfg.Commons.Reva.TLS, - } - } else if cfg.Reva == nil { - cfg.Reva = &shared.Reva{} - } - if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { cfg.TokenManager = &config.TokenManager{ JWTSecret: cfg.Commons.TokenManager.JWTSecret, @@ -95,17 +80,6 @@ func EnsureDefaults(cfg *config.Config) { cfg.TokenManager = &config.TokenManager{} } - if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { - cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey - } - - if cfg.GRPCClientTLS == nil { - cfg.GRPCClientTLS = &shared.GRPCClientTLS{} - if cfg.Commons != nil && cfg.Commons.GRPCClientTLS != nil { - cfg.GRPCClientTLS.Mode = cfg.Commons.GRPCClientTLS.Mode - cfg.GRPCClientTLS.CACert = cfg.Commons.GRPCClientTLS.CACert - } - } if cfg.Commons != nil { cfg.HTTP.TLS = cfg.Commons.HTTPServiceTLS } diff --git a/services/ocs/pkg/config/parser/parse.go b/services/ocs/pkg/config/parser/parse.go index ecb6b0e184..bff72f8e7d 100644 --- a/services/ocs/pkg/config/parser/parse.go +++ b/services/ocs/pkg/config/parser/parse.go @@ -39,9 +39,5 @@ func Validate(cfg *config.Config) error { return shared.MissingJWTTokenError(cfg.Service.Name) } - if cfg.MachineAuthAPIKey == "" { - return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) - } - return nil } diff --git a/services/ocs/pkg/middleware/options.go b/services/ocs/pkg/middleware/options.go deleted file mode 100644 index c3f58e51f3..0000000000 --- a/services/ocs/pkg/middleware/options.go +++ /dev/null @@ -1,42 +0,0 @@ -package middleware - -import ( - "github.com/owncloud/ocis/v2/ocis-pkg/log" - "github.com/owncloud/ocis/v2/ocis-pkg/roles" -) - -// Option defines a single option function. -type Option func(o *Options) - -// Options defines the available options for this package. -type Options struct { - // Logger to use for logging, must be set - Logger log.Logger - // RoleManager for looking up permissions - RoleManager *roles.Manager -} - -// newOptions initializes the available default options. -func newOptions(opts ...Option) Options { - opt := Options{} - - for _, o := range opts { - o(&opt) - } - - return opt -} - -// Logger provides a function to set the logger option. -func Logger(l log.Logger) Option { - return func(o *Options) { - o.Logger = l - } -} - -// RoleManager provides a function to set the RoleManager option. -func RoleManager(val *roles.Manager) Option { - return func(o *Options) { - o.RoleManager = val - } -} diff --git a/services/ocs/pkg/middleware/requireadmin.go b/services/ocs/pkg/middleware/requireadmin.go deleted file mode 100644 index 87f58eebe0..0000000000 --- a/services/ocs/pkg/middleware/requireadmin.go +++ /dev/null @@ -1,42 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/go-chi/render" - "github.com/owncloud/ocis/v2/ocis-pkg/roles" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" - settings "github.com/owncloud/ocis/v2/services/settings/pkg/service/v0" -) - -// RequireAdmin middleware is used to require the user in context to be an admin / have account management permissions -func RequireAdmin(opts ...Option) func(next http.Handler) http.Handler { - opt := newOptions(opts...) - - mustRender := func(w http.ResponseWriter, r *http.Request, renderer render.Renderer) { - if err := render.Render(w, r, renderer); err != nil { - opt.Logger.Err(err).Msgf("failed to write response for ocs request %s on %s", r.Method, r.URL) - } - } - - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - // get roles from context - roleIDs, ok := roles.ReadRoleIDsFromContext(r.Context()) - if !ok { - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - return - } - - // check if permission is present in roles of the authenticated account - if opt.RoleManager.FindPermissionByID(r.Context(), roleIDs, settings.AccountManagementPermissionID) != nil { - next.ServeHTTP(w, r) - return - } - - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - }) - } -} diff --git a/services/ocs/pkg/middleware/requireselforadmin.go b/services/ocs/pkg/middleware/requireselforadmin.go deleted file mode 100644 index f88863db5e..0000000000 --- a/services/ocs/pkg/middleware/requireselforadmin.go +++ /dev/null @@ -1,81 +0,0 @@ -package middleware - -import ( - "net/http" - "net/url" - - revactx "github.com/cs3org/reva/v2/pkg/ctx" - "github.com/go-chi/chi/v5" - "github.com/go-chi/render" - "github.com/owncloud/ocis/v2/ocis-pkg/roles" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" - settings "github.com/owncloud/ocis/v2/services/settings/pkg/service/v0" -) - -// RequireSelfOrAdmin middleware is used to require the requesting user to be an admin or the requested user himself -func RequireSelfOrAdmin(opts ...Option) func(next http.Handler) http.Handler { - opt := newOptions(opts...) - - mustRender := func(w http.ResponseWriter, r *http.Request, renderer render.Renderer) { - if err := render.Render(w, r, renderer); err != nil { - opt.Logger.Err(err).Msgf("failed to write response for ocs request %s on %s", r.Method, r.URL) - } - } - - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - u, ok := revactx.ContextGetUser(r.Context()) - if !ok { - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - return - } - if u.Id == nil || u.Id.OpaqueId == "" { - mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "user is missing an id")) - return - } - // get roles from context - roleIDs, ok := roles.ReadRoleIDsFromContext(r.Context()) - if !ok { - opt.Logger.Debug().Str("userid", u.Id.OpaqueId).Msg("No roles in context, contacting settings service") - var err error - roleIDs, err = opt.RoleManager.FindRoleIDsForUser(r.Context(), u.Id.OpaqueId) - if err != nil { - opt.Logger.Err(err).Str("userid", u.Id.OpaqueId).Msg("failed to get roles for user") - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - return - } - if len(roleIDs) == 0 { - roleIDs = append(roleIDs, settings.BundleUUIDRoleUser, settings.SelfManagementPermissionID) - // if roles are empty, assume we haven't seen the user before and assign a default user role. At least until - // proper roles are provided. See https://github.com/owncloud/ocis/v2/issues/1825 for more context. - //return user, nil - } - } - - // check if account management permission is present in roles of the authenticated account - if opt.RoleManager.FindPermissionByID(r.Context(), roleIDs, settings.AccountManagementPermissionID) != nil { - next.ServeHTTP(w, r) - return - } - - // check if self management permission is present in roles of the authenticated account - if opt.RoleManager.FindPermissionByID(r.Context(), roleIDs, settings.SelfManagementPermissionID) != nil { - userid := chi.URLParam(r, "userid") - var err error - if userid, err = url.PathUnescape(userid); err != nil { - mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "malformed username")) - } - - if userid == "" || userid == u.Id.OpaqueId || userid == u.Username { - next.ServeHTTP(w, r) - return - } - } - - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - - }) - } -} diff --git a/services/ocs/pkg/middleware/requireuser.go b/services/ocs/pkg/middleware/requireuser.go deleted file mode 100644 index 2b17f178b0..0000000000 --- a/services/ocs/pkg/middleware/requireuser.go +++ /dev/null @@ -1,39 +0,0 @@ -package middleware - -import ( - "net/http" - - revactx "github.com/cs3org/reva/v2/pkg/ctx" - "github.com/go-chi/render" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" -) - -// RequireUser middleware is used to require a user in context -func RequireUser(opts ...Option) func(next http.Handler) http.Handler { - opt := newOptions(opts...) - - mustRender := func(w http.ResponseWriter, r *http.Request, renderer render.Renderer) { - if err := render.Render(w, r, renderer); err != nil { - opt.Logger.Err(err).Msgf("failed to write response for ocs request %s on %s", r.Method, r.URL) - } - } - - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - u, ok := revactx.ContextGetUser(r.Context()) - if !ok { - mustRender(w, r, response.ErrRender(data.MetaUnauthorized.StatusCode, "Unauthorized")) - return - } - if u.Id == nil || u.Id.OpaqueId == "" { - mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "user is missing an id")) - return - } - - next.ServeHTTP(w, r) - - }) - } -} diff --git a/services/ocs/pkg/service/v0/config.go b/services/ocs/pkg/service/v0/config.go deleted file mode 100644 index 9ff28bad19..0000000000 --- a/services/ocs/pkg/service/v0/config.go +++ /dev/null @@ -1,19 +0,0 @@ -package svc - -import ( - "net/http" - - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" -) - -// GetConfig renders the ocs config endpoint -func (o Ocs) GetConfig(w http.ResponseWriter, r *http.Request) { - o.mustRender(w, r, response.DataRender(&data.ConfigData{ - Version: "1.7", // TODO get from env - Website: "ocis", // TODO get from env - Host: "", // TODO get from FRONTEND config - Contact: "", // TODO get from env - SSL: "true", // TODO get from env - })) -} diff --git a/services/ocs/pkg/service/v0/data/config.go b/services/ocs/pkg/service/v0/data/config.go deleted file mode 100644 index 0978b73c5f..0000000000 --- a/services/ocs/pkg/service/v0/data/config.go +++ /dev/null @@ -1,10 +0,0 @@ -package data - -// ConfigData holds basic config -type ConfigData struct { - Version string `json:"version" xml:"version"` - Website string `json:"website" xml:"website"` - Host string `json:"host" xml:"host"` - Contact string `json:"contact" xml:"contact"` - SSL string `json:"ssl" xml:"ssl"` -} diff --git a/services/ocs/pkg/service/v0/data/group.go b/services/ocs/pkg/service/v0/data/group.go deleted file mode 100644 index 1eab5d8bd3..0000000000 --- a/services/ocs/pkg/service/v0/data/group.go +++ /dev/null @@ -1,6 +0,0 @@ -package data - -// Groups holds group ids for the groups listing -type Groups struct { - Groups []string `json:"groups" xml:"groups>element"` -} diff --git a/services/ocs/pkg/service/v0/data/user.go b/services/ocs/pkg/service/v0/data/user.go index 8b210afb57..fbb3e0d8d5 100644 --- a/services/ocs/pkg/service/v0/data/user.go +++ b/services/ocs/pkg/service/v0/data/user.go @@ -1,31 +1,5 @@ package data -// Users holds user ids for the user listing -type Users struct { - Users []string `json:"users" xml:"users>element"` -} - -// User holds the payload for a GetUser response -type User struct { - Enabled string `json:"enabled" xml:"enabled"` - UserID string `json:"id" xml:"id"` // UserID is mapped to the preferred_name attribute in accounts - DisplayName string `json:"display-name" xml:"display-name"` - LegacyDisplayName string `json:"displayname" xml:"displayname"` - Email string `json:"email" xml:"email"` - Quota *Quota `json:"quota" xml:"quota"` - UIDNumber int64 `json:"uidnumber" xml:"uidnumber"` - GIDNumber int64 `json:"gidnumber" xml:"gidnumber"` -} - -// Quota holds quota information -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"` -} - // SigningKey holds the Payload for a GetSigningKey response type SigningKey struct { User string `json:"user" xml:"user"` diff --git a/services/ocs/pkg/service/v0/groups.go b/services/ocs/pkg/service/v0/groups.go deleted file mode 100644 index 0f13642261..0000000000 --- a/services/ocs/pkg/service/v0/groups.go +++ /dev/null @@ -1,88 +0,0 @@ -package svc - -import ( - "net/http" - - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" - "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" -) - -const ( - _backendCS3 = "cs3" -) - -// ListUserGroups lists a users groups -func (o Ocs) ListUserGroups(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - // TODO - o.mustRender(w, r, response.DataRender(&data.Groups{})) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// AddToGroup adds a user to a group -func (o Ocs) AddToGroup(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - // TODO - o.cs3WriteNotSupported(w, r) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// RemoveFromGroup removes a user from a group -func (o Ocs) RemoveFromGroup(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - // TODO - o.cs3WriteNotSupported(w, r) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// ListGroups lists all groups -func (o Ocs) ListGroups(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - // TODO - o.mustRender(w, r, response.DataRender(&data.Groups{})) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// AddGroup adds a group -// oC10 implementation: https://github.com/owncloud/core/blob/762780a23c9eadda4fb5fa8db99eba66a5100b6e/apps/provisioning_api/lib/Groups.php#L126-L154 -func (o Ocs) AddGroup(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - o.cs3WriteNotSupported(w, r) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// DeleteGroup deletes a group -func (o Ocs) DeleteGroup(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - o.cs3WriteNotSupported(w, r) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// GetGroupMembers lists all members of a group -func (o Ocs) GetGroupMembers(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case _backendCS3: - // TODO - o.mustRender(w, r, response.DataRender(&data.Users{})) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} diff --git a/services/ocs/pkg/service/v0/instrument.go b/services/ocs/pkg/service/v0/instrument.go index 15c42b348f..8c48325201 100644 --- a/services/ocs/pkg/service/v0/instrument.go +++ b/services/ocs/pkg/service/v0/instrument.go @@ -23,8 +23,3 @@ type instrument struct { func (i instrument) ServeHTTP(w http.ResponseWriter, r *http.Request) { i.next.ServeHTTP(w, r) } - -// GetConfig implements the Service interface. -func (i instrument) GetConfig(w http.ResponseWriter, r *http.Request) { - i.next.GetConfig(w, r) -} diff --git a/services/ocs/pkg/service/v0/logging.go b/services/ocs/pkg/service/v0/logging.go index bb22e46fcc..c4e7c8382e 100644 --- a/services/ocs/pkg/service/v0/logging.go +++ b/services/ocs/pkg/service/v0/logging.go @@ -23,8 +23,3 @@ type logging struct { func (l logging) ServeHTTP(w http.ResponseWriter, r *http.Request) { l.next.ServeHTTP(w, r) } - -// GetConfig implements the Service interface. -func (l logging) GetConfig(w http.ResponseWriter, r *http.Request) { - l.next.GetConfig(w, r) -} diff --git a/services/ocs/pkg/service/v0/option.go b/services/ocs/pkg/service/v0/option.go index bfefbe61f0..40ccc9e1c7 100644 --- a/services/ocs/pkg/service/v0/option.go +++ b/services/ocs/pkg/service/v0/option.go @@ -4,8 +4,6 @@ import ( "net/http" "github.com/owncloud/ocis/v2/ocis-pkg/log" - "github.com/owncloud/ocis/v2/ocis-pkg/roles" - settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" "github.com/owncloud/ocis/v2/services/ocs/pkg/config" ) @@ -14,11 +12,9 @@ type Option func(o *Options) // Options defines the available options for this package. type Options struct { - Logger log.Logger - Config *config.Config - Middleware []func(http.Handler) http.Handler - RoleService settingssvc.RoleService - RoleManager *roles.Manager + Logger log.Logger + Config *config.Config + Middleware []func(http.Handler) http.Handler } // newOptions initializes the available default options. @@ -52,17 +48,3 @@ func Middleware(val ...func(http.Handler) http.Handler) Option { o.Middleware = val } } - -// RoleService provides a function to set the RoleService option. -func RoleService(val settingssvc.RoleService) Option { - return func(o *Options) { - o.RoleService = val - } -} - -// RoleManager provides a function to set the RoleManager option. -func RoleManager(val *roles.Manager) Option { - return func(o *Options) { - o.RoleManager = val - } -} diff --git a/services/ocs/pkg/service/v0/service.go b/services/ocs/pkg/service/v0/service.go index 60b7e2b08b..5e333415a9 100644 --- a/services/ocs/pkg/service/v0/service.go +++ b/services/ocs/pkg/service/v0/service.go @@ -3,10 +3,6 @@ package svc import ( "net/http" - "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" - "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" - "github.com/owncloud/ocis/v2/ocis-pkg/store" - "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/render" @@ -14,19 +10,15 @@ import ( "github.com/owncloud/ocis/v2/ocis-pkg/account" "github.com/owncloud/ocis/v2/ocis-pkg/log" opkgm "github.com/owncloud/ocis/v2/ocis-pkg/middleware" - "github.com/owncloud/ocis/v2/ocis-pkg/roles" - settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" "github.com/owncloud/ocis/v2/services/ocs/pkg/config" ocsm "github.com/owncloud/ocis/v2/services/ocs/pkg/middleware" "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" - "github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend" ) // Service defines the service handlers. type Service interface { ServeHTTP(http.ResponseWriter, *http.Request) - GetConfig(http.ResponseWriter, *http.Request) } // NewService returns a service implementation for Service. @@ -36,40 +28,12 @@ func NewService(opts ...Option) Service { m := chi.NewMux() m.Use(options.Middleware...) - roleService := options.RoleService - if roleService == nil { - roleService = settingssvc.NewRoleService("com.owncloud.api.settings", grpc.DefaultClient()) - } - roleManager := options.RoleManager - if roleManager == nil { - storeOptions := store.OcisStoreOptions{ - Type: options.Config.CacheStore.Type, - Address: options.Config.CacheStore.Address, - Size: options.Config.CacheStore.Size, - } - m := roles.NewManager( - roles.StoreOptions(storeOptions), - roles.Logger(options.Logger), - roles.RoleService(roleService), - ) - roleManager = &m - } - svc := Ocs{ - config: options.Config, - mux: m, - RoleManager: roleManager, - logger: options.Logger, + config: options.Config, + mux: m, + logger: options.Logger, } - if svc.config.AccountBackend == "" { - svc.config.AccountBackend = "cs3" - } - - requireUser := ocsm.RequireUser( - ocsm.Logger(options.Logger), - ) - m.Route(options.Config.HTTP.Root, func(r chi.Router) { r.NotFound(svc.NotFound) r.Use(middleware.StripSlashes) @@ -80,31 +44,23 @@ func NewService(opts ...Option) Service { r.Use(ocsm.OCSFormatCtx) // updates request Accept header according to format=(json|xml) query parameter r.Route("/v{version:(1|2)}.php", func(r chi.Router) { r.Use(response.VersionCtx) // stores version in context - r.Route("/apps/files_sharing/api/v1", func(r chi.Router) {}) - r.Route("/apps/notifications/api/v1", func(r chi.Router) {}) - r.Route("/cloud", func(r chi.Router) { - r.Route("/capabilities", func(r chi.Router) {}) - // TODO /apps - r.Route("/user", func(r chi.Router) { - r.Get("/signing-key", svc.GetSigningKey) - }) - }) - r.Route("/config", func(r chi.Router) { - r.With(requireUser).Get("/", svc.GetConfig) - }) + r.Get("/cloud/user/signing-key", svc.GetSigningKey) }) }) + _ = chi.Walk(m, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + return svc } // Ocs defines implements the business logic for Service. type Ocs struct { - config *config.Config - logger log.Logger - RoleService settingssvc.RoleService - RoleManager *roles.Manager - mux *chi.Mux + config *config.Config + logger log.Logger + mux *chi.Mux } // ServeHTTP implements the Service interface. @@ -117,19 +73,6 @@ func (o Ocs) NotFound(w http.ResponseWriter, r *http.Request) { o.mustRender(w, r, response.ErrRender(data.MetaNotFound.StatusCode, "not found")) } -func (o Ocs) getCS3Backend() backend.UserBackend { - revaClient, err := pool.GetGatewayServiceClient(o.config.Reva.Address, o.config.Reva.GetRevaOptions()...) - if err != nil { - o.logger.Fatal().Msgf("could not get reva client at address %s", o.config.Reva.Address) - } - return backend.NewCS3UserBackend(nil, revaClient, o.config.MachineAuthAPIKey, "", nil, o.logger) -} - -// NotImplementedStub returns a not implemented error -func (o Ocs) NotImplementedStub(w http.ResponseWriter, r *http.Request) { - o.mustRender(w, r, response.ErrRender(data.MetaUnknownError.StatusCode, "Not implemented")) -} - func (o Ocs) mustRender(w http.ResponseWriter, r *http.Request, renderer render.Renderer) { if err := render.Render(w, r, renderer); err != nil { o.logger.Err(err).Msgf("failed to write response for ocs request %s on %s", r.Method, r.URL) diff --git a/services/ocs/pkg/service/v0/tracing.go b/services/ocs/pkg/service/v0/tracing.go index 6c807d772d..4a2c04f51f 100644 --- a/services/ocs/pkg/service/v0/tracing.go +++ b/services/ocs/pkg/service/v0/tracing.go @@ -21,8 +21,3 @@ type tracing struct { func (t tracing) ServeHTTP(w http.ResponseWriter, r *http.Request) { middleware.TraceContext(t.next).ServeHTTP(w, r) } - -// GetConfig implements the Service interface. -func (t tracing) GetConfig(w http.ResponseWriter, r *http.Request) { - t.next.GetConfig(w, r) -} diff --git a/services/ocs/pkg/service/v0/users.go b/services/ocs/pkg/service/v0/users.go index df788d9103..f0bb5c742d 100644 --- a/services/ocs/pkg/service/v0/users.go +++ b/services/ocs/pkg/service/v0/users.go @@ -1,155 +1,20 @@ package svc import ( - "context" "crypto/rand" "encoding/hex" "net/http" - "net/url" storemsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/store/v0" storesvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/store/v0" - cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" revactx "github.com/cs3org/reva/v2/pkg/ctx" - "github.com/go-chi/chi/v5" "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/data" "github.com/owncloud/ocis/v2/services/ocs/pkg/service/v0/response" - ocstracing "github.com/owncloud/ocis/v2/services/ocs/pkg/tracing" merrors "go-micro.dev/v4/errors" ) -// GetSelf returns the currently logged in user -func (o Ocs) GetSelf(w http.ResponseWriter, r *http.Request) { - u, ok := revactx.ContextGetUser(r.Context()) - if !ok || u.Id == nil || u.Id.OpaqueId == "" { - o.mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "user is missing an id")) - return - } - d := &data.User{ - UserID: u.Username, - DisplayName: u.DisplayName, - LegacyDisplayName: u.DisplayName, - Email: u.Mail, - UIDNumber: u.UidNumber, - GIDNumber: u.GidNumber, - } - o.mustRender(w, r, response.DataRender(d)) -} - -// GetUser returns the user with the given userid -func (o Ocs) GetUser(w http.ResponseWriter, r *http.Request) { - userid := chi.URLParam(r, "userid") - userid, err := url.PathUnescape(userid) - if err != nil { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error())) - } - - var user *cs3.User - switch { - case userid == "": - o.mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "missing user in context")) - case o.config.AccountBackend == "cs3": - user, err = o.fetchAccountFromCS3Backend(r.Context(), userid) - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } - - if err != nil { - merr := merrors.FromError(err) - if merr.Code == http.StatusNotFound { - o.mustRender(w, r, response.ErrRender(data.MetaNotFound.StatusCode, data.MessageUserNotFound)) - } else { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, err.Error())) - } - o.logger.Error().Err(merr).Str("userid", userid).Msg("could not get account for user") - return - } - - o.logger.Debug().Interface("user", user).Msg("got user") - - d := &data.User{ - UserID: user.Username, - DisplayName: user.DisplayName, - LegacyDisplayName: user.DisplayName, - Email: user.Mail, - UIDNumber: user.UidNumber, - GIDNumber: user.GidNumber, - Enabled: "true", // TODO include in response only when admin? - // TODO query storage registry for free space? of home storage, maybe... - Quota: &data.Quota{ - Free: 2840756224000, - Used: 5059416668, - Total: 2845815640668, - Relative: 0.18, - Definition: "default", - }, - } - - _, span := ocstracing.TraceProvider. - Tracer("ocs"). - Start(r.Context(), "GetUser") - defer span.End() - - o.mustRender(w, r, response.DataRender(d)) -} - -// AddUser creates a new user account -func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// EditUser creates a new user account -func (o Ocs) EditUser(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// DeleteUser deletes a user -func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// EnableUser enables a user -func (o Ocs) EnableUser(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -// DisableUser disables a user -func (o Ocs) DisableUser(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - // GetSigningKey returns the signing key for the current user. It will create it on the fly if it does not exist // The signing key is part of the user settings and is used by the proxy to authenticate requests // Currently, the username is used as the OC-Credential @@ -222,29 +87,3 @@ func (o Ocs) GetSigningKey(w http.ResponseWriter, r *http.Request) { SigningKey: signingKey, })) } - -// ListUsers lists the users -func (o Ocs) ListUsers(w http.ResponseWriter, r *http.Request) { - switch o.config.AccountBackend { - case "cs3": - // TODO - o.cs3WriteNotSupported(w, r) - return - default: - o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend) - } -} - -func (o Ocs) fetchAccountFromCS3Backend(ctx context.Context, name string) (*cs3.User, error) { - backend := o.getCS3Backend() - u, _, err := backend.GetUserByClaims(ctx, "username", name, false) - if err != nil { - return nil, err - } - return u, nil -} - -func (o Ocs) cs3WriteNotSupported(w http.ResponseWriter, r *http.Request) { - o.logger.Warn().Msg("the CS3 backend does not support adding or updating users") - o.NotImplementedStub(w, r) -} diff --git a/services/settings/pkg/server/http/server.go b/services/settings/pkg/server/http/server.go index fd92344ad1..2a7813036a 100644 --- a/services/settings/pkg/server/http/server.go +++ b/services/settings/pkg/server/http/server.go @@ -2,13 +2,14 @@ package http import ( "fmt" + "net/http" "github.com/go-chi/chi/v5" chimiddleware "github.com/go-chi/chi/v5/middleware" "github.com/owncloud/ocis/v2/ocis-pkg/account" "github.com/owncloud/ocis/v2/ocis-pkg/cors" "github.com/owncloud/ocis/v2/ocis-pkg/middleware" - "github.com/owncloud/ocis/v2/ocis-pkg/service/http" + ohttp "github.com/owncloud/ocis/v2/ocis-pkg/service/http" "github.com/owncloud/ocis/v2/ocis-pkg/version" settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" "github.com/owncloud/ocis/v2/services/settings/pkg/assets" @@ -17,24 +18,24 @@ import ( ) // Server initializes the http service and server. -func Server(opts ...Option) (http.Service, error) { +func Server(opts ...Option) (ohttp.Service, error) { options := newOptions(opts...) - service, err := http.NewService( - http.TLSConfig(options.Config.HTTP.TLS), - http.Logger(options.Logger), - http.Name(options.Name), - http.Version(version.GetString()), - http.Address(options.Config.HTTP.Addr), - http.Namespace(options.Config.HTTP.Namespace), - http.Context(options.Context), - http.Flags(options.Flags...), + service, err := ohttp.NewService( + ohttp.TLSConfig(options.Config.HTTP.TLS), + ohttp.Logger(options.Logger), + ohttp.Name(options.Name), + ohttp.Version(version.GetString()), + ohttp.Address(options.Config.HTTP.Addr), + ohttp.Namespace(options.Config.HTTP.Namespace), + ohttp.Context(options.Context), + ohttp.Flags(options.Flags...), ) if err != nil { options.Logger.Error(). Err(err). Msg("Error initializing http service") - return http.Service{}, fmt.Errorf("could not initialize http service: %w", err) + return ohttp.Service{}, fmt.Errorf("could not initialize http service: %w", err) } handle := svc.NewService(options.Config, options.Logger) @@ -88,6 +89,11 @@ func Server(opts ...Option) (http.Service, error) { settingssvc.RegisterPermissionServiceWeb(r, handle) }) + _ = chi.Walk(mux, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + micro.RegisterHandler(service.Server(), mux) return service, nil diff --git a/services/thumbnails/pkg/service/http/v0/service.go b/services/thumbnails/pkg/service/http/v0/service.go index 428986a3a1..1fe63be6e8 100644 --- a/services/thumbnails/pkg/service/http/v0/service.go +++ b/services/thumbnails/pkg/service/http/v0/service.go @@ -55,6 +55,11 @@ func NewService(opts ...Option) Service { r.Get("/data", svc.GetThumbnail) }) + _ = chi.Walk(m, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + return svc } diff --git a/services/web/pkg/service/v0/service.go b/services/web/pkg/service/v0/service.go index a00e28bcdd..aeb1c3083d 100644 --- a/services/web/pkg/service/v0/service.go +++ b/services/web/pkg/service/v0/service.go @@ -45,6 +45,11 @@ func NewService(opts ...Option) Service { r.Mount("/", svc.Static(options.Config.HTTP.CacheTTL)) }) + _ = chi.Walk(m, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + return svc } diff --git a/services/webdav/pkg/service/v0/service.go b/services/webdav/pkg/service/v0/service.go index 2557b619c7..963abbd663 100644 --- a/services/webdav/pkg/service/v0/service.go +++ b/services/webdav/pkg/service/v0/service.go @@ -134,6 +134,11 @@ func NewService(opts ...Option) (Service, error) { })) }) + _ = chi.Walk(m, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + options.Logger.Debug().Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint") + return nil + }) + return svc, nil }