diff --git a/app/models/base.py b/app/models/base.py index f106ec5..f48e2ed 100644 --- a/app/models/base.py +++ b/app/models/base.py @@ -87,7 +87,7 @@ class MirrorList(AbstractConfiguration): if self.provider == "s3": return f"s3://{self.container}/{self.filename}" if self.provider == "http_post": - return self.container + return str(self.container) return "Unknown provider" @classmethod diff --git a/app/models/onions.py b/app/models/onions.py index 8de5740..06929f3 100644 --- a/app/models/onions.py +++ b/app/models/onions.py @@ -19,7 +19,6 @@ class Onion(AbstractConfiguration): group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False) domain_name = db.Column(db.String(255), nullable=False) - onion_name = db.Column(db.String(56), nullable=False, unique=True) onion_public_key = db.Column(db.LargeBinary, nullable=False) onion_private_key = db.Column(db.LargeBinary, nullable=False) @@ -30,7 +29,7 @@ class Onion(AbstractConfiguration): group = db.relationship("Group", back_populates="onions") @property - def calculated_onion_name(self): + def onion_name(self) -> str: p = self.onion_public_key[32:] h = hashlib.sha3_256() diff --git a/app/portal/onion.py b/app/portal/onion.py index 11b4a63..ad1e52c 100644 --- a/app/portal/onion.py +++ b/app/portal/onion.py @@ -4,9 +4,10 @@ from typing import Optional from flask import flash, redirect, url_for, render_template, Response, Blueprint from flask.typing import ResponseReturnValue from flask_wtf import FlaskForm -from flask_wtf.file import FileAllowed, FileRequired +from flask_wtf.file import FileRequired from sqlalchemy import exc -from wtforms import StringField, SelectField, SubmitField, FileField +from wtforms import StringField, SelectField, SubmitField +from flask_wtf.file import FileField from wtforms.validators import DataRequired from app.extensions import db @@ -19,8 +20,6 @@ bp = Blueprint("onion", __name__) class NewOnionForm(FlaskForm): # type: ignore domain_name = StringField('Domain Name', validators=[DataRequired()]) - # onion_name = StringField('Onion Name', validators=[DataRequired(), Length(min=56, max=56)], - # description="Onion service hostname, excluding the .onion suffix") description = StringField('Description', validators=[DataRequired()]) onion_private_key = FileField('Onion Private Key', validators=[FileRequired()]) onion_public_key = FileField('Onion Public Key', @@ -37,9 +36,6 @@ class NewOnionForm(FlaskForm): # type: ignore class EditOnionForm(FlaskForm): # type: ignore description = StringField('Description', validators=[DataRequired()]) group = SelectField('Group', validators=[DataRequired()]) - onion_private_key = FileField('Onion Private Key') - onion_public_key = FileField('Onion Public Key', - description="The onion hostname will be automatically calculated from the public key.") tls_private_key = FileField('TLS Private Key (PEM format)', description="If no file is submitted, the TLS key will remain unchanged.") tls_public_key = FileField('TLS Certificate (PEM format)', @@ -56,17 +52,16 @@ def onion_new(group_id: Optional[int] = None) -> ResponseReturnValue: onion = Onion() onion.group_id = form.group.data onion.domain_name = form.domain_name.data - # onion.onion_name = form.onion_name.data for at in [ "onion_private_key", "onion_public_key", "tls_private_key", "tls_public_key" ]: - print(f"testing {at}") - if form.__getattribute__(at).data is not None: - print(f"Setting {at}") - onion.__setattr__(at, form.__getattribute__(at).data.read()) + if form.__getattribute__(at).data is None: + flash(f"Failed to create new onion. {at} was not provided.", "danger") + return redirect(url_for("portal.onion.onion_list")) + onion.__setattr__(at, form.__getattribute__(at).data.read()) onion.description = form.description.data onion.created = datetime.utcnow() onion.updated = datetime.utcnow() @@ -99,14 +94,10 @@ def onion_edit(onion_id: int) -> ResponseReturnValue: onion.group_id = form.group.data onion.description = form.description.data for at in [ - "onion_private_key", - "onion_public_key", "tls_private_key", "tls_public_key" ]: - print(f"testing {at}") if form.__getattribute__(at).data is not None: - print(f"Setting {at}") onion.__setattr__(at, form.__getattribute__(at).data.read()) onion.updated = datetime.utcnow() try: @@ -138,7 +129,7 @@ def onion_destroy(onion_id: int) -> ResponseReturnValue: return view_lifecycle( header=f"Destroy onion service {onion.onion_name}", message=onion.description, - success_message="You will need to manually remove this from the EOTK configuration.", + success_message="Successfully removed onion service.", success_view="portal.onion.onion_list", section="onion", resource=onion, diff --git a/migrations/versions/6a59928efeb7_remove_onion_key_column.py b/migrations/versions/6a59928efeb7_remove_onion_key_column.py new file mode 100644 index 0000000..74f2c99 --- /dev/null +++ b/migrations/versions/6a59928efeb7_remove_onion_key_column.py @@ -0,0 +1,58 @@ +"""remove onion key column + +Revision ID: 6a59928efeb7 +Revises: c4ce00f86823 +Create Date: 2022-11-09 15:16:10.116405 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '6a59928efeb7' +down_revision = 'c4ce00f86823' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('onion', schema=None) as batch_op: + batch_op.alter_column('onion_public_key', + existing_type=postgresql.BYTEA(), + nullable=False) + batch_op.alter_column('onion_private_key', + existing_type=postgresql.BYTEA(), + nullable=False) + batch_op.alter_column('tls_public_key', + existing_type=postgresql.BYTEA(), + nullable=False) + batch_op.alter_column('tls_private_key', + existing_type=postgresql.BYTEA(), + nullable=False) + batch_op.drop_constraint('uq_onion_onion_name', type_='unique') + batch_op.drop_column('onion_name') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('onion', schema=None) as batch_op: + batch_op.add_column(sa.Column('onion_name', sa.VARCHAR(length=56), autoincrement=False, nullable=False)) + batch_op.create_unique_constraint('uq_onion_onion_name', ['onion_name']) + batch_op.alter_column('tls_private_key', + existing_type=postgresql.BYTEA(), + nullable=True) + batch_op.alter_column('tls_public_key', + existing_type=postgresql.BYTEA(), + nullable=True) + batch_op.alter_column('onion_private_key', + existing_type=postgresql.BYTEA(), + nullable=True) + batch_op.alter_column('onion_public_key', + existing_type=postgresql.BYTEA(), + nullable=True) + + # ### end Alembic commands ###