diff --git a/.gitignore b/.gitignore index 808ffe5..f510506 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules/ -demo/ +demo-app/ .DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 106f917..5ccf3f9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Add [PHP](https://www.php.net/), [Composer](https://getcomposer.org/), [MySQL](https://mariadb.org/), [phpMyAdmin](https://www.phpmyadmin.net/) and [PHP CRUD API](https://github.com/mevdschee/php-crud-api) to your local development environment. -You might be interested in a simple [JavaScript API Wrapper](https://github.com/scriptPilot/js-php-mysql-crud-api) or a [Local Persistent Database + MySQL Sync](https://github.com/scriptPilot/pouchdb-mysql/). +You might be interested in a simple [Synchronization between local IndexedDB and MySQL Database](https://github.com/scriptPilot/dexie-mysql-sync). ## Installation @@ -24,6 +24,8 @@ You might be interested in a simple [JavaScript API Wrapper](https://github.com/ - Run `npm run backend` to start the backend - Open the PHP server at http://localhost:8000 + - API endpoint at http://localhost:8000/api.php + - example: http://localhost:8000/api.php/records/tasks - Open phpMyAdmin at http://localhost:8080 - Login with username `root` and password `root` - Use the PHP CRUD API in frontend with `/api.php` @@ -52,8 +54,9 @@ Report bugs in the [issues list](https://github.com/scriptPilot/add-php-backend/ ## Maintainer -1. Apply changes -2. Run `npm run backend` to build the `demo` folder -3. Commit changes with an issue (closure) reference -4. Run `npm version patch | minor | major` and push changes -5. Let the workflow manage the release to GitHub and NPM +1. Apply changes to the code +2. Run `npm run demo` to build and start the `demo-app` +3. Apply changes to the `README.md` file and screenshots +4. Commit changes with an issue (closure) reference +5. Run `npm version patch | minor | major` and push changes +6. Let the workflow manage the release to GitHub and NPM diff --git a/package-lock.json b/package-lock.json index e5105e0..a7573ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "add-php-backend", - "version": "1.8.2", + "version": "1.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "add-php-backend", - "version": "1.8.2", + "version": "1.10.0", "license": "MIT", "dependencies": { "fs-extra": "^11.2.0", diff --git a/package.json b/package.json index 2b3ac81..651f1e5 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "add-php-backend", - "version": "1.8.2", + "version": "1.10.0", "description": "", "main": "src/index.js", "bin": "src/index.js", "type": "module", "scripts": { "test": "", - "backend": "rm -rf demo && node . && cd demo && npm run backend", + "demo": "rm -rf demo-app && npm create vite demo-app -- --template react && node . && cd demo-app && npm install && npm run dev", "preversion": "npm install && npm test" }, "repository": { diff --git a/src/index.js b/src/index.js index c4db0d0..6130c59 100755 --- a/src/index.js +++ b/src/index.js @@ -10,7 +10,7 @@ import fs from 'fs-extra' const scriptFolder = path.dirname(url.fileURLToPath(import.meta.url)) const processFolder = process.cwd() const isDevMode = processFolder === path.resolve(scriptFolder, '..') -const appFolder = isDevMode ? path.resolve(scriptFolder, '../demo') : processFolder +const appFolder = isDevMode ? path.resolve(scriptFolder, '../demo-app') : processFolder const templateFolder = path.resolve(scriptFolder, 'templates') // Define files @@ -68,7 +68,6 @@ const serverStr = ` },` const proxyStr = ` proxy: { - // eslint-disable-next-line no-useless-escape '^(.+)\\\\.php': 'http://localhost:8000/', },` if (!viteConfigFileContent.match(regexStartOfServer)) { diff --git a/src/templates/public/api.php b/src/templates/public/api.php index d14e7c9..85f792e 100644 --- a/src/templates/public/api.php +++ b/src/templates/public/api.php @@ -1,44 +1,58 @@ MYSQL_DATABASE === 'development', - // Database Credentials + // Credentials 'address' => MYSQL_HOST, 'database' => MYSQL_DATABASE, 'username' => MYSQL_USERNAME, 'password' => MYSQL_PASSWORD, - // Database Authentication - 'middlewares' => 'dbAuth,authorization', + // Middlewares + 'middlewares' => 'dbAuth,authorization,multiTenancy', + + // Database authentication 'dbAuth.mode' => 'optional', 'dbAuth.registerUser' => '1', + 'dbAuth.passwordLength' => '3', + + // Database Authorization 'authorization.tableHandler' => function ($operation, $tableName) { + + // No access to the users table if ($tableName === 'users') return false; + + // Access to all other tables return true; - } - + + }, + + // Multi Tenancy + 'multiTenancy.handler' => function ($operation, $tableName) { + + // For all tables, limit access to the current user + return ['userId' => $_SESSION['user']['id'] ?? 0]; + + }, + ]); // Initialization diff --git a/src/templates/schema.sql b/src/templates/schema.sql index 3e7beb5..2f86c63 100644 --- a/src/templates/schema.sql +++ b/src/templates/schema.sql @@ -1,11 +1,12 @@ CREATE TABLE IF NOT EXISTS `users` ( - `id` INTEGER(4) NOT NULL PRIMARY KEY AUTO_INCREMENT, + `id` INTEGER(8) NOT NULL PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(255) NOT NULL, `password` VARCHAR(255) NOT NULL -); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; CREATE TABLE IF NOT EXISTS `tasks` ( - `id` INTEGER(4) NOT NULL PRIMARY KEY AUTO_INCREMENT, - `title` VARCHAR(255) NOT NULL, + `id` INTEGER(8) NOT NULL PRIMARY KEY AUTO_INCREMENT, + `userId` INTEGER(8) NOT NULL DEFAULT 0, + `title` VARCHAR(255) NOT NULL DEFAULT "", `done` TINYINT(1) NOT NULL DEFAULT 0 -); \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; \ No newline at end of file diff --git a/src/templates/testdata.sql b/src/templates/testdata.sql index 7732132..4d13f7f 100644 --- a/src/templates/testdata.sql +++ b/src/templates/testdata.sql @@ -1,5 +1,2 @@ -INSERT IGNORE INTO `users` (`id`, `username`, `password`) -VALUES (1, "root", "cm9vdA=="); - INSERT IGNORE INTO `tasks` (`id`, `title`, `done`) VALUES (1, "First Task", 1), (2, "Second Task", 0), (3, "Third Task", 1); \ No newline at end of file