Skip to content

Commit 30a4a9b

Browse files
committed
Add permission for Rooms
1 parent 456a97e commit 30a4a9b

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 5.0.9 on 2024-12-28 12:28
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
("Appointment", "0004_room_image_room_quick_reservable_roomclass"),
10+
("auth", "0012_alter_user_first_name_max_length"),
11+
]
12+
13+
operations = [
14+
migrations.AlterModelOptions(
15+
name="room",
16+
options={
17+
"ordering": ["Rid"],
18+
"permissions": [("can_book_example_rooms", "可预约样例房间")],
19+
"verbose_name": "房间",
20+
"verbose_name_plural": "房间",
21+
},
22+
),
23+
migrations.AddField(
24+
model_name="room",
25+
name="required_perm",
26+
field=models.ForeignKey(
27+
blank=True,
28+
default=None,
29+
null=True,
30+
on_delete=django.db.models.deletion.SET_NULL,
31+
to="auth.permission",
32+
),
33+
),
34+
]

Appointment/models.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from django.db.models import QuerySet, Q
77
from django.dispatch import receiver
88
from django.db import transaction
9+
from django.contrib.auth.models import Permission
910

1011
from utils.models.descriptor import admin_only
1112
from utils.models.choice import choice, CustomizedDisplay, DefaultDisplay
1213
from utils.models.manager import ManyRelatedManager
1314
from utils.models.permission import PermissionModelBase, BasePermission
1415
from generic.models import User
1516
from Appointment.config import appointment_config as CONFIG
17+
from Appointment.apps import AppointmentConfig
1618

1719
__all__ = [
1820
'User',
@@ -144,6 +146,10 @@ class Meta:
144146
verbose_name = '房间'
145147
verbose_name_plural = verbose_name
146148
ordering = ['Rid']
149+
# 可以临时修改来生成 migrations 文件,但具体的权限不要留在 develop 分支里
150+
permissions = [
151+
('can_book_example_rooms', '可预约样例房间'),
152+
]
147153

148154
# 房间编号我不确定是否需要。如果地下室有门牌的话(例如B101)保留房间编号比较好
149155
# 如果删除Rid记得把Rtitle设置成主键
@@ -156,6 +162,15 @@ class Meta:
156162
Rlatest_time = models.DateTimeField("摄像头心跳", auto_now_add=True)
157163
Rpresent = models.IntegerField('目前人数', default=0)
158164
image = models.ImageField('房间图片', upload_to='room_images', null=True)
165+
# 不使用 “perms”,避免又一个 many-to-many 的表
166+
required_perm = models.ForeignKey(
167+
Permission, default=None, null=True, blank=True,
168+
on_delete=models.SET_NULL)
169+
170+
def check_user_perm(self, user: User) -> bool:
171+
'''检查用户是否有权限预约此房间'''
172+
return self.required_perm is None or user.has_perm(
173+
f'{AppointmentConfig.name}.{self.required_perm.codename}')
159174

160175
# Rstatus 标记当前房间是否允许预约,可由管理员修改
161176
class Status(models.IntegerChoices):

Appointment/views.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,8 @@ def credit(request):
270270

271271
@identity_check(redirect_field_name='origin', auth_func=lambda x: True)
272272
def index(request): # 主页
273-
render_context = {}
274-
render_context.update(
275-
show_admin=(request.user.is_superuser or request.user.is_staff),
276-
)
273+
user: User = request.user
274+
render_context = dict(show_admin=(user.is_superuser or user.is_staff))
277275
# 处理学院公告
278276
announcements = College_Announcement.objects.filter(
279277
show=College_Announcement.Show_Status.Yes)
@@ -308,11 +306,14 @@ def format_time(delta): # 格式化timedelta,隐去0h
308306
'-Rtitle') # 开放房间
309307
statistics_info = [(room, (room.Rpresent * 10) // (room.Rmax or 1))
310308
for room in unlimited_rooms] # 开放房间人数统计
311-
# TODO: optimization
312-
reservable_room_classes = [
313-
rclass for rclass in RoomClass.objects.order_by('sort_idx')
314-
if rclass.rooms.permitted().exists()
315-
]
309+
reservable_room_classes = []
310+
for rclass in RoomClass.objects.order_by('sort_idx').prefetch_related('rooms'):
311+
# TODO: perm check optimization?
312+
rooms = [room for room in rclass.rooms.permitted()
313+
if room.check_user_perm(user)]
314+
if rooms:
315+
reservable_room_classes.append((rclass, rooms))
316+
316317
quick_reservable_rooms = Room.objects.permitted().filter(quick_reservable=True)
317318
room_info = [(room, room.Rid in occupied_rooms,
318319
format_time(room_appointments[room.Rid]))
@@ -384,10 +385,12 @@ def arrange_time(request: HttpRequest):
384385
"""
385386
选择预约时间
386387
"""
387-
388+
user: User = request.user
388389
room = Room.objects.permitted().get(Rid=request.GET.get('Rid'))
390+
if not room.check_user_perm(user):
391+
raise PermissionError('您没有权限预约该房间!')
389392
# 判断当前用户是否可以进行长期预约
390-
has_longterm_permission = get_participant(request.user).longterm
393+
has_longterm_permission = get_participant(user).longterm
391394
is_longterm = (request.GET.get(
392395
'longterm') == 'on') and has_longterm_permission
393396
next_week = (request.GET.get('start_week') == '1') and is_longterm
@@ -504,7 +507,9 @@ def arrange_talk_room(request):
504507
or re_time.date() - datetime.now().date() > timedelta(days=6)):
505508
return redirect(reverse("Appointment:index"))
506509

507-
room_list = RoomClass.objects.get(name=room_class).rooms.permitted()
510+
room_list = [
511+
room for room in RoomClass.objects.get(name=room_class).rooms.permitted()
512+
if room.check_user_perm(request.user)]
508513
Rids = [room.Rid for room in room_list]
509514
# TODO: Fix `get_talkroom_timerange`
510515
t_start, t_finish = web_func.get_talkroom_timerange(

templates/Appointment/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ <h2 class="title col-0 my-auto mr-1">{{ room.Rid }}</h2>
232232
</div>
233233
</section>
234234

235-
{% for room_class in reservable_room_classes %}
235+
{% for room_class, rooms in reservable_room_classes %}
236236
<section class="section section-doctor" >
237237
<div class="container-fluid" >
238238
<div class="section-header text-center">
@@ -254,7 +254,7 @@ <h2>{{room_class.name}}预约</h2>
254254
</form>
255255
</div>
256256
<div class="doctor-slider slider" >
257-
{% for room in room_class.rooms.permitted %}
257+
{% for room in rooms %}
258258
<div class="profile-widget">
259259
<div class="doc-img">
260260
<img class="img-fluid" alt="User Image" src="/media/{{room.image}}">

0 commit comments

Comments
 (0)