diff --git a/ARCHITECHTURE.md b/ARCHITECHTURE.md index 14a2f3a..2bde6ea 100644 --- a/ARCHITECHTURE.md +++ b/ARCHITECHTURE.md @@ -1,16 +1,14 @@ devbox for shareable development environment tooling -git monorepo for housing separate node packages within a single repository - -TypeScript +git monorepo for housing separate packages within a single repository (see ./services and ./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 diff --git a/README.md b/README.md index b1175b9..4da5df7 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,19 @@ See ./ARCHITECTURE.md for an overview of the infrastructure components. ## 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 [devbox](https://www.jetify.com/devbox/docs/installing_devbox/) +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` 2. Install development environment & packages using devbox. 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 @@ -38,8 +41,7 @@ Use devbox helper script Keeping track of metrics we want to scrape using Prometheus -### Uppy - -https://uppy.fp.sbtp.xyz/metrics + + diff --git a/devbox.lock b/devbox.lock index 2ba8f4c..3fea3f4 100644 --- a/devbox.lock +++ b/devbox.lock @@ -2,150 +2,150 @@ "lockfile_version": "1", "packages": { "ffmpeg@latest": { - "last_modified": "2024-07-24T00:53:51Z", - "resolved": "github:NixOS/nixpkgs/4f02464258baaf54992debfd010a7a3662a25536#ffmpeg", + "last_modified": "2025-01-07T09:15:50Z", + "resolved": "github:NixOS/nixpkgs/8c9fd3e564728e90829ee7dbac6edc972971cd0f#ffmpeg", "source": "devbox-search", - "version": "6.1.1", + "version": "7.1", "systems": { "aarch64-darwin": { "outputs": [ { "name": "bin", - "path": "/nix/store/7jl394717pnlj5jy8n46jq65sw1gwb20-ffmpeg-6.1.1-bin", + "path": "/nix/store/m48ypyjnl04mqigi6fbxa7k2c5bsvazz-ffmpeg-7.1-bin", "default": true }, { "name": "man", - "path": "/nix/store/ma1ssbkbwrasdgsyp0y3x6jbc72pp9s7-ffmpeg-6.1.1-man", + "path": "/nix/store/10ncvfz8srnzckq16bn14wffcx8j04ki-ffmpeg-7.1-man", "default": true }, - { - "name": "out", - "path": "/nix/store/smq7vi0562incbgwf4cbx10i0y46jsbc-ffmpeg-6.1.1" - }, { "name": "data", - "path": "/nix/store/289ikv8ld8whmixs3r4qd4r878mkjmm9-ffmpeg-6.1.1-data" + "path": "/nix/store/rqbsc9zyzi988hwcd423qdh1vh40zlzc-ffmpeg-7.1-data" }, { "name": "dev", - "path": "/nix/store/r8y6va82y6libjw065gkn5gr51715gac-ffmpeg-6.1.1-dev" + "path": "/nix/store/6ml3pn92nbmnc40s5jfpr84y65ysizk3-ffmpeg-7.1-dev" }, { "name": "doc", - "path": "/nix/store/yasff9ggma6myg47sm805idfxnz0zkac-ffmpeg-6.1.1-doc" + "path": "/nix/store/ni6gri7m1pavfjxx0yfj1msvb0cfasgg-ffmpeg-7.1-doc" }, { "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": { "outputs": [ { "name": "bin", - "path": "/nix/store/6ydyry316fcc59iy80zpnxnsrh9f18ki-ffmpeg-6.1.1-bin", + "path": "/nix/store/lj99z3ldzka2slgm94w2yl8cjkphn4m3-ffmpeg-7.1-bin", "default": true }, { "name": "man", - "path": "/nix/store/k1frp52lx3ycwbdgliwcrmb81zm4n10n-ffmpeg-6.1.1-man", + "path": "/nix/store/gisda8d2pifrrjw0yirrs0x2cyn6b96i-ffmpeg-7.1-man", "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", - "path": "/nix/store/6z17gry0dn1yxr3r36fk87sxnddcjg66-ffmpeg-6.1.1" + "path": "/nix/store/pc332zx12j2fqf5m9mdhhs1rwksbk2fk-ffmpeg-7.1" }, { "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": { "outputs": [ { "name": "bin", - "path": "/nix/store/84yjd9p94kknxpdn974ksb7y28l6paq4-ffmpeg-6.1.1-bin", + "path": "/nix/store/z44kr817zx99vi2cc204i06cnmz83f1n-ffmpeg-7.1-bin", "default": true }, { "name": "man", - "path": "/nix/store/r1g3627b14nqpz4aqfp87ba0fh49ar5k-ffmpeg-6.1.1-man", + "path": "/nix/store/slrha22nqrx2xw009hd37svv2nvpp26i-ffmpeg-7.1-man", "default": true }, { "name": "data", - "path": "/nix/store/dv5lc67c3xykza11q5pwk4vivnsdswmw-ffmpeg-6.1.1-data" + "path": "/nix/store/n3xm2rr1k1ari7ysbp9jhg65pih28x6x-ffmpeg-7.1-data" }, { "name": "dev", - "path": "/nix/store/f0qcama09w9kri8hqvn0lk89zck4978v-ffmpeg-6.1.1-dev" + "path": "/nix/store/59gcv4rfg38rqnazv1iq9jssjak2l3ih-ffmpeg-7.1-dev" }, { "name": "doc", - "path": "/nix/store/7sg26fama7a6gpdm0kkphblzc2x03dfx-ffmpeg-6.1.1-doc" + "path": "/nix/store/2cqa3lc75ciqzgmxjm36fd733f3gjgil-ffmpeg-7.1-doc" }, { "name": "lib", - "path": "/nix/store/rhq35qgr8yvhygpj24wm14anidf9gmmc-ffmpeg-6.1.1-lib" + "path": "/nix/store/ir47x8skj54wilcyz2x59am4y085lf6l-ffmpeg-7.1-lib" }, { "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": { "outputs": [ { "name": "bin", - "path": "/nix/store/wnmy246m582splkkqwpgza390sa4m1k1-ffmpeg-6.1.1-bin", + "path": "/nix/store/d1lv3x7iq129vb19ba9ph6k0yhy4fv34-ffmpeg-7.1-bin", "default": true }, { "name": "man", - "path": "/nix/store/hqq9mmrwrbazfdcsmd2dd3jgpvpsyj5p-ffmpeg-6.1.1-man", + "path": "/nix/store/qqgvvfw2gqp47zl5v9jhdsl8mb77l909-ffmpeg-7.1-man", "default": true }, + { + "name": "doc", + "path": "/nix/store/gmfj9af6za9i2830cgbj1qazz2nir2vs-ffmpeg-7.1-doc" + }, { "name": "lib", - "path": "/nix/store/5jynrssm1bvrj3kskwgyyhb2069f8dwv-ffmpeg-6.1.1-lib" + "path": "/nix/store/x8j2nr5qmikfaggl34wpm1dlldb7ik06-ffmpeg-7.1-lib" }, { "name": "out", - "path": "/nix/store/xdb4w2ccvig6020ish7qpl88i8fqg2ai-ffmpeg-6.1.1" + "path": "/nix/store/cx89mypnxgk0q4dibacg7dsrb4w66mv9-ffmpeg-7.1" }, { "name": "data", - "path": "/nix/store/sw8wxzscsnxnvrwqzq4fqxvggcd1xic7-ffmpeg-6.1.1-data" + "path": "/nix/store/5y8zk8fqpaammsnz2svgpdsayn4zlsn2-ffmpeg-7.1-data" }, { "name": "dev", - "path": "/nix/store/p6jd7041xggbkwyfzrgsm8ccj370w1hz-ffmpeg-6.1.1-dev" - }, - { - "name": "doc", - "path": "/nix/store/1dfla14f5g5xwmw3w5cjfnwdfr64qw7z-ffmpeg-6.1.1-doc" + "path": "/nix/store/qdz8aidi7rksr4g5cpxgz9iivrlsa247-ffmpeg-7.1-dev" } ], - "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": { - "last_modified": "2024-07-07T07:43:47Z", + "last_modified": "2024-12-23T21:10:33Z", "plugin_version": "0.0.2", - "resolved": "github:NixOS/nixpkgs/b60793b86201040d9dee019a05089a9150d08b5b#nodejs_20", + "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#nodejs_20", "source": "devbox-search", - "version": "20.14.0", + "version": "20.18.1", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/sqnbldm1fjw88v23yq4v6531y4m7v2fh-nodejs-20.14.0", + "path": "/nix/store/q49zbi0pzjhg4zn085h9hyz9m1k3hvpb-nodejs-20.18.1", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/r1nwmlbsn67f5rhayr7jjjdmiflxpk92-nodejs-20.14.0", + "path": "/nix/store/4m1ql1hsd6kqmzr8a657qhipjgssrr0c-nodejs-20.18.1", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/wzgnws4r1c98vzj5q6gq4drz2jfq7d5q-nodejs-20.14.0", + "path": "/nix/store/7ky0mn6k33731jwzhsxq6a6dsbjqamqs-nodejs-20.18.1", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/ilkfhnqz4xczrliqjva8770x2svbfznd-nodejs-20.14.0", + "path": "/nix/store/j7dx1n6m5axf9r2bvly580x2ixx546wq-nodejs-20.18.1", "default": true }, { "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": { - "last_modified": "2024-07-07T07:43:47Z", + "last_modified": "2024-12-23T21:10:33Z", "plugin_version": "0.0.4", - "resolved": "github:NixOS/nixpkgs/b60793b86201040d9dee019a05089a9150d08b5b#python310", + "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#python310", "source": "devbox-search", - "version": "3.10.14", + "version": "3.10.16", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/n0gcjj86qjx7w59bwpzqvzdwrjdc7bwy-python3-3.10.14", + "path": "/nix/store/382cajdyw7qsgrzjf8y79hssg8ggv18x-python3-3.10.16", "default": true } ], - "store_path": "/nix/store/n0gcjj86qjx7w59bwpzqvzdwrjdc7bwy-python3-3.10.14" + "store_path": "/nix/store/382cajdyw7qsgrzjf8y79hssg8ggv18x-python3-3.10.16" }, "aarch64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/pzpn4j6hh8ayy15cb36s7i8v0mkavy0z-python3-3.10.14", + "path": "/nix/store/bvvky8yghyl23vwdhf6dmq6w1a4nm1mg-python3-3.10.16", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/3ia1741fyzlcjgp3kg01hlk3z1jlp9x0-python3-3.10.14", + "path": "/nix/store/2dnz9rwscr6d1pma8h5q7ckfavsrvhb1-python3-3.10.16", "default": true } ], - "store_path": "/nix/store/3ia1741fyzlcjgp3kg01hlk3z1jlp9x0-python3-3.10.14" + "store_path": "/nix/store/2dnz9rwscr6d1pma8h5q7ckfavsrvhb1-python3-3.10.16" }, "x86_64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/handws5bj8l411asgs68s3bj8f05qnn5-python3-3.10.14", + "path": "/nix/store/rv4ykblb2w9qc7w7a10dbw4r1am7zm9n-python3-3.10.16", "default": true }, { "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": { - "last_modified": "2024-07-18T22:08:26Z", - "resolved": "github:NixOS/nixpkgs/cfa5366588c940ab6ee3bee399b337175545c664#yt-dlp", + "last_modified": "2025-01-03T14:51:55Z", + "resolved": "github:NixOS/nixpkgs/a27871180d30ebee8aa6b11bf7fef8a52f024733#yt-dlp", "source": "devbox-search", - "version": "2024.7.16", + "version": "2024.12.23", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/sb1129rd65qynmf5pqshr2885g54hjdz-python3.12-yt-dlp-2024.7.16", + "path": "/nix/store/8fmy039278i7q31zyyrfmr4z5k35xvp6-yt-dlp-2024.12.23", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/rzr6pr2axf653258rnlrldx540wag1h0-python3.12-yt-dlp-2024.7.16", + "path": "/nix/store/wzna2q40a81qj4icma4q20q9fjg9md76-yt-dlp-2024.12.23", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/q3sqpq348nj1zhlwsfmbwcqnmkfglmlj-python3.12-yt-dlp-2024.7.16", + "path": "/nix/store/mpbp9jar45hk22ddldm0bbk60vz5w643-yt-dlp-2024.12.23", "default": true }, { "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": { "outputs": [ { "name": "out", - "path": "/nix/store/m47znwi2bc09g66j2kn6k7fvfx9cvr38-python3.12-yt-dlp-2024.7.16", + "path": "/nix/store/wqcs5crm36p603fkh9j2k868zzb8q79c-yt-dlp-2024.12.23", "default": true }, { "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" } } } diff --git a/docker-compose.yml b/docker-compose.yml index 886573e..87c4280 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -76,17 +76,36 @@ services: - db # volumes: # - ./services/bright/lib:/app/lib + # volumes: + # - /home/cj/Documents/ueberauth_patreon:/app/contrib/ueberauth_patreon develop: watch: - - action: sync - path: ./services/bright/ + - path: ./services/bright/ target: /app/ - - action: sync+restart - path: ./services/bright/application.ex + action: sync + - path: ./services/bright/application.ex target: /app/lib/bright/application.ex - - action: sync+restart - path: ./services/bright/mix.exs + action: sync+restart + - 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 + action: sync+restart + # - path: /home/cj/Documents/ueberauth_patreon + # action: sync + # target: /app/contrib/ueberauth_patreon + db: image: postgres:15 diff --git a/dockerfiles/bright.dockerfile b/dockerfiles/bright.dockerfile index 3228717..eb222a1 100644 --- a/dockerfiles/bright.dockerfile +++ b/dockerfiles/bright.dockerfile @@ -41,12 +41,16 @@ RUN echo MIX_ENV=$MIX_ENV COPY ./services/bright/mix.exs ./services/bright/mix.lock ./ RUN mix deps.get --only $MIX_ENV RUN mkdir config +RUN mkdir contrib # copy compile-time config files before we compile dependencies # to ensure any relevant config change will trigger the dependencies # to be re-compiled. 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 COPY ./services/bright/priv priv @@ -55,6 +59,7 @@ COPY ./services/bright/lib lib COPY ./services/bright/assets assets + # compile assets RUN mix assets.deploy @@ -70,8 +75,8 @@ RUN mix release ## dev target FROM builder AS dev -# RUN mix ecto.setup RUN echo "balls. that is all." +RUN ls -la ./contrib/ CMD [ "mix", "phx.server" ] @@ -94,7 +99,9 @@ WORKDIR "/app" RUN chown nobody /app # 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 COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/bright ./ diff --git a/services/bright/config/config.exs b/services/bright/config/config.exs index e52d3ac..942613f 100644 --- a/services/bright/config/config.exs +++ b/services/bright/config/config.exs @@ -32,6 +32,16 @@ config :bright, Oban, {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 # diff --git a/services/bright/config/runtime.exs b/services/bright/config/runtime.exs index 427306b..cfaeab1 100644 --- a/services/bright/config/runtime.exs +++ b/services/bright/config/runtime.exs @@ -65,6 +65,18 @@ if config_env() == :prod do ], 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 # # To get SSL working, you will need to add the `https` key diff --git a/services/bright/lib/bright/accounts.ex b/services/bright/lib/bright/accounts.ex index 0b92a86..3715aa5 100644 --- a/services/bright/lib/bright/accounts.ex +++ b/services/bright/lib/bright/accounts.ex @@ -10,6 +10,8 @@ defmodule Bright.Accounts do ## Database getters + + @doc """ 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])) end + + @doc ~S""" Delivers the update email instructions to the given user. diff --git a/services/bright/lib/bright/accounts/user.ex b/services/bright/lib/bright/accounts/user.ex index 8e4a7b8..da1799f 100644 --- a/services/bright/lib/bright/accounts/user.ex +++ b/services/bright/lib/bright/accounts/user.ex @@ -8,6 +8,7 @@ defmodule Bright.Accounts.User do field :hashed_password, :string, redact: true field :current_password, :string, virtual: true, redact: true field :confirmed_at, :utc_datetime + field :provider, :string timestamps(type: :utc_datetime) end @@ -44,7 +45,7 @@ defmodule Bright.Accounts.User do defp validate_email(changeset, opts) do changeset - |> validate_required([:email]) + |> validate_required([:email, :provider]) |> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces") |> validate_length(:email, max: 160) |> maybe_validate_unique_email(opts) diff --git a/services/bright/lib/bright/user.ex b/services/bright/lib/bright/user.ex index 15d1e9e..aba9ce3 100644 --- a/services/bright/lib/bright/user.ex +++ b/services/bright/lib/bright/user.ex @@ -1,12 +1,19 @@ defmodule Bright.User do use Ecto.Schema import Ecto.Changeset + alias Bright.Repo schema "users" do field :name, :string field :email, :string - field :bio, :string 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) end @@ -14,7 +21,29 @@ defmodule Bright.User do @doc false def changeset(user, attrs) do 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]) 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 diff --git a/services/bright/lib/bright/user_from_auth.ex b/services/bright/lib/bright/user_from_auth.ex new file mode 100644 index 0000000..b18e951 --- /dev/null +++ b/services/bright/lib/bright/user_from_auth.ex @@ -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 diff --git a/services/bright/lib/bright_web.ex b/services/bright/lib/bright_web.ex index 8ed9cfe..54da0e1 100644 --- a/services/bright/lib/bright_web.ex +++ b/services/bright/lib/bright_web.ex @@ -21,7 +21,7 @@ defmodule BrightWeb do def router do quote do - use Phoenix.Router, helpers: false + use Phoenix.Router, helpers: true # Import common connection and controller functions to use in pipelines import Plug.Conn diff --git a/services/bright/lib/bright_web/components/core_components.ex b/services/bright/lib/bright_web/components/core_components.ex index ca2d3de..61f4679 100644 --- a/services/bright/lib/bright_web/components/core_components.ex +++ b/services/bright/lib/bright_web/components/core_components.ex @@ -112,7 +112,6 @@ defmodule BrightWeb.CoreComponents do
<%= @title %>
diff --git a/services/bright/lib/bright_web/components/layouts/root.html.heex b/services/bright/lib/bright_web/components/layouts/root.html.heex index 69ab04a..00c461a 100644 --- a/services/bright/lib/bright_web/components/layouts/root.html.heex +++ b/services/bright/lib/bright_web/components/layouts/root.html.heex @@ -97,7 +97,7 @@ - + <.link + href={~p"/auth/github"} + class="navbar-item" + > + Log in via GH + %> + <% end %>hello this is request.html
\ No newline at end of file diff --git a/services/bright/lib/bright_web/controllers/page_html/home.html.heex b/services/bright/lib/bright_web/controllers/page_html/home.html.heex index 1685cbe..ad2b3d5 100644 --- a/services/bright/lib/bright_web/controllers/page_html/home.html.heex +++ b/services/bright/lib/bright_web/controllers/page_html/home.html.heex @@ -6,6 +6,7 @@ +The Galaxy's Best VTuber Hentai Site
@@ -25,6 +26,20 @@ + + diff --git a/services/bright/lib/bright_web/controllers/user_controller.ex b/services/bright/lib/bright_web/controllers/user_controller.ex new file mode 100644 index 0000000..55901d7 --- /dev/null +++ b/services/bright/lib/bright_web/controllers/user_controller.ex @@ -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 diff --git a/services/bright/lib/bright_web/controllers/user_html.ex b/services/bright/lib/bright_web/controllers/user_html.ex new file mode 100644 index 0000000..60eac6b --- /dev/null +++ b/services/bright/lib/bright_web/controllers/user_html.ex @@ -0,0 +1,4 @@ +defmodule BrightWeb.UserHTML do + use BrightWeb, :html + embed_templates "user_html/*" +end diff --git a/services/bright/lib/bright_web/controllers/user_html/user.html.heex b/services/bright/lib/bright_web/controllers/user_html/user.html.heex new file mode 100644 index 0000000..a595a7e --- /dev/null +++ b/services/bright/lib/bright_web/controllers/user_html/user.html.heex @@ -0,0 +1,11 @@ + +<.header> + Visitor Profile + + +<%= if @current_user do %> +@current_user is {@current_user}
+<% else %> +there is no @current_user
+<% end %> + diff --git a/services/bright/lib/bright_web/router.ex b/services/bright/lib/bright_web/router.ex index ebea60f..c246292 100644 --- a/services/bright/lib/bright_web/router.ex +++ b/services/bright/lib/bright_web/router.ex @@ -24,16 +24,27 @@ defmodule BrightWeb.Router do plug :accepts, ["json"] 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 @@ -58,6 +69,8 @@ defmodule BrightWeb.Router do # get "/vtubers/:id/edit", VtuberController, :edit # end + get "/profile", UserController, :show + get "/tags/new", TagController, :new post "/tags", TagController, :create @@ -82,8 +95,6 @@ defmodule BrightWeb.Router do get "/streams", StreamController, :index get "/streams/:id", StreamController, :show - # get "/vods", VodController, :index - # get "/vods/:id", VodController, :show resources "/vods", VodController get "/vods/:id", VodController, :show diff --git a/services/bright/lib/bright_web/user_auth.ex b/services/bright/lib/bright_web/user_auth.ex index 6eec60f..c7b4e25 100644 --- a/services/bright/lib/bright_web/user_auth.ex +++ b/services/bright/lib/bright_web/user_auth.ex @@ -5,6 +5,7 @@ defmodule BrightWeb.UserAuth do import Phoenix.Controller alias Bright.Accounts + alias Bright.User # Make the remember me cookie valid for 60 days. # If you want bump or reduce this value, also change @@ -208,11 +209,37 @@ defmodule BrightWeb.UserAuth do conn |> put_flash(:error, "You must log in to access this page.") |> maybe_store_return_to() - |> redirect(to: ~p"/users/log_in") + |> redirect(to: ~p"/auth/github") |> halt() 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 conn |> put_session(:user_token, token) diff --git a/services/bright/mix.exs b/services/bright/mix.exs index 7681137..fc519e8 100644 --- a/services/bright/mix.exs +++ b/services/bright/mix.exs @@ -56,7 +56,10 @@ defmodule Bright.MixProject do {:bandit, "~> 1.5"}, {:oban, "~> 2.17"}, {:mox, "~> 0.5.0", only: :test}, - {:httpoison, "~> 2.0"} + {:httpoison, "~> 2.0"}, + {:ueberauth, "~> 0.7.0"}, + {:ueberauth_github, "~> 0.8"}, + {:timex, "~> 3.0"}, ] end diff --git a/services/bright/mix.lock b/services/bright/mix.lock index 228ab82..33ddf8e 100644 --- a/services/bright/mix.lock +++ b/services/bright/mix.lock @@ -4,6 +4,7 @@ "bulma": {:hex, :bulma, "1.0.2", "50dfffe8d28b0bd527418560223b407f9e80e990e187e1653b17eff818f8fcbe", [:mix], [], "hexpm", "27745727ff7f451d140a2438c0ca4448bc8ca73e0a6d2d4f24e1b5b9ced8a774"}, "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"}, "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"}, "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"}, @@ -31,6 +32,7 @@ "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "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"}, "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"}, @@ -52,7 +54,12 @@ "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_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"}, + "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"}, "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"}, diff --git a/services/bright/priv/repo/migrations/20250115053147_add_provider_to_user.exs b/services/bright/priv/repo/migrations/20250115053147_add_provider_to_user.exs new file mode 100644 index 0000000..8a3522a --- /dev/null +++ b/services/bright/priv/repo/migrations/20250115053147_add_provider_to_user.exs @@ -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 diff --git a/services/bright/priv/repo/migrations/20250116134417_add_is_admin_to_user.exs b/services/bright/priv/repo/migrations/20250116134417_add_is_admin_to_user.exs new file mode 100644 index 0000000..dd07394 --- /dev/null +++ b/services/bright/priv/repo/migrations/20250116134417_add_is_admin_to_user.exs @@ -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 diff --git a/services/bright/priv/repo/migrations/20250116154212_add_auth_token_to_user.exs b/services/bright/priv/repo/migrations/20250116154212_add_auth_token_to_user.exs new file mode 100644 index 0000000..caac560 --- /dev/null +++ b/services/bright/priv/repo/migrations/20250116154212_add_auth_token_to_user.exs @@ -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 diff --git a/services/bright/priv/repo/migrations/20250116155928_add_provider_handles_to_user.exs b/services/bright/priv/repo/migrations/20250116155928_add_provider_handles_to_user.exs new file mode 100644 index 0000000..3e68c5a --- /dev/null +++ b/services/bright/priv/repo/migrations/20250116155928_add_provider_handles_to_user.exs @@ -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 diff --git a/services/bright/priv/repo/migrations/20250116200213_add_name_to_user.exs b/services/bright/priv/repo/migrations/20250116200213_add_name_to_user.exs new file mode 100644 index 0000000..d48322f --- /dev/null +++ b/services/bright/priv/repo/migrations/20250116200213_add_name_to_user.exs @@ -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