Skip to content

Instantly share code, notes, and snippets.

@patatoid
Last active January 29, 2025 16:06
Show Gist options
  • Save patatoid/6ac4093b547a3802606509041d02d17c to your computer and use it in GitHub Desktop.
Save patatoid/6ac4093b547a3802606509041d02d17c to your computer and use it in GitHub Desktop.
boruta integration proof of concept
diff --git a/src/collections/CredentialTemplates.ts b/src/collections/CredentialTemplates.ts
index b93e7d3..758460a 100644
--- a/src/collections/CredentialTemplates.ts
+++ b/src/collections/CredentialTemplates.ts
@@ -3,8 +3,84 @@ import CreateTemplate from '../components/template/CreateTemplate';
import TemplatePageDescription from '../components/template/TemplatePageDescription';
import CodeEditorWithCsvValidation from '../components/template/CodeEditorWithCsvValidation';
+function buildBackendPayload(data) {
+ function parseValue (value, key, acc = []) {
+ if (value instanceof Object) {
+ throw new Error('Arrays not supported yet on boruta')
+ }
+
+ if (value instanceof Array) {
+ throw new Error('Arrays not supported yet on boruta')
+ }
+
+ return {
+ type: 'attribute',
+ name: key,
+ label: key,
+ pointer: acc.concat([key]).join('.')
+ }
+ }
+
+ let claims = []
+
+ Object.keys(data).forEach(key => {
+ claims.push(parseValue(data[key], key))
+ })
+
+ return {
+ backend: {
+ verifiable_credentials: [{
+ version: '13',
+ credential_identifier: 'BorutaTest',
+ format: 'vc+sd-jwt',
+ types: 'credential test',
+ display: { name: 'test credential created with dcc', logo: {} },
+ claims
+ }]
+ }
+ }
+}
+
const CredentialsTemplatesCollection: CollectionConfig = {
slug: 'credential-template',
+ hooks: {
+ beforeChange: [
+ async ({ data }) => {
+ const backendPayload = buildBackendPayload(data.credentialTemplateJson)
+ const auth = await fetch(
+ 'http://127.0.0.1:4000/oauth/token',
+ {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ grant_type: 'client_credentials',
+ client_id: '00000000-0000-0000-0000-000000000001',
+ client_secret: 'zpbc4IZTrGRfzNH0Wr9suGb8b1qpcxcsrRLxkv0W44jotuvzs7D8jhvz4weltGf3oC4dgVJRj1GcqVnrpQ3v8G',
+ scope: 'identity-providers:manage:all'
+ })
+ }
+ )
+
+ const { access_token } = await auth.json()
+
+ const response = await fetch(
+ 'http://127.0.0.1:4001/api/backends/00000000-0000-0000-0000-000000000001',
+ {
+ method: 'PATCH',
+ headers: {
+ 'Authorization': 'Bearer ' + access_token,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(backendPayload)
+ }
+ )
+
+ console.log(await response.json())
+
+ return data
+ }
+ ]
+ },
admin: {
defaultColumns: ['title', 'id'],
useAsTitle: 'title',
diff --git a/src/endpoints/sendBatchEmail.ts b/src/endpoints/sendBatchEmail.ts
index 874fbc5..fb152ea 100644
--- a/src/endpoints/sendBatchEmail.ts
+++ b/src/endpoints/sendBatchEmail.ts
@@ -44,7 +44,7 @@ export const sendBatchEmail: PayloadHandler = async (req, res, next) => {
console.log('//req body', req?.body);
const data = await payload.find({
collection: 'credential', // required
- depth: 2,
+ depth: 3,
where: { ...query }, // pass a `where` query here
sort: '-title',
locale: 'en',
@@ -57,9 +57,32 @@ export const sendBatchEmail: PayloadHandler = async (req, res, next) => {
const claimPageBaseUrl = process.env.CLAIM_PAGE_URL || 'https://localhost:4321';
- const emails = data?.docs?.map(record => {
+ const emails = await Promise.all(data?.docs?.map(async record => {
const jwt = generateJwtFromId(record?.id);
- const link = `${claimPageBaseUrl}/?token=${jwt}`;
+
+ const credentialTemplate = Handlebars.compile(
+ JSON.stringify(record.batch.template.credentialTemplateJson)
+ )
+
+ const auth = await fetch(
+ 'http://127.0.0.1:4000/oauth/token',
+ {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ grant_type: 'agent_credentials',
+ client_id: '00000000-0000-0000-0000-000000000001',
+ client_secret: 'zpbc4IZTrGRfzNH0Wr9suGb8b1qpcxcsrRLxkv0W44jotuvzs7D8jhvz4weltGf3oC4dgVJRj1GcqVnrpQ3v8G',
+ bind_data: credentialTemplate(credential.extraFields),
+ bind_configuration: '{}'
+ })
+ }
+ )
+
+ const { agent_token } = await auth.json()
+
+ const link = `http://localhost:4000/oauth/authorize?client_id=00000000-0000-0000-0000-000000000001&redirect_uri=https://redirect.uri.boruta&agent_token=${agent_token}&scope=BorutaTest&response_type=urn:ietf:params:oauth:response-type:pre-authorized_code`
+ // const link = `${claimPageBaseUrl}/?token=${jwt}`;
// replace handlebar variables in email template with record data
const mergedRecordWithLink = {
...(record.extraFields as any),
@@ -79,7 +102,7 @@ export const sendBatchEmail: PayloadHandler = async (req, res, next) => {
email: 'test email2',
html: `${parsedHtml}`,
};
- });
+ }));
await payload.update({
collection: 'credential-batch',
diff --git a/src/endpoints/sendEmail.ts b/src/endpoints/sendEmail.ts
index 4c63679..19d2c85 100644
--- a/src/endpoints/sendEmail.ts
+++ b/src/endpoints/sendEmail.ts
@@ -51,8 +51,31 @@ export const sendEmail: PayloadHandler = async (req, res) => {
const claimPageBaseUrl = process.env.CLAIM_PAGE_URL || 'https://localhost:4321';
+ const credentialTemplate = Handlebars.compile(
+ JSON.stringify(credential.batch.template.credentialTemplateJson)
+ )
+
const jwt = generateJwtFromId(credential.id);
- const link = `${claimPageBaseUrl}/?token=${jwt}`;
+
+ const auth = await fetch(
+ 'http://127.0.0.1:4000/oauth/token',
+ {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ grant_type: 'agent_credentials',
+ client_id: '00000000-0000-0000-0000-000000000001',
+ client_secret: 'zpbc4IZTrGRfzNH0Wr9suGb8b1qpcxcsrRLxkv0W44jotuvzs7D8jhvz4weltGf3oC4dgVJRj1GcqVnrpQ3v8G',
+ bind_data: credentialTemplate(credential.extraFields),
+ bind_configuration: '{}'
+ })
+ }
+ )
+
+ const { agent_token } = await auth.json()
+
+ const link = `http://localhost:4000/oauth/authorize?client_id=00000000-0000-0000-0000-000000000001&redirect_uri=https://redirect.uri.boruta&agent_token=${agent_token}&scope=BorutaTest&response_type=urn:ietf:params:oauth:response-type:pre-authorized_code`,
+
// replace handlebar variables in email template with record data
const mergedRecordWithLink = {
...(credential.extraFields as any),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment