openvibers/openvibe.locker Commits
Hero: no site name above the title (#36)
Changes
@@@ -22,7 +22,7 @@ function createPages({ config }) {body: `<div id="navbar-mount"></div><main id="main" class="locker-page" data-mode="${mode}"><div id="notice" role="status" aria-live="polite"></div>${body}</main><script>window.LockerPage=${boot};window.OpenVibeLockerConfig={network:'',reauthUrl:'/reauth'};</script><script src="/shared/ov-locker-core.js"></script><script src="/shared/ov-locker.js"></script><script src="/shared/ov-share.js"></script><script src="/js/payload.js"></script><script src="/js/passwords.js"></script><script src="/js/app.js"></script>`,}));}-- r.get('/', (req, res) => page(req, res, 'Keep it yours', `<header class="hero"><div><p class="eyebrow">OPENVIBE LOCKER</p><h1>Keep it<br><em>yours.</em></h1><p class="lead">A private place for your files.<br>Locked on your device, before they leave it.</p><div class="actions"><a class="button primary" href="/drive">Open your Drive</a><a class="button" href="/sends">Send something privately</a></div></div><div class="lock-art" aria-hidden="true"><div class="shackle"></div><div class="lock-body"><span></span></div><span class="art-caption">ONLY YOU HOLD THE KEYS</span></div></header>${device}<section class="grid"><a class="panel feature" href="/drive"><span class="number">01 / DRIVE</span><h2>Your files.<br>Your keys.</h2><p>Files and folders encrypted on your device. Share with people you choose.</p><span class="link-label">Go to Drive ↗</span></a><a class="panel feature" href="/sends"><span class="number">02 / SENDS</span><h2>A link with<br>a time limit.</h2><p>Send a file or a private note. Choose when it expires and how often it can be opened.</p><span class="link-label">Create a Send ↗</span></a></section><section class="plain"><h2>Private, including from us.</h2><p>OpenVibe stores encrypted bytes. Names, file types and content stay inside the lock. We can see the owner, padded size and time.</p><p>${warning}</p><a href="/recovery">Set up your locker and keep a recovery kit →</a></section>`, 'home'));++ r.get('/', (req, res) => page(req, res, 'Keep it yours', `<header class="hero"><div><h1>Keep it<br><em>yours.</em></h1><p class="lead">A private place for your files.<br>Locked on your device, before they leave it.</p><div class="actions"><a class="button primary" href="/drive">Open your Drive</a><a class="button" href="/sends">Send something privately</a></div></div><div class="lock-art" aria-hidden="true"><div class="shackle"></div><div class="lock-body"><span></span></div><span class="art-caption">ONLY YOU HOLD THE KEYS</span></div></header>${device}<section class="grid"><a class="panel feature" href="/drive"><span class="number">01 / DRIVE</span><h2>Your files.<br>Your keys.</h2><p>Files and folders encrypted on your device. Share with people you choose.</p><span class="link-label">Go to Drive ↗</span></a><a class="panel feature" href="/sends"><span class="number">02 / SENDS</span><h2>A link with<br>a time limit.</h2><p>Send a file or a private note. Choose when it expires and how often it can be opened.</p><span class="link-label">Create a Send ↗</span></a></section><section class="plain"><h2>Private, including from us.</h2><p>OpenVibe stores encrypted bytes. Names, file types and content stay inside the lock. We can see the owner, padded size and time.</p><p>${warning}</p><a href="/recovery">Set up your locker and keep a recovery kit →</a></section>`, 'home'));r.get('/drive', (req, res) => page(req, res, 'Drive', `<header class="page-heading"><p class="eyebrow">YOUR PRIVATE SPACE</p><h1>Drive</h1><p>Files and folders that only you and the people you choose can open.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><div class="section-heading"><h2>Your files</h2><a href="/files/shared">Shared with you ↗</a></div><div class="upload-grid"><form id="upload-form"><label>Choose a file<input name="file" type="file" required></label><label>Folder<select id="upload-parent" name="parent"><option value="">Drive</option></select></label><button class="primary">Lock and upload</button></form><form id="folder-form"><label>New folder name<input name="name" maxlength="200" required autocomplete="off"></label><button>Create locked folder</button></form></div><p id="progress" role="status"></p><nav id="folders" aria-label="Folders" class="actions"></nav><div id="items" class="item-list"><p class="empty">Sign in to see your encrypted files.</p></div></section>`, 'drive'));r.get('/passwords', (req, res) => page(req, res, 'Passwords', `<header class="page-heading"><p class="eyebrow">LOCKED ON YOUR DEVICE</p><h1>Your passwords.</h1><p>Encrypted in your browser before they are saved, then ready on every device where you unlock your locker. OpenVibe cannot read them.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><h2>Add a login</h2><form id="login-form"><div class="grid"><label>Website URL<input name="site" type="url" required autocomplete="url" placeholder="https://example.com"></label><label>Username<input name="username" autocomplete="username"></label><label>Password<input name="password" type="password" autocomplete="new-password" required></label><label>Two-factor secret or otpauth:// link (optional)<input name="totp" autocomplete="off" spellcheck="false"></label></div><label>Notes<textarea name="notes" rows="3"></textarea></label><div class="actions"><button class="primary">Save encrypted login</button><button id="generate-password" type="button">Generate password</button></div></form><p id="progress" role="status"></p></section><section class="panel"><div class="section-heading"><h2>Saved logins</h2><input id="login-search" type="search" placeholder="Search unlocked logins" aria-label="Search saved logins"><label class="button">Import CSV<input id="login-import" type="file" accept=".csv,text/csv" hidden></label></div><p>Search and site icons are created on this device after unlock. CSV files are read here and uploaded only as encrypted login items.</p><div id="items" class="item-list"></div></section><section class="panel"><h2>Check for a breach</h2><p>For each check, only the first five characters of the password’s SHA-1 hash are sent to Have I Been Pwned. The rest stays on this device.</p><p id="breach-consent">Each check asks before sending that five-character prefix to Have I Been Pwned.</p></section>`, 'passwords'));r.get('/sends', (req, res) => page(req, res, 'Sends', `<header class="page-heading"><p class="eyebrow">PRIVATE, FOR A WHILE</p><h1>Sends</h1><p>A locked file or note. The recipient needs only the full link.</p></header><section class="panel"><h2>Create a Send</h2><form id="send-form"><div class="grid"><label>A file<input name="file" type="file"></label><label>Or a private note<textarea name="text" rows="4" maxlength="1048576" placeholder="Write your note here"></textarea></label></div><div class="grid"><label>Expires after<select name="expires"><option value="3600">1 hour</option><option value="86400" selected>1 day</option><option value="604800">7 days</option><option value="2592000">30 days</option></select></label><label>Download limit (optional)<input name="limit" type="number" min="1" max="100000" placeholder="Until it expires"></label></div><p class="warning">${warning}</p><button class="primary">Lock and create link</button></form><p id="progress" role="status"></p><div id="send-result"></div></section><section class="plain"><p>The key stays after # in the link and is never sent to OpenVibe. Anyone with the full link can open the Send and keep a copy. Each download attempt counts, including interrupted downloads.</p></section><section class="panel"><h2>Your Sends</h2><div id="items" class="item-list"><p class="empty">Sign in to create and manage Sends.</p></div></section>`, 'sends'));
@@ -22,7 +22,7 @@ function createPages({ config }) {
@@ -22,7 +22,7 @@ function createPages({ config }) {
body: `<div id="navbar-mount"></div><main id="main" class="locker-page" data-mode="${mode}"><div id="notice" role="status" aria-live="polite"></div>${body}</main><script>window.LockerPage=${boot};window.OpenVibeLockerConfig={network:'',reauthUrl:'/reauth'};</script><script src="/shared/ov-locker-core.js"></script><script src="/shared/ov-locker.js"></script><script src="/shared/ov-share.js"></script><script src="/js/payload.js"></script><script src="/js/passwords.js"></script><script src="/js/app.js"></script>`,
body: `<div id="navbar-mount"></div><main id="main" class="locker-page" data-mode="${mode}"><div id="notice" role="status" aria-live="polite"></div>${body}</main><script>window.LockerPage=${boot};window.OpenVibeLockerConfig={network:'',reauthUrl:'/reauth'};</script><script src="/shared/ov-locker-core.js"></script><script src="/shared/ov-locker.js"></script><script src="/shared/ov-share.js"></script><script src="/js/payload.js"></script><script src="/js/passwords.js"></script><script src="/js/app.js"></script>`,
}));
}));
}
}
- r.get('/', (req, res) => page(req, res, 'Keep it yours', `<header class="hero"><div><p class="eyebrow">OPENVIBE LOCKER</p><h1>Keep it<br><em>yours.</em></h1><p class="lead">A private place for your files.<br>Locked on your device, before they leave it.</p><div class="actions"><a class="button primary" href="/drive">Open your Drive</a><a class="button" href="/sends">Send something privately</a></div></div><div class="lock-art" aria-hidden="true"><div class="shackle"></div><div class="lock-body"><span></span></div><span class="art-caption">ONLY YOU HOLD THE KEYS</span></div></header>${device}<section class="grid"><a class="panel feature" href="/drive"><span class="number">01 / DRIVE</span><h2>Your files.<br>Your keys.</h2><p>Files and folders encrypted on your device. Share with people you choose.</p><span class="link-label">Go to Drive ↗</span></a><a class="panel feature" href="/sends"><span class="number">02 / SENDS</span><h2>A link with<br>a time limit.</h2><p>Send a file or a private note. Choose when it expires and how often it can be opened.</p><span class="link-label">Create a Send ↗</span></a></section><section class="plain"><h2>Private, including from us.</h2><p>OpenVibe stores encrypted bytes. Names, file types and content stay inside the lock. We can see the owner, padded size and time.</p><p>${warning}</p><a href="/recovery">Set up your locker and keep a recovery kit →</a></section>`, 'home'));
+ r.get('/', (req, res) => page(req, res, 'Keep it yours', `<header class="hero"><div><h1>Keep it<br><em>yours.</em></h1><p class="lead">A private place for your files.<br>Locked on your device, before they leave it.</p><div class="actions"><a class="button primary" href="/drive">Open your Drive</a><a class="button" href="/sends">Send something privately</a></div></div><div class="lock-art" aria-hidden="true"><div class="shackle"></div><div class="lock-body"><span></span></div><span class="art-caption">ONLY YOU HOLD THE KEYS</span></div></header>${device}<section class="grid"><a class="panel feature" href="/drive"><span class="number">01 / DRIVE</span><h2>Your files.<br>Your keys.</h2><p>Files and folders encrypted on your device. Share with people you choose.</p><span class="link-label">Go to Drive ↗</span></a><a class="panel feature" href="/sends"><span class="number">02 / SENDS</span><h2>A link with<br>a time limit.</h2><p>Send a file or a private note. Choose when it expires and how often it can be opened.</p><span class="link-label">Create a Send ↗</span></a></section><section class="plain"><h2>Private, including from us.</h2><p>OpenVibe stores encrypted bytes. Names, file types and content stay inside the lock. We can see the owner, padded size and time.</p><p>${warning}</p><a href="/recovery">Set up your locker and keep a recovery kit →</a></section>`, 'home'));
r.get('/drive', (req, res) => page(req, res, 'Drive', `<header class="page-heading"><p class="eyebrow">YOUR PRIVATE SPACE</p><h1>Drive</h1><p>Files and folders that only you and the people you choose can open.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><div class="section-heading"><h2>Your files</h2><a href="/files/shared">Shared with you ↗</a></div><div class="upload-grid"><form id="upload-form"><label>Choose a file<input name="file" type="file" required></label><label>Folder<select id="upload-parent" name="parent"><option value="">Drive</option></select></label><button class="primary">Lock and upload</button></form><form id="folder-form"><label>New folder name<input name="name" maxlength="200" required autocomplete="off"></label><button>Create locked folder</button></form></div><p id="progress" role="status"></p><nav id="folders" aria-label="Folders" class="actions"></nav><div id="items" class="item-list"><p class="empty">Sign in to see your encrypted files.</p></div></section>`, 'drive'));
r.get('/drive', (req, res) => page(req, res, 'Drive', `<header class="page-heading"><p class="eyebrow">YOUR PRIVATE SPACE</p><h1>Drive</h1><p>Files and folders that only you and the people you choose can open.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><div class="section-heading"><h2>Your files</h2><a href="/files/shared">Shared with you ↗</a></div><div class="upload-grid"><form id="upload-form"><label>Choose a file<input name="file" type="file" required></label><label>Folder<select id="upload-parent" name="parent"><option value="">Drive</option></select></label><button class="primary">Lock and upload</button></form><form id="folder-form"><label>New folder name<input name="name" maxlength="200" required autocomplete="off"></label><button>Create locked folder</button></form></div><p id="progress" role="status"></p><nav id="folders" aria-label="Folders" class="actions"></nav><div id="items" class="item-list"><p class="empty">Sign in to see your encrypted files.</p></div></section>`, 'drive'));
r.get('/passwords', (req, res) => page(req, res, 'Passwords', `<header class="page-heading"><p class="eyebrow">LOCKED ON YOUR DEVICE</p><h1>Your passwords.</h1><p>Encrypted in your browser before they are saved, then ready on every device where you unlock your locker. OpenVibe cannot read them.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><h2>Add a login</h2><form id="login-form"><div class="grid"><label>Website URL<input name="site" type="url" required autocomplete="url" placeholder="https://example.com"></label><label>Username<input name="username" autocomplete="username"></label><label>Password<input name="password" type="password" autocomplete="new-password" required></label><label>Two-factor secret or otpauth:// link (optional)<input name="totp" autocomplete="off" spellcheck="false"></label></div><label>Notes<textarea name="notes" rows="3"></textarea></label><div class="actions"><button class="primary">Save encrypted login</button><button id="generate-password" type="button">Generate password</button></div></form><p id="progress" role="status"></p></section><section class="panel"><div class="section-heading"><h2>Saved logins</h2><input id="login-search" type="search" placeholder="Search unlocked logins" aria-label="Search saved logins"><label class="button">Import CSV<input id="login-import" type="file" accept=".csv,text/csv" hidden></label></div><p>Search and site icons are created on this device after unlock. CSV files are read here and uploaded only as encrypted login items.</p><div id="items" class="item-list"></div></section><section class="panel"><h2>Check for a breach</h2><p>For each check, only the first five characters of the password’s SHA-1 hash are sent to Have I Been Pwned. The rest stays on this device.</p><p id="breach-consent">Each check asks before sending that five-character prefix to Have I Been Pwned.</p></section>`, 'passwords'));
r.get('/passwords', (req, res) => page(req, res, 'Passwords', `<header class="page-heading"><p class="eyebrow">LOCKED ON YOUR DEVICE</p><h1>Your passwords.</h1><p>Encrypted in your browser before they are saved, then ready on every device where you unlock your locker. OpenVibe cannot read them.</p></header>${device}<div id="account" class="storage"></div><section class="panel"><h2>Add a login</h2><form id="login-form"><div class="grid"><label>Website URL<input name="site" type="url" required autocomplete="url" placeholder="https://example.com"></label><label>Username<input name="username" autocomplete="username"></label><label>Password<input name="password" type="password" autocomplete="new-password" required></label><label>Two-factor secret or otpauth:// link (optional)<input name="totp" autocomplete="off" spellcheck="false"></label></div><label>Notes<textarea name="notes" rows="3"></textarea></label><div class="actions"><button class="primary">Save encrypted login</button><button id="generate-password" type="button">Generate password</button></div></form><p id="progress" role="status"></p></section><section class="panel"><div class="section-heading"><h2>Saved logins</h2><input id="login-search" type="search" placeholder="Search unlocked logins" aria-label="Search saved logins"><label class="button">Import CSV<input id="login-import" type="file" accept=".csv,text/csv" hidden></label></div><p>Search and site icons are created on this device after unlock. CSV files are read here and uploaded only as encrypted login items.</p><div id="items" class="item-list"></div></section><section class="panel"><h2>Check for a breach</h2><p>For each check, only the first five characters of the password’s SHA-1 hash are sent to Have I Been Pwned. The rest stays on this device.</p><p id="breach-consent">Each check asks before sending that five-character prefix to Have I Been Pwned.</p></section>`, 'passwords'));
r.get('/sends', (req, res) => page(req, res, 'Sends', `<header class="page-heading"><p class="eyebrow">PRIVATE, FOR A WHILE</p><h1>Sends</h1><p>A locked file or note. The recipient needs only the full link.</p></header><section class="panel"><h2>Create a Send</h2><form id="send-form"><div class="grid"><label>A file<input name="file" type="file"></label><label>Or a private note<textarea name="text" rows="4" maxlength="1048576" placeholder="Write your note here"></textarea></label></div><div class="grid"><label>Expires after<select name="expires"><option value="3600">1 hour</option><option value="86400" selected>1 day</option><option value="604800">7 days</option><option value="2592000">30 days</option></select></label><label>Download limit (optional)<input name="limit" type="number" min="1" max="100000" placeholder="Until it expires"></label></div><p class="warning">${warning}</p><button class="primary">Lock and create link</button></form><p id="progress" role="status"></p><div id="send-result"></div></section><section class="plain"><p>The key stays after # in the link and is never sent to OpenVibe. Anyone with the full link can open the Send and keep a copy. Each download attempt counts, including interrupted downloads.</p></section><section class="panel"><h2>Your Sends</h2><div id="items" class="item-list"><p class="empty">Sign in to create and manage Sends.</p></div></section>`, 'sends'));
r.get('/sends', (req, res) => page(req, res, 'Sends', `<header class="page-heading"><p class="eyebrow">PRIVATE, FOR A WHILE</p><h1>Sends</h1><p>A locked file or note. The recipient needs only the full link.</p></header><section class="panel"><h2>Create a Send</h2><form id="send-form"><div class="grid"><label>A file<input name="file" type="file"></label><label>Or a private note<textarea name="text" rows="4" maxlength="1048576" placeholder="Write your note here"></textarea></label></div><div class="grid"><label>Expires after<select name="expires"><option value="3600">1 hour</option><option value="86400" selected>1 day</option><option value="604800">7 days</option><option value="2592000">30 days</option></select></label><label>Download limit (optional)<input name="limit" type="number" min="1" max="100000" placeholder="Until it expires"></label></div><p class="warning">${warning}</p><button class="primary">Lock and create link</button></form><p id="progress" role="status"></p><div id="send-result"></div></section><section class="plain"><p>The key stays after # in the link and is never sent to OpenVibe. Anyone with the full link can open the Send and keep a copy. Each download attempt counts, including interrupted downloads.</p></section><section class="panel"><h2>Your Sends</h2><div id="items" class="item-list"><p class="empty">Sign in to create and manage Sends.</p></div></section>`, 'sends'));