diff --git a/Dockerfile b/Dockerfile index bd00393359f35522da1d57ffd1620c54c94a3f8f..1ac29c7c8ba10c2e0c41486d5bda00b91de789c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.5 +FROM python:3.5.2 RUN apt-get update && apt-get install -y --no-install-recommends apt-utils RUN apt-get update && apt-get -y upgrade && apt-get install -y apt-transport-https software-properties-common libsasl2-dev python-dev libldap2-dev libssl-dev unixodbc unixodbc-dev freetds-dev freetds-bin tdsodbc memcached RUN apt-get install -y gettext diff --git a/Poppins/settings.py b/Poppins/settings.py index 1185eda56c64f4216a3395149178f13716d1a341..d47063c89457317bfab1f91c2d654bbeff302e12 100644 --- a/Poppins/settings.py +++ b/Poppins/settings.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ Copyright 2019 de la Dirección General de Sistemas Informáticos – SecretarÃa Legal y Técnica - Nación. @@ -7,6 +8,8 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ """ +import sys + """ Django settings for Poppins project. @@ -148,7 +151,7 @@ STATIC_URL = '/static/' ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window -ACCOUNT_DEFAULT_LIMIT = 100000 # in wei +ACCOUNT_DEFAULT_LIMIT = 2000000000 # in wei LOGIN_REDIRECT_URL = '/accounts/list/' LOGOUT_REDIRECT_URL = '/accounts/login/' @@ -182,16 +185,22 @@ LOGGING = { } }, 'handlers': { + 'stdout': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'stream': sys.stdout, + 'formatter': 'history' + }, 'info_file': { 'level': 'INFO', 'class': 'logging.FileHandler', - 'filename': LOG_ROOT + 'server.info.log', + 'filename': LOG_ROOT + 'info.log', 'formatter': 'history', }, 'error_file': { 'level': 'ERROR', 'class': 'logging.FileHandler', - 'filename': LOG_ROOT + 'server.error.log', + 'filename': LOG_ROOT + 'error.log', 'formatter': 'detailed', }, 'sentry': { @@ -215,5 +224,10 @@ LOGGING = { 'level': 'DEBUG', 'propagate': True, }, + 'cmd-logger': { + 'handlers': ['stdout', 'info_file', 'error_file', 'sentry'], + 'level': 'DEBUG', + 'propagate': True + } }, } diff --git a/frontend/views.py b/frontend/views.py index 0e070249e27042e1b32a8ff50dff369808afb6cb..e94108cc1a91714e573e247809394b0a4e9e12f6 100644 --- a/frontend/views.py +++ b/frontend/views.py @@ -36,15 +36,14 @@ from Poppins import settings from api.models import CustomUser, Institution, Service, Section from api.managers import RegistrationManager, ServiceManager from dapp.models import Account -from dapp.services import AsociacionCuenta, PetitorioEtherCuenta, NotValidAddressException +from dapp.services import AsociacionCuenta, PetitorioEtherCuenta, NotValidAddressException, DesvinculacionCuenta from logica_cuentas.models import RelacionUsuarioAccount as CustomUserAccount, RelacionUsuarioAccountStatus -from logica_cuentas.services import AltaCuentaEthereum +from logica_cuentas.services import AltaCuentaEthereum, CreacionRelacionCuentaUsuario logger = logging.getLogger('logger') class RegistrationView(RegistrationView): - email_body_template = 'django_registration/activation_email_body.html' def post(self, request, *args, **kwargs): @@ -86,7 +85,7 @@ class RegistrationView(RegistrationView): user = super().register(form) CustomUser.objects.create( - user_id=user.id, + user_id=user.id ) RegistrationManager.send_email_to_admin(form) @@ -139,7 +138,10 @@ class AccountListView(LoginRequiredMixin, ListView): context = super().get_context_data(**kwargs) context['institutions'] = CustomUser.objects.get(user_id=self.request.user.id).enabled_institutions.all() - context['services'] = Service.objects.filter(id__in=list(Account.objects.filter(institution_id__in=list(CustomUser.objects.get(user_id=self.request.user.id).enabled_institutions.values_list('id', flat=True))).values_list('service_id', flat=True))) + context['services'] = Service.objects.filter(id__in=list(Account.objects.filter(institution_id__in=list( + CustomUser.objects.get(user_id=self.request.user.id).enabled_institutions.values_list('id', + flat=True))).values_list( + 'service_id', flat=True))) context['distillery_address'] = settings.DISTILLERY_ADDRESS return context @@ -167,22 +169,30 @@ class AccountCreateView(LoginRequiredMixin, CreateView): service = ServiceManager.create_service(request.POST['service_name']) account, clave = self.alta_cuenta.alta_cuenta_ethereum(request.POST['address'], - Institution.objects.filter(id=request.POST['institution']).first(), + Institution.objects.filter( + id=request.POST['institution']).first(), service, custom_user, settings.ACCOUNT_DEFAULT_LIMIT ) - messages.success(request, (_('account_added') % (request.POST['address']) + ' <input type="hidden" id="hidden-clave" value="'+clave+'" /> <input type="hidden" id="hidden-address" value="'+request.POST['address']+'" /> <input type="hidden" id="hidden-contract-address" value="'+settings.DISTILLERY_ADDRESS+'" />')) + messages.success(request, (_('account_added') % (request.POST[ + 'address']) + ' <input type="hidden" id="hidden-clave" value="' + clave + '" /> <input type="hidden" id="hidden-address" value="' + + request.POST[ + 'address'] + '" /> <input type="hidden" id="hidden-contract-address" value="' + settings.DISTILLERY_ADDRESS + '" />')) else: messages.error(request, _('existing_account') % request.POST['address'], extra_tags='danger') except NotValidAddressException: messages.error(request, _('address_not_valid') % request.POST['address'], extra_tags='danger') except IntegrityError as e: if 'service_name_key' in str(e): - messages.error(request, _('error_create_view') + ': ' + _('existing_service') % request.POST['service_name'], extra_tags='danger') + messages.error(request, + _('error_create_view') + ': ' + _('existing_service') % request.POST['service_name'], + extra_tags='danger') else: messages.error(request, _('error_create_view'), extra_tags='danger') + client.captureException() + logger.error(str(e)) except Exception as e: client.captureException() messages.error(request, _('error_create_view'), extra_tags='danger') @@ -192,25 +202,23 @@ class AccountCreateView(LoginRequiredMixin, CreateView): class CustomUserAccountCreateView(LoginRequiredMixin, CreateView): - model = CustomUserAccount success_url = '/accounts/list/' - + creacion_vinculo = CreacionRelacionCuentaUsuario() + manager = CustomUserAccount.objects def post(self, request, *args, **kwargs): try: with transaction.atomic(): - sin_verificar = RelacionUsuarioAccountStatus.objects.get_sin_verificar_relacion() - account = Account.objects.filter(service__id=request.POST['service']).first() custom_user = CustomUser.objects.filter(user_id=request.user.id).first() - custom_user_account = CustomUserAccount.objects.create(user=custom_user, account=account, status=sin_verificar) + custom_user_account = self.creacion_vinculo.vincular(custom_user, account) - account_users = User.objects.filter(id__in=list(CustomUserAccount.objects.filter(account=account.id).values_list('user_id', flat=True))) + owner = self.manager.owner(account) scheme = 'https' if self.request.is_secure() else 'http' site = get_current_site(self.request) @@ -227,7 +235,7 @@ class CustomUserAccountCreateView(LoginRequiredMixin, CreateView): render_to_string('django_registration/approve_account_subject.txt'), render_to_string('django_registration/approve_account_body.html', body_context), settings.DEFAULT_FROM_EMAIL, - list(account_users.values_list('email', flat=True)), + [owner.email], fail_silently=False, html_message=render_to_string('django_registration/approve_account_body.html', body_context) ) @@ -238,6 +246,8 @@ class CustomUserAccountCreateView(LoginRequiredMixin, CreateView): messages.error(request, _('user_already_has_account') % (account.address), extra_tags='danger') else: messages.error(request, _('error_create_view'), extra_tags='danger') + client.captureException() + logger.error(str(e)) except Exception as e: client.captureException() messages.error(request, _('error_create_view'), extra_tags='danger') @@ -249,16 +259,16 @@ class CustomUserAccountCreateView(LoginRequiredMixin, CreateView): class AccountDeleteView(LoginRequiredMixin, DeleteView): model = CustomUserAccount success_url = '/accounts/list/' + desvinculacion_account = DesvinculacionCuenta() def post(self, request, *args, **kwargs): try: - + # TODO: pasar todo esto a clase en services with transaction.atomic(): customuser_account = self.get_object() - custom_user = CustomUser.objects.get(user_id=request.user.id) - if customuser_account.account.owner == custom_user: + if customuser_account.is_owner: accounts = CustomUserAccount.objects.filter(account_id=customuser_account.account_id) @@ -279,9 +289,7 @@ class AccountDeleteView(LoginRequiredMixin, DeleteView): account_address = customuser_account.account.address customuser_account.delete() - account.delete() - service = Service.objects.get(pk=account.service_id) - service.delete() + self.desvinculacion_account.desvincular_cuenta(account) messages.success(request, _('cuenta_borrada') % account_address) @@ -293,7 +301,6 @@ class AccountDeleteView(LoginRequiredMixin, DeleteView): messages.error(request, _('error_borrar_cuenta'), extra_tags='danger') logger.error(str(e)) - return HttpResponseRedirect(self.success_url) @@ -347,31 +354,31 @@ class CaptchaLoginView(LoginView): else: return self.form_invalid(form) + @csrf_exempt def get_service_address(request): - if not request.POST['service']: return JsonResponse({'status': 'success', 'address': ''}) account = Account.objects.filter(service=Service.objects.get(pk=request.POST['service'])) - return JsonResponse({'status':'success', 'address': account.values().first()['address']}) + return JsonResponse({'status': 'success', 'address': account.values().first()['address']}) -def approve_account(request, pk): +def approve_account(request, pk): custom_user_account = CustomUserAccount.objects.filter(id=pk).first() custom_user_account.status = RelacionUsuarioAccountStatus.objects.get_relacion_verificada() custom_user_account.save() return HttpResponseRedirect('/accounts/approved/') + def account_approved(request): return render(request, 'django_registration/account_approved.html') @login_required(login_url='/accounts/login/') def update_user(request): - custom_user = CustomUser.objects.get(user_id=request.user.id) user = request.user @@ -401,14 +408,16 @@ def update_user(request): custom_user.save() messages.success(request, _('user_updated')) - except Exception: + except Exception as e: messages.error(request, _('user_update_error'), extra_tags='danger') + client.captureException() + logger.error(str(e)) return HttpResponseRedirect('/mis_datos/') + @login_required(login_url='/accounts/login/') def change_password(request): - if request.method == 'GET': return render(request, 'registration/change_password.html', {}) else: @@ -418,4 +427,4 @@ def change_password(request): messages.success(request, _('password_changed')) - return HttpResponseRedirect('/mis_datos/') \ No newline at end of file + return HttpResponseRedirect('/mis_datos/')