forked from NotNet/gluestick
Merge remote-tracking branch 'origin/nix'
This commit is contained in:
commit
3b11a40928
|
@ -38,3 +38,6 @@ database.db*
|
||||||
|
|
||||||
# graphql-codegen
|
# graphql-codegen
|
||||||
src/__generated__
|
src/__generated__
|
||||||
|
|
||||||
|
# NixOS
|
||||||
|
result
|
||||||
|
|
37
README.md
37
README.md
|
@ -50,6 +50,7 @@ After cloning, create an `.env.local` with the following contents (in `key=value
|
||||||
- `LDAP_BIND_PASSWORD`: the password of the bind user
|
- `LDAP_BIND_PASSWORD`: the password of the bind user
|
||||||
- `BASE_DOMAIN`: the domain gluestick is deployed on, with a protocol and trailing slash
|
- `BASE_DOMAIN`: the domain gluestick is deployed on, with a protocol and trailing slash
|
||||||
- This domain will be used for OAuth redirects - if you are testing locally, set it to `http://localhost:3000/`
|
- This domain will be used for OAuth redirects - if you are testing locally, set it to `http://localhost:3000/`
|
||||||
|
- `DATABASE_URL`: a Prisma-like path to your database
|
||||||
|
|
||||||
Example config:
|
Example config:
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ GITHUB_TOKEN=redacted
|
||||||
GITHUB_ORG=n2pm
|
GITHUB_ORG=n2pm
|
||||||
|
|
||||||
BASE_DOMAIN=https://gluestick.n2.pm/
|
BASE_DOMAIN=https://gluestick.n2.pm/
|
||||||
|
DATABASE_URL=file:./database.db
|
||||||
```
|
```
|
||||||
|
|
||||||
### Generating code
|
### Generating code
|
||||||
|
@ -93,7 +95,7 @@ export GRAPHQL_CODEDGEN_AUTH=...
|
||||||
Then, generate the GraphQL and database code:
|
Then, generate the GraphQL and database code:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
npm run graphql-codegen
|
GRAPHQL_USE_INTROSPECTION=true npm run graphql-codegen
|
||||||
npm run prisma-generate
|
npm run prisma-generate
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -108,7 +110,36 @@ npm run start
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
You'll want to run these two commands at the same time:
|
### Generating GraphQL code
|
||||||
|
|
||||||
|
Because the LLDAP GraphQL API is locked behind authentication, and of a quirk with `graphl-codegen` configuration files, we need to set a temporary environment variable to generate GraphQL code. If not using introspection, you will need a running LLDAP server.
|
||||||
|
|
||||||
|
Run the `get-token.js` helper script and set the environment variable from its output:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
node get-token.js
|
||||||
|
export GRAPHQL_CODEDGEN_AUTH=...
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, generate the GraphQL code:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm run graphql-codegen
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use introspection, set `GRAPHQL_USE_INTROSPECTION=true` before generating the code. You won't need to set the auth environment variable in this case.
|
||||||
|
|
||||||
|
### Working with Prisma
|
||||||
|
|
||||||
|
gluestick uses [Prisma](https://www.prisma.io/) for accessing the database. If you will be modifying the database schema, you will need to work with it. Consider taking some time to familiarize yourself with the [Prisma CLI](https://www.prisma.io/docs/reference/api-reference/command-reference) first.
|
||||||
|
|
||||||
|
When first cloning, generate the Prisma client:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm run prisma-generate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the server
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Next.js hot reload
|
# Next.js hot reload
|
||||||
|
@ -119,5 +150,3 @@ npm run dev | pino-pretty
|
||||||
# Only required if working on GraphQL code
|
# Only required if working on GraphQL code
|
||||||
npm run graphql-codegen -- -w
|
npm run graphql-codegen -- -w
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're interacting with the database, take some time to familiarize yourself with the [Prisma CLI](https://www.prisma.io/docs/reference/api-reference/command-reference).
|
|
||||||
|
|
26
codegen.ts
26
codegen.ts
|
@ -4,24 +4,32 @@ import { CodegenConfig } from "@graphql-codegen/cli";
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
dotenv.config({ path: ".env.local" });
|
dotenv.config({ path: ".env.local" });
|
||||||
|
|
||||||
|
const useIntrospection = ["1", "true"].includes(
|
||||||
|
process.env.GRAPHQL_USE_INTROSPECTION?.toLowerCase() ?? ""
|
||||||
|
);
|
||||||
|
|
||||||
const config: CodegenConfig = {
|
const config: CodegenConfig = {
|
||||||
schema: {
|
schema: useIntrospection
|
||||||
[`http://${process.env.LDAP_HOST}:17170/api/graphql`]: {
|
? "introspection.json"
|
||||||
headers: {
|
: {
|
||||||
// can't make the request automatically (await on top level)
|
[`http://${process.env.LDAP_HOST}:17170/api/graphql`]: {
|
||||||
Authorization: `Bearer ${process.env.GRAPHQL_CODEGEN_AUTH}`
|
headers: {
|
||||||
}
|
// can't make the request automatically (await on top level)
|
||||||
}
|
Authorization: `Bearer ${process.env.GRAPHQL_CODEGEN_AUTH}`
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
documents: ["src/**/*.ts", "src/**/*.tsx"],
|
documents: ["src/**/*.ts", "src/**/*.tsx"],
|
||||||
generates: {
|
generates: {
|
||||||
"./src/__generated__/": {
|
"./src/__generated__/": {
|
||||||
preset: "client",
|
preset: "client",
|
||||||
plugins: [],
|
|
||||||
presetConfig: {
|
presetConfig: {
|
||||||
gqlTagName: "gql"
|
gqlTagName: "gql"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"introspection.json": {
|
||||||
|
plugins: ["introspection"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ignoreNoDocuments: true
|
ignoreNoDocuments: true
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681202837,
|
||||||
|
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1682656005,
|
||||||
|
"narHash": "sha256-fYplYo7so1O+rSQ2/aS+SbTPwLTeoUXk4ekKNtSl4P8=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "6806b63e824f84b0f0e60b6d660d4ae753de0477",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
{
|
||||||
|
description =
|
||||||
|
"NotNet's one stop shop for authentication and account onboarding";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
let
|
||||||
|
packages = flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages."${system}";
|
||||||
|
|
||||||
|
# I really cannot be assed to pick this apart
|
||||||
|
inputs = with pkgs; [ vips pkg-config python3 ];
|
||||||
|
|
||||||
|
# https://github.com/prisma/prisma/issues/3026#issuecomment-927258138
|
||||||
|
prismaHook = with pkgs; ''
|
||||||
|
export PRISMA_MIGRATION_ENGINE_BINARY="${prisma-engines}/bin/migration-engine"
|
||||||
|
export PRISMA_QUERY_ENGINE_BINARY="${prisma-engines}/bin/query-engine"
|
||||||
|
export PRISMA_QUERY_ENGINE_LIBRARY="${prisma-engines}/lib/libquery_engine.node"
|
||||||
|
export PRISMA_INTROSPECTION_ENGINE_BINARY="${prisma-engines}/bin/introspection-engine"
|
||||||
|
export PRISMA_FMT_BINARY="${prisma-engines}/bin/prisma-fmt"
|
||||||
|
'';
|
||||||
|
in rec {
|
||||||
|
packages.gluestick = pkgs.buildNpmPackage {
|
||||||
|
pname = "gluestick";
|
||||||
|
version = "0.1.0";
|
||||||
|
src = ./.;
|
||||||
|
npmDepsHash = "sha256-keOreamXKunlJzU2AKJo0J02ZxQrjLdoCIMCaiwEU4Y=";
|
||||||
|
|
||||||
|
nativeBuildInputs = inputs;
|
||||||
|
buildInputs = inputs;
|
||||||
|
|
||||||
|
preBuild = ''
|
||||||
|
${prismaHook}
|
||||||
|
|
||||||
|
# Use the introspection.json, because we can't connect to the API at build time
|
||||||
|
GRAPHQL_USE_INTROSPECTION=true npm run graphql-codegen
|
||||||
|
npm run prisma-generate
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r .next/standalone $out/server
|
||||||
|
cp -r .next/static $out/server/.next/static
|
||||||
|
cp -r public $out/server/public
|
||||||
|
cp -r prisma $out/prisma
|
||||||
|
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cat > $out/bin/gluestick <<EOF
|
||||||
|
#!${pkgs.stdenv.shell}
|
||||||
|
${prismaHook}
|
||||||
|
${pkgs.nodejs}/bin/node $out/server/server.js \$@
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/gluestick
|
||||||
|
|
||||||
|
cat > $out/bin/prisma <<EOF
|
||||||
|
#!${pkgs.stdenv.shell}
|
||||||
|
${prismaHook}
|
||||||
|
|
||||||
|
${pkgs.nodePackages.prisma}/bin/prisma \$@
|
||||||
|
EOF
|
||||||
|
chmod +x $out/bin/prisma
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
description =
|
||||||
|
"NotNet's one stop shop for authentication and account onboarding";
|
||||||
|
homepage = "https://git.n2.pm/NotNet/gluestick";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
apps.gluestick = flake-utils.lib.mkApp {
|
||||||
|
name = "gluestick";
|
||||||
|
drv = packages.gluestick;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
inputsFrom = [ packages.gluestick ];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
${prismaHook}
|
||||||
|
|
||||||
|
if [ -f .env.local ]; then
|
||||||
|
set -a
|
||||||
|
source .env.local
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in packages // {
|
||||||
|
nixosModule = { config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.gluestick;
|
||||||
|
pkg = self.packages.${pkgs.system}.gluestick;
|
||||||
|
in {
|
||||||
|
options.services.gluestick = {
|
||||||
|
enable = mkEnableOption "gluestick";
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "gluestick";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "gluestick";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 3000;
|
||||||
|
};
|
||||||
|
|
||||||
|
envFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/gluestick/.env.local";
|
||||||
|
};
|
||||||
|
|
||||||
|
databaseFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/gluestick/database.db";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.gluestick = {
|
||||||
|
description = "gluestick";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
export DATABASE_URL="file:${cfg.databaseFile}"
|
||||||
|
${pkg}/bin/prisma migrate deploy --schema=${pkg}/prisma/schema.prisma
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
export PORT=${toString cfg.port}
|
||||||
|
export NODE_ENV=production
|
||||||
|
export DATABASE_URL="file:${cfg.databaseFile}"
|
||||||
|
${pkg}/bin/gluestick
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
Restart = "always";
|
||||||
|
WorkingDirectory = "/var/lib/gluestick";
|
||||||
|
EnvironmentFile = cfg.envFile;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users = mkIf (cfg.user == "gluestick") {
|
||||||
|
gluestick = {
|
||||||
|
home = "/var/lib/gluestick";
|
||||||
|
createHome = true;
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
groups = mkIf (cfg.group == "gluestick") { gluestick = { }; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,8 @@
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
experimental: {
|
experimental: {
|
||||||
appDir: true
|
appDir: true
|
||||||
}
|
},
|
||||||
|
output: "standalone"
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = nextConfig;
|
module.exports = nextConfig;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "^3.3.1",
|
"@graphql-codegen/cli": "^3.3.1",
|
||||||
"@graphql-codegen/client-preset": "^3.0.1",
|
"@graphql-codegen/client-preset": "^3.0.1",
|
||||||
|
"@graphql-codegen/introspection": "^3.0.1",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.1",
|
||||||
"pino-pretty": "^10.0.0",
|
"pino-pretty": "^10.0.0",
|
||||||
"prisma": "^4.13.0"
|
"prisma": "^4.13.0"
|
||||||
|
@ -1380,6 +1381,20 @@
|
||||||
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@graphql-codegen/introspection": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@graphql-codegen/introspection/-/introspection-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-D6vJQTEL/np4EmeUHm5spLK59cr+AMXEoLRoTI+dagFzlHYDTfXZH6F7uhKaakxcj0SAQhIWKvGMggotUdEtyg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@graphql-codegen/plugin-helpers": "^4.1.0",
|
||||||
|
"@graphql-codegen/visitor-plugin-common": "^3.0.1",
|
||||||
|
"tslib": "~2.5.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@graphql-codegen/plugin-helpers": {
|
"node_modules/@graphql-codegen/plugin-helpers": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-4.2.0.tgz",
|
||||||
|
@ -9265,6 +9280,17 @@
|
||||||
"tslib": "~2.5.0"
|
"tslib": "~2.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@graphql-codegen/introspection": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@graphql-codegen/introspection/-/introspection-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-D6vJQTEL/np4EmeUHm5spLK59cr+AMXEoLRoTI+dagFzlHYDTfXZH6F7uhKaakxcj0SAQhIWKvGMggotUdEtyg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@graphql-codegen/plugin-helpers": "^4.1.0",
|
||||||
|
"@graphql-codegen/visitor-plugin-common": "^3.0.1",
|
||||||
|
"tslib": "~2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@graphql-codegen/plugin-helpers": {
|
"@graphql-codegen/plugin-helpers": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-4.2.0.tgz",
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "^3.3.1",
|
"@graphql-codegen/cli": "^3.3.1",
|
||||||
"@graphql-codegen/client-preset": "^3.0.1",
|
"@graphql-codegen/client-preset": "^3.0.1",
|
||||||
|
"@graphql-codegen/introspection": "^3.0.1",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.1",
|
||||||
"pino-pretty": "^10.0.0",
|
"pino-pretty": "^10.0.0",
|
||||||
"prisma": "^4.13.0"
|
"prisma": "^4.13.0"
|
||||||
|
|
|
@ -4,7 +4,7 @@ generator client {
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "sqlite"
|
provider = "sqlite"
|
||||||
url = "file:./database.db"
|
url = env("DATABASE_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model AuthTicket {
|
model AuthTicket {
|
||||||
|
|
Loading…
Reference in New Issue