oauth test

This commit is contained in:
CJ_Clippy 2025-01-16 12:23:58 -08:00
parent 1469545429
commit c3f5d612c3
30 changed files with 543 additions and 139 deletions

View File

@ -1,16 +1,14 @@
devbox for shareable development environment tooling devbox for shareable development environment tooling
git monorepo for housing separate node packages within a single repository git monorepo for housing separate packages within a single repository (see ./services and ./packages)
TypeScript
pnpm for package management and workspaces (separate node packages.) pnpm for package management and workspaces (separate node packages.)
Kubernetes for Development using Tiltfile Phoenix framework
Kubernetes for Production, deployed using FluxCD docker-compose for containerized development
Kubernetes deployed to Hetzner using https://github.com/kube-hetzner/terraform-hcloud-kube-hetzner Kamal for deployments
ggshield for preventing git commits containing secrets ggshield for preventing git commits containing secrets

View File

@ -8,16 +8,19 @@ See ./ARCHITECTURE.md for an overview of the infrastructure components.
## Getting Started ## Getting Started
I'm working towards a better development experience with devbox and Tilt. This process is in a state of flux and is likely to be broken. The main gist is as follows.
The main gist is as follows 1. install [docker](https://docs.docker.com/engine/install) `wget -O- get.docker.com | bash`
1. Install [devbox](https://www.jetify.com/devbox/docs/installing_devbox/) `curl -fsSL https://get.jetify.com/devbox | bash`
1. Install [devbox](https://www.jetify.com/devbox/docs/installing_devbox/)
2. Install development environment & packages using devbox. 2. Install development environment & packages using devbox.
devbox install devbox install
3.
3. Run `docker compose up --watch`
4. Visit http://localhost:4000
If all went well, editing source code will automatically affect the website running in your browser.
## backup/restore dev database ## backup/restore dev database
@ -38,8 +41,7 @@ Use devbox helper script
Keeping track of metrics we want to scrape using Prometheus Keeping track of metrics we want to scrape using Prometheus
### Uppy
https://uppy.fp.sbtp.xyz/metrics

View File

@ -2,150 +2,150 @@
"lockfile_version": "1", "lockfile_version": "1",
"packages": { "packages": {
"ffmpeg@latest": { "ffmpeg@latest": {
"last_modified": "2024-07-24T00:53:51Z", "last_modified": "2025-01-07T09:15:50Z",
"resolved": "github:NixOS/nixpkgs/4f02464258baaf54992debfd010a7a3662a25536#ffmpeg", "resolved": "github:NixOS/nixpkgs/8c9fd3e564728e90829ee7dbac6edc972971cd0f#ffmpeg",
"source": "devbox-search", "source": "devbox-search",
"version": "6.1.1", "version": "7.1",
"systems": { "systems": {
"aarch64-darwin": { "aarch64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "bin", "name": "bin",
"path": "/nix/store/7jl394717pnlj5jy8n46jq65sw1gwb20-ffmpeg-6.1.1-bin", "path": "/nix/store/m48ypyjnl04mqigi6fbxa7k2c5bsvazz-ffmpeg-7.1-bin",
"default": true "default": true
}, },
{ {
"name": "man", "name": "man",
"path": "/nix/store/ma1ssbkbwrasdgsyp0y3x6jbc72pp9s7-ffmpeg-6.1.1-man", "path": "/nix/store/10ncvfz8srnzckq16bn14wffcx8j04ki-ffmpeg-7.1-man",
"default": true "default": true
}, },
{
"name": "out",
"path": "/nix/store/smq7vi0562incbgwf4cbx10i0y46jsbc-ffmpeg-6.1.1"
},
{ {
"name": "data", "name": "data",
"path": "/nix/store/289ikv8ld8whmixs3r4qd4r878mkjmm9-ffmpeg-6.1.1-data" "path": "/nix/store/rqbsc9zyzi988hwcd423qdh1vh40zlzc-ffmpeg-7.1-data"
}, },
{ {
"name": "dev", "name": "dev",
"path": "/nix/store/r8y6va82y6libjw065gkn5gr51715gac-ffmpeg-6.1.1-dev" "path": "/nix/store/6ml3pn92nbmnc40s5jfpr84y65ysizk3-ffmpeg-7.1-dev"
}, },
{ {
"name": "doc", "name": "doc",
"path": "/nix/store/yasff9ggma6myg47sm805idfxnz0zkac-ffmpeg-6.1.1-doc" "path": "/nix/store/ni6gri7m1pavfjxx0yfj1msvb0cfasgg-ffmpeg-7.1-doc"
}, },
{ {
"name": "lib", "name": "lib",
"path": "/nix/store/pmv9jg541b2valk47vh7q40m1p8xr7ik-ffmpeg-6.1.1-lib" "path": "/nix/store/2v2rr9dmq4grzwmg4zcsxrmbdcshks7m-ffmpeg-7.1-lib"
},
{
"name": "out",
"path": "/nix/store/nvccyp4dra8f92ywd00lk3ra121gj162-ffmpeg-7.1"
} }
], ],
"store_path": "/nix/store/7jl394717pnlj5jy8n46jq65sw1gwb20-ffmpeg-6.1.1-bin" "store_path": "/nix/store/m48ypyjnl04mqigi6fbxa7k2c5bsvazz-ffmpeg-7.1-bin"
}, },
"aarch64-linux": { "aarch64-linux": {
"outputs": [ "outputs": [
{ {
"name": "bin", "name": "bin",
"path": "/nix/store/6ydyry316fcc59iy80zpnxnsrh9f18ki-ffmpeg-6.1.1-bin", "path": "/nix/store/lj99z3ldzka2slgm94w2yl8cjkphn4m3-ffmpeg-7.1-bin",
"default": true "default": true
}, },
{ {
"name": "man", "name": "man",
"path": "/nix/store/k1frp52lx3ycwbdgliwcrmb81zm4n10n-ffmpeg-6.1.1-man", "path": "/nix/store/gisda8d2pifrrjw0yirrs0x2cyn6b96i-ffmpeg-7.1-man",
"default": true "default": true
}, },
{
"name": "dev",
"path": "/nix/store/rdh4mv7fnmj79a4dp9rfqnd711y9inpv-ffmpeg-6.1.1-dev"
},
{
"name": "doc",
"path": "/nix/store/vam8a1591x7bkqjljvwsral2v72xwa77-ffmpeg-6.1.1-doc"
},
{
"name": "lib",
"path": "/nix/store/k2mdb9lh6qjb63pizcc0lv7kzakgvcm1-ffmpeg-6.1.1-lib"
},
{ {
"name": "out", "name": "out",
"path": "/nix/store/6z17gry0dn1yxr3r36fk87sxnddcjg66-ffmpeg-6.1.1" "path": "/nix/store/pc332zx12j2fqf5m9mdhhs1rwksbk2fk-ffmpeg-7.1"
}, },
{ {
"name": "data", "name": "data",
"path": "/nix/store/qxyrrzdl4svxs3dfszsmi2mky4vrzvfa-ffmpeg-6.1.1-data" "path": "/nix/store/4yhsn6lrfn91dk1kq9wyyd71p4hcfans-ffmpeg-7.1-data"
},
{
"name": "dev",
"path": "/nix/store/71103mmkxhzzmbj9mpzsrzbp988z3p98-ffmpeg-7.1-dev"
},
{
"name": "doc",
"path": "/nix/store/k9cc4d60frcn27zapkzhag5h9r0ig5xa-ffmpeg-7.1-doc"
},
{
"name": "lib",
"path": "/nix/store/dgcmpc8az51a4d2bxgrmfz8zlmvqxwa5-ffmpeg-7.1-lib"
} }
], ],
"store_path": "/nix/store/6ydyry316fcc59iy80zpnxnsrh9f18ki-ffmpeg-6.1.1-bin" "store_path": "/nix/store/lj99z3ldzka2slgm94w2yl8cjkphn4m3-ffmpeg-7.1-bin"
}, },
"x86_64-darwin": { "x86_64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "bin", "name": "bin",
"path": "/nix/store/84yjd9p94kknxpdn974ksb7y28l6paq4-ffmpeg-6.1.1-bin", "path": "/nix/store/z44kr817zx99vi2cc204i06cnmz83f1n-ffmpeg-7.1-bin",
"default": true "default": true
}, },
{ {
"name": "man", "name": "man",
"path": "/nix/store/r1g3627b14nqpz4aqfp87ba0fh49ar5k-ffmpeg-6.1.1-man", "path": "/nix/store/slrha22nqrx2xw009hd37svv2nvpp26i-ffmpeg-7.1-man",
"default": true "default": true
}, },
{ {
"name": "data", "name": "data",
"path": "/nix/store/dv5lc67c3xykza11q5pwk4vivnsdswmw-ffmpeg-6.1.1-data" "path": "/nix/store/n3xm2rr1k1ari7ysbp9jhg65pih28x6x-ffmpeg-7.1-data"
}, },
{ {
"name": "dev", "name": "dev",
"path": "/nix/store/f0qcama09w9kri8hqvn0lk89zck4978v-ffmpeg-6.1.1-dev" "path": "/nix/store/59gcv4rfg38rqnazv1iq9jssjak2l3ih-ffmpeg-7.1-dev"
}, },
{ {
"name": "doc", "name": "doc",
"path": "/nix/store/7sg26fama7a6gpdm0kkphblzc2x03dfx-ffmpeg-6.1.1-doc" "path": "/nix/store/2cqa3lc75ciqzgmxjm36fd733f3gjgil-ffmpeg-7.1-doc"
}, },
{ {
"name": "lib", "name": "lib",
"path": "/nix/store/rhq35qgr8yvhygpj24wm14anidf9gmmc-ffmpeg-6.1.1-lib" "path": "/nix/store/ir47x8skj54wilcyz2x59am4y085lf6l-ffmpeg-7.1-lib"
}, },
{ {
"name": "out", "name": "out",
"path": "/nix/store/31q5qklv5jmv91sjs4ljmq45smi7ngxy-ffmpeg-6.1.1" "path": "/nix/store/gqw958wdgrbfsxczqf56vnq1iffg5qv1-ffmpeg-7.1"
} }
], ],
"store_path": "/nix/store/84yjd9p94kknxpdn974ksb7y28l6paq4-ffmpeg-6.1.1-bin" "store_path": "/nix/store/z44kr817zx99vi2cc204i06cnmz83f1n-ffmpeg-7.1-bin"
}, },
"x86_64-linux": { "x86_64-linux": {
"outputs": [ "outputs": [
{ {
"name": "bin", "name": "bin",
"path": "/nix/store/wnmy246m582splkkqwpgza390sa4m1k1-ffmpeg-6.1.1-bin", "path": "/nix/store/d1lv3x7iq129vb19ba9ph6k0yhy4fv34-ffmpeg-7.1-bin",
"default": true "default": true
}, },
{ {
"name": "man", "name": "man",
"path": "/nix/store/hqq9mmrwrbazfdcsmd2dd3jgpvpsyj5p-ffmpeg-6.1.1-man", "path": "/nix/store/qqgvvfw2gqp47zl5v9jhdsl8mb77l909-ffmpeg-7.1-man",
"default": true "default": true
}, },
{
"name": "doc",
"path": "/nix/store/gmfj9af6za9i2830cgbj1qazz2nir2vs-ffmpeg-7.1-doc"
},
{ {
"name": "lib", "name": "lib",
"path": "/nix/store/5jynrssm1bvrj3kskwgyyhb2069f8dwv-ffmpeg-6.1.1-lib" "path": "/nix/store/x8j2nr5qmikfaggl34wpm1dlldb7ik06-ffmpeg-7.1-lib"
}, },
{ {
"name": "out", "name": "out",
"path": "/nix/store/xdb4w2ccvig6020ish7qpl88i8fqg2ai-ffmpeg-6.1.1" "path": "/nix/store/cx89mypnxgk0q4dibacg7dsrb4w66mv9-ffmpeg-7.1"
}, },
{ {
"name": "data", "name": "data",
"path": "/nix/store/sw8wxzscsnxnvrwqzq4fqxvggcd1xic7-ffmpeg-6.1.1-data" "path": "/nix/store/5y8zk8fqpaammsnz2svgpdsayn4zlsn2-ffmpeg-7.1-data"
}, },
{ {
"name": "dev", "name": "dev",
"path": "/nix/store/p6jd7041xggbkwyfzrgsm8ccj370w1hz-ffmpeg-6.1.1-dev" "path": "/nix/store/qdz8aidi7rksr4g5cpxgz9iivrlsa247-ffmpeg-7.1-dev"
},
{
"name": "doc",
"path": "/nix/store/1dfla14f5g5xwmw3w5cjfnwdfr64qw7z-ffmpeg-6.1.1-doc"
} }
], ],
"store_path": "/nix/store/wnmy246m582splkkqwpgza390sa4m1k1-ffmpeg-6.1.1-bin" "store_path": "/nix/store/d1lv3x7iq129vb19ba9ph6k0yhy4fv34-ffmpeg-7.1-bin"
} }
} }
}, },
@ -246,124 +246,124 @@
} }
}, },
"nodejs@20": { "nodejs@20": {
"last_modified": "2024-07-07T07:43:47Z", "last_modified": "2024-12-23T21:10:33Z",
"plugin_version": "0.0.2", "plugin_version": "0.0.2",
"resolved": "github:NixOS/nixpkgs/b60793b86201040d9dee019a05089a9150d08b5b#nodejs_20", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#nodejs_20",
"source": "devbox-search", "source": "devbox-search",
"version": "20.14.0", "version": "20.18.1",
"systems": { "systems": {
"aarch64-darwin": { "aarch64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/sqnbldm1fjw88v23yq4v6531y4m7v2fh-nodejs-20.14.0", "path": "/nix/store/q49zbi0pzjhg4zn085h9hyz9m1k3hvpb-nodejs-20.18.1",
"default": true "default": true
}, },
{ {
"name": "libv8", "name": "libv8",
"path": "/nix/store/1i0rb2axkrxvsq5pz8s2q07ard2p36a1-nodejs-20.14.0-libv8" "path": "/nix/store/l08rljd2yr7i1q4x778qazcys2l4ja23-nodejs-20.18.1-libv8"
} }
], ],
"store_path": "/nix/store/sqnbldm1fjw88v23yq4v6531y4m7v2fh-nodejs-20.14.0" "store_path": "/nix/store/q49zbi0pzjhg4zn085h9hyz9m1k3hvpb-nodejs-20.18.1"
}, },
"aarch64-linux": { "aarch64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/r1nwmlbsn67f5rhayr7jjjdmiflxpk92-nodejs-20.14.0", "path": "/nix/store/4m1ql1hsd6kqmzr8a657qhipjgssrr0c-nodejs-20.18.1",
"default": true "default": true
}, },
{ {
"name": "libv8", "name": "libv8",
"path": "/nix/store/5ii3xkbd3iv0xvqqvjg3agsm0dinidgm-nodejs-20.14.0-libv8" "path": "/nix/store/r8s1xalb4rpy1r44i413j84i4ny6mnsc-nodejs-20.18.1-libv8"
} }
], ],
"store_path": "/nix/store/r1nwmlbsn67f5rhayr7jjjdmiflxpk92-nodejs-20.14.0" "store_path": "/nix/store/4m1ql1hsd6kqmzr8a657qhipjgssrr0c-nodejs-20.18.1"
}, },
"x86_64-darwin": { "x86_64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/wzgnws4r1c98vzj5q6gq4drz2jfq7d5q-nodejs-20.14.0", "path": "/nix/store/7ky0mn6k33731jwzhsxq6a6dsbjqamqs-nodejs-20.18.1",
"default": true "default": true
}, },
{ {
"name": "libv8", "name": "libv8",
"path": "/nix/store/gc2gnkc8hvkh51ab3a29fvgzy2qsqb2s-nodejs-20.14.0-libv8" "path": "/nix/store/jw62k3wxl38r8fcbvxaxrm696ivv3imr-nodejs-20.18.1-libv8"
} }
], ],
"store_path": "/nix/store/wzgnws4r1c98vzj5q6gq4drz2jfq7d5q-nodejs-20.14.0" "store_path": "/nix/store/7ky0mn6k33731jwzhsxq6a6dsbjqamqs-nodejs-20.18.1"
}, },
"x86_64-linux": { "x86_64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/ilkfhnqz4xczrliqjva8770x2svbfznd-nodejs-20.14.0", "path": "/nix/store/j7dx1n6m5axf9r2bvly580x2ixx546wq-nodejs-20.18.1",
"default": true "default": true
}, },
{ {
"name": "libv8", "name": "libv8",
"path": "/nix/store/2qaf68dzimr8as4bgli0xmsn11c0ah2j-nodejs-20.14.0-libv8" "path": "/nix/store/qljmc2skrldj0g94rib6nl4jq84193fa-nodejs-20.18.1-libv8"
} }
], ],
"store_path": "/nix/store/ilkfhnqz4xczrliqjva8770x2svbfznd-nodejs-20.14.0" "store_path": "/nix/store/j7dx1n6m5axf9r2bvly580x2ixx546wq-nodejs-20.18.1"
} }
} }
}, },
"python310@latest": { "python310@latest": {
"last_modified": "2024-07-07T07:43:47Z", "last_modified": "2024-12-23T21:10:33Z",
"plugin_version": "0.0.4", "plugin_version": "0.0.4",
"resolved": "github:NixOS/nixpkgs/b60793b86201040d9dee019a05089a9150d08b5b#python310", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#python310",
"source": "devbox-search", "source": "devbox-search",
"version": "3.10.14", "version": "3.10.16",
"systems": { "systems": {
"aarch64-darwin": { "aarch64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/n0gcjj86qjx7w59bwpzqvzdwrjdc7bwy-python3-3.10.14", "path": "/nix/store/382cajdyw7qsgrzjf8y79hssg8ggv18x-python3-3.10.16",
"default": true "default": true
} }
], ],
"store_path": "/nix/store/n0gcjj86qjx7w59bwpzqvzdwrjdc7bwy-python3-3.10.14" "store_path": "/nix/store/382cajdyw7qsgrzjf8y79hssg8ggv18x-python3-3.10.16"
}, },
"aarch64-linux": { "aarch64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/pzpn4j6hh8ayy15cb36s7i8v0mkavy0z-python3-3.10.14", "path": "/nix/store/bvvky8yghyl23vwdhf6dmq6w1a4nm1mg-python3-3.10.16",
"default": true "default": true
}, },
{ {
"name": "debug", "name": "debug",
"path": "/nix/store/h873y0nbzqlmsda6m2vfdcjw1v6c660f-python3-3.10.14-debug" "path": "/nix/store/msw7k25qw8wfqjrdv6j2sydqxddmaw32-python3-3.10.16-debug"
} }
], ],
"store_path": "/nix/store/pzpn4j6hh8ayy15cb36s7i8v0mkavy0z-python3-3.10.14" "store_path": "/nix/store/bvvky8yghyl23vwdhf6dmq6w1a4nm1mg-python3-3.10.16"
}, },
"x86_64-darwin": { "x86_64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/3ia1741fyzlcjgp3kg01hlk3z1jlp9x0-python3-3.10.14", "path": "/nix/store/2dnz9rwscr6d1pma8h5q7ckfavsrvhb1-python3-3.10.16",
"default": true "default": true
} }
], ],
"store_path": "/nix/store/3ia1741fyzlcjgp3kg01hlk3z1jlp9x0-python3-3.10.14" "store_path": "/nix/store/2dnz9rwscr6d1pma8h5q7ckfavsrvhb1-python3-3.10.16"
}, },
"x86_64-linux": { "x86_64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/handws5bj8l411asgs68s3bj8f05qnn5-python3-3.10.14", "path": "/nix/store/rv4ykblb2w9qc7w7a10dbw4r1am7zm9n-python3-3.10.16",
"default": true "default": true
}, },
{ {
"name": "debug", "name": "debug",
"path": "/nix/store/sl3yyz93mar0jk6cnw0lqv4xrvsbas0a-python3-3.10.14-debug" "path": "/nix/store/l0fx7jgxq5pn27n74haq9c5bhwvbkpab-python3-3.10.16-debug"
} }
], ],
"store_path": "/nix/store/handws5bj8l411asgs68s3bj8f05qnn5-python3-3.10.14" "store_path": "/nix/store/rv4ykblb2w9qc7w7a10dbw4r1am7zm9n-python3-3.10.16"
} }
} }
}, },
@ -518,66 +518,66 @@
} }
}, },
"yt-dlp@latest": { "yt-dlp@latest": {
"last_modified": "2024-07-18T22:08:26Z", "last_modified": "2025-01-03T14:51:55Z",
"resolved": "github:NixOS/nixpkgs/cfa5366588c940ab6ee3bee399b337175545c664#yt-dlp", "resolved": "github:NixOS/nixpkgs/a27871180d30ebee8aa6b11bf7fef8a52f024733#yt-dlp",
"source": "devbox-search", "source": "devbox-search",
"version": "2024.7.16", "version": "2024.12.23",
"systems": { "systems": {
"aarch64-darwin": { "aarch64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/sb1129rd65qynmf5pqshr2885g54hjdz-python3.12-yt-dlp-2024.7.16", "path": "/nix/store/8fmy039278i7q31zyyrfmr4z5k35xvp6-yt-dlp-2024.12.23",
"default": true "default": true
}, },
{ {
"name": "dist", "name": "dist",
"path": "/nix/store/7c75jyvxvqhnhlb8iv99m0m2gzaz1562-python3.12-yt-dlp-2024.7.16-dist" "path": "/nix/store/v9mplambvs7hlcpcpnvmf7c30pk5cx8d-yt-dlp-2024.12.23-dist"
} }
], ],
"store_path": "/nix/store/sb1129rd65qynmf5pqshr2885g54hjdz-python3.12-yt-dlp-2024.7.16" "store_path": "/nix/store/8fmy039278i7q31zyyrfmr4z5k35xvp6-yt-dlp-2024.12.23"
}, },
"aarch64-linux": { "aarch64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/rzr6pr2axf653258rnlrldx540wag1h0-python3.12-yt-dlp-2024.7.16", "path": "/nix/store/wzna2q40a81qj4icma4q20q9fjg9md76-yt-dlp-2024.12.23",
"default": true "default": true
}, },
{ {
"name": "dist", "name": "dist",
"path": "/nix/store/js7w9zzcydsf020njvhy3dbvarv4c9qj-python3.12-yt-dlp-2024.7.16-dist" "path": "/nix/store/z0b0nv6a2wl0565f5ffrzhg2zcqflvrl-yt-dlp-2024.12.23-dist"
} }
], ],
"store_path": "/nix/store/rzr6pr2axf653258rnlrldx540wag1h0-python3.12-yt-dlp-2024.7.16" "store_path": "/nix/store/wzna2q40a81qj4icma4q20q9fjg9md76-yt-dlp-2024.12.23"
}, },
"x86_64-darwin": { "x86_64-darwin": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/q3sqpq348nj1zhlwsfmbwcqnmkfglmlj-python3.12-yt-dlp-2024.7.16", "path": "/nix/store/mpbp9jar45hk22ddldm0bbk60vz5w643-yt-dlp-2024.12.23",
"default": true "default": true
}, },
{ {
"name": "dist", "name": "dist",
"path": "/nix/store/f6i4bq4fbcd1s7k660fkqr15g0lzrfvx-python3.12-yt-dlp-2024.7.16-dist" "path": "/nix/store/gq4l9yfs7fjb05qkl97hmsq69s3k4shr-yt-dlp-2024.12.23-dist"
} }
], ],
"store_path": "/nix/store/q3sqpq348nj1zhlwsfmbwcqnmkfglmlj-python3.12-yt-dlp-2024.7.16" "store_path": "/nix/store/mpbp9jar45hk22ddldm0bbk60vz5w643-yt-dlp-2024.12.23"
}, },
"x86_64-linux": { "x86_64-linux": {
"outputs": [ "outputs": [
{ {
"name": "out", "name": "out",
"path": "/nix/store/m47znwi2bc09g66j2kn6k7fvfx9cvr38-python3.12-yt-dlp-2024.7.16", "path": "/nix/store/wqcs5crm36p603fkh9j2k868zzb8q79c-yt-dlp-2024.12.23",
"default": true "default": true
}, },
{ {
"name": "dist", "name": "dist",
"path": "/nix/store/7laiz6ilsx4xzk6xni7yl8g3g04wyl55-python3.12-yt-dlp-2024.7.16-dist" "path": "/nix/store/j452c5bii2slx1biix7lfc5k0aqg2rvs-yt-dlp-2024.12.23-dist"
} }
], ],
"store_path": "/nix/store/m47znwi2bc09g66j2kn6k7fvfx9cvr38-python3.12-yt-dlp-2024.7.16" "store_path": "/nix/store/wqcs5crm36p603fkh9j2k868zzb8q79c-yt-dlp-2024.12.23"
} }
} }
} }

