mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-07-19 05:09:41 +02:00
Set auth cookie lifetime (#102)
* Set auth cookie lifetime * Small fixes - upgrade editor and tools - add link tool - move "save" button and "uri" field * Update twig.js * move to deps
This commit is contained in:
parent
40d5285e5e
commit
94a9a963ff
17 changed files with 2413 additions and 793 deletions
14
package.json
14
package.json
|
@ -13,7 +13,7 @@
|
|||
"build:dev": "webpack ./src/frontend/js/app.js --o='./public/dist/[name].bundle.js' --output-library=Docs --output-public-path=/dist/ -p --mode=development --watch",
|
||||
"precommit": "yarn lint && yarn test --exit",
|
||||
"generatePassword": "node ./generatePassword.js",
|
||||
"editor-upgrade": "yarn add -D @editorjs/{editorjs,header,code,delimiter,list,image,table,inline-code,marker,warning,checklist}@latest"
|
||||
"editor-upgrade": "yarn add -D @editorjs/{editorjs,header,code,delimiter,list,link,image,table,inline-code,marker,warning,checklist}@latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^3.0.3",
|
||||
|
@ -34,6 +34,7 @@
|
|||
"nedb": "^1.8.0",
|
||||
"node-fetch": "^2.3.0",
|
||||
"nodemon": "^1.18.3",
|
||||
"open-graph-scraper": "^4.5.0",
|
||||
"twig": "~1.12.0",
|
||||
"typescript-eslint": "^0.0.1-alpha.0",
|
||||
"uuid4": "^1.0.0"
|
||||
|
@ -45,13 +46,14 @@
|
|||
"@babel/preset-env": "^7.1.0",
|
||||
"@codexteam/misprints": "^1.0.0",
|
||||
"@editorjs/checklist": "^1.1.0",
|
||||
"@editorjs/code": "^2.4.1",
|
||||
"@editorjs/code": "^2.5.0",
|
||||
"@editorjs/delimiter": "^1.1.0",
|
||||
"@editorjs/editorjs": "^2.17.0",
|
||||
"@editorjs/header": "^2.4.1",
|
||||
"@editorjs/image": "^2.3.4",
|
||||
"@editorjs/editorjs": "^2.18.0",
|
||||
"@editorjs/header": "^2.5.0",
|
||||
"@editorjs/image": "^2.4.2",
|
||||
"@editorjs/inline-code": "^1.3.1",
|
||||
"@editorjs/list": "^1.4.0",
|
||||
"@editorjs/link": "^2.2.1",
|
||||
"@editorjs/list": "^1.5.0",
|
||||
"@editorjs/marker": "^1.2.2",
|
||||
"@editorjs/table": "^1.2.2",
|
||||
"@editorjs/warning": "^1.1.1",
|
||||
|
|
2
public/dist/code-styling.bundle.js
vendored
2
public/dist/code-styling.bundle.js
vendored
File diff suppressed because one or more lines are too long
18
public/dist/editor.bundle.js
vendored
18
public/dist/editor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/main.bundle.js
vendored
2
public/dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/main.css
vendored
2
public/dist/main.css
vendored
File diff suppressed because one or more lines are too long
|
@ -11,6 +11,7 @@ import Delimiter from '@editorjs/delimiter';
|
|||
import Table from '@editorjs/table';
|
||||
import Warning from '@editorjs/warning';
|
||||
import Checklist from '@editorjs/checklist';
|
||||
import LinkTool from '@editorjs/link';
|
||||
|
||||
/**
|
||||
* Inline Tools for the Editor
|
||||
|
@ -59,6 +60,13 @@ export default class Editor {
|
|||
}
|
||||
},
|
||||
|
||||
linkTool: {
|
||||
class: LinkTool,
|
||||
config: {
|
||||
endpoint: '/api/fetchUrl',
|
||||
}
|
||||
},
|
||||
|
||||
code: {
|
||||
class: CodeTool,
|
||||
shortcut: 'CMD+SHIFT+D'
|
||||
|
|
|
@ -418,3 +418,69 @@
|
|||
.block-checklist__item-checkbox--checked, .block-checklist__item-checkbox::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.block-link {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 40px auto;
|
||||
padding: 25px !important;
|
||||
border: 1px solid var(--color-line-gray) !important;
|
||||
box-shadow: 0 1px 1px #4246540a;
|
||||
border-radius: 2px;
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
|
||||
@media (--mobile) {
|
||||
box-sizing: border-box;
|
||||
padding: 20px !important;
|
||||
margin: 30px auto;
|
||||
}
|
||||
|
||||
&__image {
|
||||
float: right;
|
||||
max-width: 70px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
margin: 0 0 30px 30px;
|
||||
border-radius: 3px;
|
||||
|
||||
@media (--mobile) {
|
||||
margin: 0 0 15px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 16px;
|
||||
line-height: 1.45em;
|
||||
font-weight: 600;
|
||||
|
||||
@media (--mobile) {
|
||||
font-size: 12.2px;
|
||||
}
|
||||
}
|
||||
|
||||
&__domain {
|
||||
display: inline-block;
|
||||
font-variant: small-caps;
|
||||
margin-top: 20px;
|
||||
border: 0 !important;
|
||||
color: var(--color-text-second);
|
||||
font-size: 0.85em;
|
||||
|
||||
@media (--mobile) {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&__description {
|
||||
margin-top: 10px;
|
||||
font-size: 0.9em;
|
||||
|
||||
@media (--mobile) {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ const router = express.Router();
|
|||
|
||||
const pagesAPI = require('./pages');
|
||||
const transportAPI = require('./transport');
|
||||
const linksAPI = require('./links');
|
||||
|
||||
router.use('/', pagesAPI);
|
||||
router.use('/', transportAPI);
|
||||
router.use('/', linksAPI);
|
||||
|
||||
module.exports = router;
|
||||
|
|
38
src/routes/api/links.js
Normal file
38
src/routes/api/links.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const ogs = require('open-graph-scraper');
|
||||
|
||||
/**
|
||||
* Accept file url to fetch
|
||||
*/
|
||||
router.get('/fetchUrl', async (req, res) => {
|
||||
const response = {
|
||||
success: 0
|
||||
};
|
||||
|
||||
if (!req.query.url) {
|
||||
res.status(400).json(response);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const linkData = (await ogs({ url: req.query.url })).result;
|
||||
|
||||
response.success = 1;
|
||||
response.meta = {
|
||||
title: linkData.ogTitle,
|
||||
description: linkData.ogDescription,
|
||||
site_name: linkData.ogSiteName,
|
||||
image: {
|
||||
url: linkData.ogImage.url
|
||||
}
|
||||
};
|
||||
|
||||
res.status(200).json(response);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
res.status(500).json(response);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -51,7 +51,10 @@ router.post('/auth', parseForm, csrfProtection, async (req, res) => {
|
|||
iat: Date.now(),
|
||||
}, passHash + config.secret);
|
||||
|
||||
res.cookie('authToken', token, { httpOnly: true });
|
||||
res.cookie('authToken', token, {
|
||||
httpOnly: true,
|
||||
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 1 year
|
||||
});
|
||||
|
||||
res.redirect('/');
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ const router = express.Router();
|
|||
/* GET home page. */
|
||||
router.get('/', verifyToken, async (req, res) => {
|
||||
const config = req.app.locals.config;
|
||||
|
||||
if (config.startPage) {
|
||||
return res.redirect(config.startPage);
|
||||
}
|
||||
|
|
|
@ -29,4 +29,18 @@ module.exports = (function () {
|
|||
twig.extendFilter('urlify', function (string) {
|
||||
return urlify(string);
|
||||
});
|
||||
|
||||
/**
|
||||
* Parse link as URL object
|
||||
*
|
||||
* @param {string} linkUrl - link to be processed
|
||||
* @returns {UrlWithStringQuery} — url data
|
||||
*/
|
||||
twig.extendFunction('parseLink', function (linkUrl) {
|
||||
try {
|
||||
return new URL(linkUrl);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<p>
|
||||
Enter a password to access pages editing
|
||||
</p>
|
||||
<input type="hidden" name="_csrf" value={{csrfToken}}>
|
||||
<input type="hidden" name="_csrf" value={{ csrfToken }}>
|
||||
<input type="password" name="password" placeholder="Password">
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
|
|
17
src/views/pages/blocks/linkTool.twig
Normal file
17
src/views/pages/blocks/linkTool.twig
Normal file
|
@ -0,0 +1,17 @@
|
|||
<a class="block-link" href="{{ link }}" target="_blank" rel="nofollow">
|
||||
{% if meta.image.url %}
|
||||
<img class="block-link__image" src="{{ meta.image.url }}">
|
||||
{% endif %}
|
||||
|
||||
<div class="block-link__title">
|
||||
{{ meta.title }}
|
||||
</div>
|
||||
|
||||
<div class="block-link__description">
|
||||
{{ meta.description }}
|
||||
</div>
|
||||
|
||||
<span class="block-link__domain">
|
||||
{{ parseLink(link).hostname }}
|
||||
</span>
|
||||
</a>
|
|
@ -48,18 +48,20 @@
|
|||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="writing-header__save" name="js-submit-save">Save</span>
|
||||
|
||||
{% if page is not empty %}
|
||||
<p><input type="text" class="uri-input" name="uri-input" placeholder="URI (Optional)" value="{{ page.uri }}"></p>
|
||||
{% endif %}
|
||||
</header>
|
||||
<div class="writing-editor">
|
||||
<div id="editorjs"></div>
|
||||
</div>
|
||||
<div class="writing-buttons">
|
||||
<span class="writing-header__save" name="js-submit-save">Save</span>
|
||||
|
||||
{% if page._id is not empty %}
|
||||
<span class="writing-buttons__remove" name="js-submit-remove">Remove</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if page is not empty %}
|
||||
<p><input type="text" class="uri-input" name="uri-input" placeholder="URI(Optional)" value="{{ page.uri }}"></p>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
{% for block in page.body.blocks %}
|
||||
{# Skip first header, because it is already showed as a Title #}
|
||||
{% if not (loop.first and block.type == 'header') %}
|
||||
{% if block.type in ['paragraph', 'header', 'image', 'code', 'list', 'delimiter', 'table', 'warning', 'checklist'] %}
|
||||
{% if block.type in ['paragraph', 'header', 'image', 'code', 'list', 'delimiter', 'table', 'warning', 'checklist', 'linkTool'] %}
|
||||
{% include './blocks/' ~ block.type ~ '.twig' with block.data %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue