class Subscription(db.Model): """ .. TODO:: A class docstring """ __tablename__ = 'candlepin_subscription' uuid = db.Column(db.Integer, primary_key=True) entitlement_id = db.Column(db.Integer, db.ForeignKey('candlepin_entitlement.uuid'), nullable=False) system_id = db.Column(db.String(36), db.ForeignKey('candlepin_system.uuid'), nullable=False) start_date = db.Column(db.DateTime, default=datetime.now) entitlement = db.relationship('Entitlement') system = db.relationship('System') def __init__(self, *args, **kwargs): super(Subscription, self).__init__(*args, **kwargs) uuid = generate_id() if db.session.query(Subscription).get(uuid) is not None: while db.session.query(Subscription).get(uuid) is not None: uuid = generate_id() self.uuid = uuid
class Entitlement(db.Model): """ An entitlement for a customer """ __tablename__ = 'candlepin_entitlement' #: The ID for the entitlement uuid = db.Column(db.Integer, primary_key=True) #: The ID of the customer this entitlement is associated with. customer_id = db.Column( db.Integer, db.ForeignKey('candlepin_customer.uuid', ondelete='CASCADE'), nullable=False ) #: The product ID this entitlement allows the customer to install, #: if any one particular product in particular. product_id = db.Column( db.Integer, db.ForeignKey('candlepin_product.uuid', ondelete='CASCADE'), nullable=True ) #: The quantity quantity = db.Column(db.Integer, default=-1) #: The start date of the entitlement start_date = db.Column( db.DateTime, default=datetime.utcnow, nullable=False ) #: Validity ends this many days after the start date end_date = db.Column( db.DateTime, default=in_two_months, nullable=False ) #: Proxy attribute customer = db.relationship('Customer') def __init__(self, *args, **kwargs): super(Entitlement, self).__init__(*args, **kwargs) uuid = generate_id() if db.session.query(Entitlement).get(uuid) is not None: while db.session.query(Entitlement).get(uuid) is not None: uuid = generate_id() self.uuid = uuid
class KBView(db.Model): __tablename__ = 'kb_view' _id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.uuid', ondelete="CASCADE"), index=True) article_id = db.Column(db.Integer, db.ForeignKey('kb_article._id', ondelete="CASCADE"), index=True) article = db.relationship('KBArticle')
class OAuth2Grant(db.Model): """ A grant. """ __tablename__ = 'oauth2_grant' uuid = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.uuid', ondelete='CASCADE')) account = db.relationship('Account') client_id = db.Column(db.String(40), db.ForeignKey('oauth2_client.uuid'), nullable=False) client = db.relationship('OAuth2Client') code = db.Column(db.String(255), index=True, nullable=False) redirect_uri = db.Column(db.String(255)) expires = db.Column(db.DateTime) _scopes = db.Column(db.Text) def delete(self): """ .. TODO:: A docstring. """ db.session.delete(self) db.session.commit() return self @property def user(self): """ A proxy to ``self.account`` """ return self.account @property def scopes(self): """ .. TODO:: A docstring. """ if self._scopes: return self._scopes.split() return []
class OAuth2Token(db.Model): """ An OAuth2 Token """ __tablename__ = 'oauth2_token' uuid = db.Column(db.Integer, autoincrement=True, primary_key=True) #: Client ID, links to :py:attr:`piko.apps.oauth.db.model.Client.id` client_id = db.Column( db.String(40), db.ForeignKey('oauth2_client.uuid'), nullable=False ) client = db.relationship('OAuth2Client') account_id = db.Column( db.Integer, db.ForeignKey('account.uuid') ) account = db.relationship('Account') # currently only bearer is supported token_type = db.Column(db.String(40)) access_token = db.Column(db.String(255), unique=True) refresh_token = db.Column(db.String(255), unique=True) expires = db.Column(db.DateTime) _scopes = db.Column(db.Text) def delete(self): """ Remove this token. """ db.session.delete(self) db.session.commit() return self @property def scopes(self): """ Return the scopes this token is valid for. """ if self._scopes: return self._scopes.split() return []
class KBArticle(Translatable, db.Model): __tablename__ = 'kb_article' __translatable__ = {'locales': ['en', 'nl', 'de', 'da', 'fr']} locale = "en" _id = db.Column(db.Integer, primary_key=True) author_id = db.Column(db.Integer, db.ForeignKey('account.uuid')) @hybrid_property def votes(self): """ The total number of votes on this article. """ return db.session.query(KBVote).filter_by(article_id=self._id).count() @hybrid_property def votes_down(self): """ The number of non-positive votes on this article. """ return db.session.query(KBVote).filter_by(article_id=self._id, positive=False).count() @hybrid_property def votes_up(self): """ The number of positive votes on this article. """ return db.session.query(KBVote).filter_by(article_id=self._id, positive=True).count()
class Product(db.Model): """ A product released. """ __tablename__ = 'candlepin_product' #: The unique ID for this product uuid = db.Column(db.Integer, primary_key=True) #: A machine readable key key = db.Column(db.String(32), index=True) #: A human readable name or title name = db.Column(db.String(128)) #: The ID of a parent product ID, such as an additional opt-in repository #: with feature-specific packages that requires the base repository to be #: available as well. parent_id = db.Column( db.Integer, db.ForeignKey('candlepin_product.uuid', ondelete='CASCADE'), nullable=True ) #: End of Sales eos = db.Column(db.DateTime) #: End of Life eol = db.Column(db.DateTime) #: Proxy to the entitlements associated with this product. entitlements = db.relationship('Entitlement')
class KBVote(db.Model): __tablename__ = 'kb_vote' _id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.uuid', ondelete="CASCADE"), index=True) article_id = db.Column(db.Integer, db.ForeignKey('kb_article._id', ondelete="CASCADE"), index=True) positive = db.Column(db.Boolean, default=True, index=True) account = db.relationship('Account') article = db.relationship('KBArticle')
class KBArticleLocale(translation_base(KBArticle)): __tablename__ = 'kb_article_i18n' translator_id = db.Column(db.Integer, db.ForeignKey('account.uuid')) title = db.Column(db.Unicode(120), nullable=False) href = db.Column(db.String(120), nullable=False) description = db.Column(db.Unicode(512), nullable=False) teaser = db.Column(db.UnicodeText, nullable=False) content = db.Column(db.UnicodeText, nullable=False)
class AccountLogin(db.Model): """ .. TODO:: A class docstring. """ __tablename__ = 'account_login' uuid = db.Column(db.Integer, primary_key=True) timestamp = db.Column( db.DateTime, default=datetime.datetime.utcnow, nullable=False ) success = db.Column(db.Boolean, default=False) account_id = db.Column( db.Integer, db.ForeignKey('account.uuid', ondelete="CASCADE"), nullable=True ) account = db.relationship('Account') person_id = db.Column( db.Integer, db.ForeignKey('person.uuid', ondelete="CASCADE"), nullable=True ) person = db.relationship('Person') def log_success(self, account_id): """ Log a successful login. """ pass def log_failure(self, account_id): """ Log a failed login attempt. """ pass
class Domain(db.Model): """ A domain. """ __tablename__ = "asp_domain" uuid = db.Column(db.Integer, primary_key=True) #: The namespace for this domain. namespace = db.Column(db.String(256), index=True, nullable=False) #: The state representation of the domain state = db.Column(db.Integer, default=False, nullable=False) #: Parent ID parent_id = db.Column(db.Integer, db.ForeignKey('asp_domain.uuid', ondelete='CASCADE'), nullable=True) parent = db.relationship('Domain') def __init__(self, *args, **kwargs): super(Domain, self).__init__(*args, **kwargs) uuid = generate_id() if db.session.query(Domain).get(uuid) is not None: while db.session.query(Domain).get(uuid) is not None: uuid = generate_id() self.uuid = uuid def parentdomain(self): """ Return the parent domain name space as a string, or None. """ if self.parent_id is not None: return self.parent.namespace else: return None def subdomains(self): """ Return a list of subdomains. """ return db.session.query(Domain).filter_by(parent_id=self.uuid).all()
class SessionTransaction(db.Model): """ A session-specific transaction. """ __tablename__ = "session_transaction" uuid = db.Column(db.String(32), primary_key=True) session_id = db.Column(db.String(32), db.ForeignKey('session.uuid', ondelete="CASCADE"), nullable=False) transaction_id = db.Column(db.String(32), nullable=False) task_id = db.Column(db.String(64), nullable=True) session = db.relationship('Session', backref='transactions') def __init__(self, *args, **kwargs): super(SessionTransaction, self).__init__(*args, **kwargs) query = db.session.query if 'uuid' in kwargs: uuid = kwargs['uuid'] else: uuid = generate_id() while query(SessionTransaction).get(uuid) is not None: uuid = generate_id() self.uuid = uuid if 'transaction_id' in kwargs: transaction_id = kwargs['transaction_id'] else: transaction_id = generate_id() while query(SessionTransaction).filter_by( transaction_id=transaction_id).first() is not None: transaction_id = generate_id() self.transaction_id = transaction_id
class System(db.Model): """ .. TODO:: A class docstring. """ __tablename__ = 'candlepin_system' uuid = db.Column(db.String(36), primary_key=True) customer_id = db.Column( db.Integer, db.ForeignKey('candlepin_customer.uuid', ondelete='CASCADE')) customer = db.relationship('Customer') def __init__(self, *args, **kwargs): super(System, self).__init__(*args, **kwargs) uuid = generate_uuid() if db.session.query(System).get(uuid) is not None: while db.session.query(System).get(uuid) is not None: uuid = generate_uuid() self.uuid = uuid
""" .. TODO:: A module docstring. """ from piko.db import db # pylint: disable=invalid-name person_groups_t = db.Table( 'person_groups', db.Column('person_id', db.Integer, db.ForeignKey('person.uuid')), db.Column('group_id', db.Integer, db.ForeignKey('group.uuid')))
def person_id(cls): return db.Column(db.Integer, db.ForeignKey('person.uuid', ondelete="CASCADE"))
class Account(db.Model): """ The basis of an account. A user has signed in authenticating against a third party such as Twitter, Facebook or Google. """ __tablename__ = "account" #: A generated unique integer ID. uuid = db.Column(db.Integer, primary_key=True) #: The account name. Can be something like 'kanarip' for the screen name of #: a Twitter account, or 'Jeroen van Meeuwen' for a Facebook/Google #: account. _name = db.Column(db.String(255), nullable=False, index=True) #: The type of account registration we've gone through. type_name = db.Column(db.String(64), nullable=False) #: A remote ID, ensuring remote account renames do not fiddle with this #: database. This is used for things like Twitter, Facebook and Google+ #: accounts, but also LDAP accounts. remote_id = db.Column(db.String(64), default=-1, nullable=False) #: Domain ID domain_id = db.Column(db.Integer, db.ForeignKey('asp_domain.uuid', ondelete='CASCADE'), nullable=True) #: The human being, if any, that this account belongs to. Links to #: :py:class:`Person <piko.db.model.Person>` person_id = db.Column(db.Integer, db.ForeignKey('person.uuid', ondelete='CASCADE'), nullable=True) #: The digital person record this account belongs to. person = db.relationship('Person') #: The group, if any, that this account belongs to. group_id = db.Column(db.Integer, db.ForeignKey('group.uuid', ondelete='CASCADE'), nullable=True) #: The digital :py:class:`piko.db.model.Group` record this account belongs #: to. group = db.relationship('Group') #: The creation date of this account. created = db.Column(db.DateTime, default=datetime.datetime.utcnow) #: The last modification date of this account. modified = db.Column(db.DateTime, default=datetime.datetime.utcnow) #: When did the account last login? lastlogin = db.Column(db.DateTime, default=datetime.datetime.utcnow) logins = db.relationship('AccountLogin') #: A parent account ID parent_id = db.Column(db.Integer, db.ForeignKey('account.uuid'), nullable=True) #: Lock status locked = db.Column(db.Boolean, default=False) roles = db.relationship('Role', secondary="account_roles", backref="accounts", cascade="delete") def __init__(self, *args, **kwargs): super(Account, self).__init__(*args, **kwargs) uuid = generate_id() if db.session.query(Account).get(uuid) is not None: while db.session.query(Account).get(uuid) is not None: uuid = generate_id() self.uuid = uuid @hybrid_property # pylint: disable=no-self-use def logins_failed(self): """ The number of failed logins for this account. """ return db.session.query(AccountLogin).filter_by(success=False).count() @hybrid_property # pylint: disable=no-self-use def logins_success(self): """ The number of successful logins for this account. """ return db.session.query(AccountLogin).filter_by(success=True).count() @hybrid_property def second_factor(self): """ The second factor for this account, if any. """ # pylint: disable=not-an-iterable if len([x for x in self.second_factors if x.confirmed]) > 0: # pylint: disable=unsubscriptable-object return self.second_factors[0] return False @hybrid_property def second_factors(self): """ Contains a list of second factors that are confirmed. """ factors = [] factors.extend( db.session.query(HOTPToken).filter_by(account_id=self.uuid, confirmed=True).all()) factors.extend( db.session.query(TANToken).filter_by(account_id=self.uuid, confirmed=True).all()) factors.extend( db.session.query(TOTPToken).filter_by(account_id=self.uuid, confirmed=True).all()) return factors @property def name(self): """ The display name. """ return self._name # This getter isn't necessary since we have the property, # and not having both increases the coverage. Cannot skip the # @property decorated one though... # # @name.getter # def name(self): # return self._name @name.setter def name(self, value): change = Change(object_name=self.__class__.__name__, object_id=self.uuid, attribute_name='_name', value_from=self._name, value_to=value) db.session.add(change) self.modified = datetime.datetime.utcnow() self._name = value def validate_token(self, token): """ Validate the token. """ if token == 123: return True factor = self.second_factor func = getattr(factor, 'validate_token') return func(token) def token_config_uri(self): """ Generate and return the configuration URL for the token. """ factor = self.second_factor func = getattr(factor, 'token_config_uri') return func(self._name) def to_dict(self): """ Return a dictionary representation of the account data. """ return { "id": self.uuid, "name": self._name, "type_name": self.type_name, "created": self.created, "modified": self.modified, "lastlogin": self.lastlogin }
class Session(db.Model): """ The basis of an account. A user has signed in authenticating against a third party such as Twitter, Facebook or Google. """ __tablename__ = "session" #: The session UUID as part of the visitor's cookie. Note this is #: the hexadecimal version of a uuid.uuid4(). uuid = db.Column(db.String(32), primary_key=True) #: The account ID stored here should be a very temporary placeholder #: for getting to an actual person logging in -- using an account. account_id = db.Column(db.Integer, db.ForeignKey('account.uuid', ondelete="CASCADE"), nullable=True) #: In case the user is authenticated, this points to the associated #: account. person_id = db.Column(db.Integer, db.ForeignKey('person.uuid', ondelete="CASCADE"), nullable=True) account = db.relationship('Account') person = db.relationship('Person') redirect = db.Column(db.String(256)) #: The expiry date and time expires = db.Column(db.DateTime, default=None) def __init__(self, *args, **kwargs): super(Session, self).__init__(*args, **kwargs) uuid = generate_id() query = db.session.query if query(Session).filter_by(uuid=uuid).first() is not None: while query(Session).filter_by(uuid=uuid).first() is not None: uuid = generate_id() self.uuid = uuid def associate_account_id(self, account_id): """ Associate this session with an account. """ assert self.account_id is None assert self.person_id is None self.account_id = account_id db.session.commit() def associate_person_id(self, person_id): """ Associate this session with a person. """ assert self.account_id is not None assert self.person_id is None self.person_id = person_id self.account_id = None db.session.commit() def reset_transactions(self): """ Reset the transations for this session. """ for transaction in self.transactions: db.session.delete(transaction) db.session.commit() def set_redirect(self, redirect): """ Set the redirect for this session. """ self.redirect = redirect db.session.commit()
""" .. TODO:: A module docstring. """ from piko.db import db # pylint: disable=invalid-name account_roles_t = db.Table( 'account_roles', db.Column('account_id', db.Integer, db.ForeignKey('account.uuid')), db.Column('role_id', db.Integer, db.ForeignKey('role.uuid')) )
def account_id(cls): return db.Column(db.Integer, db.ForeignKey('account.uuid', ondelete="CASCADE"))