Skip to content

Commit

Permalink
Merge pull request #1069 from scieloorg/beta
Browse files Browse the repository at this point in the history
Incorporação de códigos estáveis
  • Loading branch information
gustavofonseca committed Feb 23, 2015
2 parents a1c2bcd + e862052 commit 131f121
Show file tree
Hide file tree
Showing 50 changed files with 2,633 additions and 179 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ Celery
django-celery
django-kombu
defusedxml==0.4.1
django-countries
44 changes: 44 additions & 0 deletions scielomanager/accounts/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# coding: utf-8
from django import forms
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.models import get_current_site
from django.utils.http import int_to_base36
from django.template import loader
from scielomanager.tasks import send_mail


class PasswordChangeForm(forms.Form):
Expand All @@ -9,3 +15,41 @@ class PasswordChangeForm(forms.Form):
widget=forms.PasswordInput(attrs={'class': 'span3'}))
new_password_again = forms.CharField(
widget=forms.PasswordInput(attrs={'class': 'span3'}))


class PasswordResetForm(PasswordResetForm):
"""
Customization of django.contrib.auth.forms:PasswordResetForm
to send emails via celery task
"""

def save(self, domain_override=None,
subject_template_name='registration/password_reset_subject.txt',
email_template_name='registration/password_reset_email.html',
use_https=False, token_generator=default_token_generator,
from_email=None, request=None):
"""
Generates a one-use only link for resetting password and sends to the
user.
"""
for user in self.users_cache:
if not domain_override:
current_site = get_current_site(request)
site_name = current_site.name
domain = current_site.domain
else:
site_name = domain = domain_override
c = {
'email': user.email,
'domain': domain,
'site_name': site_name,
'uid': int_to_base36(user.id),
'user': user,
'token': token_generator.make_token(user),
'protocol': use_https and 'https' or 'http',
}
subject = loader.render_to_string(subject_template_name, c)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
email = loader.render_to_string(email_template_name, c)
send_mail.delay(subject, email, [user.email])
Empty file.
Empty file.
87 changes: 87 additions & 0 deletions scielomanager/accounts/management/commands/anonymize_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# coding: utf-8
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
from django.db.models import Q

def display_users(users_list):
print "-" * 80
print "| pk | username | first_name | last_name | email |"
for user in users_list:
print "| %s | %s | %s | %s | %s |" % (user.pk, user.username, user.first_name, user.last_name, user.email)
print "-" * 80
print "total: %s users" % users_list.count()
print "-" * 80


class Command(BaseCommand):
help = 'replace sensible data to be anonymized, such as first_name, last_name, email, api tokens, etc'

def handle(self, *args, **options):
print "#" * 80
print "# THIS COMMAND WILL MODIFY USER DATA, AND SHOULD AFFECT THE LOGIN CREDENTIALS! #"
print "# ----------- PLEASE BE SURE YOU HAVE A BACKUP TO AVOID DATA LOSS ------------ #"
print "#" * 80
prompt_backup = raw_input('the database has a back up? [y/N]: ')
if prompt_backup.lower() == 'y':
users = User.objects.all()
print "Found %s users!" % users.count()
prompt_show_all_users = raw_input('want to list all these users? [y/N]: ')
if prompt_show_all_users.lower() == 'y':
display_users(users)

# exclude non-scielo users
non_scielo_users = users.exclude(email__endswith="@scielo.org")
print "Found %s NON-scielo users!" % non_scielo_users.count()
prompt_show_non_scielo_users = raw_input('want to list all these users? [y/N]: ')
if prompt_show_non_scielo_users.lower() == 'y':
display_users(non_scielo_users)

# lookup to know if exists particular users to be excludes, such as: QAL1, QAL2, Produtor, etc
has_special_users = non_scielo_users.filter(
Q(first_name__iexact="Produtor") | Q(first_name__iexact="QAL1") | Q(first_name__iexact="QAL2")
).exists()

