Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/pr-integration-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,35 @@ jobs:
done
done

# Remove any lite plugins from the changed_dirs array
readarray -t lite_plugin_array < lite_plugins

echo "${changed_dirs[@]}"
echo "${lite_plugin_array[@]}"
# Function to remove items in array2 from array1
remove_items() {
local -n source_array=$1
local -n remove_array=$2
local temp_array=()

for item in "${source_array[@]}"; do
skip=false
for remove_item in "${remove_array[@]}"; do
if [[ "$item" == "$remove_item" ]]; then
skip=true
break
fi
done
if ! $skip; then
temp_array+=("$item")
fi
done

source_array=("${temp_array[@]}")
}

remove_items changed_dirs lite_plugin_array

echo "changed-plugins=${changed_dirs[*]}" >> $GITHUB_OUTPUT

#----------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-linting-and-unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
run: |
for dir in ${{ steps.changed-plugins.outputs.changed-plugins }}; do
cd $dir
poetry install --no-interaction --no-root --extras "aca-py"
poetry install --no-interaction --no-root --all-extras
cd ..
done
#----------------------------------------------
Expand Down
197 changes: 194 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,200 @@
###
### Python
###

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
test-reports/

# Translations
*.mo
*.pot

# Django stuff:
*.log
*.lock
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
Pipfile
Pipfile.lock

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

###
### Visual Studio Code
###

.vscode/

###
### MacOS
###

# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

###
### IntelliJ IDEs
###

.idea/*
**/.idea/*

###
### Windows
###

# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

# Docs build
_build/
**/*.iml

# Open API build
open-api/.build

# devcontainer
.pytest.ini

# project specific
.ruff_cache/
.test-reports/
**/test-reports/
.coverage
coverage.xml
settings.json
.env
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ A script was developed to help with maitenance of the repo called `repo_manager.
Run `python repo_manager.py` and you will be met with 2 options.
- (1) Is used for starting or adding a new plugin. It will generate all the common scaffolding for a plugin which has the expected format.
- (2) Is used for updating and changing common poetry dependencies and configurations. It takes the poetry sections in the `pyproject.toml` files from the `plugin_globals` directory and combines them with the local plugin poetry sections. For the dependencies the common will be overridden by the globals. The other config sections will be replaced by the global configs. Then the lock files will be removed and re-installed.
- (3) Is used for updating the plugin versions in the `plugin_globals` directory. It will update the versions of the plugins in the `plugin_globals` directory to the latest version on the main branch of the plugin repo. It will also update the `plugin_globals` directory to the latest version on the main branch of the plugin repo.
- (4) This option is used by the CI/CD release pipeline. It updates the release notes and the individual plugins with a new version of aries_cloudagent.
- (5) This option is also used by the CI/CD release pipeline. It gets any plugins that have succeeded the tests after a new version of aries_cloudagent has been released if their changes were not reverted than the plugin has been updated to the new version of aries_cloudagent.
- (6) This option will run a general update for all poetry lock files in all plugins.
- (7) This option is used for upgrading a particular library for all plugins. It's useful for when you don't want to do a general upgrade for every library.

## Lite plugins

Sometimes is desirable to have a plugin that doesn't need integration tests or extra scaffholding. However, we need a way to avoid these plugins running integration tests in the CI/CD pipeline. To do this, we can simply add the plugin name to the `lite_plugins` file. Which is a line seperated list of plugin names.
```

## Plugin Documentation

Expand Down
7 changes: 7 additions & 0 deletions jwt_vc_json/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# JWT_VC_JSON credential format plugin

This plugin provides `jwt_vc_json` credential support for the OID4VCI plugin. It acts as a module, dynamically loaded by the OID4VCI plugin, takes input parameters, and constructs and signs `jwt_vc_json` credentials.

## Configuration:

No configuration is required for this plugin.
1 change: 1 addition & 0 deletions jwt_vc_json/jwt_vc_json/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""jwt_vc_json credential handler plugin."""
6 changes: 6 additions & 0 deletions jwt_vc_json/jwt_vc_json/v1_0/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Initialize processor."""

from .cred_processor import CredProcessor


cred_processor = CredProcessor()
64 changes: 64 additions & 0 deletions jwt_vc_json/jwt_vc_json/v1_0/cred_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Issue a jwt_vc_json credential."""

import datetime
import logging
import uuid

from aries_cloudagent.admin.request_context import AdminRequestContext
from aries_cloudagent.wallet.jwt import jwt_sign

from oid4vci.models.exchange import OID4VCIExchangeRecord
from oid4vci.models.supported_cred import SupportedCredential
from oid4vci.public_routes import types_are_subset
from oid4vci.pop_result import PopResult
from oid4vci.cred_processor import ICredProcessor, CredIssueError

LOGGER = logging.getLogger(__name__)


class CredProcessor(ICredProcessor):
"""Credential processor class for jwt_vc_json format."""

async def issue_cred(
self,
body: any,
supported: SupportedCredential,
ex_record: OID4VCIExchangeRecord,
pop: PopResult,
context: AdminRequestContext,
):
"""Return signed credential in JWT format."""
if not types_are_subset(body.get("types"), supported.format_data.get("types")):
raise CredIssueError("Requested types does not match offer.")

current_time = datetime.datetime.now(datetime.timezone.utc)
current_time_unix_timestamp = int(current_time.timestamp())
formatted_time = current_time.strftime("%Y-%m-%dT%H:%M:%SZ")
cred_id = str(uuid.uuid4())

# note: Some wallets require that the "jti" and "id" are a uri
payload = {
"vc": {
**(supported.vc_additional_data or {}),
"id": f"urn:uuid:{cred_id}",
"issuer": ex_record.issuer_id,
"issuanceDate": formatted_time,
"credentialSubject": {
**(ex_record.credential_subject or {}),
"id": pop.holder_kid,
},
},
"iss": ex_record.issuer_id,
"nbf": current_time_unix_timestamp,
"jti": f"urn:uuid:{cred_id}",
"sub": pop.holder_kid,
}

jws = await jwt_sign(
context.profile,
{},
payload,
verification_method=ex_record.verification_method,
)

return jws
1 change: 1 addition & 0 deletions jwt_vc_json/jwt_vc_json/v1_0/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""CredentialProcessor test."""
Loading