Skip to content

Commit

Permalink
Format and add linting rules/github action
Browse files Browse the repository at this point in the history
Signed-off-by: jamshale <jamiehalebc@gmail.com>
  • Loading branch information
jamshale committed Jan 14, 2025
1 parent 945e891 commit ba2d013
Show file tree
Hide file tree
Showing 18 changed files with 303 additions and 169 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/pr-linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Ruff Code Formatter and Linting Check

on:
pull_request:
branches: [ main ]

jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Ruff Format and Lint Check
uses: astral-sh/ruff-action@v3
with:
src: "./server"
version: "0.9.1"
args: "format --check"
4 changes: 3 additions & 1 deletion server/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fastapi import FastAPI, APIRouter
from fastapi import APIRouter, FastAPI
from fastapi.responses import JSONResponse

from app.routers import identifiers
from config import settings

Expand All @@ -10,6 +11,7 @@

@api_router.get("/server/status", tags=["Server"], include_in_schema=False)
async def server_status():
"""Server status endpoint."""
return JSONResponse(status_code=200, content={"status": "ok"})


Expand Down
8 changes: 6 additions & 2 deletions server/app/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""This module contains dependencies used by the FastAPI application."""

from fastapi import HTTPException
from config import settings

from app.plugins import AskarStorage


async def identifier_available(did: str):
"""Check if a DID identifier is available."""
if await AskarStorage().fetch("didDocument", did):
raise HTTPException(status_code=409, detail="Identifier unavailable.")


async def did_document_exists(did: str):
"""Check if a DID document exists."""
if not await AskarStorage().fetch("didDocument", did):
raise HTTPException(status_code=404, detail="Ressource not found.")
raise HTTPException(status_code=404, detail="Resource not found.")
14 changes: 13 additions & 1 deletion server/app/models/di_proof.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
from typing import Dict, Any
"""This module defines the DataIntegrityProof model used for data integrity proofs."""

from typing import Any, Dict

from pydantic import BaseModel, Field, field_validator


class BaseModel(BaseModel):
"""Base model for all models in the application."""

def model_dump(self, **kwargs) -> Dict[str, Any]:
"""Dump the model to a dictionary."""
return super().model_dump(by_alias=True, exclude_none=True, **kwargs)


class DataIntegrityProof(BaseModel):
"""DataIntegrityProof model."""

type: str = Field("DataIntegrityProof")
cryptosuite: str = Field("eddsa-jcs-2022")
proofValue: str = Field()
Expand Down Expand Up @@ -35,22 +43,26 @@ class DataIntegrityProof(BaseModel):
@field_validator("type")
@classmethod
def validate_type(cls, value):
"""Validate the type field."""
assert value == "DataIntegrityProof"
return value

@field_validator("cryptosuite")
@classmethod
def validate_cryptosuite(cls, value):
"""Validate the cryptosuite field."""
assert value in ["eddsa-jcs-2022"]
return value

@field_validator("proofPurpose")
@classmethod
def validate_proof_purpose(cls, value):
"""Validate the proofPurpose field."""
assert value in ["assertionMethod", "authentication"]
return value

@field_validator("expires")
@classmethod
def validate_expires(cls, value):
"""Validate the expires field."""
return value
48 changes: 36 additions & 12 deletions server/app/models/did_document.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
from typing import Union, List, Dict, Any
from pydantic import BaseModel, Field, field_validator
from .di_proof import DataIntegrityProof
from multiformats import multibase
from config import settings
"""DID Document model."""

import re
from typing import Any, Dict, List, Union

import validators
from multiformats import multibase
from pydantic import BaseModel, Field, field_validator

from .di_proof import DataIntegrityProof

DID_WEB_REGEX = re.compile("did:web:((?:[a-zA-Z0-9._%-]*:)*[a-zA-Z0-9._%-]+)")

DID_WEB_ID_REGEX = re.compile(
"did:web:((?:[a-zA-Z0-9._%-]*:)*[a-zA-Z0-9._%-]+)#([a-z0-9._%-]+)"
)
DID_WEB_ID_REGEX = re.compile("did:web:((?:[a-zA-Z0-9._%-]*:)*[a-zA-Z0-9._%-]+)#([a-z0-9._%-]+)")


class BaseModel(BaseModel):
"""Base model for all models in the application."""

def model_dump(self, **kwargs) -> Dict[str, Any]:
"""Dump the model to a dictionary."""
return super().model_dump(by_alias=True, exclude_none=True, **kwargs)


class VerificationMethod(BaseModel):
"""VerificationMethod model."""

id: str = Field()
type: Union[str, List[str]] = Field()
controller: str = Field()

@field_validator("id")
@classmethod
def verification_method_id_validator(cls, value):
"""Validate the id field."""
assert value.startswith("did:")
return value

@field_validator("type")
@classmethod
def verification_method_type_validator(cls, value):
"""Validate the type field."""
assert value in [
"Multikey",
"JsonWebKey",
Expand All @@ -42,58 +49,73 @@ def verification_method_type_validator(cls, value):
@field_validator("controller")
@classmethod
def verification_method_controller_validator(cls, value):
"""Validate the controller field."""
assert value.startswith("did:")
return value


class JsonWebKey(BaseModel):
"""JsonWebKey model."""

kty: str = Field("OKP")
crv: str = Field("Ed25519")
x: str = Field()


class VerificationMethodJwk(VerificationMethod):
"""VerificationMethodJwk model."""

publicKeyJwk: JsonWebKey = Field()

@field_validator("publicKeyJwk")
@classmethod
def verification_method_public_key_validator(cls, value):
"""Validate the public key field."""
# TODO decode b64
return value


class VerificationMethodMultikey(VerificationMethod):
"""VerificationMethodMultikey model."""

publicKeyMultibase: str = Field()

@field_validator("publicKeyMultibase")
@classmethod
def verification_method_public_key_validator(cls, value):
"""Validate the public key field."""
try:
multibase.decode(value)
except:
except Exception:
assert False, f"Unable to decode public key multibase value {value}"
return value


class Service(BaseModel):
"""Service model."""

id: str = Field()
type: Union[str, List[str]] = Field()
serviceEndpoint: str = Field()

@field_validator("id")
@classmethod
def service_id_validator(cls, value):
"""Validate the id field."""
assert value.startswith("did:")
return value

@field_validator("serviceEndpoint")
@classmethod
def service_endpoint_validator(cls, value):
"""Validate the service endpoint field."""
assert validators.url(value), f"Invalid service endpoint {value}."
return value


class DidDocument(BaseModel):
"""DID Document model."""

context: Union[str, List[str]] = Field(
["https://www.w3.org/ns/did/v1"],
alias="@context",
Expand All @@ -103,9 +125,7 @@ class DidDocument(BaseModel):
description: str = Field(None)
controller: str = Field(None)
alsoKnownAs: List[str] = Field(None)
verificationMethod: List[
Union[VerificationMethodMultikey, VerificationMethodJwk]
] = Field(None)
verificationMethod: List[Union[VerificationMethodMultikey, VerificationMethodJwk]] = Field(None)
authentication: List[Union[str, VerificationMethod]] = Field(None)
assertionMethod: List[Union[str, VerificationMethod]] = Field(None)
keyAgreement: List[Union[str, VerificationMethod]] = Field(None)
Expand All @@ -127,15 +147,19 @@ class DidDocument(BaseModel):
@field_validator("context")
@classmethod
def context_validator(cls, value):
"""Validate the context field."""
assert value[0] == "https://www.w3.org/ns/did/v1", "Invalid context."
return value

@field_validator("id")
@classmethod
def id_validator(cls, value):
"""Validate the id field."""
assert value.startswith("did:")
return value


class SecuredDidDocument(DidDocument):
"""Secured DID Document model."""

proof: Union[DataIntegrityProof, List[DataIntegrityProof]] = Field()
28 changes: 25 additions & 3 deletions server/app/models/did_log.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
from typing import Union, List, Dict, Any
"""DID Log models."""

from typing import Any, Dict, List, Union

from pydantic import BaseModel, Field
from .did_document import DidDocument
from .di_proof import DataIntegrityProof

from config import settings

from .di_proof import DataIntegrityProof
from .did_document import DidDocument


class BaseModel(BaseModel):
"""Base model for all models in the application."""

def model_dump(self, **kwargs) -> Dict[str, Any]:
"""Dump the model to a dictionary."""
return super().model_dump(by_alias=True, exclude_none=True, **kwargs)


class Witness(BaseModel):
"""Witness model."""

id: str = Field(None)
weight: int = Field(None)


class WitnessParam(BaseModel):
"""WitnessParam model."""

threshold: int = Field(None)
selfWeight: int = Field(None)
witnesses: List[Witness] = Field(None)


class WitnessSignature(BaseModel):
"""WitnessSignature model."""

versionId: str = Field(None)
proof: List[DataIntegrityProof] = Field()


class InitialLogParameters(BaseModel):
"""InitialLogParameters model."""

method: str = Field(f"did:webvh:{settings.WEBVH_VERSION}")
scid: str = Field()
updateKeys: List[str] = Field()
Expand All @@ -37,6 +53,8 @@ class InitialLogParameters(BaseModel):


class LogParameters(BaseModel):
"""LogParameters model."""

prerotation: bool = Field(None)
portable: bool = Field(None)
updateKeys: List[str] = Field(None)
Expand Down Expand Up @@ -64,6 +82,8 @@ class LogParameters(BaseModel):


class InitialLogEntry(BaseModel):
"""InitialLogEntry model."""

versionId: str = Field()
versionTime: str = Field()
parameters: LogParameters = Field()
Expand All @@ -72,6 +92,8 @@ class InitialLogEntry(BaseModel):


class LogEntry(BaseModel):
"""LogEntry model."""

versionId: str = Field()
versionTime: str = Field()
parameters: LogParameters = Field()
Expand Down
19 changes: 16 additions & 3 deletions server/app/models/web_schemas.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
from typing import Dict, Any, List
"""Pydantic models for the web schemas."""

from typing import Any, Dict, List

from pydantic import BaseModel, Field
from .did_document import SecuredDidDocument
from .did_log import InitialLogEntry, LogEntry, WitnessSignature

from .di_proof import DataIntegrityProof
from .did_document import SecuredDidDocument
from .did_log import InitialLogEntry, LogEntry


class BaseModel(BaseModel):
"""Base model for all models in the application."""

def model_dump(self, **kwargs) -> Dict[str, Any]:
"""Dump the model to a dictionary."""
return super().model_dump(by_alias=True, exclude_none=True, **kwargs)


class RegisterDID(BaseModel):
"""RegisterDID model."""

didDocument: SecuredDidDocument = Field()


class RegisterInitialLogEntry(BaseModel):
"""RegisterInitialLogEntry model."""

logEntry: InitialLogEntry = Field()


class UpdateLogEntry(BaseModel):
"""UpdateLogEntry model."""

logEntry: LogEntry = Field()
witnessProof: List[DataIntegrityProof] = Field(None)

Expand Down
Loading

0 comments on commit ba2d013

Please sign in to comment.