mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
core&ui: new domain_join logic
This commit is contained in:
1 parent
706a9a0928
commit
7fd01715bc
9 files changed
+81
-39
No files matched your search
@@ -114,12 +114,11 @@ class DomainUserHandler extends ManageHandler {
|
||||
// TODO: switch to getListForRender for better performance
|
||||
const udict = await user.getList(domainId, dudocs.map((dudoc) => dudoc.uid));
|
||||
const users = dudocs.filter((dudoc) => udict[dudoc.uid].priv & PRIV.PRIV_USER_PROFILE);
|
||||
for (const role of roles) {
|
||||
rudocs[role._id] = users.filter((dudoc) => dudoc.role === role._id).map((i) => udict[i.uid]);
|
||||
}
|
||||
const joined = Object.fromEntries(dudocs.map((dudoc) => [dudoc.uid, dudoc.join]));
|
||||
for (const role of roles) rudocs[role._id] = users.filter((udoc) => udoc.role === role._id);
|
||||
this.response.template = format === 'raw' ? 'domain_user_raw.html' : 'domain_user.html';
|
||||
this.response.body = {
|
||||
roles, rudocs, udict, domain: this.domain,
|
||||
roles, rudocs, domain: this.domain, joined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -215,7 +214,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
|
||||
async get() {
|
||||
const r = await domain.getRoles(this.domain);
|
||||
const roles = r.map((role) => role._id).sort();
|
||||
this.response.body.rolesWithText = roles.filter((i) => !['default', 'guest'].includes(i)).map((role) => [role, role]);
|
||||
this.response.body.rolesWithText = roles.filter((i) => i !== 'guest').map((role) => [role, role]);
|
||||
this.response.body.joinSettings = domain.getJoinSettings(this.domain, roles);
|
||||
this.response.body.expirations = { ...domain.JOIN_EXPIRATION_RANGE };
|
||||
if (!this.response.body.joinSettings) {
|
||||
@@ -279,33 +278,58 @@ class DomainJoinHandler extends Handler {
|
||||
joinSettings: any;
|
||||
noCheckPermView = true;
|
||||
|
||||
async prepare() {
|
||||
const r = await domain.getRoles(this.domain);
|
||||
@param('target', Types.DomainId, true)
|
||||
async prepare({ domainId }, target: string = domainId) {
|
||||
const [ddoc, dudoc] = await Promise.all([
|
||||
domain.get(target),
|
||||
domain.getDomainUser(target, this.user),
|
||||
]);
|
||||
if (dudoc.join) throw new DomainJoinAlreadyMemberError(target, this.user._id);
|
||||
const r = await domain.getRoles(ddoc);
|
||||
const roles = r.map((role) => role._id);
|
||||
this.joinSettings = domain.getJoinSettings(this.domain, roles);
|
||||
if (!this.joinSettings) throw new DomainJoinForbiddenError(this.domain._id);
|
||||
if (this.user.role !== 'default') throw new DomainJoinAlreadyMemberError(this.domain._id, this.user._id);
|
||||
this.joinSettings = domain.getJoinSettings(ddoc, roles);
|
||||
if (dudoc.role !== 'default') delete this.joinSettings;
|
||||
else if (!this.joinSettings) throw new DomainJoinForbiddenError(target);
|
||||
}
|
||||
|
||||
@param('code', Types.Content, true)
|
||||
async get(domainId: string, code: string) {
|
||||
@param('target', Types.DomainId, true)
|
||||
@param('redirect', Types.Content, true)
|
||||
async get({ domainId }, code: string, target: string = domainId, redirect: string = '') {
|
||||
this.response.template = 'domain_join.html';
|
||||
this.response.body.joinSettings = this.joinSettings;
|
||||
this.response.body.code = code;
|
||||
const ddoc = await domain.get(target);
|
||||
const domainInfo = {
|
||||
name: ddoc.name,
|
||||
owner: await user.getById(domainId, ddoc.owner),
|
||||
avatar: ddoc.avatar,
|
||||
bulletin: ddoc.showBulletin ? ddoc.bulletin : '',
|
||||
};
|
||||
this.response.body = {
|
||||
joinSettings: this.joinSettings,
|
||||
code,
|
||||
redirect,
|
||||
target,
|
||||
domainInfo,
|
||||
};
|
||||
}
|
||||
|
||||
@param('code', Types.Content, true)
|
||||
async post(domainId: string, code: string) {
|
||||
if (this.joinSettings.method === domain.JOIN_METHOD_CODE) {
|
||||
@param('target', Types.DomainId, true)
|
||||
@param('redirect', Types.Content, true)
|
||||
async post({ domainId }, code: string, target: string = domainId, redirect: string = '') {
|
||||
if (this.joinSettings?.method === domain.JOIN_METHOD_CODE) {
|
||||
if (this.joinSettings.code !== code) {
|
||||
throw new InvalidJoinInvitationCodeError(this.domain._id);
|
||||
throw new InvalidJoinInvitationCodeError(target);
|
||||
}
|
||||
}
|
||||
await Promise.all([
|
||||
domain.setUserRole(this.domain._id, this.user._id, this.joinSettings.role),
|
||||
domain.setUserInDomain(target, this.user._id, {
|
||||
join: true,
|
||||
...(this.joinSettings ? { role: this.joinSettings.role } : {}),
|
||||
}),
|
||||
oplog.log(this, 'domain.join', {}),
|
||||
]);
|
||||
this.response.redirect = this.url('homepage', { query: { notification: 'Successfully joined domain.' } });
|
||||
this.response.redirect = redirect || this.url('homepage', { domainId: target, query: { notification: 'Successfully joined domain.' } });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,6 +207,7 @@ class DomainModel {
|
||||
let dudoc = await collUser.findOne({ domainId, uid: udoc._id });
|
||||
dudoc ||= { domainId, uid: udoc._id };
|
||||
if (!(udoc.priv & PRIV.PRIV_USER_PROFILE)) dudoc.role = 'guest';
|
||||
if (!dudoc.join) dudoc.role = 'guest';
|
||||
if (udoc.priv & PRIV.PRIV_MANAGE_ALL_DOMAIN) dudoc.role = 'root';
|
||||
dudoc.role ||= 'default';
|
||||
const ddoc = await DomainModel.get(domainId);
|
||||
|
||||
@@ -212,6 +212,14 @@ export async function apply(ctx: Context) {
|
||||
redirect: (this.context.originalPath || this.request.path) + this.context.search,
|
||||
},
|
||||
});
|
||||
} else if (!this.user._dudoc.join && error instanceof PermissionError) {
|
||||
this.response.redirect = this.url('domain_join', {
|
||||
domainId: 'system',
|
||||
query: {
|
||||
redirect: (this.context.originalPath || this.request.path) + this.context.search,
|
||||
target: this.domain._id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.response.status = error instanceof UserFacingError ? error.code : 500;
|
||||
this.response.template = error instanceof UserFacingError ? 'error.html' : 'bsod.html';
|
||||
|
||||
@@ -489,6 +489,8 @@ IOI(Strict): IOI(严格)
|
||||
Is rated: 计入排名
|
||||
It works!: 它成了!
|
||||
Italic: 斜体
|
||||
Join Domain to Create a Discussion: 加入域后创建讨论
|
||||
Join Domain to Submit: 加入域后递交
|
||||
Join: 加入
|
||||
Judge Config: 评测设置
|
||||
Judge Status: 评测状态
|
||||
@@ -603,6 +605,7 @@ Not Attended: 未参加
|
||||
Not available: 不可用
|
||||
Not Claimed: 未认领
|
||||
Not Enrolled: 未参加
|
||||
Not joined yet: 暂未加入
|
||||
Not started with a number: 不以数字开头
|
||||
Not wrapped with space: 两侧不含空格
|
||||
Numeric PID: 数字题号
|
||||
@@ -698,9 +701,9 @@ problem_import: 导入题目
|
||||
problem_main: 题库
|
||||
problem_solution: 题解
|
||||
problem_submit: 递交代码
|
||||
problem_type.communication: 通信题
|
||||
problem_type.default: 传统题
|
||||
problem_type.interactive: 交互题
|
||||
problem_type.communication: 通信题
|
||||
problem_type.objective: 客观题
|
||||
problem_type.remote_judge: 远端评测题
|
||||
problem_type.submit_answer: 提交答案题
|
||||
|
||||
@@ -5,12 +5,25 @@
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
{{ _('Join {0}').format(handler.domain['name']) }}
|
||||
{% if joinSettings %}
|
||||
{{ _('Join {0}').format(domainInfo['name']) }}
|
||||
{% else %}
|
||||
{{ _('You are invited to join {0}').format(domainInfo['name']) }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p>{{ _('By clicking the button, you will become a member of the domain {0}.').format(handler.domain['name']) }}</p>
|
||||
<p>{{ _('By clicking the button, you will become a member of the domain {0}.').format(domainInfo['name']) }}</p>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p>{{ _('The domain owner:') }}</p>
|
||||
{{ user.render_inline(domainInfo['owner']) }}
|
||||
</div>
|
||||
{% if domainInfo['bulletin'] %}
|
||||
<div class="section__body typo">
|
||||
{{ domainInfo['bulletin']|markdown }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body typo">
|
||||
<form method="post">
|
||||
{% if joinSettings['method'] == model.domain.JOIN_METHOD_CODE %}
|
||||
@@ -24,6 +37,8 @@
|
||||
autofocus:true
|
||||
}) }}
|
||||
{% endif %}
|
||||
<input type="hidden" name="target" value="{{ target }}">
|
||||
<input type="hidden" name="redirect" value="{{ redirect }}">
|
||||
<button type="submit" class="primary rounded button">{{ _('Join') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -25,14 +25,6 @@
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Settings') }}</h1>
|
||||
</div>
|
||||
{% if rolesWithText.length == 1 %}
|
||||
<div class="section__body typo">
|
||||
<blockquote class="warn">
|
||||
<p>{{ _("The 'default' role applies to ALL REGISTERED USER.")|safe }}</p>
|
||||
<p>{{ _("You may want to create a new role in 'Manage Role' page.")|safe }}</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body">
|
||||
<form method="POST">
|
||||
{{ form.form_select({
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Permissions').format(domain.name) }}</h1>
|
||||
</div>
|
||||
{% if roles.length == 3 %}
|
||||
<div class="section__body typo">
|
||||
<blockquote class="warn">
|
||||
<p>{{ _("The 'default' role applies to ALL REGISTERED USER.")|safe }}</p>
|
||||
<p>{{ _("You may want to create a new role in 'Manage Role' page.")|safe }}</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body no-padding domain-users">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
|
||||
@@ -100,7 +100,8 @@
|
||||
{{ rudoc._id }}
|
||||
</td>
|
||||
<td class="col--user">
|
||||
{{ user.render_inline(udict[rudoc._id], badge=false) }}
|
||||
{{ user.render_inline(rudoc, badge=false) }}
|
||||
{% if not joined[rudoc._id] %}<span class="text-orange">({{ _('Not joined yet') }})</span>{% endif %}
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ form.select({
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
{% if not handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="javascript:showSignInDialog();">
|
||||
<span class="icon icon-add"></span> {{ _('Login to Create a Discussion') }}</a></li>
|
||||
{% elif not handler.user._dudoc.join %}
|
||||
<li class="menu__item"><a class="menu__link" href="javascript:joinDomain();">
|
||||
<span class="icon icon-add"></span> {{ _('Join Domain to Create a Discussion') }}</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link disabled" href="javascript:;">
|
||||
<span class="icon icon-add"></span> {{ _('No Permission to Create a Discussion') }}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -46,6 +48,10 @@
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="javascript:showSignInDialog();">
|
||||
<span class="icon icon-send"></span> {{ _('Login to Submit') }}
|
||||
</a></li>
|
||||
{% elif not handler.user._dudoc.join %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link disabled{% if page_name == 'problem_submit' %} active{% endif %}" href="javascript:joinDomain();">
|
||||
<span class="icon icon-send"></span> {{ _('Join Domain to Submit') }}
|
||||
</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link disabled{% if page_name == 'problem_submit' %} active{% endif %}" href="javascript:;">
|
||||
<span class="icon icon-send"></span> {{ _('No Permission to Submit') }}
|
||||
|
||||
Reference in new issue
Block a user