From 83081ad7e488c44757e43ff40e83458a2e1451ed Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 1 Mar 2016 22:47:53 +0100 Subject: begin integration of the new architecture --- src/web/models/__init__.py | 8 ++----- src/web/models/article.py | 18 ++------------- src/web/models/category.py | 16 ++++++++++--- src/web/models/feed.py | 22 ++---------------- src/web/models/right_mixin.py | 54 +++++++++++++++++++++++++++++++++++++++++++ src/web/models/user.py | 16 ++++++------- 6 files changed, 80 insertions(+), 54 deletions(-) create mode 100644 src/web/models/right_mixin.py (limited to 'src/web/models') diff --git a/src/web/models/__init__.py b/src/web/models/__init__.py index d9489dbb..7c50cab3 100644 --- a/src/web/models/__init__.py +++ b/src/web/models/__init__.py @@ -88,17 +88,13 @@ def db_create(db): "Will create the database from conf parameters." db.create_all() - role_admin = Role(name="admin") - role_user = Role(name="user") - user1 = User(nickname="admin", email=os.environ.get("ADMIN_EMAIL", "root@jarr.localhost"), pwdhash=generate_password_hash( os.environ.get("ADMIN_PASSWORD", "password")), - enabled=True) - user1.roles.extend([role_admin, role_user]) + is_admin=True) db.session.add(user1) db.session.commit() - return role_admin, role_user + return user1 diff --git a/src/web/models/article.py b/src/web/models/article.py index 1fee7096..d3c0bed2 100644 --- a/src/web/models/article.py +++ b/src/web/models/article.py @@ -29,9 +29,10 @@ __license__ = "GPLv3" from bootstrap import db from datetime import datetime from sqlalchemy import asc, desc +from web.models.right_mixin import RightMixin -class Article(db.Model): +class Article(db.Model, RightMixin): "Represent an article from a feed." id = db.Column(db.Integer(), primary_key=True) entry_id = db.Column(db.String()) @@ -68,18 +69,3 @@ class Article(db.Model): return "" % (self.id, self.entry_id, self.title, self.date, self.retrieved_date) - - def dump(self): - return {"id": self.id, - "user_id": self.user_id, - "entry_id": self.entry_id, - "title": self.title, - "link": self.link, - "content": self.content, - "readed": self.readed, - "like": self.like, - "date": self.date, - "updated_date": self.updated_date, - "retrieved_date": self.retrieved_date, - "feed_id": self.feed_id, - "category_id": self.category_id} diff --git a/src/web/models/category.py b/src/web/models/category.py index 78054809..c35db52e 100644 --- a/src/web/models/category.py +++ b/src/web/models/category.py @@ -1,11 +1,21 @@ from bootstrap import db +from sqlalchemy import Index +from web.models.right_mixin import RightMixin -class Category(db.Model): +class Category(db.Model, RightMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String()) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) - def dump(self): - return {key: getattr(self, key) for key in ('id', 'name', 'user_id')} + idx_category_uid = Index('user_id') + + # api whitelists + @staticmethod + def _fields_base_read(): + return {'id', 'user_id'} + + @staticmethod + def _fields_base_write(): + return {'name'} diff --git a/src/web/models/feed.py b/src/web/models/feed.py index cb78f7ad..ba9255e9 100644 --- a/src/web/models/feed.py +++ b/src/web/models/feed.py @@ -29,9 +29,10 @@ __license__ = "GPLv3" from bootstrap import db from datetime import datetime from sqlalchemy import desc +from web.models.right_mixin import RightMixin -class Feed(db.Model): +class Feed(db.Model, RightMixin): """ Represent a feed. """ @@ -63,22 +64,3 @@ class Feed(db.Model): def __repr__(self): return '' % (self.title) - - def dump(self): - return {"id": self.id, - "user_id": self.user_id, - "category_id": self.category_id, - "title": self.title, - "description": self.description, - "link": self.link, - "site_link": self.site_link, - "etag": self.etag, - "enabled": self.enabled, - "filters": self.filters, - "icon_url": self.icon_url, - "error_count": self.error_count, - "last_error": self.last_error, - "created_date": self.created_date, - "last_modified": self.last_modified, - "last_retrieved": self.last_retrieved, - "nb_articles": self.articles.count()} diff --git a/src/web/models/right_mixin.py b/src/web/models/right_mixin.py new file mode 100644 index 00000000..c4d92008 --- /dev/null +++ b/src/web/models/right_mixin.py @@ -0,0 +1,54 @@ +class RightMixin: + + @staticmethod + def _fields_base_write(): + return {} + + @staticmethod + def _fields_base_read(): + return {'id'} + + @staticmethod + def _fields_api_write(): + return {} + + @staticmethod + def _fields_api_read(): + return {'id'} + + @classmethod + def fields_base_write(cls): + return cls._fields_base_write() + + @classmethod + def fields_base_read(cls): + return cls._fields_base_write().union(cls._fields_base_read()) + + @classmethod + def fields_api_write(cls): + return cls.fields_base_write().union(cls._fields_api_write()) + + @classmethod + def fields_api_read(cls): + return cls.fields_base_read().union(cls._fields_api_read()) + + def __getitem__(self, key): + if not hasattr(self, '__dump__'): + self.__dump__ = {} + return self.__dump__.get(key) + + def __setitem__(self, key, value): + if not hasattr(self, '__dump__'): + self.__dump__ = {} + self.__dump__[key] = value + + def dump(self, role='admin'): + if role == 'admin': + dico = {k: getattr(self, k) for k in self.__table__.columns.keys()} + elif role == 'api': + dico = {k: getattr(self, k) for k in self.fields_api_read()} + else: + dico = {k: getattr(self, k) for k in self.fields_base_read()} + if hasattr(self, '__dump__'): + dico.update(self.__dump__) + return dico diff --git a/src/web/models/user.py b/src/web/models/user.py index 1a276f7e..133901a5 100644 --- a/src/web/models/user.py +++ b/src/web/models/user.py @@ -34,9 +34,10 @@ from werkzeug import check_password_hash from flask.ext.login import UserMixin from bootstrap import db +from web.models.right_mixin import RightMixin -class User(db.Model, UserMixin): +class User(db.Model, UserMixin, RightMixin): """ Represent a user. """ @@ -44,14 +45,17 @@ class User(db.Model, UserMixin): nickname = db.Column(db.String(), unique=True) email = db.Column(db.String(254), index=True, unique=True) pwdhash = db.Column(db.String()) - roles = db.relationship('Role', backref='user', lazy='dynamic') - enabled = db.Column(db.Boolean(), default=False) date_created = db.Column(db.DateTime(), default=datetime.now) last_seen = db.Column(db.DateTime(), default=datetime.now) feeds = db.relationship('Feed', backref='subscriber', lazy='dynamic', cascade='all,delete-orphan') refresh_rate = db.Column(db.Integer, default=60) # in minutes + # user rights + is_active = db.Column(db.Boolean(), default=True) + is_admin = db.Column(db.Boolean(), default=False) + is_api = db.Column(db.Boolean(), default=False) + @staticmethod def make_valid_nickname(nickname): return re.sub('[^a-zA-Z0-9_\.]', '', nickname) @@ -68,12 +72,6 @@ class User(db.Model, UserMixin): """ return check_password_hash(self.pwdhash, password) - def is_admin(self): - """ - Return True if the user has administrator rights. - """ - return "admin" in [role.name for role in self.roles] - def __eq__(self, other): return self.id == other.id -- cgit