View File

@ -76,17 +76,36 @@ services:
- db - db
# volumes: # volumes:
# - ./services/bright/lib:/app/lib # - ./services/bright/lib:/app/lib
# volumes:
# - /home/cj/Documents/ueberauth_patreon:/app/contrib/ueberauth_patreon
develop: develop:
watch: watch:
- action: sync - path: ./services/bright/
path: ./services/bright/
target: /app/ target: /app/
- action: sync+restart action: sync
path: ./services/bright/application.ex - path: ./services/bright/application.ex
target: /app/lib/bright/application.ex target: /app/lib/bright/application.ex
- action: sync+restart action: sync+restart
path: ./services/bright/mix.exs - path: ./services/bright/config/config.exs
target: /app/lib/bright/config/config.exs
action: sync+restart
- path: ./services/bright/config/runtime.exs
target: /app/lib/bright/config/runtime.exs
action: sync+restart
# @todo we need "docker@27.5.0" in devbox.json because we need docker compose >= `v2.32.0` for `sync+exec` feature.
# For now, we don't have `sync+exec` support which means docker image rebuilds are required when updating mix.exs
# - path: ./services/bright/mix.exs
# action: sync+exec
# target: /app/mix.exs
# exec:
# command: mix deps.get
- path: ./services/bright/mix.exs
target: /app/mix.exs target: /app/mix.exs
action: sync+restart
# - path: /home/cj/Documents/ueberauth_patreon
# action: sync
# target: /app/contrib/ueberauth_patreon
db: db:
image: postgres:15 image: postgres:15

