feat(core): add generation & exportation of pub/priv keys

master
Romain J 10 months ago
parent 531c0eb78f
commit 10a19601a1
No known key found for this signature in database
GPG Key ID: 3227578329C2A3A7

@ -29,16 +29,10 @@ h
8chat/apps/guilds/features/channels/consumers/__init__.py,e/2/e291cafecaedae4562004377f14184839884fd88
^
.chat/apps/guilds/features/channels/__init__.py,1/e/1ec598764d7b8851aa9d3cd178d3c844b5d132b9
]
-chat/apps/guilds/features/channels/signals.py,5/f/5f30f5d04bcb2c49cfde4a698c9a8307bbd4fa6e
[
+chat/apps/guilds/migrations/0002_initial.py,0/2/020b45107d0df50edcd5865afacd54bf4d6632a4
B
chat/pages/apps.py,b/6/b61d6a1f522283203801f2468bf9caba725507ae
H
chat/apps/users/forms.py,c/5/c590740c4ac867b1db50168e191a9f5bbca5397c
H
chat/apps/guilds/apps.py,f/8/f8550eeba98ecb491e727fb1d0f24ad5c394d099
@
.readthedocs.yml,8/1/81ccd5c4e1f93eb3ab80c73b5532455bf4f82fe9
V

@ -69,8 +69,6 @@ class ChannelAdmin(admin.ModelAdmin):
"guild",
"position",
"parent",
"last_message",
"messages_count",
]
search_fields = ["id", "name"]

@ -59,21 +59,13 @@ class Channel(models.Model):
name = models.TextField(max_length=100)
topic = models.TextField(max_length=1024, blank=True, null=True)
last_message = models.ForeignKey(
"Message",
on_delete=models.SET_NULL,
related_name="last_message",
blank=True,
null=True,
)
# =========================================================================
def get_messages(self):
def get_messages(self, recipient: User):
return Message.objects.filter(channel=self)
def messages_count(self):
return len(self.get_messages().all())
# def messages_count(self):
# return len(self.get_messages().all())
# =========================================================================
@ -99,26 +91,11 @@ class Message(models.Model):
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="author"
)
attachments = models.ManyToManyField("Attachment", blank=True)
previous = models.OneToOneField(
"self",
null=True,
blank=True,
related_name="previous_message",
on_delete=models.SET_NULL,
recipient = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="recipient"
)
same_previous_author = models.BooleanField(blank=True, null=True)
next = models.OneToOneField(
"self",
null=True,
blank=True,
related_name="next_message",
on_delete=models.SET_NULL,
)
same_next_author = models.BooleanField(blank=True, null=True)
attachments = models.ManyToManyField("Attachment", blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@ -131,9 +108,8 @@ class Message(models.Model):
def __str__(self):
return (
f"from: {self.author}, "
f"to: {self.recipient}, "
f"id: {self.id}, "
f"same_previous_author: {self.same_previous_author}, "
f"same_next_author: {self.same_next_author}"
)

@ -1,7 +1,8 @@
# Generated by Django 3.2.8 on 2021-11-10 21:18
# Generated by Django 3.2.8 on 2022-05-25 12:33
import chat.utils.functions
from django.db import migrations, models
import django_extensions.db.fields
import uuid
@ -9,147 +10,66 @@ class Migration(migrations.Migration):
initial = True
dependencies = []
dependencies = [
]
operations = [
migrations.CreateModel(
name="Attachment",
name='Attachment',
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"filename",
models.TextField(blank=True, default=None, null=True),
),
(
"file",
models.FileField(
upload_to=chat.utils.functions.PathAndRename(
"guilds/attachments"
)
),
),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('filename', models.TextField(blank=True, default=None, null=True)),
('file', models.FileField(upload_to=chat.utils.functions.PathAndRename('guilds/attachments'))),
],
),
migrations.CreateModel(
name="Channel",
name='Category',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('position', models.IntegerField(default=1)),
('name', models.TextField(max_length=100)),
],
options={
'verbose_name_plural': 'Categories',
},
),
migrations.CreateModel(
name='Channel',
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"type",
models.CharField(
choices=[
("DM", "Direct Message"),
("GROUP_DM", "Group Direct Message"),
("TEXT", "Text"),
("CATEGORY", "Category"),
("NEWS", "News"),
],
max_length=10,
),
),
("position", models.IntegerField()),
("name", models.TextField(max_length=100)),
(
"topic",
models.TextField(blank=True, max_length=1024, null=True),
),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('position', models.IntegerField(default=1)),
('name', models.TextField(max_length=100)),
('topic', models.TextField(blank=True, max_length=1024, null=True)),
],
),
migrations.CreateModel(
name="Guild",
name='Guild',
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"name",
models.CharField(
max_length=200, verbose_name="Guild Name"
),
),
(
"avatar",
models.ImageField(
upload_to=chat.utils.functions.PathAndRename(
"guilds/avatar"
),
verbose_name="Guild Icon",
),
),
(
"description",
models.TextField(blank=True, max_length=1024, null=True),
),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('name', models.CharField(max_length=200, verbose_name='Guild Name')),
('avatar', models.ImageField(upload_to=chat.utils.functions.PathAndRename('guilds/avatar'), verbose_name='Guild Icon')),
('description', models.TextField(blank=True, max_length=1024, null=True)),
],
),
migrations.CreateModel(
name="Invite",
name='Invite',
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("key", models.CharField(max_length=10)),
("uses", models.IntegerField(default=0)),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('key', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=10, unique=True)),
('uses', models.IntegerField(default=0)),
],
),
migrations.CreateModel(
name="Message",
name='Message',
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("content", models.TextField()),
(
"same_previous_author",
models.BooleanField(blank=True, null=True),
),
(
"same_next_author",
models.BooleanField(blank=True, null=True),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"attachments",
models.ManyToManyField(blank=True, to="guilds.Attachment"),
),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('content', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('attachments', models.ManyToManyField(blank=True, to='guilds.Attachment')),
],
options={
"ordering": ["created_at"],
'ordering': ['created_at'],
},
),
]

