This application is deployed at https://go.d1m.dev
This is an implementation of Go Links powered by Next.js, GraphQL through PostGraphile and Auth0.
In short, Go Links are a type of URL Shorteners. You can create an alias that points to an URL and will redirect the user to that URL.
Please check the Related section to have a glance on how other companies and universities leverage go links.
- golinks.ncsu.edu
- go.middlebury.edu
- brown.edu/go
- github.com/kellegous/go
- The quick and simple guide to go links
- Google's go link culture
These are just a few ideas that come in my mind. Please feel free to suggest more features by creating an Issue. I'd love to hear your thoughts.
Contributions for the following are very welcome.
- Create Links
- Delete Links
- Edit Links
- Redirect Links
- Auth
- Powered by Auth0
- Security
- Row Level Security using Auth0 Roles and Permissions
- Link Description
- Link Suggestion on 404
- Link Usage Metrics
- Number: Usage Total Count
- Graph: Usage of last 14 days
- Link Ownership
- Link Parameters
- Private Links
- Temporary Links
- Random Alias
- Chrome Plugin
A Docker Image is available at Docker Hub: https://hub.docker.com/r/armand1m/golinks
Make sure to change the manifests accordingly to your environment.
Check the ./kubernetes folder for k8s manifests content.
These manifests deploy the application together with a cloud_sql_proxy sidecar to allow networking with Google Cloud SQL.
Create a secret to keep the connection string:
kubectl create secret generic golinks-database \
--from-literal=connectionstring='postgres://<user>:<pass>@<host>:5432/golinks'Create a secret to keep the Cloud SQL service account:
kubectl create secret generic cloudsql-service-account \
--from-file=service-account.json=./service-account.jsonCreate a secret to keep Auth0 ids and secrets:
kubectl create secret generic auth0-properties \
--from-literal=client_id='auth0-app-client-id' \
--from-literal=client_secret='auth0-app-client-secret' \
--from-literal=cookie_secret='random-cookie-secret'Create a deployment and service:
kubectl apply -f ./kubernetes/deployment.yaml
kubectl apply -f ./kubernetes/service.yamlMake sure to change the manifests accordingly to your environment.
Create the virtual service and destination rules:
kubectl apply -f ./kubernetes/istio/virtual-service.yaml
kubectl apply -f ./kubernetes/istio/destination-rule.yamlThis app leverages Auth0 as an Identity provider. Auth0 is used to manage users and their permissions to access and modify data in this application.
In the future, these steps will be automated through the Auth0 Provider for Terraform.
Create a Regular Web Application:
It's important that it is a Regular Web Application since this is a Next.js app. It also relies on the accessToken being a JWT token, so the server can extract roles and permissions from Auth0.
Setup callback and logout urls:
Setup the callback and logout url's to redirect to your domain + the route.
E.g.:
Callback URL: http://localhost:3000/api/callback
Post Logout Redirect URL: http://localhost:3000
Keep the audience, domain, client_id and client_secret for easy access, as you'll need these to spin up the server (both in development and production)
Create the following roles and permissions:
I'm using YAML here to give a better representation of how the permissions should be setup in Auth0 roles:
role: editor
permissions:
- create:golinks
- update:golinks
- delete:golinksrole: viewer
permissions:
- read:golinksThese roles are used by Postgraphile when setting up a transaction for a query in a specific request context. This allows us to leverage Row Level Security through Postgres Policies to avoid access to data in the source of truth.
These roles are also used in the frontend to avoid rendering features for the user.
Create an user and assign roles:
Create an user and assign both the editor and viewer roles so you have access to all features.
armand1m/golinks is a Next.js app using GraphQL.
The database must be a Postgres 12.x database as the GraphQL API is generated using Postgraphile and leverages features like Row Level Security only available from Postgres 9.6+.
PostGraphile is then used as a NPM module and served through Next.js routes itself, so you don't have to worry about CORS, and the API is initialized together with the Next.js application.
GraphQL Type definitions are generated on application startup during development, so make sure your database executed the initialization scripts during startup as PostGraphile will infer them to the generate the type-defs.graphqls file. (This brings some caveats when making breaking changes in the database schema during development time, but easy to overcome.)
graphql-let then is used to generate type definitions in Typescript for development use.
For development, we use the official postgres docker image. This image comes with a feature that initializes the database when provided a folder with scripts.
When started without a volume setup, the image will execute all the .sql scripts in the ./database folder.
Start the database:
docker-compose up -d dbPrepare the project and run in development mode:
yarn
yarn devAccess http://localhost:3000 and you should have a live development environment running.
cat > ./.env.local <<EOL
DATABASE_CONNECTION_STRING=postgres://dev:dev@db:5432/golinks
DATABASE_SCHEMA=public
NODE_ENV=production
AUTH0_DOMAIN=<auth0-domain>
AUTH0_AUDIENCE=<auth0-audience>
AUTH0_CLIENT_ID=<auth0-client-id>
AUTH0_CLIENT_SECRET=<auth0-client-secret>
AUTH0_COOKIE_SECRET=<auth0-cookie-secret>
AUTH0_COOKIE_DOMAIN=localhost
AUTH0_REDIRECT_URL=http://localhost:3000/api/callback
AUTH0_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
HOSTNAME=http://localhost:3000
LOGONAME=go.mydomain.dev
EOL
docker-compose upAccess http://localhost:3000
# Environment Variables for the Application
cat > ./.env.cloud <<EOL
DATABASE_CONNECTION_STRING=postgres://<postgraphile-user>:<postgraphile-user-password>@db:5432/golinks
DATABASE_SCHEMA=public
NODE_ENV=production
AUTH0_DOMAIN=<auth0-domain>
AUTH0_AUDIENCE=<auth0-audience>
AUTH0_CLIENT_ID=<auth0-client-id>
AUTH0_CLIENT_SECRET=<auth0-client-secret>
AUTH0_COOKIE_SECRET=<auth0-cookie-secret>
AUTH0_COOKIE_DOMAIN=localhost
AUTH0_REDIRECT_URL=http://localhost:3000/api/callback
AUTH0_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
HOSTNAME=http://localhost:3000
LOGONAME=go.mydomain.dev
EOL
# Environment Variables for the Cloud SQL Proxy
export GCP_KEY_PATH="~/cloud-sql-service-account.json"
export CLOUDSQL_INSTANCE="<gcp-project>:<gcp-region>:<cloud-sql-instance-name>=tcp:0.0.0.0:5432"
docker-compose -f ./docker-compose-cloud-sql.yml up./clean-local-database.shdocker build . -t armand1m/golinksMIT © Armando Magalhaes