View File

@ -41,12 +41,16 @@ RUN echo MIX_ENV=$MIX_ENV
COPY ./services/bright/mix.exs ./services/bright/mix.lock ./ COPY ./services/bright/mix.exs ./services/bright/mix.lock ./
RUN mix deps.get --only $MIX_ENV RUN mix deps.get --only $MIX_ENV
RUN mkdir config RUN mkdir config
RUN mkdir contrib
# copy compile-time config files before we compile dependencies # copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies # to ensure any relevant config change will trigger the dependencies
# to be re-compiled. # to be re-compiled.
COPY ./services/bright/config/config.exs ./services/bright/config/${MIX_ENV}.exs config/ COPY ./services/bright/config/config.exs ./services/bright/config/${MIX_ENV}.exs config/
RUN ls -la config/ # COPY ./packages/ueberauth_patreon /app/contrib/ueberauth_patreon
# COPY ./packages/ueberauth_github /app/contrib/ueberauth_github
RUN ls -la /app/contrib/
RUN mix deps.compile RUN mix deps.compile
COPY ./services/bright/priv priv COPY ./services/bright/priv priv
@ -55,6 +59,7 @@ COPY ./services/bright/lib lib
COPY ./services/bright/assets assets COPY ./services/bright/assets assets
# compile assets # compile assets
RUN mix assets.deploy RUN mix assets.deploy
@ -70,8 +75,8 @@ RUN mix release
## dev target ## dev target
FROM builder AS dev FROM builder AS dev
# RUN mix ecto.setup
RUN echo "balls. that is all." RUN echo "balls. that is all."
RUN ls -la ./contrib/
CMD [ "mix", "phx.server" ] CMD [ "mix", "phx.server" ]
@ -94,7 +99,9 @@ WORKDIR "/app"
RUN chown nobody /app RUN chown nobody /app
# set runner ENV # set runner ENV
ENV MIX_ENV="prod" ARG MIX_ENV
ENV MIX_ENV $MIX_ENV
RUN echo MIX_ENV=$MIX_ENV
# Only copy the final release from the build stage # Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/bright ./ COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/bright ./

View File

@ -32,6 +32,16 @@ config :bright, Oban,
{Oban.Plugins.Lifeline, rescue_after: :timer.minutes(30)} {Oban.Plugins.Lifeline, rescue_after: :timer.minutes(30)}
] ]
# @see https://github.com/ueberauth/ueberauth
config :ueberauth, Ueberauth,
providers: [
github: {Ueberauth.Strategy.Github, [default_scope: "user:email"]},
patreon: {Ueberauth.Strategy.Patreon, []}
]
config :ueberauth, Ueberauth.Strategy.Github.OAuth,
client_id: System.get_env("GITHUB_CLIENT_ID"),
client_secret: System.get_env("GITHUB_CLIENT_SECRET")
# Configures the mailer # Configures the mailer
# #

View File

@ -65,6 +65,18 @@ if config_env() == :prod do
], ],
secret_key_base: secret_key_base secret_key_base: secret_key_base
# config :ueberauth, Ueberauth.Strategy.Patreon.OAuth,
# client_id: System.get_env("PATREON_CLIENT_ID"),
# client_secret: System.get_env("PATREON_CLIENT_SECRET")
# config :ueberauth, Ueberauth.Strategy.Github.OAuth,
# client_id: System.get_env("GITHUB_CLIENT_ID"),
# client_secret: System.get_env("GITHUB_CLIENT_SECRET")
# config :ueberauth, Ueberauth.Strategy.Github.OAuth,
# client_id: {:system, "GITHUB_CLIENT_ID"},
# client_secret: {:system, "GITHUB_CLIENT_SECRET"}
# ## SSL Support # ## SSL Support
# #
# To get SSL working, you will need to add the `https` key # To get SSL working, you will need to add the `https` key

View File

@ -10,6 +10,8 @@ defmodule Bright.Accounts do
## Database getters ## Database getters
@doc """ @doc """
Gets a user by email. Gets a user by email.
@ -157,6 +159,8 @@ defmodule Bright.Accounts do
|> Ecto.Multi.delete_all(:tokens, UserToken.by_user_and_contexts_query(user, [context])) |> Ecto.Multi.delete_all(:tokens, UserToken.by_user_and_contexts_query(user, [context]))
end end
@doc ~S""" @doc ~S"""
Delivers the update email instructions to the given user. Delivers the update email instructions to the given user.

View File

@ -8,6 +8,7 @@ defmodule Bright.Accounts.User do
field :hashed_password, :string, redact: true field :hashed_password, :string, redact: true
field :current_password, :string, virtual: true, redact: true field :current_password, :string, virtual: true, redact: true
field :confirmed_at, :utc_datetime field :confirmed_at, :utc_datetime
field :provider, :string
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime)
end end
@ -44,7 +45,7 @@ defmodule Bright.Accounts.User do
defp validate_email(changeset, opts) do defp validate_email(changeset, opts) do
changeset changeset
|> validate_required([:email]) |> validate_required([:email, :provider])
|> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces") |> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces")
|> validate_length(:email, max: 160) |> validate_length(:email, max: 160)
|> maybe_validate_unique_email(opts) |> maybe_validate_unique_email(opts)

View File

@ -1,12 +1,19 @@
defmodule Bright.User do defmodule Bright.User do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
alias Bright.Repo
schema "users" do schema "users" do
field :name, :string field :name, :string
field :email, :string field :email, :string
field :bio, :string
field :number_of_pets, :integer field :number_of_pets, :integer
field :is_admin, :boolean
field :auth_token, :string
field :auth_token_expires_at, :utc_datetime
field :signed_in_at, :utc_datetime
field :joined_at, :utc_datetime
field :patreon_handle, :string
field :github_handle, :string
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime)
end end
@ -14,7 +21,29 @@ defmodule Bright.User do
@doc false @doc false
def changeset(user, attrs) do def changeset(user, attrs) do
user user
|> cast(attrs, [:name, :email, :bio, :number_of_pets]) |> cast(attrs, [:name, :email, :bio, :number_of_pets, :is_admin])
|> validate_required([:name, :email, :bio, :number_of_pets]) |> validate_required([:name, :email, :bio, :number_of_pets])
end end
def get_by_ueberauth(%{provider: :github, info: %{nickname: handle}}) do
Repo.get_by(__MODULE__, github_handle: handle)
end
def get_by_ueberauth(%{provider: :patreon, info: %{nickname: handle}}) do
Repo.get_by(__MODULE__, patreon_handle: handle)
end
def get_by_ueberauth(_), do: nil
def sign_in_changes(user) do
change(user, %{
auth_token: nil,
auth_token_expires_at: nil,
signed_in_at: now_in_seconds(),
joined_at: user.joined_at || now_in_seconds()
})
end
defp now_in_seconds, do: Timex.now() |> DateTime.truncate(:second)
end end

View File

@ -0,0 +1,70 @@
defmodule Bright.UserFromAuth do
@moduledoc """
Retrieve the user information from an auth request
"""
require Logger
require Jason
alias Ueberauth.Auth
def find_or_create(%Auth{provider: :identity} = auth) do
case validate_pass(auth.credentials) do
:ok ->
{:ok, basic_info(auth)}
{:error, reason} ->
{:error, reason}
end
end
def find_or_create(%Auth{} = auth) do
{:ok, basic_info(auth)}
end
# github does it this way
defp avatar_from_auth(%{info: %{urls: %{avatar_url: image}}}), do: image
# facebook does it this way
defp avatar_from_auth(%{info: %{image: image}}), do: image
# default case if nothing matches
defp avatar_from_auth(auth) do
Logger.warn("#{auth.provider} needs to find an avatar URL!")
Logger.debug(Jason.encode!(auth))
nil
end
defp basic_info(auth) do
%{id: auth.uid, name: name_from_auth(auth), avatar: avatar_from_auth(auth)}
end
defp name_from_auth(auth) do
if auth.info.name do
auth.info.name
else
name =
[auth.info.first_name, auth.info.last_name]
|> Enum.filter(&(&1 != nil and &1 != ""))
if Enum.empty?(name) do
auth.info.nickname
else
Enum.join(name, " ")
end
end
end
defp validate_pass(%{other: %{password: nil}}) do
{:error, "Password required"}
end
defp validate_pass(%{other: %{password: pw, password_confirmation: pw}}) do
:ok
end
defp validate_pass(%{other: %{password: _}}) do
{:error, "Passwords do not match"}
end
defp validate_pass(_), do: {:error, "Password Required"}
end

View File

@ -21,7 +21,7 @@ defmodule BrightWeb do
def router do def router do
quote do quote do
use Phoenix.Router, helpers: false use Phoenix.Router, helpers: true
# Import common connection and controller functions to use in pipelines # Import common connection and controller functions to use in pipelines
import Plug.Conn import Plug.Conn

View File

@ -112,7 +112,6 @@ defmodule BrightWeb.CoreComponents do
<div <div
:if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)} :if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)}
id={@id} id={@id}
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
role="alert" role="alert"
class={[ class={[
"mb-5 notification", "mb-5 notification",
@ -121,7 +120,12 @@ defmodule BrightWeb.CoreComponents do
]} ]}
{@rest} {@rest}
> >
<button type="button" class="delete" aria-label={gettext("close")}></button> <button
type="button"
class="delete"
aria-label={gettext("close")}
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
></button>
<p :if={@title} class="has-text-weight-bold"> <p :if={@title} class="has-text-weight-bold">
<%= @title %> <%= @title %>
</p> </p>

View File

@ -97,7 +97,7 @@
<!-- <%= if @current_user do %> <%= if @current_user do %>
<.link <.link
href={~p"/profile"} href={~p"/profile"}
class="navbar-item"> class="navbar-item">
@ -123,13 +123,19 @@
> >
Register Register
</.link> </.link>
<.link <%# <.link
href={~p"/users/log_in"} href={~p"/auth/github"}
class="navbar-item" class="navbar-item"
> >
Log in Log in
</.link> </.link>
<% end %> --> <.link
href={~p"/auth/github"}
class="navbar-item"
>
Log in via GH
</.link> %>
<% end %>
</div> </div>
</div> </div>

View File

@ -0,0 +1,92 @@
defmodule BrightWeb.AuthController do
@moduledoc """
Auth controller responsible for handling Ueberauth responses
"""
require Logger
use BrightWeb, :controller
plug Ueberauth
alias Ueberauth.Strategy.Helpers
alias Bright.UserFromAuth
alias Bright.User
def delete(conn, _params) do
conn
|> put_flash(:info, "You have been logged out!")
|> clear_session()
|> redirect(to: "/")
end
def callback(%{assigns: %{ueberauth_failure: _fails}} = conn, _params) do
conn
|> put_flash(:error, "Failed to authenticate.")
|> redirect(to: "/")
end
# def callback(conn, %{"provider" => provider}) do
# end
def callback(conn = %{assigns: %{ueberauth_auth: auth}}, _params) do
if user = User.get_by_ueberauth(auth) do
sign_in_and_redirect(conn, user, ~p"/~")
else
conn
|> put_flash(:success, "Almost there! Please complete your profile now.")
|> redirect(to: ~p"/join?#{params_from_ueberauth(auth)}")
end
end
defp sign_in_and_redirect(conn, user, route) do
user
|> User.sign_in_changes()
|> Repo.update()
conn
|> assign(:current_user, user)
|> put_flash(:success, "Welcome!")
|> put_session("id", user.id)
|> configure_session(renew: true)
|> redirect(to: route)
end
defp params_from_ueberauth(%{provider: :github, info: info}) do
%{name: info.name, handle: info.nickname, github_handle: info.nickname}
end
defp params_from_ueberauth(%{provider: :patreon, info: info}) do
%{name: info.name, handle: info.nickname, patreon_handle: info.nickname}
end
# case Ueberauth.Auth.fetch!(conn) do
# {:ok, auth} ->
# Logger.info("auth is as follows: #{inspect(auth)}")
# {:error, reason} ->
# conn
# |> put_flash(:error, "Auth failed! #{reason}")
# |> redirect(to: ~p"/")
# end
# case UserFromAuth.find_or_create(auth) do
# {:ok, user} ->
# conn
# |> put_flash(:info, "Successfully authenticated #{inspect(user)}")
# |> put_session(:current_user, user)
# |> configure_session(renew: true)
# |> redirect(to: "/")
# {:error, reason} ->
# conn
# |> put_flash(:error, reason)
# |> redirect(to: "/")
# end
end

View File

@ -0,0 +1,7 @@
defmodule BrightWeb.AuthHTML do
use BrightWeb, :html
embed_templates "auth_html/*"
end

View File

@ -0,0 +1 @@
<p>hello this is request.html</p>

View File

@ -6,6 +6,7 @@
<p class="title is-2"> <p class="title is-2">
The Galaxy's Best VTuber Hentai Site The Galaxy's Best VTuber Hentai Site
</p> </p>
@ -25,6 +26,20 @@
</div> </div>
<!--<%= inspect(@current_user) %>
<%= if @current_user do %>
<div>
<h1>Welcome, <%= @current_user[:name] %>!</h1>
<p>ID: <%= @current_user[:id] %></p>
<p>Avatar: <%= @current_user[:avatar] %></p>
</div>
<% else %>
<div>
<p>You are not logged in. Please <a href="/auth/github">log in</a>.</p>
</div>
<% end %>-->

View File

@ -0,0 +1,15 @@
defmodule BrightWeb.UserController do
use BrightWeb, :controller
def index(conn, _params) do
render(conn, :index)
end
def show(conn) do
conn
|> render(:show)
end
end

View File

@ -0,0 +1,4 @@
defmodule BrightWeb.UserHTML do
use BrightWeb, :html
embed_templates "user_html/*"
end

View File

@ -0,0 +1,11 @@
<.header>
Visitor Profile
</.header>
<%= if @current_user do %>
<p>@current_user is {@current_user}</p>
<% else %>
<p>there is no @current_user</p>
<% end %>

View File

@ -24,16 +24,27 @@ defmodule BrightWeb.Router do
plug :accepts, ["json"] plug :accepts, ["json"]
end end
# scope "/" do
# pipe_through [:browser, :require_authenticated_user, :require_admin_user]
# ## !!! DANGER, platforms must only be writable by admins, (unless we implement SVG sanitizing)
# get "/platforms/new", PlatformController, :new
# post "/platforms", PlatformController, :create
# get "/platforms/:id/edit", PlatformController, :edit
# patch "/platforms/:id", PlatformController, :update
# put "/platforms/:id", PlatformController, :update
# end
scope "/" do
pipe_through [:browser, :require_authenticated_user, :require_admin_user]
## !!! DANGER, platforms must only be writable by admins, (unless we implement SVG sanitizing)
get "/platforms/new", PlatformController, :new
post "/platforms", PlatformController, :create
get "/platforms/:id/edit", PlatformController, :edit
patch "/platforms/:id", PlatformController, :update
put "/platforms/:id", PlatformController, :update
end
scope "/auth", BrightWeb do
pipe_through :browser
get "/:provider", AuthController, :request
get "/:provider/callback", AuthController, :callback
post "/:provider/callback", AuthController, :callback
delete "/logout", AuthController, :delete
end
scope "/" do scope "/" do
@ -58,6 +69,8 @@ defmodule BrightWeb.Router do
# get "/vtubers/:id/edit", VtuberController, :edit # get "/vtubers/:id/edit", VtuberController, :edit
# end # end
get "/profile", UserController, :show
get "/tags/new", TagController, :new get "/tags/new", TagController, :new
post "/tags", TagController, :create post "/tags", TagController, :create
@ -82,8 +95,6 @@ defmodule BrightWeb.Router do
get "/streams", StreamController, :index get "/streams", StreamController, :index
get "/streams/:id", StreamController, :show get "/streams/:id", StreamController, :show
# get "/vods", VodController, :index
# get "/vods/:id", VodController, :show
resources "/vods", VodController resources "/vods", VodController
get "/vods/:id", VodController, :show get "/vods/:id", VodController, :show

View File

@ -5,6 +5,7 @@ defmodule BrightWeb.UserAuth do
import Phoenix.Controller import Phoenix.Controller
alias Bright.Accounts alias Bright.Accounts
alias Bright.User
# Make the remember me cookie valid for 60 days. # Make the remember me cookie valid for 60 days.
# If you want bump or reduce this value, also change # If you want bump or reduce this value, also change
@ -208,11 +209,37 @@ defmodule BrightWeb.UserAuth do
conn conn
|> put_flash(:error, "You must log in to access this page.") |> put_flash(:error, "You must log in to access this page.")
|> maybe_store_return_to() |> maybe_store_return_to()
|> redirect(to: ~p"/users/log_in") |> redirect(to: ~p"/auth/github")
|> halt() |> halt()
end end
end end
@doc """
Used for routes that require the user to be an administrator.
"""
def require_admin_user(conn, _opts) do
Logger.info("con.assigns[:current_user] as follows. #{inspect(conn.assigns)}")
case conn.assigns[:current_user] do
%User{is_admin: true} -> # Assuming the user struct has an `is_admin` field
conn
%User{} ->
conn
|> put_flash(:error, "You do not have permission to access this page.")
|> redirect(to: ~p"/")
|> halt()
nil ->
conn
|> put_flash(:error, "You must log in to access this page.")
|> maybe_store_return_to()
|> redirect(to: ~p"/auth/github")
|> halt()
end
end
defp put_token_in_session(conn, token) do defp put_token_in_session(conn, token) do
conn conn
|> put_session(:user_token, token) |> put_session(:user_token, token)

View File

@ -56,7 +56,10 @@ defmodule Bright.MixProject do
{:bandit, "~> 1.5"}, {:bandit, "~> 1.5"},
{:oban, "~> 2.17"}, {:oban, "~> 2.17"},
{:mox, "~> 0.5.0", only: :test}, {:mox, "~> 0.5.0", only: :test},
{:httpoison, "~> 2.0"} {:httpoison, "~> 2.0"},
{:ueberauth, "~> 0.7.0"},
{:ueberauth_github, "~> 0.8"},
{:timex, "~> 3.0"},
] ]
end end

View File

@ -4,6 +4,7 @@
"bulma": {:hex, :bulma, "1.0.2", "50dfffe8d28b0bd527418560223b407f9e80e990e187e1653b17eff818f8fcbe", [:mix], [], "hexpm", "27745727ff7f451d140a2438c0ca4448bc8ca73e0a6d2d4f24e1b5b9ced8a774"}, "bulma": {:hex, :bulma, "1.0.2", "50dfffe8d28b0bd527418560223b407f9e80e990e187e1653b17eff818f8fcbe", [:mix], [], "hexpm", "27745727ff7f451d140a2438c0ca4448bc8ca73e0a6d2d4f24e1b5b9ced8a774"},
"castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"}, "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"comeonin": {:hex, :comeonin, "5.5.0", "364d00df52545c44a139bad919d7eacb55abf39e86565878e17cebb787977368", [:mix], [], "hexpm", "6287fc3ba0aad34883cbe3f7949fc1d1e738e5ccdce77165bc99490aa69f47fb"}, "comeonin": {:hex, :comeonin, "5.5.0", "364d00df52545c44a139bad919d7eacb55abf39e86565878e17cebb787977368", [:mix], [], "hexpm", "6287fc3ba0aad34883cbe3f7949fc1d1e738e5ccdce77165bc99490aa69f47fb"},
"dart_sass": {:hex, :dart_sass, "0.7.0", "7979e056cb74fd6843e1c72db763cffc7726a9192a657735b7d24c0d9c26a1ce", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "4a8e70bca41aa00846398abdf5ad8a64d7907a0f7bf40145cd2e40d5971629f2"}, "dart_sass": {:hex, :dart_sass, "0.7.0", "7979e056cb74fd6843e1c72db763cffc7726a9192a657735b7d24c0d9c26a1ce", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "4a8e70bca41aa00846398abdf5ad8a64d7907a0f7bf40145cd2e40d5971629f2"},
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
@ -31,6 +32,7 @@
"mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"}, "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
"oauth2": {:hex, :oauth2, "2.1.0", "beb657f393814a3a7a8a15bd5e5776ecae341fd344df425342a3b6f1904c2989", [:mix], [{:tesla, "~> 1.5", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "8ac07f85b3307dd1acfeb0ec852f64161b22f57d0ce0c15e616a1dfc8ebe2b41"},
"oban": {:hex, :oban, "2.18.3", "1608c04f8856c108555c379f2f56bc0759149d35fa9d3b825cb8a6769f8ae926", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "36ca6ca84ef6518f9c2c759ea88efd438a3c81d667ba23b02b062a0aa785475e"}, "oban": {:hex, :oban, "2.18.3", "1608c04f8856c108555c379f2f56bc0759149d35fa9d3b825cb8a6769f8ae926", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "36ca6ca84ef6518f9c2c759ea88efd438a3c81d667ba23b02b062a0aa785475e"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"phoenix": {:hex, :phoenix, "1.7.18", "5310c21443514be44ed93c422e15870aef254cf1b3619e4f91538e7529d2b2e4", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "1797fcc82108442a66f2c77a643a62980f342bfeb63d6c9a515ab8294870004e"}, "phoenix": {:hex, :phoenix, "1.7.18", "5310c21443514be44ed93c422e15870aef254cf1b3619e4f91538e7529d2b2e4", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "1797fcc82108442a66f2c77a643a62980f342bfeb63d6c9a515ab8294870004e"},
@ -52,7 +54,12 @@
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"},
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
"tesla": {:hex, :tesla, "1.12.3", "7189f71ac607169a1bb2dfcf8747dedd4d9384ec00cec6c7b38c5f03811a73c7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "4dfb0d6a81ca79c8662a4f03884843a5b3251825ba47ea6f9ab84dcc354fdeec"},
"thousand_island": {:hex, :thousand_island, "1.3.7", "1da7598c0f4f5f50562c097a3f8af308ded48cd35139f0e6f17d9443e4d0c9c5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0139335079953de41d381a6134d8b618d53d084f558c734f2662d1a72818dd12"}, "thousand_island": {:hex, :thousand_island, "1.3.7", "1da7598c0f4f5f50562c097a3f8af308ded48cd35139f0e6f17d9443e4d0c9c5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0139335079953de41d381a6134d8b618d53d084f558c734f2662d1a72818dd12"},
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
"tzdata": {:hex, :tzdata, "1.1.2", "45e5f1fcf8729525ec27c65e163be5b3d247ab1702581a94674e008413eef50b", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cec7b286e608371602318c414f344941d5eb0375e14cfdab605cca2fe66cba8b"},
"ueberauth": {:hex, :ueberauth, "0.7.0", "9c44f41798b5fa27f872561b6f7d2bb0f10f03fdd22b90f454232d7b087f4b75", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2efad9022e949834f16cc52cd935165049d81fa9e925690f91035c2e4b58d905"},
"ueberauth_github": {:hex, :ueberauth_github, "0.8.3", "1c478629b4c1dae446c68834b69194ad5cead3b6c67c913db6fdf64f37f0328f", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "ae0ab2879c32cfa51d7287a48219b262bfdab0b7ec6629f24160564247493cc6"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},

View File

@ -0,0 +1,9 @@
defmodule Bright.Repo.Migrations.AddPlatformToUser do
use Ecto.Migration
def change do
alter table(:users) do
add :is_admin, :boolean, default: false, null: false
end
end
end

View File

@ -0,0 +1,9 @@
defmodule Bright.Repo.Migrations.AddIsAdminToUser do
use Ecto.Migration
def change do
alter table(:users) do
add :is_admin, :boolean, default: false, null: false
end
end
end

View File

@ -0,0 +1,12 @@
defmodule Bright.Repo.Migrations.AddAuthTokenToUser do
use Ecto.Migration
def change do
alter table(:users) do
add :auth_token, :string
add :auth_token_expires_at, :utc_datetime
add :joined_at, :utc_datetime
add :signed_in_at, :utc_datetime
end
end
end

View File

@ -0,0 +1,10 @@
defmodule Bright.Repo.Migrations.AddProviderHandlesToUser do
use Ecto.Migration
def change do
alter table(:users) do
add :patreon_handle, :string
add :github_handle, :string
end
end
end

View File

@ -0,0 +1,9 @@
defmodule Bright.Repo.Migrations.AddNameToUser do
use Ecto.Migration
def change do
alter table(:users) do
add :name, :string
end
end
end