@ -1,4 +1,4 @@
# Generated by Django 3.2.8 on 2021-11-10 21:18
# Generated by Django 3.2.8 on 2022-05-25 12:33
from django.conf import settings
from django.db import migrations, models
@ -11,123 +11,73 @@ class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("guilds", "0001_initial"),
('guilds', '0001_initial'),
]
operations = [
migrations.AddField(
model_name="message",
name="author",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="author",
to=settings.AUTH_USER_MODEL,
),
model_name='message',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='author', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="message",
name="channel",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="guilds.channel",
),
model_name='message',
name='channel',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='guilds.channel'),
),
migrations.AddField(
model_name="message",
name="next",
field=models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="next_message",
to="guilds.message",
),
model_name='message',
name='recipient',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipient', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="message",
name="previous",
field=models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="previous_message",
to="guilds.message",
),
model_name='invite',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="invite",
name="author",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
model_name='invite',
name='guild',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.guild'),
),
migrations.AddField(
model_name="invite",
name="guild",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="guilds.guild"
),
model_name='guild',
name='bans',
field=models.ManyToManyField(related_name='bans', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="guild",
name="bans",
field=models.ManyToManyField(
related_name="bans", to=settings.AUTH_USER_MODEL
),
model_name='guild',
name='categories',
field=models.ManyToManyField(blank=True, related_name='categories', to='guilds.Category'),
),
migrations.AddField(
model_name="guild",
name="channels",
field=models.ManyToManyField(
blank=True, related_name="channels", to="guilds.Channel"
),
model_name='guild',
name='channels',
field=models.ManyToManyField(blank=True, related_name='channels', to='guilds.Channel'),
),
migrations.AddField(
model_name="guild",
name="members",
model_name='guild',
name='members',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="guild",
name="owner",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="owner",
to=settings.AUTH_USER_MODEL,
),
model_name='guild',
name='owner',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owner', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name="channel",
name="guild",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="guilds.guild",
),
model_name='channel',
name='guild',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='guilds.guild'),
),
migrations.AddField(
model_name="channel",
name="last_message",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="last_message",
to="guilds.message",
),
model_name='channel',
name='parent',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='guilds.category'),
),
migrations.AddField(
model_name="channel",
name="parent",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="guilds.channel",
),
model_name='category',
name='guild',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='guilds.guild'),
),
]

