Browse Source

Apply black

pull/583/head
Guillaume Vincent 3 years ago
parent
commit
ecddb4f29e
15 changed files with 258 additions and 140 deletions
  1. +22
    -20
      containers/backend/api/admin.py
  2. +1
    -1
      containers/backend/api/apps.py
  3. +79
    -34
      containers/backend/api/migrations/0001_initial.py
  4. +36
    -15
      containers/backend/api/migrations/0002_password.py
  5. +17
    -8
      containers/backend/api/migrations/0003_mv_entries_to_password.py
  6. +7
    -7
      containers/backend/api/migrations/0004_remove_entries_password_info_models.py
  7. +3
    -3
      containers/backend/api/migrations/0005_password_version.py
  8. +5
    -5
      containers/backend/api/migrations/0006_change_default_password_profile.py
  9. +3
    -3
      containers/backend/api/migrations/0007_lesspassuser_key.py
  10. +29
    -8
      containers/backend/api/migrations/0008_encryptedpasswordprofiles.py
  11. +3
    -1
      containers/backend/api/serializers.py
  12. +8
    -5
      containers/backend/api/tests/test_auth.py
  13. +22
    -20
      containers/backend/api/tests/tests_passwords.py
  14. +21
    -8
      containers/backend/lesspass/settings.py
  15. +2
    -2
      containers/backend/lesspass/urls.py

+ 22
- 20
containers/backend/api/admin.py View File

@@ -10,12 +10,14 @@ from django.db.models import Count


class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
password2 = forms.CharField(
label="Password confirmation", widget=forms.PasswordInput
)

class Meta:
model = LessPassUser
fields = ('email',)
fields = ("email",)

def clean_password2(self):
password1 = self.cleaned_data.get("password1")
@@ -37,7 +39,7 @@ class UserChangeForm(forms.ModelForm):

class Meta:
model = LessPassUser
fields = ('email', 'password', 'is_active', 'is_admin')
fields = ("email", "password", "is_active", "is_admin")

def clean_password(self):
return self.initial["password"]
@@ -47,36 +49,36 @@ class LessPassUserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm

list_display = ('email', 'is_admin', 'column_passwords_count')
list_filter = ('is_admin', 'is_active')
list_display = ("email", "is_admin", "column_passwords_count")
list_filter = ("is_admin", "is_active")
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_admin',)}),
(None, {"fields": ("email", "password")}),
("Permissions", {"fields": ("is_admin",)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')}
),
(None, {"classes": ("wide",), "fields": ("email", "password1", "password2")}),
)
search_fields = ('email',)
ordering = ('email',)
search_fields = ("email",)
ordering = ("email",)
filter_horizontal = ()

def get_queryset(self, request):
return models.LessPassUser.objects.annotate(passwords_count=Count('passwords'))
return models.LessPassUser.objects.annotate(passwords_count=Count("passwords"))

def column_passwords_count(self, instance):
return instance.passwords_count

column_passwords_count.short_description = 'Password count'
column_passwords_count.admin_order_field = 'passwords_count'
column_passwords_count.short_description = "Password count"
column_passwords_count.admin_order_field = "passwords_count"


class PasswordAdmin(admin.ModelAdmin):
list_display = ('id', 'user',)
search_fields = ('user__email',)
ordering = ('user',)
list_display = (
"id",
"user",
)
search_fields = ("user__email",)
ordering = ("user",)


admin.site.register(models.Password, PasswordAdmin)


+ 1
- 1
containers/backend/api/apps.py View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig


class ApiConfig(AppConfig):
name = 'api'
name = "api"

+ 79
- 34
containers/backend/api/migrations/0001_initial.py View File

@@ -12,62 +12,107 @@ class Migration(migrations.Migration):

initial = True

dependencies = [
]
dependencies = []

