Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access sharing example #276

Merged
merged 2 commits into from
Nov 7, 2024
Merged
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
75 changes: 75 additions & 0 deletions examples/node/7-private-bucket-access-sharing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { DdcClient, File, TESTNET, AuthToken, UriSigner, AuthTokenOperation } from '@cere-ddc-sdk/ddc-client';
import path from 'path';
import { fileURLToPath } from 'url';
import * as fs from 'fs';

// The Bob's wallet should have enough CERE to pay for the transaction fees
const bob = 'hybrid label reunion only dawn maze asset draft cousin height flock nation';
const bobSigner = new UriSigner(bob);
/**
* The Alice wallet doesn't require any tokens because it accesses Bob's bucket so Bob pays for it.
* Actually the Alice doesn't need to have a wallet on blockchain, it can be a simple key pair used to sign access tokens.
*/
const alice = 'system visit notice before step medal top theme oblige river inner bracket';
const aliceSigner = new UriSigner(alice);

// The DDC cluster where the bucket will be created (mainnet cluster id is '0x0059f5ada35eee46802d80750d5ca4a490640511')
const clusterId = '0x825c4b2352850de9986d9d28568db6f0c023a1e3';

// Create a DDC client instance
const client = await DdcClient.create(bob, TESTNET);

// Create a private bucket
const bucketId = await client.createBucket(clusterId, { isPublic: false });
console.log('Private bucket created', bucketId);

// Detect the current directory
const dir = path.dirname(fileURLToPath(import.meta.url));

const pathToFileToUpload = path.resolve(dir, '../assets/nature.jpg');

// Upload file
const fileSize = fs.statSync(pathToFileToUpload).size;
const fileToUpload = new File(fs.createReadStream(pathToFileToUpload), { size: fileSize });
const uploadedFileUri = await client.store(bucketId, fileToUpload);
console.log('File stored into bucket', bucketId, 'with CID', uploadedFileUri.cid);
console.log(
"The file can't be accessed by this URL because bucket is private and access token required",
`https://cdn.testnet.cere.network/${bucketId}/${uploadedFileUri.cid}`,
);

// Create an access token that is signed by a Bob and can be shared so that anyone having this token can access a bucket (or specific file)
const bobToken = new AuthToken({
bucketId,
pieceCid: uploadedFileUri.cid,
operations: [AuthTokenOperation.GET],
});
await bobToken.sign(bobSigner);
console.log(
"The file can be accessed by this URL (Bob's token passed in query parameters)",
`https://cdn.testnet.cere.network/${bucketId}/${uploadedFileUri.cid}?token=${bobToken.toString()}`,
);

/**
* Create an access token that is signed by a Bob and is granted to Alice so that only Alice can use this token to access a content.
* The Bobs token can't be used directly because he has specified an Alice in a token 'subject' so this token should be wrapped into another token that is signed by Alice
*/
const bobTokenGrantedToAlice = await client.grantAccess(aliceSigner.address, {
bucketId,
operations: [AuthTokenOperation.GET],
pieceCid: uploadedFileUri.cid,
});
// Alice wraps Bob's token (aka token chain) and sign wrapped token by Alice key pair. The token expiration time is 5 minutes.
const aliceToken = new AuthToken({
operations: [AuthTokenOperation.GET],
pieceCid: uploadedFileUri.cid,
prev: bobTokenGrantedToAlice,
expiresIn: 5 * 60 * 1000,
});
await aliceToken.sign(aliceSigner);
console.log(
"The file can be accessed by this URL (Alice's token passed in query parameters)",
`https://cdn.testnet.cere.network/${bucketId}/${uploadedFileUri.cid}?token=${aliceToken.toString()}`,
);

await client.disconnect();
3 changes: 2 additions & 1 deletion examples/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This examples directory contains several common DDC SDK use-cases for NodeJs app
- [How to stream events](./4-store-read-events/index.ts)
- [How to use exported account (Cere Wallet)](./5-use-exported-account/index.ts)
- [How to index files so that they are visible in Developer Console](./6-developer-console-compatibility/index.ts)
- [How to share access to a content in private bucket](./7-private-bucket-access-sharing/index.ts)

## Quick start

Expand Down Expand Up @@ -40,7 +41,7 @@ Run the following commands from the project root
5. Run an example

```bash
npm run example:1 # can be 1-6
npm run example:1 # can be 1-7
```


Expand Down
3 changes: 2 additions & 1 deletion examples/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"example:3": "ts-node --esm ./3-upload-website/index.ts",
"example:4": "ts-node --esm ./4-store-read-events/index.ts",
"example:5": "ts-node --esm ./5-use-exported-account/index.ts",
"example:6": "ts-node --esm ./6-developer-console-compatibility/index.ts"
"example:6": "ts-node --esm ./6-developer-console-compatibility/index.ts",
"example:7": "ts-node --esm ./7-private-bucket-access-sharing/index.ts"
},
"dependencies": {
"@cere-ddc-sdk/ddc-client": "2.13.0",
Expand Down
Loading