Browse Source

Update until basics

master
alfred 3 months ago
parent
commit
efd26a7a9f

+ 3
- 0
.gitignore View File

@@ -10,3 +10,6 @@ node_modules
10 10
 **/__pycache__/*
11 11
 **/.sass-cache/*
12 12
 **/migrations/**
13
+
14
+djawth/settings/**
15
+!djawth/settings/dev.py

+ 11
- 0
apps/authentication/models/authentication.py View File

@@ -0,0 +1,11 @@
1
+from django.db import models
2
+from apps.project import models as project
3
+
4
+
5
+class Authentication(models.Model):
6
+    class Meta:
7
+        abstract = True
8
+    user = models.ForeignKey(project.Identity, on_delete=models.CASCADE, related_name='passwordless')
9
+
10
+    def invite(self, identity):
11
+        raise NotImplementedError()

+ 6
- 3
apps/authentication/models/passwordless.py View File

@@ -1,7 +1,10 @@
1 1
 from django.db import models
2
-from apps.base import models as base_models
2
+from .authentication import Authentication
3 3
 
4 4
 
5
-class Passwordless(models.Model):
6
-    user = models.ForeignKey(base_models.User, on_delete=models.CASCADE, related_name='passwordless')
5
+class Passwordless(Authentication):
7 6
     token = models.CharField(max_length=50, blank=False, null=False)
7
+    access = models.CharField(max_length=50, blank=False, null=False)
8
+    one_use_access = models.BooleanField(default=True)
9
+    web_hook_base = models.TextField(blank=True)
10
+    access_parameter = models.CharField(max_length=20, blank=False, null=False)

+ 0
- 9
apps/authentication/urls.py View File

@@ -1,9 +0,0 @@
1
-#!/usr/bin/env python
2
-# -*- coding: utf-8 -*-
3
-
4
-from django.urls import path
5
-from django.views.generic import TemplateView
6
-from django.contrib.auth.views import LoginView, LogoutView
7
-
8
-urlpatterns = [
9
-]

+ 0
- 4
apps/base/models.py View File

@@ -4,7 +4,3 @@ from django.contrib.auth.models import AbstractUser
4 4
 
5 5
 class User(AbstractUser):
6 6
     email = models.EmailField('email address', blank=True, null=True)
7
-
8
-    @property
9
-    def full_name(self):
10
-        return self.get_full_name()

+ 3
- 3
apps/base/static/styles/scss/definitions.scss View File

@@ -1,5 +1,3 @@
1
-$primary-color-dark: #333;
2
-
3 1
 @font-face {
4 2
   font-family: SourceSansPro;
5 3
   src: url(../fonts/SourceSansPro/SourceSansPro-Regular.ttf);
@@ -11,4 +9,6 @@ $primary-color-dark: #333;
11 9
 }
12 10
 
13 11
 $primary-background-color: #1F2439;
14
-$secondary-background-color: #2E334A;
12
+$secondary-background-color: #2E334A;
13
+
14
+$primary-color-dark: #333;

+ 15
- 5
apps/base/static/styles/scss/stylesheet.scss View File

@@ -6,6 +6,7 @@
6 6
 
7 7
 body {
8 8
     background-color: $primary-background-color;
9
+    min-height: 100vh;
9 10
 }
10 11
 
11 12
 header {
@@ -20,8 +21,14 @@ header {
20 21
     padding: 0 50px;
21 22
 }
22 23
 
23
-button {
24
-    color: #333;
24
+footer {
25
+    position: fixed;
26
+    bottom: 0;
27
+    width: 100%;
28
+}
29
+
30
+input, button {
31
+    color: $primary-color-dark;
25 32
 }
26 33
 
27 34
 .title {
@@ -57,14 +64,17 @@ button {
57 64
 .content {
58 65
     margin-top: 50px;
59 66
     background-color: #EEE;
60
-    color: $primary-background-color;
61 67
     padding: 25px;
62 68
     border-radius: 25px;
63 69
 
70
+    table, thead, tbody, tr, th, td {
71
+        color: $primary-background-color;
72
+    }
73
+
64 74
     h2 {
65 75
         font-size: 1.8rem;
66 76
         font-family: Rubik, serif;
67
-        color: #333;
77
+        color: $primary-color-dark;
68 78
         text-decoration: underline;
69 79
         padding: 0;
70 80
         margin: 0;
@@ -73,7 +83,7 @@ button {
73 83
     .no-projects {
74 84
         display: flex;
75 85
         height: 200px;
76
-        color: #333;
86
+        color: $primary-color-dark;
77 87
         align-items: center;
78 88
         padding-left: 25px;
79 89
     }

+ 10
- 3
apps/base/static/styles/stylesheet.css View File

@@ -6455,7 +6455,8 @@ input[type=range]::-ms-thumb {
6455 6455
   color: #D8D9DB; }
6456 6456
 
6457 6457
 body {
6458
-  background-color: #1F2439; }
6458
+  background-color: #1F2439;
6459
+  min-height: 100vh; }
6459 6460
 
6460 6461
 header {
6461 6462
   background-color: #2E334A;
@@ -6467,7 +6468,12 @@ header {
6467 6468
   align-items: center;
6468 6469
   padding: 0 50px; }
6469 6470
 
6470
-button {
6471
+footer {
6472
+  position: fixed;
6473
+  bottom: 0;
6474
+  width: 100%; }
6475
+
6476
+input, button {
6471 6477
   color: #333; }
6472 6478
 
6473 6479
 .title h1 {
@@ -6494,9 +6500,10 @@ button {
6494 6500
 .content {
6495 6501
   margin-top: 50px;
6496 6502
   background-color: #EEE;
6497
-  color: #1F2439;
6498 6503
   padding: 25px;
6499 6504
   border-radius: 25px; }
6505
+  .content table, .content thead, .content tbody, .content tr, .content th, .content td {
6506
+    color: #1F2439; }
6500 6507
   .content h2 {
6501 6508
     font-size: 1.8rem;
6502 6509
     font-family: Rubik, serif;

+ 3
- 1
apps/base/templates/base.html View File

@@ -15,7 +15,6 @@
15 15
   <link rel="shortcut icon" href="favicon.ico" type="image/vnd.microsoft.icon">
16 16
   <link href="{% static 'fonts/MaterialIcons.css' %}" rel="stylesheet">
17 17
   <link rel="stylesheet" href="{% static 'styles/stylesheet.css' %}" type="text/css">
18
-  <script type="text/javascript" src="{% static 'js/materialize/bin/materialize.min.js' %}"></script>
19 18
   </head>
20 19
   <body>
21 20
   {% block body %}
@@ -45,5 +44,8 @@
45 44
         {% endblock %}
46 45
     </div>
47 46
   {% endblock %}
47
+  <footer>
48
+      Hey!
49
+  </footer>
48 50
   </body>
49 51
 </html>

apps/authentication/migrations/__init__.py → apps/project/__init__.py View File


+ 5
- 0
apps/project/apps.py View File

@@ -0,0 +1,5 @@
1
+from django.apps import AppConfig
2
+
3
+
4
+class ProjectConfig(AppConfig):
5
+    name = 'project'

+ 8
- 0
apps/project/forms.py View File

@@ -0,0 +1,8 @@
1
+from django.forms import ModelForm
2
+from apps.project.models import Project
3
+
4
+
5
+class ConfirmProjectForm(ModelForm):
6
+    class Meta:
7
+        model = Project
8
+        fields = '__all__'

+ 44
- 0
apps/project/models.py View File

@@ -0,0 +1,44 @@
1
+from django.db import models
2
+from apps.base import models as base_models
3
+from django.utils.text import slugify
4
+
5
+
6
+class Project(models.Model):
7
+    name = models.CharField(max_length=255, blank=False, null=False)
8
+    owner = models.ForeignKey(base_models.User, on_delete=models.CASCADE, related_name='projects')
9
+    identifier = models.CharField(max_length=265, blank=False, null=False, unique=True)
10
+    secret = models.CharField(max_length=255, blank=False, null=False)
11
+    allow_signup = models.BooleanField(default=False)
12
+    created = models.DateTimeField(auto_now_add=True)
13
+    updated = models.DateTimeField(auto_now=True)
14
+
15
+    @classmethod
16
+    def get_identifier(cls, name, value=0):
17
+        _name = name if value == 0 else f'{name} {value}'
18
+        identifier = slugify(_name)
19
+        try:
20
+            Project.objects.get(identifier=identifier)
21
+            return Project.get_identifier(name, value + 1)
22
+        except Project.DoesNotExist:
23
+            return identifier
24
+
25
+
26
+class Identity(models.Model):
27
+    class Meta:
28
+        unique_together = ['email', 'project']
29
+    uuid = models.UUIDField(unique=True)
30
+    email = models.EmailField('email address', blank=True, null=True)
31
+    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='users')
32
+    user = models.ForeignKey(base_models.User, on_delete=models.CASCADE, related_name='credentials', null=True)
33
+
34
+    @classmethod
35
+    def invite(cls, email, project):
36
+        pass
37
+
38
+    def has_logged_in(self):
39
+        return self.history.objects.count() > 0
40
+
41
+
42
+class History(models.Model):
43
+    identity = models.ForeignKey(Identity, on_delete=models.CASCADE, related_name='history')
44
+    date = models.DateTimeField(auto_created=True)

+ 21
- 0
apps/project/templates/projects/confirm_project.html View File

@@ -0,0 +1,21 @@
1
+{% extends "base.html" %}
2
+
3
+{% block content %}
4
+<h2>Confirm project</h2>
5
+
6
+<form method="post" action="{% url 'confirm_project' %}">
7
+{% csrf_token %}
8
+<input type="hidden" name="name" value="{{ form.name.value }}" />
9
+<input type="hidden" name="secret" value="{{ form.secret.value }}" />
10
+<div class="row">
11
+    Name: <input type="text" name="visible_name" value="{{ form.name.value }}" disabled>
12
+</div>
13
+<div class="row">
14
+    Identifier: <input type="text" name="identifier" value="{{ form.identifier.value }}">
15
+</div>
16
+<div class="row">
17
+    <input type="submit">
18
+</div>
19
+</form>
20
+
21
+{% endblock %}

+ 19
- 0
apps/project/templates/projects/create_project.html View File

@@ -0,0 +1,19 @@
1
+{% extends "base.html" %}
2
+
3
+{% block content %}
4
+<h2>Project creation</h2>
5
+
6
+<form method="post" action="{% url 'confirm_project' %}">
7
+{% csrf_token %}
8
+<div class="row">
9
+    Name: <input type="text" name="name">
10
+</div>
11
+<div class="row">
12
+    Secret: <input type="text" name="secret">
13
+</div>
14
+<div class="row">
15
+    <input type="submit">
16
+</div>
17
+</form>
18
+
19
+{% endblock %}

+ 31
- 0
apps/project/templates/projects/projects_list.html View File

@@ -0,0 +1,31 @@
1
+{% extends "base.html" %}
2
+
3
+{% block content %}
4
+<h2>Projects</h2>
5
+{% if user.projects.count < 1 %}
6
+<div class="no-projects">
7
+No projects
8
+</div>
9
+{% else %}
10
+<table class="stripped" style="margin: 20px 0;">
11
+    <thead>
12
+    <tr>
13
+      <th>Project</th>
14
+      <th>Authentication</th>
15
+      <th>Credentials</th>
16
+    </tr>
17
+    </thead>
18
+
19
+    <tbody>
20
+    {% for project in user.projects.all %}
21
+    <tr>
22
+        <td><a href="#!">{{ project.name }}</a></td>
23
+        <td><a class="waves-effect waves-teal btn-flat">Button</a></td>
24
+        <td><a class="waves-effect waves-teal btn-flat">Button</a></td>
25
+    </tr>
26
+    {% endfor %}
27
+    </tbody>
28
+</table>
29
+{% endif %}
30
+<a class="waves-effect waves-light btn" href="{% url 'new_project' %}"><i class="material-icons left">add_circle</i>Create project</a>
31
+{% endblock %}

+ 21
- 0
apps/project/urls.py View File

@@ -0,0 +1,21 @@
1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+
4
+from django.urls import path
5
+from django.views.generic import TemplateView
6
+from django.contrib.auth.decorators import login_required
7
+from .views import ConfirmProjectView
8
+
9
+urlpatterns = [
10
+    path('home', login_required(TemplateView.as_view(
11
+        template_name='projects/projects_list.html'
12
+    )), name='home'),
13
+    path('new_project', login_required(TemplateView.as_view(
14
+        template_name='projects/create_project.html'
15
+    )), name='new_project'),
16
+    path('confirm_project', login_required(ConfirmProjectView.as_view()), name='confirm_project'),
17
+    # path('authentication/<slug>', login_required(UpdateView(
18
+    # )), name='edit_authentication'),
19
+    # path('edit_project/<slug>', login_required(UpdateView(
20
+    # )), name='project'),
21
+]

+ 29
- 0
apps/project/views.py View File

@@ -0,0 +1,29 @@
1
+from django.views.generic import CreateView
2
+from django.http import QueryDict
3
+from .forms import ConfirmProjectForm
4
+
5
+
6
+class ConfirmProjectView(CreateView):
7
+    template_name = 'projects/confirm_project.html'
8
+    success_url = 'home'
9
+    form_class = ConfirmProjectForm
10
+
11
+    def get_form_kwargs(self):
12
+        from .models import Project
13
+        kwargs = super().get_form_kwargs()
14
+        identifier = self.request.POST.get('identifier', self.request.POST['name'])
15
+
16
+        post_data = QueryDict(mutable=True)
17
+        post_data.update(self.request.POST)
18
+        post_data.update({
19
+            'owner': self.request.user,
20
+            'identifier': Project.get_identifier(identifier)
21
+        })
22
+
23
+        kwargs.update({'data': post_data})
24
+        return kwargs
25
+
26
+    def form_valid(self, form):
27
+        if 'new_project' in self.request.META['HTTP_REFERER']:
28
+            return super().form_invalid(form)
29
+        return super().form_valid(form)

+ 0
- 0
apps/projects/__init__.py View File


+ 0
- 5
apps/projects/apps.py View File

@@ -1,5 +0,0 @@
1
-from django.apps import AppConfig
2
-
3
-
4
-class ProjectsConfig(AppConfig):
5
-    name = 'projects'

+ 0
- 0
apps/projects/migrations/__init__.py View File


+ 0
- 29
apps/projects/models.py View File

@@ -1,29 +0,0 @@
1
-from django.db import models
2
-from apps.base import models as base_models
3
-from django.contrib.auth.validators import UnicodeUsernameValidator
4
-from django.utils.translation import gettext_lazy as _
5
-
6
-
7
-class Project(models.Model):
8
-    name = models.CharField(max_length=255, blank=False, null=False)
9
-    owner = models.ForeignKey(base_models.User, on_delete=models.CASCADE, related_name='projects')
10
-    secret = models.CharField(max_length=255, blank=False, null=False)
11
-
12
-
13
-class User(models.Model):
14
-    class Meta:
15
-        unique_together = ['username', 'project']
16
-    username_validator = UnicodeUsernameValidator()
17
-    username = models.CharField(
18
-            _('username'),
19
-            max_length=50,
20
-            unique=False,
21
-            help_text=_('Required. 50 characters or fewer. Letters, digits and @/./+/-/_ only.'),
22
-            validators=[username_validator],
23
-            error_messages={
24
-                'unique': _("A user with that username already exists."),
25
-            },
26
-        )
27
-    password = models.CharField(_('password'), max_length=128)
28
-    last_login = models.DateTimeField(_('last login'), blank=True, null=True)
29
-    project = models.ForeignKey(base_models.User, on_delete=models.CASCADE, related_name='users')

+ 0
- 11
apps/projects/templates/projects/home.html View File

@@ -1,11 +0,0 @@
1
-{% extends "base.html" %}
2
-
3
-{% block content %}
4
-<h2>Projects</h2>
5
-{% if user.projects.count < 1 %}
6
-<div class="no-projects">
7
-No projects
8
-</div>
9
-{% endif %}
10
-<a class="waves-effect waves-light btn"><i class="material-icons left">add_circle</i>Create project</a>
11
-{% endblock %}

+ 0
- 12
apps/projects/urls.py View File

@@ -1,12 +0,0 @@
1
-#!/usr/bin/env python
2
-# -*- coding: utf-8 -*-
3
-
4
-from django.urls import path
5
-from django.views.generic import TemplateView
6
-from django.contrib.auth.decorators import login_required
7
-
8
-urlpatterns = [
9
-    path('home', login_required(TemplateView.as_view(
10
-        template_name='projects/home.html'
11
-    )), name='home')
12
-]

+ 4
- 4
djawth/settings/dev.py View File

@@ -32,14 +32,14 @@ ALLOWED_HOSTS = []
32 32
 # Application definition
33 33
 
34 34
 INSTALLED_APPS = [
35
+    'apps.base',
36
+    'apps.project',
37
+    # 'apps.authentication',
35 38
     'django.contrib.auth',
36 39
     'django.contrib.contenttypes',
37 40
     'django.contrib.sessions',
38 41
     'django.contrib.messages',
39 42
     'django.contrib.staticfiles',
40
-    'apps.base',
41
-    'apps.projects',
42
-    'apps.authentication'
43 43
 ]
44 44
 
45 45
 MIDDLEWARE = [
@@ -79,7 +79,7 @@ WSGI_APPLICATION = 'djawth.wsgi.application'
79 79
 DATABASES = {
80 80
     'default': {
81 81
         'ENGINE': 'django.db.backends.postgresql',
82
-        'NAME': 'trackmanager',
82
+        'NAME': 'djawth',
83 83
         'USER': 'postgres',
84 84
         'PASSWORD': 'mysecretpassword',
85 85
         'HOST': os.environ.get('DB_HOST', '127.0.0.1'),

+ 1
- 2
djawth/urls.py View File

@@ -17,6 +17,5 @@ from django.urls import path, include
17 17
 
18 18
 urlpatterns = [
19 19
     path('', include('apps.base.urls')),
20
-    path('', include('apps.projects.urls')),
21
-    path('', include('apps.authentication.urls'))
20
+    path('', include('apps.project.urls'))
22 21
 ]

Loading…
Cancel
Save