This is an automated email from the git hooks/post-receive script.
clime pushed a commit to branch private_tables
in repository copr/copr.
commit 607b07503f9e860f05ce6b8a854fa19b48650133
Author: clime <clime(a)redhat.com>
AuthorDate: Mon Dec 3 12:53:52 2018 +0100
[frontend] private tables for user and copr
---
...2bde564_separate_private_stuff_into_private_.py | 47 +++++++
...d580c625_copy_private_data_to_private_tables.py | 26 ++++
.../coprs_frontend/coprs/logic/packages_logic.py | 2 +-
frontend/coprs_frontend/coprs/logic/users_logic.py | 4 +-
frontend/coprs_frontend/coprs/models.py | 149 ++++++++++++++++++---
5 files changed, 207 insertions(+), 21 deletions(-)
diff --git
a/frontend/coprs_frontend/alembic/schema/versions/29c352bde564_separate_private_stuff_into_private_.py
b/frontend/coprs_frontend/alembic/schema/versions/29c352bde564_separate_private_stuff_into_private_.py
new file mode 100644
index 0000000..b0132fc
--- /dev/null
+++
b/frontend/coprs_frontend/alembic/schema/versions/29c352bde564_separate_private_stuff_into_private_.py
@@ -0,0 +1,47 @@
+"""separate private stuff into private tables by schema
+
+Revision ID: 29c352bde564
+Revises: 6fed8655d074
+Create Date: 2018-12-03 12:55:34.810037
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '29c352bde564'
+down_revision = '6fed8655d074'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.create_table('user_private',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('mail', sa.String(length=150), nullable=False),
+ sa.Column('timezone', sa.String(length=50), nullable=True),
+ sa.Column('api_login', sa.String(length=40), nullable=False),
+ sa.Column('api_token', sa.String(length=40), nullable=False),
+ sa.Column('api_token_expiration', sa.Date(), nullable=False),
+ sa.Column('user_id', sa.Integer(), nullable=False),
+ sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_index(op.f('ix_user_private_user_id'), 'user_private',
['user_id'], unique=True)
+ op.create_table('copr_private',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('webhook_secret', sa.String(length=100), nullable=True),
+ sa.Column('scm_api_auth_json', sa.Text(), nullable=True),
+ sa.Column('copr_id', sa.Integer(), nullable=False),
+ sa.ForeignKeyConstraint(['copr_id'], ['copr.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_index('copr_private_webhook_secret', 'copr_private',
['webhook_secret'], unique=False)
+ op.create_index(op.f('ix_copr_private_copr_id'), 'copr_private',
['copr_id'], unique=True)
+
+
+def downgrade():
+ op.drop_index(op.f('ix_copr_private_copr_id'),
table_name='copr_private')
+ op.drop_index('copr_private_webhook_secret',
table_name='copr_private')
+ op.drop_table('copr_private')
+ op.drop_index(op.f('ix_user_private_user_id'),
table_name='user_private')
+ op.drop_table('user_private')
diff --git
a/frontend/coprs_frontend/alembic/schema/versions/7723d580c625_copy_private_data_to_private_tables.py
b/frontend/coprs_frontend/alembic/schema/versions/7723d580c625_copy_private_data_to_private_tables.py
new file mode 100644
index 0000000..5c266eb
--- /dev/null
+++
b/frontend/coprs_frontend/alembic/schema/versions/7723d580c625_copy_private_data_to_private_tables.py
@@ -0,0 +1,26 @@
+"""copy private data to private tables
+
+Revision ID: 7723d580c625
+Revises: 29c352bde564
+Create Date: 2018-12-03 13:49:15.501999
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '7723d580c625'
+down_revision = '29c352bde564'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ session = sa.orm.sessionmaker(bind=op.get_bind())()
+ session.execute("""INSERT INTO copr_private(webhook_secret,
scm_api_auth_json, copr_id)
+ (select webhook_secret, scm_api_auth_json, id from copr) ON CONFLICT
DO NOTHING;""")
+ session.execute("""INSERT INTO user_private(mail, timezone, api_login,
api_token, api_token_expiration, user_id)
+ (select mail, timezone, api_login, api_token, api_token_expiration,
id from \"user\") ON CONFLICT DO NOTHING;""")
+
+def downgrade():
+ # no downgrade
+ pass
diff --git a/frontend/coprs_frontend/coprs/logic/packages_logic.py
b/frontend/coprs_frontend/coprs/logic/packages_logic.py
index 8199c42..84e5ee4 100644
--- a/frontend/coprs_frontend/coprs/logic/packages_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/packages_logic.py
@@ -145,7 +145,7 @@ WHERE package.copr_dir_id = :copr_dir_id;
clone_url_stripped = re.sub(r'(\.git)?/*$', '', clone_url)
packages = (models.Package.query.join(models.Copr)
- .filter(models.Copr.webhook_secret == webhook_secret)
+ .filter(models.CoprPrivate.webhook_secret == webhook_secret)
.filter(models.Package.source_type ==
helpers.BuildSourceEnum("scm"))
.filter(models.Package.copr_id == copr_id)
.filter(models.Package.webhook_rebuild == true())
diff --git a/frontend/coprs_frontend/coprs/logic/users_logic.py
b/frontend/coprs_frontend/coprs/logic/users_logic.py
index 6fc898d..05b6698 100644
--- a/frontend/coprs_frontend/coprs/logic/users_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/users_logic.py
@@ -3,7 +3,7 @@ from coprs import exceptions
from flask import url_for
from coprs import app, db
-from coprs.models import User, Group
+from coprs.models import User, Group, UserPrivate
from coprs.helpers import copr_url
from sqlalchemy import update
@@ -16,7 +16,7 @@ class UsersLogic(object):
@classmethod
def get_by_api_login(cls, login):
- return User.query.filter(User.api_login == login)
+ return User.query.join(UserPrivate).filter(UserPrivate.api_login == login)
@classmethod
def raise_if_cant_update_copr(cls, user, copr, message):
diff --git a/frontend/coprs_frontend/coprs/models.py
b/frontend/coprs_frontend/coprs/models.py
index df5ff79..39c730f 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -31,22 +31,38 @@ class CoprSearchRelatedData(object):
raise "Not Implemented"
-class User(db.Model, helpers.Serializer):
+class UserPrivate(db.Model, helpers.Serializer):
"""
- Represents user of the copr frontend
+ Records all the private information for a user.
"""
-
id = db.Column(db.Integer, primary_key=True)
- # unique username
- username = db.Column(db.String(100), nullable=False, unique=True)
-
# email
mail = db.Column(db.String(150), nullable=False)
# optional timezone
timezone = db.Column(db.String(50), nullable=True)
+ # stuff for the cli interface
+ api_login = db.Column(db.String(40), nullable=False, default="abc")
+ api_token = db.Column(db.String(40), nullable=False, default="abc")
+ api_token_expiration = db.Column(
+ db.Date, nullable=False, default=datetime.date(2000, 1, 1))
+
+ user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True,
nullable=False)
+ user = db.relationship("User", back_populates="private")
+
+
+class User(db.Model, helpers.Serializer):
+ """
+ Represents user of the copr frontend
+ """
+
+ id = db.Column(db.Integer, primary_key=True)
+
+ # unique username
+ username = db.Column(db.String(100), nullable=False, unique=True)
+
# is this user proven? proven users can modify builder memory and
# timeout for single builds
proven = db.Column(db.Boolean, default=False)
@@ -57,21 +73,72 @@ class User(db.Model, helpers.Serializer):
# can this user behave as someone else?
proxy = db.Column(db.Boolean, default=False)
- # stuff for the cli interface
- api_login = db.Column(db.String(40), nullable=False, default="abc")
- api_token = db.Column(db.String(40), nullable=False, default="abc")
- api_token_expiration = db.Column(
- db.Date, nullable=False, default=datetime.date(2000, 1, 1))
-
# list of groups as retrieved from openid
openid_groups = db.Column(JSONEncodedDict)
+ # private info
+ private = db.relationship("UserPrivate", uselist=False,
back_populates="user")
+
+ def set_private(self, attr, value):
+ if not self.private:
+ self.private = UserPrivate()
+ setattr(self.private, attr, value)
+
+ @property
+ def mail(self):
+ if self.private:
+ return self.private.mail
+ return None
+
+ @property
+ def timezone(self):
+ if self.private:
+ return self.private.timezone
+ return None
+
+ @property
+ def api_login(self):
+ if self.private:
+ return self.private.api_login
+ return None
+
+ @property
+ def api_token(self):
+ if self.private:
+ return self.private.api_token
+ return None
+
+ @property
+ def api_token_expiration(self):
+ if self.private:
+ return self.private.api_token_expiration
+ return None
+
+ @mail.setter
+ def mail(self, value):
+ self.set_private("mail", value)
+
+ @timezone.setter
+ def timezone(self, value):
+ self.set_private("timezone", value)
+
+ @api_login.setter
+ def api_login(self, value):
+ self.set_private("api_login", value)
+
+ @api_token.setter
+ def api_token(self, value):
+ self.set_private("api_token", value)
+
+ @api_token_expiration.setter
+ def api_token_expiration(self, value):
+ self.set_private("api_token_expiration", value)
+
@property
def name(self):
"""
Return the short username of the user, e.g. bkabrda
"""
-
return self.username
def permissions_for_copr(self, copr):
@@ -179,9 +246,31 @@ class User(db.Model, helpers.Serializer):
return ""
+class CoprPrivate(db.Model, helpers.Serializer):
+ """
+ Records all the private information for a copr.
+ """
+
+ __table_args__ = (
+ db.Index('copr_private_webhook_secret', 'webhook_secret'),
+ )
+
+ id = db.Column(db.Integer, primary_key=True)
+
+ # a secret to be used for webhooks authentication
+ webhook_secret = db.Column(db.String(100))
+
+ # remote Git sites auth info
+ scm_api_auth_json = db.Column(db.Text)
+
+ # copr relation
+ copr_id = db.Column(db.Integer, db.ForeignKey("copr.id"), index=True,
nullable=False)
+ copr = db.relationship("Copr", back_populates="private")
+
+
class Copr(db.Model, helpers.Serializer, CoprSearchRelatedData):
"""
- Represents a single copr (private repo with builds, mock chroots, etc.).
+ Represents a single copr (personal repo with builds, mock chroots, etc.).
"""
__table_args__ = (
@@ -217,9 +306,6 @@ class Copr(db.Model, helpers.Serializer, CoprSearchRelatedData):
forked_from_id = db.Column(db.Integer, db.ForeignKey("copr.id"))
forked_from = db.relationship("Copr", remote_side=id,
backref=db.backref("forks"))
- # a secret to be used for webhooks authentication
- webhook_secret = db.Column(db.String(100))
-
# enable networking for the builds by default
build_enable_net = db.Column(db.Boolean, default=True,
server_default="1", nullable=False)
@@ -244,12 +330,39 @@ class Copr(db.Model, helpers.Serializer, CoprSearchRelatedData):
# scm integration properties
scm_repo_url = db.Column(db.Text)
scm_api_type = db.Column(db.Text)
- scm_api_auth_json = db.Column(db.Text)
+
+ # private info
+ private = db.relationship("CoprPrivate", uselist=False,
back_populates="copr")
__mapper_args__ = {
"order_by": created_on.desc()
}
+ def set_private(self, attr, value):
+ if not self.private:
+ self.private = CoprPrivate()
+ setattr(self.private, attr, value)
+
+ @property
+ def webhook_secret(self):
+ if self.private:
+ return self.private.webhook_secret
+ return None
+
+ @property
+ def scm_api_auth_json(self):
+ if self.private:
+ return self.private.scm_api_auth_json
+ return None
+
+ @webhook_secret.setter
+ def webhook_secret(self, value):
+ self.set_private("webhook_secret", value)
+
+ @scm_api_auth_json.setter
+ def scm_api_auth_json(self, value):
+ self.set_private("scm_api_auth_json", value)
+
@property
def main_dir(self):
"""
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.