Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support setting record publicity #255

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions vj4/handler/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from vj4.model import user
from vj4.model.adaptor import contest
from vj4.model.adaptor import problem
from vj4.model.adaptor import setting
from vj4.service import bus
from vj4.util import options

Expand Down Expand Up @@ -142,16 +143,24 @@ async def get(self, *, rid: objectid.ObjectId):
show_status = self.tdoc_visible(tdoc)
else:
tdoc = None
# TODO(twd2): futher check permission for visibility.
if (not self.own(rdoc, field='uid')
udoc, dudoc = await asyncio.gather(
user.get_by_uid(rdoc['uid']),
domain.get_user(self.domain_id, rdoc['uid']))
# check visibility
visibility = rdoc.get('visibility', constant.setting.SUBMISSION_VISIBILITY_DEFAULT)
if visibility == constant.setting.SUBMISSION_VISIBILITY_USE_SETTINGS:
u = setting.UserSetting(udoc)
visibility = u.get_setting('show_submission_code')
can_view_code = visibility == constant.setting.PRIVACY_PUBLIC \
or (visibility == constant.setting.PRIVACY_REGISTERED_ONLY
and self.has_priv(builtin.PRIV_USER_PROFILE))
if (not can_view_code
and not self.own(rdoc, field='uid')
and not self.has_perm(builtin.PERM_READ_RECORD_CODE)
and not self.has_priv(builtin.PRIV_READ_RECORD_CODE)):
del rdoc['code']
if not show_status and 'code' not in rdoc:
raise error.PermissionError(builtin.PERM_VIEW_CONTEST_HIDDEN_STATUS)
udoc, dudoc = await asyncio.gather(
user.get_by_uid(rdoc['uid']),
domain.get_user(self.domain_id, rdoc['uid']))
try:
pdoc = await problem.get(rdoc['domain_id'], rdoc['pid'])
except error.ProblemNotFoundError:
Expand Down Expand Up @@ -205,6 +214,8 @@ class RecordRejudgeHandler(base.Handler):
@base.sanitize
async def post(self, *, rid: objectid.ObjectId):
rdoc = await record.get(rid)
if not rdoc:
raise error.RecordNotFoundError(rid)
if rdoc['domain_id'] == self.domain_id:
self.check_perm(builtin.PERM_REJUDGE)
else:
Expand All @@ -213,6 +224,22 @@ async def post(self, *, rid: objectid.ObjectId):
self.json_or_redirect(self.referer_or_main)


@app.route('/records/{rid}/visibility', 'record_visibility')
class RecordVisibilityHandler(base.Handler):
@base.route_argument
@base.post_argument
@base.require_csrf_token
@base.sanitize
async def post(self, *, rid: objectid.ObjectId, visibility: int):
rdoc = await record.get(rid)
if not rdoc or rdoc['domain_id'] != self.domain_id:
raise error.RecordNotFoundError(rid)
if (not self.own(rdoc, field='uid', perm=builtin.PERM_EDIT_RECORD_VISIBILITY_SELF)):
self.check_perm(builtin.PERM_EDIT_RECORD_VISIBILITY)
await record.set_visibility(rdoc['_id'], visibility)
self.json_or_redirect(self.referer_or_main)


@app.route('/records/{rid}/data', 'record_pretest_data')
class RecordPretestDataHandler(base.Handler):
@base.route_argument
Expand Down
36 changes: 18 additions & 18 deletions vj4/locale/zh_CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Begin Time: 开始时间
Belongs to: 属于
Bio: 个人简介
Bio Visibility: 个人简介可见性
Submission Code Visibility: 递交记录代码可见性
Sets whether your source code is public to others. This option may be overridden by submission options.: 设置其他人是否可以看到您递交的代码。该设置可能被递交记录的设置覆盖。
Blog: 博客
Boom!: 炸了!
Browser: 浏览器
Expand Down Expand Up @@ -142,6 +144,7 @@ Save All Changes: 保存所有修改
Saved session: 已保存的会话
Score: 分数
Secret: 保密
Use account settings: 由账户设置决定
Secret (visible to admins): 保密(对管理员可见)
Security: 安全
Select a node to create discussion.: 选择一个节点来发表讨论。
Expand Down Expand Up @@ -201,7 +204,7 @@ Using your Vijos universal account: 使用您的 Vijos 通用账户
View Problem: 查看题目
View or create discussion: 查看与发表讨论
View or submit solution: 查看与发表题解
Visible to registered users: 对注册用户可见
Public to registered users: 对注册用户可见
Vote: 投票
We use Gravatar to present your avatar icon.: 我们使用 Gravatar 服务来呈现您的头像。
Whether to show tags in the problem list.: 是否在题目列表中显示题目的标签。
Expand Down Expand Up @@ -407,33 +410,33 @@ View problems: 查看题目
Submit problem: 递交题目
Read data of problem: 读取题目数据
Read data of own problems: 读取自己题目的数据
Read record codes: 读取记录的代码
Read any record codes: 读取任意记录的代码
Rejudge problems: 重测题目
Rejudge records: 重测记录
View problem solutions: 查看题解
Create problem solutions: 创建题解
Vote problem solutions: 为题解投票
Edit problem solutions: 修改题解
Edit any problem solutions: 修改任意题解
Edit own problem solutions: 修改自己的题解
Delete problem solutions: 删除题解
Delete any problem solutions: 删除任意题解
Delete own problem solutions: 删除自己的题解
Reply problem solutions: 回复题解
Edit problem solution replies: 修改题解的回复
Edit any problem solution replies: 修改任意题解的回复
Edit own problem solution replies: 修改题解中自己的回复
Delete problem solution replies: 删除题解的回复
Delete any problem solution replies: 删除任意题解的回复
Delete own problem solution replies: 删除题解中自己的回复
View discussions: 查看讨论
Create discussions: 创建讨论
Highlight discussions: 高亮讨论
Edit discussions: 修改讨论
Edit any discussions: 修改任意讨论
Edit own discussions: 修改自己的讨论
Delete discussions: 删除讨论
Delete any discussions: 删除任意讨论
Delete own discussions: 删除自己的讨论
Reply discussions: 回复讨论
Edit discussion replies: 修改讨论的回复
Edit any discussion replies: 修改任意讨论的回复
Edit own discussion replies: 修改讨论中自己的回复
Edit discussion replies of own discussion: 修改自己讨论中的回复
Delete discussion replies: 删除讨论回复
Delete any discussion replies: 删除任意讨论回复
Delete own discussion replies: 删除讨论中自己的回复
Delete discussion replies of own discussion: 删除自己讨论中的回复
View contests: 查看比赛
Expand Down Expand Up @@ -524,7 +527,7 @@ collapse: 收缩
'Note: Problem title may not be hidden.': 注意:题目标题可能不会被隐藏。
Partic.: 参赛人数
Create training plans: 创建训练计划
Edit training plans: 修改训练计划
Edit any training plans: 修改任意训练计划
Edit own training plans: 修改自己的训练计划
Click here to chat with me: 点击这里与我聊天
Terms of Service: 服务条款
Expand Down Expand Up @@ -646,14 +649,11 @@ You cannot visit this domain.: 您不能访问此域。
Menu: 菜单
'Copy failed :(': '复制失败 :('
Code copied to clipboard!: 代码已复制到剪贴板!
Set any records' code visibility: 设置任意记录中代码的可见性
Set own records' code visibility: 设置自己记录中代码的可见性
No comments so far...: 目前还没有评论...
No solutions so far...: 目前还没有题解...
Edit Profile: 编辑个人信息
Send Message: 发送站内信息
Copy Email: 复制电子邮件
Copy QQ Number: 复制QQ号
Copy WeChat Account: 复制微信号
'"{data}" copied to clipboard!': “{data}”已复制到剪贴板!
'Copy "{data}" failed :(': '复制“{data}”失败 :('
You don't have the permission to view the code.: 您没有权限查看代码。
Visibility: 可见性
Introduce: 简介
Introduce must not exceed 500 characters and it will be shown in the list view.: 简介不能超过 500 个字符,将显示在列表页面中。
20 changes: 10 additions & 10 deletions vj4/locale/zh_TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Using your Vijos universal account: 使用您的 Vijos 通用賬戶
View Problem: 檢視題目
View or create discussion: 檢視與發表討論
View or submit solution: 檢視與發表題解
Visible to registered users: 對註冊使用者可見
Public to registered users: 對註冊使用者可見
Vote: 投票
We use Gravatar to present your avatar icon.: 我們使用 Gravatar 服務來呈現您的頭像。
Whether to show tags in the problem list.: 是否在題目列表中顯示題目的標籤。
Expand Down Expand Up @@ -401,33 +401,33 @@ View problems: 檢視題目
Submit problem: 遞交題目
Read data of problem: 讀取題目資料
Read data of own problems: 讀取自己題目的資料
Read record codes: 讀取記錄的程式碼
Read any record codes: 讀取記錄的程式碼
Rejudge problems: 重測題目
Rejudge records: 重測記錄
View problem solutions: 檢視題解
Create problem solutions: 創建題解
Vote problem solutions: 為題解投票
Edit problem solutions: 修改題解
Edit any problem solutions: 修改題解
Edit own problem solutions: 修改自己的題解
Delete problem solutions: 刪除題解
Delete any problem solutions: 刪除題解
Delete own problem solutions: 刪除自己的題解
Reply problem solutions: 回覆題解
Edit problem solution replies: 修改題解的回覆
Edit any problem solution replies: 修改題解的回覆
Edit own problem solution replies: 修改題解中自己的回覆
Delete problem solution replies: 刪除題解的回覆
Delete any problem solution replies: 刪除題解的回覆
Delete own problem solution replies: 刪除題解中自己的回覆
View discussions: 檢視討論
Create discussions: 創建討論
Highlight discussions: 高亮討論
Edit discussions: 修改討論
Edit any discussions: 修改討論
Edit own discussions: 修改自己的討論
Delete discussions: 刪除討論
Delete any discussions: 刪除討論
Delete own discussions: 刪除自己的討論
Reply discussions: 回覆討論
Edit discussion replies: 修改討論的回覆
Edit any discussion replies: 修改討論的回覆
Edit own discussion replies: 修改討論中自己的回覆
Edit discussion replies of own discussion: 修改自己討論中的回覆
Delete discussion replies: 刪除討論回覆
Delete any discussion replies: 刪除討論回覆
Delete own discussion replies: 刪除討論中自己的回覆
Delete discussion replies of own discussion: 刪除自己討論中的回覆
View contests: 檢視比賽
Expand Down
3 changes: 3 additions & 0 deletions vj4/model/adaptor/setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
ui='select', name='Gender Visibility'),
Setting('setting_privacy', 'show_bio', int, range=constant.setting.PRIVACY_RANGE,
ui='select', name='Bio Visibility'),
Setting('setting_privacy', 'show_submission_code', int, range=constant.setting.PRIVACY_RANGE,
ui='select', name='Submission Code Visibility', default=constant.setting.PRIVACY_SECRET,
desc='Sets whether your source code is public to others. This option may be overridden by submission options.'),
Setting('setting_customize', 'background_img', int, range=constant.setting.BACKGROUND_RANGE,
ui='image_radio', name='Profile Background Image', desc='Choose the background image in your profile page.',
image_class='user-profile-bg--thumbnail-{0}')]
Expand Down
29 changes: 18 additions & 11 deletions vj4/model/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
PERM_EDIT_TRAINING = 1 << 48
PERM_EDIT_TRAINING_SELF = 1 << 49

