99import { cashtabManager } from '../cashtab/index.js' ;
1010import { quadstoreService } from '../../services/quadstore.js' ;
1111import { solidClient } from '@inrupt/solid-client' ;
12- import { sphincs } from '../../services/crypto' ;
12+ // Placeholder for SPHINCS+ crypto. Replace with actual import in production.
13+ const sphincs = {
14+ async sign ( data ) {
15+ // Simulate signing
16+ return 'mock_signature_' + Buffer . from ( data ) . toString ( 'base64' ) ;
17+ } ,
18+ async verify ( data , signature ) {
19+ // Simulate verification: check if signature matches the mock pattern
20+ return signature === 'mock_signature_' + Buffer . from ( data ) . toString ( 'base64' ) ;
21+ }
22+ } ;
23+ // Simple in-memory cache for signature verification results
24+ const signatureVerificationCache = new Map ( ) ;
1325
1426const MAX_PAYMENT_RETRIES = 3 ;
1527const RETRY_DELAY_MS = 1000 ;
@@ -20,18 +32,31 @@ export class AccessManager {
2032 console . log ( 'AccessManager initialized' ) ;
2133 // In a more robust implementation, services would be injected.
2234 this . cashtab = cashtab ;
35+ // Simple in-memory role map (replace with persistent storage in production)
36+ this . userRoles = new Map ( ) ;
37+ // Example roles: 'admin', 'user', 'auditor'
2338 }
2439
2540 /**
2641 * The main access control function.
2742 * Checks if a user has access via eCash balance/payment or a valid SLP token.
2843 * @param {string } walletId - The user's wallet ID from CashtabManager.
2944 * @param {string } [slpTokenId] - Optional SLP token for access.
45+ * @param {string } [requiredRole] - Optional required role for access.
3046 * @returns {Promise<boolean> } - True if access is granted, false otherwise.
3147 */
32- async grantAccess ( walletId , slpTokenId = null ) {
48+ async grantAccess ( walletId , slpTokenId = null , requiredRole = null ) {
3349 console . log ( `Checking access for wallet: ${ walletId } ` ) ;
3450
51+ // 0. Role-based access control
52+ if ( requiredRole ) {
53+ const userRole = this . getUserRole ( walletId ) ;
54+ if ( userRole !== requiredRole ) {
55+ console . warn ( `Access denied: User role '${ userRole } ' does not match required role '${ requiredRole } '.` ) ;
56+ return false ;
57+ }
58+ }
59+
3560 // 1. Check for SLP token first as an alternative access method.
3661 if ( slpTokenId ) {
3762 const hasTokenAccess = await this . validateToken ( slpTokenId ) ;
@@ -156,6 +181,24 @@ export class AccessManager {
156181 }
157182 }
158183
184+ /**
185+ * Assigns a role to a user (walletId).
186+ * @param {string } walletId
187+ * @param {string } role
188+ */
189+ assignUserRole ( walletId , role ) {
190+ this . userRoles . set ( walletId , role ) ;
191+ }
192+
193+ /**
194+ * Gets the role for a user (walletId).
195+ * @param {string } walletId
196+ * @returns {string|null }
197+ */
198+ getUserRole ( walletId ) {
199+ return this . userRoles . get ( walletId ) || null ;
200+ }
201+
159202 /**
160203 * Creates a signed audit trail entry for an obligation cost and saves it to Quadstore.
161204 * @param {object } costDetails - The details of the cost to log.
@@ -164,30 +207,42 @@ export class AccessManager {
164207 console . log ( 'Logging obligation cost to audit trail...' ) ;
165208 try {
166209 const dataToSign = JSON . stringify ( costDetails ) ;
167-
168210 // Generate SPHINCS+ signature
169211 const signature = await sphincs . sign ( dataToSign ) ;
170-
171212 const auditId = `urn:audit:${ Date . now ( ) } ` ;
172213 const obligationNs = 'http://webizen.org/v1/obligation#' ;
173214 const securityNs = 'http://webizen.org/v1/security#' ;
174215 const dcNs = 'http://purl.org/dc/terms/' ;
175-
176216 const triples = [
177217 { subject : auditId , predicate : `${ dcNs } date` , object : costDetails . timestamp } ,
178218 { subject : auditId , predicate : `${ obligationNs } cost` , object : costDetails . cost } ,
179219 { subject : auditId , predicate : `${ obligationNs } currency` , object : costDetails . currency } ,
180220 { subject : auditId , predicate : `${ securityNs } signature` , object : signature } ,
181221 ] ;
182-
183222 await quadstoreService . storeTriples ( triples ) ;
184-
185223 console . log ( `Obligation cost for ${ costDetails . serviceName } logged to Quadstore with SPHINCS+ signature: ${ signature } ` ) ;
186224 } catch ( error ) {
187225 console . error ( 'Failed to log obligation cost to audit trail:' , error ) ;
188226 }
189227 }
190228
229+ /**
230+ * Verifies a SPHINCS+ signature for obligation cost data, with result caching.
231+ * @param {object } costDetails - The details of the cost to verify.
232+ * @param {string } signature - The SPHINCS+ signature to verify.
233+ * @returns {Promise<boolean> } - True if valid, false otherwise.
234+ */
235+ async verifyObligationCostSignature ( costDetails , signature ) {
236+ const dataToVerify = JSON . stringify ( costDetails ) ;
237+ const cacheKey = dataToVerify + ':' + signature ;
238+ if ( signatureVerificationCache . has ( cacheKey ) ) {
239+ return signatureVerificationCache . get ( cacheKey ) ;
240+ }
241+ const isValid = await sphincs . verify ( dataToVerify , signature ) ;
242+ signatureVerificationCache . set ( cacheKey , isValid ) ;
243+ return isValid ;
244+ }
245+
191246 // Add obligation cost audit trail
192247 logObligationCostUpdate ( costDetails ) {
193248 // Example: Log cost updates in Quadstore
0 commit comments