Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions sloth/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,21 +615,27 @@ class PasswordForm(Action):
class Meta:
verbose_name = 'Alterar Senha'

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
if not self.user:
self.user = self.request.user

def clean(self):
password = self.cleaned_data.get('password')
password2 = self.cleaned_data.get('password2')
if password != password2:
raise forms.ValidationError('Senhas não conferem.')

if settings.SLOTH.get('FORCE_PASSWORD_DEFINITION') == True and settings.SLOTH.get('DEFAULT_PASSWORD'):
default_password = settings.SLOTH['DEFAULT_PASSWORD'](self.request.user)
if self.request.user.check_password(default_password) and self.request.user.check_password(password):
default_password = settings.SLOTH['DEFAULT_PASSWORD'](self.user)
if self.user.check_password(default_password) and self.user.check_password(password):
raise forms.ValidationError('Senha não pode ser a senha padrão.')

return self.cleaned_data

def submit(self):
self.request.user.set_password(self.cleaned_data.get('password'))
self.request.user.save()
auth.login(self.request, self.request.user, backend='django.contrib.auth.backends.ModelBackend')
self.user.set_password(self.cleaned_data.get('password'))
self.user.save()
auth.login(self.request, self.user, backend='django.contrib.auth.backends.ModelBackend')
self.redirect(message='Senha alterada com sucesso.')
2 changes: 1 addition & 1 deletion sloth/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get_general_info(self):
return self.values(('first_name', 'last_name'), 'username', 'email').verbose_name('Dados Gerais')

def get_access_info(self):
return self.values('is_superuser',).verbose_name('Dados de Acesso')
return self.values(('is_superuser', 'is_active')).verbose_name('Dados de Acesso')

@meta('Papéis')
def get_roles(self):
Expand Down
20 changes: 20 additions & 0 deletions sloth/api/tokes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import six
from django.contrib.auth.tokens import PasswordResetTokenGenerator


class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.is_active)
)


class PasswordResetToken(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp)
)


account_activation_token = AccountActivationTokenGenerator()
password_reset_token = PasswordResetToken()
3 changes: 2 additions & 1 deletion sloth/app/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from django.urls import path, re_path
from . import views

from . import views

urlpatterns = [
path('', views.index),
Expand All @@ -15,6 +15,7 @@
path('app/logout/', views.logout),
path('app/password/', views.password),
path('app/action/<str:name>/', views.action),
path('app/account_activate/<str:uid64>/<str:token>/', views.account_activate),
path('app/<str:app_label>/<str:model_name>/', views.dispatcher),
path('app/<str:app_label>/<str:model_name>/<str:x>/', views.dispatcher),
path('app/<str:app_label>/<str:model_name>/<str:x>/<str:y>/<str:z>/<str:w>/<str:k>/', views.dispatcher),
Expand Down
23 changes: 22 additions & 1 deletion sloth/app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
from django.conf import settings
from django.contrib import auth, messages
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail
from django.http import JsonResponse, HttpResponseForbidden, HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from django.template.loader import render_to_string
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_decode
from sloth.api.tokes import account_activation_token

from .templatetags.tags import is_ajax
from ..core import views
Expand Down Expand Up @@ -176,6 +180,23 @@ def logout(request):
return HttpResponseRedirect('/')


def account_activate(request, uid64, token):
uid = force_str(urlsafe_base64_decode(uid64))
user = get_object_or_404(User, pk=uid)
if user is not None and account_activation_token.check_token(user, token):
form = PasswordForm(request=request, user=user)
if form.is_valid():
form.submit()
user.is_active = True
user.save()
auth.login(request, user)
return HttpResponseRedirect('/app/')
return render(request, ['app/default.html'], context(request, form=form))

messages.warning(request, "Link de ativação inválido")
return HttpResponseRedirect('/')


def index(request):
return HttpResponseRedirect('/app/')

Expand Down
4 changes: 3 additions & 1 deletion sloth/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
'ROLES':{
'ALLOW_MULTIPLE': True
},
'OAUTH_LOGIN': {
'OAUTH_LOGIN': {
'APP': {
'TEXT': 'Acessar com APP',
'LOGO': None,
Expand All @@ -60,6 +60,8 @@
'LIST_PER_PAGE': 20,
'DEFAULT_PASSWORD': lambda user=None: '123',
'FORCE_PASSWORD_DEFINITION': False,
'ADD_USER_CONFIRMATION': False,
'LIST_PER_PAGE': 20,
'ICONS': ['fontawesome', 'materialicons']
}

Expand Down
36 changes: 33 additions & 3 deletions sloth/core/base.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from functools import lru_cache
import types
from functools import lru_cache

from django.apps import apps
from django.conf import settings
from django.core.exceptions import FieldDoesNotExist
from django.core.mail import send_mail
from django.db import transaction
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode

from sloth.actions import Action, ACTIONS
from sloth.core.valueset import ValueSet
from sloth.api.tokes import account_activation_token
from sloth.core.queryset import QuerySet
from sloth.utils import to_snake_case, to_camel_case, getattrr
from sloth.core.valueset import ValueSet
from sloth.utils import to_snake_case, getattrr

FILTER_FIELD_TYPES = 'BooleanField', 'NullBooleanField', 'ForeignKey', 'ForeignKeyPlus', 'DateField', 'DateFieldPlus'
SEARCH_FIELD_TYPES = 'CharField', 'CharFieldPlus', 'TextField'
Expand Down Expand Up @@ -145,6 +151,7 @@ def get_role_tuples(self, ignore_active_condition=False):
# print('\n\n')
return tuples

@transaction.atomic()
def sync_roles(self, role_tuples):
from django.contrib.auth.models import User
user_id = None
Expand All @@ -162,8 +169,31 @@ def sync_roles(self, role_tuples):
default_password = settings.SLOTH['DEFAULT_PASSWORD'](user)
else:
default_password = '123' if settings.DEBUG else str(abs(hash(username)))
if settings.SLOTH.get('ADD_USER_CONFIRMATION') == True:
user.is_active = False
user.set_password(default_password)
user.save()

site = settings.CSRF_TRUSTED_ORIGINS[0]
uid = urlsafe_base64_encode(force_bytes(user.pk))
token = account_activation_token.make_token(user)
send_mail(
subject="Cadastro no RAIZ",
message=None,
html_message=f"""
<h3>
Olá {user},
</h3>
Para ativar o seu cadastro e definir sua senha clique no link abaixo:
<br /><br />
<a href="{site}/app/account_activate/{uid}/{token}">Definir senha</a>
<br><br>
Se o link acima não funcionar, por favor, copie e cole a URL no seu navegador.
""",
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=(email,),
)

user_id = user.id
role.objects.get_or_create(
user_id=user_id, name=scope_name,
Expand Down