# Record.
PERM_EDIT_RECORD_VISIBILITY = 1 << 50
PERM_EDIT_RECORD_VISIBILITY_SELF = 1 << 51
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is near the limit of int52. Please be careful :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int52???

Copy link
Member Author

@breezewish breezewish Aug 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iceb0y Shall we store permission in binary format in MongoDB? We could serialize a long int to binary via something like xx.to_bytes(16, byteorder='little')


PERM_ALL = -1

Permission = functools.partial(
Expand All @@ -90,33 +94,35 @@
Permission('perm_problem', PERM_SUBMIT_PROBLEM, 'Submit problem'),
Permission('perm_problem', PERM_READ_PROBLEM_DATA, 'Read data of problem'),
Permission('perm_problem', PERM_READ_PROBLEM_DATA_SELF, 'Read data of own problems'),
Permission('perm_record', PERM_READ_RECORD_CODE, 'Read record codes'),
Permission('perm_record', PERM_READ_RECORD_CODE, 'Read any record codes'),
Permission('perm_record', PERM_EDIT_RECORD_VISIBILITY, 'Set any records\' code visibility'),
Permission('perm_record', PERM_EDIT_RECORD_VISIBILITY_SELF, 'Set own records\' code visibility'),
Permission('perm_record', PERM_REJUDGE_PROBLEM, 'Rejudge problems'),
Permission('perm_record', PERM_REJUDGE, 'Rejudge records'),
Permission('perm_problem_solution', PERM_VIEW_PROBLEM_SOLUTION, 'View problem solutions'),
Permission('perm_problem_solution', PERM_CREATE_PROBLEM_SOLUTION, 'Create problem solutions'),
Permission('perm_problem_solution', PERM_VOTE_PROBLEM_SOLUTION, 'Vote problem solutions'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION, 'Edit problem solutions'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION, 'Edit any problem solutions'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION_SELF, 'Edit own problem solutions'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION, 'Delete problem solutions'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION, 'Delete any problem solutions'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION_SELF, 'Delete own problem solutions'),
Permission('perm_problem_solution', PERM_REPLY_PROBLEM_SOLUTION, 'Reply problem solutions'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION_REPLY, 'Edit problem solution replies'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION_REPLY, 'Edit any problem solution replies'),
Permission('perm_problem_solution', PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF, 'Edit own problem solution replies'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION_REPLY, 'Delete problem solution replies'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION_REPLY, 'Delete any problem solution replies'),
Permission('perm_problem_solution', PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF, 'Delete own problem solution replies'),
Permission('perm_discussion', PERM_VIEW_DISCUSSION, 'View discussions'),
Permission('perm_discussion', PERM_CREATE_DISCUSSION, 'Create discussions'),
Permission('perm_discussion', PERM_HIGHLIGHT_DISCUSSION, 'Highlight discussions'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION, 'Edit discussions'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION, 'Edit any discussions'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION_SELF, 'Edit own discussions'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION, 'Delete discussions'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION, 'Delete any discussions'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION_SELF, 'Delete own discussions'),
Permission('perm_discussion', PERM_REPLY_DISCUSSION, 'Reply discussions'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION_REPLY, 'Edit discussion replies'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION_REPLY, 'Edit any discussion replies'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION_REPLY_SELF, 'Edit own discussion replies'),
Permission('perm_discussion', PERM_EDIT_DISCUSSION_REPLY_SELF_DISCUSSION, 'Edit discussion replies of own discussion'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION_REPLY, 'Delete discussion replies'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION_REPLY, 'Delete any discussion replies'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION_REPLY_SELF, 'Delete own discussion replies'),
Permission('perm_discussion', PERM_DELETE_DISCUSSION_REPLY_SELF_DISCUSSION, 'Delete discussion replies of own discussion'),
Permission('perm_contest', PERM_VIEW_CONTEST, 'View contests'),
Expand All @@ -126,7 +132,7 @@
Permission('perm_contest', PERM_ATTEND_CONTEST, 'Attend contests'),
Permission('perm_training', PERM_VIEW_TRAINING, 'View training plans'),
Permission('perm_training', PERM_CREATE_TRAINING, 'Create training plans'),
Permission('perm_training', PERM_EDIT_TRAINING, 'Edit training plans'),
Permission('perm_training', PERM_EDIT_TRAINING, 'Edit any training plans'),
Permission('perm_training', PERM_EDIT_TRAINING_SELF, 'Edit own training plans'),
]