@ -1,38 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-14 17:32
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('guilds', '0002_initial'),
]
operations = [
migrations.RemoveField(
model_name='channel',
name='type',
),
migrations.AlterField(
model_name='channel',
name='position',
field=models.IntegerField(default=1),
),
migrations.CreateModel(
name='Category',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('position', models.IntegerField(default=1)),
('name', models.TextField(max_length=100)),
('guild', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='guilds.guild')),
],
),
migrations.AlterField(
model_name='channel',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='guilds.category'),
),
]

@ -1,22 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-14 17:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guilds', '0003_auto_20211114_1732'),
]
operations = [
migrations.AlterModelOptions(
name='category',
options={'verbose_name_plural': 'Categories'},
),
migrations.AddField(
model_name='guild',
name='categories',
field=models.ManyToManyField(blank=True, related_name='categories', to='guilds.Category'),
),
]

@ -1,19 +0,0 @@
# Generated by Django 3.2.8 on 2022-02-15 17:07
from django.db import migrations
import django_extensions.db.fields
class Migration(migrations.Migration):
dependencies = [
('guilds', '0004_auto_20211114_1754'),
]
operations = [
migrations.AlterField(
model_name='invite',
name='key',
field=django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=10, unique=True),
),
]

@ -1,19 +0,0 @@
# Generated by Django 3.2.8 on 2022-05-21 22:01
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('guilds', '0005_alter_invite_key'),
]
operations = [
migrations.AlterField(
model_name='channel',
name='parent',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='guilds.category'),
),
]

@ -1,9 +1,10 @@
# Generated by Django 3.2.8 on 2021-11-10 21:18
# Generated by Django 3.2.8 on 2022-05-25 12:33
import chat.utils.functions
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
@ -13,137 +14,50 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
('guilds', '0001_initial'),
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name="User",
name='UserSettings',
fields=[
(
"password",
models.CharField(max_length=128, verbose_name="password"),
),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now,
verbose_name="date joined",
),
),
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"avatar",
models.ImageField(
blank=True,
null=True,
upload_to=chat.utils.functions.PathAndRename(
"users/avatar"
),
),
),
(
"bio",
models.TextField(blank=True, max_length=1000, null=True),
),
(
"language",
models.CharField(
choices=[
("fr-FR", "Français (beta)"),
("en-US", "English"),
],
default="en-us",
max_length=10,
),
),
(
"mneomonic",
models.CharField(blank=True, max_length=255, null=True),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.Group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.Permission",
verbose_name="user permissions",
),
),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('language', models.CharField(choices=[('fr-fr', 'Français (beta)'), ('en-us', 'English')], default='en-us', max_length=10)),
('theme', models.CharField(choices=[('DK', 'Dark'), ('LT', 'Light')], default='DK', max_length=2)),
('avatar', models.ImageField(blank=True, null=True, upload_to=chat.utils.functions.PathAndRename('users/avatar'))),
('bio', models.TextField(blank=True, max_length=1000, null=True)),
('pubkey', models.TextField(blank=True, default=None, null=True)),
('collapsed_categories', models.ManyToManyField(blank=True, default=None, to='guilds.Category')),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
'verbose_name_plural': 'User Settings',
},
),
migrations.CreateModel(
name='User',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('first_connect', models.BooleanField(default=True)),
('mnemonic', models.CharField(blank=True, max_length=255, null=True)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('settings', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='user_settings', to='users.usersettings')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
('objects', django.contrib.auth.models.UserManager()),
],
),
]

@ -0,0 +1,22 @@
# Generated by Django 3.2.8 on 2022-05-25 13:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='usersettings',
name='pubkey',
),
migrations.AddField(
model_name='user',
name='pubkey',
field=models.CharField(blank=True, max_length=255, null=True),
),
]

@ -1,18 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-11 18:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="user",
name="first_connect",
field=models.BooleanField(default=True),
),
]

@ -1,18 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-11 22:46
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("users", "0002_user_first_connect"),
]
operations = [
migrations.RenameField(
model_name="user",
old_name="mneomonic",
new_name="mnemonic",
),
]

@ -0,0 +1,18 @@
# Generated by Django 3.2.8 on 2022-05-25 13:46
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0002_auto_20220525_1344'),
]
operations = [
migrations.RenameField(
model_name='user',
old_name='pubkey',
new_name='public_key',
),
]

