Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
dbabe40
fix: listener extract functions
jeroenbranje Jul 9, 2025
3614af4
feat(envited): add debug logs
royscheeren Jul 9, 2025
03163cf
feat(envited): add debug logs
royscheeren Jul 9, 2025
f77e99f
feat(envited): add debug logs
royscheeren Jul 9, 2025
2dfcf0f
feat(envited): add debug logs
royscheeren Jul 9, 2025
039d106
fix: upload asset
jeroenbranje Jul 9, 2025
d779df2
fix: add logs
jeroenbranje Jul 9, 2025
308d1ec
feat(envited): add debug logs
royscheeren Jul 9, 2025
d3c3806
fix: add logs
jeroenbranje Jul 9, 2025
1c58f7b
Merge branch 'fix_listener_extract_functions' of github.com:ASCS-eV/e…
royscheeren Jul 9, 2025
eff9b7b
refactor: stream to buffer
royscheeren Jul 9, 2025
ef2e335
refactor: stream to buffer
royscheeren Jul 9, 2025
6204738
refactor: stream to buffer
royscheeren Jul 9, 2025
ecd0a81
fix: fix cids manifest and domainmetadata
jeroenbranje Jul 10, 2025
ad7dc49
fix: fix cids manifest and domainmetadata
jeroenbranje Jul 10, 2025
108727a
feat(envited): add debug logs
royscheeren Jul 10, 2025
06fb5ba
feat(envited): update listener
royscheeren Jul 10, 2025
20abc8a
feat(envited): add order
royscheeren Jul 10, 2025
bcb1ca6
feat(envited): debug assetUpload
royscheeren Jul 10, 2025
e3cbfc3
feat(envited): debug assetUpload
royscheeren Jul 10, 2025
7fb0139
feat(envited): debug assetUpload
royscheeren Jul 10, 2025
c28749c
feat(envited): wrap ipfs upload
royscheeren Jul 10, 2025
e303320
feat(envited): order getAssetByCID
royscheeren Jul 10, 2025
8ab6dbd
feat(envited): update displayCID
royscheeren Jul 10, 2025
44cc96e
feat(gatehouse-api): update sign in for new credentials
royscheeren Nov 1, 2025
3531776
fix(gatehouse-api): typings
royscheeren Nov 1, 2025
76f4630
test: console logs
royscheeren Nov 2, 2025
cfd6096
test: console logs
royscheeren Nov 2, 2025
310682d
test: console logs
royscheeren Nov 2, 2025
7456b21
test: console logs
royscheeren Nov 2, 2025
c1d2e2d
test: console logs
royscheeren Nov 2, 2025
b197747
test: console logs
royscheeren Nov 2, 2025
95b4ee0
feat: update signin for new credentials
royscheeren Nov 4, 2025
39bf9ce
test: update tests
royscheeren Nov 4, 2025
d5d2988
test: update tests
royscheeren Nov 4, 2025
8c92303
feat(envited-x-data-space): update link
royscheeren Nov 27, 2025
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
4 changes: 2 additions & 2 deletions apps/envited-x-data-space/app/onboarding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,12 +426,12 @@ export default async function Index() {
within the ecosystem.
</p>
<p className="mt-6 text-lg leading-8 text-gray-400">
Once your company's digital identity and those of your employees are verified, you can use them for
Once your company&apos;s digital identity and those of your employees are verified, you can use them for
seamless and secure login. This ensures that every user accessing the data space is authenticated,
protecting the integrity of the ecosystem and enabling transparent, trustworthy collaboration.
</p>
<div className="mt-10 flex items-center gap-x-6">
<Button href={'https://staging.identity.ascs.digital/'} colorScheme={ColorScheme.dark} target="_blank">
<Button href={'https://identity.ascs.digital/'} colorScheme={ColorScheme.dark} target="_blank">
Create your own identity
</Button>
<Link href={'/about-us'} className="text-white text-base font-semibold">
Expand Down
27 changes: 20 additions & 7 deletions apps/envited-x-data-space/common/asset/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Log, log } from '../logger'
import { SCHEMA } from '../schemas'
import { extractContentFromStream, formatAssetUri, streamToUint8Array } from '../utils'
import { formatError, internalServerErrorError } from '../utils'
import { stringToStream } from '../utils/utils'
import { streamToBuffer, stringToStream } from '../utils/utils'
import { validateShacl } from '../validator/shacl'
import { MANIFEST_FILE, README_FILE } from './constants'
import { AccessLevel, ExtractedResourceWithCID, Manifest, ManifestCategoryId } from './types'
Expand Down Expand Up @@ -96,25 +96,38 @@ export const _deleteAssetResource =
export const deleteAssetResource = _deleteAssetResource({ db, log })

