OAuth: Add app type (is_clientside)

This commit is contained in:
rubenwardy 2023-11-07 23:06:22 +00:00
parent f74931633c
commit 9b0f84bac5
5 changed files with 52 additions and 2 deletions

@ -22,7 +22,7 @@ from flask import Blueprint, render_template, redirect, url_for, request, jsonif
from flask_babel import lazy_gettext, gettext from flask_babel import lazy_gettext, gettext
from flask_login import current_user, login_required from flask_login import current_user, login_required
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, URLField from wtforms import StringField, SubmitField, URLField, SelectField
from wtforms.validators import InputRequired, Length, Optional from wtforms.validators import InputRequired, Length, Optional
from app import csrf from app import csrf
@ -167,6 +167,10 @@ class OAuthClientForm(FlaskForm):
title = StringField(lazy_gettext("Title"), [InputRequired(), Length(5, 30)]) title = StringField(lazy_gettext("Title"), [InputRequired(), Length(5, 30)])
description = StringField(lazy_gettext("Description"), [Optional()]) description = StringField(lazy_gettext("Description"), [Optional()])
redirect_url = URLField(lazy_gettext("Redirect URL"), [InputRequired(), Length(5, 123)]) redirect_url = URLField(lazy_gettext("Redirect URL"), [InputRequired(), Length(5, 123)])
app_type = SelectField(lazy_gettext("App Type"), [InputRequired()], choices=[
("server", "Server-side (client_secret is kept safe)"),
("client", "Client-side (client_secret is visible to all users)"),
], coerce=lambda x: x)
submit = SubmitField(lazy_gettext("Save")) submit = SubmitField(lazy_gettext("Save"))
@ -186,6 +190,7 @@ def create_edit_client(username, id_=None):
abort(404) abort(404)
form = OAuthClientForm(formdata=request.form, obj=client) form = OAuthClientForm(formdata=request.form, obj=client)
if form.validate_on_submit(): if form.validate_on_submit():
if is_new: if is_new:
client = OAuthClient() client = OAuthClient()

@ -55,6 +55,7 @@ class Collection(db.Model):
long_description = db.Column(db.UnicodeText, nullable=True) long_description = db.Column(db.UnicodeText, nullable=True)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
private = db.Column(db.Boolean, nullable=False, default=False) private = db.Column(db.Boolean, nullable=False, default=False)
pinned = db.Column(db.Boolean, nullable=False, default=False)
packages = db.relationship("Package", secondary=CollectionPackage.__table__, backref="collections") packages = db.relationship("Package", secondary=CollectionPackage.__table__, backref="collections")
items = db.relationship("CollectionPackage", back_populates="collection", order_by=db.asc("order"), items = db.relationship("CollectionPackage", back_populates="collection", order_by=db.asc("order"),

@ -560,6 +560,7 @@ class OAuthClient(db.Model):
redirect_url = db.Column(db.String(128), nullable=False) redirect_url = db.Column(db.String(128), nullable=False)
approved = db.Column(db.Boolean, nullable=False, default=False) approved = db.Column(db.Boolean, nullable=False, default=False)
verified = db.Column(db.Boolean, nullable=False, default=False) verified = db.Column(db.Boolean, nullable=False, default=False)
is_clientside = 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")
@ -567,3 +568,11 @@ class OAuthClient(db.Model):
tokens = db.relationship("APIToken", back_populates="client", lazy="dynamic", cascade="all, delete, delete-orphan") tokens = db.relationship("APIToken", back_populates="client", lazy="dynamic", cascade="all, delete, delete-orphan")
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
def get_app_type(self):
return "client" if self.is_clientside else "server"
def set_app_type(self, value):
self.is_clientside = value == "client"
app_type = property(get_app_type, set_app_type)

@ -47,7 +47,9 @@
<label class="form-label" for="client_secret">client_secret</label> <label class="form-label" for="client_secret">client_secret</label>
<input class="form-control" type="text" id="client_secret" name="client_secret" value="{{ client.secret }}" readonly> <input class="form-control" type="text" id="client_secret" name="client_secret" value="{{ client.secret }}" readonly>
<p class="form-text text-muted"> <p class="form-text text-muted">
{{ _("Keep the secret safe") }} {% if not client.is_clientside %}
{{ _("You must keep the secret safe. If you are unable, set the app type to 'client-side'.") }}
{% endif %}
</p> </p>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -65,6 +67,7 @@
{{ render_field(form.title) }} {{ render_field(form.title) }}
{{ render_field(form.description, hint=_("Shown to users when you request access to their account")) }} {{ render_field(form.description, hint=_("Shown to users when you request access to their account")) }}
{{ render_field(form.redirect_url) }} {{ render_field(form.redirect_url) }}
{{ render_field(form.app_type, hint=_("Where will you store your client_secret?")) }}
{{ render_submit_field(form.submit) }} {{ render_submit_field(form.submit) }}
</form> </form>

@ -0,0 +1,32 @@
"""empty message
Revision ID: 7828535fe339
Revises: 52cf6746f255
Create Date: 2023-11-07 22:51:39.450652
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '7828535fe339'
down_revision = '52cf6746f255'
branch_labels = None
depends_on = None
def upgrade():
with op.batch_alter_table('collection', schema=None) as batch_op:
batch_op.add_column(sa.Column('pinned', sa.Boolean(), nullable=False, server_default="false"))
with op.batch_alter_table('oauth_client', schema=None) as batch_op:
batch_op.add_column(sa.Column('is_clientside', sa.Boolean(), nullable=False, server_default="false"))
def downgrade():
with op.batch_alter_table('oauth_client', schema=None) as batch_op:
batch_op.drop_column('is_clientside')
with op.batch_alter_table('collection', schema=None) as batch_op:
batch_op.drop_column('pinned')