Coverage for app / security / models.py: 88%

24 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-12-06 04:49 +0000

1""" 

2Defines database models and admin views for authentication and role management. 

3 

4This module includes models for users and roles, integrating with Flask-Security  

5and Flask-Admin for authentication and role-based access control. It also provides 

6a custom admin view enforcing restricted access to authorized administrators only. 

7 

8Classes: 

9 Role: Represents a user role in the application with specific permissions. 

10 User: Represents an application user with role associations and relationships. 

11 SecureModelView: A custom admin view with access restricted to 'admin' users. 

12""" 

13from flask_admin.contrib.sqla import ModelView 

14from flask_security import current_user 

15from flask_security.models import fsqla_v3 as fsqla 

16from sqlalchemy.orm import relationship, declared_attr 

17 

18from app import db 

19 

20# Define models 

21fsqla.FsModels.set_db_info(db) 

22 

23 

24class Role(db.Model, fsqla.FsRoleMixin): 

25 """ 

26 Represents the roles a user can have in the application. 

27 

28 Each role defines a set of permissions or access levels 

29 assigned to users for role-based authentication. 

30 """ 

31 

32 def __repr__(self) -> str: 

33 return f"{self.name}" 

34 

35 

36class User(db.Model, fsqla.FsUserMixin): 

37 """ 

38 Represents a user in the application with authentication and role information. 

39 

40 A user can have multiple relationships such as reading statuses and feedbacks, 

41 allowing association with various entities in the application. 

42 """ 

43 

44 @declared_attr 

45 def reading_statuses(self): 

46 """ 

47 Defines a property for accessing the reading statuses associated with the user. 

48 

49 The property is declared as a SQLAlchemy relationship, linking the current 

50 user to their respective reading statuses. This property facilitates 

51 bidirectional association and interaction between the user and the 

52 ReadingStatus model. 

53 

54 :return: A SQLAlchemy relationship object linking the user with their 

55 reading statuses. 

56 :rtype: sqlalchemy.orm.relationship 

57 """ 

58 return relationship("ReadingStatus", back_populates="user") 

59 

60 @declared_attr 

61 def feedbacks(self): 

62 """ 

63 Represents the relationship between the current model and the "Feedback" model. 

64 

65 This property defines a relationship, where the "Feedback" model is connected 

66 to the current model and can be accessed through the `user` attribute of 

67 "Feedback". It uses the SQLAlchemy `relationship` function to establish this 

68 link with bidirectional behavior. 

69 

70 :return: A SQLAlchemy relationship configured with "Feedback" as the related model. 

71 :rtype: sqlalchemy.orm.relationship 

72 """ 

73 return relationship("Feedback", back_populates="user") 

74 

75 # Relationship to tags owned by the user 

76 @declared_attr 

77 def tags(self): 

78 """ 

79 Provides a declared attribute for relationship with the 'List' model. 

80 

81 This attribute enables the establishment of a relationship between the current 

82 model and the 'List' model, defining how they are interconnected in the database 

83 or ORM (Object-Relational Mapping) structure. 

84 

85 :return: A SQLAlchemy relationship between this model and the 'List' model. 

86 :rtype: sqlalchemy.orm.relationship 

87 """ 

88 return relationship("Tag", back_populates="owner") 

89 

90 def __repr__(self) -> str: 

91 """ 

92 Provides a string representation of the instance for debugging 

93 and logging purposes. The returned string is a concise, 

94 format that includes the email attribute. 

95 

96 :return: A string representing the instance, primarily including 

97 the email attribute. 

98 :rtype: str 

99 """ 

100 return f"{self.email}" 

101 

102 

103class SecureModelView(ModelView): 

104 """ 

105 Custom model view that adds security measures by restricting access to administrators. 

106 

107 The view ensures only authenticated users with the 'admin' role can access 

108 the underlying functionality. 

109 """ 

110 

111 def is_accessible(self): 

112 """ 

113 Checks if the current user is authenticated and has the 'admin' role. 

114 

115 :return: True if the current user can access this view, otherwise False. 

116 :rtype: bool 

117 """ 

118 return current_user.is_authenticated and current_user.has_role('admin')