export const extractManifest = async (assetArchive: Uint8Array) => {
console.log('EXTRACTING MANIFEST')
const manifestStream = await extractFileFromArchive(assetArchive, MANIFEST_FILE)
const manifest = await extractContentFromStream(manifestStream)
console.log('MANIFEST STREAM', manifestStream)
const manifest = await extractContentFromStream(manifestStream).then(JSON.parse)
console.log('MANIFEST', manifest)
const manifestSchemaStream = stringToStream(SCHEMA.manifest)
const { conforms, report } = await validateShacl(manifestSchemaStream)(manifestStream)
const manifestArrayBuffer = await streamToUint8Array(manifestStream)
// const manifestArrayBuffer = await streamToBuffer(manifestStream)
// console.log('MANIFEST ARRAY BUFFER', manifestArrayBuffer)
// const cid = await predetermineCID(manifestArrayBuffer)
const manifestArrayBuffer = await jsonToUint8Array(manifest)
const cid = await predetermineCID(manifestArrayBuffer)
return { conforms, report, data: JSON.parse(manifest), cid, fileSize: manifestArrayBuffer.byteLength }
console.log('MANIFEST CID', cid)
return { conforms, report, data: manifest, cid, fileSize: manifestArrayBuffer.byteLength }
}

export const extractDomainMetadata = async (assetArchive: Uint8Array, manifest: Manifest) => {
const domainMetadataPath = getDomainMetadataPath(manifest)
console.log('DOMAIN METADATA PATH', domainMetadataPath)
const domainMetadataStream = await extractFileFromArchive(assetArchive, domainMetadataPath)
console.log('DOMAIN METADATA STREAM', domainMetadataStream)
const domainMetadata = await extractContentFromStream(domainMetadataStream).then(JSON.parse)
const schemas = getDomainMetadataSchemas(domainMetadata['@context'])
const validationsPromises = schemas.map(schema => validateShacl(stringToStream(schema))(domainMetadataStream))
const validationsResults = await Promise.all(validationsPromises)
const domainMetadataArrayBuffer = await streamToUint8Array(domainMetadataStream)
// const domainMetadataArrayBuffer = await streamToBuffer(domainMetadataStream)
// console.log('DMAB', domainMetadataArrayBuffer)
// const cid = await predetermineCID(domainMetadataArrayBuffer)
const domainMetadataArrayBuffer = await jsonToUint8Array(domainMetadata)
const cid = await predetermineCID(domainMetadataArrayBuffer)

console.log('DOMAIN METADATA', domainMetadata)
console.log('DOMAIN METADATA CID', cid)
return {
conforms: all(x => equals(true)(prop('conforms')(x)), validationsResults),
report: validationsResults,
Expand Down Expand Up @@ -143,7 +156,7 @@ export const getCoverImage = async (assetArchive: Uint8Array, media: ExtractedRe
const coverImageStream = await extractFileFromArchive(assetArchive, coverImage.path)
return {
cid: coverImage.cid,
fileSize: (await streamToUint8Array(coverImageStream)).byteLength,
fileSize: (await streamToBuffer(coverImageStream)).byteLength,
uri: `${formatAssetUri(coverImage.cid)}${coverImage.path}`,
}
}
12 changes: 12 additions & 0 deletions apps/envited-x-data-space/common/auth/auth.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import { _signIn } from './auth'

// Mock the feature flags to disable OIDC for testing
jest.mock('../featureFlags', () => ({
FEATURE_FLAGS: {
development: {
oidc: false,
contract: false,
uniqueAsset: false,
uniqueGlobalIdentifier: false,
},
},
}))

describe('common/auth/auth', () => {
describe('signIn', () => {
it('should call the sign in method with the expected parameters', async () => {
Expand Down
43 changes: 23 additions & 20 deletions apps/envited-x-data-space/common/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { decodeJwt } from 'jose'
import type { NextAuthOptions, Session } from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import { signIn as NASignIn, signOut as NASignOut } from 'next-auth/react'
import { equals, has, isEmpty, isNil, omit, pluck, prop, reject } from 'ramda'
import { equals, has, isEmpty, isNil, pluck, reject } from 'ramda'

import { db } from '../database/queries'
import { Credential } from '../database/types'
import { FEATURE_FLAGS } from '../featureFlags'
import { parseGlobalIdentifier } from '../globalIdentifiers'
import { httpPost } from '../http'
Expand Down Expand Up @@ -77,35 +77,35 @@ export const authOptions: NextAuthOptions = {
clientId: process.env.OIDC_CLIENT_ID,
clientSecret: process.env.OIDC_CLIENT_SECRET,
profile: async profile => {
const credential = decodeJwt(profile.credential as string)
return {
id: profile.sub,
did: profile.sub,
id: (credential.vc as any).credentialSubject.id,
did: (credential.vc as any).credentialSubject.id,
}
},
},
],
secret: process.env.SECRET,
secret: process.env.NEXTAUTH_SECRET,
debug: true,
callbacks: {
async signIn({ profile }) {
try {
if (FEATURE_FLAGS[(process.env.ENV as Environment) || 'development'].oidc) {
log.info('Verifying credential')
log.info(profile)

if (!has('credential')(profile)) {
log.error('Credential not found')
return '/error?error=CREDENTIAL_NOT_FOUND'
}

const credential = omit(['proof'])(
prop('credential')(profile) as Partial<Record<'proof', any>>,
) as Credential[]
log.info('Credential found')
const credential = decodeJwt(profile.credential as string)
log.info('Credential decoded')
const {
id,
issuer,
issuer: { id: issuer },
credentialSubject: { id: credentialSubjectId, type: credentialSubjectType },
} = credential[0]

} = credential.vc as any
log.info('Credential parsed', id, issuer, credentialSubjectId, credentialSubjectType)
if (FEATURE_FLAGS[(process.env.ENV as Environment) || 'development'].contract) {
log.info('Starting revocation registry check')
log.info('credential', id, credentialSubjectId, issuer, credentialSubjectType)
Expand All @@ -126,7 +126,7 @@ export const authOptions: NextAuthOptions = {

if (equals(CredentialType.AscsUser)(credentialSubjectType as CredentialType)) {
const principal = await connection.getUserByDid(parseGlobalIdentifier(issuer))

log.info('Principal found', principal)
log.info('User credential, checking principal credentials')

if (isEmpty(principal)) {
Expand All @@ -142,7 +142,7 @@ export const authOptions: NextAuthOptions = {
}

const existingUser = (await connection.getUserByDid(parseGlobalIdentifier(credentialSubjectId))) as User

log.info('User found', existingUser)
if (!isNil(existingUser)) {
// User already exists
if (!existingUser.isActive) {
Expand All @@ -155,7 +155,7 @@ export const authOptions: NextAuthOptions = {
}

log.info('Inserting user')
await connection.insertUserTx(credential)
await connection.insertUserTx(credential.vc)
}
log.info('Completing signin')
return true
Expand All @@ -171,12 +171,15 @@ export const authOptions: NextAuthOptions = {
if (user) {
token.user = user
}
if (profile && profile.sub) {
const { sub } = profile

if (profile && profile.credential) {
const credential = decodeJwt(profile.credential as string)
const connection = await db()

const user = await connection.getUserByDid(parseGlobalIdentifier(sub))
const result = await connection.getUserRolesByDid(parseGlobalIdentifier(sub))
const user = await connection.getUserByDid(parseGlobalIdentifier((credential.vc as any).credentialSubject.id))
const result = await connection.getUserRolesByDid(
parseGlobalIdentifier((credential.vc as any).credentialSubject.id),
)
const userRoles = pluck('usersToRoles', result)
token.user.role = assignSingleRole(userRoles)
token.user.id = user.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export const processAssetUpload =

return
}
console.log('manifest', manifest)
// Get the domain metadata
const {
conforms: domainMetadataConforms,
Expand All @@ -176,9 +177,14 @@ export const processAssetUpload =

// Get the resources from manifest
const resources = extractResources(manifest)
console.log('RESOURCES', resources)
console.log('MEDIA FILES', getMediaFiles)
const isPublicMedia = pipe(propOr([], 'isPublic'), getMediaFiles)(resources) as ExtractedResource[]
console.log('PBULIC MEDIA', isPublicMedia)
const isRegisteredMedia = pipe(propOr([], 'isRegistered'), getMediaFiles)(resources) as ExtractedResource[]
console.log('REGISTERED MEDIA', isRegisteredMedia)
const isOwnerMedia = pipe(propOr([], 'isOwner'), getMediaFiles)(resources) as ExtractedResource[]
console.log('OWNER MEDIA', isOwnerMedia)
const minter = await getMinter(asset)

// Upload the resources
Expand All @@ -196,16 +202,20 @@ export const processAssetUpload =
ContentEncoding: 'base64',
ContentDisposition: 'inline',
})

await uploadFileToIPFS({ arrayBuffer: fileBuffer, filename: last(split('/', path)) as string, group })
await insertAssetResource({
console.log(upload)
try {
await uploadFileToIPFS({ arrayBuffer: fileBuffer, filename: last(split('/', path)) as string, group })
} catch (err) {
console.log(err)
}
const assetResource = await insertAssetResource({
assetId: asset.id,
name: last(split('/', path)) as string,
cid,
mimeType,
accessLevel: AccessLevel.public,
})

console.log(assetResource)
return upload.done()
},
)
Expand Down Expand Up @@ -275,6 +285,8 @@ export const processAssetUpload =
domainMetadataCID,
media: isPublicMediaWithCids,
})(manifest)

console.log('modifiedManifest', modifiedManifest)
const modifiedManifestCID = await predetermineCID(jsonToUint8Array(modifiedManifest))
const coverImage = await getCoverImage(uploadedFile, isPublicMediaWithCids)

Expand Down Expand Up @@ -306,19 +318,22 @@ export const processAssetUpload =
path: pathOr('', MANIFEST_LICENSE_PATH)(manifest),
},
})
console.log('tzip21Metadata', tzip21Metadata)

await uploadJsonToIPFS({
console.log('domainMetadata', domainMetadata)

const domainCid = await uploadJsonToIPFS({
data: domainMetadata,
filename: `${assetCID}-domain-metadata.json`,
group,
})

await uploadJsonToIPFS({
console.log(domainCid)
const manCid = await uploadJsonToIPFS({
data: modifiedManifest,
filename: `${assetCID}-manifest.json`,
group,
})

console.log(manCid)
// Update stored asset in DB
await updateAsset(
assetCID,
Expand Down
4 changes: 2 additions & 2 deletions apps/envited-x-data-space/common/database/queries/assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { eq } from 'drizzle-orm'
import { desc, eq } from 'drizzle-orm'
import { omit } from 'ramda'

import { Asset, AssetStatus } from '../../types'
Expand All @@ -14,7 +14,7 @@ export const getAsset = (db: DatabaseConnection) => async (id: string) =>
export const getAssets = (db: DatabaseConnection) => async () => db.select().from(asset)

export const getAssetByCID = (db: DatabaseConnection) => async (cid: string) =>
db.select().from(asset).where(eq(asset.cid, cid))
db.select().from(asset).where(eq(asset.cid, cid)).orderBy(desc(asset.createdAt))

export const deleteAsset = (db: DatabaseConnection) => async (id: string) =>
db.delete(asset).where(eq(asset.id, id)).returning()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ describe('common/database/users', () => {
isEnvitedMember: true,
issuanceDate: new Date('2023-11-22T17:14:33.000Z'),
issuerId: 'ISSUER_ID',
name: 'User',
name: 'User ',
postalCode: '12345',
privacyPolicyAccepted: 'https://media.ascs.digital/terms/ascs_privacy_policy_2020-07-08.pdf#SHA-256',
privacyPolicyAccepted: '',
streetAddress: 'Teststraße 1',
updatedAt: new Date(),
vatId: '',
Expand Down
Loading