Describe the feature
As we get user-owned storage back, it is important to lookup the read url from the profile. This is what getUserAppFileUrl does. This function should be exported by @stacks/storage
thanks @friedger, we'd have to see if/how we could prioritize this. do you have more context on the importance - is this a blocker for you? in what use case/app?
As a workaround, I have cloned the code for the function.
I am upgrading my blockstack apps to stacks apps. I am using the function to get a public calendar from a different user on cal.openintents.org
@friedger I was looking into this issue. The getUserAppFileUrl is a method of Storage class which is already exported from storage package. To call this method we need a instance of Storage class which is exported by storage.
Example test case:
const { Storage } = require('../src');
const storage = new Storage({ userSession });
await storage.getUserAppFileUrl(path, name, appOrigin).then((url: string) => {
expect(url).toBeTruthy();
expect(url).toEqual(fileUrl);
});
@friedger If you can elaborate what sort of export you are envisioning for getUserAppFileUrl that would be great.
cc: @agraebe @friedger @asimm241
@asimm241 investigated this and it seems not to be an issue. closing for now; please reopen with more details if it still is an issue
@agraebe Could you please reopen it.
The issue is about the requirement of a user session. The method is querying of a different user's profile. There is no need for this dependency.
Workaround would be to define a new function that creates the objects.
async function getUserAppFileUrl2(...) {
return new Storage({new UserSession()}).getUserAppFileUrl(...)
}
The method does not belong to the storage object, I think.
@agraebe Could you please reopen it.
The issue is about the requirement of a user session. The method is querying of a different user's profile. There is no need for this dependency.
Workaround would be to define a new function that creates the objects.
async function getUserAppFileUrl2(...) { return new Storage({new UserSession()}).getUserAppFileUrl(...) }The method does not belong to the storage object, I think.
@friedger Just reiterating this thing.
The method getUserAppFileUrl belongs to storage class. To call the method you need a storage class object. Here is the reference:
https://github.com/blockstack/stacks.js/blob/f3cf94683b377619b9390fb400f445edf47f378a/packages/storage/src/storage.ts#L196
Test case: https://github.com/blockstack/stacks.js/blob/f3cf94683b377619b9390fb400f445edf47f378a/packages/storage/tests/storage.test.ts#L1970
It would be great if you can visit my previous comment with snipit:
const { Storage } = require('../src');
const storage = new Storage({ userSession });
await storage.getUserAppFileUrl(path, name, appOrigin).then((url: string) => {
expect(url).toBeTruthy();
expect(url).toEqual(fileUrl);
});
And elaborate on what sort of getUserAppFileUrl export you need. As its a method of storage class which is already exported.
The method getUserAppFileUrl belongs to storage class.
@ahsan-javaid I disagree here. As a app developer, I just need the Stacks chain to resolve the username, lookup the profile and construct the read-only url.
The use-case is that I want to show a list of public avatar, they are stored at a specific file on the users gaia bucket unencrypted. There is no need to authenticate with the gaia storage, no need to be authenticated as a user. I just want to call getUserAppFileUrl(path, username, window.location.origin) and display that image.
The storage object describes mainly my own storage, the storage object has an understanding of my gaia host configuration. At least that is my understanding.
cc @HariniRajan397 as she investigates how to support custom gaia configurations.
Furthermore, the implementation is
async function getUserAppFileUrl(path, username, appOrigin, zoneFileLookupURL) {
const profile = await lookupProfile({ username, zoneFileLookupURL })
let bucketUrl
if (profile.hasOwnProperty('apps')) {
if (profile.apps.hasOwnProperty(appOrigin)) {
const url = profile.apps[appOrigin]
const bucket = url.replace(/\/?(\?|#|$)/, '/$1')
bucketUrl = `${bucket}${path}`
}
}
return bucketUrl
}
There is no use of any gaia related methods. The function could be even moved to @stacks/profile. However, without any storage calls there won't be any meaningful files to resolve. To be discussed.
@friedger it looks like the issue is mostly about making this function a bit more straightforward to use (i.e. not requiring construction of a Storage class)?
Seems like a reasonable request.
One thing I'd caution is that if the function getUserAppFileUrl(path, username, appOrigin, zoneFileLookupURL) is exposed, it should require the last param zoneFileLookupURL to be specified. It would help inform/encourage app devs that they are forfeiting a possible user-supplied endpoint in favor of either the Hiro hosted instance or the app-dev's instance. In other words, we want to encourage devs to use the Storage class when the user is logged in, where the user may have specified their own decentralized node endpoint.
And I'd recommend this regardless if the wallets/authenticators currently support user supplied endpoints.