operations = [
migrations.CreateModel(
name='LessPassUser',
name="LessPassUser",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('email', models.EmailField(max_length=255, unique=True, verbose_name='email address')),
('is_active', models.BooleanField(default=True)),
('is_admin', models.BooleanField(default=False)),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"email",
models.EmailField(
max_length=255, unique=True, verbose_name="email address"
),
),
("is_active", models.BooleanField(default=True)),
("is_admin", models.BooleanField(default=False)),
],
options={
'verbose_name_plural': 'Users',
"verbose_name_plural": "Users",
},
),
migrations.CreateModel(
name='Entry',
name="Entry",
fields=[
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('login', models.CharField(default='', max_length=255)),
('site', models.CharField(default='', max_length=255)),
('title', models.CharField(blank=True, max_length=255, null=True)),
('username', models.CharField(blank=True, max_length=255, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('description', models.TextField(blank=True, null=True)),
('url', models.URLField(blank=True, null=True)),
(
"created",
models.DateTimeField(auto_now_add=True, verbose_name="created"),
),
(
"modified",
models.DateTimeField(auto_now=True, verbose_name="modified"),
),
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("login", models.CharField(default="", max_length=255)),
("site", models.CharField(default="", max_length=255)),
("title", models.CharField(blank=True, max_length=255, null=True)),
("username", models.CharField(blank=True, max_length=255, null=True)),
("email", models.EmailField(blank=True, max_length=254, null=True)),
("description", models.TextField(blank=True, null=True)),
("url", models.URLField(blank=True, null=True)),
],
options={
'verbose_name_plural': 'Entries',
"verbose_name_plural": "Entries",
},
),
migrations.CreateModel(
name='PasswordInfo',
name="PasswordInfo",
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('counter', models.IntegerField(default=1)),
('settings', models.TextField()),
('length', models.IntegerField(default=12)),
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("counter", models.IntegerField(default=1)),
("settings", models.TextField()),
("length", models.IntegerField(default=12)),
],
options={
'verbose_name_plural': 'Password info',
"verbose_name_plural": "Password info",
},
),
migrations.AddField(
model_name='entry',
name='password',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.PasswordInfo'),
model_name="entry",
name="password",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="api.PasswordInfo"
),
),
migrations.AddField(
model_name='entry',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='entries', to=settings.AUTH_USER_MODEL),
model_name="entry",
name="user",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="entries",
to=settings.AUTH_USER_MODEL,
),
),
]

+ 36
- 15
containers/backend/api/migrations/0002_password.py View File

@@ -11,28 +11,49 @@ import uuid
class Migration(migrations.Migration):

dependencies = [
('api', '0001_initial'),
("api", "0001_initial"),
]

operations = [
migrations.CreateModel(
name='Password',
name="Password",
fields=[
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('login', models.CharField(blank=True, max_length=255, null=True)),
('site', models.CharField(blank=True, max_length=255, null=True)),
('lowercase', models.BooleanField(default=True)),
('uppercase', models.BooleanField(default=True)),
('symbols', models.BooleanField(default=True)),
('numbers', models.BooleanField(default=True)),
('counter', models.IntegerField(default=1)),
('length', models.IntegerField(default=12)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='passwords', to=settings.AUTH_USER_MODEL)),
(
"created",
models.DateTimeField(auto_now_add=True, verbose_name="created"),
),
(
"modified",
models.DateTimeField(auto_now=True, verbose_name="modified"),
),
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("login", models.CharField(blank=True, max_length=255, null=True)),
("site", models.CharField(blank=True, max_length=255, null=True)),
("lowercase", models.BooleanField(default=True)),
("uppercase", models.BooleanField(default=True)),
("symbols", models.BooleanField(default=True)),
("numbers", models.BooleanField(default=True)),
("counter", models.IntegerField(default=1)),
("length", models.IntegerField(default=12)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="passwords",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
'abstract': False,
"abstract": False,
},
),
]

+ 17
- 8
containers/backend/api/migrations/0003_mv_entries_to_password.py View File