Expand Down Expand Up @@ -209,7 +215,8 @@
PERM_ATTEND_CONTEST |
PERM_VIEW_TRAINING |
PERM_CREATE_TRAINING |
PERM_EDIT_TRAINING_SELF
PERM_EDIT_TRAINING_SELF |
PERM_EDIT_RECORD_VISIBILITY_SELF
)
ADMIN_PERMISSIONS = PERM_ALL
DOMAIN_SYSTEM = {
Expand Down
10 changes: 10 additions & 0 deletions vj4/model/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ async def rejudge(record_id: objectid.ObjectId, enqueue: bool=True):
await queue.publish('judge', rid=doc['_id'])


@argmethod.wrap
async def set_visibility(rid: objectid.ObjectId, visibility: int):
if visibility not in constant.setting.SUBMISSION_VISIBILITY_RANGE:
raise error.ValidationError('visibility')
coll = db.coll('record')
doc = await coll.find_one_and_update(filter={'_id': rid},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc is not used, please either remove the variable definition, or return something

update={'$set': {'visibility': visibility}},
return_document=ReturnDocument.AFTER)


@argmethod.wrap
def get_all_multi(end_id: objectid.ObjectId=None, get_hidden: bool=False, *, fields=None,
**kwargs):
Expand Down
6 changes: 6 additions & 0 deletions vj4/ui/components/form/button.page.styl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
cursor: default
opacity: 0.5

&.compact
margin-bottom: 0
height: rem($compact-control-height)
line-height: rem($compact-control-height - 2)
padding: rem(0 15px)

.button.inverse
line-height: rem($form-control-height - 4)
border: 2px solid #FFF
Expand Down
13 changes: 12 additions & 1 deletion vj4/ui/constant/setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ export const PRIVACY_REGISTERED_ONLY = 1;
export const PRIVACY_SECRET = 2;
export const PRIVACY_RANGE = {
[PRIVACY_PUBLIC]: 'Public',
[PRIVACY_REGISTERED_ONLY]: 'Visible to registered users',
[PRIVACY_REGISTERED_ONLY]: 'Public to registered users',
[PRIVACY_SECRET]: 'Secret',
};
attachObjectMeta(PRIVACY_RANGE, 'intKey', true);

export const SUBMISSION_VISIBILITY_USE_SETTINGS = 3;
export const SUBMISSION_VISIBILITY_RANGE = {
[PRIVACY_PUBLIC]: 'Public',
[PRIVACY_REGISTERED_ONLY]: 'Public to registered users',
[PRIVACY_SECRET]: 'Secret',
[SUBMISSION_VISIBILITY_USE_SETTINGS]: 'Use account settings',
};
attachObjectMeta(SUBMISSION_VISIBILITY_RANGE, 'intKey', true);

export const SUBMISSION_VISIBILITY_DEFAULT = SUBMISSION_VISIBILITY_USE_SETTINGS;

export const FUNCTION_RANGE = {
0: 'Disabled',
1: 'Enabled',
Expand Down
6 changes: 6 additions & 0 deletions vj4/ui/pages/record_detail.page.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { NamedPage } from 'vj/misc/PageLoader';

const page = new NamedPage('record_detail', async () => {
// Update visibility
$('[name="visibility-form"] [name="visibility"]').change(() => {
$('[name="visibility-form"]').submit();
});

// Realtime update
const SockJs = await System.import('sockjs-client');
const DiffDOM = await System.import('diff-dom');

Expand Down
1 change: 0 additions & 1 deletion vj4/ui/pages/record_detail.page.styl
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.page--record_detail

.compiler-text
padding: rem(20px 0)
font-size: rem($font-size-small)
&:empty
display: none
Expand Down
Loading