Exemplo n.º 1
0
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
Exemplo n.º 2
0
class Group(db.Model):
    """
        An abstract, digital representation of a group of
        :py:class:`Accounts <piko.db.model.Account>` or
        :py:class:`Persons <piko.db.model.Persons>`.

        A group can be a simple collection of Accounts, such that
        a family of "John" and "Jane" can be grouped as the
        "Doe Family".

        Both "John" and "Jane" would have accounts.

    """
    __tablename__ = 'group'

    #: An automatically generated unique integer ID
    uuid = db.Column(db.Integer, primary_key=True)

    _name = db.Column(db.String(255), nullable=False)

    #: List of :py:class:`piko.db.model.Account` records associated
    #: with this :py:class:`Group`.
    accounts = db.relationship('Account')

    #: List of :py:class:`piko.db.model.Person` records associated
    #: with this :py:class:`Group`.
    persons = db.relationship('Person',
                              secondary="person_groups",
                              cascade="delete")

    def __init__(self, *args, **kwargs):
        """
            When a group is created, assign it a unique integer ID.
        """
        super(Group, self).__init__(*args, **kwargs)

        uuid = generate_id()

        if db.session.query(Group).get(uuid) is not None:
            while db.session.query(Group).get(uuid) is not None:
                uuid = generate_id()

        self.uuid = uuid

    @property
    def name(self):
        """
            A display name such as 'Doe Family' or 'Example, Inc.'.
        """

        return self._name

    @name.setter
    def name(self, value):
        self._name = value
Exemplo n.º 3
0
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 []
Exemplo n.º 4
0
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 []
Exemplo n.º 5
0
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')
Exemplo n.º 6
0
Arquivo: vote.py Projeto: kanarip/piko
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')
Exemplo n.º 7
0
class Customer(db.Model):
    """
        A customer.
    """
    __tablename__ = 'candlepin_customer'

    #: The unique ID for the customer. Note that this ID cannot be predictable,
    #: and is generated.
    uuid = db.Column(db.Integer, primary_key=True)

    #: A name for the customer. Think along the lines of *Example, Inc.*.
    name = db.Column(db.String(128))

    #: The date and time this customer was created -- GMT.
    created = db.Column(db.DateTime, default=datetime.utcnow)

    modified = db.Column(db.DateTime, default=datetime.utcnow)
    """
        The date and time this customer was modified -- GMT.

        .. NOTE::

            It should probably be linked with a 'whodunnit', and it should
            also be updated (automatically).
    """

    entitlements = db.relationship('Entitlement')

    systems = db.relationship('System')

    def __init__(self, *args, **kwargs):
        """
            Upon creation of the customer entity, ensure that the integer ID
            assigned to it is random as well as unique without trial and error.
        """
        super(Customer, self).__init__(*args, **kwargs)

        uuid = generate_id()

        if db.session.query(Customer).get(uuid) is not None:
            while db.session.query(Customer).get(uuid) is not None:
                uuid = generate_id()

        self.uuid = uuid
Exemplo n.º 8
0
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
Exemplo n.º 9
0
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
Exemplo n.º 10
0
Arquivo: view.py Projeto: kanarip/piko
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')
Exemplo n.º 11
0
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()
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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
Exemplo n.º 14
0
 def person(cls):
     # pylint: disable=no-member
     return db.relationship('Person', backref=cls.__name__.lower())
Exemplo n.º 15
0
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()
Exemplo n.º 16
0
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
        }
Exemplo n.º 17
0
 def account(cls):
     # pylint: disable=no-member
     return db.relationship('Account', backref=cls.__name__.lower())
Exemplo n.º 18
0
class Person(db.Model):
    """
        An abstract, digital representation of a human being.
    """
    __tablename__ = 'person'

    #: A unique integer ID.
    uuid = db.Column(db.Integer, primary_key=True)

    #: The name for this person.
    name = db.Column(db.String(255), nullable=False)

    #: This should be considered a token as well, but is most commonly
    #: recognized as the first token.
    password_hash = db.Column(db.String(128))

    #: Fast preference setting.
    locale = db.Column(db.String(64), default='en')

    #: Fast preference setting.
    timezone = db.Column(db.String(64), default='UTC')

    #: Groups this person is a member of.
    groups = db.relationship('Group',
                             secondary="person_groups",
                             cascade="delete")

    def __init__(self, *args, **kwargs):
        super(Person, self).__init__(*args, **kwargs)

        if 'uuid' in kwargs:
            uuid = kwargs['uuid']
        else:
            uuid = generate_id()

        while db.session.query(Person).get(uuid) is not None:
            uuid = generate_id()

        self.uuid = uuid

    @hybrid_property
    def accounts(self):
        """
            List of accounts associated with this Person.
        """
        return self._accounts().all()

    @hybrid_property
    def group_accounts(self):
        """
            List of Accounts associated with Groups associated with
            this Person.
        """
        groups = []
        for group in self.groups:
            groups.append(group)

        return groups

    @property
    def password(self):
        """
            Proxy getting the password.
        """
        raise AttributeError("password cannot be read")

    @password.setter
    def password(self, password):
        """
            Set a new passord.
        """
        # pylint: disable=no-value-for-parameter
        self.password_hash = generate_password_hash(password)

        change = Change(object_name=self.__class__.__name__,
                        object_id=self.uuid,
                        attribute_name='password',
                        value_from='****',
                        value_to='****')

        db.session.add(change)

    @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):
        """
            Return a list of second factors.
        """
        factors = []

        factors.extend(
            db.session.query(HOTPToken).filter_by(person_id=self.uuid,
                                                  confirmed=True).all())

        factors.extend(
            db.session.query(TANToken).filter_by(person_id=self.uuid,
                                                 confirmed=True).all())

        factors.extend(
            db.session.query(TOTPToken).filter_by(person_id=self.uuid,
                                                  confirmed=True).all())

        return factors

    def verify_password(self, password, transaction=None):
        """
            Verify the password.
        """
        if transaction is None:
            # pylint: disable=no-value-for-parameter
            result = check_password_hash(self.password_hash, password)

            from .accountlogin import AccountLogin

            db.session.add(AccountLogin(person_id=self.uuid, success=result))
            db.session.commit()

            return result

        else:
            task = check_password_hash.delay(self.password_hash, password)
            transaction.task_id = task.id
            db.session.commit()
            return task.id

    def _accounts(self):
        """
            Return the Query object for Accounts associated with this
            Person.
        """
        from .account import Account

        return db.session.query(Account).filter_by(person_id=self.uuid)

    def to_dict(self):
        """
            Return a dictionary presentation of this object.
        """
        groups = self.groups

        group_accounts = []

        for group in groups:
            if len(group.accounts) > 1:
                for account in group.accounts:
                    group_accounts.append(account.name)

        return {
            'locale': self.locale,
            'groups': [x.name for x in self.groups],
            # pylint: disable=not-an-iterable
            'accounts': [x.name for x in self.accounts],
            'group_accounts': group_accounts
        }