diff --git a/.dockerignore b/.dockerignore index 5029788..c8b4810 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,3 +6,6 @@ .git docker-run.sh docker-build.sh +images +images* +*.db* diff --git a/.gitignore b/.gitignore index f802313..24ff8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ images +images* node_modules tinypin.db +tinypin.db* .DS_Store chrome-extension.crx chrome-extension.pem \ No newline at end of file diff --git a/TODO.md b/TODO.md index 8c68533..369f160 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,9 @@ # todo list -- update brick layout algo to be height aware, rather than simply add to columns in order -- check breakpoints for iOS -- add hidden flag to boards / control +- --update brick layout algo to be height aware, rather than simply add to columns in order-- +- --check breakpoints for iOS-- +- --add hidden flag to boards / control-- - add change password function -- add logged in user name to menu -- addpin.html remember last board +- --add logged in user name to menu-- +- --addpin.html remember last board-- diff --git a/server.js b/server.js index c6a03e0..5c1be72 100644 --- a/server.js +++ b/server.js @@ -200,6 +200,7 @@ app.use ( async (req, res, next) => { if ( !req.user ){ res.redirect("/login"); + return; } if ( req.method == "GET" && req.originalUrl == "/logout" ){ @@ -247,6 +248,10 @@ const ALREADY_EXISTS = {status: "error", error: "already exists"}; const SERVER_ERROR = {status: "error", error: "server error"}; +app.get("/api/whoami", (req, res) => { + res.send({name: req.user.name}); +}); + // list boards app.get("/api/boards", async (req, res) => { try{ @@ -290,7 +295,7 @@ app.get("/api/boards/:boardId", async (req, res) => { // create board app.post('/api/boards', (req, res) => { try{ - let result = db.prepare("INSERT INTO boards (name, userId, createDate) VALUES (@name, @userId, @createDate)").run({name: req.body.name, userId: req.user.id, createDate: new Date().toISOString()}); + let result = db.prepare("INSERT INTO boards (name, userId, hidden, createDate) VALUES (@name, @userId, @hidden, @createDate)").run({name: req.body.name, userId: req.user.id, hidden: req.body.hidden, createDate: new Date().toISOString()}); let id = result.lastInsertRowid; let board = db.prepare("SELECT * FROM boards WHERE userId = @userId and id = @boardId").get({userId: req.user.id, boardId: id}); board.titlePinId = 0; @@ -310,7 +315,7 @@ app.post('/api/boards', (req, res) => { // update board app.post("/api/boards/:boardId", (req, res) =>{ try{ - let result = db.prepare("UPDATE boards SET name = @name WHERE userId = @userId and id = @boardId").run({name: req.body.name, userId: req.user.id, boardId: req.params.boardId}); + let result = db.prepare("UPDATE boards SET name = @name, hidden = @hidden WHERE userId = @userId and id = @boardId").run({name: req.body.name, hidden: req.body.hidden, userId: req.user.id, boardId: req.params.boardId}); if ( result.changes == 1 ){ res.send(OK); } else { @@ -498,65 +503,102 @@ function initDb(){ `).run(); let schemaVersion = db.prepare('select max(id) as id from migrations').get().id; + let isNewDb = false; + let createdBackup = false; if ( !schemaVersion || schemaVersion < 1 ){ console.log(" running migration v1"); + isNewDb = true; - db.prepare(` - CREATE TABLE users ( - id INTEGER NOT NULL PRIMARY KEY, - username TEXT NOT NULL UNIQUE, - key TEXT NOT NULL, - salt TEXT NOT NULL, - createDate TEXT - ) - `).run(); + db.transaction( () => { - db.prepare(` - CREATE TABLE properties ( - key TEXT NOT NULL UNIQUE PRIMARY KEY, - value TEXT NOT NULL + db.prepare(` + CREATE TABLE users ( + id INTEGER NOT NULL PRIMARY KEY, + username TEXT NOT NULL UNIQUE, + key TEXT NOT NULL, + salt TEXT NOT NULL, + createDate TEXT ) - `).run(); + `).run(); - db.prepare(` - CREATE TABLE boards ( - id INTEGER NOT NULL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - userId INTEGER NOT NULL, - createDate TEXT, - - FOREIGN KEY (userId) REFERENCES users(id) + db.prepare(` + CREATE TABLE properties ( + key TEXT NOT NULL UNIQUE PRIMARY KEY, + value TEXT NOT NULL + ) + `).run(); + + db.prepare(` + CREATE TABLE boards ( + id INTEGER NOT NULL PRIMARY KEY, + name TEXT NOT NULL UNIQUE, + userId INTEGER NOT NULL, + createDate TEXT, + + FOREIGN KEY (userId) REFERENCES users(id) + ) + `).run(); + + // autoincrement on pins so that pin ids are stable and are not reused. + // this allows for better caching of images + db.prepare(` + CREATE TABLE pins ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + boardId INTEGER NOT NULL, + imageUrl TEXT, + siteUrl TEXT, + description TEXT, + sortOrder INTEGER, + originalHeight INTEGER, + originalWidth INTEGER, + thumbnailHeight INTEGER, + thumbnailWidth INTEGER, + userId INTEGER NOT NULL, + createDate TEXT, + + FOREIGN KEY (boardId) REFERENCES boards(id), + FOREIGN KEY (userId) REFERENCES users(id) ) - `).run(); + `).run(); - // autoincrement on pins so that pin ids are stable and are not reused. - // this allows for better caching of images - db.prepare(` - CREATE TABLE pins ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - boardId INTEGER NOT NULL, - imageUrl TEXT, - siteUrl TEXT, - description TEXT, - sortOrder INTEGER, - originalHeight INTEGER, - originalWidth INTEGER, - thumbnailHeight INTEGER, - thumbnailWidth INTEGER, - userId INTEGER NOT NULL, - createDate TEXT, + db.prepare("INSERT INTO properties (key, value) VALUES (@key, @value)").run({key: "cookieKey", value: crypto.randomBytes(32).toString('hex')}); + db.prepare("INSERT INTO migrations (id, createDate) VALUES ( @id, @createDate )").run({id:1, createDate: new Date().toISOString()}); - FOREIGN KEY (boardId) REFERENCES boards(id), - FOREIGN KEY (userId) REFERENCES users(id) - ) - `).run(); + schemaVersion = 1; - db.prepare("INSERT INTO properties (key, value) VALUES (@key, @value)").run({key: "cookieKey", value: crypto.randomBytes(32).toString('hex')}); - db.prepare("INSERT INTO migrations (id, createDate) VALUES ( @id, @createDate )").run({id:1, createDate: new Date().toISOString()}); + })(); + } - schemaVersion = 1; + if ( schemaVersion < 2 ){ + console.log(" running migration v2"); + + if ( !isNewDb ){ + let backupPath = DB_PATH + ".backup-" + new Date().toISOString(); + console.log(" backing up to: " + backupPath); + db.prepare(` + VACUUM INTO ? + `).run(backupPath); + createdBackup = true; + } + + db.transaction( () => { + + db.prepare(` + ALTER TABLE boards ADD COLUMN hidden INTEGER + `).run(); + + db.prepare(` + UPDATE boards SET hidden = 0 + `).run(); + + db.prepare(` + INSERT INTO migrations (id, createDate) VALUES ( @id, @createDate ) + `).run({id:2, createDate: new Date().toISOString()}); + + schemaVersion = 2; + })(); } console.log(`database ready - schema version v${schemaVersion}`); diff --git a/static/addpin.html b/static/addpin.html index 9d0fe6a..5d7a84e 100644 --- a/static/addpin.html +++ b/static/addpin.html @@ -77,7 +77,9 @@ app.addSetter("load.boards", async (data) => { data.initialized = true; - if ( data.boards && data.boards.length > 0 ){ + if ( window.localStorage.addPinLastBoardId ){ + data.addPinModal.boardId = window.localStorage.addPinLastBoardId; + } else if ( data.boards && data.boards.length > 0 ){ data.addPinModal.boardId = data.boards[0].id; } else { data.addPinModal.boardId = "new"; @@ -87,7 +89,6 @@ app.addSetter("load.boards", async (data) => { }); app.addSetter('addPinModal.updatePreview', (data) => { - console.log("update preview"); if ( data.addPinModal.imageUrl.startsWith("http") ){ ( async() => { let res = await fetch(data.addPinModal.imageUrl, { @@ -161,6 +162,7 @@ app.addSetter('addPinModal.save', async (data) => { }); if ( res.status == 200 ){ + window.localStorage.addPinLastBoardId = boardId; window.close(); } @@ -228,7 +230,7 @@ const appComponent = new Reef("#app", { + +