Skip to content

Commit e77690b

Browse files
committed
feat: password protected page
1 parent 26c903f commit e77690b

File tree

7 files changed

+296
-95
lines changed

7 files changed

+296
-95
lines changed

deps/publish/src/logseq/publish/meta_store.cljs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"owner_sub TEXT,"
2323
"created_at INTEGER,"
2424
"updated_at INTEGER,"
25+
"password_hash TEXT,"
2526
"PRIMARY KEY (graph_uuid, page_uuid)"
2627
");"))
2728
(let [cols (publish-common/get-sql-rows (publish-common/sql-exec sql "PRAGMA table_info(pages);"))
@@ -31,7 +32,9 @@
3132
(when-not (contains? col-names "page_tags")
3233
(publish-common/sql-exec sql "ALTER TABLE pages ADD COLUMN page_tags TEXT;"))
3334
(when-not (contains? col-names "short_id")
34-
(publish-common/sql-exec sql "ALTER TABLE pages ADD COLUMN short_id TEXT;")))
35+
(publish-common/sql-exec sql "ALTER TABLE pages ADD COLUMN short_id TEXT;"))
36+
(when-not (contains? col-names "password_hash")
37+
(publish-common/sql-exec sql "ALTER TABLE pages ADD COLUMN password_hash TEXT;")))
3538
(let [cols (publish-common/get-sql-rows (publish-common/sql-exec sql "PRAGMA table_info(page_refs);"))
3639
col-names (set (map #(aget % "name") cols))]
3740
(when (seq col-names)
@@ -109,8 +112,9 @@
109112
"owner_sub,"
110113
"created_at,"
111114
"updated_at,"
112-
"short_id"
113-
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
115+
"short_id,"
116+
"password_hash"
117+
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
114118
" ON CONFLICT(graph_uuid, page_uuid) DO UPDATE SET"
115119
" page_uuid=excluded.page_uuid,"
116120
" page_title=excluded.page_title,"
@@ -122,7 +126,8 @@
122126
" r2_key=excluded.r2_key,"
123127
" owner_sub=excluded.owner_sub,"
124128
" updated_at=excluded.updated_at,"
125-
" short_id=excluded.short_id;")
129+
" short_id=excluded.short_id,"
130+
" password_hash=excluded.password_hash;")
126131
(aget body "page_uuid")
127132
(aget body "page_title")
128133
(aget body "page_tags")
@@ -135,7 +140,8 @@
135140
(aget body "owner_sub")
136141
(aget body "created_at")
137142
(aget body "updated_at")
138-
(aget body "short_id"))
143+
(aget body "short_id")
144+
(aget body "password_hash"))
139145
(let [refs (aget body "refs")
140146
tagged-nodes (aget body "tagged_nodes")
141147
graph-uuid (aget body "graph")
@@ -244,6 +250,18 @@
244250
row (first rows)]
245251
(publish-common/json-response {:page (when row (js->clj row :keywordize-keys false))}))
246252

253+
(= (nth parts 4 nil) "password")
254+
(let [rows (publish-common/get-sql-rows
255+
(publish-common/sql-exec sql
256+
(str "SELECT password_hash "
257+
"FROM pages WHERE graph_uuid = ? AND page_uuid = ? LIMIT 1;")
258+
graph-uuid
259+
page-uuid))
260+
row (first rows)]
261+
(if-not row
262+
(publish-common/not-found)
263+
(publish-common/json-response {:password_hash (aget row "password_hash")})))
264+
247265
(= (nth parts 4 nil) "refs")
248266
(let [rows (publish-common/get-sql-rows
249267
(publish-common/sql-exec sql

deps/publish/src/logseq/publish/publish.css

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,51 @@ a:hover {
339339
letter-spacing: 0.12em;
340340
}
341341

342+
.password-card {
343+
margin: 20px auto 0;
344+
max-width: 460px;
345+
padding: 24px;
346+
border-radius: 18px;
347+
border: 1px solid var(--border);
348+
background: #fff7ee;
349+
box-shadow: 0 14px 24px rgba(217, 125, 63, 0.12);
350+
text-align: center;
351+
}
352+
353+
.password-form {
354+
margin-top: 18px;
355+
display: grid;
356+
gap: 12px;
357+
}
358+
359+
.password-label {
360+
font-size: 12px;
361+
text-transform: uppercase;
362+
letter-spacing: 0.14em;
363+
color: var(--muted);
364+
}
365+
366+
.password-input {
367+
width: 100%;
368+
padding: 10px 12px;
369+
border-radius: 10px;
370+
border: 1px solid rgba(31, 26, 20, 0.2);
371+
font-size: 15px;
372+
font-family: inherit;
373+
}
374+
375+
.password-input:focus {
376+
outline: 2px solid rgba(217, 125, 63, 0.4);
377+
border-color: rgba(217, 125, 63, 0.6);
378+
}
379+
380+
.password-error {
381+
margin: 8px 0 0;
382+
color: #b42318;
383+
font-size: 13px;
384+
font-weight: 600;
385+
}
386+
342387
.not-found {
343388
text-align: center;
344389
padding: 32px 16px 8px;

deps/publish/src/logseq/publish/publish.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
import katexPkg from "https://esm.sh/katex@0.16.10?bundle";
2+
3+
// Core CodeMirror pieces
4+
import { EditorState } from "https://esm.sh/@codemirror/state@6";
25
import {
3-
EditorState,
46
EditorView,
5-
basicSetup,
6-
defaultHighlightStyle,
7+
lineNumbers,
8+
} from "https://esm.sh/@codemirror/view@6";
9+
10+
// Highlighting
11+
import {
712
syntaxHighlighting,
8-
javascript,
9-
python,
10-
html,
11-
css,
12-
json,
13-
markdown,
14-
sql,
15-
clojure,
16-
} from "https://esm.sh/@codemirror/basic-setup@0.20.0?bundle";
13+
defaultHighlightStyle,
14+
} from "https://esm.sh/@codemirror/language@6";
15+
16+
// Languages
17+
import { javascript } from "https://esm.sh/@codemirror/lang-javascript@6";
18+
import { python } from "https://esm.sh/@codemirror/lang-python@6";
19+
import { html } from "https://esm.sh/@codemirror/lang-html@6";
20+
import { json } from "https://esm.sh/@codemirror/lang-json@6";
21+
import { markdown } from "https://esm.sh/@codemirror/lang-markdown@6";
22+
import { sql } from "https://esm.sh/@codemirror/lang-sql@6";
23+
import { css } from "https://esm.sh/@codemirror/lang-css@6";
24+
import { clojure } from "https://esm.sh/@nextjournal/lang-clojure";
1725

1826
const katex = katexPkg.default || katexPkg;
1927

@@ -54,6 +62,7 @@ const initPublish = () => {
5462
const codeEl = block.querySelector("code");
5563
const doc = codeEl ? codeEl.textContent : "";
5664
block.textContent = "";
65+
5766
const lang = (block.dataset.lang || "").toLowerCase();
5867
const langExt = (() => {
5968
if (!lang) return null;
@@ -62,24 +71,28 @@ const initPublish = () => {
6271
}
6372
if (["py", "python"].includes(lang)) return python();
6473
if (["html", "htm"].includes(lang)) return html();
65-
if (["css", "scss"].includes(lang)) return css();
6674
if (["json"].includes(lang)) return json();
6775
if (["md", "markdown"].includes(lang)) return markdown();
6876
if (["sql"].includes(lang)) return sql();
77+
if (["css", "scss"].includes(lang)) return css();
6978
if (["clj", "cljc", "cljs", "clojure"].includes(lang)) return clojure();
7079
return null;
7180
})();
81+
7282
const extensions = [
73-
basicSetup,
83+
lineNumbers(),
7484
syntaxHighlighting(defaultHighlightStyle),
7585
EditorView.editable.of(false),
7686
EditorView.lineWrapping,
7787
];
88+
7889
if (langExt) extensions.push(langExt);
90+
7991
const state = EditorState.create({
8092
doc,
8193
extensions,
8294
});
95+
8396
new EditorView({ state, parent: block });
8497
});
8598
};

deps/publish/src/logseq/publish/render.cljs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,37 @@
696696
[:p.tag-sub "This page hasn't been published yet."]]]]]
697697
(str "<!doctype html>" (render-hiccup doc))))
698698