@ -1,32 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-25 16:29
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('users', '0003_rename_mneomonic_user_mnemonic'),
]
operations = [
migrations.CreateModel(
name='UserSettings',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('language', models.CharField(choices=[('fr-FR', 'Français (beta)'), ('en-US', 'English')], default='en-us', max_length=10)),
('theme', models.CharField(choices=[('DK', 'Dark'), ('LT', 'Light')], default='DK', max_length=2)),
],
),
migrations.RemoveField(
model_name='user',
name='language',
),
migrations.AddField(
model_name='user',
name='settings',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='users.usersettings'),
),
]

@ -1,36 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-25 17:11
import chat.utils.functions
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0004_auto_20211125_1629'),
]
operations = [
migrations.AlterModelOptions(
name='usersettings',
options={'verbose_name_plural': 'User Settings'},
),
migrations.RemoveField(
model_name='user',
name='avatar',
),
migrations.RemoveField(
model_name='user',
name='bio',
),
migrations.AddField(
model_name='usersettings',
name='avatar',
field=models.ImageField(blank=True, null=True, upload_to=chat.utils.functions.PathAndRename('users/avatar')),
),
migrations.AddField(
model_name='usersettings',
name='bio',
field=models.TextField(blank=True, max_length=1000, null=True),
),
]

@ -1,19 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-25 17:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0005_auto_20211125_1711'),
]
operations = [
migrations.AlterField(
model_name='user',
name='settings',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='settings', to='users.usersettings'),
),
]

@ -1,24 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-25 18:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0006_alter_user_settings'),
]
operations = [
migrations.AlterField(
model_name='user',
name='settings',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='user_settings', to='users.usersettings'),
),
migrations.AlterField(
model_name='usersettings',
name='language',
field=models.CharField(choices=[('fr', 'Français (beta)'), ('en', 'English')], default='en-us', max_length=10),
),
]

@ -1,24 +0,0 @@
# Generated by Django 3.2.8 on 2021-11-26 12:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guilds', '0004_auto_20211114_1754'),
('users', '0007_auto_20211125_1800'),
]
operations = [
migrations.AddField(
model_name='usersettings',
name='collapsed_categories',
field=models.ManyToManyField(blank=True, default=None, to='guilds.Category'),
),
migrations.AlterField(
model_name='usersettings',
name='language',
field=models.CharField(choices=[('fr-fr', 'Français (beta)'), ('en-us', 'English')], default='en-us', max_length=10),
),
]

@ -1,18 +0,0 @@
# Generated by Django 3.2.8 on 2022-05-16 13:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0008_auto_20211126_1212'),
]
operations = [
migrations.AddField(
model_name='user',
name='email',
field=models.EmailField(blank=True, max_length=254, null=True, unique=True),
),
]

@ -1,17 +0,0 @@
# Generated by Django 3.2.8 on 2022-05-21 22:01
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0009_user_email'),
]
operations = [
migrations.RemoveField(
model_name='user',
name='email',
),
]

@ -81,7 +81,9 @@ class User(AbstractUser):
# email = models.EmailField(unique=True, blank=True, null=True) # None # type: ignore
first_connect = models.BooleanField(default=True)
mnemonic = models.CharField(max_length=255, blank=True, null=True)
public_key = models.CharField(max_length=255, blank=True, null=True)
# =========================================================================

