def __acl__(self): """Return ACL for bulk end-points.""" if authority := client_authority(self.request): # Currently only LMS uses this end-point if authority.startswith("lms.") and authority.endswith( ".hypothes.is"): return [(Allow, f"client_authority:{authority}", "bulk_action") ]
def create(request): """Create a group from the POST payload.""" appstruct = CreateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority).validate(_json_payload(request)) group_service = request.find_service(name='group') group_create_service = request.find_service(name='group_create') # Check for duplicate group groupid = appstruct.get('groupid', None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group: raise ConflictError( _("group with groupid '{}' already exists").format(groupid)) group = group_create_service.create_private_group( name=appstruct['name'], userid=request.user.userid, description=appstruct.get('description', None), groupid=groupid, ) return GroupJSONPresenter(GroupContext( group, request)).asdict(expand=['organization'])
def create(request): """Create a group from the POST payload.""" appstruct = CreateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority, ).validate(_json_payload(request)) group_service = request.find_service(name="group") group_create_service = request.find_service(name="group_create") # Check for duplicate group groupid = appstruct.get("groupid", None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group: raise HTTPConflict( _("group with groupid '{}' already exists").format(groupid)) group = group_create_service.create_private_group( name=appstruct["name"], userid=request.user.userid, description=appstruct.get("description", None), groupid=groupid, ) return GroupJSONPresenter( group, request).asdict(expand=["organization", "scopes"])
def create(request): """Create a group from the POST payload.""" appstruct = CreateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority, ).validate(_json_payload(request)) group_service = request.find_service(name="group") group_create_service = request.find_service(name="group_create") # Check for duplicate group groupid = appstruct.get("groupid", None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group: raise HTTPConflict( _("group with groupid '{}' already exists").format(groupid) ) group = group_create_service.create_private_group( name=appstruct["name"], userid=request.user.userid, description=appstruct.get("description", None), groupid=groupid, ) return GroupJSONPresenter(GroupContext(group, request)).asdict( expand=["organization", "scopes"] )
def __getitem__(self, username): authority = client_authority(self.request) or self.request.default_authority user = self.user_svc.fetch(username, authority) if not user: raise KeyError() return user
def upsert(context, request): """ Create or update a group from a PUT payload. If no group model is present in the passed ``context`` (on ``context.group``), treat this as a create action and delegate to ``create``. Otherwise, replace the existing group's resource properties entirely and update the object. :arg context: :type context: h.traversal.GroupUpsertContext """ if context.group is None: return create(request) group = context.group # Because this is a PUT endpoint and not a PATCH, a full replacement of the # entire resource is expected. Thus, we're validating against the Create schema # here as we want to make sure properties required for a fresh object are present appstruct = CreateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority, ).validate(_json_payload(request)) group_update_service = request.find_service(name="group_update") group_service = request.find_service(name="group") # Check for duplicate group groupid = appstruct.get("groupid", None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group and (duplicate_group != group): raise HTTPConflict( _("group with groupid '{}' already exists").format(groupid) ) # Need to make sure every resource-defined property is present, as this # is meant as a full-resource-replace operation. # TODO: This may be better handled in the schema at some point update_properties = { "name": appstruct["name"], "description": appstruct.get("description", ""), "groupid": appstruct.get("groupid", None), } group = group_update_service.update(group, **update_properties) # Note that this view takes a ``GroupUpsertContext`` but uses a ``GroupContext`` here return GroupJSONPresenter(GroupContext(group, request)).asdict( expand=["organization", "scopes"] )
def create(request): """ Create a user. This API endpoint allows authorised clients (those able to provide a valid Client ID and Client Secret) to create users in their authority. These users are created pre-activated, and are unable to log in to the web service directly. Note: the authority-enforcement logic herein is, by necessity, strange. The API accepts an ``authority`` parameter but the only valid value for the param is the client's verified authority. If the param does not match the client's authority, ``ValidationError`` is raised. :raises ValidationError: if ``authority`` param does not match client authority :raises HTTPConflict: if user already exists """ client_authority_ = client_authority(request) schema = CreateUserAPISchema() appstruct = schema.validate(_json_payload(request)) # Enforce authority match if appstruct["authority"] != client_authority_: raise ValidationError( "authority '{auth_param}' does not match client authority".format( auth_param=appstruct["authority"] ) ) user_unique_service = request.find_service(name="user_unique") try: user_unique_service.ensure_unique(appstruct, authority=client_authority_) except DuplicateUserError as err: raise HTTPConflict(str(err)) user_signup_service = request.find_service(name="user_signup") user = user_signup_service.signup(require_activation=False, **appstruct) presenter = UserJSONPresenter(user) return presenter.asdict()
def bulk(request): """ Perform a bulk request which can modify multiple records in on go. This end-point can: * Upsert users * Upsert groups * Add users to groups This end-point is intended to be called using the classes provided by `h_api.bulk_api`. """ results = BulkAPI.from_byte_stream( request.body_file, executor=BulkExecutor(db=request.db, authority=client_authority(request)), ) if results is None: return Response(status=204) # When we get an iterator we must force the first return value to be # created to be sure input validation has occurred. Otherwise we might # raise errors outside of the view when called try: results = chain( # pylint: disable=redefined-variable-type [next(results)], results) except StopIteration: results = [] # An NDJSON response is required return Response( app_iter=((json.dumps(result) + "\n").encode("utf-8") for result in results), status=200, content_type="application/x-ndjson", )
def update(group, request): """Update a group from a PATCH payload.""" appstruct = UpdateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority, ).validate(_json_payload(request)) group_update_service = request.find_service(name="group_update") group_service = request.find_service(name="group") # Check for duplicate group groupid = appstruct.get("groupid", None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group and (duplicate_group != group): raise HTTPConflict( _("group with groupid '{}' already exists").format(groupid)) group = group_update_service.update(group, **appstruct) return GroupJSONPresenter(GroupContext( group, request)).asdict(expand=["organization", "scopes"])
def update(group, request): """Update a group from a PATCH payload.""" appstruct = UpdateGroupAPISchema( default_authority=request.default_authority, group_authority=client_authority(request) or request.default_authority, ).validate(_json_payload(request)) group_update_service = request.find_service(name="group_update") group_service = request.find_service(name="group") # Check for duplicate group groupid = appstruct.get("groupid", None) if groupid is not None: duplicate_group = group_service.fetch(pubid_or_groupid=groupid) if duplicate_group and (duplicate_group != group): raise HTTPConflict( _("group with groupid '{}' already exists").format(groupid) ) group = group_update_service.update(group, **appstruct) return GroupJSONPresenter(GroupContext(group, request)).asdict( expand=["organization", "scopes"] )
def test_it_returns_authority_if_authority_principal_matchpyramid_requesi( self, principals, authority, pyramid_request, pyramid_config ): pyramid_config.testing_securitypolicy("LYZADOODLE", groupids=principals) assert util.client_authority(pyramid_request) == authority