Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

limits.py 6.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. from __future__ import unicode_literals
  2. import frappe
  3. from frappe import _
  4. from frappe.utils import now_datetime, getdate, flt, cint, get_fullname
  5. from frappe.installer import update_site_config
  6. from frappe.utils.data import formatdate
  7. from frappe.utils.user import get_enabled_system_users, get_system_managers
  8. import os, subprocess, urlparse, urllib
  9. class SiteExpiredError(frappe.ValidationError):
  10. pass
  11. EXPIRY_WARNING_DAYS = 10
  12. def check_if_expired():
  13. """check if account is expired. If expired, do not allow login"""
  14. if not has_expired():
  15. return
  16. limits = get_limits()
  17. expires_on = formatdate(limits.get("expiry"))
  18. support_email = limits.get("support_email")
  19. if limits.upgrade_url:
  20. message = _("""Your subscription expired on {0}. To renew, {1}.""").format(expires_on, get_upgrade_link(limits.upgrade_url))
  21. elif support_email:
  22. message = _("""Your subscription expired on {0}. To renew, please send an email to {1}.""").format(expires_on, support_email)
  23. else:
  24. message = _("""Your subscription expired on {0}""").format(expires_on)
  25. frappe.throw(message, SiteExpiredError)
  26. def has_expired():
  27. if frappe.session.user=="Administrator":
  28. return False
  29. expires_on = get_limits().expiry
  30. if not expires_on:
  31. return False
  32. if now_datetime().date() <= getdate(expires_on):
  33. return False
  34. return True
  35. def get_expiry_message():
  36. if "System Manager" not in frappe.get_roles():
  37. return ""
  38. limits = get_limits()
  39. if not limits.expiry:
  40. return ""
  41. expires_on = getdate(get_limits().get("expiry"))
  42. today = now_datetime().date()
  43. message = ""
  44. if today > expires_on:
  45. message = _("Your subscription has expired.")
  46. else:
  47. days_to_expiry = (expires_on - today).days
  48. if days_to_expiry == 0:
  49. message = _("Your subscription will expire today.")
  50. elif days_to_expiry == 1:
  51. message = _("Your subscription will expire tomorrow.")
  52. elif days_to_expiry <= EXPIRY_WARNING_DAYS:
  53. message = _("Your subscription will expire on {0}.").format(formatdate(expires_on))
  54. if message and limits.upgrade_url:
  55. upgrade_link = get_upgrade_link(limits.upgrade_url)
  56. message += ' ' + _('To renew, {0}.').format(upgrade_link)
  57. return message
  58. @frappe.whitelist()
  59. def get_usage_info():
  60. '''Get data to show for Usage Info'''
  61. # imported here to prevent circular import
  62. from frappe.email.queue import get_emails_sent_this_month
  63. limits = get_limits()
  64. if not (limits and any([limits.users, limits.space, limits.emails, limits.expiry])):
  65. # no limits!
  66. return
  67. limits.space = (limits.space or 0) * 1024.0 # to MB
  68. if not limits.space_usage:
  69. # hack! to show some progress
  70. limits.space_usage = {
  71. 'database_size': 26,
  72. 'files_size': 1,
  73. 'backup_size': 1,
  74. 'total': 28
  75. }
  76. usage_info = frappe._dict({
  77. 'limits': limits,
  78. 'enabled_users': len(get_enabled_system_users()),
  79. 'emails_sent': get_emails_sent_this_month(),
  80. 'space_usage': limits.space_usage['total'],
  81. })
  82. if limits.expiry:
  83. usage_info['expires_on'] = formatdate(limits.expiry)
  84. usage_info['days_to_expiry'] = (getdate(limits.expiry) - getdate()).days
  85. if limits.upgrade_url:
  86. usage_info['upgrade_url'] = get_upgrade_url(limits.upgrade_url)
  87. return usage_info
  88. def get_upgrade_url(upgrade_url):
  89. parts = urlparse.urlsplit(upgrade_url)
  90. params = dict(urlparse.parse_qsl(parts.query))
  91. params.update({
  92. 'site': frappe.local.site,
  93. 'email': frappe.session.user,
  94. 'full_name': get_fullname(),
  95. 'country': frappe.db.get_value("System Settings", "System Settings", 'country')
  96. })
  97. query = urllib.urlencode(params, doseq=True)
  98. url = urlparse.urlunsplit((parts.scheme, parts.netloc, parts.path, query, parts.fragment))
  99. return url
  100. def get_upgrade_link(upgrade_url, label=None):
  101. upgrade_url = get_upgrade_url(upgrade_url)
  102. upgrade_link = '<a href="{upgrade_url}" target="_blank">{click_here}</a>'.format(upgrade_url=upgrade_url, click_here=label or _('click here'))
  103. return upgrade_link
  104. def get_limits():
  105. '''
  106. "limits": {
  107. "users": 1,
  108. "space": 0.5, # in GB
  109. "emails": 1000 # per month
  110. "expiry": "2099-12-31"
  111. }
  112. '''
  113. return frappe._dict(frappe.local.conf.limits or {})
  114. def update_limits(limits_dict):
  115. '''Add/Update limit in site_config'''
  116. limits = get_limits()
  117. limits.update(limits_dict)
  118. update_site_config("limits", limits, validate=False)
  119. frappe.local.conf.limits = limits
  120. def clear_limit(key):
  121. '''Remove a limit option from site_config'''
  122. limits = get_limits()
  123. to_clear = [key] if isinstance(key, basestring) else key
  124. for key in to_clear:
  125. if key in limits:
  126. del limits[key]
  127. update_site_config("limits", limits, validate=False)
  128. frappe.conf.limits = limits
  129. def validate_space_limit(file_size):
  130. """Stop from writing file if max space limit is reached"""
  131. from frappe.utils.file_manager import MaxFileSizeReachedError
  132. limits = get_limits()
  133. if not limits.space:
  134. return
  135. # to MB
  136. space_limit = flt(limits.space * 1024.0, 2)
  137. # in MB
  138. usage = frappe._dict(limits.space_usage or {})
  139. if not usage:
  140. # first time
  141. usage = frappe._dict(update_space_usage())
  142. file_size = file_size / (1024.0 ** 2)
  143. if flt(flt(usage.total) + file_size, 2) > space_limit:
  144. # Stop from attaching file
  145. frappe.throw(_("You have exceeded the max space of {0} for your plan. {1}.").format(
  146. "<b>{0}MB</b>".format(cint(space_limit)) if (space_limit < 1024) else "<b>{0}GB</b>".format(limits.space),
  147. '<a href="#usage-info">{0}</a>'.format(_("Click here to check your usage or upgrade to a higher plan"))),
  148. MaxFileSizeReachedError)
  149. # update files size in frappe subscription
  150. usage.files_size = flt(usage.files_size) + file_size
  151. update_limits({ 'space_usage': usage })
  152. def update_space_usage():
  153. # public and private files
  154. files_size = get_folder_size(frappe.get_site_path("public", "files"))
  155. files_size += get_folder_size(frappe.get_site_path("private", "files"))
  156. backup_size = get_folder_size(frappe.get_site_path("private", "backups"))
  157. database_size = get_database_size()
  158. usage = {
  159. 'files_size': flt(files_size, 2),
  160. 'backup_size': flt(backup_size, 2),
  161. 'database_size': flt(database_size, 2),
  162. 'total': flt(flt(files_size) + flt(backup_size) + flt(database_size), 2)
  163. }
  164. update_limits({ 'space_usage': usage })
  165. return usage
  166. def get_folder_size(path):
  167. '''Returns folder size in MB if it exists'''
  168. if os.path.exists(path):
  169. return flt(subprocess.check_output(['du', '-ms', path]).split()[0], 2)
  170. def get_database_size():
  171. '''Returns approximate database size in MB'''
  172. db_name = frappe.conf.db_name
  173. # This query will get the database size in MB
  174. db_size = frappe.db.sql('''
  175. SELECT table_schema "database_name", sum( data_length + index_length ) / 1024 / 1024 "database_size"
  176. FROM information_schema.TABLES WHERE table_schema = %s GROUP BY table_schema''', db_name, as_dict=True)
  177. return flt(db_size[0].get('database_size'), 2)