mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-24 22:53:43 +03:00
added oauth, health checks, new blog and user features
This commit is contained in:
parent
bf8e191a65
commit
9b2cf1656b
17
akarpov/blog/migrations/0002_alter_comment_options.py
Normal file
17
akarpov/blog/migrations/0002_alter_comment_options.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 4.0.8 on 2022-11-23 09:23
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('blog', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='comment',
|
||||||
|
options={'ordering': ['-rating', '-created']},
|
||||||
|
),
|
||||||
|
]
|
|
@ -98,7 +98,7 @@ def __str__(self):
|
||||||
return f"{self.author.username}'s comment on {self.post.title}"
|
return f"{self.author.username}'s comment on {self.post.title}"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-rating"]
|
ordering = ["-rating", "-created"]
|
||||||
|
|
||||||
|
|
||||||
class CommentRating(models.Model):
|
class CommentRating(models.Model):
|
||||||
|
|
|
@ -19,7 +19,14 @@ def post_on_save(sender, instance: Post, **kwargs):
|
||||||
{"image_cropped"}
|
{"image_cropped"}
|
||||||
):
|
):
|
||||||
if instance.image:
|
if instance.image:
|
||||||
crop_model_image.delay(instance.pk, "blog", "Post")
|
crop_model_image.apply_async(
|
||||||
|
kwargs={
|
||||||
|
"pk": instance.pk,
|
||||||
|
"app_label": "blog",
|
||||||
|
"model_name": "Post",
|
||||||
|
},
|
||||||
|
countdown=10,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
instance.image_cropped = None
|
instance.image_cropped = None
|
||||||
instance.save()
|
instance.save()
|
||||||
|
@ -74,4 +81,11 @@ def post_rating_delete(sender, instance: PostRating, **kwargs):
|
||||||
def post_on_create(sender, instance: Post, created, **kwargs):
|
def post_on_create(sender, instance: Post, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
if instance.image:
|
if instance.image:
|
||||||
crop_model_image.delay(instance.pk, "blog", "Post")
|
crop_model_image.apply_async(
|
||||||
|
kwargs={
|
||||||
|
"pk": instance.pk,
|
||||||
|
"app_label": "blog",
|
||||||
|
"model_name": "Post",
|
||||||
|
},
|
||||||
|
countdown=10,
|
||||||
|
)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
{% load socialaccount %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Signup" %}{% endblock %}
|
{% block head_title %}{% translate "Signup" %}{% endblock %}
|
||||||
|
|
||||||
|
@ -16,6 +17,9 @@
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="row mb-2">
|
||||||
|
<a href="{% provider_login_url 'github' %}"><i class="bi bi-github btn"></i></a>
|
||||||
|
</div>
|
||||||
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div>
|
<div>
|
||||||
<label for="textarea" class="form-label">write your comments</label>
|
<label for="textarea" class="form-label">write your comments</label>
|
||||||
<textarea name="body" class="form-control" id="textarea" rows="3"></textarea>
|
<textarea name="body" maxlength="100" class="form-control" id="textarea" rows="3"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-sm btn-secondary mt-2" type="submit">Send</button>
|
<button class="btn btn-sm btn-secondary mt-2" type="submit">Send</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
<p class="mb-1">
|
<p class="mb-1">
|
||||||
{{ comment.author.username }} <span class="small">- {{ comment.created | naturaltime }}</span>
|
{{ comment.author.username }} <span class="small">- {{ comment.created | naturaltime }}</span>
|
||||||
</p>
|
</p>
|
||||||
<button class="btn btn-outline-primary"><i class="bi bi-reply"></i><span class="small"> reply</span></button>
|
<!--<button class="btn btn-outline-primary"><i class="bi bi-reply"></i><span class="small"> reply</span></button> -->
|
||||||
</div>
|
</div>
|
||||||
<p class="small mb-0">
|
<p class="small mb-0">
|
||||||
{{ comment.body }}
|
{{ comment.body }}
|
||||||
|
|
21
akarpov/templates/socialaccount/login.html
Normal file
21
akarpov/templates/socialaccount/login.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Sign In" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if process == "connect" %}
|
||||||
|
<h1>{% blocktrans with provider.name as provider %}Connect {{ provider }}{% endblocktrans %}</h1>
|
||||||
|
|
||||||
|
<p>{% blocktrans with provider.name as provider %}You are about to connect a new third party account from {{ provider }}.{% endblocktrans %}</p>
|
||||||
|
{% else %}
|
||||||
|
<h1>{% blocktrans with provider.name as provider %}Sign In Via {{ provider }}{% endblocktrans %}</h1>
|
||||||
|
|
||||||
|
<p>{% blocktrans with provider.name as provider %}You are about to sign in using a third party account from {{ provider }}.{% endblocktrans %}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-success" type="submit">{% trans "Continue" %}</button>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
52
akarpov/templates/socialaccount/providers/connections.html
Normal file
52
akarpov/templates/socialaccount/providers/connections.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block head_title %}{% trans "Account Connections" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Account Connections" %}</h1>
|
||||||
|
|
||||||
|
{% if form.accounts %}
|
||||||
|
<p>{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
|
||||||
|
<form method="post" action="{% url 'socialaccount_connections' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{% if form.non_field_errors %}
|
||||||
|
<div id="errorMsg">{{ form.non_field_errors }}</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for base_account in form.accounts %}
|
||||||
|
{% with base_account.get_provider_account as account %}
|
||||||
|
<div>
|
||||||
|
<label for="id_account_{{ base_account.id }}">
|
||||||
|
<input id="id_account_{{ base_account.id }}" type="radio" name="account" value="{{ base_account.id }}"/>
|
||||||
|
<span class="socialaccount_provider {{ base_account.provider }} {{ account.get_brand.id }}">{{account.get_brand.name}}</span>
|
||||||
|
{{ account }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit">{% trans 'Remove' %}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<p>{% trans 'You currently have no social network accounts connected to this account.' %}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2>{% trans 'Add a 3rd Party Account' %}</h2>
|
||||||
|
|
||||||
|
<ul class="socialaccount_providers">
|
||||||
|
{% include "socialaccount/snippets/provider_list.html" with process="connect" %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% include "socialaccount/snippets/login_extra.html" %}
|
||||||
|
|
||||||
|
{% endblock %}
|
21
akarpov/templates/socialaccount/snippets/provider_list.html
Normal file
21
akarpov/templates/socialaccount/snippets/provider_list.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% load socialaccount %}
|
||||||
|
|
||||||
|
{% get_providers as socialaccount_providers %}
|
||||||
|
|
||||||
|
{% for provider in socialaccount_providers %}
|
||||||
|
{% if provider.id == "openid" %}
|
||||||
|
{% for brand in provider.get_brands %}
|
||||||
|
<li>
|
||||||
|
<a title="{{brand.name | lower}}"
|
||||||
|
class="socialaccount_provider {{provider.id}} {{brand.id}}"
|
||||||
|
href="{% provider_login_url provider.id openid=brand.openid_url process=process %}"
|
||||||
|
><i class="bi bi-{{ brand.name }}"></i>{{brand.name}}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<i class="bi bi-{{provider.name | lower}}"></i>
|
||||||
|
<a title="{{provider.name}}" class="socialaccount_provider {{provider.id}}"
|
||||||
|
href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}">{{provider.name}}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
|
@ -35,10 +35,20 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:update' %}">
|
<a href="{% url 'account_email' %}">
|
||||||
<i class="bi bi-envelope"></i>
|
<i class="bi bi-envelope"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'account_reset_password' %}">
|
||||||
|
<i class="bi bi-key"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'socialaccount_connections' %}">
|
||||||
|
<i class="bi bi-person-add"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -15,7 +15,14 @@ def on_change(sender, instance: User, **kwargs):
|
||||||
{"image_cropped"}
|
{"image_cropped"}
|
||||||
):
|
):
|
||||||
if instance.image:
|
if instance.image:
|
||||||
crop_model_image.delay(instance.pk, "users", "User")
|
crop_model_image.apply_async(
|
||||||
|
kwargs={
|
||||||
|
"pk": instance.pk,
|
||||||
|
"app_label": "users",
|
||||||
|
"model_name": "User",
|
||||||
|
},
|
||||||
|
countdown=10,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
instance.image_cropped = None
|
instance.image_cropped = None
|
||||||
instance.save()
|
instance.save()
|
||||||
|
@ -25,4 +32,12 @@ def on_change(sender, instance: User, **kwargs):
|
||||||
def post_on_create(sender, instance: User, created, **kwargs):
|
def post_on_create(sender, instance: User, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
if instance.image:
|
if instance.image:
|
||||||
crop_model_image.delay(instance.pk, "users", "User")
|
if instance.image:
|
||||||
|
crop_model_image.apply_async(
|
||||||
|
kwargs={
|
||||||
|
"pk": instance.pk,
|
||||||
|
"app_label": "users",
|
||||||
|
"model_name": "User",
|
||||||
|
},
|
||||||
|
countdown=10,
|
||||||
|
)
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
"django.forms",
|
"django.forms",
|
||||||
]
|
]
|
||||||
|
|
||||||
THIRD_PARTY_APPS = [
|
THIRD_PARTY_APPS = [
|
||||||
"crispy_forms",
|
"crispy_forms",
|
||||||
"crispy_bootstrap5",
|
"crispy_bootstrap5",
|
||||||
|
@ -82,13 +83,34 @@
|
||||||
"colorfield",
|
"colorfield",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
HEALTH_CHECKS = [
|
||||||
|
"health_check", # required
|
||||||
|
"health_check.db", # stock Django health checkers
|
||||||
|
"health_check.cache",
|
||||||
|
"health_check.storage",
|
||||||
|
"health_check.contrib.celery",
|
||||||
|
"health_check.contrib.celery_ping",
|
||||||
|
"health_check.contrib.migrations",
|
||||||
|
"health_check.contrib.psutil", # disk and memory utilization
|
||||||
|
"health_check.contrib.redis",
|
||||||
|
]
|
||||||
|
|
||||||
|
ALL_AUTH_PROVIDERS = [
|
||||||
|
"allauth.socialaccount.providers.github",
|
||||||
|
# "allauth.socialaccount.providers.google",
|
||||||
|
# "allauth.socialaccount.providers.telegram",
|
||||||
|
# "allauth.socialaccount.providers.yandex",
|
||||||
|
]
|
||||||
|
|
||||||
LOCAL_APPS = [
|
LOCAL_APPS = [
|
||||||
"akarpov.users",
|
"akarpov.users",
|
||||||
"akarpov.blog",
|
"akarpov.blog",
|
||||||
# Your stuff: custom apps go here
|
# Your stuff: custom apps go here
|
||||||
]
|
]
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
INSTALLED_APPS = (
|
||||||
|
DJANGO_APPS + THIRD_PARTY_APPS + HEALTH_CHECKS + ALL_AUTH_PROVIDERS + LOCAL_APPS
|
||||||
|
)
|
||||||
|
|
||||||
# MIGRATIONS
|
# MIGRATIONS
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -284,6 +306,7 @@
|
||||||
CELERY_TASK_SOFT_TIME_LIMIT = 60
|
CELERY_TASK_SOFT_TIME_LIMIT = 60
|
||||||
# https://docs.celeryq.dev/en/stable/userguide/configuration.html#beat-scheduler
|
# https://docs.celeryq.dev/en/stable/userguide/configuration.html#beat-scheduler
|
||||||
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"
|
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"
|
||||||
|
|
||||||
# django-allauth
|
# django-allauth
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
|
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
|
||||||
|
@ -291,6 +314,9 @@
|
||||||
ACCOUNT_AUTHENTICATION_METHOD = "username"
|
ACCOUNT_AUTHENTICATION_METHOD = "username"
|
||||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
ACCOUNT_EMAIL_REQUIRED = True
|
ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
|
||||||
|
ACCOUNT_LOGIN_ON_PASSWORD_RESET = True
|
||||||
|
SOCIALACCOUNT_EMAIL_VERIFICATION = False
|
||||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
@ -301,6 +327,23 @@
|
||||||
SOCIALACCOUNT_ADAPTER = "akarpov.users.adapters.SocialAccountAdapter"
|
SOCIALACCOUNT_ADAPTER = "akarpov.users.adapters.SocialAccountAdapter"
|
||||||
# https://django-allauth.readthedocs.io/en/latest/forms.html
|
# https://django-allauth.readthedocs.io/en/latest/forms.html
|
||||||
SOCIALACCOUNT_FORMS = {"signup": "akarpov.users.forms.UserSocialSignupForm"}
|
SOCIALACCOUNT_FORMS = {"signup": "akarpov.users.forms.UserSocialSignupForm"}
|
||||||
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
|
"github": {
|
||||||
|
"SCOPE": [
|
||||||
|
"user",
|
||||||
|
"read:org",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"google": {
|
||||||
|
"SCOPE": [
|
||||||
|
"profile",
|
||||||
|
"email",
|
||||||
|
],
|
||||||
|
"AUTH_PARAMS": {
|
||||||
|
"access_type": "online",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
# django-rest-framework
|
# django-rest-framework
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
path(
|
path(
|
||||||
"about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
|
"about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
|
||||||
),
|
),
|
||||||
|
path("health/", include("health_check.urls")),
|
||||||
# Django Admin, use {% url 'admin:index' %}
|
# Django Admin, use {% url 'admin:index' %}
|
||||||
path(settings.ADMIN_URL, admin.site.urls),
|
path(settings.ADMIN_URL, admin.site.urls),
|
||||||
# User management
|
# User management
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pytz==2022.6 # https://github.com/stub42/pytz
|
pytz==2022.6 # https://github.com/stub42/pytz
|
||||||
|
psutil==5.9.4
|
||||||
python-slugify==6.1.2 # https://github.com/un33k/python-slugify
|
python-slugify==6.1.2 # https://github.com/un33k/python-slugify
|
||||||
Pillow==9.3.0 # https://github.com/python-pillow/Pillow
|
Pillow==9.3.0 # https://github.com/python-pillow/Pillow
|
||||||
argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi
|
argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi
|
||||||
|
@ -12,6 +13,7 @@ flower==1.2.0 # https://github.com/mher/flower
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
django==4.0.8 # pyup: < 4.1 # https://www.djangoproject.com/
|
django==4.0.8 # pyup: < 4.1 # https://www.djangoproject.com/
|
||||||
|
django-health-check==3.17.0
|
||||||
django-environ==0.9.0 # https://github.com/joke2k/django-environ
|
django-environ==0.9.0 # https://github.com/joke2k/django-environ
|
||||||
django-model-utils==4.2.0 # https://github.com/jazzband/django-model-utils
|
django-model-utils==4.2.0 # https://github.com/jazzband/django-model-utils
|
||||||
django-allauth==0.51.0 # https://github.com/pennersr/django-allauth
|
django-allauth==0.51.0 # https://github.com/pennersr/django-allauth
|
||||||
|
|
Loading…
Reference in New Issue
Block a user