dashwood.net -

Ryan Stefan's Micro Blog

Flask Permission

Nov 292018

I've been digging into the code of this flask boilerplate and I finally found how views are changed based on different user permissions. They just use {% if current_user.is_admin() %} in Jinja2 in the page_macros.html

    {% if current_user.is_admin() %}
       <button class="ui button start-edit">
        Edit
       </button>
       <button class="ui primary button end-edit">
        Save
       </button>
    {% endif %}

Okay so I hit a snag in the bitwise/hex permission function, but I finally figured out what was happening. The & bitwise operator basically results in whatever is true in binary in both instances. Then you just compare it to the permission and it should be the same.  For example, CAN_LIKE or 00000010 and AUTHOR or 00001111 both have 00000010 in them so that's what it will result in if you do (CAN_LIKE & AUTHOR). Here's the full code:

CAN_LIKE = 0x01 # 00000001
CAN_FLAG = 0x02 # 00000010
CAN_COMMENT = 0x04 # 00000100
CAN_POST = 0x08 # 00001000
CAN_EDIT = 0x10 # 00010000
CAN_APPROVE = 0x20 # 00100000
CAN_REMOVE = 0x40 # 01000000

GENERAL = (CAN_LIKE | CAN_FLAG | CAN_COMMENT) # 00000111
AUTHOR = (CAN_LIKE | CAN_FLAG | CAN_COMMENT | CAN_POST) # 00001111
EDITOR = (CAN_LIKE | CAN_FLAG | CAN_COMMENT | CAN_POST | CAN_EDIT | CAN_APPROVE) # 00111111
ADMINISTER = (CAN_LIKE | CAN_FLAG | CAN_COMMENT | CAN_POST | CAN_EDIT | CAN_APPROVE | CAN_REMOVE) # 01111111

def can(role, perm):
    return (role & perm) == perm

# ---- Tests ----

# (self.role.permissions & permissions) == permissions

actions = {
'like': CAN_LIKE,
'flag': CAN_FLAG,
'comment': CAN_COMMENT,
'post': CAN_POST,
'edit': CAN_EDIT,
'approve': CAN_APPROVE,
'remove': CAN_REMOVE
 }

roles = {
'User': GENERAL,
'Author': AUTHOR,
'Editor': EDITOR,
'Admin': ADMINISTER
}

for action in actions:
    for role in roles:
        if can(roles[role], actions[action]):
        	print('{} can {}'.format(role, action))
        else:
        	print('{} can not {}'.format(role, action))

'''
User can like
Author can like
Editor can like
Admin can like
User can flag
Author can flag
Editor can flag
Admin can flag
User can comment
Author can comment
Editor can comment
Admin can comment
User can not post
Author can post
Editor can post
Admin can post
User can not edit
Author can not edit
Editor can edit
Admin can edit
User can not approve
Author can not approve
Editor can approve
Admin can approve
User can not remove
Author can not remove
Editor can not remove
Admin can remove
'''

Object Oriented Flask: An Overdue Update

Nov 262018

I was on vacation for a while, thus my daily blog suffered some... neglect. However, I did do a lot of coding during this time on Review Mill. I've begun refactoring my database completely using an open source tool called Visual Alchemist. It needs to be updated so that it works with the most recent SQLalchemy version, but it does put everything in classes and makes it really easy to visualize the entire database to a project. 

undefined

Now, armed with proper object oriented pythonic database classes, I'm applying this database to a skeleton flask project with a user system. The one I found is called Flask Base and seems to have a very cutting edge development style using blueprints and all kinds of optimization features. Here are some of the perks to Flask Base:

  • Blueprints
  • User and permissions management
  • Flask-SQLAlchemy for databases
  • Flask-WTF for forms
  • Flask-Assets for asset management and SCSS compilation
  • Flask-Mail for sending emails
  • gzip compression
  • Redis Queue for handling asynchronous tasks
  • ZXCVBN password strength checker
  • CKEditor for editing pages

It is a bit of a headache reading through all of the code so that I understand how it works, but at least I actually do understand it for once and it will help me build my app with the proper techniques and structures.

 

Here's some of the modified SQLAlchemy code:

class Amazon_Product(db.Model):
    __tablename__ = "amazon_products"
    asin = db.Column(db.Text(15), primary_key=True, unique=True)
    category = db.Column(db.Text(255))
    category_path = db.Column(db.Text(255))
    company = db.Column(db.Text(255))
    rating = db.Column(db.Float)
    num_reviews = db.Column(db.Integer)
    prod_desc = db.Column(db.Text(255))
    img_path = db.Column(db.Text(255))
    img_url = db.Column(db.Text(255))
    price = db.Column(db.Text(255))
    url = db.Column(db.Text(255))

    review_meta = db.relationship("Review_Meta")
    milled_reviews = db.relationship("Milled_Reviews")
    comments = db.relationship("Comment")
    tags = db.relationship("Prod_Tag")