def create_version(cls, community_id, community_schema, root_schema_version=None): """Create a new schema draft for the given community. Args: community_id (UUID): ID of the community whose schema is create. community_schema (dict): loaded JSON Schema validating the community specific metadata. root_schema_version (int): version of the root schema used by this community schema. If set to None, the root_schema of the last version is used, if there is no previous version (new community), the last root_schema is used. Returns: :class:`b2share.modules.schemas.api.CommunitySchema`: the new Community schema. """ from .models import CommunitySchemaVersion from b2share.modules.schemas.helpers import validate_json_schema previous_community_schemas = _fetch_all_query_pages( CommunitySchemaVersion.query.filter( CommunitySchemaVersion.community == community_id).order_by( CommunitySchemaVersion.version.asc())) prev_schemas = map(lambda x: x.community_schema, previous_community_schemas) validate_json_schema(community_schema, prev_schemas) with db.session.begin_nested(): if len(previous_community_schemas) > 0: last_schema = previous_community_schemas[-1] new_version = last_schema.version + 1 if root_schema_version is None: root_schema_version = last_schema.root_schema else: if root_schema_version is None: # there is no schema yet, the community is new. # Use the last RootSchema. from .models import RootSchemaVersion try: root_schema_version = RootSchemaVersion.query.order_by( RootSchemaVersion.version).limit(1).one().version except NoResultFound as e: raise RootSchemaDoesNotExistError from e new_version = 0 model = CommunitySchemaVersion( community=community_id, root_schema=root_schema_version, community_schema=json.dumps( community_schema, # avoid default whitespaces separators=(',', ':')), version=new_version) db.session.add(model) return cls(model)
def create_version(cls, community_id, community_schema, root_schema_version=None): """Create a new schema draft for the given community. Args: community_id (UUID): ID of the community whose schema is create. community_schema (dict): loaded JSON Schema validating the community specific metadata. root_schema_version (int): version of the root schema used by this community schema. If set to None, the root_schema of the last version is used, if there is no previous version (new community), the last root_schema is used. Returns: :class:`b2share.modules.schemas.api.CommunitySchema`: the new Community schema. """ from .models import CommunitySchemaVersion previous_community_schemas = _fetch_all_query_pages( CommunitySchemaVersion.query.filter( CommunitySchemaVersion.community == community_id ).order_by(CommunitySchemaVersion.version.asc()) ) prev_schemas = map(lambda x: x.community_schema, previous_community_schemas) validate_json_schema(community_schema, prev_schemas) with db.session.begin_nested(): if len(previous_community_schemas) > 0: last_schema = previous_community_schemas[-1] new_version = last_schema.version + 1 if root_schema_version is None: root_schema_version = last_schema.root_schema else: if root_schema_version is None: # there is no schema yet, the community is new. # Use the last RootSchema. from .models import RootSchemaVersion try: root_schema_version = RootSchemaVersion.query.order_by( RootSchemaVersion.version).limit(1).one().version except NoResultFound as e: raise RootSchemaDoesNotExistError from e new_version = 0 model = CommunitySchemaVersion( community=community_id, root_schema=root_schema_version, community_schema=json.dumps(community_schema, # avoid default whitespaces separators=(',', ':')), version=new_version) db.session.add(model) return cls(model)
def create_version(self, json_schema, version_number=None): """Create a new version of this schema and release it. Args: json_schema (dict): the json_schema to use for this new version. Returns: :class:`b2share.modules.schemas.models.BlockSchemaVersion`: The new block schema version. Raises: :class:`b2share.modules.schemas.errors.InvalidJSONSchemaError`: The given JSON Schema is not valid. """ from .models import BlockSchemaVersion as BlockSchemaVersionModel if self.deprecated: raise BlockSchemaIsDeprecated() if not isinstance(json_schema, dict): raise InvalidJSONSchemaError('json_schema must be a dict') previous_block_schema_versions = _fetch_all_query_pages( BlockSchemaVersionModel.query.filter( BlockSchemaVersionModel.block_schema == self.model.id, # BlockSchemaVersionModel.version < version_number ).order_by(BlockSchemaVersionModel.version.asc()) ) prev_schemas = map(lambda x: x.json_schema, previous_block_schema_versions) validate_json_schema(json_schema, prev_schemas) # FIXME: validate the json-schema with db.session.begin_nested(): last_version = db.session.query( sqlalchemy.func.max(BlockSchemaVersionModel.version) .label('last_version') ).filter( BlockSchemaVersionModel.block_schema == self.model.id ).one().last_version new_version = (last_version + 1 if last_version is not None else 0) if version_number and new_version < version_number: raise InvalidSchemaVersionError(last_version) elif version_number and new_version > version_number: raise SchemaVersionExistsError(last_version) model = BlockSchemaVersionModel( block_schema=self.model.id, # we specify the separators in order to avoir whitespaces json_schema=json.dumps(json_schema, separators=(',', ':')), version=new_version) db.session.add(model) return BlockSchemaVersion(model, self)
def create_new_version(cls, version, json_schema, options={}): """Load a new root schema version. Args: version (int): version number of this schema. Versions are known in advance and are the same for all B2Share instances. This is more of a security check as the version MUST follow the last loaded one. json_schema (dict): the JSON Schema corresponding to this version. Raises: :class:`b2share.modules.schemas.errors.InvalidRootSchemaError`: If the root schema version is invalid. :class:`b2share.modules.schemas.errors.InvalidJSONSchemaError`: The given JSON Schema is not valid. """ from .models import RootSchemaVersion if not isinstance(json_schema, dict): raise InvalidJSONSchemaError('json_schema must be a dict') previous_root_schemas = _fetch_all_query_pages( RootSchemaVersion.query.filter( RootSchemaVersion.version < version).order_by( RootSchemaVersion.version.asc())) prev_schemas = map(lambda x: x.json_schema, previous_root_schemas) if 'definitions' in json_schema: json_schema = Schema._resolveLocalReferences( json_schema, json_schema['definitions']) del json_schema['definitions'] validate_json_schema(json_schema, prev_schemas, options) with db.session.begin_nested(): # Force the given version to follow the previous one. # Root schema versions are not random and should be hard-coded. # This is just to make sure that a version was not skipped. last_version = db.session.query( sqlalchemy.func.max(RootSchemaVersion.version).label( 'last_version')).one().last_version if last_version is None: if version != 0: raise InvalidRootSchemaError('First version should ' 'be 0.') elif last_version + 1 != version: raise InvalidRootSchemaError('Given version does not ' 'follow the previous one.') # Create the root schema. model = RootSchemaVersion(json_schema=json.dumps(json_schema), version=version) root_schema = cls(model) db.session.add(model) return root_schema
def create_new_version(cls, version, json_schema): """Load a new root schema version. Args: version (int): version number of this schema. Versions are known in advance and are the same for all B2Share instances. This is more of a security check as the version MUST follow the last loaded one. json_schema (dict): the JSON Schema corresponding to this version. Raises: :class:`b2share.modules.schemas.errors.InvalidRootSchemaError`: If the root schema version is invalid. :class:`b2share.modules.schemas.errors.InvalidJSONSchemaError`: The given JSON Schema is not valid. """ from .models import RootSchemaVersion if not isinstance(json_schema, dict): raise InvalidJSONSchemaError('json_schema must be a dict') previous_root_schemas = _fetch_all_query_pages( RootSchemaVersion.query.filter( RootSchemaVersion.version < version ).order_by(RootSchemaVersion.version.asc()) ) prev_schemas = map(lambda x: x.json_schema, previous_root_schemas) validate_json_schema(json_schema, prev_schemas) with db.session.begin_nested(): # Force the given version to follow the previous one. # Root schema versions are not random and should be hard-coded. # This is just to make sure that a version was not skipped. last_version = db.session.query( sqlalchemy.func.max( RootSchemaVersion.version).label('last_version') ).one().last_version if last_version is None: if version != 0: raise InvalidRootSchemaError('First version should ' 'be 0.') elif last_version + 1 != version: raise InvalidRootSchemaError('Given version does not ' 'follow the previous one.') # Create the root schema. model = RootSchemaVersion( json_schema=json.dumps(json_schema), version=version) root_schema = cls(model) db.session.add(model) return root_schema
def update_existing_version(cls, version, json_schema, options={}): """Update an existing root schema version. Args: version (int): version number of this schema. Versions are known in advance and are the same for all B2Share instances. This is more of a security check as the version MUST follow the last loaded one. json_schema (dict): the JSON Schema corresponding to this version. Raises: :class:`b2share.modules.schemas.errors.InvalidRootSchemaError`: If the root schema version is invalid. :class:`b2share.modules.schemas.errors.RootSchemaDoesNotExistError`: If the root schema version does not exist. :class:`b2share.modules.schemas.errors.InvalidJSONSchemaError`: The given JSON Schema is not valid. """ from .models import RootSchemaVersion if not isinstance(json_schema, dict): raise InvalidJSONSchemaError('json_schema must be a dict') existing_schema = RootSchemaVersion.query.filter( RootSchemaVersion.version == version).one() if existing_schema is None: raise RootSchemaDoesNotExistError( "Root schema version {0} intended for update does not exist.". format(version)) # resolve references if definitions present if 'definitions' in json_schema: json_schema = Schema._resolveLocalReferences( json_schema, json_schema['definitions']) del json_schema['definitions'] validate_json_schema(json_schema, [existing_schema.json_schema], options) with db.session.begin_nested(): # Update the root schema. model = RootSchemaVersion(json_schema=json.dumps(json_schema), version=version) root_schema = cls(model) db.session.merge(model) return root_schema