mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: feat: blog
This commit is contained in:
1 parent
f43c1bc8c9
commit
79aca189d1
10 files changed
+31
-26
No files matched your search
@@ -92,6 +92,9 @@ Begin Time: 开始时间
|
|||||||
Belongs to: 属于
|
Belongs to: 属于
|
||||||
Bio Visibility: 个人简介可见性
|
Bio Visibility: 个人简介可见性
|
||||||
Bio: 个人简介
|
Bio: 个人简介
|
||||||
|
blog_detail: 博客详情
|
||||||
|
blog_edit: 编辑博客
|
||||||
|
blog_main: 博客
|
||||||
Blog: 博客
|
Blog: 博客
|
||||||
Bold: 加粗
|
Bold: 加粗
|
||||||
Boom!: 炸了!
|
Boom!: 炸了!
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "3.2.22",
|
"version": "3.2.23",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
import { DiscussionNotFoundError } from '../error';
|
import { DiscussionNotFoundError, ForbiddenError } from '../error';
|
||||||
import { BlogDoc } from '../interface';
|
import { BlogDoc } from '../interface';
|
||||||
import paginate from '../lib/paginate';
|
import paginate from '../lib/paginate';
|
||||||
import * as blog from '../model/blog';
|
import * as blog from '../model/blog';
|
||||||
import { PERM, PRIV } from '../model/builtin';
|
import { PRIV } from '../model/builtin';
|
||||||
import * as discussion from '../model/discussion';
|
|
||||||
import * as oplog from '../model/oplog';
|
import * as oplog from '../model/oplog';
|
||||||
|
import * as system from '../model/system';
|
||||||
import user from '../model/user';
|
import user from '../model/user';
|
||||||
import {
|
import {
|
||||||
Handler, param, Route, Types,
|
Handler, param, Route, Types,
|
||||||
@@ -16,7 +16,7 @@ class BlogHandler extends Handler {
|
|||||||
|
|
||||||
@param('did', Types.ObjectID, true)
|
@param('did', Types.ObjectID, true)
|
||||||
async _prepare(domainId: string, did: ObjectID) {
|
async _prepare(domainId: string, did: ObjectID) {
|
||||||
this.checkPerm(PERM.PERM_VIEW_DISCUSSION);
|
if (!system.get('server.blog')) throw new ForbiddenError('Blog is disabled');
|
||||||
if (did) {
|
if (did) {
|
||||||
this.ddoc = await blog.get(did);
|
this.ddoc = await blog.get(did);
|
||||||
if (!this.ddoc) throw new DiscussionNotFoundError(domainId, did);
|
if (!this.ddoc) throw new DiscussionNotFoundError(domainId, did);
|
||||||
@@ -89,7 +89,6 @@ class BlogEditHandler extends BlogHandler {
|
|||||||
@param('title', Types.Title)
|
@param('title', Types.Title)
|
||||||
@param('content', Types.Content)
|
@param('content', Types.Content)
|
||||||
async postCreate(domainId: string, title: string, content: string) {
|
async postCreate(domainId: string, title: string, content: string) {
|
||||||
this.checkPerm(PERM.PERM_CREATE_DISCUSSION);
|
|
||||||
await this.limitRate('add_blog', 3600, 60);
|
await this.limitRate('add_blog', 3600, 60);
|
||||||
const did = await blog.add(this.user._id, title, content, this.request.ip);
|
const did = await blog.add(this.user._id, title, content, this.request.ip);
|
||||||
this.response.body = { did };
|
this.response.body = { did };
|
||||||
@@ -100,8 +99,7 @@ class BlogEditHandler extends BlogHandler {
|
|||||||
@param('title', Types.Title)
|
@param('title', Types.Title)
|
||||||
@param('content', Types.Content)
|
@param('content', Types.Content)
|
||||||
async postUpdate(domainId: string, did: ObjectID, title: string, content: string) {
|
async postUpdate(domainId: string, did: ObjectID, title: string, content: string) {
|
||||||
if (!this.user.own(this.ddoc)) this.checkPerm(PERM.PERM_EDIT_DISCUSSION);
|
if (!this.user.own(this.ddoc)) this.checkPriv(PRIV.PRIV_EDIT_SYSTEM);
|
||||||
else this.checkPerm(PERM.PERM_EDIT_DISCUSSION_SELF);
|
|
||||||
await blog.edit(did, title, content);
|
await blog.edit(did, title, content);
|
||||||
await oplog.add({
|
await oplog.add({
|
||||||
...this.ddoc, operator: this.user._id, type: 'edit',
|
...this.ddoc, operator: this.user._id, type: 'edit',
|
||||||
@@ -112,9 +110,8 @@ class BlogEditHandler extends BlogHandler {
|
|||||||
|
|
||||||
@param('did', Types.ObjectID)
|
@param('did', Types.ObjectID)
|
||||||
async postDelete(domainId: string, did: ObjectID) {
|
async postDelete(domainId: string, did: ObjectID) {
|
||||||
if (!this.user.own(this.ddoc)) this.checkPerm(PERM.PERM_DELETE_DISCUSSION);
|
if (!this.user.own(this.ddoc)) this.checkPriv(PRIV.PRIV_EDIT_SYSTEM);
|
||||||
else this.checkPerm(PERM.PERM_DELETE_DISCUSSION_SELF);
|
await blog.del(did);
|
||||||
await discussion.del(domainId, did);
|
|
||||||
await oplog.add({
|
await oplog.add({
|
||||||
...this.ddoc, operator: this.user._id, operateIp: this.request.ip, type: 'delete',
|
...this.ddoc, operator: this.user._id, operateIp: this.request.ip, type: 'delete',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ SystemSetting(
|
|||||||
Setting('setting_server', 'server.language', 'zh_CN', langRange, 'server.language', 'Default display language'),
|
Setting('setting_server', 'server.language', 'zh_CN', langRange, 'server.language', 'Default display language'),
|
||||||
Setting('setting_server', 'server.login', true, 'boolean', 'server.login', 'Allow builtin-login', FLAG_PRO),
|
Setting('setting_server', 'server.login', true, 'boolean', 'server.login', 'Allow builtin-login', FLAG_PRO),
|
||||||
Setting('setting_server', 'server.message', true, 'boolean', 'server.message', 'Allow users send messages'),
|
Setting('setting_server', 'server.message', true, 'boolean', 'server.message', 'Allow users send messages'),
|
||||||
|
Setting('setting_server', 'server.blog', true, 'boolean', 'server.blog', 'Allow users post blog'),
|
||||||
Setting('setting_server', 'server.ignoreUA', ignoreUA, 'textarea', 'server.ignoreUA', 'ignoredUA'),
|
Setting('setting_server', 'server.ignoreUA', ignoreUA, 'textarea', 'server.ignoreUA', 'ignoredUA'),
|
||||||
ServerLangSettingNode,
|
ServerLangSettingNode,
|
||||||
Setting('setting_limits', 'limit.problem_files_max', 100, 'number', 'limit.problem_files_max', 'Max files per problem'),
|
Setting('setting_limits', 'limit.problem_files_max', 100, 'number', 'limit.problem_files_max', 'Max files per problem'),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ console.log(
|
|||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
window.UiContext = JSON.parse(window.UiContext);
|
window.UiContext = JSON.parse(window.UiContext);
|
||||||
|
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
@@ -32,16 +32,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
eval(payload[0]); // eslint-disable-line no-eval
|
eval(payload[0]); // eslint-disable-line no-eval
|
||||||
payload.shift();
|
payload.shift();
|
||||||
window.Hydro.preload = payload;
|
window.Hydro.preload = payload;
|
||||||
import('./hydro');
|
|
||||||
} else {
|
} else {
|
||||||
fetch(`/constant?version=${UiContext.constantVersion}`)
|
const res = await fetch(`/constant?version=${UiContext.constantVersion}`);
|
||||||
.then((res) => res.json())
|
const data = await res.json();
|
||||||
.then((data) => {
|
|
||||||
eval(data.payload[0]); // eslint-disable-line no-eval
|
eval(data.payload[0]); // eslint-disable-line no-eval
|
||||||
localStorage.setItem('hydro-constant', JSON.stringify(data));
|
localStorage.setItem('hydro-constant', JSON.stringify(data));
|
||||||
data.payload.shift();
|
data.payload.shift();
|
||||||
window.Hydro.preload = data.payload;
|
window.Hydro.preload = data.payload;
|
||||||
import('./hydro');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import('./hydro');
|
||||||
}, false);
|
}, false);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.27.11",
|
"version": "4.27.12",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><h2>{{ ddoc.title }}</h2></li>
|
<li><h2>{{ ddoc.title }}</h2></li>
|
||||||
<li>
|
<li>
|
||||||
{{ user.render_inline(udict[ddoc.owner]) }}
|
{{ user.render_inline(udoc) }}
|
||||||
@
|
@
|
||||||
{{ datetimeSpan(ddoc._id)|safe }}
|
{{ datetimeSpan(ddoc._id)|safe }}
|
||||||
</li>
|
</li>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="section__footer supplementary dot list">
|
<ul class="section__footer supplementary dot list">
|
||||||
{% if handler.user.hasPerm(perm.PERM_EDIT_DISCUSSION) or (handler.user.own(ddoc) and handler.user.hasPerm(perm.PERM_EDIT_DISCUSSION_SELF)) %}
|
{% if handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) or handler.user.own(ddoc) %}
|
||||||
<li><a href="{{ url('blog_edit', uid=udoc._id, did=ddoc.docId) }}">
|
<li><a href="{{ url('blog_edit', uid=udoc._id, did=ddoc.docId) }}">
|
||||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||||
</a></li>
|
</a></li>
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
<input type="hidden" name="operation" value="{% if not dsdoc['star'] %}star{% else %}unstar{% endif %}">
|
<input type="hidden" name="operation" value="{% if not dsdoc['star'] %}star{% else %}unstar{% endif %}">
|
||||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<button class="star{% if dsdoc['star'] %} activated{% endif %}" type="submit">
|
<button class="star{% if dsdoc['star'] %} activated{% endif %}" type="submit">
|
||||||
<span class="starred--hide"><span class="icon icon-star--outline"></span> {{ _('Star Topic') }}</span>
|
<span class="starred--hide"><span class="icon icon-star--outline"></span> {{ _('Star') }}</span>
|
||||||
<span class="starred--show"><span class="icon icon-star"></span> {{ _('Unstar Topic') }}</span>
|
<span class="starred--show"><span class="icon icon-star"></span> {{ _('Unstar') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</form></li>
|
</form></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<button name="operation" value="{{ 'update' if ddoc else 'create' }}" type="submit" class="rounded primary button">
|
<button name="operation" value="{{ 'update' if ddoc else 'create' }}" type="submit" class="rounded primary button">
|
||||||
{{ _('Update') if ddoc else _('Create') }} (Ctrl+Enter)
|
{{ _('Update') if ddoc else _('Create') }} (Ctrl+Enter)
|
||||||
</button>
|
</button>
|
||||||
{% if ddoc and (handler.user.own(ddoc) or handler.user.hasPerm(perm.PERM_DELETE_DISCUSSION)) %}
|
{% if ddoc and (handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) or handler.user.own(ddoc)) %}
|
||||||
<button name="operation" value="delete" type="submit" class="rounded button">
|
<button name="operation" value="delete" type="submit" class="rounded button">
|
||||||
{{ _('Delete') }}
|
{{ _('Delete') }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<h1 class="section__title">{{ _("{0}'s blog").format(udoc.uname) }}</h1>
|
<h1 class="section__title">{{ _("{0}'s blog").format(udoc.uname) }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="section__body">
|
<div class="section__body">
|
||||||
{% if handler.user.hasPerm(perm.PERM_CREATE_DISCUSSION) and handler.user._id == udoc._id %}
|
{% if handler.user._id == udoc._id %}
|
||||||
<p><a href="{{ url('blog_create', uid=udoc._id) }}" class="expanded primary button">{{ _('Create a Post') }}</a></p>
|
<p><a href="{{ url('blog_create', uid=udoc._id) }}" class="expanded primary button">{{ _('Create a Post') }}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -71,13 +71,19 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if handler.user.hasPriv(PRIV.PRIV_CREATE_FILE) %}
|
{% if handler.user.hasPriv(PRIV.PRIV_CREATE_FILE) %}
|
||||||
<li class="menu__seperator"></li>
|
|
||||||
<li class="menu__item">
|
<li class="menu__item">
|
||||||
<a href="{{ url('home_files') }}" class="menu__link">
|
<a href="{{ url('home_files') }}" class="menu__link">
|
||||||
<span class="icon icon-file"></span> {{ _('My Files') }}
|
<span class="icon icon-file"></span> {{ _('My Files') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) and model.system.get('server.blog') %}
|
||||||
|
<li class="menu__item">
|
||||||
|
<a href="{{ url('blog_main', uid=handler.user._id) }}" class="menu__link">
|
||||||
|
<span class="icon icon-book"></span> {{ _('Blog') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li class="menu__seperator"></li>
|
<li class="menu__seperator"></li>
|
||||||
{% if handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) %}
|
{% if handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) %}
|
||||||
<li class="menu__item nojs--hide">
|
<li class="menu__item nojs--hide">
|
||||||
|
|||||||
Reference in new issue
Block a user