@@ -11,14 +11,23 @@ from api import models

def create_password_with(entry):
settings = json.dumps(entry.password.settings)
lowercase = 'lowercase' in settings
uppercase = 'uppercase' in settings
symbols = 'symbols' in settings
numbers = 'numbers' in settings
lowercase = "lowercase" in settings
uppercase = "uppercase" in settings
symbols = "symbols" in settings
numbers = "numbers" in settings
user = models.LessPassUser.objects.get(id=entry.user.id)
models.Password.objects.create(id=entry.id, site=entry.site, login=entry.login, user=user,
lowercase=lowercase, uppercase=uppercase, symbols=symbols, numbers=numbers,
counter=entry.password.counter, length=entry.password.length)
models.Password.objects.create(
id=entry.id,
site=entry.site,
login=entry.login,
user=user,
lowercase=lowercase,
uppercase=uppercase,
symbols=symbols,
numbers=numbers,
counter=entry.password.counter,
length=entry.password.length,
)


def mv_entries_to_password(apps, schema_editor):
@@ -29,7 +38,7 @@ def mv_entries_to_password(apps, schema_editor):

class Migration(migrations.Migration):
dependencies = [
('api', '0002_password'),
("api", "0002_password"),
]

operations = [


+ 7
- 7
containers/backend/api/migrations/0004_remove_entries_password_info_models.py View File

@@ -8,22 +8,22 @@ from django.db import migrations
class Migration(migrations.Migration):

dependencies = [
('api', '0003_mv_entries_to_password'),
("api", "0003_mv_entries_to_password"),
]

operations = [
migrations.RemoveField(
model_name='entry',
name='password',
model_name="entry",
name="password",
),
migrations.RemoveField(
model_name='entry',
name='user',
model_name="entry",
name="user",
),
migrations.DeleteModel(
name='Entry',
name="Entry",
),
migrations.DeleteModel(
name='PasswordInfo',
name="PasswordInfo",
),
]

+ 3
- 3
containers/backend/api/migrations/0005_password_version.py View File

@@ -8,13 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):

dependencies = [
('api', '0004_remove_entries_password_info_models'),
("api", "0004_remove_entries_password_info_models"),
]

operations = [
migrations.AddField(
model_name='password',
name='version',
model_name="password",
name="version",
field=models.IntegerField(default=1),
),
]

+ 5
- 5
containers/backend/api/migrations/0006_change_default_password_profile.py View File

@@ -8,18 +8,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):

dependencies = [
('api', '0005_password_version'),
("api", "0005_password_version"),
]

operations = [
migrations.AlterField(
model_name='password',
name='length',
model_name="password",
name="length",
field=models.IntegerField(default=16),
),
migrations.AlterField(
model_name='password',
name='version',
model_name="password",
name="version",
field=models.IntegerField(default=2),
),
]

+ 3
- 3
containers/backend/api/migrations/0007_lesspassuser_key.py View File

@@ -6,13 +6,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):

dependencies = [
('api', '0006_change_default_password_profile'),
("api", "0006_change_default_password_profile"),
]

operations = [
migrations.AddField(
model_name='lesspassuser',
name='key',
model_name="lesspassuser",
name="key",
field=models.TextField(null=True),
),
]

+ 29
- 8
containers/backend/api/migrations/0008_encryptedpasswordprofiles.py View File

@@ -9,21 +9,42 @@ import uuid
class Migration(migrations.Migration):

dependencies = [
('api', '0007_lesspassuser_key'),
("api", "0007_lesspassuser_key"),
]

operations = [
migrations.CreateModel(
name='EncryptedPasswordProfile',
name="EncryptedPasswordProfile",
fields=[
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('password_profile', models.TextField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='encrypted_password_profiles', to=settings.AUTH_USER_MODEL)),
(
"created",
models.DateTimeField(auto_now_add=True, verbose_name="created"),
),
(
"modified",
models.DateTimeField(auto_now=True, verbose_name="modified"),
),
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("password_profile", models.TextField()),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="encrypted_password_profiles",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
'abstract': False,
"abstract": False,
},
),
]

