Web application for managing video and PDF files. Admin users are authorized to create, read, update and delete files from admin dashboard. Member users are allowed to read only.
Note: You will need to create valid accounts for Cloudinary, Atlas and Auth0 to run the application
# create .env files.
# please read the .env.template files for documentation on each variable value
cat .env.template >> .env
cat client/.env.template >> client/.env
# install server dependencies
npm i
# install client dependencies
cd client && npm i
All users are managed by Auth0. In order to configure the application to authenticate correctly, you will need to create an Auth0 account. In addition, there are a few things you need to do from the Auth0 dashboard:
In order for Auth0 to know which application users are logging into (and where to redirect back to), we need to create and register the web client application from the Auth0 dashboard.
Under Applications, select Applications and click create. Select Single Page Web Application. Under settings tab add the URL of your Vite client root routes (e.g. http://localhost:5173
) to the following form fields:
- Allowed Callback URL's
- For this one, you need to add both
http://localhost:5173
andhttp://localhost:5173/admin
separated by a comma.
- For this one, you need to add both
- Allowed Logout URL's
- Allowed Web Origins
At the top of settings you will find the credentials for connecting to the Auth0 Service from your frontend web application. See client/.env.template
file for reference.
When running the web app locally you should be able to log in and sign up users successfully from the landing page.
In order for the server to authenticate requests, we need to create and configure an Auth0 API which will allow requests to made to our server api/
endpoints
Under Applications Menu, select APIs and click Create API. Give it a name and use the server endpoint as your identifier (e.g. http://localhost:8080
). Your identifier will be used for the VITE_AUTH0_AUDIENCE
and AUTH0_AUDIENCE
environment variables. Under Quickstart --> Node.js you will see the AUTH0_ISSUER_BASE_URL
value needed to configure your Auth0 server connection.
You can define the permissions that apply to this API under the Permissions tab. For this project, you'll need to create create:files
, read:files
, update:files
, and delete:files
.
To enforce the permissions defined above, under User Management --> Roles you must create a User Role and apply the relevant permissions for the selected API. Create two, one called Member, and another called Admin. Member roles should only be assigned read:files
permissions, while Admin roles should be given all possible permissions.
Under User Management --> Users, create two users and assign one of them the member role, and the other an admin role. Once the admin user is created, under details add a metadata field like this (this is what tells the client app to determine what type of user is logged in):
{
"admin": true
}
Under Auth0 --> Actions --> Library, go to Custom, and select "Create Action". In the code editor paste the following code:
exports.onExecutePostLogin = async (event, api) => {
// Check if the user has roles defined in the app metadata
if (event.user && event.user.app_metadata) {
api.idToken.setCustomClaim(`http://localhost:5173/app_metadata`, event.user.app_metadata);
}
};
In the above example the http://localhost:5173 portion of the template literal is your namespace. This will need to be adjusted in a production environment.
Save the draft, and click deploy.
Go to Actions --> Flows, and select Login. In the "Add Action" panel, select "Custom", and drag over the new action you just created, in between Start and Complete.
To authorize requests to your server, you can use the allow()
middleware function which will prevent users without the specified permissions to access the endpoint.
// example
server.get(
'/authorized-to-read',
allow(['read:resource'], (req, res) => {
res.status(200).send('resources sent!')
})
)
Once you create an account you can easily retrieve the SDK environment variables from the console.
From the main dashboard in Atlas, create a new project and follow the steps to create a new database. Select the database from the side menu and click Connect. Select the first option (NodeJs Driver). The connection string looks something like this:
mongodb+srv://<user>:<password>@<database>.mongodb.net/<name>
Before you run the applications, make sure all the environment variables have been defined and are correct or else you will likely see errors.
# run dev server (from root project folder)
npm run dev
# on a different terminal window, run web client
cd client && npm run dev
Make sure to add the following values to the .env file to make sure we have callback URIs for the Stripe API. You will also need to add the STRIPE_WEBHOOK_SIGNING_SECRET found in the Stripe dashboard.
Examples:
STRIPE_SUCCESS_URI='http://localhost:8080/stripe/confirm?status=success'
STRIPE_FAILURE_URI='http://localhost:8080/stripe/confirm?status=failure'
STRIPE_SUCCESS_REDIRECT='http://localhost:5173/payment-confirmation?status=success'
STRIPE_FAILURE_REDIRECT='http://localhost:5173/payment-confirmation?status=failure'
STRIPE_USER_PORTAL_CALLBACK_URI='http://localhost:5173'
STRIPE_WEBHOOK_SIGNING_SECRET="your secret here"
STRIPE_PRICE_LOOKUP_KEY="price id here"
The user goes to the subscription page which details the subscription and offers a checkout button. The checkout button directs the user to the stripe/create-checkout-session route which will then use the stripe api to redirect the user to Stripe's secure checkout form. Once complete the user will be redirected back to the app.
Account management is handled via Stripe's assets, so we have created a route that will redirect the user to stripe, and using our STRIPE_USER_PORTAL_CALLBACK_URI Stripe will redirect the user back to our app when they are done managing subscriptions.
- Add env variables
- Configure Stripe
- Stripe CLI for testing
We use the Auth0 API to attach subscription status metadata to the Auth0 user. If the user is authenticated but not subscribed, they are are re-routed to the subscription page, where they have to sign up in order to access content.
Auth0 needs to be configured to provide app_metadata, which is also necessary for the admin feature.