From 970c01dd11145f9b7c551ab69578d64809bd4e66 Mon Sep 17 00:00:00 2001 From: Drake Date: Tue, 23 Jun 2026 09:08:12 -0500 Subject: [PATCH] updates --- .gitea/workflows/build_and_deploy.yaml | 50 ++++++ Dockerfile | 19 +++ package-lock.json | 203 ++++++++++++++++++++++--- package.json | 6 + src/app.html | 3 + static/favicon-dev.ico | Bin 0 -> 4286 bytes static/favicon-prod.ico | Bin 0 -> 4286 bytes 7 files changed, 263 insertions(+), 18 deletions(-) create mode 100644 .gitea/workflows/build_and_deploy.yaml create mode 100644 Dockerfile create mode 100644 static/favicon-dev.ico create mode 100644 static/favicon-prod.ico diff --git a/.gitea/workflows/build_and_deploy.yaml b/.gitea/workflows/build_and_deploy.yaml new file mode 100644 index 0000000..08dd330 --- /dev/null +++ b/.gitea/workflows/build_and_deploy.yaml @@ -0,0 +1,50 @@ +name: Build and Deploy + +on: + push: + branches: + - main + +jobs: + build_docker_image: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Extract package version from package.json + id: version + run: | + VERSION=$(node -p "require('./package.json').version") + echo "package_version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Login to Docker Registry + uses: docker/login-action@v3 + with: + registry: git.marinodev.com + username: ${{ vars.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and Push Docker Image + uses: docker/build-push-action@v6 + with: + pull: true + push: true + no-cache: true + tags: | + git.marinodev.com/marinodev/lindner_visitor:latest + git.marinodev.com/marinodev/lindner_visitor:${{ steps.version.outputs.package_version }} + + deploy: + runs-on: ubuntu-latest + needs: docker_image + steps: + - name: Restart Service + uses: https://github.com/appleboy/ssh-action@v1.0.3 + with: + host: ${{ vars.DEPLOY_HOST }} + username: ${{ vars.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY }} + script: | + cd ${{ vars.DEPLOY_PATH }} + docker-compose down && docker-compose pull && docker-compose up -d \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..866ee63 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM node:26 as builder + +RUN apt update && apt upgrade -y + +# Make an /app dir, which everything will eventually live in +RUN mkdir -p /app +WORKDIR /app +COPY . . + +RUN npm ci +RUN npm run build + +FROM node:26 as runner + +# Copy build to runner +COPY --from=builder /app/build/* /app/ + +EXPOSE 8080 +ENTRYPOINT exec node /app diff --git a/package-lock.json b/package-lock.json index 4c8099c..f5e1526 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,12 @@ "": { "name": "lindner-visitor", "version": "0.0.1", + "dependencies": { + "bcrypt": "^6.0.0", + "dotenv": "^17.4.2", + "jsonwebtoken": "^9.0.3", + "postgres": "^3.4.9" + }, "devDependencies": { "@eslint/js": "^10.0.1", "@sveltejs/adapter-node": "^5.5.4", @@ -2117,6 +2123,20 @@ "node": "18 || 20 || >=22" } }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/brace-expansion": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", @@ -2130,6 +2150,12 @@ "node": "18 || 20 || >=22" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -2270,6 +2296,27 @@ "dev": true, "license": "MIT" }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/enhanced-resolve": { "version": "5.21.6", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", @@ -2833,6 +2880,49 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3180,6 +3270,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -3240,7 +3372,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -3269,6 +3400,26 @@ "dev": true, "license": "MIT" }, + "node_modules/node-addon-api": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.8.0.tgz", + "integrity": "sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/obug": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", @@ -3566,6 +3717,19 @@ "node": ">=4" } }, + "node_modules/postgres": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.9.tgz", + "integrity": "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw==", + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3714,11 +3878,30 @@ "node": ">=6" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/semver": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4414,22 +4597,6 @@ } } }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "extraneous": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 4990f1a..d2a76a4 100644 --- a/package.json +++ b/package.json @@ -35,5 +35,11 @@ "vite": "^8.0.16", "vitest": "^4.1.8", "vitest-browser-svelte": "^2.1.1" + }, + "dependencies": { + "bcrypt": "^6.0.0", + "dotenv": "^17.4.2", + "jsonwebtoken": "^9.0.3", + "postgres": "^3.4.9" } } diff --git a/src/app.html b/src/app.html index 6a2bb58..b6a23aa 100644 --- a/src/app.html +++ b/src/app.html @@ -4,7 +4,10 @@ + + Lindner Visitor System %sveltekit.head% +
%sveltekit.body%
diff --git a/static/favicon-dev.ico b/static/favicon-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..a4bfcb65ea198e1064e1c32bc470dbc89c72aadf GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/static/favicon-prod.ico b/static/favicon-prod.ico new file mode 100644 index 0000000000000000000000000000000000000000..f5b4629db8b57f0c22ef36ad1eccea87eba119e2 GIT binary patch literal 4286 zcmcgwXH->bmc5i!V^`O7Rj*#%Ju_M$c2$>zmnAEr7>YtbRFn*oL2?dC5|p515Jf>$ zN>U*~auQHbK!W6)d4&QZiV_6&eD~F=TJ7ptYu5CSxvc%T_rAy7=X~Ej=j;bX36URB zQHp-0GX6+Wf2Al&jDXyt_7l+e1qXTW|8h7VWm4WuEy_ui^*a|8Hq+&Mwz<<`_6>)F z>_)o->}lKm>^C<1Sc{f>nG@!FSaoLd%vcjShQ6^3<2%FMlAl>9Fexpj1SKLOLgNzx z5n&M#mawq!PJ&Mf{>O0KRU|2&V;ss`o%NZw21n9MjpO5?%BgWv;mo=mVXrwIVy)XN zvo>w_vo_D}V{KY1GB+&uFxSl$SSzM-OumUMv-pe*)6PhSxl@b7*uvZO4JEo$^a~MD z5k=u0BD%sN!ar>LdfOK}cJBBme!r6pDnLz|@;}c0qn{?n(DxX(_M8T1$y<#BPgM@Q z)TH2h`T&BAHE_{P3qd9);j60#SG9exQR2cvfdvu+EaX`WrgE$Y22u=lLmuPz+jfZj zURYFENqC2_8Cip)+qZB3LR3`rBYv-A5>%|AJas{f^It()+`zz-+)4lA+)cmZJOt_O zM}oU4vJ%2jnso=Yr3GksSb_Sga#R=Qp&%^4$UJmS)ICKmfM$(KvLn(&c zDXzqyw(k($M)<|Zx(k2(_1B*g{KkL&$ls_a%RSU3ZT5eL=y1a?X>(r%pW@=8t{kp; zo2M^!qzUP~|1tNl6D;bo0hhY0!~XKJKKER>9&bKWhl>akC1ggP!_%4yba!=P zpuZ2JBg2@QoWRSO8O+bk63k(S&qrfTC8Auw4&2K18LhKB~h zpPs_P!YjOg_YP}otN8HY1C|zFqqU|CaqgA~JSB@HO9iA~uttFKX*eI0M!-pBSnrns z(Id!Sv=TiiUgR262GSA&{!3coRDwB=iZ$VU6KBFJiZ$kK#+u0?C&rs_*9+E_&UtQj z7R&G7V|{%c*aSA#KVWWp3^iFd5$~vj=rgj&aFs_{j4k5btl)S^7NOe8_$fLVp|<8Q zlV{U0tQku)Z;<-@3jsyegi0`DQE{e>&l1hK)`{l4g#^>xNb@%$>sgB4o^Fhej^Ne& zJl0lMvAMY^!288H3^rAuAl3&rU613QyD}<6RnVFhh@WDE;C1`}E@((2&D$LHWrc|H za3-4M!jjYm*^5bI8K#DoBvZ&pib>tF;!xMEINNSoaSD?xxSKcal~9?HAkZ1Dt67rw z>e?FN-N5?tB3_L&;dwy}3L`9#e@O>*aeC-Tcfw#zD$4G};i9n`!cOnTU8iGcF3KXc zk`8C}?_t01mzp58xlUq8B>8`JMwUTo5gDY|un*s|;fyC+agZ5gfR_4)0*&*hr}6IX zYpg8t@n)pk=*^&72tYA2IdM(x<9m^kz+8d}IU?KdBuavgpgvX;qmS-j zX0#u<*JI$SaR8nwJS1AFqdMyr(xSs)e@F(TS1*$od`;vTTYj|VnP)q(n)2P4C_Bf* z<4}3D#HpY=?liVOkt|I@(cqFBLATdq`hm5k0aJ%oP~_mgyk%D&Jjd zz0zM6Pa_YaE9Df1?%QFqIv8{9cd<0lfYpUjti9pm-Bc@HHYQ`Vz!N>`XVIN*je+~l zn0kB-3*&7VYOTk;Fi!;QA4H@fkJRHnG-k(OVyIuxKPqyw;I6I+GBXL-w{4YJ|6bs! zh?)>pv|Q6e*N@g1EDOh2Q#M|Xl3W*ONWNouGxCUN?>Z(+d@x?%M07wjQ0xW%qgbMW zTD;~DprbkmX@ORVwK{@SqNCz~edsQV#o{a)_>P+;tJ;r!z3HS}km?*n|(LBPLXOD>@S4>q9?KP0+4pm}# zZUl29t!Ta$FTD%J{O-0x%vqAjB zb(;g6t@-Zq2TOd|ImKQQDDmatNwPKCQq9qIOBelVhD3YTM0>87uJXgnr}2chT%dvF z*&+Pgav!bfUZ{#OMsFdrVY_juyJ$^?_cy2w5J%%>IdmjxU?|H>z{`Iah}ovAcr#o@ct?m9Ca~CF zfvKu+^kmqh{kA1K(k#%IWrvB{c)aCzW0Uk|`k?2-{QR6??>pLBkbJ=v9;!SL4>Rv{ zh;3r0%=o0pdB<#}&#u+_5E-;zQ^!D-1;&friT*BN`e`EB-zvg6CeXp+U=@C@i^RkO zH;ml3$55^#hVxx8Q5}kT64Tn!ynvT}p?mc^GN+~{Ck1QYP+f)yn^W-kfekkmcAxVR zmb9PxZmRmiUNpvNpzDq)26MkkCCn?cuDqmuCsvDKG9{q6UOt24hjip zi5I3HhG4!c7t8ab*xdLf=U=&3$-J0-`BI>}uFmJkyBURm(|h1`l)d4h%1(Frp802Y zRW?;0apHYTlF`8PTSgtv5>!_nhwVYbO$$7)yn~*SNDSt>VL00cqxa7e{gGNL_a`a22@+iNLA)G%)H!pWN7+X9%8V_p-?ON? za82hY@w&=2m*muH0>s;E10>NvVraXjiJn`e2W6OG{DGr@mtRNn?a09U7hTv`UHXWZ zzS!8pbrATEBA4yu<(?vwHGY3z zc^W3Q*^#7Fz?ylRD&I3r38kGD5V8k37v?xS+-L^F6`(GUz0aayvnPL!qd0ukTP7EQQuY zb@XSLW313^ZM@iXwlCdyr789xYQvQ9IMtPStXy=pKO@iX7U-GoXS6S(Jt*xH=>F16 z-h1BCh(|@4$O^YdyoDmJ=yMUK%UvWfL>>P26?ahh*#BxNgD4RWsfi@srPqpLHaD`maQuRDcfqBX0VlKKhhi<5m4#&B;15H!QimiDul`*fZR{5eD4PVXYMsLV(FFJlDCm!mj z6l=EobqmhkcoWW7hb4unP+i7H&-_;|k}SliNJDWd&u!P|MV{jSk?SfhmhUdHm+-3+ zewB1brhKZc