مدیریت پروژه


کار ها:

  • نوشتن Decorator برای view ها (نمره:‌ ۶۵ درصد)
  • نوشتن view برای فعال کردن پروژه فعلی (نمره:‌ ۱۵ درصد)
  • نوشتن تابع has_permission (نمره:‌ ۲۰ درصد)

یک شرکت نرم‌افزاری می‌خواهد برای خود یک سیستم مدیریت پروژه بنویسد. بدین منظور سایتی با قابلیت های زیر طراحی شده است:

  • در این سایت چندین پروژه می‌تواند وجود داشته باشد.
  • هر پروژه می‌تواند چندین عضو داشته باشد.
  • هر کاربر می‌تواند در چند پروژه در نقش های مختلف عضویت داشته باشد.

از این لینک می‌توانید source code های پروژه را دانلود کنید.

ساختار این پروژه به شکل زیر است:

    src
    ├── manage.py
    ├── ProjectManager
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── projects
    │   ├── admin.py
    │   ├── apps.py
    │   ├── decorators.py        <--------
    │   ├── models.py            <--------
    │   ├── activation_view.py   <--------
    │   ├── templates
    │   │   └── projects
    │   │       └── project_home.html
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    └── requirements.txt
Plain text

مدلِProjectMembership که در فایل models.py نوشته شده است، عضویت یک فرد را در یک پروژه به همراه نقش او در پروژه نشان می‌دهد.

در فایل views.py نیز چندین view وجود دارد که اعمال مختلف قابل انجام روی پروژه را پیاده سازی کرده است.

این سایت بدین شکل کار می‌کند که همواره فقط یکی از پروژه های کاربر به عنوان "پروژه فعلی" او انتخاب شده است که از طریق صفحه‌ی index نیز قادر به مشاهده این پروژه هستیم و تمامی اعمال مختلف مانند حذف پروژه و غیره، روی همین پروژه فعلی انجام می‌شوند.

نکته: یک کاربر در یک پروژه فقط یک بار و با یک نقش می‌تواند عضو باشد. بنابراین واژه های "پروژه‌ی فعلی" و "عضویت فعلی" به یک معنا هستند.

حال از شما می‌خواهیم تغییرات زیر را در این پروژه انجام دهید.

۱. نوشتن activation_view:🔗

این view شناسه‌ی یک پروژه را به عنوان ورودی گرفته و آن را به عنوان پروژه فعلی انتخاب می‌کند. بدین منظور یک field در مدل ProjectMembership به نام is_current در نظر گرفته شده است که باید آن را مقدار دهی کند(is_current=True) و برای سایر عضویت‌ها (ProjectMembership) نیز این field را False کند.

  • توجه کنید ممکن است به هر دلیلی مانند race condition، از قبل برای یک کاربر چندین عضویت با is_current=True وجود داشته باشد. بعد از اجرای این کد باید اطمینان حاصل شود که برای این user، فقط یک عضویت فعلی وجود دارد.
  • در صورتی که کاربر فعلی در پروژه با شناسه مورد نظر عضویت نداشت یا به کل پروژه‌ای با شناسه مورد نظر وجود نداشت، باید یک پاسخ ۴۰۴ نشان دهید.
  • بعد از این که پروژه مورد نظر با موفقیت به عنوان پروژه فعلی برای کاربر فعلی انتخاب شد، این view باید به صفخه index (یعنی آدرس /project‍) redirect کند. در صفحه‌ی index باید بتوانیم پروژه انتخاب شده را ببینیم.

۲. نوشتن تابع has_permission:🔗

برای این بخش از سوال باید یک تابع به نام has_permission(action) در مدل ProjectMembership تعریف کنید. این تابع یک رشته را به عنوان ورودی دریافت می‌کند و بر اساس role یک boolean باز‌می‌گراند. انواع roleها در این مدل مشخص اند. شما باید بر اساس جدول زیر به ازای هر رشته ورودی خروجی درست را بازگردانید. توجه کنید که ورودی تابع به صورت snake_case می‌باشد.

جدول زیر دسترسی های نقش های مختلف در این پروژه را مشخص می‌کند.

Action Guest Reporter Developer Master Owner
create_new_issue
leave_comments
pull_project_code
assign_issues_and_merge_requests
see_a_list_of_merge_requests
manage_merge_requests
create_new_branches
add_new_team_members
push_to_protected_branches
switch_visibility_level
remove_project
force_push_to_protected_branches

۳. نوشتن Decorator:🔗

یک فایل به نام decorators.py نوشته شده است. شما باید در این فایل یک decorator بنویسید. این decorator در بالای همه‌ی view های موجود در فایل views.py قرار داده شده است. این decoratorبه شکل @projects_panel() در بالای view ها استفاده می‌شود که یک آرگومان optional به نام permissions دریافت می‌کند. در صورتی که این آرگومان به decorator پاس داده شود باید به صورت یک لیست باشد. برای مثال:

@projects_panel(permissions=['remove_project'])
def remove_project(request):
    request.project.delete()    
    return redirect('index')
Python

در این decorator باید کار های زیر را به ترتیب انجام دهید:

۱. ابتدا باید چک کنید که آیا برای کابر مورد نظر پروژه ای وجود دارد یا خیر.

  • اگر پروژه ای وجود نداشت یک خطای ۴۰۴ با متن "No projects found" بازگردانید.
  • در غیر این صورت، request.memberships را برابر queryset عضویت های کاربر قرار دهید.

۲. سپس باید چک کنید که آیا یک پروژه به عنوان پروژه فعلی برای کاربر وجود دارد یا خیر.

  • اگر پروژه ای به عنوان پروژه فعلی وجود نداشت، عضویت ای با کمترین id را به عنوان عضویت فعلی او انتخاب کنید. سپس request.current_membershipرا برابر عضویت فعلی کاربر قرار دهید.

۳. request.project را برابر پروژه فعلی کاربر قرار دهید.

۴. اگر آرگومان permissions وجود داشت باید بررسی کنید که آیا کاربر درعضویت فعلی خود، دسترسی های لازم را دارد یا خیر. برای این کار می‌توانید از تابع has_permission که در قسمت قبل نوشتید استفاده کنید.

  • اگر دسترسی وجود نداشت باید یک خطای ۴۰۳ (Forbidden) بازگردانید.

نکات🔗

  • شما تنها مجاز به تغییر در فایل هایی هستید که در ساختار بالا با فلش مشخص شده اند. اگر تغییری در سایر فایل‌ها ایجاد کنید، این تغییرات نادیده گرفته خواهد شد.
  • در فایل models.py میتوانید به تعداد دلخواه به هر مدلی تابع اضافه کنید. اما field ها و نام های مدل ها را تغییر ندهید.
  • پس از اعمال تغییرات، کل پروژه را Zip کرده و ارسال کنید.
  • نام فایل Zip اهمیت ندارد.
ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.