1- from datetime import timedelta , datetime
1+ from datetime import datetime , timedelta
22
33from django .utils import timezone
4+ from rest_framework .exceptions import PermissionDenied , ValidationError
5+ from rest_framework .permissions import SAFE_METHODS , BasePermission
46
5- from rest_framework .permissions import BasePermission , SAFE_METHODS
6- from rest_framework .exceptions import PermissionDenied
7-
7+ from partner_programs .models import PartnerProgram , PartnerProgramUserProfile
88from projects .models import Project
9- from partner_programs .models import PartnerProgramUserProfile
109
1110
1211class IsProjectLeaderOrReadOnlyForNonDrafts (BasePermission ):
@@ -79,29 +78,37 @@ class TimingAfterEndsProgramPermission(BasePermission):
7978 for `_SECONDS_AFTER_CANT_EDIT` seconds -> days from the end of the program.
8079 If the project is not in program or the request in `SAFE_METHODS` -> allowed.
8180 """
81+
8282 _SECONDS_AFTER_CANT_EDIT : int = 60 * 60 * 24 * 30 # Now 30 days.
8383
8484 def has_object_permission (self , request , view , obj ) -> bool :
8585 if request .method in SAFE_METHODS :
8686 return True
8787
8888 program_profile = (
89- PartnerProgramUserProfile .objects
90- .filter (user = request .user , project = obj )
89+ PartnerProgramUserProfile .objects .filter (user = request .user , project = obj )
9190 .select_related ("partner_program" )
9291 .first ()
9392 )
9493 moscow_time : datetime = timezone .localtime (timezone .now ())
9594
9695 if program_profile :
97- date_from_end_program : timedelta = (moscow_time - program_profile .partner_program .datetime_finished )
96+ date_from_end_program : timedelta = (
97+ moscow_time - program_profile .partner_program .datetime_finished
98+ )
9899 days_from_end_program : int = date_from_end_program .days
99100 seconds_from_end_program : int = date_from_end_program .total_seconds ()
100101 if 0 <= seconds_from_end_program <= self ._SECONDS_AFTER_CANT_EDIT :
101- raise PermissionDenied (detail = self ._prepare_exception_detail (days_from_end_program , program_profile ))
102+ raise PermissionDenied (
103+ detail = self ._prepare_exception_detail (
104+ days_from_end_program , program_profile
105+ )
106+ )
102107 return True
103108
104- def _prepare_exception_detail (self , days_from_end_program : int , program_profile : PartnerProgramUserProfile ):
109+ def _prepare_exception_detail (
110+ self , days_from_end_program : int , program_profile : PartnerProgramUserProfile
111+ ):
105112 """
106113 Prepare response body when `PermissionDenied` exception raised:
107114 program_name: str -> Program title
@@ -112,7 +119,11 @@ def _prepare_exception_detail(self, days_from_end_program: int, program_profile:
112119 when_can_edit : datetime = timezone .localtime (
113120 datetime_finished + timedelta (seconds = self ._SECONDS_AFTER_CANT_EDIT )
114121 )
115- days_until_resolution : int = int (self ._SECONDS_AFTER_CANT_EDIT / 60 / 60 / 24 ) - days_from_end_program - 1
122+ days_until_resolution : int = (
123+ int (self ._SECONDS_AFTER_CANT_EDIT / 60 / 60 / 24 )
124+ - days_from_end_program
125+ - 1
126+ )
116127 return {
117128 "program_name" : program_profile .partner_program .name ,
118129 "when_can_edit" : when_can_edit ,
@@ -140,3 +151,24 @@ def has_object_permission(self, request, view, obj):
140151 ) or obj .project .leader == request .user :
141152 return True
142153 return False
154+
155+
156+ class CanBindProjectToProgram (BasePermission ):
157+ message = "Привязать проект к программе может только её участник (или менеджер)."
158+
159+ def has_permission (self , request , view ):
160+ program_id = (request .data or {}).get ("partner_program_id" )
161+ if not program_id :
162+ return True
163+
164+ try :
165+ program = PartnerProgram .objects .get (pk = program_id )
166+ except PartnerProgram .DoesNotExist :
167+ raise ValidationError ({"partner_program_id" : "Программа не найдена." })
168+
169+ if program .is_manager (request .user ):
170+ return True
171+
172+ return PartnerProgramUserProfile .objects .filter (
173+ user = request .user , partner_program = program
174+ ).exists ()
0 commit comments