diff --git a/common/api.py b/common/api.py index ea37d559..09b58b64 100644 --- a/common/api.py +++ b/common/api.py @@ -18,7 +18,7 @@ class OAuthAccessTokenAuth(HttpBearer): _logger.debug("API auth: no access token or user not authenticated") return False request_scopes = [] - if request.method.upper() in ["GET", "HEAD", "OPTIONS"]: + if request.method in ["GET", "HEAD", "OPTIONS"]: request_scopes = ["read"] else: request_scopes = ["write"] diff --git a/developer/migrations/0001_initial.py b/developer/migrations/0001_initial.py index 45828108..eb0d70ca 100644 --- a/developer/migrations/0001_initial.py +++ b/developer/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.19 on 2023-06-28 02:44 +# Generated by Django 3.2.19 on 2023-06-28 05:09 from django.conf import settings import django.core.validators @@ -10,7 +10,6 @@ import oauth2_provider.models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -19,27 +18,111 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Application', + name="Application", fields=[ - ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('client_id', models.CharField(db_index=True, default=oauth2_provider.generators.generate_client_id, max_length=100, unique=True)), - ('redirect_uris', models.TextField(blank=True, help_text='Allowed URIs list, space separated')), - ('post_logout_redirect_uris', models.TextField(blank=True, help_text='Allowed Post Logout URIs list, space separated')), - ('client_type', models.CharField(choices=[('confidential', 'Confidential'), ('public', 'Public')], max_length=32)), - ('authorization_grant_type', models.CharField(choices=[('authorization-code', 'Authorization code'), ('implicit', 'Implicit'), ('password', 'Resource owner password-based'), ('client-credentials', 'Client credentials'), ('openid-hybrid', 'OpenID connect hybrid')], max_length=32)), - ('client_secret', oauth2_provider.models.ClientSecretField(blank=True, db_index=True, default=oauth2_provider.generators.generate_client_secret, help_text='Hashed on Save. Copy it now if this is a new secret.', max_length=255)), - ('skip_authorization', models.BooleanField(default=False)), - ('created', models.DateTimeField(auto_now_add=True)), - ('updated', models.DateTimeField(auto_now=True)), - ('algorithm', models.CharField(blank=True, choices=[('', 'No OIDC support'), ('RS256', 'RSA with SHA-2 256'), ('HS256', 'HMAC with SHA-2 256')], default='', max_length=5)), - ('name', models.CharField(max_length=255, unique=True, validators=[django.core.validators.RegexValidator(message='至少两个字,不可包含普通文字和-_.以外的字符', regex='^\\w[\\w_\\-. ]*\\w$')])), - ('descrpition', markdownx.models.MarkdownxField(blank=True, default='')), - ('url', models.URLField(blank=True, null=True)), - ('is_official', models.BooleanField(default=False)), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='developer_application', to=settings.AUTH_USER_MODEL)), + ("id", models.BigAutoField(primary_key=True, serialize=False)), + ( + "client_id", + models.CharField( + db_index=True, + default=oauth2_provider.generators.generate_client_id, + max_length=100, + unique=True, + ), + ), + ( + "redirect_uris", + models.TextField( + blank=True, help_text="Allowed URIs list, space separated" + ), + ), + ( + "post_logout_redirect_uris", + models.TextField( + blank=True, + help_text="Allowed Post Logout URIs list, space separated", + ), + ), + ( + "client_type", + models.CharField( + choices=[ + ("confidential", "Confidential"), + ("public", "Public"), + ], + max_length=32, + ), + ), + ( + "authorization_grant_type", + models.CharField( + choices=[ + ("authorization-code", "Authorization code"), + ("implicit", "Implicit"), + ("password", "Resource owner password-based"), + ("client-credentials", "Client credentials"), + ("openid-hybrid", "OpenID connect hybrid"), + ], + max_length=32, + ), + ), + ( + "client_secret", + oauth2_provider.models.ClientSecretField( + blank=True, + db_index=True, + default=oauth2_provider.generators.generate_client_secret, + help_text="Hashed on Save. Copy it now if this is a new secret.", + max_length=255, + ), + ), + ("skip_authorization", models.BooleanField(default=False)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), + ( + "algorithm", + models.CharField( + blank=True, + choices=[ + ("", "No OIDC support"), + ("RS256", "RSA with SHA-2 256"), + ("HS256", "HMAC with SHA-2 256"), + ], + default="", + max_length=5, + ), + ), + ( + "name", + models.CharField( + max_length=255, + validators=[ + django.core.validators.RegexValidator( + message="minimum two characters, words and -_. only, no special characters", + regex="^\\w[\\w_\\-. ]*\\w$", + ) + ], + ), + ), + ( + "description", + markdownx.models.MarkdownxField(blank=True, default=""), + ), + ("url", models.URLField(blank=True, null=True)), + ("is_official", models.BooleanField(default=False)), + ( + "user", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="developer_application", + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), ] diff --git a/developer/models.py b/developer/models.py index 4c595171..be11d5a5 100644 --- a/developer/models.py +++ b/developer/models.py @@ -1,7 +1,9 @@ from django.db import models from django.core.validators import RegexValidator +from django.utils.translation import gettext_lazy as _ from oauth2_provider.models import AbstractApplication from markdownx.models import MarkdownxField +from journal.renderers import render_md class Application(AbstractApplication): @@ -11,11 +13,16 @@ class Application(AbstractApplication): validators=[ RegexValidator( regex=r"^\w[\w_\-. ]*\w$", - message="至少两个字,不可包含普通文字和-_.以外的字符", + message=_( + "minimum two characters, words and -_. only, no special characters" + ), ), ], - unique=True, ) - descrpition = MarkdownxField(default="", blank=True) + description = MarkdownxField(default="", blank=True) url = models.URLField(null=True, blank=True) is_official = models.BooleanField(default=False) + unique_together = [["user", "name"]] + + def description_html(self): + return render_md(self.description) diff --git a/developer/templates/oauth2_provider/application_detail.html b/developer/templates/oauth2_provider/application_detail.html new file mode 100644 index 00000000..951e8511 --- /dev/null +++ b/developer/templates/oauth2_provider/application_detail.html @@ -0,0 +1,52 @@ +{% extends "oauth2_provider/base.html" %} +{% load i18n %} +{% block content %} +
+ {% trans "Client ID" %} +
+ ++ {% trans "Client Secret" %} +
+ ++ {% trans "URL" %} +
+{{ application.url | default:"" | urlize }}
++ {% trans "Description" %} +
+{{ application.description_html|safe }}
++ {% trans "Redirect Uris" %} +
+ +- {{ application.name }} 是 {{ application.user.mastodon_username }} 创建和维护的应用程序, 并非来自{{ site_name }}官方。 + {{ application.name }} 是由 {{ application.user.mastodon_username }} 创建和维护的应用程序。 + {{ site_name }}无法保证其安全性和有效性,请自行验证确认后再授权。
{% endif %} {% if application.url %}应用网址: {{ application.url | urlize }}{% endif %} +{{ application.description_html|safe }}
{% for field in form %} {% if field.is_hidden %}{{ field }}{% endif %} {% endfor %} diff --git a/developer/urls.py b/developer/urls.py index 987e7412..89d93ab8 100644 --- a/developer/urls.py +++ b/developer/urls.py @@ -44,7 +44,7 @@ _urlpatterns += [ ), re_path( r"^developer/applications/register/$", - oauth2_views.ApplicationRegistration.as_view(), + ApplicationRegistration.as_view(), name="register", ), re_path( @@ -59,7 +59,7 @@ _urlpatterns += [ ), re_path( r"^developer/applications/(?P+ 查看已授权的应用程序 +
+