Comments (10)
Hi @yousihy!
I just tested it here with a similar setup, but I couldn't replicate the problem.
I believe the configuration is correct.
Some things you could try to narrow the problem down:
- reload the page a few times (this will make sure that the initial load happens after the cookie is already set)
- take a look at your network tab to see if the
init
request is succeeding - put some logs in the createContext, so you know exactly what's being set
- try calling the
reset
function before showing the images
const { edgestore, reset } = useEdgeStore();
async function runAfterAuthChange() {
await reset(); // this will re-run the createContext function
}
Other thing.. There was is a bug for accessControl in production environments (with https) in the current version. It's unrelated to this problem, but you might want to update your package.json to:
"@edgestore/react": "^0.1.5-alpha.5",
"@edgestore/server": "^0.1.5-alpha.5",
this should become stable soon.
Let me know if this helps you solve the problem
from edgestore.
Thanks for the prompt response.
Ok, so here is what I did:
Since I am using Clerk, I don't know how to trigger the reset
after SignIn
. So I added this logic inside useEffect
in the page I am using.
The first image worked and loaded successfully after uploading. However, other images are not loading with the same unauthorized error. I am using the same component on the Edgestore website for multiple image upload, but I removed the progress bars and replaced them with a logic to display the images that were uploaded.
I deleted the cookie
manually and I can see it is being generated again.
I can see that the init
request is getting 200.
The logs in the createContext
are clearly showing that the UserId
is being returned fine with every request.
I did update the libraries in the package, but it had no effect.
For the sake of moving forward with my project, I will ignore the accessControl for now. However, I am unable to delete the Bucket from the Edgestore now that it is protected and I don't want to create a new Bucket. How to do that?
from edgestore.
@yousihy I just created a simple example app with access control in a way that only signed in users can see the images.
Screen.Recording.2023-12-01.at.17.34.44.mov
Here is the router configuration:
import { initEdgeStore } from '@edgestore/server';
import {
createEdgeStoreNextHandler,
type CreateContextOptions,
} from '@edgestore/server/adapters/next/app';
import { initEdgeStoreClient } from '@edgestore/server/core';
import { cookies } from 'next/headers';
import { z } from 'zod';
type Context = {
signedIn: 'true' | 'false';
};
function createContext(_opts: CreateContextOptions): Context {
const signedIn = cookies().get('signedIn')?.value ?? 'false';
return {
signedIn: signedIn === 'true' ? 'true' : 'false',
};
}
const es = initEdgeStore.context<Context>().create();
/**
* This is the main router for the Edge Store buckets.
*/
const edgeStoreRouter = es.router({
privateFiles: es
.fileBucket({
accept: ['image/*'],
})
.input(z.object({ type: z.enum(['post', 'article']) }))
.path(({ input }) => [{ type: input.type }])
.accessControl({
signedIn: { not: 'false' },
}),
});
const handler = createEdgeStoreNextHandler({
router: edgeStoreRouter,
createContext,
});
export { handler as GET, handler as POST };
/**
* This type is used to create the type-safe client for the frontend.
*/
export type EdgeStoreRouter = typeof edgeStoreRouter;
export const backendClient = initEdgeStoreClient({
router: edgeStoreRouter,
baseUrl: 'http://localhost:3000/api/edgestore',
});
You can run this example in your machine with the following steps:
- clone the repo
- checkout to the
next
branch - cd into the
examples/basic-access-control
folder - add your environment variables to
.env.local
npm install
npm run dev
- access it in
http://localhost:3000
I am unable to delete the Bucket from the Edgestore now that it is protected and I don't want to create a new Bucket. How to do that?
Sorry. This is a missing feature in the dashboard. It will be added eventually, but right now all you can do is ignore the old bucket or delete and recreate the whole project.
from edgestore.
Hey! thanks for the updated code. I tried your code after changing the auth logic to use Clerk and instead of using fileBucket, I used the imageBucket.
I first tried to upload 1 image. And it worked. I was able to see the image. Then I tried uploading two images, both are getting 500. I am not sure why it is working for the first image but not for subsequent images:
![image](https://private-user-images.githubusercontent.com/70659920/287969158-204421e6-e720-44e7-bbe8-b7af9c4e5b74.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTkzOTU0ODUsIm5iZiI6MTcxOTM5NTE4NSwicGF0aCI6Ii83MDY1OTkyMC8yODc5NjkxNTgtMjA0NDIxZTYtZTcyMC00NGU3LWJiZTgtYjdhZjljNGU1Yjc0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA2MjYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNjI2VDA5NDYyNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTdmZGFlOThjOTY0MjcxNmFjNGU3NmZhNmU4NDMxN2ZjZmNkMGU1MWZlZWIxNmUxYmJjM2M1M2JhN2M5YzA1ZDMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.UMRCl564v948weE7BqhZ0owhmZ99Fuo6MN2acjYS0BA)
After this, ALL image uploads are getting the 500. I tried to reload the app, restart the server, clear the cashe ... nothing worked.
HOWEVER! By mere luck! I looked at the code and I decided to try loading the images using the url
and not the thumbnailUrl
, and it worked! :)
<MultiFileDropzoneSimple
loadingImages={isUploading}
value={fileStates}
onChange={(files) => {
setFileStates(files)
}}
onFilesAdded={async (addedFiles) => {
setFileStates([...fileStates, ...addedFiles])
setIsUploading(true)
await Promise.all(
addedFiles.map(async (addedFileState) => {
try {
const res =
await edgestore.privateFilesTest.upload({
file: addedFileState.file,
options: {
temporary: true,
},
input: { type: "unit" },
onProgressChange: async (progress) => {
updateFileProgress(
addedFileState.key,
progress
)
if (progress === 100) {
await new Promise((resolve) =>
setTimeout(resolve, 1000)
)
updateFileProgress(
addedFileState.key,
"COMPLETE"
)
}
},
})
setUploadedFiles((uploadedFiles) => [
...uploadedFiles,
{
url: res.url,
thumbnailUrl: res.thumbnailUrl,
},
])
} catch (err) {
updateFileProgress(addedFileState.key, "ERROR")
}
})
)
setIsUploading(false)
}}
/>
</div>
{uploadedFiles.length > 0 && (
<div className="grid grid-cols-4 mt-5 gap-2">
{uploadedFiles.map((file) => (
<div
key={file.thumbnailUrl || file.url}
className="relative w-full h-40 bg-gray-100 rounded-md overflow-hidden"
>
<img
src={file.thumbnailUrl || file.url}
className="absolute inset-0 w-full h-full object-cover"
/>
</div>
))}
</div>
)}
I update the below section to use url instead:
setUploadedFiles((uploadedFiles) => [
...uploadedFiles,
{
url: res.url,
thumbnailUrl: res.url,
},
])
And everything is working now:
![image](https://private-user-images.githubusercontent.com/70659920/287972960-fc2aa4d9-04dc-4427-a007-621630331617.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTkzOTU0ODUsIm5iZiI6MTcxOTM5NTE4NSwicGF0aCI6Ii83MDY1OTkyMC8yODc5NzI5NjAtZmMyYWE0ZDktMDRkYy00NDI3LWEwMDctNjIxNjMwMzMxNjE3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA2MjYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNjI2VDA5NDYyNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU2ZmQ5OTE5M2YxMGU3OGZlNWFhNGZiNDIwOTdhYjcwZmJjYmE0ZTNlZWMxNWY1YmZjMDMwMzIzMmI2ZDg4M2UmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.cTUE_Gn_o5gQwgA2zIFfGgZUV7PNDkz1F4mO-FCuqio)
Am I doing something wrong when it comes to setting or reading the thumbnailUrl
?
from edgestore.
POST http://localhost:3000/api/edgestore/init 500 (Internal Server Error)
Saya baru saja mengikuti tutorial dari dokumentasi secara langsung, tapi saya sudah mendapat pesan error ini, dan berikut konfigurasi yang baru saya tulis :
...
type Context = {
userId: string | null | undefined;
};
async function createContext({ req }: CreateContextOptions): Promise<Context> {
// const { id, role } = await getUserSession(req); // replace with your own session logic
const session = await getServerSession(authOptions);
if (session) {
return {
userId: session?.user?.name,
};
}
return {
// userId: "", // ternyata tidak boleh kosong
userId: "123"
};
}
...
from edgestore.
POST http://localhost:3000/api/edgestore/init 500 (Internal Server Error)
Saya baru saja mengikuti tutorial dari dokumentasi secara langsung, tapi saya sudah mendapat pesan error ini, dan berikut konfigurasi yang baru saya tulis :
... type Context = { userId: string | null | undefined; }; async function createContext({ req }: CreateContextOptions): Promise<Context> { // const { id, role } = await getUserSession(req); // replace with your own session logic const session = await getServerSession(authOptions); if (session) { return { userId: session?.user?.name, }; } return { // userId: "", // ternyata tidak boleh kosong userId: "123" }; } ...
Shouldn't you reply in English so everyone can understand what you're saying? :)
from edgestore.
@wadahkode If you need support running edgestore that's unrelated to this issue, please create a new issue or ask in the Discord server! 🙏
I'll do my best to help you out.
from edgestore.
HOWEVER! By mere luck! I looked at the code and I decided to try loading the images using the url and not the thumbnailUrl, and it worked! :)
Interesting! I'll investigate as soon as I can.
Some things to be aware of when using thumbnails (probably unrelated to the problem):
- Thumbnails are only created for image buckets.
- Thumbnails are not always created. They are created only for images larger than a certain size.
- Thumbnails may take a few seconds to be created after the upload finishes, so if you try to use it as soon as the upload ends, it might still be unaccessible.
That said... I haven't tried using thumbnails with a protected image bucket, there might be a bug in there. I'll let you know when I take a look.
from edgestore.
@yousihy I changed my example project to use image buckets with the thumbnailUrls and I couldn't replicate the problem.
I temporarily deployed the sample app here: https://example-access-control.vercel.app/
the code is updated in the next
branch inside examples/basic-access-control
.
Take a look to see if you can find the problem.
Also, another issue with protected files was reported by a user in Discord.
It's unrelated to this issue, but I'll share it here as well:
It seems that protected files are not accessible in some browsers in a deployed production environment.
Here are some browsers I tested:
- Desktop(Mac) Chrome:
OK
✅ - Desktop(Mac) Arc:
OK
✅ - Desktop(Mac) Firefox:
OK
✅ - Desktop(Mac) Safari:
NG
❌ - Mobile(iOS) Chrome:
NG
❌ - Mobile(iOS) Safari:
NG
❌
This is happens because some browsers have third party cookies disabled by default.
You can make it work by enabling third party cookies for the browser.
But this workaround is not realistic as we can't ask all our users to change their configuration.
Another temporary workaround would be to use the proxyUrl that is used in development to show the file. Considering that the files are not too big, this can be a good workaround for now, as they will be proxied through your api which is in the same domain as the site.
/**
* @example
* const url = 'https://files.edgestore.dev/some/file/path.txt';
* const proxyUrl = convertToProxyUrl(url);
* // => 'https://my-site-domain.com/api/edgestore/proxy-file?url=https%3A%2F%2Ffiles.edgestore.dev%2Fsome%2Ffile%2Fpath.txt'
*/
function convertToProxyUrl(url: string) {
const apiPath = '/api/edgestore'
if (process.env.NODE_ENV === 'production' && !url.includes('/_public/')) {
// In development this is already done internally
const proxyUrl = new URL(window.location.origin);
proxyUrl.pathname = `${apiPath}/proxy-file`;
proxyUrl.search = new URLSearchParams({
url,
}).toString();
return proxyUrl.toString();
}
return url;
}
I believe this issue can only be completely handled when I make a feature for setting custom domains for the file storage.
I'll try to prioritize this after the current release I'm working on right now.
(custom domains will probably be a PRO feature)
from edgestore.
I'll close this issue for now.
If you have any other problems feel free to let me know.
from edgestore.
Related Issues (20)
- delete files on the server side HOT 2
- Error: Image with src "blob:http://localhost:3000/0a4d8c9b-c204-413e-9990-7a32b711735d" is missing required "width" property. HOT 1
- How to view the files on the other end once uploaded...? HOT 2
- Module not found: Can't resolve '@edgestore/shared' after yarn upgrade HOT 4
- Is there a way to dynamically Set S3 Bucket? HOT 1
- Error when deploying to vercel. HOT 2
- Issue when nextjs trailingSlash = true HOT 3
- Ip blocking HOT 1
- Are there any Edgestore's website source code? HOT 1
- How to integrate with react-hook-form? HOT 1
- Deleting files from s3 bucket - possible to use edgestore? HOT 1
- Service only working on localhost HOT 7
- Product website isn't working. HOT 6
- Works perfectly on production but not working on development (localhost) HOT 2
- Product website not working - Internet Provider blocking the site? HOT 2
- Missing edgestore-ctx cookie "UNAUTHORIZED" HOT 3
- How do you delete multiple files? HOT 1
- Error when starting next-intl issue HOT 1
- Thumbnail rotated HOT 2
- Backend Client not outputting thumbnail url HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from edgestore.