only allow admins to set global notifications

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2023-06-30 11:48:57 +02:00
parent bca4d4f9fd
commit 6ab2f10386
6 changed files with 73 additions and 3 deletions

View File

@@ -104,6 +104,7 @@ func Server(cfg *config.Config) *cli.Command {
hClient := ehsvc.NewEventHistoryService("com.owncloud.api.eventhistory", ogrpc.DefaultClient())
vClient := settingssvc.NewValueService("com.owncloud.api.settings", ogrpc.DefaultClient())
rClient := settingssvc.NewRoleService("com.owncloud.api.settings", ogrpc.DefaultClient())
{
server, err := http.Server(
@@ -116,6 +117,7 @@ func Server(cfg *config.Config) *cli.Command {
http.GatewaySelector(gatewaySelector),
http.History(hClient),
http.Value(vClient),
http.Role(rClient),
http.RegisteredEvents(_registeredEvents),
)

View File

@@ -31,6 +31,7 @@ type Options struct {
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
HistoryClient ehsvc.EventHistoryService
ValueClient settingssvc.ValueService
RoleClient settingssvc.RoleService
RegisteredEvents []events.Unmarshaller
}
@@ -128,3 +129,10 @@ func Value(vs settingssvc.ValueService) Option {
o.ValueClient = vs
}
}
// Roles provides a function to configure the roles service client
func Role(rs settingssvc.RoleService) Option {
return func(o *Options) {
o.RoleClient = rs
}
}

View File

@@ -77,6 +77,7 @@ func Server(opts ...Option) (http.Service, error) {
svc.HistoryClient(options.HistoryClient),
svc.GatewaySelector(options.GatewaySelector),
svc.ValueClient(options.ValueClient),
svc.RoleClient(options.RoleClient),
svc.RegisteredEvents(options.RegisteredEvents),
)
if err != nil {

View File

@@ -6,6 +6,10 @@ import (
"github.com/cs3org/reva/v2/pkg/ctx"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
settings "github.com/owncloud/ocis/v2/services/settings/pkg/service/v0"
)
// HeaderAcceptLanguage is the header where the client can set the locale
@@ -122,8 +126,6 @@ func (ul *UserlogService) HandlePostEvent(w http.ResponseWriter, r *http.Request
return
}
// TODO: Check user is allowed to do this
var req PostEventsRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
ul.log.Error().Err(err).Int("returned statuscode", http.StatusBadRequest).Msg("request body is malformed")
@@ -192,3 +194,44 @@ type PostEventsRequest struct {
type DeprovisionData struct {
DeprovisionDate string `json:"date"`
}
// RequireAdmin middleware is used to require the user in context to be an admin / have account management permissions
func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.HandlerFunc) http.HandlerFunc {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
u, ok := revactx.ContextGetUser(r.Context())
if !ok {
errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized")
return
}
if u.Id == nil || u.Id.OpaqueId == "" {
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "user is missing an id")
return
}
// get roles from context
roleIDs, ok := roles.ReadRoleIDsFromContext(r.Context())
if !ok {
logger.Debug().Str("userid", u.Id.OpaqueId).Msg("No roles in context, contacting settings service")
var err error
roleIDs, err = rm.FindRoleIDsForUser(r.Context(), u.Id.OpaqueId)
if err != nil {
logger.Err(err).Str("userid", u.Id.OpaqueId).Msg("failed to get roles for user")
errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized")
return
}
if len(roleIDs) == 0 {
errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized")
return
}
}
// check if permission is present in roles of the authenticated account
if rm.FindPermissionByID(r.Context(), roleIDs, settings.AccountManagementPermissionID) != nil {
next.ServeHTTP(w, r)
return
}
errorcode.AccessDenied.Render(w, r, http.StatusForbidden, "Forbidden")
}
}
}

View File

@@ -25,6 +25,7 @@ type Options struct {
HistoryClient ehsvc.EventHistoryService
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
ValueClient settingssvc.ValueService
RoleClient settingssvc.RoleService
RegisteredEvents []events.Unmarshaller
}
@@ -84,8 +85,16 @@ func RegisteredEvents(e []events.Unmarshaller) Option {
}
}
// ValueClient adds a grpc client for the value service
func ValueClient(vs settingssvc.ValueService) Option {
return func(o *Options) {
o.ValueClient = vs
}
}
// RoleClient adds a grpc client for the role service
func RoleClient(rs settingssvc.RoleService) Option {
return func(o *Options) {
o.RoleClient = rs
}
}

View File

@@ -19,6 +19,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -80,9 +81,15 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) {
ul.registeredEvents[typ.String()] = e
}
m := roles.NewManager(
// TODO: caching?
roles.Logger(o.Logger),
roles.RoleService(o.RoleClient),
)
ul.m.Route("/ocs/v2.php/apps/notifications/api/v1/notifications", func(r chi.Router) {
r.Get("/", ul.HandleGetEvents)
r.Post("/", ul.HandlePostEvent)
r.Post("/", RequireAdmin(&m, ul.log)(ul.HandlePostEvent))
r.Delete("/", ul.HandleDeleteEvents)
if !ul.cfg.DisableSSE {