+ 3
- 1
containers/backend/api/serializers.py View File

@@ -40,7 +40,9 @@ class EncryptedPasswordProfileSerializer(serializers.ModelSerializer):

def create(self, validated_data):
user = self.context["request"].user
return models.EncryptedPasswordProfile.objects.create(user=user, **validated_data)
return models.EncryptedPasswordProfile.objects.create(
user=user, **validated_data
)


class BackwardCompatibleTokenObtainPairSerializer(TokenObtainPairSerializer):


+ 8
- 5
containers/backend/api/tests/test_auth.py View File

@@ -60,11 +60,12 @@ class OldLoginTestCase(APITestCase):
"password": "correct horse battery staple",
}
request = self.client.post("/api/tokens/auth/", data)
headers = {"HTTP_AUTHORIZATION": "JWT {token}".format(token=request.data["token"])}
headers = {
"HTTP_AUTHORIZATION": "JWT {token}".format(token=request.data["token"])
}
request = self.client.get("/api/passwords/", **headers)
self.assertEqual(request.status_code, 200)
self.assertEqual(request.data["results"][0]['login'], password.login)

self.assertEqual(request.data["results"][0]["login"], password.login)

def test_nrt_get_passwords_with_bearer(self):
user = factories.UserFactory(
@@ -76,7 +77,9 @@ class OldLoginTestCase(APITestCase):
"password": "correct horse battery staple",
}
request = self.client.post("/api/auth/jwt/create/", data)
headers = {"HTTP_AUTHORIZATION": "Bearer {token}".format(token=request.data["access"])}
headers = {
"HTTP_AUTHORIZATION": "Bearer {token}".format(token=request.data["access"])
}
request = self.client.get("/api/passwords/", **headers)
self.assertEqual(request.status_code, 200)
self.assertEqual(request.data["results"][0]['login'], password.login)
self.assertEqual(request.data["results"][0]["login"], password.login)

+ 22
- 20
containers/backend/api/tests/tests_passwords.py View File

@@ -6,7 +6,7 @@ from api.tests import factories

class LogoutPasswordsTestCase(APITestCase):
def test_get_passwords_401(self):
response = self.client.get('/api/passwords/')
response = self.client.get("/api/passwords/")
self.assertEqual(401, response.status_code)


@@ -17,31 +17,31 @@ class LoginPasswordsTestCase(APITestCase):
self.client.force_authenticate(user=self.user)

def test_get_empty_passwords(self):
request = self.client.get('/api/passwords/')
self.assertEqual(0, len(request.data['results']))
request = self.client.get("/api/passwords/")
self.assertEqual(0, len(request.data["results"]))

def test_retrieve_its_own_passwords(self):
password = factories.PasswordFactory(user=self.user)
request = self.client.get('/api/passwords/')
self.assertEqual(1, len(request.data['results']))
self.assertEqual(password.site, request.data['results'][0]['site'])
request = self.client.get("/api/passwords/")
self.assertEqual(1, len(request.data["results"]))
self.assertEqual(password.site, request.data["results"][0]["site"])

def test_cant_retrieve_other_passwords(self):
not_my_password = factories.PasswordFactory(user=factories.UserFactory())
request = self.client.get('/api/passwords/%s/' % not_my_password.id)
request = self.client.get("/api/passwords/%s/" % not_my_password.id)
self.assertEqual(404, request.status_code)

def test_delete_its_own_passwords(self):
password = factories.PasswordFactory(user=self.user)
self.assertEqual(1, models.Password.objects.all().count())
request = self.client.delete('/api/passwords/%s/' % password.id)
request = self.client.delete("/api/passwords/%s/" % password.id)
self.assertEqual(204, request.status_code)
self.assertEqual(0, models.Password.objects.all().count())

