Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -8,10 +8,11 @@ on:
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Copy files to server
|
||||
uses: appleboy/scp-action@v0.1.6
|
||||
@@ -21,8 +22,19 @@ jobs:
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
source: "."
|
||||
target: "/root/hshop/"
|
||||
rm: true
|
||||
|
||||
- name: SSH command to build and start Docker
|
||||
- name: Deploy environment file
|
||||
uses: appleboy/ssh-action@v0.1.6
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
username: ${{ secrets.SSH_USER }}
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
script: |
|
||||
mkdir -p /root/hshop/backend/
|
||||
printf "%s" "${{ secrets.ENV_FILE_CONTENT }}" > /root/hshop/backend/.env.local
|
||||
|
||||
- name: Build and start Docker containers
|
||||
uses: appleboy/ssh-action@v0.1.6
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
@@ -30,6 +42,11 @@ jobs:
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
script: |
|
||||
cd /root/hshop/
|
||||
docker compose down
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
||||
docker compose down --remove-orphans --timeout 60
|
||||
|
||||
docker compose up --build --detach --remove-orphans
|
||||
|
||||
docker image prune -af
|
||||
|
||||
docker compose ps
|
||||
@@ -242,3 +242,10 @@ class SecurityBreachAttemptModel(models.Model):
|
||||
class Meta:
|
||||
verbose_name = "تلاش نفوذ"
|
||||
verbose_name_plural = "تلاشهای نفوذ"
|
||||
|
||||
# class NotifModel(models.Model):
|
||||
# subject = models.CharField(max_length=100)
|
||||
# description = models.TextField()
|
||||
|
||||
# def __str__(self):
|
||||
# return f'{self.subject[:30]}'
|
||||
@@ -2,6 +2,8 @@ from django.urls import path
|
||||
from . import views
|
||||
from djoser.urls.jwt import views as djoser_jwt_views
|
||||
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('profile', views.ProfileView.as_view()),
|
||||
path('verify', djoser_jwt_views.TokenVerifyView.as_view(), name='jwt-verify'),
|
||||
@@ -13,6 +15,7 @@ urlpatterns = [
|
||||
path('address/list', views.GetUserAddressesView.as_view(), name='list-addresses'),
|
||||
path('address/<int:pk>', views.GetIDUserAddressView.as_view(), name='get-ID-address'),
|
||||
path('subscribe', views.SubscribeView.as_view(), name='subscibe'),
|
||||
path('unsubscribe', views.UnsubscribeView.as_view(), name='unsubscibe'),
|
||||
path('attack/view/<int:pk>', views.ChangeViewAttack.as_view(), name='attack-view'),
|
||||
path('logout', views.LogoutView.as_view(), name='logout'),
|
||||
]
|
||||
@@ -11,12 +11,11 @@ from django.shortcuts import get_object_or_404, redirect
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
import ghasedak_sms
|
||||
from django.views import View
|
||||
# this works only need to be used
|
||||
# class APIView(APIView):
|
||||
# def __init__(self, *args, **kwargs):
|
||||
# super().__init__(*args, **kwargs)
|
||||
# if AllowAny in self.permission_classes or not self.permission_classes:
|
||||
# self.authentication_classes = []
|
||||
from rest_framework import serializers
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
|
||||
|
||||
class SendOTPView(APIView):
|
||||
permission_classes = [AllowAny]
|
||||
@extend_schema(
|
||||
@@ -143,7 +142,9 @@ class CreateAddressView(generics.CreateAPIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(user=self.request.user)
|
||||
user = self.request.user
|
||||
is_first_address = not UserAddressModel.objects.filter(user=user).exists()
|
||||
serializer.save(user=user, is_main=is_first_address)
|
||||
|
||||
class EditAddressView(generics.UpdateAPIView):
|
||||
queryset = UserAddressModel.objects.all()
|
||||
@@ -190,6 +191,25 @@ class SubscribeView(APIView):
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class UnsubscribeSerializer(serializers.Serializer):
|
||||
end_point = serializers.CharField()
|
||||
|
||||
class UnsubscribeView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = UnsubscribeSerializer
|
||||
def post(self, request):
|
||||
endpoint = request.data.get("end_point")
|
||||
if not endpoint:
|
||||
return Response({"detail": "اند پوینت لازم است"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
deleted, _ = PushSubscription.objects.filter(user=request.user, endpoint=endpoint).delete()
|
||||
|
||||
if deleted:
|
||||
return Response({"detail": "با موفقیت اشتراک پاک شد"}, status=status.HTTP_200_OK)
|
||||
|
||||
return Response({"detail": "اند پوینت پیدا نشد"}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
class ChangeViewAttack(View):
|
||||
def get(self, request, pk):
|
||||
attack = get_object_or_404(SecurityBreachAttemptModel, pk=pk)
|
||||
@@ -198,8 +218,6 @@ class ChangeViewAttack(View):
|
||||
return redirect('admin:account_securitybreachattemptmodel_changelist')
|
||||
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
class LogoutSerializer(serializers.Serializer):
|
||||
refresh_token = serializers.CharField(help_text="Refresh token to be blacklisted")
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 5.1.2 on 2025-03-19 17:58
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('azbankgateways', '0006_bank_order'),
|
||||
('order', '0023_remove_ordermodel_bank_records'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='bank',
|
||||
name='order',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bank_records', to='order.ordermodel'),
|
||||
),
|
||||
]
|
||||
@@ -143,7 +143,7 @@ USE_TZ = True
|
||||
# Static Files Configuration
|
||||
# ==============================================================================
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(BASE_DIR, "custom_static"),
|
||||
# os.path.join(BASE_DIR, "custom_static"),
|
||||
BASE_DIR / "core" / "static",
|
||||
]
|
||||
|
||||
|
||||
@@ -5,3 +5,6 @@ class OrderConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'order'
|
||||
verbose_name = 'سفارش'
|
||||
|
||||
def ready(self):
|
||||
import order.signals
|
||||
@@ -20,7 +20,21 @@ class GetOrderPermission(BasePermission):
|
||||
def has_object_permission(self, request, view, obj):
|
||||
if obj.user != request.user:
|
||||
return False
|
||||
if obj.status != 'CART':
|
||||
if obj.status == 'CART':
|
||||
self.message = "سفارش در وضعیت سبد خرید است"
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
||||
from rest_framework.permissions import BasePermission
|
||||
|
||||
class SetAddressPermissions(BasePermission):
|
||||
message = "این ادرس متعلق به شما نیست."
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
if obj.user != request.user:
|
||||
self.message = "این ادرس متعلق به شما نیست."
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from django.db.models.signals import pre_save
|
||||
from django.dispatch import receiver
|
||||
from .models import OrderModel
|
||||
|
||||
@receiver(pre_save, sender=OrderModel)
|
||||
def order_status_changed(sender, instance, **kwargs):
|
||||
if instance.pk:
|
||||
previous = OrderModel.objects.get(pk=instance.pk)
|
||||
|
||||
if previous.status != instance.status:
|
||||
send_change_status_notif(instance)
|
||||
|
||||
|
||||
def send_change_status_notif(order):
|
||||
pass
|
||||
|
||||
def update_cart_price_fields(order):
|
||||
pass
|
||||
|
||||
def update_sell_data(order):
|
||||
pass
|
||||
|
||||
def update_quantity(order):
|
||||
pass
|
||||
@@ -1,16 +1,17 @@
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from .views import CartItemViews, CartView, OrderlistView, CartItemClear, ApplyDiscountView, OrderGetView
|
||||
from .views import CartItemViews, CartView, OrderlistView, CartItemClear, ApplyDiscountView, OrderGetView, SetAddressForCartView
|
||||
from .views import PaymentView, callback_view
|
||||
|
||||
urlpatterns = [
|
||||
path('all', OrderlistView.as_view(), name='order-list'),
|
||||
path('cart', CartView.as_view()),
|
||||
path('cart/set-address', SetAddressForCartView.as_view()),
|
||||
path('cart/discount', ApplyDiscountView.as_view()),
|
||||
path('cart/all', CartItemClear.as_view()),
|
||||
path('cart/item/<int:pk>', CartItemViews.as_view(), name='change-item-cart'),
|
||||
path('payment', PaymentView.as_view(), name='payment'),
|
||||
path('cart/payment', PaymentView.as_view(), name='payment'),
|
||||
path('callback', callback_view, name='callback-gateway'),
|
||||
path('<int:pk>', OrderGetView.as_view(), name='order-get'),
|
||||
]
|
||||
|
||||
+42
-1
@@ -7,13 +7,16 @@ from .serializers import *
|
||||
# from cart.models import
|
||||
from rest_framework import status
|
||||
from .models import OrderItemModel, OrderModel, DiscountCode
|
||||
from .permissons import CanDeleteCartItemPermissions, GetOrderPermission
|
||||
from .permissons import CanDeleteCartItemPermissions, GetOrderPermission, SetAddressPermissions
|
||||
from azbankgateways import bankfactories, models as bank_models
|
||||
from azbankgateways.exceptions import AZBankGatewaysException
|
||||
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
||||
from utils.pagination import StructurePagination
|
||||
from order.models import OrderModel
|
||||
from django.urls import reverse
|
||||
from account.models import UserAddressModel
|
||||
|
||||
|
||||
# try:
|
||||
# pass
|
||||
# except DiscountNotAvailableError:
|
||||
@@ -176,9 +179,22 @@ class OrderGetView(APIView):
|
||||
order_ser = self.serializer_class(order_object, context={'request': request})
|
||||
return Response(order_ser.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
class BankTypeSerializer(serializers.Serializer):
|
||||
gateway_type = serializers.ChoiceField(choices=['BMI', 'SEP', 'ZARINPAL', 'IDPAY', 'ZIBAL', 'BAHAMTA', 'MELLAT', 'PAYV1'])
|
||||
|
||||
|
||||
class PaymentView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = BankTypeSerializer
|
||||
@extend_schema(
|
||||
description="choices=['BMI', 'SEP', 'ZARINPAL', 'IDPAY', 'ZIBAL', 'BAHAMTA', 'MELLAT', 'PAYV1']"
|
||||
)
|
||||
def post(self, request):
|
||||
print(request.data.get('gateway_type'))
|
||||
cart_order = get_object_or_404(OrderModel, user=request.user, status='CART')
|
||||
amount = 5000
|
||||
user_mobile_number = request.user.phone
|
||||
@@ -237,3 +253,28 @@ def callback_view(request):
|
||||
return HttpResponse(
|
||||
"پرداخت با شکست مواجه شده است. اگر پول کم شده است ظرف مدت ۴۸ ساعت پول به حساب شما بازخواهد گشت."
|
||||
)
|
||||
|
||||
|
||||
|
||||
class SetAddressSerilizer(serializers.Serializer):
|
||||
address_id = serializers.IntegerField()
|
||||
|
||||
class SetAddressForCartView(APIView):
|
||||
serializer_class = SetAddressSerilizer
|
||||
permission_classes = [IsAuthenticated, SetAddressPermissions]
|
||||
def post(self, request):
|
||||
address_id = request.data.get('address_id', None)
|
||||
if not address_id:
|
||||
return Response({'detail': 'address_id را ارسال کنید'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
address_object = get_object_or_404(UserAddressModel, pk=address_id)
|
||||
permission = SetAddressPermissions()
|
||||
if not permission.has_object_permission(request, self, address_object):
|
||||
return Response({"detail": permission.message}, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
cart_order, created = OrderModel.objects.get_or_create(
|
||||
user=request.user,
|
||||
status='CART'
|
||||
)
|
||||
cart_order.address = address_object
|
||||
cart_order.save()
|
||||
return Response({'detail': 'ادرس با موفقیت انتخاب شد'})
|
||||
Reference in New Issue
Block a user