Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Bootstrapping

Erik Roberts edited this page Mar 7, 2023 · 12 revisions

When you first spin up the Glimpse API, the database is going to be empty. With no permissions and no users, you will not be able to do anything with the API. You need to bootstrap your database with some initial data to make the project usable. There are a number of ways you can do this.

ℹ️ This article assumes you have already generated your database schema. If not, read the Prisma Migrate section.

CLI

The API repository comes with a CLI which you can run via npm run cli. This CLI will help you in quickly bootstrapping your database with just a couple commands and is the recommended way to get started (particularly for development).

Here are the steps.

  1. Clone this repository: git clone https://github.com/rpitv/glimpse-api.git
  2. Enter the repository directory: cd glimpse-api
  3. Install dependencies: npm install
  4. Copy the sample .env file: cp .env.sample .env
  5. Edit your .env file to contain the proper DATABASE_URL URI.
  6. Start the CLI: npm run cli
  7. Run the commands groups and user in the CLI and follow any prompted steps.

Here is a preview:

Demo of the CLI

Pros

  • Database is bootstrapped for you with some initial groups, permissions, and a user account with just two commands.
  • If not using Docker, the command works out-of-the-box.
  • You can generate an admin account with a password.

Cons

  • If using Docker, you must clone this repository locally and set up your .env file with the DATABASE_URL property set.
  • You must expose your database port to the CLI client machine (temporarily) to use the CLI.
  • You can only create one account via the CLI (although more can be created with the GraphQL API afterwards).

Manual

If you do not want to use the CLI, you can bootstrap the database yourself by manually inserting data, however it's going to take some more steps. You will need a PostgreSQL client to do this; any client works. In production, you'll likely want to use the psql command. In development, your IDE may have a database client built-in or available as a plugin.

ℹ️ If your database is running in Docker, your container will likely have a psql client available within it. The following command should work with the default docker-compose.yml file we have provided: docker exec -it <CONTAINER_NAME> psql -U postgres

Once you have a client and are connected to your database, here are the steps you'll want to take:

  1. Create Groups called "Guest", "Member", and "Admin" within the groups table.
    INSERT INTO "groups" ("name") VALUES ('Guest'), ('Member'), ('Admin');
  2. Create a "manage all" permission for the "Guest" and "Admin" groups. The Guest group's permission is temporary and lets us generate an account with a password via the API.
    INSERT INTO "group_permissions" ("group", "action", "subject") VALUES (1, 'manage', '{"all"}'), (3, 'manage', '{"all"}');
  3. You can now close your database client. Start the API and navigate to the GraphQL playground. If the playground isn't running, open your preferred HTTP request client (e.g. cURL, Postman).
  4. Send a GraphQL request to create a new User account with a password.
    mutation {
      createUser(input:{
        username: "username",
        mail: "user@example.com",
        password: "password"
      }) {
        id
      }
    }
  5. Add your new user to the Admin group.
    mutation {
      createUserGroup(input:{
        userId: 1,
        groupId: 3
      }) {
        id
      }
    }
  6. Log into the API. This will respond with a session cookie which you must include in subsequent requests. This is done automatically for you if the playground is running and configured correctly. If you don't get a session cookie, check if the HTTPS config variable is set and whether you're sending your requests to an HTTPS server.
    mutation {
      loginLocal(username: "username", password: "password") {
        id
      }
    }
  7. Delete the Guest permission that was granting "manage all" access.
    mutation {
      deleteGroupPermission(id:1) {
        id
      }
    }
  8. You can now create the necessary groups, users, permissions, etc. for your use-case via the GraphQL API, so long as you're logged into your account.

Alternative Methods

Granting "manage all" permissions to the Guest account may not be ideal depending on your scenario. Here are some alternatives.

Generate a Password Externally

Passwords are hashed with argon2id. So long as you use the argon2id hashing algorithm (and ideally use the same parameters), you can hash your password on a third-party website (e.g. https://www.coderstool.com/argon2-hash-generator) and then insert it manually.

  1. Create Groups called "Guest", "Member", and "Admin" within the groups table.
    INSERT INTO "groups" ("name") VALUES ('Guest'), ('Member'), ('Admin');
  2. Create a "manage all" permission for the "Admin" group.
    INSERT INTO "group_permissions" ("group", "action", "subject") VALUES (3, 'manage', '{"all"}');
  3. Create a new User with your hashed password
    INSERT INTO "users" ("username", "mail", "password") VALUES ('username', 'user@example.com', '$argon2id$v=19$m=32768,t=4,p=1$aG94aXYxdTlkZjAwMDAwMA$AfzQGvPM8X/9S7f5C5WPqw');
  4. Add your User to the "Admin" group.
    INSERT INTO "user_groups" ("user", "group") VALUES (1, 3);
  5. You can now close your database client. Start the API and navigate to the GraphQL playground. If the playground isn't running, open your preferred HTTP request client (e.g. cURL, Postman).
  6. Log into the API. This will respond with a session cookie which you must include in subsequent requests. This is done automatically for you if the playground is running and configured correctly. If you don't get a session cookie, check if the HTTPS config variable is set and whether you're sending your requests to an HTTPS server.
    mutation {
      loginLocal(username: "username", password: "password") {
        id
      }
    }
  7. You can now create the necessary groups, users, permissions, etc. for your use-case via the GraphQL API, so long as you're logged into your account.

Login via Discord

If you have "Login with Discord" setup, you can bypass using passwords altogether. This will require you to have your Discord app set up correctly, and may require you to log in through the UI.

  1. Create Groups called "Guest", "Member", and "Admin" within the groups table.
    INSERT INTO "groups" ("name") VALUES ('Guest'), ('Member'), ('Admin');
  2. Create a "manage all" permission for the "Admin" group.
    INSERT INTO "group_permissions" ("group", "action", "subject") VALUES (3, 'manage', '{"all"}');
  3. Create a new User with your Discord account ID
    INSERT INTO "users" ("username", "mail", "discord") VALUES ('username', 'user@example.com', '255781419387846657');
  4. Add your User to the "Admin" group.
    INSERT INTO "user_groups" ("user", "group") VALUES (1, 3);
  5. You can now close your database client. Start the API and then log into it via Discord OAuth at /auth/discord. This will likely be easiest through the user interface in your browser. Read the Authentication article for more information.
  6. You can now create the necessary groups, users, permissions, etc. for your use-case via the GraphQL API, so long as you're logged into your account.

Pros

  • No external tools are strictly required. All you need is your database and API container(s).
  • Since you're interacting directly with the database, you can create whatever you want just via your database client.
  • You do not necessarily have to expose your database to external traffic.

Cons

  • Will likely take longer to setup.
  • Some knowledge about the internal database structure, PostgreSQL, and SQL and GraphQL syntax may be helpful.
  • An initial set of permissions is not generated for you.