if has_special_users:
prompt_to_exclude_special_users = raw_input(
'Found at least one special user (QAL1 or QAL2 or Produtor). Do you want to ignore this users from modifications? [y/N]: '
)
if prompt_to_exclude_special_users.lower() == 'y':
non_scielo_users = non_scielo_users.exclude(
Q(first_name__iexact="Produtor") | Q(first_name__iexact="QAL1") | Q(first_name__iexact="QAL2")
)
print "Now the list of NON-scielo users to be modified has %s users" % non_scielo_users.count()
prompt_show_non_scielo_users = raw_input('want to list all these users? [y/N]: ')
if prompt_show_non_scielo_users.lower() == 'y':
display_users(non_scielo_users)

print "#" * 80
print "# NOW WILL MODIFY USER DATA! #"
print "# user.username will be set to user_<user.pk> #"
print "# user.first_name will be set to user_fn_<user.pk> #"
print "# user.last_name will be set to user_ln_<user.pk> #"
print "# user.email will be set to user_<user.pk>@example.com #"
print "# user.password will be set to 'test.scielo' [hashed] #"
print "# user.api_key will be regenerated with a random uuid using tastypie.models > ApiKey > generate_key #"
print "# ----------- BE SURE YOU HAVE A BACKUP TO AVOID DATA LOSS ------------ #"
print "#" * 80
prompt_confirm_modify = raw_input('Are you sure? the process CAN NOT BE UNDONE [y/N]: ')
if prompt_confirm_modify.lower() == 'y':
print "Updating users ... (hold on, may take a while) ..."
for user in non_scielo_users:
user.username = "user_%s" % user.pk
user.first_name = "user_fn_%s" % user.pk
user.last_name = "user_ln_%s" % user.pk
user.email = "user_%[email protected]" % user.pk
user.set_password('test.scielo')
# save new user field
user.save()
# generate a new api_key
user.api_key.key = None
user.api_key.save()
# show updated user info
display_users(non_scielo_users)
print "done!"
else:
print "Nothing to do here! NON-scielo users were NOT changed!"
else:
print "Nothing to do here! Go and make a backup."
164 changes: 142 additions & 22 deletions scielomanager/accounts/templates/accounts/my_account.html
Original file line number Diff line number Diff line change
@@ -1,28 +1,148 @@
{% extends "base_lv1.html" %}
{% load i18n %}
{% load user_avatar %}
{% block content %}
<style>
#accountTabContent { min-height: 470px; }
.avatar-rounded{ border-radius: 6px 6px 0 0; }
</style>

