mirror of
				https://git.sr.ht/~cadence/bibliogram
				synced 2025-10-31 03:25:36 +00:00 
			
		
		
		
	Add settings restore link
This commit is contained in:
		
							parent
							
								
									21875a8e83
								
							
						
					
					
						commit
						0c16c027e9
					
				| @ -8,6 +8,7 @@ const db = require("../../lib/db") | |||||||
| module.exports = [ | module.exports = [ | ||||||
| 	{ | 	{ | ||||||
| 		route: "/settings", methods: ["GET"], code: async ({req, url}) => { | 		route: "/settings", methods: ["GET"], code: async ({req, url}) => { | ||||||
|  | 			const token = getToken(req) | ||||||
| 			const settings = getSettings(req) | 			const settings = getSettings(req) | ||||||
| 			// console.log(settings)
 | 			// console.log(settings)
 | ||||||
| 			const csrf = generateCSRF() | 			const csrf = generateCSRF() | ||||||
| @ -19,6 +20,7 @@ module.exports = [ | |||||||
| 				returnURL: url.searchParams.get("referrer") || "/", | 				returnURL: url.searchParams.get("referrer") || "/", | ||||||
| 				constants, | 				constants, | ||||||
| 				settings, | 				settings, | ||||||
|  | 				token, | ||||||
| 				csrf, | 				csrf, | ||||||
| 				status, | 				status, | ||||||
| 				message | 				message | ||||||
| @ -28,7 +30,7 @@ module.exports = [ | |||||||
| 	{ | 	{ | ||||||
| 		route: "/settings/(stay|return)", methods: ["POST"], upload: true, code: async ({req, body, fill, url}) => { | 		route: "/settings/(stay|return)", methods: ["POST"], upload: true, code: async ({req, body, fill, url}) => { | ||||||
| 			const action = fill[0] | 			const action = fill[0] | ||||||
| 			const oldToken = getToken(req) | 			const token = getToken(req) | ||||||
| 			const params = new URLSearchParams(body.toString()) | 			const params = new URLSearchParams(body.toString()) | ||||||
| 			if (!checkCSRF(params.get("csrf"))) { | 			if (!checkCSRF(params.get("csrf"))) { | ||||||
| 				const returnParams = new URLSearchParams() | 				const returnParams = new URLSearchParams() | ||||||
| @ -55,14 +57,17 @@ module.exports = [ | |||||||
| 				prepared[setting.name] = valueCorrectType | 				prepared[setting.name] = valueCorrectType | ||||||
| 			} | 			} | ||||||
| 			// console.log(prepared)
 | 			// console.log(prepared)
 | ||||||
|  | 			if (token) { | ||||||
|  | 				prepared.token = token | ||||||
|  | 			} else { | ||||||
| 				const checkPrepared = db.prepare("SELECT token FROM UserSettings WHERE token = ?") | 				const checkPrepared = db.prepare("SELECT token FROM UserSettings WHERE token = ?") | ||||||
| 				do { | 				do { | ||||||
| 					prepared.token = crypto.randomBytes(16).toString("hex") | 					prepared.token = crypto.randomBytes(16).toString("hex") | ||||||
| 				} while (checkPrepared.get(prepared.token)) | 				} while (checkPrepared.get(prepared.token)) | ||||||
|  | 			} | ||||||
| 			prepared.created = Date.now() | 			prepared.created = Date.now() | ||||||
| 			const fields = constants.user_settings.map(s => s.name) | 			const fields = constants.user_settings.map(s => s.name) | ||||||
| 			db.prepare(`INSERT INTO UserSettings (token, created, ${fields.join(", ")}) VALUES (@token, @created, ${fields.map(f => "@"+f).join(", ")})`).run(prepared) | 			db.prepare(`REPLACE INTO UserSettings (token, created, ${fields.join(", ")}) VALUES (@token, @created, ${fields.map(f => "@"+f).join(", ")})`).run(prepared) | ||||||
| 			db.prepare("DELETE FROM UserSettings WHERE token = ?").run(oldToken) |  | ||||||
| 			const expires = new Date(Date.now() + 4000*24*60*60*1000).toUTCString() | 			const expires = new Date(Date.now() + 4000*24*60*60*1000).toUTCString() | ||||||
| 			let location | 			let location | ||||||
| 			if (action === "return" && url.searchParams.has("referrer")) { | 			if (action === "return" && url.searchParams.has("referrer")) { | ||||||
| @ -86,5 +91,19 @@ module.exports = [ | |||||||
| 				content: "Redirecting..." | 				content: "Redirecting..." | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		route: "/applysettings/([0-9a-f]+)", methods: ["GET"], code: async ({fill}) => { | ||||||
|  | 			const expires = new Date(Date.now() + 4000*24*60*60*1000).toUTCString() | ||||||
|  | 			return { | ||||||
|  | 				statusCode: 302, | ||||||
|  | 				headers: { | ||||||
|  | 					"Location": "/", | ||||||
|  | 					"Set-Cookie": `settings=${fill[0]}; Path=/; Expires=${expires}; SameSite=Lax` | ||||||
|  | 				}, | ||||||
|  | 				contentType: "text/html; charset=UTF-8", | ||||||
|  | 				content: "Settings restored. Redirecting..." | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| ] | ] | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| const crypto = require("crypto") | const crypto = require("crypto") | ||||||
| const {parse} = require("cookie") | const {parse: parseCookie} = require("cookie") | ||||||
| 
 | 
 | ||||||
| const constants = require("../../../lib/constants") | const constants = require("../../../lib/constants") | ||||||
| const db = require("../../../lib/db") | const db = require("../../../lib/db") | ||||||
| @ -22,7 +22,7 @@ function addDefaults(input = {}) { | |||||||
| 
 | 
 | ||||||
| function getToken(req) { | function getToken(req) { | ||||||
| 	if (!req.headers.cookie) return null | 	if (!req.headers.cookie) return null | ||||||
| 	const cookie = parse(req.headers.cookie) | 	const cookie = parseCookie(req.headers.cookie) | ||||||
| 	const token = cookie.settings | 	const token = cookie.settings | ||||||
| 	if (token) return token | 	if (token) return token | ||||||
| 	else return null | 	else return null | ||||||
|  | |||||||
| @ -4,3 +4,5 @@ if (params.has("status")) { | |||||||
| 	params.delete("message") | 	params.delete("message") | ||||||
| 	history.replaceState(null, "", "?" + params.toString()) | 	history.replaceState(null, "", "?" + params.toString()) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | document.getElementById("restore-link").addEventListener("click", event => event.preventDefault()) | ||||||
|  | |||||||
| @ -30,10 +30,10 @@ html | |||||||
| 	head | 	head | ||||||
| 		title Settings | Bibliogram | 		title Settings | Bibliogram | ||||||
| 		include includes/head | 		include includes/head | ||||||
|  | 		script(src=getStaticURL("html", "/static/js/settings_message.js") type="module") | ||||||
| 	body.settings-page | 	body.settings-page | ||||||
| 		if status && message | 		if status && message | ||||||
| 			.status-notice(class=status)= message | 			.status-notice(class=status)= message | ||||||
| 			script(src=getStaticURL("html", "/static/js/settings_message.js") type="module") |  | ||||||
| 		main.settings | 		main.settings | ||||||
| 			form(action=returnAction method="post" enctype="application/x-www-form-urlencoded") | 			form(action=returnAction method="post" enctype="application/x-www-form-urlencoded") | ||||||
| 				input(type="hidden" name="csrf" value=csrf) | 				input(type="hidden" name="csrf" value=csrf) | ||||||
| @ -129,6 +129,9 @@ html | |||||||
| 								label.pill(for=thisID tabindex=0 onkeypress=`[" ", "Enter"].includes(event.key) && this.click()`) Label | 								label.pill(for=thisID tabindex=0 onkeypress=`[" ", "Enter"].includes(event.key) && this.click()`) Label | ||||||
| 									span.fake-checkbox | 									span.fake-checkbox | ||||||
| 
 | 
 | ||||||
|  | 				if token | ||||||
|  | 					p You can restore and sync saved settings by #[a(href=`/applysettings/${token}`)#restore-link bookmarking this link.] | ||||||
|  | 
 | ||||||
| 				.action-container | 				.action-container | ||||||
| 					span.home-link-container: a(href=returnURL).home-link ← Return | 					span.home-link-container: a(href=returnURL).home-link ← Return | ||||||
| 					button(type="submit" formaction=stayAction).save-button Save | 					button(type="submit" formaction=stayAction).save-button Save | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user