mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: domain-join: bug fixes & add i18n
Co-authored-by: panda <panda_dtdyy@outlook.com>
This commit is contained in:
1 parent
b9dbdc39ca
commit
e9c5bf5900
6 files changed
+70
-20
No files matched your search
@@ -101,24 +101,68 @@ class DomainUserHandler extends ManageHandler {
|
|||||||
@requireSudo
|
@requireSudo
|
||||||
@param('format', Types.Range(['default', 'raw']), true)
|
@param('format', Types.Range(['default', 'raw']), true)
|
||||||
async get({ domainId }, format = 'default') {
|
async get({ domainId }, format = 'default') {
|
||||||
const rudocs = {};
|
|
||||||
const [dudocs, roles] = await Promise.all([
|
const [dudocs, roles] = await Promise.all([
|
||||||
domain.getMultiUserInDomain(domainId, {
|
domain.collUser.aggregate([
|
||||||
$and: [
|
{
|
||||||
{ role: { $nin: ['default', 'guest'] } },
|
$match: {
|
||||||
{ role: { $ne: null } },
|
$or: [{
|
||||||
],
|
join: true,
|
||||||
}).toArray(),
|
}, {
|
||||||
|
role: {
|
||||||
|
$nin: ['default', 'guest'],
|
||||||
|
$ne: null,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
domainId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: 'user',
|
||||||
|
let: { uid: '$uid' },
|
||||||
|
pipeline: [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
$expr: { $eq: ['$_id', '$$uid'] },
|
||||||
|
priv: { $bitsAllSet: PRIV.PRIV_USER_PROFILE },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
_id: 1,
|
||||||
|
uname: 1,
|
||||||
|
avatar: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
as: 'user',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ $unwind: '$user' },
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
user: 1,
|
||||||
|
role: 1,
|
||||||
|
join: 1,
|
||||||
|
displayName: this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]).toArray(),
|
||||||
domain.getRoles(domainId),
|
domain.getRoles(domainId),
|
||||||
]);
|
]);
|
||||||
// TODO: switch to getListForRender for better performance
|
const users = dudocs.map((dudoc) => {
|
||||||
const udict = await user.getList(domainId, dudocs.map((dudoc) => dudoc.uid));
|
const u = {
|
||||||
const users = dudocs.filter((dudoc) => udict[dudoc.uid].priv & PRIV.PRIV_USER_PROFILE);
|
...dudoc,
|
||||||
const joined = Object.fromEntries(dudocs.map((dudoc) => [dudoc.uid, dudoc.join]));
|
...dudoc.user,
|
||||||
|
};
|
||||||
|
delete u.user;
|
||||||
|
return u;
|
||||||
|
});
|
||||||
|
const rudocs = {};
|
||||||
for (const role of roles) rudocs[role._id] = users.filter((udoc) => udoc.role === role._id);
|
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.template = format === 'raw' ? 'domain_user_raw.html' : 'domain_user.html';
|
||||||
this.response.body = {
|
this.response.body = {
|
||||||
roles, rudocs, domain: this.domain, joined,
|
roles, rudocs, domain: this.domain,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +330,7 @@ class DomainJoinHandler extends Handler {
|
|||||||
]);
|
]);
|
||||||
const assignedRole = this.user.hasPriv(PRIV.PRIV_MANAGE_ALL_DOMAIN)
|
const assignedRole = this.user.hasPriv(PRIV.PRIV_MANAGE_ALL_DOMAIN)
|
||||||
? 'root'
|
? 'root'
|
||||||
: dudoc?.role;
|
: dudoc?.role || 'default';
|
||||||
if (dudoc?.join) throw new DomainJoinAlreadyMemberError(target, this.user._id);
|
if (dudoc?.join) throw new DomainJoinAlreadyMemberError(target, this.user._id);
|
||||||
const r = await domain.getRoles(ddoc);
|
const r = await domain.getRoles(ddoc);
|
||||||
const roles = r.map((role) => role._id);
|
const roles = r.map((role) => role._id);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class DomainModel {
|
|||||||
};
|
};
|
||||||
await bus.parallel('domain/create', ddoc);
|
await bus.parallel('domain/create', ddoc);
|
||||||
await coll.insertOne(ddoc);
|
await coll.insertOne(ddoc);
|
||||||
await DomainModel.setUserRole(domainId, owner, 'root');
|
await DomainModel.setUserRole(domainId, owner, 'root', true);
|
||||||
return domainId;
|
return domainId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,9 +133,10 @@ class DomainModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async setUserRole(domainId: string, uid: MaybeArray<number>, role: string) {
|
static async setUserRole(domainId: string, uid: MaybeArray<number>, role: string, autojoin = false) {
|
||||||
|
const update = { $set: { role, ...(autojoin ? { join: true } : {}) } };
|
||||||
if (!(uid instanceof Array)) {
|
if (!(uid instanceof Array)) {
|
||||||
const res = await collUser.findOneAndUpdate({ domainId, uid }, { $set: { role } }, { upsert: true, returnDocument: 'after' });
|
const res = await collUser.findOneAndUpdate({ domainId, uid }, update, { upsert: true, returnDocument: 'after' });
|
||||||
const udoc = await UserModel.getById(domainId, uid);
|
const udoc = await UserModel.getById(domainId, uid);
|
||||||
deleteUserCache(udoc);
|
deleteUserCache(udoc);
|
||||||
return res;
|
return res;
|
||||||
@@ -144,7 +145,7 @@ class DomainModel {
|
|||||||
.project<{ _id: number, mail: string, uname: string }>({ mail: 1, uname: 1 })
|
.project<{ _id: number, mail: string, uname: string }>({ mail: 1, uname: 1 })
|
||||||
.toArray();
|
.toArray();
|
||||||
for (const udoc of affected) deleteUserCache(udoc);
|
for (const udoc of affected) deleteUserCache(udoc);
|
||||||
return await collUser.updateMany({ domainId, uid: { $in: uid } }, { $set: { role } }, { upsert: true });
|
return await collUser.updateMany({ domainId, uid: { $in: uid } }, update, { upsert: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getRoles(domainId: string, count?: boolean): Promise<any[]>;
|
static async getRoles(domainId: string, count?: boolean): Promise<any[]>;
|
||||||
|
|||||||
@@ -707,7 +707,7 @@ export const coreScripts: MigrationScript[] = [
|
|||||||
async function _91_92() {
|
async function _91_92() {
|
||||||
await domain.collUser.updateMany({}, { $set: { join: true } });
|
await domain.collUser.updateMany({}, { $set: { join: true } });
|
||||||
await domain.coll.updateMany(
|
await domain.coll.updateMany(
|
||||||
{ _join: { $or: [{ $exists: false }, { $eq: null }] } },
|
{ $or: [{ _join: { $exists: false } }, { _join: { $eq: null } }] },
|
||||||
{ $set: { _join: { method: domain.JOIN_METHOD_ALL, role: 'default', expire: null }, _migratedJoin: true } },
|
{ $set: { _join: { method: domain.JOIN_METHOD_ALL, role: 'default', expire: null }, _migratedJoin: true } },
|
||||||
);
|
);
|
||||||
const domainUser = await domain.coll.find({ domainId: 'system', join: true }, onPrimary)
|
const domainUser = await domain.coll.find({ domainId: 'system', join: true }, onPrimary)
|
||||||
|
|||||||
@@ -906,6 +906,7 @@ Testdata: 测试数据
|
|||||||
Text: 文本
|
Text: 文本
|
||||||
The 'default' role applies to ALL REGISTERED USER.: default 角色作用于<b>所有已注册用户</b>
|
The 'default' role applies to ALL REGISTERED USER.: default 角色作用于<b>所有已注册用户</b>
|
||||||
The contest is a flexible time contest. You need to complete the contest within a specified time after you attended.: 本场比赛采用灵活时间模式,你需要在参加后的指定时间内完成比赛。
|
The contest is a flexible time contest. You need to complete the contest within a specified time after you attended.: 本场比赛采用灵活时间模式,你需要在参加后的指定时间内完成比赛。
|
||||||
|
The domain owner: 域所有者:
|
||||||
The homework's deadline is due but in extension. You can still submit for this problem but your score will be penalized.: 作业已超过截止时间,但仍在延期时间内。您递交题目将无法获得全部分数。
|
The homework's deadline is due but in extension. You can still submit for this problem but your score will be penalized.: 作业已超过截止时间,但仍在延期时间内。您递交题目将无法获得全部分数。
|
||||||
The invitation code to enter to successfully join the domain. You can only use letters and numbers in the code and it should not be longer than 64 characters.: 加入此域的邀请码。您只能使用字母和数字,并且不能长于 64 个字符。
|
The invitation code to enter to successfully join the domain. You can only use letters and numbers in the code and it should not be longer than 64 characters.: 加入此域的邀请码。您只能使用字母和数字,并且不能长于 64 个字符。
|
||||||
The invitation code you provided is invalid.: 您提供的邀请码无效。
|
The invitation code you provided is invalid.: 您提供的邀请码无效。
|
||||||
@@ -1057,6 +1058,7 @@ Write Your Comment: 发表您的评论
|
|||||||
Write Your Solution: 发表您的题解
|
Write Your Solution: 发表您的题解
|
||||||
Year: 年
|
Year: 年
|
||||||
You are currently in legacy mode. Some additional features will be unavailable. We strongly recommend switching to standard mode on a modern browser.: 您当前处于兼容模式。某些功能在此模式下不可用。我们强烈建议在现代浏览器上切换为标准模式以获得更好的体验。
|
You are currently in legacy mode. Some additional features will be unavailable. We strongly recommend switching to standard mode on a modern browser.: 您当前处于兼容模式。某些功能在此模式下不可用。我们强烈建议在现代浏览器上切换为标准模式以获得更好的体验。
|
||||||
|
You are invited to join {0}: '您被邀请加入 {0}'
|
||||||
You are not allowed to join the domain. The link is either invalid or expired.: 您无法加入该域,链接无效或已过期。
|
You are not allowed to join the domain. The link is either invalid or expired.: 您无法加入该域,链接无效或已过期。
|
||||||
You can also upload your avatar to Gravatar and it will be automatically updated here.: 你也可以将头像上传到 <a href="https://gravatar.com/">Gravatar</a>,本站的头像将自动更新。
|
You can also upload your avatar to Gravatar and it will be automatically updated here.: 你也可以将头像上传到 <a href="https://gravatar.com/">Gravatar</a>,本站的头像将自动更新。
|
||||||
You can create your own training plans and share them with others.: 您可以创建您自己的训练计划并且与他人分享。
|
You can create your own training plans and share them with others.: 您可以创建您自己的训练计划并且与他人分享。
|
||||||
|
|||||||
@@ -82,7 +82,9 @@
|
|||||||
{%- for udoc in udocs -%}
|
{%- for udoc in udocs -%}
|
||||||
{% set is_disabled=(rudoc._id == handler.user._id) %}
|
{% set is_disabled=(rudoc._id == handler.user._id) %}
|
||||||
<input type="checkbox" data-uid="{{udoc._id}}" data-checkbox-group="user" {% if is_disabled %}disabled{% else %}data-checkbox-range{% endif %}>
|
<input type="checkbox" data-uid="{{udoc._id}}" data-checkbox-group="user" {% if is_disabled %}disabled{% else %}data-checkbox-range{% endif %}>
|
||||||
[{{udoc._id}}]{{ user.render_inline(udoc, avatar=false, badge=false) }}
|
[{{udoc._id}}]{{ user.render_inline(udoc, avatar=false, badge=false) }}{% if not udoc.join %}
|
||||||
|
<span class="text-orange">({{ _('Not joined yet') }})</span>
|
||||||
|
{% endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
</div></td>
|
</div></td>
|
||||||
<td>{{ role }}</td>
|
<td>{{ role }}</td>
|
||||||
@@ -101,7 +103,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="col--user">
|
<td class="col--user">
|
||||||
{{ user.render_inline(rudoc, badge=false) }}
|
{{ user.render_inline(rudoc, badge=false) }}
|
||||||
{% if not joined[rudoc._id] %}<span class="text-orange">({{ _('Not joined yet') }})</span>{% endif %}
|
{% if not rudoc.join %}<span class="text-orange">({{ _('Not joined yet') }})</span>{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="col--role">
|
<td class="col--role">
|
||||||
{{ form.select({
|
{{ form.select({
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
<li class="menu__item"><a class="menu__link" href="javascript:joinDomain();">
|
<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>
|
<span class="icon icon-add"></span> {{ _('Join Domain to Create a Discussion') }}</a></li>
|
||||||
{% else %}
|
{% 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>
|
<span class="icon icon-add"></span> {{ _('No Permission to Create a Discussion') }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in new issue
Block a user