aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpack <pack@packgekko.xyz>2026-08-12 17:06:50 +0000
committerpack <pack@packgekko.xyz>2026-08-12 17:06:50 +0000
commit5611527e313c4add16c432e5cf9d55a987558c02 (patch)
tree59ad054325096b6305277b94982bbe7f7f585f59
parentd3adc16a08d95d6e331de55d7d3bf05a66a874a8 (diff)
downloadcrud-5611527e313c4add16c432e5cf9d55a987558c02.tar.gz
final commit
-rw-r--r--.gitignore3
-rw-r--r--README.md61
-rw-r--r--db.js28
-rw-r--r--middleware/auth.js10
-rw-r--r--package-lock.json668
-rw-r--r--package.json23
-rw-r--r--routes/auth.js76
-rw-r--r--routes/tasks.js54
-rw-r--r--server.js20
9 files changed, 258 insertions, 685 deletions
diff --git a/.gitignore b/.gitignore
index 3269e1c..190ab61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,9 +6,11 @@
*.cmd
*.d
*.dSYM/
+*.db
*.dll
*.dylib
*.elf
+*.env
*.exe
*.exp
*.gch
@@ -31,6 +33,7 @@
*.pdb
*.so
*.so.*
+*.sqlite
*.su
*.x86_64
.tmp_versions/
diff --git a/README.md b/README.md
index e69de29..5ccb65f 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,61 @@
+![screenshot](img_crud_logo.png)
+
+A minimal task management API with user authentication, built with express and better-sqlite3.
+
+![screenshot](img_screenshot.png)
+
+
+
+~download
+
+You can get a copy using git with the following command:
+
+```bash
+git clone https://git.200l.xyz/crud
+```
+
+
+
+~features
+
+- Create, read, update, and delete tasks.
+- User authentication with sessions.
+- Per-user task isolation.
+- Lightweight sqlite database, no external db server needed.
+
+
+
+~dependencies
+
+- node.js
+- express
+- better-sqlite3
+
+
+
+~development
+
+Install dependencies and start the server:
+
+```bash
+npm install
+node server.js
+```
+
+
+
+~usage
+
+Register a user, log in, and manage tasks via the rest api:
+
+| Method | Endpoint | Description | Body |
+|----------|----------------|----------------------|-----------------------------------|
+| `POST` | `/tasks` | Create a new task | `{ "title": "...", "description": "..." }` |
+| `GET` | `/tasks` | Get all tasks | — |
+| `GET` | `/tasks/:id` | Get a single task | — |
+| `PUT` | `/tasks/:id` | Update a task | `{ "title": "...", "description": "...", "done": 0 }` |
+| `DELETE` | `/tasks/:id` | Delete a task | — |
+
+~license
+
+Trinity
diff --git a/db.js b/db.js
index 1ca5195..468441a 100644
--- a/db.js
+++ b/db.js
@@ -1,9 +1,21 @@
-const sqlite3 = require('sqlite3').verbose();
-const db = new sqlite3.Database('./app.db');
-db.serialize(() => {
- db.run(`CREATE TABLE IF NOT EXISTS users (
- id INTEGER PRIMARY KEY, username TEXT UNIQUE, password TEXT)`);
- db.run(`CREATE TABLE IF NOT EXISTS items (
- id INTEGER PRIMARY KEY, user_id INTEGER, title TEXT, content TEXT)`);
-});
+const Database = require('better-sqlite3');
+const db = new Database('./crud.db');
+
+db.exec(`
+ CREATE TABLE IF NOT EXISTS users (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ username TEXT UNIQUE NOT NULL,
+ password TEXT NOT NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS tasks (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER NOT NULL,
+ title TEXT NOT NULL,
+ description TEXT,
+ done INTEGER DEFAULT 0,
+ FOREIGN KEY (user_id) REFERENCES users(id)
+ )
+`);
+
module.exports = db;
diff --git a/middleware/auth.js b/middleware/auth.js
index e69de29..4f98a81 100644
--- a/middleware/auth.js
+++ b/middleware/auth.js
@@ -0,0 +1,10 @@
+function requireAuth(req, res, next)
+{
+ if (req.session.userId)
+ {
+ return next();
+ }
+ res.status(401).json({ error: 'Not authenticated' });
+}
+
+module.exports = requireAuth;
diff --git a/package-lock.json b/package-lock.json
index 0cbdc70..4f26e79 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,31 +9,9 @@
"version": "1.0.0",
"dependencies": {
"bcryptjs": "^3.0.3",
+ "better-sqlite3": "^13.0.3",
"express": "^5.2.1",
- "express-session": "^1.19.0",
- "sqlite3": "^6.0.1"
- }
- },
- "node_modules/@isaacs/fs-minipass": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
- "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^7.0.4"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/abbrev": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz",
- "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==",
- "license": "ISC",
- "optional": true,
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "express-session": "^1.19.0"
}
},
"node_modules/accepts": {
@@ -49,26 +27,6 @@
"node": ">= 0.6"
}
},
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "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/bcryptjs": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
@@ -78,24 +36,16 @@
"bcrypt": "bin/bcrypt"
}
},
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "node_modules/better-sqlite3": {
+ "version": "13.0.3",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz",
+ "integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==",
"license": "MIT",
"dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
+ "node-addon-api": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=22"
}
},
"node_modules/body-parser": {
@@ -135,30 +85,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "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",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -197,15 +123,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/chownr": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
- "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/content-disposition": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
@@ -263,30 +180,6 @@
}
}
},
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -296,15 +189,6 @@
"node": ">= 0.8"
}
},
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -334,25 +218,6 @@
"node": ">= 0.8"
}
},
- "node_modules/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -398,22 +263,6 @@
"node": ">= 0.6"
}
},
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/exponential-backoff": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
- "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
- "license": "Apache-2.0",
- "optional": true
- },
"node_modules/express": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
@@ -501,30 +350,6 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
"node_modules/finalhandler": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
@@ -564,12 +389,6 @@
"node": ">= 0.8"
}
},
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -616,12 +435,6 @@
"node": ">= 0.4"
}
},
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -634,13 +447,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC",
- "optional": true
- },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -701,38 +507,12 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "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": "BSD-3-Clause"
- },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "license": "ISC"
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -748,16 +528,6 @@
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
- "node_modules/isexe": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz",
- "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==",
- "license": "BlueOak-1.0.0",
- "optional": true,
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -817,66 +587,12 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
- "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/minizlib": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
- "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "license": "MIT"
- },
"node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
@@ -886,18 +602,6 @@
"node": ">= 0.6"
}
},
- "node_modules/node-abi": {
- "version": "3.94.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz",
- "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/node-addon-api": {
"version": "8.9.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.1.tgz",
@@ -907,47 +611,6 @@
"node": "^18 || ^20 || >= 21"
}
},
- "node_modules/node-gyp": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz",
- "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "env-paths": "^2.2.0",
- "exponential-backoff": "^3.1.1",
- "graceful-fs": "^4.2.6",
- "nopt": "^9.0.0",
- "proc-log": "^6.0.0",
- "semver": "^7.3.5",
- "tar": "^7.5.4",
- "tinyglobby": "^0.2.12",
- "undici": "^6.25.0",
- "which": "^6.0.0"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
- "node_modules/nopt": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz",
- "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "abbrev": "^4.0.0"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -1009,56 +672,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/proc-log": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz",
- "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==",
- "license": "ISC",
- "optional": true,
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1072,16 +685,6 @@
"node": ">= 0.10"
}
},
- "node_modules/pump": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
"node_modules/qs": {
"version": "6.15.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
@@ -1135,35 +738,6 @@
"node": ">= 0.10"
}
},
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@@ -1206,18 +780,6 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
- "node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/send": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
@@ -1341,78 +903,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "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/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "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",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/sqlite3": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-6.0.1.tgz",
- "integrity": "sha512-X0czUUMG2tmSqJpEQa3tCuZSHKIx8PwM53vLZzKp/o6Rpy25fiVfjdbnZ988M8+O3ZWR1ih0K255VumCb3MAnQ==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "bindings": "^1.5.0",
- "node-addon-api": "^8.0.0",
- "prebuild-install": "^7.1.3",
- "tar": "^7.5.10"
- },
- "engines": {
- "node": ">=20.17.0"
- },
- "optionalDependencies": {
- "node-gyp": "12.x"
- },
- "peerDependencies": {
- "node-gyp": "12.x"
- },
- "peerDependenciesMeta": {
- "node-gyp": {
- "optional": true
- }
- }
- },
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -1422,91 +912,6 @@
"node": ">= 0.8"
}
},
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/tar": {
- "version": "7.5.22",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz",
- "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/fs-minipass": "^4.0.0",
- "chownr": "^3.0.0",
- "minipass": "^7.1.2",
- "minizlib": "^3.1.0",
- "yallist": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
- "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-fs/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -1516,18 +921,6 @@
"node": ">=0.6"
}
},
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/type-is": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
@@ -1571,16 +964,6 @@
"node": ">= 0.8"
}
},
- "node_modules/undici": {
- "version": "6.28.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
- "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=18.17"
- }
- },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -1590,12 +973,6 @@
"node": ">= 0.8"
}
},
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -1605,36 +982,11 @@
"node": ">= 0.8"
}
},
- "node_modules/which": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz",
- "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "isexe": "^4.0.0"
- },
- "bin": {
- "node-which": "bin/which.js"
- },
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
- },
- "node_modules/yallist": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
- "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
}
}
}
diff --git a/package.json b/package.json
index 195e72a..3eb8ad4 100644
--- a/package.json
+++ b/package.json
@@ -1,19 +1,22 @@
{
"name": "crud",
"version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "main": "server.js",
+ "scripts":
+ {
+ "start": "node server.js",
+ "dev": "nodemon server.js"
},
- "keywords": [],
"type": "commonjs",
- "start": "node app.js"
- "dev": "nodemon app.js"
- "dependencies": {
+ "dependencies":
+ {
"bcryptjs": "^3.0.3",
+ "better-sqlite3": "^13.0.3",
"express": "^5.2.1",
- "express-session": "^1.19.0",
- "sqlite3": "^6.0.1"
+ "express-session": "^1.19.0"
+ },
+ "allowScripts":
+ {
+ "better-sqlite3@13.0.3": true
}
}
diff --git a/routes/auth.js b/routes/auth.js
index e69de29..d6949d4 100644
--- a/routes/auth.js
+++ b/routes/auth.js
@@ -0,0 +1,76 @@
+const express = require('express');
+const bcrypt = require('bcryptjs');
+const db = require('../db');
+const requireAuth = require('../middleware/auth');
+
+const router = express.Router();
+
+/* register */
+router.post('/register', async (req, res) =>
+{
+ const { username, password } = req.body;
+ if (!username || !password)
+ {
+ return res.status(400).json({ error: 'Username and password required' });
+ }
+ try
+ {
+ const existing = db.prepare('SELECT id FROM users WHERE username = ?').get(username);
+ if (existing)
+ {
+ return res.status(409).json({ error: 'Username already taken' });
+ }
+ const hashed = bcrypt.hashSync(password, 10);
+ const result = db.prepare('INSERT INTO users (username, password) VALUES (?, ?)').run(username, hashed);
+ req.session.userId = result.lastInsertRowid;
+ res.status(201).json({ id: result.lastInsertRowid, username });
+ } catch (err)
+ {
+ res.status(500).json({ error: 'Registration failed' });
+ }
+});
+
+/* login. */
+router.post('/login', async (req, res) =>
+{
+ const { username, password } = req.body;
+ if (!username || !password)
+ {
+ return res.status(400).json({ error: 'Username and password required' });
+ }
+ try
+ {
+ const user = db.prepare('SELECT * FROM users WHERE username = ?').get(username);
+ if (!user || !bcrypt.compareSync(password, user.password))
+ {
+ return res.status(401).json({ error: 'Invalid username or password' });
+ }
+ req.session.userId = user.id;
+ res.json({ id: user.id, username: user.username });
+ } catch (err)
+ {
+ res.status(500).json({ error: 'Login failed' });
+ }
+});
+
+/* logout */
+router.post('/logout', (req, res) =>
+{
+ req.session.destroy(() =>
+ {
+ res.clearCookie('connect.sid');
+ res.json({ message: 'Logged out' });
+ });
+});
+
+/* check session */
+router.get('/check', (req, res) =>
+{
+ if (req.session.userId)
+ {
+ return res.json({ loggedIn: true });
+ }
+ res.status(401).json({ loggedIn: false });
+});
+
+module.exports = router;
diff --git a/routes/tasks.js b/routes/tasks.js
index e69de29..99b1748 100644
--- a/routes/tasks.js
+++ b/routes/tasks.js
@@ -0,0 +1,54 @@
+const express = require('express');
+const db = require('../db');
+const auth = require('../middleware/auth');
+const router = express.Router();
+
+/* all routes require login. */
+router.use(auth);
+
+/* create. */
+router.post('/', (req, res) =>
+{
+ const { title, description } = req.body;
+ if (!title) return res.status(400).json({ error: 'Title required' });
+ const result = db.prepare(
+ 'INSERT INTO tasks (user_id, title, description) VALUES (?, ?, ?)'
+ ).run(req.session.userId, title, description || '');
+ res.json({ id: result.lastInsertRowid, title, description: description || '', done: 0 });
+});
+
+/* read all. */
+router.get('/', (req, res) =>
+{
+ const rows = db.prepare('SELECT * FROM tasks WHERE user_id = ?').all(req.session.userId);
+ res.json(rows);
+});
+
+/* read on. */
+router.get('/:id', (req, res) =>
+{
+ const row = db.prepare('SELECT * FROM tasks WHERE id = ? AND user_id = ?').get(req.params.id, req.session.userId);
+ if (!row) return res.status(404).json({ error: 'Task not found' });
+ res.json(row);
+});
+
+/* update. */
+router.put('/:id', (req, res) =>
+{
+ const { title, description, done } = req.body;
+ const result = db.prepare(
+ 'UPDATE tasks SET title = COALESCE(?, title), description = COALESCE(?, description), done = COALESCE(?, done) WHERE id = ? AND user_id = ?'
+ ).run(title, description, done, req.params.id, req.session.userId);
+ if (result.changes === 0) return res.status(404).json({ error: 'Task not found' });
+ res.json({ id: Number(req.params.id), title, description, done });
+});
+
+/* delete. */
+router.delete('/:id', (req, res) =>
+{
+ const result = db.prepare('DELETE FROM tasks WHERE id = ? AND user_id = ?').run(req.params.id, req.session.userId);
+ if (result.changes === 0) return res.status(404).json({ error: 'Task not found' });
+ res.json({ message: 'Deleted' });
+});
+
+module.exports = router;
diff --git a/server.js b/server.js
index a663c83..fbe0d63 100644
--- a/server.js
+++ b/server.js
@@ -1,19 +1,21 @@
const express = require('express');
const session = require('express-session');
+const requireAuth = require('./middleware/auth');
+
const app = express();
-app.use(express.urlencoded({ extended: true }));
app.use(express.json());
+app.use(express.static('public'));
+
app.use(session({
- secret: 'change-this-secret',
+ secret: 'zxcv1234',
resave: false,
- saveUninitialized: false
+ saveUninitialized: false,
+ cookie: { maxAge: 1000 * 60 * 60 * 24 } /* 1 day. */
}));
-const authRoutes = require('./routes/auth');
-const taskRoutes = require('./routes/tasks');
-
-app.use('/auth', authRoutes);
-app.use('/tasks', taskRoutes);
+app.use('/auth', require('./routes/auth'));
+app.use('/tasks', requireAuth, require('./routes/tasks')); /* protect task routes. */
-app.listen(3000, () => console.log('running on http://localhost:3000'));
+const PORT = process.env.PORT || 3000;
+app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));