Coverage for postrfp/ref/exceptions.py: 0%

36 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-22 21:34 +0000

1""" 

2Permission-specific exception classes for the reference content management system. 

3 

4These exceptions provide enhanced error reporting with detailed context about 

5why permission checks failed and what users can do to resolve access issues. 

6""" 

7 

8from typing import Any 

9from postrfp.shared.exceptions import AuthorizationFailure 

10 

11 

12class PermissionDeniedError(AuthorizationFailure): 

13 """ 

14 Enhanced authorization failure with detailed permission context. 

15 

16 This exception is designed to work with the existing framework's error 

17 handling while providing rich context about permission failures. 

18 """ 

19 

20 def __init__( 

21 self, 

22 permission_result=None, 

23 resource_type: str | None = None, 

24 resource_id: Any = None, 

25 resource_title: str | None = None, 

26 attempted_action: str | None = None, 

27 user_org_id: str | None = None, 

28 **kwargs, 

29 ): 

30 self.permission_result = permission_result 

31 self.resource_type = resource_type 

32 self.resource_id = resource_id 

33 self.resource_title = resource_title 

34 self.attempted_action = attempted_action 

35 self.user_org_id = user_org_id 

36 

37 # Build the main error message 

38 if permission_result: 

39 message = permission_result.get_user_friendly_message() 

40 # Set errors for framework compatibility 

41 errors = permission_result.to_structured_error() 

42 else: 

43 message = kwargs.get("message", self.default_message) 

44 errors = kwargs.get("errors", None) 

45 

46 # Enhance message with resource context if available 

47 if resource_title and attempted_action: 

48 message = f"Cannot {attempted_action} {resource_type or 'resource'} '{resource_title}': {message}" 

49 

50 super().__init__(message=message, errors=errors, **kwargs) 

51 

52 def __str__(self) -> str: 

53 """Return user-friendly error message.""" 

54 if self.permission_result: 

55 return self.permission_result.get_user_friendly_message() 

56 return super().__str__() 

57 

58 

59class ContentPermissionDeniedError(PermissionDeniedError): 

60 """ 

61 Specific exception for content permission failures. 

62 

63 Provides content-specific error messaging and suggested actions. 

64 """ 

65 

66 def __init__( 

67 self, 

68 content=None, 

69 permission_result=None, 

70 attempted_action: str | None = None, 

71 user_org_id: str | None = None, 

72 **kwargs, 

73 ): 

74 # Extract content details if content object provided 

75 resource_title = content.title if content else kwargs.get("resource_title") 

76 resource_id = content.id if content else kwargs.get("resource_id") 

77 

78 super().__init__( 

79 permission_result=permission_result, 

80 resource_type="Content", 

81 resource_id=resource_id, 

82 resource_title=resource_title, 

83 attempted_action=attempted_action, 

84 user_org_id=user_org_id, 

85 **kwargs, 

86 ) 

87 

88 

89class SubjectPermissionDeniedError(PermissionDeniedError): 

90 """ 

91 Specific exception for subject permission failures. 

92 

93 Provides subject-specific error messaging and suggested actions. 

94 """ 

95 

96 def __init__( 

97 self, 

98 subject=None, 

99 permission_result=None, 

100 attempted_action: str | None = None, 

101 user_org_id: str | None = None, 

102 **kwargs, 

103 ): 

104 # Extract subject details if subject object provided 

105 resource_title = subject.name if subject else kwargs.get("resource_title") 

106 resource_id = subject.id if subject else kwargs.get("resource_id") 

107 

108 super().__init__( 

109 permission_result=permission_result, 

110 resource_type="Subject", 

111 resource_id=resource_id, 

112 resource_title=resource_title, 

113 attempted_action=attempted_action, 

114 user_org_id=user_org_id, 

115 **kwargs, 

116 ) 

117 

118 

119def create_content_permission_error( 

120 content, permission_result, attempted_action: str, user_org_id: str 

121) -> ContentPermissionDeniedError: 

122 """ 

123 Factory function to create content permission errors with proper context. 

124 

125 This function generates appropriate suggested actions based on the 

126 permission failure reason and content characteristics. 

127 """ 

128 return ContentPermissionDeniedError( 

129 content=content, 

130 permission_result=permission_result, 

131 attempted_action=attempted_action, 

132 user_org_id=user_org_id, 

133 ) 

134 

135 

136def create_subject_permission_error( 

137 subject, permission_result, attempted_action: str, user_org_id: str 

138) -> SubjectPermissionDeniedError: 

139 """ 

140 Factory function to create subject permission errors with proper context. 

141 """ 

142 return SubjectPermissionDeniedError( 

143 subject=subject, 

144 permission_result=permission_result, 

145 attempted_action=attempted_action, 

146 user_org_id=user_org_id, 

147 )