mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-10 06:57:34 +01:00
OAuth2: Add approval and verified apps
This commit is contained in:
parent
073dcf9517
commit
00f7dbb28d
@ -72,10 +72,8 @@ def create_edit_token(username, id=None):
|
|||||||
access_token = None
|
access_token = None
|
||||||
if not is_new:
|
if not is_new:
|
||||||
token = APIToken.query.get(id)
|
token = APIToken.query.get(id)
|
||||||
if token is None:
|
if token is None or token.owner != user:
|
||||||
abort(404)
|
abort(404)
|
||||||
elif token.owner != user:
|
|
||||||
abort(403)
|
|
||||||
|
|
||||||
access_token = session.pop("token_" + str(token.id), None)
|
access_token = session.pop("token_" + str(token.id), None)
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ from wtforms.validators import InputRequired, Length
|
|||||||
|
|
||||||
from app import csrf
|
from app import csrf
|
||||||
from app.blueprints.users.settings import get_setting_tabs
|
from app.blueprints.users.settings import get_setting_tabs
|
||||||
from app.models import db, OAuthClient, User, Permission, APIToken, AuditSeverity
|
from app.models import db, OAuthClient, User, Permission, APIToken, AuditSeverity, UserRank
|
||||||
from app.utils import random_string, add_audit_log
|
from app.utils import random_string, add_audit_log
|
||||||
|
|
||||||
bp = Blueprint("oauth", __name__)
|
bp = Blueprint("oauth", __name__)
|
||||||
@ -63,6 +63,9 @@ def oauth_start():
|
|||||||
if client.redirect_url != redirect_uri:
|
if client.redirect_url != redirect_uri:
|
||||||
return "redirect_uri does not match client", 400
|
return "redirect_uri does not match client", 400
|
||||||
|
|
||||||
|
if not client.approved and client.owner != current_user:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
scope = request.args.get("scope", "public")
|
scope = request.args.get("scope", "public")
|
||||||
if scope != "public":
|
if scope != "public":
|
||||||
return "Unsupported scope, only public is supported", 400
|
return "Unsupported scope, only public is supported", 400
|
||||||
@ -189,6 +192,7 @@ def create_edit_client(username, id_=None):
|
|||||||
client.owner = user
|
client.owner = user
|
||||||
client.id = random_string(24)
|
client.id = random_string(24)
|
||||||
client.secret = random_string(32)
|
client.secret = random_string(32)
|
||||||
|
client.approved = current_user.rank.atLeast(UserRank.EDITOR)
|
||||||
|
|
||||||
form.populate_obj(client)
|
form.populate_obj(client)
|
||||||
|
|
||||||
|
@ -559,9 +559,12 @@ class OAuthClient(db.Model):
|
|||||||
__tablename__ = "oauth_client"
|
__tablename__ = "oauth_client"
|
||||||
|
|
||||||
id = db.Column(db.String(24), primary_key=True)
|
id = db.Column(db.String(24), primary_key=True)
|
||||||
title = db.Column(db.String(64), unique=True)
|
title = db.Column(db.String(64), unique=True, nullable=False)
|
||||||
secret = db.Column(db.String(32))
|
description = db.Column(db.String(300), nullable=True)
|
||||||
redirect_url = db.Column(db.String(128))
|
secret = db.Column(db.String(32), nullable=False)
|
||||||
|
redirect_url = db.Column(db.String(128), nullable=False)
|
||||||
|
approved = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
verified = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||||
owner = db.relationship("User", foreign_keys=[owner_id], back_populates="clients")
|
owner = db.relationship("User", foreign_keys=[owner_id], back_populates="clients")
|
||||||
|
@ -28,9 +28,24 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if client.verified %}
|
||||||
|
<div class="row my-4 align-items-center">
|
||||||
|
<div class="col-2 text-center fs-3">
|
||||||
|
<i class="fas text-info fa-check-circle fa-xl"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<p class="my-0">
|
||||||
|
{{ _("Verified Application") }}
|
||||||
|
</p>
|
||||||
|
<p class="text-muted my-0">
|
||||||
|
{{ _("ContentDB trusts this application") }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="row my-4 align-items-center">
|
<div class="row my-4 align-items-center">
|
||||||
<div class="col-2 text-center">
|
<div class="col-2 text-center fs-3">
|
||||||
<i class="fas fa-globe fa-xl"></i>
|
<i class="fas fa-globe-europe"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="my-0">
|
<p class="my-0">
|
||||||
@ -57,4 +72,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</form>
|
</form>
|
||||||
|
{% if not client.approved %}
|
||||||
|
<aside class="alert alert-danger mt-5 w-50 mx-auto">
|
||||||
|
<h3 class="mt-0">{{ _("Application isn't approved yet") }}</h3>
|
||||||
|
<p class="mb-0">
|
||||||
|
{{ _("To allow users other than yourself to log in, you'll need to contact ContentDB staff and ask them to approve your app.") }}
|
||||||
|
</p>
|
||||||
|
</aside>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -21,6 +21,15 @@
|
|||||||
<h1 class="mt-0">{{ self.title() }}</h1>
|
<h1 class="mt-0">{{ self.title() }}</h1>
|
||||||
|
|
||||||
{% if client %}
|
{% if client %}
|
||||||
|
{% if not client.approved %}
|
||||||
|
<aside class="alert alert-info my-5">
|
||||||
|
<h3 class="mt-0">{{ _("Application isn't approved yet") }}</h3>
|
||||||
|
<p class="mb-0">
|
||||||
|
{{ _("To allow users other than yourself to log in, you'll need to contact ContentDB staff and ask them to approve your app.") }}
|
||||||
|
</p>
|
||||||
|
</aside>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<form class="card my-5" method="POST" action="{{ url_for("oauth.revoke_all", username=client.owner.username, id_=client.id) }}">
|
<form class="card my-5" method="POST" action="{{ url_for("oauth.revoke_all", username=client.owner.username, id_=client.id) }}">
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||||
<div class="card-body d-flex flex-row align-items-center">
|
<div class="card-body d-flex flex-row align-items-center">
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
{% for client in user.clients %}
|
{% for client in user.clients %}
|
||||||
<a class="list-group-item list-group-item-action" href="{{ url_for('oauth.create_edit_client', username=user.username, id_=client.id) }}">
|
<a class="list-group-item list-group-item-action" href="{{ url_for('oauth.create_edit_client', username=user.username, id_=client.id) }}">
|
||||||
|
{% if not client.approved %}
|
||||||
|
<span class="badge bg-warning float-end">{{ _("Unpublished") }}</span>
|
||||||
|
{% endif %}
|
||||||
{{ client.title }}
|
{{ client.title }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
39
migrations/versions/52cf6746f255_.py
Normal file
39
migrations/versions/52cf6746f255_.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 52cf6746f255
|
||||||
|
Revises: 9395ba96f853
|
||||||
|
Create Date: 2023-10-31 19:56:58.249938
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '52cf6746f255'
|
||||||
|
down_revision = '9395ba96f853'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
with op.batch_alter_table('oauth_client', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('description', sa.String(length=300), nullable=True))
|
||||||
|
batch_op.add_column(sa.Column('approved', sa.Boolean(), nullable=False, server_default="false"))
|
||||||
|
batch_op.add_column(sa.Column('verified', sa.Boolean(), nullable=False, server_default="false"))
|
||||||
|
batch_op.alter_column('title',
|
||||||
|
existing_type=sa.VARCHAR(length=64),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('secret',
|
||||||
|
existing_type=sa.VARCHAR(length=32),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('redirect_url',
|
||||||
|
existing_type=sa.VARCHAR(length=128),
|
||||||
|
nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
with op.batch_alter_table('oauth_client', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('verified')
|
||||||
|
batch_op.drop_column('approved')
|
||||||
|
batch_op.drop_column('description')
|
Loading…
Reference in New Issue
Block a user