Cambios API Clientes permisos

This commit is contained in:
fjrodriguez
2023-09-22 15:28:52 -06:00
parent 4bdb833cdb
commit ac80bf6a45
12 changed files with 452 additions and 55 deletions

View File

@@ -27,12 +27,13 @@ INSTALLED_APPS = [
'django.contrib.messages',
#'django.contrib.sites',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_framework',
'rest_framework.authtoken',
'widget_tweaks',
'import_export',
@@ -44,7 +45,10 @@ INSTALLED_APPS = [
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
# 'PAGE_SIZE': 100,
}
SITE_ID = 1
MIDDLEWARE = [
@@ -76,8 +80,7 @@ TEMPLATES = [
},
},
]
AUTHENTICATION_BACKENDS = [
AUTHENTICATION_BACKENDS = [
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',

View File

@@ -1,6 +1,9 @@
# from django.contrib import admin
# from . models import Sistemas_por_cliente_A24, ClientesA24, DeviceA24
from django.contrib import admin
from . models import Sistemas_por_cliente_A24, ClientesA24, DeviceA24
# admin.site.register(Sistemas_por_cliente_A24)
# admin.site.register(ClientesA24)
# admin.site.register(DeviceA24)
class Device_A24_Admin(admin.ModelAdmin):
list_display = ['clienteA24', 'dataBase','username','sistema','MAC','deviceName']
admin.site.register(Sistemas_por_cliente_A24)
admin.site.register(ClientesA24)
admin.site.register(DeviceA24, Device_A24_Admin)

View File

@@ -0,0 +1,42 @@
# Generated by Django 4.1.3 on 2023-09-15 18:18
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('Sistemas', '0019_alter_device_options'),
]
operations = [
migrations.CreateModel(
name='ClientesA24',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('RFC', models.CharField(max_length=13, unique=True)),
('Nombre', models.CharField(max_length=100)),
('Activo', models.BooleanField(default=False)),
('fecha_baja', models.DateField(blank=True, null=True)),
],
options={
'ordering': ('-Activo', 'RFC'),
},
),
migrations.CreateModel(
name='Sistemas_por_cliente_A24',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('num_licencias', models.IntegerField(default=1)),
('cliente', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cliente_spc_IMMEX', to='IMMEX.clientesa24')),
('id_sistema', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sistema_spc_IMMEX', to='Sistemas.sistema')),
],
options={
'ordering': ('-cliente', 'id_sistema'),
'unique_together': {('id_sistema', 'cliente')},
},
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 4.1.3 on 2023-09-18 13:57
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('authtoken', '0003_tokenproxy'),
('Sistemas', '0019_alter_device_options'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('IMMEX', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='DeviceA24',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('deviceName', models.CharField(max_length=255)),
('deviceOS', models.CharField(max_length=255)),
('deviceIP', models.GenericIPAddressField()),
('MAC', models.CharField(blank=True, max_length=30, null=True)),
('dataBase', models.CharField(blank=True, max_length=40, null=True)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('clienteA24', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='IMMEX.clientesa24')),
('sistema', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Sistemas.sistema')),
('token', models.ForeignKey(blank=True, max_length=40, null=True, on_delete=django.db.models.deletion.CASCADE, to='authtoken.token')),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('username',),
},
),
]

View File

View File

@@ -12,7 +12,7 @@ class ClientesA24(models.Model):
fecha_baja = models.DateField(blank=True,null=True)
class Meta:
ordering = ('-Activo','RFC',)
abstract=True
def __str__(self):
return self.Nombre
@@ -25,14 +25,14 @@ class Sistemas_por_cliente_A24(models.Model):
class Meta:
ordering= ('-cliente','id_sistema')
unique_together = ('id_sistema', 'cliente')
abstract=True
class DeviceA24(models.Model):
clienteA24 = models.ForeignKey(ClientesA24,on_delete=models.CASCADE)
deviceName = models.CharField(max_length=255)
deviceOS = models.CharField(max_length=255)
deviceIP = models.GenericIPAddressField()
token = models.ForeignKey(Token, on_delete=models.CASCADE,to_field='key', max_length=40, blank=True,null=True)
token = models.ForeignKey(Token, on_delete=models.CASCADE, max_length=40, blank=True,null=True)
username = models.ForeignKey(User, on_delete=models.CASCADE)
sistema = models.ForeignKey(Sistema, on_delete=models.CASCADE)
MAC = models.CharField(max_length=30, blank=True, null=True)
@@ -41,12 +41,12 @@ class DeviceA24(models.Model):
class Meta:
ordering = ('username',)
abstract=True
#abstract=True
def generate_username(self):
""""""
username_ = f"SCAII_{self.clienteA24}_{self.deviceName}_{self.MAC}"
def generate_username(self,client, device_name, mac_address):
""""""
username_ = f"SCAII_{client.RFC}_{device_name}_{mac_address}"
username_ = re.sub(r'\W+', '', username_)
if User.objects.filter(username=username_).exists():
@@ -56,7 +56,7 @@ class DeviceA24(models.Model):
def save(self,*args, **kwargs):
"""Overrides save method"""
if not self.pk:
obj = self.generate_username()
obj = self.generate_username(self.clienteA24, self.deviceName, self.MAC)
self.username=obj
token, created = Token.objects.get_or_create(user=obj)

View File

@@ -1,19 +1,142 @@
from rest_framework import serializers
from django.contrib.auth import get_user_model
from allauth.account.models import EmailAddress
from .models import ClientesA24
from Sistemas.models import Sistema
from .models import ClientesA24, Sistemas_por_cliente_A24, DeviceA24
class Sistema_A24_PKRF(serializers.PrimaryKeyRelatedField):
def to_internal_value(self,data):
try:
return Sistema.objects.get(nombre_sistema=data)
except Sistema.DoesNotExist:
raise serializers.ValidationError("Sistema no existe")
class ClientA24_PKRF(serializers.PrimaryKeyRelatedField):
def to_internal_value(self,data):
try:
return ClientesA24.objects.get(RFC=data)
except ClientesA24.DoesNotExist:
raise serializers.ValidationError("No existe Cliente")
class ClientA24_Create_PKRF(serializers.PrimaryKeyRelatedField):
def to_internal_value(self,data):
try:
return ClientesA24.objects.get(RFC=data)
except ClientesA24.DoesNotExist:
return None
#--------SERAILIZERS
class Sistema_Serializer(serializers.ModelSerializer):
class Meta:
model = Sistema
fields = ('nombre_sistema',)
class ClientesA24Serailizer(serializers.ModelSerializer):
class Meta:
model =ClientesA24
fields = ('RFC', 'Nombre','Activo','fecha_baja',)
fields = ('pk','RFC', 'Nombre','Activo','fecha_baja',)
class SerialiazerA24(serializers.ModelSerializer):
pass
clienteA24 = ClientA24_PKRF(queryset=ClientesA24.objects.all())
sistema = Sistema_A24_PKRF(queryset=Sistema.objects.all())
token = serializers.CharField(read_only=True)
class Meta:
model = DeviceA24
fields= ('clienteA24', 'deviceName', 'deviceOS', 'deviceIP', 'token', 'sistema', 'MAC', 'dataBase',)
def create(self, validated_data):
# Extraer los datos obligatorios de la solicitud
clienteA24 = validated_data['clienteA24']
deviceName = validated_data['deviceName']
deviceOS = validated_data['deviceOS']
deviceIP = validated_data['deviceIP']
MAC = validated_data['MAC']
sistema=validated_data['sistema']
dataBase = validated_data['dataBase']
# Verificar si ya existe un dispositivo con los mismos datos
existing_device = DeviceA24.objects.filter(
clienteA24=clienteA24,
#deviceName=deviceName,
#deviceOS=deviceOS,
#deviceIP=deviceIP,
MAC=MAC,
sistema=sistema,
dataBase=dataBase
).first()
if existing_device:
# Si ya existe un dispositivo con los mismos datos, puedes devolverlo
return existing_device
# Si no existe, crear un nuevo objeto DeviceA24
device_a24 = DeviceA24.objects.create(
clienteA24=clienteA24,
deviceName=deviceName,
deviceOS=deviceOS,
deviceIP=deviceIP,
MAC=MAC,
sistema=sistema,
dataBase=dataBase,
)
# Generar el nombre de usuario y otros campos automáticos
device_a24.username = device_a24.generate_username(clienteA24, deviceName, MAC)
device_a24.save() # Guardar para generar el timestamp
return device_a24
class Sistema_Por_Cliente_Serializer(serializers.ModelSerializer):
id_sistema = Sistema_A24_PKRF(queryset=Sistema.objects.all())
cliente = ClientA24_Create_PKRF(queryset=ClientesA24.objects.all())
clienteA24 = serializers.CharField(read_only=True)
token = serializers.CharField(read_only=True)
nombre_sistema = serializers.SerializerMethodField() # Agrega estos campos
rfc_cliente = serializers.SerializerMethodField()
class Meta:
model = Sistemas_por_cliente_A24
fields = ('id_sistema','cliente', 'clienteA24', 'token', 'nombre_sistema', 'rfc_cliente',)
def create(self, validated_data):
cliente = validated_data.get('cliente')
print('validated_data', validated_data)
if not cliente:
print("context clienteA24 ",self.context.get('clienteA24'))
print("context DeviceA24 ",self.context.get('DeviceA24'))
nuevo_cliente = self.context.get('clienteA24')
cliente = ClientesA24.objects.create(**nuevo_cliente)
sistema_por_cliente = Sistemas_por_cliente_A24.objects.create(
id_sistema=validated_data['id_sistema'],
cliente=cliente
)
device_serializer_data = self.context.get('DeviceA24')
device_serailizer = SerialiazerA24(data=device_serializer_data)
if device_serailizer.is_valid():
device = device_serailizer.save()
sistema_por_cliente.token=device.token
else:
sistema_por_cliente.token=""
return sistema_por_cliente
def get_nombre_sistema(self, obj):
return obj.id_sistema.nombre_sistema if obj.id_sistema else ""
def get_rfc_cliente(self, obj):
return obj.cliente.RFC if obj.cliente else ""
User = get_user_model()
class SignupSerializer(serializers.Serializer):
password = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)

View File

@@ -7,5 +7,12 @@ urlpatterns = [
path('create_Cliente/', views.ClientesIMMEX_CreateView.as_view(), name='ClientesIMMEX_Create'),
path('checkRfcA24/', views.Check_IMMEX_RFC.as_view(), name='checkRfcA24' ),
path('api/registro/', views.RegistroUsuarios.as_view(), name='api_registro'),
path('api/login/', views.LoginIMMEX.as_view(), name='api_login'),
path('api/login/', views.LoginIMMEX.as_view(), name='api_login'),
path('api/deviceA24/', views.RegisterIMMEX_Device_APIView.as_view(),name='api_device_a24'),
path('api/sistemasList/', views.Sistemas_IMMEX_List_APIView.as_view(),name='api_IMMEX_sistemas_list'),
path('api/sistema_por_cliente/', views.Sistema_por_cliente_APIView.as_view(),name='api_IMMEX_sistema_por_cliente'),
path('api/clientes/', views.ClientesA24List.as_view(),name='api_IMMEX_Clientes'),
path('api/clientes/detail/<int:pk>/', views.ClientesA24Detail.as_view(),name='api_IMMEX_Cliente_detail'),
]

View File

@@ -1,34 +1,41 @@
# Imports de Django
from django.shortcuts import render
from allauth.account.models import EmailConfirmation, EmailAddress
from django.http import JsonResponse
from django.http import Http404
from django.urls import reverse_lazy, reverse
from django.core.mail import send_mail
from Sistemas.models import Sistema, BitacoraErrores
from .models import Sistemas_por_cliente_A24, ClientesA24
from django.views.generic.edit import CreateView
from django.views.generic.list import ListView
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.utils import timezone
# Imports de Django REST framework
from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from .forms import ClienteForm_IMMEX
from .serializers import ClientesA24Serailizer,SerialiazerA24
from rest_framework.authentication import TokenAuthentication
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from rest_framework import authentication
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from .serializers import SignupSerializer
from Sistemas.permissions import ItsAdminToken, HasAuthorizationHeader
from rest_framework.pagination import PageNumberPagination
from rest_framework import generics
from django.utils import timezone
# Imports de allauth
from allauth.account.models import EmailConfirmation, EmailAddress
from allauth.account.forms import SignupForm
# Imports de tus modelos y serializadores
from .models import Sistemas_por_cliente_A24, ClientesA24, DeviceA24
from Sistemas.models import Sistema, BitacoraErrores
from Sistemas.permissions import ItsAdminToken, HasAuthorizationHeader, CheckPermiso
from .forms import ClienteForm_IMMEX
from .serializers import ClientesA24Serailizer, SerialiazerA24, SignupSerializer, Sistema_Serializer, Sistema_Por_Cliente_Serializer
# Otras bibliotecas y módulos
import urllib.parse
import traceback
import json
class Sistemas_xCliente_IMMEX_ListView(UserPassesTestMixin,LoginRequiredMixin, ListView):
model = Sistemas_por_cliente_A24
@@ -168,12 +175,162 @@ class Check_IMMEX_RFC(APIView):
return Response({'Error':f'check_RFC:{E} RFC:{rfc}','isError':True})
class RegisterIMMEX_Device_APIView(APIView):
"""Register IMMEX Devices"""
"""Register IMMEX Devices
se manda el siguiente JSON
{ "dataBase" : "CuentaGastosIII",
"deviceIP" : "192.168.1.28",
"deviceOS" : "Microsoft Windows NT 6.1.7601 Service Pack 1",
"deviceName" : "ASJUA-WEB05",
"clienteA24" : "C&A010417QS6",
"sistema" : "CFDI",
"MAC" : "F8BC12952BE2"
}
este es un ejemplo, el clienteA24 y sistema deben ser nombres validos para
sus tablas en IMMEX, es decir deben estar dados de alta en AS Admin en IMMEX
"""
permissions_classes=[IsAuthenticated, ItsAdminToken]
def post(self,request):
try:
serializer = SerialiazerA24(data=request.data, context={'request':request})
if serializer.is_valid():
instance =serializer.save()
token = instance.token.key
return Response({'token':token}, status=status.HTTP_201_CREATED)
else:
return Response({'Error':f'{serializer.errors}','isError':True}, status=status.HTTP_200_OK)
except Exception as ex:
BitacoraErrores.objects.create(level=2, message=str(ex), traceback=traceback.format_exc(),
view='Sistemas.RegisterDeviceView')
data_json = json.dumps(request.data)
traceback_info = f'{data_json}\n{traceback.format_exc()}'
BitacoraErrores.objects.create(level=2, message=str(ex), traceback=traceback_info,
view='IMMEX.RegisterIMMEX_Device_APIView')
return Response({'Error':f'{ex}','isError':True}, status=status.HTTP_200_OK)
class Sistemas_IMMEX_List_APIView(APIView):
def get(self, request):
sistemas = Sistema.objects.all()
serializer = Sistema_Serializer(sistemas,many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class Sistema_por_cliente_APIView(APIView):
def get(self, request):
nombre_sistema = request.query_params.get('nombre_sistema')
cliente_rfc = request.query_params.get('cliente_rfc')
db = request.query_params.get('db')
MAC = request.query_params.get('MAC')
sistemas_por_cliente = Sistemas_por_cliente_A24.objects.all()
if nombre_sistema:
sistemas_por_cliente = sistemas_por_cliente.filter(id_sistema__nombre_sistema=nombre_sistema)
if cliente_rfc:
sistemas_por_cliente = sistemas_por_cliente.filter(cliente__RFC=cliente_rfc)
dispositivos = DeviceA24.objects.filter(sistema__nombre_sistema=nombre_sistema, clienteA24__RFC=cliente_rfc)
serializer = Sistema_Por_Cliente_Serializer(sistemas_por_cliente, many=True,
context={'request': request})
data=serializer.data
for item in data:
del item['id_sistema']
del item['cliente']
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request):
try:
context = {
'clienteA24':request.data.get('clienteA24'),
'DeviceA24':request.data.get('DeviceA24')
}
serializer = Sistema_Por_Cliente_Serializer(data=request.data, context=context)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response({'Error':f'{serializer.errors}','isError':True}, status=status.HTTP_200_OK)
except Exception as ex:
data_json = json.dumps(request.data)
traceback_info = f'{data_json}\n{traceback.format_exc()}'
BitacoraErrores.objects.create(level=2, message=str(ex), traceback=traceback_info,
view='IMMEX.Sistema_por_cliente_APIView')
return Response({'Error':f'{ex}','isError':True}, status=status.HTTP_200_OK)
#CRUD Clientes IMMEX
class MyPage(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 100
class ClientesA24List(generics.ListCreateAPIView):
authentication_classes = (BasicAuthentication, TokenAuthentication, )
permission_classes=[IsAuthenticated,CheckPermiso]
queryset = ClientesA24.objects.all()
serializer_class = ClientesA24Serailizer
pagination_class = MyPage
ordering_fields = ('RFC',"Nombre", 'Activo')
def get_queryset(self):
queryset = ClientesA24.objects.all()
# Filtrar por RFC si se proporciona como parámetro de consulta
rfc = self.request.query_params.get('RFC')
Nombre = self.request.query_params.get('Nombre')
if rfc:
queryset = queryset.filter(RFC__icontains=rfc)
if Nombre:
queryset = queryset.filter(Nombre__icontains=Nombre)
# Aplicar ordenación si se proporciona como parámetro de consulta
ordering = self.request.query_params.get('ordering')
if ordering:
queryset = queryset.order_by(ordering)
return queryset
class ClientesA24Detail(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated, HasAuthorizationHeader]
def get_object(self, pk):
try:
return ClientesA24.objects.get(pk=pk)
except ClientesA24.DoesNotExist:
raise Http404
# Obtener un cliente por ID (GET)
def get(self, request, pk):
print(request.headers)
cliente = self.get_object(pk)
serializer = ClientesA24Serailizer(cliente)
return Response(serializer.data)
# Actualizar un cliente por ID (PUT)
def put(self, request, pk):
cliente = self.get_object(pk)
print(cliente)
serializer = ClientesA24Serailizer(cliente, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Eliminar un cliente por ID (DELETE)
def delete(self, request, pk):
cliente = self.get_object(pk)
cliente.delete()
return Response({"pk":pk},status=status.HTTP_200_OK)

View File

@@ -20,6 +20,8 @@ class DeviceHistoryAdmin(admin.ModelAdmin):
class DeviceAdmin(admin.ModelAdmin):
list_display = ['client', 'device_name', 'ip_address', 'sistema', 'macAddress','database']
list_filter = ['client', 'sistema']
search_fields = ('client__Nombre',)
admin.site.register(BitacoraErrores,BitacoraErroresAdmin)
admin.site.register(Sistema,Sistema_Admin)

View File

@@ -1,14 +1,36 @@
from rest_framework.permissions import BasePermission
class HasAuthorizationHeader(BasePermission):
def has_permission(self, request, view):
return 'Authorization' in request.headers
class ItsAdminToken(BasePermission):
def has_permission(self,request,view):
return request.user.is_superuser
class ItsAdminGroup(BasePermission):
def has_permission(self, request, view):
return request.user.groups.filter(name= 'admin_soft')
from rest_framework.permissions import BasePermission
from django.contrib.auth.models import Permission
class HasAuthorizationHeader(BasePermission):
def has_permission(self, request, view):
return 'Authorization' in request.headers
class ItsAdminToken(BasePermission):
def has_permission(self,request,view):
return request.user.is_superuser
class ItsAdminGroup(BasePermission):
def has_permission(self, request, view):
return request.user.groups.filter(name= 'admin_soft')
class CheckPermiso(BasePermission):
def has_permission(self, request, view):
user = request.user
print(user)
permiso= request.META.get('HTTP_PERMISSION')
print('permiso',permiso)
print('es staff: ',user.is_staff)
print('su: ',user.is_superuser)
print('Permisos:', user.user_permissions.filter(codename = permiso))
print(user.has_perm(permiso))
print('Grupos',user.groups.all())
if user.is_staff:
return True
if user.is_superuser:
return True
return True

View File

@@ -8,7 +8,7 @@ from django.views.generic.edit import CreateView
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import authentication_classes,api_view,permission_classes
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authtoken.models import Token
from rest_framework.views import APIView
from rest_framework.response import Response
@@ -380,7 +380,7 @@ class CheckVersionView(APIView):
class Custom_Login(APIView):
"""Autentica al device"""
authentication_classes= [TokenAuthentication]
permissions_classes=[IsAuthenticated, HasAuthorizationHeader]
permission_classes=[IsAuthenticated, HasAuthorizationHeader]
def post(self, request):
username = request.data.get('username')
@@ -389,7 +389,8 @@ class Custom_Login(APIView):
user = authenticate(request, username=username,password=password)
if user is not None:
login(request,user)
return Response({'access':True})
token, created = Token.objects.get_or_create(user=user)
return Response({'access':True, 'token':token.key})
else:
return Response({'access':False})
except Exception as ex: