Skip to content

Commit

Permalink
Merge pull request #11 from nexB/10-vul-package-json-schema
Browse files Browse the repository at this point in the history
Add JSON schema for Package and Vulnerability metadata
  • Loading branch information
keshav-space authored Jul 11, 2024
2 parents a8b8653 + f1b8f28 commit eafb989
Show file tree
Hide file tree
Showing 7 changed files with 456 additions and 1 deletion.
55 changes: 55 additions & 0 deletions fedcode/management/commands/gen-schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# VulnerableCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

import json

from django.core.management.base import BaseCommand
from pydantic.json_schema import GenerateJsonSchema

from fedcode import schemas


class GenerateFederatedCodeJsonSchema(GenerateJsonSchema):
def generate(self, schema, mode="validation"):
json_schema = super().generate(schema, mode=mode)
json_schema["$schema"] = self.schema_dialect
return json_schema


def get_ordered_schema(schema, schema_path):
schema["$id"] = f"https://raw.githubusercontent.com/nexB/federatedcode/main/{schema_path}"
desired_order = [
"$schema",
"$id",
"title",
"type",
]

ordered_schema = {key: schema[key] for key in desired_order}
ordered_schema.update({key: schema[key] for key in schema if key not in desired_order})
return ordered_schema


def gen_schema(model_schema, path):
schema = model_schema.model_json_schema(schema_generator=GenerateFederatedCodeJsonSchema)
ordered_schema = get_ordered_schema(schema=schema, schema_path=path)
with open(path, "w", encoding="utf-8") as f:
json.dump(ordered_schema, f, indent=2)


class Command(BaseCommand):
def handle(self, *args, **options):
gen_schema(
model_schema=schemas.Vulnerability,
path="schemas/vulnerability.schema.json",
)
gen_schema(
model_schema=schemas.Package,
path="schemas/package.schema.json",
)
76 changes: 76 additions & 0 deletions fedcode/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# VulnerableCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

from ninja import ModelSchema
from typing import List

from fedcode import models


class RemoteActor(ModelSchema):
class Meta:
model = models.RemoteActor
fields = ["url", "username", "created_at", "updated_at"]


class Repository(ModelSchema):
"""
A git repository used as a backing storage for Package and vulnerability data
"""
class Meta:
model = models.Repository
exclude = ["admin"]


class Vulnerability(ModelSchema):
repo: Repository

class Meta:
model = models.Vulnerability
fields = "__all__"

class Reputation(ModelSchema):
"""
https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like
https://www.w3.org/ns/activitystreams#Dislike
"""
class Meta:
model = models.Reputation
fields = ["object_id", "voter", "positive"]


class Note(ModelSchema):
"""
A Note is a message send by a Person or Package.
The content is either a plain text message or structured YAML.
If the author is a Package actor then the content is always YAML
If the author is a Person actor then the content is always plain text
https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
"""
reputation: List[Reputation]
reply_to: "Note"

class Meta:
model = models.Note
fields = "__all__"


Note.model_rebuild()


class Package(ModelSchema):
"""
A software package identified by its package url ( PURL ) ignoring versions
"""
remote_actor: RemoteActor
notes: List[Note]

class Meta:
model = models.Package
exclude = ["service"]
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ django-environ==0.11.2
django-oauth-toolkit==2.3.0
django-rest-framework==0.1.0
djangorestframework==3.14.0
django-ninja==1.2.1
docutils==0.20.1
et-xmlfile==1.1.0
exceptiongroup==1.1.1
Expand Down Expand Up @@ -68,6 +69,7 @@ pytest==7.3.2
pytest-django==4.5.2
pytest-xdist==3.5.0
python-dateutil==2.8.2
pydantic==2.8.2
pytz==2023.3
PyYAML==6.0.1
readme-renderer==42.0
Expand Down
201 changes: 201 additions & 0 deletions schemas/package.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/nexB/federatedcode/main/schemas/package.schema.json",
"title": "Package",
"type": "object",
"$defs": {
"Note": {
"description": "A Note is a message send by a Person or Package.\nThe content is either a plain text message or structured YAML.\nIf the author is a Package actor then the content is always YAML\nIf the author is a Person actor then the content is always plain text\nhttps://www.w3.org/TR/activitystreams-vocabulary/#dfn-note",
"properties": {
"reputation": {
"items": {
"$ref": "#/$defs/Reputation"
},
"title": "Reputation",
"type": "array"
},
"reply_to": {
"$ref": "#/$defs/Note"
},
"id": {
"anyOf": [
{
"format": "uuid",
"type": "string"
},
{
"type": "null"
}
],
"description": "The object's unique global identifier",
"title": "Id"
},
"acct": {
"maxLength": 200,
"title": "Acct",
"type": "string"
},
"content": {
"title": "Content",
"type": "string"
},
"mediaType": {
"default": "text/plain",
"maxLength": 20,
"title": "mediaType",
"type": "string"
},
"created_at": {
"description": "A field to track when notes are created",
"format": "date-time",
"title": "Created At",
"type": "string"
},
"updated_at": {
"description": "A field to track when notes are updated",
"format": "date-time",
"title": "Updated At",
"type": "string"
}
},
"required": [
"reputation",
"reply_to",
"acct",
"content",
"created_at",
"updated_at"
],
"title": "Note",
"type": "object"
},
"RemoteActor": {
"properties": {
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Url"
},
"username": {
"maxLength": 100,
"title": "Username",
"type": "string"
},
"created_at": {
"description": "A field to track when remote actor are created",
"format": "date-time",
"title": "Created At",
"type": "string"
},
"updated_at": {
"description": "A field to track when remote actor are updated",
"format": "date-time",
"title": "Updated At",
"type": "string"
}
},
"required": [
"username",
"created_at",
"updated_at"
],
"title": "RemoteActor",
"type": "object"
},
"Reputation": {
"description": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like\nhttps://www.w3.org/ns/activitystreams#Dislike",
"properties": {
"object_id": {
"anyOf": [
{
"format": "uuid",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Object Id"
},
"voter": {
"description": "security@vcio",
"maxLength": 100,
"title": "Voter",
"type": "string"
},
"positive": {
"default": true,
"title": "Positive",
"type": "boolean"
}
},
"required": [
"voter"
],
"title": "Reputation",
"type": "object"
}
},
"description": "A software package identified by its package url ( PURL ) ignoring versions",
"properties": {
"remote_actor": {
"$ref": "#/$defs/RemoteActor"
},
"notes": {
"items": {
"$ref": "#/$defs/Note"
},
"title": "Notes",
"type": "array"
},
"summary": {
"description": "profile summary",
"maxLength": 100,
"title": "Summary",
"type": "string"
},
"public_key": {
"title": "Public Key",
"type": "string"
},
"local": {
"default": true,
"title": "Local",
"type": "boolean"
},
"id": {
"anyOf": [
{
"format": "uuid",
"type": "string"
},
{
"type": "null"
}
],
"description": "The object's unique global identifier",
"title": "Id"
},
"purl": {
"description": "PURL (no version) ex: @pkg:maven/org.apache.logging",
"maxLength": 300,
"title": "Purl",
"type": "string"
}
},
"required": [
"remote_actor",
"notes",
"summary",
"public_key",
"purl"
]
}
Loading

0 comments on commit eafb989

Please sign in to comment.