-
-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: Added service quota limits
- Loading branch information
Showing
32 changed files
with
1,048 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from django.db.models import Q | ||
from django.http import HttpRequest | ||
from django.shortcuts import render, redirect | ||
|
||
from backend.models import QuotaLimit | ||
|
||
|
||
def fetch_all_quotas(request: HttpRequest, group: str): | ||
context = {} | ||
if not request.htmx: | ||
return redirect("quotas") | ||
|
||
search_text = request.GET.get("search") | ||
|
||
results = QuotaLimit.objects.filter(slug__startswith=group).prefetch_related("quota_overrides", "quota_usage").order_by("-slug") | ||
|
||
if search_text: | ||
results = results.filter(Q(name__icontains=search_text)) | ||
|
||
quotas = [ | ||
{ | ||
"quota_limit": ql.get_quota_limit(request.user), | ||
"period_usage": ql.get_period_usage(request.user), | ||
"quota_object": ql, | ||
} | ||
for ql in results | ||
] | ||
|
||
context.update({"quotas": quotas}) | ||
return render(request, "pages/quotas/_fetch_body.html", context) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
from dataclasses import dataclass | ||
from typing import Union | ||
|
||
from django.contrib import messages | ||
from django.http import HttpRequest, HttpResponse | ||
from django.shortcuts import redirect, render | ||
from django.views.decorators.http import require_http_methods | ||
|
||
from backend.decorators import superuser_only | ||
from backend.models import QuotaIncreaseRequest, QuotaLimit, QuotaUsage, QuotaOverrides | ||
from backend.utils import quota_usage_check_under | ||
|
||
|
||
def submit_request(request: HttpRequest, slug) -> HttpResponse: | ||
if not request.htmx: | ||
return redirect("quotas") | ||
|
||
new_value = request.POST.get("new_value") | ||
reason = request.POST.get("reason") | ||
|
||
try: | ||
quota_limit = QuotaLimit.objects.get(slug=slug) | ||
except QuotaLimit.DoesNotExist: | ||
return error(request, "Failed to get the quota limit type") | ||
|
||
usage_per_item = quota_usage_check_under(request, "quota_increase-request", extra_data=quota_limit.id, api=True, htmx=True) | ||
usage_per_month = quota_usage_check_under( | ||
request, "quota_increase-requests_per_month_per_quota", extra_data=quota_limit.id, api=True, htmx=True | ||
) | ||
|
||
if not isinstance(usage_per_item, bool): | ||
return usage_per_item | ||
|
||
if not isinstance(usage_per_month, bool): | ||
return usage_per_month | ||
|
||
current = quota_limit.get_quota_limit(request.user) | ||
|
||
validate = validate_request(new_value, reason, current) | ||
|
||
if isinstance(validate, Error): | ||
return error(request, validate.message) | ||
|
||
quota_increase_request = QuotaIncreaseRequest.objects.create( | ||
user=request.user, quota_limit=quota_limit, new_value=new_value, current_value=current | ||
) | ||
|
||
QuotaUsage.create_str(request.user, "quota_increase-request", quota_increase_request.id) | ||
QuotaUsage.create_str(request.user, "quota_increase-requests_per_month_per_quota", quota_limit.id) | ||
|
||
messages.success(request, "Successfully submitted a quota increase request") | ||
return render(request, "partials/messages_list.html") | ||
|
||
|
||
@dataclass | ||
class Error: | ||
message: str | ||
|
||
|
||
def error(request: HttpRequest, message: str) -> HttpResponse: | ||
messages.error(request, message) | ||
return render(request, "partials/messages_list.html") | ||
|
||
|
||
def validate_request(new_value, reason, current) -> Union[True, Error]: | ||
if not new_value: | ||
return Error("Please enter a valid increase value") | ||
|
||
try: | ||
new_value = int(new_value) | ||
if new_value <= current: | ||
raise ValueError | ||
except ValueError: | ||
return Error("Please enter a valid increase value that is above your current limit.") | ||
|
||
if len(reason) < 25: | ||
return Error("Please enter a valid reason for the increase.") | ||
|
||
return True | ||
|
||
|
||
@superuser_only | ||
@require_http_methods(["DELETE", "POST"]) | ||
def approve_request(request: HttpRequest, request_id) -> HttpResponse: | ||
if not request.htmx: | ||
return redirect("quotas") | ||
try: | ||
quota_request = QuotaIncreaseRequest.objects.get(id=request_id) | ||
except QuotaIncreaseRequest.DoesNotExist: | ||
return error(request, "Failed to get the quota increase request") | ||
|
||
QuotaOverrides.objects.filter(user=quota_request.user).delete() | ||
|
||
QuotaOverrides.objects.create( | ||
user=quota_request.user, | ||
value=quota_request.new_value, | ||
quota_limit=quota_request.quota_limit, | ||
) | ||
|
||
quota_limit_for_increase = QuotaLimit.objects.get(slug="quota_increase-request") | ||
QuotaUsage.objects.filter(user=quota_request.user, quota_limit=quota_limit_for_increase, extra_data=quota_request.id).delete() | ||
quota_request.status = "approved" | ||
quota_request.save() | ||
|
||
return HttpResponse(status=200) | ||
|
||
|
||
@superuser_only | ||
@require_http_methods(["DELETE", "POST"]) | ||
def decline_request(request: HttpRequest, request_id) -> HttpResponse: | ||
if not request.htmx: | ||
return redirect("quotas") | ||
try: | ||
quota_request = QuotaIncreaseRequest.objects.get(id=request_id) | ||
except QuotaIncreaseRequest.DoesNotExist: | ||
return error(request, "Failed to get the quota increase request") | ||
|
||
quota_limit_for_increase = QuotaLimit.objects.get(slug="quota_increase-request") | ||
QuotaUsage.objects.filter(user=quota_request.user, quota_limit=quota_limit_for_increase, extra_data=quota_request.id).delete() | ||
quota_request.status = "decline" | ||
quota_request.save() | ||
|
||
return HttpResponse(status=200) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from django.urls import path | ||
|
||
from . import fetch, requests | ||
|
||
urlpatterns = [ | ||
path( | ||
"fetch/<str:group>/", | ||
fetch.fetch_all_quotas, | ||
name="fetch", | ||
), | ||
path("submit_request/<slug:slug>/", requests.submit_request, name="submit_request"), | ||
path("request/<int:request_id>/approve/", requests.approve_request, name="approve request"), | ||
path("request/<int:request_id>/decline/", requests.decline_request, name="decline request"), | ||
] | ||
|
||
app_name = "quotas" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.