def test_cant_delete_other_password(self):
not_my_password = factories.PasswordFactory(user=factories.UserFactory())
self.assertEqual(1, models.Password.objects.all().count())
request = self.client.delete('/api/passwords/%s/' % not_my_password.id)
request = self.client.delete("/api/passwords/%s/" % not_my_password.id)
self.assertEqual(404, request.status_code)
self.assertEqual(1, models.Password.objects.all().count())

@@ -54,10 +54,10 @@ class LoginPasswordsTestCase(APITestCase):
"number": True,
"symbol": True,
"counter": 1,
"length": 12
"length": 12,
}
self.assertEqual(0, models.Password.objects.count())
self.client.post('/api/passwords/', password)
self.client.post("/api/passwords/", password)
self.assertEqual(1, models.Password.objects.count())

def test_create_password_v2(self):
@@ -70,14 +70,14 @@ class LoginPasswordsTestCase(APITestCase):
"symbol": True,
"counter": 1,
"length": 12,
"version": 2
"version": 2,
}
self.client.post('/api/passwords/', password)
self.client.post("/api/passwords/", password)
self.assertEqual(2, models.Password.objects.first().version)

def test_update_password(self):
password = factories.PasswordFactory(user=self.user)
self.assertNotEqual('facebook.com', password.site)
self.assertNotEqual("facebook.com", password.site)
new_password = {
"site": "facebook.com",
"login": "test@oslab.fr",
@@ -86,19 +86,21 @@ class LoginPasswordsTestCase(APITestCase):
"number": True,
"symbol": True,
"counter": 1,
"length": 12
"length": 12,
}
request = self.client.put('/api/passwords/%s/' % password.id, new_password)
self.assertEqual(200, request.status_code, request.content.decode('utf-8'))
request = self.client.put("/api/passwords/%s/" % password.id, new_password)
self.assertEqual(200, request.status_code, request.content.decode("utf-8"))
password_updated = models.Password.objects.get(id=password.id)
self.assertEqual('facebook.com', password_updated.site)
self.assertEqual("facebook.com", password_updated.site)

def test_cant_update_other_password(self):
not_my_password = factories.PasswordFactory(user=factories.UserFactory())
self.assertEqual('lesspass.com', not_my_password.site)
self.assertEqual("lesspass.com", not_my_password.site)
new_password = {
"site": "facebook",
}
request = self.client.put('/api/passwords/%s/' % not_my_password.id, new_password)
request = self.client.put(
"/api/passwords/%s/" % not_my_password.id, new_password
)
self.assertEqual(404, request.status_code)
self.assertEqual(1, models.Password.objects.all().count())

+ 21
- 8
containers/backend/lesspass/settings.py View File

@@ -92,9 +92,15 @@ AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]

LANGUAGE_CODE = "en-us"
@@ -118,7 +124,11 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "www", "media")
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {"console": {"class": "logging.StreamHandler",}},
"handlers": {
"console": {
"class": "logging.StreamHandler",
}
},
"root": {
"handlers": ["console"],
"level": env("DJANGO_LOG_LEVEL", default="DEBUG"),
@@ -128,10 +138,13 @@ LOGGING = {
AUTH_USER_MODEL = "api.LessPassUser"

SIMPLE_JWT = {
'AUTH_HEADER_TYPES': ('Bearer', 'JWT',),
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
"AUTH_HEADER_TYPES": (
"Bearer",
"JWT",
),
"ACCESS_TOKEN_LIFETIME": datetime.timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": datetime.timedelta(days=7),
"ROTATE_REFRESH_TOKENS": True,
}

REST_FRAMEWORK = {


+ 2
- 2
containers/backend/lesspass/urls.py View File

@@ -2,6 +2,6 @@ from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^api/', include('api.urls')),
url(r'^admin/', admin.site.urls),
url(r"^api/", include("api.urls")),
url(r"^admin/", admin.site.urls),
]

Loading…
Cancel
Save