Verified Commit 0fff6da3 authored by Mattia Rizzolo's avatar Mattia Rizzolo
Browse files

Merge branch 'fix/unique-fingerprint' of salsa.debian.org:lyknode/debexpo into live

MR: mentors.debian.net-team/debexpo!177


Signed-off-by: Mattia Rizzolo's avatarMattia Rizzolo <mattia@debian.org>
parents 2c55a35c a5d7f42f
Pipeline #220572 passed with stage
in 18 minutes and 42 seconds
Copyright 2008-2020 Debexpo's contributors (see AUTHORS)
Copyright 2008-2021 Debexpo's contributors (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -147,6 +147,10 @@ class ProfileForm(forms.ModelForm):
class GPGForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
def _validate_gpg_key(self, key):
if not key:
return
......@@ -156,11 +160,22 @@ class GPGForm(forms.ModelForm):
except (ExceptionGnuPG, ValueError) as e:
self.add_error('key', e)
def _validate_uniqueness(self):
try:
Key.objects.exclude(user=self.user) \
.get(fingerprint=self.key.fingerprint)
except Key.DoesNotExist:
pass
else:
self.add_error('key', 'GPG Key already in use by another account')
def clean(self):
self.cleaned_data = super().clean()
key = self.cleaned_data.get('key')
self._validate_gpg_key(key)
if hasattr(self, 'key'):
self._validate_uniqueness()
return self.cleaned_data
......
......@@ -163,10 +163,10 @@ def profile(request):
profile_form = ProfileForm(request.user, instance=request.user.profile)
gpg_fingerprint = None
try:
gpg_form = GPGForm(instance=request.user.key)
gpg_form = GPGForm(request.user, instance=request.user.key)
gpg_fingerprint = _format_fingerprint(request.user.key.fingerprint)
except Key.DoesNotExist:
gpg_form = GPGForm()
gpg_form = GPGForm(request.user)
if request.method == 'POST':
if 'commit_account' in request.POST:
......@@ -198,9 +198,10 @@ def profile(request):
if 'commit_gpg' in request.POST:
try:
gpg_form = GPGForm(request.POST, instance=request.user.key)
gpg_form = GPGForm(request.user, request.POST,
instance=request.user.key)
except Key.DoesNotExist:
gpg_form = GPGForm(request.POST)
gpg_form = GPGForm(request.user, request.POST)
if gpg_form.is_valid():
_update_key(request, gpg_form)
......@@ -215,7 +216,7 @@ def profile(request):
pass
else:
key.delete()
gpg_form = GPGForm()
gpg_form = GPGForm(request.user)
gpg_fingerprint = None
return render(request, 'profile.html', {
......
# 0003_fingerprint_uniqueness.py - Migration script for fingerprint uniqueness
#
# This file is part of debexpo
# https://salsa.debian.org/mentors.debian.net-team/debexpo
#
# Copyright © 2021 Baptiste Beauplat <lyknode@cilg.org>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('keyring', '0002_subkey'),
]
operations = [
migrations.AlterField(
model_name='key',
name='fingerprint',
field=models.TextField(max_length=40, unique=True,
verbose_name='Fingerprint'),
),
migrations.AlterField(
model_name='subkey',
name='fingerprint',
field=models.TextField(max_length=40, unique=True,
verbose_name='Fingerprint'),
),
]
......@@ -109,7 +109,8 @@ class Key(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
key = models.TextField(verbose_name=_('OpenGPG key'))
fingerprint = models.TextField(max_length=40, verbose_name=_('Fingerprint'))
fingerprint = models.TextField(max_length=40, verbose_name=_('Fingerprint'),
unique=True)
last_updated = models.DateTimeField(verbose_name=_('Last update on'),
auto_now=True)
......@@ -139,4 +140,5 @@ class Key(models.Model):
class SubKey(models.Model):
key = models.ForeignKey(Key, on_delete=models.CASCADE)
fingerprint = models.TextField(max_length=40, verbose_name=_('Fingerprint'))
fingerprint = models.TextField(max_length=40, verbose_name=_('Fingerprint'),
unique=True)
......@@ -3,7 +3,7 @@
# This file is part of debexpo
# https://salsa.debian.org/mentors.debian.net-team/debexpo
#
# Copyright © 2020 Baptiste Beauplat <lyknode@cilg.org>
# Copyright © 2021 Baptiste Beauplat <lyknode@cilg.org>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
......
......@@ -109,7 +109,7 @@ Xcgnuh6Rlywt6uiaFIGYnGefYPGXRAA=
key.save()
key.update_subkeys()
def _setup_example_user(self, gpg=False):
def _setup_example_user(self, gpg=False, email='email@example.com'):
"""Add an example user.
The example user with name ``Test user``, email address
......@@ -120,8 +120,7 @@ Xcgnuh6Rlywt6uiaFIGYnGefYPGXRAA=
classes.
"""
# Create a test user and save it.
user = User.objects.create_user('email@example.com',
'Test user', 'password')
user = User.objects.create_user(email, 'Test user', 'password')
user.save()
profile = Profile(user=user, status=UserStatus.contributor.value)
profile.save()
......
......@@ -269,6 +269,16 @@ Xcgnuh6Rlywt6uiaFIGYnGefYPGXRAA=
self.assertEquals(user.key.key, self._GPGKEY)
# Again?
response = self.client.post(reverse('profile'), {
'key': self._GPGKEY,
'commit_gpg': 'submit'
})
self.assertEquals(response.status_code, 200)
self.assertNotIn('errorlist', str(response.content))
self.assertEquals(user.key.key, self._GPGKEY)
# Update it
response = self.client.post(reverse('profile'), {
'key': self._GPGKEY_2,
......@@ -345,6 +355,20 @@ Xcgnuh6Rlywt6uiaFIGYnGefYPGXRAA=
self._assert_gpg_post_failed(response, message)
def test_gpg_already_in_use(self):
self._setup_example_user(True, 'another@example.org')
response = self.client.post(reverse('login'), self._AUTHDATA)
# Post GPG key
response = self.client.post(reverse('profile'), {
'key': self._GPGKEY,
'commit_gpg': 'submit'
})
self._assert_gpg_post_failed(response, 'GPG Key already in use by '
'another account')
# def test__gpg_wrong_email(self):
# response = self.client.post(reverse('profile'), {'form': 'gpg'})
# self.assertEquals(response.status_code, 302)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment