diff --git a/app/blueprints/api/tokens.py b/app/blueprints/api/tokens.py index 032bd72d..ee23a19f 100644 --- a/app/blueprints/api/tokens.py +++ b/app/blueprints/api/tokens.py @@ -72,10 +72,8 @@ def create_edit_token(username, id=None): access_token = None if not is_new: token = APIToken.query.get(id) - if token is None: + if token is None or token.owner != user: abort(404) - elif token.owner != user: - abort(403) access_token = session.pop("token_" + str(token.id), None) diff --git a/app/blueprints/oauth/__init__.py b/app/blueprints/oauth/__init__.py index cae323fa..b115b581 100644 --- a/app/blueprints/oauth/__init__.py +++ b/app/blueprints/oauth/__init__.py @@ -27,7 +27,7 @@ from wtforms.validators import InputRequired, Length from app import csrf 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 bp = Blueprint("oauth", __name__) @@ -63,6 +63,9 @@ def oauth_start(): if client.redirect_url != redirect_uri: 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") if scope != "public": return "Unsupported scope, only public is supported", 400 @@ -189,6 +192,7 @@ def create_edit_client(username, id_=None): client.owner = user client.id = random_string(24) client.secret = random_string(32) + client.approved = current_user.rank.atLeast(UserRank.EDITOR) form.populate_obj(client) diff --git a/app/models/users.py b/app/models/users.py index bb2d9dd6..b27dbd39 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -559,9 +559,12 @@ class OAuthClient(db.Model): __tablename__ = "oauth_client" id = db.Column(db.String(24), primary_key=True) - title = db.Column(db.String(64), unique=True) - secret = db.Column(db.String(32)) - redirect_url = db.Column(db.String(128)) + title = db.Column(db.String(64), unique=True, nullable=False) + description = db.Column(db.String(300), nullable=True) + 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 = db.relationship("User", foreign_keys=[owner_id], back_populates="clients") diff --git a/app/templates/oauth/authorize.html b/app/templates/oauth/authorize.html index fecdfe02..4d34796a 100644 --- a/app/templates/oauth/authorize.html +++ b/app/templates/oauth/authorize.html @@ -28,9 +28,24 @@

+ {% if client.verified %} +
+
+ +
+
+

+ {{ _("Verified Application") }} +

+

+ {{ _("ContentDB trusts this application") }} +

+
+
+ {% endif %}
-
- +
+

@@ -57,4 +72,12 @@

+ {% if not client.approved %} + + {% endif %} {% endblock %} diff --git a/app/templates/oauth/create_edit.html b/app/templates/oauth/create_edit.html index a019d7ca..8a25ee97 100644 --- a/app/templates/oauth/create_edit.html +++ b/app/templates/oauth/create_edit.html @@ -21,6 +21,15 @@

{{ self.title() }}

{% if client %} + {% if not client.approved %} + + {% endif %} +
diff --git a/app/templates/oauth/list_clients.html b/app/templates/oauth/list_clients.html index 33c2d973..cccca3b9 100644 --- a/app/templates/oauth/list_clients.html +++ b/app/templates/oauth/list_clients.html @@ -12,6 +12,9 @@
{% for client in user.clients %} + {% if not client.approved %} + {{ _("Unpublished") }} + {% endif %} {{ client.title }} {% else %} diff --git a/migrations/versions/52cf6746f255_.py b/migrations/versions/52cf6746f255_.py new file mode 100644 index 00000000..b1b0966d --- /dev/null +++ b/migrations/versions/52cf6746f255_.py @@ -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')