mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-03 19:00:05 -06:00
Add service endpoints.
This commit is contained in:
committed by
Ralf Haferkamp
parent
9b8adb65ed
commit
20f6a212f3
@@ -60,6 +60,13 @@ type EducationBackend interface {
|
||||
// RemoveUserFromEducationSchool removes a single member (by ID) from a school
|
||||
RemoveUserFromEducationSchool(ctx context.Context, schoolID string, memberID string) error
|
||||
|
||||
// GetEducationSchoolClasses lists all classes in a chool
|
||||
GetEducationSchoolClasses(ctx context.Context, schoolNumberOrID string) ([]*libregraph.EducationClass, error)
|
||||
// AddClassesToEducationSchool adds new classes (referenced by a slice of IDs) to supplied school in the identity backend.
|
||||
AddClassesToEducationSchool(ctx context.Context, schoolNumberOrID string, memberIDs []string) error
|
||||
// RemoveClassFromEducationSchool removes a class from a school.
|
||||
RemoveClassFromEducationSchool(ctx context.Context, schoolNumberOrID string, memberID string) error
|
||||
|
||||
// GetEducationClasses lists all classes
|
||||
GetEducationClasses(ctx context.Context, queryParam url.Values) ([]*libregraph.EducationClass, error)
|
||||
// GetEducationClasses reads a given class by id
|
||||
|
||||
@@ -40,6 +40,21 @@ func (i *ErrEducationBackend) GetEducationSchoolUsers(ctx context.Context, id st
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
// GetEducationSchoolClasses implements the EducationBackend interface for the ErrEducationBackend backend.
|
||||
func (i *ErrEducationBackend) GetEducationSchoolClasses(ctx context.Context, schoolNumberOrID string) ([]*libregraph.EducationClass, error) {
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
// AddClassesToEducationSchool implements the EducationBackend interface for the ErrEducationBackend backend.
|
||||
func (i *ErrEducationBackend) AddClassesToEducationSchool(ctx context.Context, schoolNumberOrID string, memberIDs []string) error {
|
||||
return errNotImplemented
|
||||
}
|
||||
|
||||
// RemoveClassFromEducationSchool implements the EducationBackend interface for the ErrEducationBackend backend.
|
||||
func (i *ErrEducationBackend) RemoveClassFromEducationSchool(ctx context.Context, schoolNumberOrID string, memberID string) error {
|
||||
return errNotImplemented
|
||||
}
|
||||
|
||||
// AddUsersToEducationSchool adds new members (reference by a slice of IDs) to supplied school in the identity backend.
|
||||
func (i *ErrEducationBackend) AddUsersToEducationSchool(ctx context.Context, schoolID string, memberID []string) error {
|
||||
return errNotImplemented
|
||||
|
||||
@@ -344,8 +344,8 @@ func (i *LDAP) getEducationClassLDAPDN(class libregraph.EducationClass) string {
|
||||
func (i *LDAP) getEducationClassByID(nameOrID string, requestMembers bool) (*ldap.Entry, error) {
|
||||
return i.getEducationObjectByNameOrID(
|
||||
nameOrID,
|
||||
i.groupAttributeMap.name,
|
||||
i.groupAttributeMap.id,
|
||||
i.userAttributeMap.id,
|
||||
i.educationConfig.classAttributeMap.externalID,
|
||||
i.groupFilter,
|
||||
i.educationConfig.classObjectClass,
|
||||
i.groupBaseDN,
|
||||
|
||||
@@ -354,7 +354,7 @@ func (i *LDAP) GetEducationSchoolUsers(ctx context.Context, schoolNumberOrID str
|
||||
logger.Debug().Str("backend", "ldap").Msg("GetEducationSchoolUsers")
|
||||
|
||||
entries, err := i.getEducationSchoolEntries(
|
||||
schoolNumberOrID, i.userFilter, i.educationConfig.userObjectClass, i.userBaseDN, i.userScope, i.getUserAttrTypes(), logger,
|
||||
schoolNumberOrID, i.userFilter, i.educationConfig.userObjectClass, i.userBaseDN, i.userScope, i.getEducationUserAttrTypes(), logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -17,6 +17,20 @@ type EducationBackend struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// AddClassesToEducationSchool provides a mock function with given fields: ctx, schoolNumberOrID, memberIDs
|
||||
func (_m *EducationBackend) AddClassesToEducationSchool(ctx context.Context, schoolNumberOrID string, memberIDs []string) error {
|
||||
ret := _m.Called(ctx, schoolNumberOrID, memberIDs)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok {
|
||||
r0 = rf(ctx, schoolNumberOrID, memberIDs)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// AddUsersToEducationSchool provides a mock function with given fields: ctx, schoolID, memberID
|
||||
func (_m *EducationBackend) AddUsersToEducationSchool(ctx context.Context, schoolID string, memberID []string) error {
|
||||
ret := _m.Called(ctx, schoolID, memberID)
|
||||
@@ -234,6 +248,29 @@ func (_m *EducationBackend) GetEducationSchool(ctx context.Context, nameOrID str
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetEducationSchoolClasses provides a mock function with given fields: ctx, schoolNumberOrID
|
||||
func (_m *EducationBackend) GetEducationSchoolClasses(ctx context.Context, schoolNumberOrID string) ([]*libregraph.EducationClass, error) {
|
||||
ret := _m.Called(ctx, schoolNumberOrID)
|
||||
|
||||
var r0 []*libregraph.EducationClass
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []*libregraph.EducationClass); ok {
|
||||
r0 = rf(ctx, schoolNumberOrID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*libregraph.EducationClass)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, schoolNumberOrID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetEducationSchoolUsers provides a mock function with given fields: ctx, id
|
||||
func (_m *EducationBackend) GetEducationSchoolUsers(ctx context.Context, id string) ([]*libregraph.EducationUser, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
@@ -326,6 +363,20 @@ func (_m *EducationBackend) GetEducationUsers(ctx context.Context, queryParam ur
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveClassFromEducationSchool provides a mock function with given fields: ctx, schoolNumberOrID, memberID
|
||||
func (_m *EducationBackend) RemoveClassFromEducationSchool(ctx context.Context, schoolNumberOrID string, memberID string) error {
|
||||
ret := _m.Called(ctx, schoolNumberOrID, memberID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, schoolNumberOrID, memberID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveUserFromEducationSchool provides a mock function with given fields: ctx, schoolID, memberID
|
||||
func (_m *EducationBackend) RemoveUserFromEducationSchool(ctx context.Context, schoolID string, memberID string) error {
|
||||
ret := _m.Called(ctx, schoolID, memberID)
|
||||
|
||||
@@ -423,6 +423,176 @@ func (g Graph) DeleteEducationSchoolUser(w http.ResponseWriter, r *http.Request)
|
||||
render.NoContent(w, r)
|
||||
}
|
||||
|
||||
// GetEducationSchoolUsers implements the Service interface.
|
||||
func (g Graph) GetEducationSchoolClasses(w http.ResponseWriter, r *http.Request) {
|
||||
logger := g.logger.SubloggerWithRequestID(r.Context())
|
||||
logger.Info().Msg("calling get school classes")
|
||||
schoolID := chi.URLParam(r, "schoolID")
|
||||
schoolID, err := url.PathUnescape(schoolID)
|
||||
if err != nil {
|
||||
logger.Debug().Str("id", schoolID).Msg("could not get school users: unescaping school id failed")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping school id failed")
|
||||
return
|
||||
}
|
||||
|
||||
if schoolID == "" {
|
||||
logger.Debug().Msg("could not get school users: missing school id")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing school id")
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debug().Str("id", schoolID).Msg("calling get school classes on backend")
|
||||
classes, err := g.identityEducationBackend.GetEducationSchoolClasses(r.Context(), schoolID)
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Msg("could not get school classes: backend error")
|
||||
var errcode errorcode.Error
|
||||
if errors.As(err, &errcode) {
|
||||
errcode.Render(w, r)
|
||||
} else {
|
||||
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, classes)
|
||||
}
|
||||
|
||||
// PostEducationSchoolUser implements the Service interface.
|
||||
func (g Graph) PostEducationSchoolClass(w http.ResponseWriter, r *http.Request) {
|
||||
logger := g.logger.SubloggerWithRequestID(r.Context())
|
||||
logger.Info().Msg("Calling post school class")
|
||||
|
||||
schoolID := chi.URLParam(r, "schoolID")
|
||||
schoolID, err := url.PathUnescape(schoolID)
|
||||
if err != nil {
|
||||
logger.Debug().
|
||||
Err(err).
|
||||
Str("id", schoolID).
|
||||
Msg("could not add class to school: unescaping school id failed")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping school id failed")
|
||||
return
|
||||
}
|
||||
|
||||
if schoolID == "" {
|
||||
logger.Debug().Msg("could not add school class: missing school id")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing school id")
|
||||
return
|
||||
}
|
||||
memberRef := libregraph.NewMemberReference()
|
||||
err = json.NewDecoder(r.Body).Decode(memberRef)
|
||||
if err != nil {
|
||||
logger.Debug().
|
||||
Err(err).
|
||||
Interface("body", r.Body).
|
||||
Msg("could not add school class: invalid request body")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
memberRefURL, ok := memberRef.GetOdataIdOk()
|
||||
if !ok {
|
||||
logger.Debug().Msg("could not add school class: @odata.id reference is missing")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "@odata.id reference is missing")
|
||||
return
|
||||
}
|
||||
memberType, id, err := g.parseMemberRef(*memberRefURL)
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Msg("could not add school class: error parsing @odata.id url")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "Error parsing @odata.id url")
|
||||
return
|
||||
}
|
||||
// The MS Graph spec allows "directoryObject", "user", "school" and "organizational Contact"
|
||||
// we restrict this to users for now. Might add Schools as members later
|
||||
if memberType != "classes" {
|
||||
logger.Debug().Str("type", memberType).Msg("could not add school class: Only classes are allowed as school members")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "Only classes are allowed as school members")
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debug().Str("memberType", memberType).Str("id", id).Msg("calling add class on backend")
|
||||
err = g.identityEducationBackend.AddClassesToEducationSchool(r.Context(), schoolID, []string{id})
|
||||
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Msg("could not add school class: backend error")
|
||||
var errcode errorcode.Error
|
||||
if errors.As(err, &errcode) {
|
||||
errcode.Render(w, r)
|
||||
} else {
|
||||
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/* TODO requires reva changes
|
||||
e := events.SchoolMemberAdded{SchoolID: schoolID, UserID: id}
|
||||
if currentUser, ok := ctxpkg.ContextGetUser(r.Context()); ok {
|
||||
e.Executant = currentUser.GetId()
|
||||
}
|
||||
g.publishEvent(e)
|
||||
*/
|
||||
|
||||
render.Status(r, http.StatusNoContent)
|
||||
render.NoContent(w, r)
|
||||
}
|
||||
|
||||
// DeleteEducationSchoolUser implements the Service interface.
|
||||
func (g Graph) DeleteEducationSchoolClass(w http.ResponseWriter, r *http.Request) {
|
||||
logger := g.logger.SubloggerWithRequestID(r.Context())
|
||||
logger.Info().Msg("calling delete school class")
|
||||
|
||||
schoolID := chi.URLParam(r, "schoolID")
|
||||
schoolID, err := url.PathUnescape(schoolID)
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Str("id", schoolID).Msg("could not delete school class: unescaping school id failed")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping school id failed")
|
||||
return
|
||||
}
|
||||
|
||||
if schoolID == "" {
|
||||
logger.Debug().Msg("could not delete school class: missing school id")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing school id")
|
||||
return
|
||||
}
|
||||
|
||||
classID := chi.URLParam(r, "classID")
|
||||
classID, err = url.PathUnescape(classID)
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Str("id", classID).Msg("could not delete school class: unescaping class id failed")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping class id failed")
|
||||
return
|
||||
}
|
||||
|
||||
if classID == "" {
|
||||
logger.Debug().Msg("could not delete school class: missing class id")
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing class id")
|
||||
return
|
||||
}
|
||||
logger.Debug().Str("schoolID", schoolID).Str("userID", classID).Msg("calling delete class on backend")
|
||||
err = g.identityEducationBackend.RemoveClassFromEducationSchool(r.Context(), schoolID, classID)
|
||||
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Msg("could not delete school class: backend error")
|
||||
var errcode errorcode.Error
|
||||
if errors.As(err, &errcode) {
|
||||
errcode.Render(w, r)
|
||||
} else {
|
||||
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/* TODO requires reva changes
|
||||
e := events.SchoolMemberRemoved{SchoolID: schoolID, UserID: userID}
|
||||
if currentUser, ok := ctxpkg.ContextGetUser(r.Context()); ok {
|
||||
e.Executant = currentUser.GetId()
|
||||
}
|
||||
g.publishEvent(e)
|
||||
*/
|
||||
|
||||
render.Status(r, http.StatusNoContent)
|
||||
render.NoContent(w, r)
|
||||
}
|
||||
|
||||
func sortEducationSchools(req *godata.GoDataRequest, schools []*libregraph.EducationSchool) ([]*libregraph.EducationSchool, error) {
|
||||
if req.Query.OrderBy == nil || len(req.Query.OrderBy.OrderByItems) != 1 {
|
||||
return schools, nil
|
||||
|
||||
@@ -241,6 +241,11 @@ func NewService(opts ...Option) (Graph, error) {
|
||||
r.Post("/$ref", svc.PostEducationSchoolUser)
|
||||
r.Delete("/{userID}/$ref", svc.DeleteEducationSchoolUser)
|
||||
})
|
||||
r.Route("/classes", func(r chi.Router) {
|
||||
r.Get("/", svc.GetEducationSchoolClasses)
|
||||
r.Post("/$ref", svc.PostEducationSchoolClass)
|
||||
r.Delete("/{classID}/$ref", svc.DeleteEducationSchoolClass)
|
||||
})
|
||||
})
|
||||
})
|
||||
r.Route("/users", func(r chi.Router) {
|
||||
|
||||
Reference in New Issue
Block a user