Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[fix bug 753398] service tab with API key generator

  • Loading branch information...
commit 031c3d07df2939272bd667d82ae2ec0cc8be8480 1 parent c604621
Tim Watts readevalprint authored
66 apps/phonebook/templates/phonebook/edit_profile.html
View
@@ -1,15 +1,23 @@
{% extends "base.html" %}
+{% block site_js %}
+ {{ super() }}
+ {{ js('edit_profile') }}
+{% endblock %}
+
+{% block site_css %}
+ {{ super() }}
+ {{ css('edit_profile') }}
+{% endblock %}
+
{% block page_title %}{{ _('Edit Your Profile') }}{% endblock %}
{% block body_id %}edit-profile{% endblock %}
{% block body_classes %}box-content{% endblock %}
-{% block page_js %}
- {{ js('edit_profile') }}
-{% endblock %}
{% block main_content %}
- <form action="{{ edit_form_action }}"
- method="POST" enctype="multipart/form-data"
+ <form action="{{ url('profile.edit') }}"
+ method="POST"
+ enctype="multipart/form-data"
class="form-horizontal edit-profile">
{{ csrf() }}
<h1>{{ _('Edit Your Profile') }}</h1>
@@ -19,6 +27,7 @@
<li><a href="#skills" data-toggle="tab">{{ _('Skills & Groups') }}</a></li>
<li><a href="#vouches" data-toggle="tab">{{ _('Vouches & Invites') }}</a></li>
<li><a href="#account" data-toggle="tab">{{ _('Account') }}</a></li>
+ <li><a href="#services" data-toggle="tab">{{ _('Services') }}</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="1">
@@ -42,22 +51,22 @@
</div>
<div class="tab-pane" id="skills">
<h2>{{ _('Groups') }}</h2>
- <p class="field_description">
- {% trans %}
- Groups are a community of Mozillians with some relation to each
- other. This can be an interest, team, project, product or
- sub-community.
- {% endtrans %}
- </p>
+ <p class="field_description">
+ {% trans %}
+ Groups are a community of Mozillians with some relation to each
+ other. This can be an interest, team, project, product or
+ sub-community.
+ {% endtrans %}
+ </p>
{{ form.groups.label_tag() }}
{{ form.groups }}
<h2>{{ _('Skills') }}</h2>
- <p class="field_description">
- {% trans %}
- A skill is the learned capacity to carry out pre-determined
- results often with the minimum outlay of time, energy, or both.
- {% endtrans %}
- </p>
+ <p class="field_description">
+ {% trans %}
+ A skill is the learned capacity to carry out pre-determined
+ results often with the minimum outlay of time, energy, or both.
+ {% endtrans %}
+ </p>
{{ form.skills.label_tag() }}
{{ form.skills }}
</div>
@@ -135,6 +144,27 @@
</div>
</div>
</div>
+ <div class="tab-pane" id="services">
+ <div class="control-group">
+ <h2>{{ _("API") }}</h2>
+ <p class="field_description">
+ {% trans %}
+ The Mozillians' Phonebook offers an API to Vouched Mozillians to help share profile data to other tools and sites
+ {% endtrans %}
+ </p>
+ <label class="control-label">{{ _("Api Key") }}</label>
+ <div class="controls">
+ <span class="label-text">
+ <div class="input-append">
+ <input id="api-key" type="text" class="span4" autocomplete="off" data-value="{{ profile.get_api_key() }}" value="{{ profile.get_api_key() }}">
+ <button type="submit" name="reset_api_key" class="btn btn-mini btn-danger">
+ {{ _("Generate new API Key") }}
+ </button>
+ </div>
+ </span>
+ </div>
+ </div>
+ </div>
</div>
</div>
<div id="edit_controls">
26 apps/phonebook/tests/test_views.py
View
@@ -276,6 +276,32 @@ def test_replace_photo(self):
new_photo = doc('#profile-photo').attr('src')
assert new_photo != old_photo
+ def test_api_key(self):
+ """Assert that the Api key will be created and displayed"""
+ client = self.mozillian_client
+ r = client.get(reverse('profile.edit'), follow=True)
+
+ doc = pq(r.content)
+ api_key = doc('#api-key').attr('value')
+
+ p = self.mozillian.get_profile()
+ assert p.get_api_key() == api_key
+
+ def test_reset_api_key(self):
+ """Assert that resetingthe aPI key changes it."""
+ client = self.mozillian_client
+ r = client.get(reverse('profile.edit'), follow=True)
+
+ doc = pq(r.content)
+ original_api_key = doc('#api-key').attr('value')
+
+ data = {'reset_api_key': True}
+ r = client.post(reverse('profile.edit'), data, follow=True)
+
+ doc = pq(r.content)
+ new_api_key = doc('#api-key').attr('value')
+ assert original_api_key != new_api_key
+
class TestVouch(TestCase):
"""
46 apps/phonebook/views.py
View
@@ -13,6 +13,8 @@
import commonware.log
from funfactory.urlresolvers import reverse
from product_details import product_details
+from funfactory.helpers import urlparams
+from tastypie.models import ApiKey
from tower import ugettext as _
from groups.helpers import stringify_groups
@@ -72,6 +74,15 @@ def edit_profile(request):
instance=profile,
)
form.fields['region'].choices = COUNTRIES
+
+ if 'reset_api_key' in request.POST:
+ # The rest of the form is irrelevant.
+ try:
+ request.user.api_key.delete()
+ except ApiKey.DoesNotExist:
+ pass
+ return redirect(urlparams(reverse('profile.edit'), 'services'))
+
if form.is_valid():
old_username = request.user.username
form.save(request)
@@ -84,24 +95,24 @@ def edit_profile(request):
'changed.'))
return redirect(reverse('profile', args=[request.user.username]))
- else:
- initial = dict(first_name=request.user.first_name,
- last_name=request.user.last_name,
- bio=profile.bio,
- website=profile.website,
- irc_nickname=profile.ircname,
- groups=user_groups,
- skills=user_skills)
+ else:
James Socol
jsocol added a note

Isn't this else: the counterpart to if form.is_valid(): and not if request.method == 'POST'? Seems like the indent level is a little too far here.

Yup, fixed it, but am having problems with the product and cannot runt the tests locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ initial = dict(first_name=request.user.first_name,
+ last_name=request.user.last_name,
+ bio=profile.bio,
+ website=profile.website,
+ irc_nickname=profile.ircname,
+ groups=user_groups,
+ skills=user_skills)
+
+ form = forms.ProfileForm(
+ instance=profile,
+ initial=initial,
+ )
+ form.fields['country'].choices = COUNTRIES
if not request.user.username.startswith('u/'):
initial.update(username=request.user.username)
- form = forms.ProfileForm(
- instance=profile,
- initial=initial,
- )
- form.fields['country'].choices = COUNTRIES
-
# When changing this keep in mind that the same view is used for
# user.register.
d = dict(form=form,
@@ -152,7 +163,9 @@ def search(request):
# If nothing has been entered don't load any searches.
if not (not query and vouched is None and profilepic is None):
- profiles = UserProfile.search(query, vouched=vouched, photo=profilepic)
+ profiles = UserProfile.search(query,
+ vouched=vouched,
+ photo=profilepic)
paginator = Paginator(profiles, limit)
@@ -164,7 +177,8 @@ def search(request):
people = paginator.page(paginator.num_pages)
if len(profiles) == 1:
- return redirect(reverse('profile', args=[people[0].user.username]))
+ return redirect(reverse('profile',
+ args=[people[0].user.username]))
if paginator.count > forms.PAGINATION_LIMIT:
show_pagination = True
5 apps/users/models.py
View
@@ -14,6 +14,7 @@
from PIL import Image, ImageOps
from product_details import product_details
from sorl.thumbnail import ImageField
+from tastypie.models import ApiKey
from tower import ugettext as _, ugettext_lazy as _lazy
from groups.models import Group, Skill
@@ -156,6 +157,10 @@ def vouch(self, vouched_by, system=True, commit=True):
# Email the user and tell them they were vouched.
self._email_now_vouched()
+ def get_api_key(self):
+ api_key, created = ApiKey.objects.get_or_create(user=self.user)
+ return api_key.key
+
def _email_now_vouched(self):
"""Email this user, letting them know they are now vouched."""
subject = _(u'You are now vouched on Mozillians!')
15 apps/users/tests.py
View
@@ -338,7 +338,7 @@ class TestUser(TestCase):
"""Test User functionality"""
def test_userprofile(self):
- u = User.objects.create(username='tmp', email='tmp@domain.com')
+ u = user()
UserProfile.objects.all().delete()
@@ -354,6 +354,19 @@ def test_userprofile(self):
# Good to go
assert u.get_profile()
+ def test_apikey(self):
+ """Test that get_api_key() will create a key if missing."""
+ # A new user will not have a key created.
+ u = user()
+ p = u.get_profile()
+ from tastypie.models import ApiKey
+
+ # A new key is not generated automatically on a user.
+ self.assertRaises(ApiKey.DoesNotExist, lambda: u.api_key)
+
+ # get_api_key will always return a key, creating one if needed.
+ eq_(p.get_api_key(), u.api_key.key)
+
class TestMigrateRegistration(TestCase):
"""Test funky behavior of flee ldap"""
4 media/css/user.css
View
@@ -0,0 +1,4 @@
+.control-group h2 {
+ border-bottom: 1px solid black;
+ margin-bottom: 10px;
+}
4 settings/default.py
View
@@ -69,6 +69,9 @@
'test': (
'css/qunit.css',
),
+ 'edit_profile': (
+ 'css/user.css',
+ ),
},
'js': {
'common': (
@@ -149,6 +152,7 @@
'cronjobs',
'elasticutils',
'sorl.thumbnail',
+ 'tastypie',
'django.contrib.admin',
'django.contrib.auth',
James Socol

Isn't this else: the counterpart to if form.is_valid(): and not if request.method == 'POST'? Seems like the indent level is a little too far here.

Tim Watts

Yup, fixed it, but am having problems with the product and cannot runt the tests locally

Please sign in to comment.
Something went wrong with that request. Please try again.