@ -127,6 +127,9 @@ class UserFistConnectView(BaseUsersView, View):
template_name = template_path + "first_connect"
def get(self, request: ASGIRequest, page: str = "first") -> HttpResponse:
if (user_settings := User.objects.get(id=request.user.id)) and not user_settings.first_connect:
return redirect("users:redirect")
if page == "first":
return render(request, self.template_name + "/first.html")
@ -151,6 +154,7 @@ class UserFistConnectView(BaseUsersView, View):
return redirect("users:first_connect")
mnemonic = request.POST.get("mnemonic")
public_key = request.POST.get("public_key")
mnemonics = request.session["mnemonics"]
if mnemonic not in mnemonics.values():
@ -164,11 +168,23 @@ class UserFistConnectView(BaseUsersView, View):
self.template_name + "/next.html",
{"mnemonics": mnemonics},
)
if not public_key:
messages.add_message(
request,
messages.WARNING,
_("Please do not edit autofilled inputs"),
)
return render(
request,
self.template_name + "/next.html",
{"mnemonics": mnemonics},
)
del request.session["mnemonics"]
user = User.objects.get(id=request.user.id)
user.mnemonic = make_password(mnemonic)
user.public_key = public_key
user.first_connect = False
user.save()

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,81 @@
// Written in 2014-2016 by Dmitry Chestnykh and Devi Mandiri.
// Public domain.
(function(root, f) {
'use strict';
if (typeof module !== 'undefined' && module.exports) module.exports = f();
else if (root.nacl) root.nacl.util = f();
else {
root.nacl = {};
root.nacl.util = f();
}
}(this, function() {
'use strict';
var util = {};
function validateBase64(s) {
if (!(/^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(s))) {
throw new TypeError('invalid encoding');
}
}
util.decodeUTF8 = function(s) {
if (typeof s !== 'string') throw new TypeError('expected string');
var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
};
util.encodeUTF8 = function(arr) {
var i, s = [];
for (i = 0; i < arr.length; i++) s.push(String.fromCharCode(arr[i]));
return decodeURIComponent(escape(s.join('')));
};
if (typeof atob === 'undefined') {
// Node.js
if (typeof Buffer.from !== 'undefined') {
// Node v6 and later
util.encodeBase64 = function (arr) { // v6 and later
return Buffer.from(arr).toString('base64');
};
util.decodeBase64 = function (s) {
validateBase64(s);
return new Uint8Array(Array.prototype.slice.call(Buffer.from(s, 'base64'), 0));
};
} else {
// Node earlier than v6
util.encodeBase64 = function (arr) { // v6 and later
return (new Buffer(arr)).toString('base64');
};
util.decodeBase64 = function(s) {
validateBase64(s);
return new Uint8Array(Array.prototype.slice.call(new Buffer(s, 'base64'), 0));
};
}
} else {
// Browsers
util.encodeBase64 = function(arr) {
var i, s = [], len = arr.length;
for (i = 0; i < len; i++) s.push(String.fromCharCode(arr[i]));
return btoa(s.join(''));
};
util.decodeBase64 = function(s) {
validateBase64(s);
var i, d = atob(s), b = new Uint8Array(d.length);
for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i);
return b;
};
}
return util;
}));

