From 2e5a2d96bfadfdac59a4a1fefe95ac1d851dd7b1 Mon Sep 17 00:00:00 2001 From: Deimos Date: Wed, 5 Aug 2020 15:25:00 -0600 Subject: [PATCH] Switch user permissions to use an enum Previously, there wasn't any defined list of which permissions were valid or not. You basically had to look through each model's __acl__ method to see what the possibilities were. Using an enum will be less convenient when adding new permissions or changing existing ones (since it will require a database migration), but it makes it much easier to see what the valid options are, and will prevent invalid permissions from being set up in the database. --- ...7ce2c4825_use_enum_for_user_permissions.py | 49 +++++++++++++++++++ tildes/tildes/enums.py | 22 +++++++++ tildes/tildes/models/user/user_permissions.py | 8 +-- 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 tildes/alembic/versions/28d7ce2c4825_use_enum_for_user_permissions.py diff --git a/tildes/alembic/versions/28d7ce2c4825_use_enum_for_user_permissions.py b/tildes/alembic/versions/28d7ce2c4825_use_enum_for_user_permissions.py new file mode 100644 index 0000000..dd0d100 --- /dev/null +++ b/tildes/alembic/versions/28d7ce2c4825_use_enum_for_user_permissions.py @@ -0,0 +1,49 @@ +"""Use enum for user permissions + +Revision ID: 28d7ce2c4825 +Revises: 82e9801eb2d6 +Create Date: 2020-08-05 20:32:51.047215 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "28d7ce2c4825" +down_revision = "82e9801eb2d6" +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute( + """ + create type userpermission as enum( + 'comment.remove', + 'comment.view_labels', + 'topic.edit_by_generic_user', + 'topic.edit_link', + 'topic.edit_title', + 'topic.lock', + 'topic.move', + 'topic.post', + 'topic.remove', + 'topic.tag', + 'user.ban', + 'user.view_removed_posts', + 'wiki.edit' + ) + """ + ) + op.execute( + """ + alter table user_permissions + alter column permission type userpermission using permission::userpermission + """ + ) + + +def downgrade(): + op.execute("alter table user_permissions alter column permission type text") + op.execute("drop type userpermission") diff --git a/tildes/tildes/enums.py b/tildes/tildes/enums.py index 0e184e9..756d930 100644 --- a/tildes/tildes/enums.py +++ b/tildes/tildes/enums.py @@ -290,6 +290,28 @@ class HTMLSanitizationContext(enum.Enum): USER_BIO = enum.auto() +# Enum for the possible user permissions +# (Using functional API for this one because the values aren't valid Python names) +UserPermission = enum.Enum( + "UserPermission", + [ + "comment.remove", + "comment.view_labels", + "topic.edit_by_generic_user", + "topic.edit_link", + "topic.edit_title", + "topic.lock", + "topic.move", + "topic.post", + "topic.remove", + "topic.tag", + "user.ban", + "user.view_removed_posts", + "wiki.edit", + ], +) + + class UserPermissionType(enum.Enum): """Enum for the types of user permissions.""" diff --git a/tildes/tildes/models/user/user_permissions.py b/tildes/tildes/models/user/user_permissions.py index 76665b4..fc7e76c 100644 --- a/tildes/tildes/models/user/user_permissions.py +++ b/tildes/tildes/models/user/user_permissions.py @@ -3,11 +3,11 @@ """Contains the UserPermissions class.""" -from sqlalchemy import Column, ForeignKey, Integer, Text +from sqlalchemy import Column, ForeignKey, Integer from sqlalchemy.dialects.postgresql import ENUM from sqlalchemy.orm import relationship -from tildes.enums import UserPermissionType +from tildes.enums import UserPermission, UserPermissionType from tildes.models import DatabaseModel from tildes.models.group import Group from tildes.models.user import User @@ -21,7 +21,7 @@ class UserPermissions(DatabaseModel): permission_id: int = Column(Integer, primary_key=True) user_id: int = Column(Integer, ForeignKey("users.user_id"), nullable=False) group_id: int = Column(Integer, ForeignKey("groups.group_id"), nullable=True) - permission: str = Column(Text, nullable=False) + permission: UserPermission = Column(ENUM(UserPermission), nullable=False) permission_type: UserPermissionType = Column( ENUM(UserPermissionType), nullable=False, server_default="ALLOW" ) @@ -50,6 +50,6 @@ class UserPermissions(DatabaseModel): if self.permission_type == UserPermissionType.DENY: principal += "!" - principal += self.permission + principal += str(self.permission.name) return principal