{% block breadcrumb %}
<ul class="breadcrumb">
<li><a href="{% url index %}">{% trans 'Home' %}</a> <span class="divider">/</span></li>
<li class="active">{% trans 'My Account' %}</li>
</ul>
<div class="row-fluid">
<div class="span9 offset2">
<div class="row-fluid">
<div class="span12">
<h4>{% trans "User information" %}:</h4>
<div class="span8 well">
<dl>
<dt>{% trans "First name" %}:</dt>
<dd>{{ user.first_name }}</dd>
<dt>{% trans "Last name" %}:</dt>
<dd>{{ user.last_name }}</dd>
<dt>{% trans "Username" %}:</dt>
<dd>{{ user.username }}</dd>
<dt>{% trans "Email" %}:</dt>
<dd>{{ user.email }}</dd>
</dl>
<br>
</div>
<div class="span3">
<img class="avatar-rounded" src="{% user_avatar_url request.user '192' %}" alt="">
<div class="alert alert-info">
<small>
<em>
Change your avatar at:
<a href="https://secure.gravatar.com">
https://secure.gravatar.com
</a>
</em>
</small>
</div>
</div>
</div>
</div>
<div class="row">
<ul class="nav nav-tabs" id="accountTab">
<li class="active">
<a data-toggle="tab" href="#profile">
<i class="icon icon-user"></i> {% trans "Profile" %}:
</a>
</li>
<li>
<a data-toggle="tab" href="#collections">
<i class="icon icon-book"></i> {% trans "My Collections" %}:
</a>
</li>
<li>
<a data-toggle="tab" href="#api_keys">
<i class="icon icon-lock"></i> {% trans "API token" %}:
</a>
</li>
</ul>
<div class="tab-content" id="accountTabContent">
<div id="profile" class="tab-pane in active">
<div class="span6">
<h4>{% trans "Change Password" %}:</h4>
<div class="well">
<form id="change_password_form" action="{% url journalmanager.password_change %}" method="POST">
{% with password_form as form %}
{% include "articletrack/includes/form_snippet.html" %}
{% endwith %}
</form>
<br>
</div>
</div>
<div class="span6">
<h4>{% trans "Notifications & Other preferences" %}:</h4>
<div class="well">
<form id="profile_form" action="." method="POST">
{% with profile_form as form %}
{% include "articletrack/includes/form_snippet.html" %}
{% endwith %}
</form>
<br>
</div>
</div>
</div>
<div id="collections" class="tab-pane">
<div class="span12">
<h4>{% trans "My collections" %}:</h4>
<div class="well">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th class="span1">#</th>
<th>{% trans "Collection" %}:</th>
<th class="span2">{% trans "Am I manager?" %}</th>
</tr>
</thead>
<tbody>
{% for collection in my_collecttions %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ collection.name }}</td>
<td>
{% if collection.is_manager %}
<i class="icon icon-ok"></i>
{% else %}
<i class="icon icon-remove"></i>
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="2">{% trans "No collections related yet!" %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div id="api_keys" class="tab-pane">
<div class="span12">
<h4>{% trans "API Token" %}:</h4>
<div class="well">
<p>{% trans "This is your token" %}: <code>{{user.api_key.key}}</code></p>
<p>
<a href="http://docs.scielo.org/projects/scielo-manager/en/latest/dev/api.html" target="_blank">
{% trans 'Read more about the API usage' %}
</a>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

{% block content %}
<div class="span8">
<ul>
<li><a href="{% url journalmanager.password_change %}">Change my password</a></li>
<li>Update my personal information</li>
</ul>
</div>
<div class="span4 alert alert-info">
<h4>API Token</h4>
<p>{{user.api_key.key}}</p>
<p>
<a href="http://docs.scielo.org/projects/scielo-manager/en/latest/dev/api.html"
target="_blank">
{% trans 'Read more about the API usage' %}
</a>
</p>
</div>
{% block extrafooter %}
{{ block.super }}
<script>
$(document).ready(function() {
$('input', '#change_password_form').removeClass('span3').addClass('span12');
$('select', '#profile_form').addClass('span12').chosen();
});
</script>
{% endblock %}
2 changes: 2 additions & 0 deletions scielomanager/accounts/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.views.generic.base import TemplateView

from . import views
from . import forms


urlpatterns = patterns('',
Expand All @@ -23,6 +24,7 @@
'template_name': 'registration/password_reset_form.html',
'email_template_name': 'registration/password_reset_email.html',
'post_reset_redirect': '/accounts/password/reset/done/',
'password_reset_form': forms.PasswordResetForm,
},
name='registration.password_reset'),

Expand Down
21 changes: 20 additions & 1 deletion scielomanager/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,32 @@
from django.utils.translation import ugettext as _
from django.contrib.auth import authenticate
from django.conf import settings
from journalmanager.forms import UserProfileForm

from . import forms


@login_required
def my_account(request):
return render_to_response('accounts/my_account.html', {},
profile_form = UserProfileForm(instance=request.user.get_profile())
password_form = forms.PasswordChangeForm()
# password_form faz post na view: password_change, então não deve ser tratado aqui
if request.method == "POST":
profile_form = UserProfileForm(request.POST, instance=request.user.get_profile())
if profile_form.is_valid():
profile_form.save()
messages.success(request, _('Saved successfully'))
else:
messages.error(request, _('There are some errors or missing data.'))

my_collecttions = [{'name': c.name, 'is_manager': c.is_managed_by_user(request.user)} for c in request.user.user_collection.all()]

context = {
'profile_form': profile_form,
'password_form': password_form,
'my_collecttions': my_collecttions,
}
return render_to_response('accounts/my_account.html', context,
context_instance=RequestContext(request))


Expand Down
Loading

0 comments on commit 131f121

Please sign in to comment.