From 3ed0523266a739b416f2f45ab0cfd9cc9121c9cb Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Wed, 12 Mar 2025 22:02:54 -0400 Subject: [PATCH 01/25] no need for setcookie in google callback --- src/controllers/GoogleController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/GoogleController.php b/src/controllers/GoogleController.php index 1fbc135..a91ca56 100644 --- a/src/controllers/GoogleController.php +++ b/src/controllers/GoogleController.php @@ -55,7 +55,6 @@ public function callbackAction() { // Redirect to a protected page or dashboard $decodedState = json_decode(urldecode($state), true); - setcookie("PHPSESSID", session_id(), time() + 3600 * 24 * 7, "/", $_ENV['INTERFACE_EDITOR_DOMAIN']); header('Location: ' . $_ENV['INTERFACE_EDITOR_URL'] . $decodedState['path']); exit; } else { From 999d47282bceea6ba4aa0011734233b3f4019b2e Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Wed, 12 Mar 2025 22:03:02 -0400 Subject: [PATCH 02/25] include .env.example --- .env.example | 1 - 1 file changed, 1 deletion(-) diff --git a/.env.example b/.env.example index 21b7119..cab0765 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,4 @@ # General -INTERFACE_EDITOR_DOMAIN=localhost:3000 INTERFACE_EDITOR_URL=http://localhost:3000 ACCESS_CONTROL_ALLOW_ORIGIN=http://localhost:3000 PUBLIC_FILE_PATH=http://localhost:9200/private/files/ From 84a293253833001987d071a55dccc2cfb176a4ba Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Wed, 12 Mar 2025 22:18:27 -0400 Subject: [PATCH 03/25] fix google callback create user query --- src/controllers/GoogleController.php | 2 +- src/queries/insert-user.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/GoogleController.php b/src/controllers/GoogleController.php index a91ca56..5bf9d5f 100644 --- a/src/controllers/GoogleController.php +++ b/src/controllers/GoogleController.php @@ -36,7 +36,7 @@ public function callbackAction() { 'id' => $userInfo->id, 'name' => $userInfo->name, 'email' => $userInfo->email, - 'picture' => $userInfo->picture + 'avatar' => $userInfo->picture ]); $userId = $this->getLastInsertedId(); // Get the new user's ID diff --git a/src/queries/insert-user.sql b/src/queries/insert-user.sql index 1b24152..9b11b8f 100644 --- a/src/queries/insert-user.sql +++ b/src/queries/insert-user.sql @@ -1,2 +1,2 @@ INSERT INTO users (google_id, name, email, avatar) -VALUES (:google_id, :name, :email, :avatar) +VALUES (:id, :name, :email, :avatar) From 9b4ea069d1e5a64c7c6f5958be6e086b0e7b81f3 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 14:10:53 -0400 Subject: [PATCH 04/25] setup github workflows --- .github/workflows/deploy-dev.yml | 54 +++++++++++++++++++++++++++++++ .github/workflows/deploy-prod.yml | 54 +++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 .github/workflows/deploy-dev.yml create mode 100644 .github/workflows/deploy-prod.yml diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml new file mode 100644 index 0000000..2018276 --- /dev/null +++ b/.github/workflows/deploy-dev.yml @@ -0,0 +1,54 @@ +name: Deploy DEV to FTP + +on: + push: + branches: + - dev # Change this to your default branch + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: composer + + - name: Install dependencies + run: composer install --no-dev --optimize-autoloader + + - name: Defining environment variables + env: + INTERFACE_EDITOR_DOMAIN: json.ms + INTERFACE_EDITOR_URL: https://json.ms + ACCESS_CONTROL_ALLOW_ORIGIN: https://json.ms + PUBLIC_FILE_PATH: https://json.ms/files/ + GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com + GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback + run: | + echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" + echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" + echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" + echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> $JSONMS_CYPHER_KEY + echo "DATABASE_DBNAME=${{ secrets.DATABASE_DBNAME }}" >> $DATABASE_DBNAME + echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> $DATABASE_HOST + echo "DATABASE_DBNAME=${{ secrets.DATABASE_DEV_DBNAME }}" >> $DATABASE_DBNAME + echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> $DATABASE_USERNAME + echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> $GOOGLE_OAUTH_CLIENT_SECRET + echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" + + - name: FTP Deploy + uses: pressidium/lftp-mirror-action@v1 + with: + host: ${{ secrets.FTP_SERVER }} # Your FTP server + user: ${{ secrets.FTP_USERNAME }} # Store your FTP username in GitHub Secrets + pass: ${{ secrets.FTP_PASSWORD }} # Store your FTP password in GitHub Secrets + localDir: ./dist/ # Adjust this to your build output directory + remoteDir: ${{ secrets.FTP_SERVER_DEV_PATH }} # Adjust this to your desired server directory diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml new file mode 100644 index 0000000..78f6ede --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,54 @@ +name: Deploy PROD to FTP + +on: + push: + branches: + - master # Change this to your default branch + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: composer + + - name: Install dependencies + run: composer install --no-dev --optimize-autoloader + + - name: Defining environment variables + env: + INTERFACE_EDITOR_DOMAIN: json.ms + INTERFACE_EDITOR_URL: https://json.ms + ACCESS_CONTROL_ALLOW_ORIGIN: https://json.ms + PUBLIC_FILE_PATH: https://json.ms/files/ + GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com + GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback + run: | + echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" + echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" + echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" + echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> $JSONMS_CYPHER_KEY + echo "DATABASE_DBNAME=${{ secrets.DATABASE_DBNAME }}" >> $DATABASE_DBNAME + echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> $DATABASE_HOST + echo "DATABASE_DBNAME=${{ secrets.DATABASE_PROD_DBNAME }}" >> $DATABASE_DBNAME + echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> $DATABASE_USERNAME + echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> $GOOGLE_OAUTH_CLIENT_SECRET + echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" + + - name: FTP Deploy + uses: pressidium/lftp-mirror-action@v1 + with: + host: ${{ secrets.FTP_SERVER }} # Your FTP server + user: ${{ secrets.FTP_USERNAME }} # Store your FTP username in GitHub Secrets + pass: ${{ secrets.FTP_PASSWORD }} # Store your FTP password in GitHub Secrets + localDir: ./dist/ # Adjust this to your build output directory + remoteDir: ${{ secrets.FTP_SERVER_PROD_PATH }} # Adjust this to your desired server directory From 59ee2cff4029ab56a90f50bd214b4c8c44ccb06a Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 14:16:06 -0400 Subject: [PATCH 05/25] setup github workflows --- .github/workflows/deploy-dev.yml | 12 ++++++------ .github/workflows/deploy-prod.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 2018276..f47f7d6 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -30,18 +30,18 @@ jobs: PUBLIC_FILE_PATH: https://json.ms/files/ GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback + JSONMS_CYPHER_KEY: ${{ secrets.JSONMS_CYPHER_KEY }} + DATABASE_HOST: ${{ secrets.DATABASE_HOST }} + DATABASE_DBNAME: ${{ secrets.DATABASE_DEV_DBNAME }} + DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }} + DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} + GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }} run: | echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" - echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> $JSONMS_CYPHER_KEY - echo "DATABASE_DBNAME=${{ secrets.DATABASE_DBNAME }}" >> $DATABASE_DBNAME - echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> $DATABASE_HOST - echo "DATABASE_DBNAME=${{ secrets.DATABASE_DEV_DBNAME }}" >> $DATABASE_DBNAME - echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> $DATABASE_USERNAME echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" - echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> $GOOGLE_OAUTH_CLIENT_SECRET echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - name: FTP Deploy diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 78f6ede..b8fd798 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -30,18 +30,18 @@ jobs: PUBLIC_FILE_PATH: https://json.ms/files/ GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback + JSONMS_CYPHER_KEY: ${{ secrets.JSONMS_CYPHER_KEY }} + DATABASE_HOST: ${{ secrets.DATABASE_HOST }} + DATABASE_DBNAME: ${{ secrets.DATABASE_PROD_DBNAME }} + DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }} + DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} + GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }} run: | echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" - echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> $JSONMS_CYPHER_KEY - echo "DATABASE_DBNAME=${{ secrets.DATABASE_DBNAME }}" >> $DATABASE_DBNAME - echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> $DATABASE_HOST - echo "DATABASE_DBNAME=${{ secrets.DATABASE_PROD_DBNAME }}" >> $DATABASE_DBNAME - echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> $DATABASE_USERNAME echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" - echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> $GOOGLE_OAUTH_CLIENT_SECRET echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - name: FTP Deploy From 289cdbd2aa31ee8243cba9cf0d2dcf6db516c9f4 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 14:17:42 -0400 Subject: [PATCH 06/25] setup github workflows --- .github/workflows/deploy-dev.yml | 10 +++++----- .github/workflows/deploy-prod.yml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index f47f7d6..2b657b6 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -47,8 +47,8 @@ jobs: - name: FTP Deploy uses: pressidium/lftp-mirror-action@v1 with: - host: ${{ secrets.FTP_SERVER }} # Your FTP server - user: ${{ secrets.FTP_USERNAME }} # Store your FTP username in GitHub Secrets - pass: ${{ secrets.FTP_PASSWORD }} # Store your FTP password in GitHub Secrets - localDir: ./dist/ # Adjust this to your build output directory - remoteDir: ${{ secrets.FTP_SERVER_DEV_PATH }} # Adjust this to your desired server directory + host: ${{ secrets.FTP_SERVER }} + user: ${{ secrets.FTP_USERNAME }} + pass: ${{ secrets.FTP_PASSWORD }} + localDir: ./ + remoteDir: ${{ secrets.FTP_SERVER_DEV_PATH }} diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index b8fd798..0396d8f 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -47,8 +47,8 @@ jobs: - name: FTP Deploy uses: pressidium/lftp-mirror-action@v1 with: - host: ${{ secrets.FTP_SERVER }} # Your FTP server - user: ${{ secrets.FTP_USERNAME }} # Store your FTP username in GitHub Secrets - pass: ${{ secrets.FTP_PASSWORD }} # Store your FTP password in GitHub Secrets - localDir: ./dist/ # Adjust this to your build output directory - remoteDir: ${{ secrets.FTP_SERVER_PROD_PATH }} # Adjust this to your desired server directory + host: ${{ secrets.FTP_SERVER }} + user: ${{ secrets.FTP_USERNAME }} + pass: ${{ secrets.FTP_PASSWORD }} + localDir: ./ + remoteDir: ${{ secrets.FTP_SERVER_PROD_PATH }} From 86cff6a57a84cda630d01ef291d3e20e44678bf7 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 14:49:48 -0400 Subject: [PATCH 07/25] setup github workflows --- .github/workflows/deploy-dev.yml | 25 +++++++++++++++++++------ .github/workflows/deploy-prod.yml | 27 ++++++++++++++++++++------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 2b657b6..d15a831 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -22,6 +22,9 @@ jobs: - name: Install dependencies run: composer install --no-dev --optimize-autoloader + - name: Zip the folder + run: zip -r archive.zip . -x "./.git/*" "./.github/*" + - name: Defining environment variables env: INTERFACE_EDITOR_DOMAIN: json.ms @@ -44,11 +47,21 @@ jobs: echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - - name: FTP Deploy - uses: pressidium/lftp-mirror-action@v1 + - name: Deploy via SSH + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.FTP_SERVER }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + source: "archive.zip" + target: ${{ secrets.FTP_SERVER_DEV_PATH }} + + - name: SSH into server and unzip + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.FTP_SERVER }} - user: ${{ secrets.FTP_USERNAME }} - pass: ${{ secrets.FTP_PASSWORD }} - localDir: ./ - remoteDir: ${{ secrets.FTP_SERVER_DEV_PATH }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + script: | + cd ${{ secrets.FTP_SERVER_DEV_PATH }} + unzip -o archive.zip -d . diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 0396d8f..74ff336 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -1,4 +1,4 @@ -name: Deploy PROD to FTP +name: Deploy DEV to FTP on: push: @@ -22,6 +22,9 @@ jobs: - name: Install dependencies run: composer install --no-dev --optimize-autoloader + - name: Zip the folder + run: zip -r archive.zip . -x "./.git/*" "./.github/*" + - name: Defining environment variables env: INTERFACE_EDITOR_DOMAIN: json.ms @@ -44,11 +47,21 @@ jobs: echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - - name: FTP Deploy - uses: pressidium/lftp-mirror-action@v1 + - name: Deploy via SSH + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.FTP_SERVER }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + source: "archive.zip" + target: ${{ secrets.FTP_SERVER_PROD_PATH }} + + - name: SSH into server and unzip + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.FTP_SERVER }} - user: ${{ secrets.FTP_USERNAME }} - pass: ${{ secrets.FTP_PASSWORD }} - localDir: ./ - remoteDir: ${{ secrets.FTP_SERVER_PROD_PATH }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + script: | + cd ${{ secrets.FTP_SERVER_PROD_PATH }} + unzip -o archive.zip -d . From ea3897dd4fb1e35ab14c1afa1a88e2f4b9e79397 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 14:56:28 -0400 Subject: [PATCH 08/25] setup github workflows --- .github/workflows/deploy-dev.yml | 34 +++++++++++------------------- .github/workflows/deploy-prod.yml | 35 ++++++++++++------------------- 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index d15a831..5e4f43d 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -25,28 +25,6 @@ jobs: - name: Zip the folder run: zip -r archive.zip . -x "./.git/*" "./.github/*" - - name: Defining environment variables - env: - INTERFACE_EDITOR_DOMAIN: json.ms - INTERFACE_EDITOR_URL: https://json.ms - ACCESS_CONTROL_ALLOW_ORIGIN: https://json.ms - PUBLIC_FILE_PATH: https://json.ms/files/ - GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com - GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback - JSONMS_CYPHER_KEY: ${{ secrets.JSONMS_CYPHER_KEY }} - DATABASE_HOST: ${{ secrets.DATABASE_HOST }} - DATABASE_DBNAME: ${{ secrets.DATABASE_DEV_DBNAME }} - DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }} - DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} - GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }} - run: | - echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" - echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" - echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" - echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" - echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" - echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - - name: Deploy via SSH uses: appleboy/scp-action@v0.1.7 with: @@ -65,3 +43,15 @@ jobs: script: | cd ${{ secrets.FTP_SERVER_DEV_PATH }} unzip -o archive.zip -d . + echo "INTERFACE_EDITOR_DOMAIN=dev.json.ms" > .env + echo "INTERFACE_EDITOR_URL=https://dev.json.ms" >> .env + echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://dev.json.ms" >> .env + echo "PUBLIC_FILE_PATH=https://dev.json.ms" >> .env + echo "GOOGLE_OAUTH_CLIENT_ID=https://dev.json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env + echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env + echo "DATABASE_DBNAME=${{ secrets.DATABASE_DEV_DBNAME }}" >> .env + echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env + echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 74ff336..19fc988 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -25,28 +25,6 @@ jobs: - name: Zip the folder run: zip -r archive.zip . -x "./.git/*" "./.github/*" - - name: Defining environment variables - env: - INTERFACE_EDITOR_DOMAIN: json.ms - INTERFACE_EDITOR_URL: https://json.ms - ACCESS_CONTROL_ALLOW_ORIGIN: https://json.ms - PUBLIC_FILE_PATH: https://json.ms/files/ - GOOGLE_OAUTH_CLIENT_ID: 637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com - GOOGLE_OAUTH_CALLBACK_URL: https://server.json.ms/google/callback - JSONMS_CYPHER_KEY: ${{ secrets.JSONMS_CYPHER_KEY }} - DATABASE_HOST: ${{ secrets.DATABASE_HOST }} - DATABASE_DBNAME: ${{ secrets.DATABASE_PROD_DBNAME }} - DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }} - DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} - GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }} - run: | - echo "Value of INTERFACE_EDITOR_DOMAIN is $INTERFACE_EDITOR_DOMAIN" - echo "Value of INTERFACE_EDITOR_URL is $INTERFACE_EDITOR_URL" - echo "Value of ACCESS_CONTROL_ALLOW_ORIGIN is $ACCESS_CONTROL_ALLOW_ORIGIN" - echo "Value of PUBLIC_FILE_PATH is $PUBLIC_FILE_PATH" - echo "Value of GOOGLE_OAUTH_CLIENT_ID is $GOOGLE_OAUTH_CLIENT_ID" - echo "Value of GOOGLE_OAUTH_CALLBACK_URL is $GOOGLE_OAUTH_CALLBACK_URL" - - name: Deploy via SSH uses: appleboy/scp-action@v0.1.7 with: @@ -65,3 +43,16 @@ jobs: script: | cd ${{ secrets.FTP_SERVER_PROD_PATH }} unzip -o archive.zip -d . + rm archive.zip + echo "INTERFACE_EDITOR_DOMAIN=json.ms" > .env + echo "INTERFACE_EDITOR_URL=https://json.ms" >> .env + echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://json.ms" >> .env + echo "PUBLIC_FILE_PATH=https://json.ms" >> .env + echo "GOOGLE_OAUTH_CLIENT_ID=https://json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env + echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env + echo "DATABASE_DBNAME=${{ secrets.DATABASE_PROD_DBNAME }}" >> .env + echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env + echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env From 37cc166692b2d3ffb755999d9fefae28a8384071 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 15:08:56 -0400 Subject: [PATCH 09/25] setup github workflows --- .github/workflows/deploy-dev.yml | 9 +++------ .github/workflows/deploy-prod.yml | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 5e4f43d..3614c43 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -43,15 +43,12 @@ jobs: script: | cd ${{ secrets.FTP_SERVER_DEV_PATH }} unzip -o archive.zip -d . - echo "INTERFACE_EDITOR_DOMAIN=dev.json.ms" > .env - echo "INTERFACE_EDITOR_URL=https://dev.json.ms" >> .env - echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://dev.json.ms" >> .env - echo "PUBLIC_FILE_PATH=https://dev.json.ms" >> .env + echo "INTERFACE_EDITOR_URL=https://dev.json.ms" > .env + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "GOOGLE_OAUTH_CLIENT_ID=https://dev.json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env - echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env echo "DATABASE_DBNAME=${{ secrets.DATABASE_DEV_DBNAME }}" >> .env echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env - echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 19fc988..813148c 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -44,15 +44,12 @@ jobs: cd ${{ secrets.FTP_SERVER_PROD_PATH }} unzip -o archive.zip -d . rm archive.zip - echo "INTERFACE_EDITOR_DOMAIN=json.ms" > .env - echo "INTERFACE_EDITOR_URL=https://json.ms" >> .env - echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://json.ms" >> .env - echo "PUBLIC_FILE_PATH=https://json.ms" >> .env + echo "INTERFACE_EDITOR_URL=https://json.ms" > .env + echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "GOOGLE_OAUTH_CLIENT_ID=https://json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env - echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env echo "DATABASE_DBNAME=${{ secrets.DATABASE_PROD_DBNAME }}" >> .env echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env - echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env From 1287ad44c6e15d91a52b7eeb04b3660fb3f701d0 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 15:20:30 -0400 Subject: [PATCH 10/25] setup github workflows --- .github/workflows/deploy-dev.yml | 6 ++++-- .github/workflows/deploy-prod.yml | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 3614c43..4c631ec 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -1,4 +1,4 @@ -name: Deploy DEV to FTP +name: Deploy DEV to host on: push: @@ -43,9 +43,11 @@ jobs: script: | cd ${{ secrets.FTP_SERVER_DEV_PATH }} unzip -o archive.zip -d . + rm archive.zip echo "INTERFACE_EDITOR_URL=https://dev.json.ms" > .env + echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://dev.json.ms" >> .env echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env - echo "GOOGLE_OAUTH_CLIENT_ID=https://dev.json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CLIENT_ID=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 813148c..bd0af5a 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -1,4 +1,4 @@ -name: Deploy DEV to FTP +name: Deploy DEV to host on: push: @@ -45,8 +45,9 @@ jobs: unzip -o archive.zip -d . rm archive.zip echo "INTERFACE_EDITOR_URL=https://json.ms" > .env + echo "ACCESS_CONTROL_ALLOW_ORIGIN=https://json.ms" >> .env echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env - echo "GOOGLE_OAUTH_CLIENT_ID=https://json.ms/files/" >> .env + echo "GOOGLE_OAUTH_CLIENT_ID=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env From 723f8370cebd18740985937fdf9aa6741df3938f Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 17 Mar 2025 15:59:31 -0400 Subject: [PATCH 11/25] fix google oauth error --- .env.example | 1 - .github/workflows/deploy-dev.yml | 2 +- .github/workflows/deploy-prod.yml | 2 +- src/controllers/SessionController.php | 22 +++++++++++++--------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.env.example b/.env.example index cab0765..362b5d7 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,6 @@ # General INTERFACE_EDITOR_URL=http://localhost:3000 ACCESS_CONTROL_ALLOW_ORIGIN=http://localhost:3000 -PUBLIC_FILE_PATH=http://localhost:9200/private/files/ JSONMS_CYPHER_KEY=urjMdK071cL935eKdczjEQ== # Database diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 4c631ec..f249f64 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -49,7 +49,7 @@ jobs: echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "GOOGLE_OAUTH_CLIENT_ID=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env - echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env + echo "GOOGLE_OAUTH_CALLBACK_URL=https://server.dev.json.ms/google/callback" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env echo "DATABASE_DBNAME=${{ secrets.DATABASE_DEV_DBNAME }}" >> .env echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index bd0af5a..491c771 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -49,7 +49,7 @@ jobs: echo "JSONMS_CYPHER_KEY=${{ secrets.JSONMS_CYPHER_KEY }}" >> .env echo "GOOGLE_OAUTH_CLIENT_ID=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env echo "GOOGLE_OAUTH_CLIENT_SECRET=${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}" >> .env - echo "GOOGLE_OAUTH_CALLBACK_URL=637442439591-qrrpb3v9d3n5m8b8gheorfa1fbi5o6qc.apps.googleusercontent.com" >> .env + echo "GOOGLE_OAUTH_CALLBACK_URL=https://server.json.ms/google/callback" >> .env echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env echo "DATABASE_DBNAME=${{ secrets.DATABASE_PROD_DBNAME }}" >> .env echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index e7f4de7..1a74e20 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -40,15 +40,18 @@ public function indexAction() { } else { - // Google Client Configuration - $client = new Google_Client(); - $client->setClientId($_ENV['GOOGLE_OAUTH_CLIENT_ID']); - $client->setClientSecret($_ENV['GOOGLE_OAUTH_CLIENT_SECRET']); - $client->setRedirectUri($_ENV['GOOGLE_OAUTH_CALLBACK_URL']); - $client->addScope('email'); - $client->addScope('profile'); - - $loginUrl = $client->createAuthUrl(); + try { + // Google Client Configuration + $client = new Google_Client(); + $client->setClientId($_ENV['GOOGLE_OAUTH_CLIENT_ID']); + $client->setClientSecret($_ENV['GOOGLE_OAUTH_CLIENT_SECRET']); + $client->setRedirectUri($_ENV['GOOGLE_OAUTH_CALLBACK_URL']); + $client->addScope('email'); + $client->addScope('profile'); + $loginUrl = $client->createAuthUrl(); + } catch(\Exception $e) { + throwError(500, $e->getMessage()); + } try { $oauth2 = new Google_Service_Oauth2($client); @@ -56,6 +59,7 @@ public function indexAction() { $loggedIn = true; } catch(\Exception $e) { $this->responseJson([ + 'error' => $e->getMessage(), 'loggedIn' => false, 'user' => $user, 'googleOAuthSignInUrl' => $loginUrl, From bf948594e35981014b50d38d2685b802ef6be8bf Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Wed, 26 Mar 2025 16:56:48 -0400 Subject: [PATCH 12/25] fix problem with obtaining user id when user failed logging process --- src/controllers/BaseController.php | 12 ++++++++---- src/controllers/GoogleController.php | 10 ++-------- src/controllers/InterfaceController.php | 14 +++++++------- src/controllers/SessionController.php | 17 ++++++++++++----- utils.php | 2 +- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/controllers/BaseController.php b/src/controllers/BaseController.php index c3d5031..fd91997 100644 --- a/src/controllers/BaseController.php +++ b/src/controllers/BaseController.php @@ -79,14 +79,18 @@ public function query(string $query, array $params = []): PDOStatement { return $this->queryRaw($sql, $params); } - public function getCurrentUser() { - if ($this->user == null) { + public function getCurrentUserId() { + if ($this->user == null && isset($_SESSION['user_id'])) { $stmt = $this->query('get-user-by-id', [ - 'id' => $_SESSION['user']['id'] + 'id' => $_SESSION['user_id'] ]); $this->user = $stmt->fetch(PDO::FETCH_OBJ); + if ($this->user) { + return $this->user->id; + } + return null; } - return $this->user; + return $this->user->id; } public function encrypt($data, $encryptionKey) { diff --git a/src/controllers/GoogleController.php b/src/controllers/GoogleController.php index 5bf9d5f..aec526b 100644 --- a/src/controllers/GoogleController.php +++ b/src/controllers/GoogleController.php @@ -30,6 +30,7 @@ public function callbackAction() { if ($stmt->rowCount() > 0) { // User exists, fetch data $user = $stmt->fetch(PDO::FETCH_ASSOC); + $userId = $user['id']; } else { // User does not exist, insert new user $this->query('insert-user', [ @@ -40,17 +41,10 @@ public function callbackAction() { ]); $userId = $this->getLastInsertedId(); // Get the new user's ID - $user = [ - 'id' => $userId, - 'googleId' => $userInfo->id, - 'name' => $userInfo->name, - 'email' => $userInfo->email, - 'avatar' => $userInfo->picture, - ]; } // Store user information in the session - $_SESSION['user'] = $user; + $_SESSION['user_id'] = $userId; $_SESSION['access_token'] = $token['access_token']; // Redirect to a protected page or dashboard diff --git a/src/controllers/InterfaceController.php b/src/controllers/InterfaceController.php index d21bf7c..6c0354d 100644 --- a/src/controllers/InterfaceController.php +++ b/src/controllers/InterfaceController.php @@ -6,7 +6,7 @@ class InterfaceController extends RestfulController { public function indexAction() { $stmt = $this->query('get-all-interfaces', [ - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); $users = $stmt->fetchAll(); $this->responseJson($users); @@ -30,7 +30,7 @@ public function createAction($data) { 'server_url' => $data->server_url, 'server_secret' => $serverSecret, 'cypher_key' => $encryptedCypherKey, - 'created_by' => $this->getCurrentUser()->id, + 'created_by' => $this->getCurrentUserId(), ]); // Get inserted interface @@ -56,11 +56,11 @@ public function updateAction($id, $data) { 'logo' => $data->logo, 'content' => $data->content, 'server_url' => $data->server_url, - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); // Clear all existing permissions (will be added later on) - if ($data->created_by === $this->getCurrentUser()->id) { + if ($data->created_by === $this->getCurrentUserId()) { $this->updatePermissions($data); } @@ -72,7 +72,7 @@ public function deleteAction($id) { if ($this->hasAccess($id)) { $stmt = $this->query('delete-interface', [ 'uuid' => $id, - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); if ($stmt->rowCount() > 0) { $this->responseJson(true); @@ -106,7 +106,7 @@ private function hasAccess($uuid, $showError = true): bool { private function getAccessibleInterface($uuid, $showError = true): false | stdClass { $stmt = $this->query('get-accessible-interface-by-uuid', [ 'uuid' => $uuid, - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); if ($stmt->rowCount() > 0) { $interface = $stmt->fetch(PDO::FETCH_OBJ); @@ -129,7 +129,7 @@ private function copyToHistory(stdClass $interface) { $this->query('insert-history', [ 'uuid' => $interface->uuid, 'content' => $interface->content, - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); } diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index 1a74e20..654d97e 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -15,7 +15,7 @@ public function indexAction() { // Check if user already exists $stmt = $this->query('get-user-by-id', [ - 'id' => $this->getCurrentUser()->id, + 'id' => $this->getCurrentUserId(), ]); if ($stmt->rowCount() > 0) { @@ -25,9 +25,8 @@ public function indexAction() { // Fetch all interfaces $stmt = $this->query('get-all-interfaces', [ - 'userId' => $this->getCurrentUser()->id, + 'userId' => $this->getCurrentUserId(), ]); - if ($stmt->rowCount() > 0) { $rows = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($rows as $row) { @@ -36,10 +35,18 @@ public function indexAction() { $interfaces[] = $row; } } + } else { + // Google Client Configuration + $client = new Google_Client(); + $client->setClientId($_ENV['GOOGLE_OAUTH_CLIENT_ID']); + $client->setClientSecret($_ENV['GOOGLE_OAUTH_CLIENT_SECRET']); + $client->setRedirectUri($_ENV['GOOGLE_OAUTH_CALLBACK_URL']); + $client->addScope('email'); + $client->addScope('profile'); + $loginUrl = $client->createAuthUrl(); } } else { - try { // Google Client Configuration $client = new Google_Client(); @@ -69,7 +76,7 @@ public function indexAction() { // Check if user already exists $stmt = $this->query('get-user-by-google-id', [ - 'id' => $this->getCurrentUser()->id, + 'id' => $this->getCurrentUserId(), ]); if ($stmt->rowCount() > 0) { diff --git a/utils.php b/utils.php index 6ecfcb3..79685f5 100644 --- a/utils.php +++ b/utils.php @@ -1,7 +1,7 @@ Date: Tue, 1 Apr 2025 15:25:22 -0400 Subject: [PATCH 13/25] new interface progresss --- LICENSE | 2 +- README.md | 3 ++ src/controllers/SessionController.php | 58 ++++++++++++++++++++------- src/queries/get-demo-interface.sql | 7 ++++ 4 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 README.md create mode 100644 src/queries/get-demo-interface.sql diff --git a/LICENSE b/LICENSE index 03e63df..25c0ab4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2025, Danny Coulombe +Copyright (c) 2025, JSON.ms Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md new file mode 100644 index 0000000..26f0138 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# @jsonms/server + +The server to use with your instance of [jsonms-www](https://github.com/JSON-ms/www). diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index 654d97e..2a21139 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -8,8 +8,19 @@ public function indexAction() { $loggedIn = isset($_SESSION['access_token']) && $_SESSION['access_token']; $user = null; - $interfaces = []; $loginUrl = null; + $interfaces = []; + + // Fetch demo interface + $stmt = $this->query('get-demo-interface'); + if ($stmt->rowCount() > 0) { + $rows = $stmt->fetchAll(PDO::FETCH_OBJ); + foreach ($rows as $row) { + $row->permission_admin = []; + $row->permission_interface = []; + $interfaces[] = $row; + } + } if ($loggedIn) { @@ -22,19 +33,6 @@ public function indexAction() { // User exists, fetch data $user = $stmt->fetch(PDO::FETCH_OBJ); - - // Fetch all interfaces - $stmt = $this->query('get-all-interfaces', [ - 'userId' => $this->getCurrentUserId(), - ]); - if ($stmt->rowCount() > 0) { - $rows = $stmt->fetchAll(PDO::FETCH_OBJ); - foreach ($rows as $row) { - $row->permission_admin = array_filter(explode(',', $row->permission_admin ?? '')); - $row->permission_interface = array_filter(explode(',', $row->permission_interface ?? '')); - $interfaces[] = $row; - } - } } else { // Google Client Configuration $client = new Google_Client(); @@ -84,6 +82,23 @@ public function indexAction() { } } + if ($loggedIn && isset($user)) { + + // Fetch all interfaces + $stmt = $this->query('get-all-interfaces', [ + 'userId' => $this->getCurrentUserId(), + ]); + $interfaces = []; + if ($stmt->rowCount() > 0) { + $rows = $stmt->fetchAll(PDO::FETCH_OBJ); + foreach ($rows as $row) { + $row->permission_admin = array_filter(explode(',', $row->permission_admin ?? '')); + $row->permission_interface = array_filter(explode(',', $row->permission_interface ?? '')); + $interfaces[] = $row; + } + } + } + $this->responseJson([ 'loggedIn' => $loggedIn && isset($user), 'user' => $user, @@ -107,11 +122,24 @@ public function logoutAction() { // Generate the login URL $loginUrl = $client->createAuthUrl(); + // Fetch demo interface + $interfaces = []; + $stmt = $this->query('get-demo-interface'); + if ($stmt->rowCount() > 0) { + $rows = $stmt->fetchAll(PDO::FETCH_OBJ); + foreach ($rows as $row) { + $row->permission_admin = []; + $row->permission_interface = []; + $interfaces[] = $row; + } + } + // Return the JSON response $this->responseJson([ 'loggedIn' => false, 'user' => null, - 'googleOAuthSignInUrl' => $loginUrl + 'googleOAuthSignInUrl' => $loginUrl, + 'interfaces' => $interfaces, ]); } } diff --git a/src/queries/get-demo-interface.sql b/src/queries/get-demo-interface.sql new file mode 100644 index 0000000..240a71c --- /dev/null +++ b/src/queries/get-demo-interface.sql @@ -0,0 +1,7 @@ +SELECT + i.*, + u.name AS owner_name +FROM interfaces AS i + INNER JOIN users AS u ON u.id = i.created_by +WHERE i.hash = "demo" +GROUP BY i.uuid From e8628ebcf65825b0fe2bbe87ce6cf17371ac205e Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Tue, 1 Apr 2025 20:22:20 -0400 Subject: [PATCH 14/25] fix read file cors issue --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4ad4450..ab3015c 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "ext-openssl": "*", "monolog/monolog": "^2.5", "psr/log": "^2.0", - "ext-pdo": "*" + "ext-pdo": "*", + "ext-fileinfo": "*" } -} \ No newline at end of file +} From 988176aac5d3d8790d9b5c05a333f37a1925a672 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Thu, 3 Apr 2025 08:54:31 -0400 Subject: [PATCH 15/25] fix permissions --- src/queries/get-all-interfaces.sql | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/queries/get-all-interfaces.sql b/src/queries/get-all-interfaces.sql index 4e5e9d9..540dab0 100644 --- a/src/queries/get-all-interfaces.sql +++ b/src/queries/get-all-interfaces.sql @@ -5,21 +5,22 @@ SELECT 'owner' AS type, u.name AS owner_name FROM interfaces AS i - INNER JOIN users AS u ON u.id = i.created_by - LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' - LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' + INNER JOIN users AS u ON u.id = i.created_by + LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' + LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' WHERE i.created_by = :userId GROUP BY i.uuid -UNION +UNION ALL SELECT i.*, null AS permission_interface, null AS permission_admin, - p.type, + GROUP_CONCAT(DISTINCT(p.type)) as type, owner.name AS owner_name FROM permissions AS p -INNER JOIN users AS u ON u.email = p.email -INNER JOIN interfaces AS i ON i.uuid = p.interface_uuid -INNER JOIN users AS owner ON owner.id = i.created_by + INNER JOIN users AS u ON u.email = p.email + INNER JOIN interfaces AS i ON i.uuid = p.interface_uuid + INNER JOIN users AS owner ON owner.id = i.created_by WHERE u.id = :userId +GROUP BY i.uuid From ec2516709595d187fd3e3c9ae4ccc431e519d60b Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Thu, 3 Apr 2025 09:05:17 -0400 Subject: [PATCH 16/25] version bump --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index ab3015c..d0b9615 100644 --- a/composer.json +++ b/composer.json @@ -1,4 +1,8 @@ { + "version": "1.0.0", + "name": "jsonms/server", + "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", + "license": "BSD-3-Clause", "require": { "google/apiclient": "^2.18", "vlucas/phpdotenv": "^5.6", From cb8336eac68a3da3161467033eca0bd5efc70575 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Thu, 3 Apr 2025 09:33:36 -0400 Subject: [PATCH 17/25] readme update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 26f0138..fcef110 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# @jsonms/server - -The server to use with your instance of [jsonms-www](https://github.com/JSON-ms/www). +# @jsonms/server + +The server to use with your instance of [jsonms-www](https://github.com/JSON-ms/www). From 2dec1f19562e576994bd52aaff64460a64aa3925 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Thu, 3 Apr 2025 09:46:16 -0400 Subject: [PATCH 18/25] return interface type --- src/controllers/SessionController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index 2a21139..fb5675a 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -18,6 +18,7 @@ public function indexAction() { foreach ($rows as $row) { $row->permission_admin = []; $row->permission_interface = []; + $row->type = 'interface,admin'; $interfaces[] = $row; } } @@ -130,6 +131,7 @@ public function logoutAction() { foreach ($rows as $row) { $row->permission_admin = []; $row->permission_interface = []; + $row->type = 'interface,admin'; $interfaces[] = $row; } } From c70e5ba93e76cdfd0d374058f21d64cdf69830a3 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Sun, 6 Apr 2025 11:10:11 -0400 Subject: [PATCH 19/25] new webhooks table support --- src/controllers/BaseController.php | 6 ++ src/controllers/InterfaceController.php | 29 +--------- src/controllers/SessionController.php | 59 ++++++++++++------- src/controllers/WebhookController.php | 72 ++++++++++++++++++++++++ src/queries/delete-webhook-by-uuid.sql | 3 + src/queries/get-all-interfaces.sql | 22 +++++--- src/queries/get-all-webhooks.sql | 5 ++ src/queries/get-demo-interface.sql | 7 ++- src/queries/get-interface-by-hash.sql | 7 ++- src/queries/get-interface-by-uuid.sql | 7 ++- src/queries/get-webhook-by-uuid.sql | 6 ++ src/queries/insert-interface.sql | 4 +- src/queries/insert-webhook.sql | 2 + src/queries/update-interface-by-uuid.sql | 2 +- src/queries/update-webhook-by-uuid.sql | 4 ++ 15 files changed, 173 insertions(+), 62 deletions(-) create mode 100644 src/controllers/WebhookController.php create mode 100644 src/queries/delete-webhook-by-uuid.sql create mode 100644 src/queries/get-all-webhooks.sql create mode 100644 src/queries/get-webhook-by-uuid.sql create mode 100644 src/queries/insert-webhook.sql create mode 100644 src/queries/update-webhook-by-uuid.sql diff --git a/src/controllers/BaseController.php b/src/controllers/BaseController.php index fd91997..45d6208 100644 --- a/src/controllers/BaseController.php +++ b/src/controllers/BaseController.php @@ -93,6 +93,12 @@ public function getCurrentUserId() { return $this->user->id; } + protected function getHash($length = 10): string { + $bytes = random_bytes($length); + $result = bin2hex($bytes); + return substr($result, 0, $length); + } + public function encrypt($data, $encryptionKey) { $ivLength = openssl_cipher_iv_length('AES-256-CBC'); $iv = openssl_random_pseudo_bytes($ivLength); diff --git a/src/controllers/InterfaceController.php b/src/controllers/InterfaceController.php index 6c0354d..81ad009 100644 --- a/src/controllers/InterfaceController.php +++ b/src/controllers/InterfaceController.php @@ -19,17 +19,13 @@ public function getAction($id) { public function createAction($data) { $hash = $this->getHash(); - $cypherKey = $this->getHash(24); - $serverSecret = $this->encrypt($this->getHash(24), $cypherKey); - $encryptedCypherKey = $this->encrypt($cypherKey, $_ENV['JSONMS_CYPHER_KEY']); + $this->query('insert-interface', [ 'hash' => $hash, 'label' => $data->label, 'logo' => $data->logo, 'content' => $data->content, - 'server_url' => $data->server_url, - 'server_secret' => $serverSecret, - 'cypher_key' => $encryptedCypherKey, + 'webhook' => $data->webhook, 'created_by' => $this->getCurrentUserId(), ]); @@ -55,7 +51,7 @@ public function updateAction($id, $data) { 'label' => $data->label, 'logo' => $data->logo, 'content' => $data->content, - 'server_url' => $data->server_url, + 'webhook' => $data->webhook, 'userId' => $this->getCurrentUserId(), ]); @@ -80,25 +76,6 @@ public function deleteAction($id) { } } - public function secretKeyAction($uuid) { - $interface = $this->getAccessibleInterface($uuid); - $decryptedCypherKey = $this->decrypt($interface->cypher_key, $_ENV['JSONMS_CYPHER_KEY']); - $decryptedServerKey = $this->decrypt($interface->server_secret, $decryptedCypherKey); - $this->responseJson($decryptedServerKey); - } - - public function cypherKeyAction($uuid) { - $interface = $this->getAccessibleInterface($uuid); - $decryptedCypherKey = $this->decrypt($interface->cypher_key, $_ENV['JSONMS_CYPHER_KEY']); - $this->responseJson($decryptedCypherKey); - } - - private function getHash($length = 10): string { - $bytes = random_bytes($length); - $result = bin2hex($bytes); - return substr($result, 0, $length); - } - private function hasAccess($uuid, $showError = true): bool { return (bool) $this->getAccessibleInterface($uuid, $showError); } diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index fb5675a..a6e21b7 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -4,14 +4,7 @@ class SessionController extends RestfulController { - public function indexAction() { - - $loggedIn = isset($_SESSION['access_token']) && $_SESSION['access_token']; - $user = null; - $loginUrl = null; - $interfaces = []; - - // Fetch demo interface + private function getDemoInterface() { $stmt = $this->query('get-demo-interface'); if ($stmt->rowCount() > 0) { $rows = $stmt->fetchAll(PDO::FETCH_OBJ); @@ -19,9 +12,35 @@ public function indexAction() { $row->permission_admin = []; $row->permission_interface = []; $row->type = 'interface,admin'; - $interfaces[] = $row; + return $row; } } + return null; + } + + private function getWebhooks($userId) { + $stmt = $this->query('get-all-webhooks', [ + 'userId' => $userId, + ]); + if ($stmt->rowCount() > 0) { + return $stmt->fetchAll(PDO::FETCH_OBJ); + } + return []; + } + + public function indexAction() { + + $loggedIn = isset($_SESSION['access_token']) && $_SESSION['access_token']; + $user = null; + $loginUrl = null; + $interfaces = []; + $webhooks = []; + + // Fetch demo interface + $demo = $this->getDemoInterface(); + if ($demo) { + $interfaces[] = $demo; + } if ($loggedIn) { @@ -70,6 +89,7 @@ public function indexAction() { 'user' => $user, 'googleOAuthSignInUrl' => $loginUrl, 'interfaces' => $interfaces, + 'webhooks' => $webhooks, ]); } @@ -100,11 +120,18 @@ public function indexAction() { } } + // Fetch demo interface + $loggedIn = $loggedIn && isset($user); + if ($loggedIn) { + $webhooks = $this->getWebhooks($user->id); + } + $this->responseJson([ - 'loggedIn' => $loggedIn && isset($user), + 'loggedIn' => $loggedIn, 'user' => $user, 'googleOAuthSignInUrl' => $loginUrl, 'interfaces' => $interfaces, + 'webhooks' => $webhooks, ]); } @@ -125,15 +152,9 @@ public function logoutAction() { // Fetch demo interface $interfaces = []; - $stmt = $this->query('get-demo-interface'); - if ($stmt->rowCount() > 0) { - $rows = $stmt->fetchAll(PDO::FETCH_OBJ); - foreach ($rows as $row) { - $row->permission_admin = []; - $row->permission_interface = []; - $row->type = 'interface,admin'; - $interfaces[] = $row; - } + $demo = $this->getDemoInterface(); + if ($demo) { + $interfaces[] = $demo; } // Return the JSON response diff --git a/src/controllers/WebhookController.php b/src/controllers/WebhookController.php new file mode 100644 index 0000000..ccf201f --- /dev/null +++ b/src/controllers/WebhookController.php @@ -0,0 +1,72 @@ +uuid)) { + $this->query('update-webhook-by-uuid', [ + 'uuid' => $webhook->uuid, + 'url' => $webhook->url, + 'userId' => $this->getCurrentUserId(), + ]); + } else { + $cypherKey = $this->getHash(24); + $serverSecret = $this->encrypt($this->getHash(24), $cypherKey); + $encryptedCypherKey = $this->encrypt($cypherKey, $_ENV['JSONMS_CYPHER_KEY']); + $this->query('insert-webhook', [ + 'url' => $webhook->url, + 'secret' => $serverSecret, + 'cypher' => $encryptedCypherKey, + 'created_by' => $this->getCurrentUserId(), + ]); + } + } + $stmt = $this->query('get-all-webhooks', [ + 'userId' => $this->getCurrentUserId(), + ]); + + if ($stmt->rowCount() > 0) { + $this->responseJson($stmt->fetchAll(PDO::FETCH_OBJ)); + } + } + + public function deleteAction($id) { + $stmt = $this->query('delete-webhook-by-uuid', [ + 'uuid' => $id, + 'userId' => $this->getCurrentUserId(), + ]); + if ($stmt->rowCount() > 0) { + $this->responseJson(true); + } + } + + public function secretKeyAction($uuid) { + $webhook = $this->getWebhook($uuid); + $decryptedCypherKey = $this->decrypt($webhook->cypher, $_ENV['JSONMS_CYPHER_KEY']); + $decryptedServerKey = $this->decrypt($webhook->secret, $decryptedCypherKey); + $this->responseJson($decryptedServerKey); + } + + public function cypherKeyAction($uuid) { + $webhook = $this->getWebhook($uuid); + $decryptedCypherKey = $this->decrypt($webhook->cypher, $_ENV['JSONMS_CYPHER_KEY']); + $this->responseJson($decryptedCypherKey); + } + + private function getWebhook($uuid, $showError = true): false | stdClass { + $stmt = $this->query('get-webhook-by-uuid', [ + 'uuid' => $uuid, + 'userId' => $this->getCurrentUserId(), + ]); + if ($stmt->rowCount() > 0) { + return $stmt->fetch(PDO::FETCH_OBJ); + } + if ($showError) { + throwError(403, 'You don\'t have permission to access this webhook'); + } + return false; + } +} diff --git a/src/queries/delete-webhook-by-uuid.sql b/src/queries/delete-webhook-by-uuid.sql new file mode 100644 index 0000000..2f482b0 --- /dev/null +++ b/src/queries/delete-webhook-by-uuid.sql @@ -0,0 +1,3 @@ +DELETE FROM webhooks +WHERE uuid = :uuid + AND created_by = :userId diff --git a/src/queries/get-all-interfaces.sql b/src/queries/get-all-interfaces.sql index 540dab0..b4d3f8a 100644 --- a/src/queries/get-all-interfaces.sql +++ b/src/queries/get-all-interfaces.sql @@ -3,24 +3,30 @@ SELECT GROUP_CONCAT(DISTINCT(pi.email)) as permission_interface, GROUP_CONCAT(DISTINCT(pa.email)) as permission_admin, 'owner' AS type, - u.name AS owner_name + u.name AS owner_name, + w.url AS server_url, + w.secret AS server_secret FROM interfaces AS i - INNER JOIN users AS u ON u.id = i.created_by - LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' - LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' + INNER JOIN users AS u ON u.id = i.created_by + LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' + LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' + LEFT JOIN webhooks AS w ON w.uuid = i.webhook WHERE i.created_by = :userId GROUP BY i.uuid UNION ALL SELECT i.*, - null AS permission_interface, - null AS permission_admin, - GROUP_CONCAT(DISTINCT(p.type)) as type, - owner.name AS owner_name + null AS permission_interface, + null AS permission_admin, + GROUP_CONCAT(DISTINCT(p.type)) as type, + owner.name AS owner_name, + w.url AS server_url, + w.secret AS server_secret FROM permissions AS p INNER JOIN users AS u ON u.email = p.email INNER JOIN interfaces AS i ON i.uuid = p.interface_uuid INNER JOIN users AS owner ON owner.id = i.created_by + LEFT JOIN webhooks AS w ON w.uuid = i.webhook WHERE u.id = :userId GROUP BY i.uuid diff --git a/src/queries/get-all-webhooks.sql b/src/queries/get-all-webhooks.sql new file mode 100644 index 0000000..ddcd0d5 --- /dev/null +++ b/src/queries/get-all-webhooks.sql @@ -0,0 +1,5 @@ +SELECT + w.* +FROM webhooks AS w +WHERE + w.created_by = :userId diff --git a/src/queries/get-demo-interface.sql b/src/queries/get-demo-interface.sql index 240a71c..e438369 100644 --- a/src/queries/get-demo-interface.sql +++ b/src/queries/get-demo-interface.sql @@ -1,7 +1,10 @@ SELECT i.*, - u.name AS owner_name + u.name AS owner_name, + w.url AS server_url, + w.secret AS server_secret FROM interfaces AS i - INNER JOIN users AS u ON u.id = i.created_by + INNER JOIN users AS u ON u.id = i.created_by + LEFT JOIN webhooks AS w ON w.uuid = i.webhook WHERE i.hash = "demo" GROUP BY i.uuid diff --git a/src/queries/get-interface-by-hash.sql b/src/queries/get-interface-by-hash.sql index ac2f793..04ea819 100644 --- a/src/queries/get-interface-by-hash.sql +++ b/src/queries/get-interface-by-hash.sql @@ -3,11 +3,14 @@ SELECT GROUP_CONCAT(DISTINCT(pi.email)) as permission_interface, GROUP_CONCAT(DISTINCT(pa.email)) as permission_admin, 'owner' AS type, - u.name AS owner_name + u.name AS owner_name, + w.url AS server_url, + w.secret AS server_secret FROM interfaces AS i INNER JOIN users AS u ON u.id = i.created_by LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' + LEFT JOIN webhooks AS w ON w.uuid = i.webhook WHERE i.hash = :hash GROUP BY - i.uuid, u.name; \ No newline at end of file + i.uuid, u.name; diff --git a/src/queries/get-interface-by-uuid.sql b/src/queries/get-interface-by-uuid.sql index 6305471..107721e 100644 --- a/src/queries/get-interface-by-uuid.sql +++ b/src/queries/get-interface-by-uuid.sql @@ -3,11 +3,14 @@ SELECT GROUP_CONCAT(DISTINCT(pi.email)) as permission_interface, GROUP_CONCAT(DISTINCT(pa.email)) as permission_admin, 'owner' AS type, - u.name AS owner_name + u.name AS owner_name, + w.url AS server_url, + w.secret AS server_secret FROM interfaces AS i INNER JOIN users AS u ON u.id = i.created_by LEFT JOIN permissions AS pa ON pa.interface_uuid = i.uuid AND pa.type = 'admin' LEFT JOIN permissions AS pi ON pi.interface_uuid = i.uuid AND pi.type = 'interface' + LEFT JOIN webhooks AS w ON w.uuid = i.webhook WHERE i.uuid = :uuid GROUP BY - i.uuid, u.name; \ No newline at end of file + i.uuid, u.name; diff --git a/src/queries/get-webhook-by-uuid.sql b/src/queries/get-webhook-by-uuid.sql new file mode 100644 index 0000000..d3fbc01 --- /dev/null +++ b/src/queries/get-webhook-by-uuid.sql @@ -0,0 +1,6 @@ +SELECT + w.* +FROM webhooks AS w +WHERE + w.uuid = :uuid + AND w.created_by = :userId diff --git a/src/queries/insert-interface.sql b/src/queries/insert-interface.sql index 26c344c..be1a49a 100644 --- a/src/queries/insert-interface.sql +++ b/src/queries/insert-interface.sql @@ -1,2 +1,2 @@ -INSERT INTO interfaces (hash, label, logo, content, server_url, server_secret, cypher_key, created_by) -VALUES (:hash, :label, :logo, :content, :server_url, :server_secret, :cypher_key, :created_by) +INSERT INTO interfaces (hash, label, logo, content, webhook, created_by) +VALUES (:hash, :label, :logo, :content, :webhook, :created_by) diff --git a/src/queries/insert-webhook.sql b/src/queries/insert-webhook.sql new file mode 100644 index 0000000..677bc26 --- /dev/null +++ b/src/queries/insert-webhook.sql @@ -0,0 +1,2 @@ +INSERT INTO webhooks (url, secret, cypher, created_by) +VALUES (:url, :secret, :cypher, :created_by) diff --git a/src/queries/update-interface-by-uuid.sql b/src/queries/update-interface-by-uuid.sql index 0f4b830..7825d99 100644 --- a/src/queries/update-interface-by-uuid.sql +++ b/src/queries/update-interface-by-uuid.sql @@ -1,3 +1,3 @@ UPDATE interfaces AS i -SET i.label = :label, i.logo = :logo, i.content = :content, i.server_url = :server_url, i.updated_at = NOW() +SET i.label = :label, i.logo = :logo, i.content = :content, i.webhook = :webhook, i.updated_at = NOW() WHERE i.uuid = :uuid diff --git a/src/queries/update-webhook-by-uuid.sql b/src/queries/update-webhook-by-uuid.sql new file mode 100644 index 0000000..a8630b4 --- /dev/null +++ b/src/queries/update-webhook-by-uuid.sql @@ -0,0 +1,4 @@ +UPDATE webhooks AS w +SET w.url = :url, w.updated_at = NOW() +WHERE w.uuid = :uuid + AND w.created_by = :userId From b012780d4346d7fe9e4bfc60928df191cfc8fa63 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Sun, 6 Apr 2025 11:15:21 -0400 Subject: [PATCH 20/25] new setup-hooks scripts for composer.json --- .pre-commit | 33 +++++++++++++++++++++++++++++++++ composer.json | 3 +++ 2 files changed, 36 insertions(+) create mode 100644 .pre-commit diff --git a/.pre-commit b/.pre-commit new file mode 100644 index 0000000..b13ff98 --- /dev/null +++ b/.pre-commit @@ -0,0 +1,33 @@ +#!/bin/bash + +# Path to composer.json +COMPOSER_FILE="composer.json" + +# Check if composer.json exists +if [ ! -f "$COMPOSER_FILE" ]; then + echo "$COMPOSER_FILE not found!" + exit 1 +fi + +# Use jq to bump the patch version +if command -v jq &> /dev/null; then + # Read the current version + CURRENT_VERSION=$(jq -r '.version' "$COMPOSER_FILE") + + # Split the version into an array + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION" + + # Increment the patch version + NEW_PATCH=$((PATCH + 1)) + + # Create the new version string + NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH" + + # Update the composer.json file + jq --arg new_version "$NEW_VERSION" '.version = $new_version' "$COMPOSER_FILE" > tmp.$.json && mv tmp.$.json "$COMPOSER_FILE" + + echo "Bumped version from $CURRENT_VERSION to $NEW_VERSION" +else + echo "jq is not installed. Please install jq to use this hook." + exit 1 +fi diff --git a/composer.json b/composer.json index d0b9615..a5fd7e8 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,9 @@ "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", + "scripts": { + "setup-hooks": "cp .pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit" + }, "require": { "google/apiclient": "^2.18", "vlucas/phpdotenv": "^5.6", From 0ddde9c6475af9c5649abc4f4a472a9d781f5622 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Sun, 6 Apr 2025 11:15:41 -0400 Subject: [PATCH 21/25] version bump --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a5fd7e8..1ed95ba 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "version": "1.0.0", + "version": "1.0.1", "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", From dd421020905b81161ff37085ccef1409d0e2e6f9 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Sun, 6 Apr 2025 11:17:16 -0400 Subject: [PATCH 22/25] version bump --- .pre-commit | 3 +++ composer.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.pre-commit b/.pre-commit index b13ff98..dfe205e 100644 --- a/.pre-commit +++ b/.pre-commit @@ -27,6 +27,9 @@ if command -v jq &> /dev/null; then jq --arg new_version "$NEW_VERSION" '.version = $new_version' "$COMPOSER_FILE" > tmp.$.json && mv tmp.$.json "$COMPOSER_FILE" echo "Bumped version from $CURRENT_VERSION to $NEW_VERSION" + + # Stage the changes to package.json + git add composer.json else echo "jq is not installed. Please install jq to use this hook." exit 1 diff --git a/composer.json b/composer.json index 1ed95ba..ee00c76 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "version": "1.0.1", + "version": "1.0.4", "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", From 80761183cd68787c581ad39bc852251fb426ef4a Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Sun, 6 Apr 2025 11:18:44 -0400 Subject: [PATCH 23/25] version bump --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ee00c76..cecae97 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "version": "1.0.4", + "version": "1.0.6", "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", From 3a13ce910167a0de69c7787ec6d3c9d319095cb9 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 7 Apr 2025 08:06:59 -0400 Subject: [PATCH 24/25] fix webhook list null when logging out --- composer.json | 2 +- src/controllers/SessionController.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index cecae97..76c2959 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "version": "1.0.6", + "version": "1.0.7", "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", diff --git a/src/controllers/SessionController.php b/src/controllers/SessionController.php index a6e21b7..1618233 100644 --- a/src/controllers/SessionController.php +++ b/src/controllers/SessionController.php @@ -163,6 +163,7 @@ public function logoutAction() { 'user' => null, 'googleOAuthSignInUrl' => $loginUrl, 'interfaces' => $interfaces, + 'webhooks' => [], ]); } } From 65e8acb5e4b74d2250d96e4aa3cd7af87b4b6178 Mon Sep 17 00:00:00 2001 From: Danny Coulombe Date: Mon, 7 Apr 2025 08:07:17 -0400 Subject: [PATCH 25/25] handle frontend error logging --- composer.json | 2 +- src/controllers/ErrorController.php | 29 +++++++++++++++++++++++++++++ src/queries/insert-error.sql | 3 +++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/controllers/ErrorController.php create mode 100644 src/queries/insert-error.sql diff --git a/composer.json b/composer.json index 76c2959..930a198 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "version": "1.0.7", + "version": "1.0.8", "name": "jsonms/server", "description": "The JSON.ms Request Handler Server is a robust backend solution designed to manage and process all incoming requests from the main JSON.ms website.", "license": "BSD-3-Clause", diff --git a/src/controllers/ErrorController.php b/src/controllers/ErrorController.php new file mode 100644 index 0000000..0ac1cb1 --- /dev/null +++ b/src/controllers/ErrorController.php @@ -0,0 +1,29 @@ +query('insert-error', [ + 'key' => $error->key, + 'message' => $error->message, + 'source' => $error->source, + 'line' => $error->line, + 'column' => $error->column, + 'stack' => $error->stack, + 'occurred_on' => $error->occurred_on, + 'last_timestamp' => $error->last_timestamp, + 'version' => $error->version, + 'route' => $error->route, + 'count' => $error->count, + 'user_agent' => $error->user_agent, + 'created_by' => $this->getCurrentUserId(), + ]); + } + + $this->responseJson(true); + } +} diff --git a/src/queries/insert-error.sql b/src/queries/insert-error.sql new file mode 100644 index 0000000..cbec6db --- /dev/null +++ b/src/queries/insert-error.sql @@ -0,0 +1,3 @@ +INSERT INTO errors (`key`, `message`, `source`, `line`, `column`, `stack`, `occurred_on`, `last_timestamp`, `version`, `route`, `count`, `user_agent`, `created_by`) +VALUES (:key, :message, :source, :line, :column, :stack, :occurred_on, :last_timestamp, :version, :route, :count, :user_agent, :created_by) +ON DUPLICATE KEY UPDATE `count` = `count` + :count, `updated_at` = NOW(); \ No newline at end of file