Coverage for paperless_mail/serialisers.py: 91%

73 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 09:07 +0000

1from django.utils.translation import gettext as _ 

2from rest_framework import serializers 

3from rest_framework.exceptions import PermissionDenied 

4 

5from documents.permissions import get_objects_for_user_owner_aware 

6from documents.permissions import has_perms_owner_aware 

7from documents.serialisers import CorrespondentField 

8from documents.serialisers import DocumentTypeField 

9from documents.serialisers import OwnedObjectSerializer 

10from documents.serialisers import TagsField 

11from paperless_mail.models import MailAccount 

12from paperless_mail.models import MailRule 

13from paperless_mail.models import ProcessedMail 

14 

15 

16class ObfuscatedPasswordField(serializers.CharField): 

17 """ 

18 Sends *** string instead of password in the clear 

19 """ 

20 

21 def to_representation(self, value) -> str: 

22 return "*" * max(10, len(value)) 

23 

24 def to_internal_value(self, data): 

25 return data 

26 

27 

28class MailAccountSerializer(OwnedObjectSerializer): 

29 password = ObfuscatedPasswordField() 

30 imap_port = serializers.IntegerField(required=True, allow_null=False) 

31 

32 class Meta: 

33 model = MailAccount 

34 fields = [ 

35 "id", 

36 "name", 

37 "imap_server", 

38 "imap_port", 

39 "imap_security", 

40 "username", 

41 "password", 

42 "character_set", 

43 "is_token", 

44 "owner", 

45 "user_can_change", 

46 "permissions", 

47 "set_permissions", 

48 "account_type", 

49 "expiration", 

50 ] 

51 

52 def update(self, instance, validated_data): 

53 if ( 

54 "password" in validated_data 

55 and len(validated_data.get("password").replace("*", "")) == 0 

56 ): 

57 validated_data.pop("password") 

58 super().update(instance, validated_data) 

59 return instance 

60 

61 

62class AccountField(serializers.PrimaryKeyRelatedField[MailAccount]): 

63 def get_queryset(self): 

64 user = getattr(self.context.get("request"), "user", None) 

65 if user is None: 65 ↛ 66line 65 didn't jump to line 66 because the condition on line 65 was never true

66 user = getattr(self.root, "user", None) 

67 

68 if user is None: 68 ↛ 69line 68 didn't jump to line 69 because the condition on line 68 was never true

69 return MailAccount.objects.none() 

70 

71 return get_objects_for_user_owner_aware( 

72 user, 

73 "change_mailaccount", 

74 MailAccount, 

75 ).order_by("-id") 

76 

77 

78class MailRuleSerializer(OwnedObjectSerializer): 

79 account = AccountField(required=True) 

80 action_parameter = serializers.CharField( 

81 allow_null=True, 

82 required=False, 

83 default="", 

84 ) 

85 assign_correspondent = CorrespondentField(allow_null=True, required=False) 

86 assign_tags = TagsField(many=True, allow_null=True, required=False) 

87 assign_document_type = DocumentTypeField(allow_null=True, required=False) 

88 order = serializers.IntegerField(required=False) 

89 

90 class Meta: 

91 model = MailRule 

92 fields = [ 

93 "id", 

94 "name", 

95 "account", 

96 "enabled", 

97 "folder", 

98 "filter_from", 

99 "filter_to", 

100 "filter_subject", 

101 "filter_body", 

102 "filter_attachment_filename_include", 

103 "filter_attachment_filename_exclude", 

104 "maximum_age", 

105 "action", 

106 "action_parameter", 

107 "assign_title_from", 

108 "assign_tags", 

109 "assign_correspondent_from", 

110 "assign_correspondent", 

111 "assign_document_type", 

112 "assign_owner_from_rule", 

113 "order", 

114 "attachment_type", 

115 "consumption_scope", 

116 "pdf_layout", 

117 "owner", 

118 "user_can_change", 

119 "permissions", 

120 "set_permissions", 

121 "stop_processing", 

122 ] 

123 

124 def update(self, instance, validated_data): 

125 super().update(instance, validated_data) 

126 return instance 

127 

128 def create(self, validated_data): 

129 assign_tags = validated_data.pop("assign_tags", []) 

130 mail_rule = super().create(validated_data) 

131 if assign_tags: 131 ↛ 132line 131 didn't jump to line 132 because the condition on line 131 was never true

132 mail_rule.assign_tags.set(assign_tags) 

133 return mail_rule 

134 

135 def validate(self, attrs): 

136 action = attrs.get("action") 

137 action_parameter = attrs.get("action_parameter") 

138 

139 if ( 

140 action in [MailRule.MailAction.TAG, MailRule.MailAction.MOVE] 

141 and not action_parameter 

142 ): 

143 raise serializers.ValidationError("An action parameter is required.") 

144 

145 return attrs 

146 

147 def validate_account(self, account): 

148 if self.user is not None and has_perms_owner_aware( 148 ↛ 155line 148 didn't jump to line 155 because the condition on line 148 was always true

149 self.user, 

150 "change_mailaccount", 

151 account, 

152 ): 

153 return account 

154 

155 raise PermissionDenied( 

156 _("Insufficient permissions."), 

157 ) 

158 

159 def validate_maximum_age(self, value): 

160 if value > 36500: # ~100 years 

161 raise serializers.ValidationError("Maximum mail age is unreasonably large.") 

162 return value 

163 

164 

165class ProcessedMailSerializer(OwnedObjectSerializer): 

166 class Meta: 

167 model = ProcessedMail 

168 fields = [ 

169 "id", 

170 "owner", 

171 "rule", 

172 "folder", 

173 "uid", 

174 "subject", 

175 "received", 

176 "processed", 

177 "status", 

178 "error", 

179 ]