Coverage for frappe_manager / site_manager / modules / upload_limit_manager.py: 18%

39 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-07-02 18:13 +0530

1""" 

2Manages client_max_body_size configuration for nginx-proxy vhost.d files. 

3""" 

4 

5import re 

6from pathlib import Path 

7 

8 

9class UploadLimitManager: 

10 """Manages upload limit directives in nginx-proxy vhost.d files.""" 

11 

12 def __init__(self, vhostd_dir: Path): 

13 """ 

14 Initialize the upload limit manager. 

15 

16 Args: 

17 vhostd_dir: Path to nginx-proxy vhost.d directory 

18 """ 

19 self.vhostd_dir = vhostd_dir 

20 

21 def set_upload_limit(self, domain: str, size: str): 

22 """ 

23 Create or update vhost.d file with upload limit directive. 

24 

25 Args: 

26 domain: Domain name (e.g., "example.com") 

27 size: Size in nginx format (e.g., "50m", "1g") 

28 """ 

29 vhost_file = self.vhostd_dir / domain 

30 

31 # Ensure size is lowercase for nginx compatibility 

32 size = size.lower() 

33 

34 # Read existing content (if any) 

35 existing_content = "" 

36 if vhost_file.exists(): 

37 existing_content = vhost_file.read_text() 

38 

39 # Check if client_max_body_size already exists 

40 if "client_max_body_size" in existing_content: 

41 # Update existing directive using regex 

42 updated = re.sub(r"client_max_body_size\s+[^;]+;", f"client_max_body_size {size};", existing_content) 

43 vhost_file.write_text(updated) 

44 else: 

45 # Append to existing content 

46 new_directive = f"\nclient_max_body_size {size};\n" 

47 vhost_file.write_text(existing_content + new_directive) 

48 

49 def set_upload_limit_for_domains(self, domains: list[str], size: str): 

50 """ 

51 Set upload limit for multiple domains. 

52 

53 Handles wildcard domains intelligently: if a wildcard exists (e.g., *.example.com), 

54 subdomains matching that wildcard will NOT get individual files (to avoid nginx duplicates). 

55 

56 Args: 

57 domains: List of domain names 

58 size: Size in nginx format (e.g., "50m", "1g") 

59 """ 

60 # Check if there are wildcard domains 

61 wildcards = [d for d in domains if d.startswith("*.")] 

62 non_wildcards = [d for d in domains if not d.startswith("*.")] 

63 

64 # First, update wildcard domains 

65 for domain in wildcards: 

66 self.set_upload_limit(domain, size) 

67 

68 # For non-wildcard domains, only update if they don't match any wildcard 

69 for domain in non_wildcards: 

70 # Check if this domain matches any wildcard 

71 matches_wildcard = False 

72 for wildcard in wildcards: 

73 # Convert *.example.com to example.com for matching 

74 wildcard_base = wildcard[2:] # Remove "*." 

75 if domain.endswith(wildcard_base) and domain != wildcard_base: 

76 # This domain is covered by the wildcard (e.g., sub.example.com matches *.example.com) 

77 matches_wildcard = True 

78 break 

79 

80 if not matches_wildcard: 

81 # Only update if not covered by a wildcard 

82 self.set_upload_limit(domain, size) 

83 

84 def remove_upload_limit(self, domain: str): 

85 """ 

86 Remove upload limit directive from vhost.d file. 

87 

88 Note: Does not delete the file if other directives exist. 

89 

90 Args: 

91 domain: Domain name 

92 """ 

93 vhost_file = self.vhostd_dir / domain 

94 

95 if not vhost_file.exists(): 

96 return 

97 

98 content = vhost_file.read_text() 

99 

100 # Remove client_max_body_size directive 

101 updated = re.sub(r"client_max_body_size\s+[^;]+;\n?", "", content) 

102 

103 # If file is now empty or only whitespace, remove it 

104 if not updated.strip(): 

105 vhost_file.unlink() 

106 else: 

107 vhost_file.write_text(updated)