@ -0,0 +1 @@
!function(e,n){"use strict";"undefined"!=typeof module&&module.exports?module.exports=n():(e.nacl||(e.nacl={}),e.nacl.util=n())}(this,function(){"use strict";var e={};function o(e){if(!/^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(e))throw new TypeError("invalid encoding")}return e.decodeUTF8=function(e){if("string"!=typeof e)throw new TypeError("expected string");var n,r=unescape(encodeURIComponent(e)),t=new Uint8Array(r.length);for(n=0;n<r.length;n++)t[n]=r.charCodeAt(n);return t},e.encodeUTF8=function(e){var n,r=[];for(n=0;n<e.length;n++)r.push(String.fromCharCode(e[n]));return decodeURIComponent(escape(r.join("")))},"undefined"==typeof atob?void 0!==Buffer.from?(e.encodeBase64=function(e){return Buffer.from(e).toString("base64")},e.decodeBase64=function(e){return o(e),new Uint8Array(Array.prototype.slice.call(Buffer.from(e,"base64"),0))}):(e.encodeBase64=function(e){return new Buffer(e).toString("base64")},e.decodeBase64=function(e){return o(e),new Uint8Array(Array.prototype.slice.call(new Buffer(e,"base64"),0))}):(e.encodeBase64=function(e){var n,r=[],t=e.length;for(n=0;n<t;n++)r.push(String.fromCharCode(e[n]));return btoa(r.join(""))},e.decodeBase64=function(e){o(e);var n,r=atob(e),t=new Uint8Array(r.length);for(n=0;n<r.length;n++)t[n]=r.charCodeAt(n);return t}),e});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -12,9 +12,9 @@
<div class="uk-margin uk-margin-auto uk-card-body">
<h1 class="uk-card-title uk-text-center">{% translate "Sign Out" %}</h1>
{# <div class="uk-alert uk-alert-primary">#}
{# <p>{% trans "Don't forget to export your key ;)" %}</p>#}
{# </div>#}
<div class="uk-alert uk-alert-primary">
<p>{% trans "Don't forget to export your key ;)" %}</p>
</div>
{% if form.non_field_errors %}
<div class="uk-alert uk-alert-danger">
@ -31,15 +31,15 @@
value="{{ redirect_field_value }}"/>
{% endif %}
{# <div class="uk-margin">#}
{# <label class="uk-inline uk-width-1-1" for="secret_key">#}
{# {% trans "Secret key" %}#}
{# <textarea class="uk-textarea uk-resize-vertical" id="secret_key" cols="30" rows="10"></textarea>#}
{# </label>#}
{# <div class="uk-width-1-1">#}
{# <a id="secret_key_export">{% trans "Download" %}</a>#}
{# </div>#}
{# </div>#}
<div class="uk-margin">
<label class="uk-inline uk-width-1-1" for="private_key">
{% trans "Private key" %}
<textarea class="uk-textarea uk-resize-vertical" id="private_key" cols="30" rows="10"></textarea>
</label>
<div class="uk-width-1-1">
<a id="private_key_export">{% trans "Download" %}</a>
</div>
</div>
<div class="uk-margin">
<button class="uk-button uk-button-primary uk-button-large uk-width-1-1">
@ -56,12 +56,16 @@
{% block inline_javascript %}
<script>
const textarea = document.getElementById("secret_key");
const anchor = document.getElementById("secret_key_export");
const secret_key = atob(sessionStorage.getItem("secret_key"));
if (window.keyPair === undefined) {
window.keyPair = window.sessionStorage.getItem("keySet").split("|");
}
const textarea = document.getElementById("private_key");
const anchor = document.getElementById("private_key_export");
const secret_key = keyPair[1];
textarea.innerHTML = secret_key;
anchor.setAttribute("href", `data:text/plain;charset=utf-8,${encodeURIComponent(secret_key)}`);
anchor.setAttribute('download', "secret_key");
anchor.setAttribute('download', "private_key");
</script>
{% endblock %}

@ -23,19 +23,19 @@
href="{% url 'guild:channel_details' guild.id channel.id %}">{{ channel }}</a>
</td>
<td class="uk-overflow-auto">
{% if channel.last_message %}
{# {% if channel.last_message %}#}
{# {% include "layouts/components/message/block.html" with message=channel.messages.first %}#}
<b class="uk-text-bold">[{{ channel.last_message.author }}]</b>
<span id="prev_{{ channel.last_message.id }}">{{ channel.last_message.content }}</span>
<script>
window.addEventListener('load', () => {
document.getElementById("prev_{{ channel.last_message.id }}").innerText = decipher('{{ channel.last_message.content }}', '{{ channel.last_message.author.id }}');
});
</script>
{% endif %}
{# <b class="uk-text-bold">[{{ channel.last_message.author }}]</b>#}
{# <span id="prev_{{ channel.last_message.id }}">{{ channel.last_message.content }}</span>#}
{# <script>#}
{# window.addEventListener('load', () => {#}
{# document.getElementById("prev_{{ channel.last_message.id }}").innerText = decipher('{{ channel.last_message.content }}', '{{ channel.last_message.author.id }}');#}
{# });#}
{# </script>#}
{# {% endif %}#}
</td>
<td>
<span>{{ channel.messages_count }}</span>
{# <span>{{ channel.messages_count }}</span>#}
</td>
</tr>
{% endfor %}

@ -33,6 +33,8 @@
<script defer src="{% static 'js/libs/uikit/uikit-icons.js' %}"></script>
<script defer src="{% static 'js/components/message.js' %}"></script>
<script defer src="{% static 'js/libs/CryptoJS.js' %}"></script>
<script defer src="{% static 'js/libs/tweetnacl/nacl.min.js' %}"></script>
<script defer src="{% static 'js/libs/tweetnacl/nacl-util.min.js' %}"></script>
<script defer src="{% static 'js/project.js' %}"></script>
{% endcompress %}
{% endblock javascript %}

@ -18,8 +18,8 @@
time by
closing the current tab.
<br><br>
Also, each time you log in, you will be asked to enter your private key which will
be
Also, each time you log in, you will be asked to enter your private key
which will be
used to read and send messages. This key will be saved in your browser like the