699+
(defn render-password-html
700+
[graph-uuid page-uuid wrong?]
701+
(let [title "Protected page"
702+
doc [:html
703+
[:head
704+
[:meta {:charset "utf-8"}]
705+
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
706+
[:title title]
707+
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
708+
[:body
709+
[:main.wrap
710+
[:div.page-toolbar
711+
(when graph-uuid
712+
[:a.toolbar-btn {:href (str "/graph/" graph-uuid)} "Home"])]
713+
[:div.password-card
714+
[:h1 title]
715+
[:p.tag-sub "This page is password protected."]
716+
(when wrong?
717+
[:p.password-error "Incorrect password."])
718+
[:form.password-form {:method "GET"}
719+
(when page-uuid
720+
[:input {:type "hidden" :name "page" :value page-uuid}])
721+
[:label.password-label {:for "publish-password"} "Enter password"]
722+
[:input.password-input {:id "publish-password"
723+
:name "password"
724+
:type "password"
725+
:placeholder "Password"
726+
:required true}]
727+
[:button.toolbar-btn {:type "submit"} "Unlock"]]]]]]]
728+
(str "<!doctype html>" (render-hiccup doc))))
729+
699730
(defn render-404-html
700731
[]
701732
(let [title "Page not found"

0 commit comments

Comments
 (0)