You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

270 lines
7.8 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # License: See license.txt
  3. from __future__ import unicode_literals
  4. import frappe, json, os
  5. from frappe.utils import strip, cint
  6. from frappe.translate import (set_default_language, get_dict, send_translations)
  7. from frappe.geo.country_info import get_country_info
  8. from frappe.utils.file_manager import save_file
  9. from frappe.utils.password import update_password
  10. from werkzeug.useragents import UserAgent
  11. import install_fixtures
  12. @frappe.whitelist()
  13. def setup_complete(args):
  14. """Calls hooks for `setup_wizard_complete`, sets home page as `desktop`
  15. and clears cache. If wizard breaks, calls `setup_wizard_exception` hook"""
  16. if cint(frappe.db.get_single_value('System Settings', 'setup_complete')):
  17. # do not throw an exception if setup is already complete
  18. # let the user continue to desk
  19. return
  20. #frappe.throw(_('Setup already complete'))
  21. args = process_args(args)
  22. try:
  23. if args.language and args.language != "english":
  24. set_default_language(get_language_code(args.lang))
  25. frappe.clear_cache()
  26. # update system settings
  27. update_system_settings(args)
  28. update_user_name(args)
  29. for method in frappe.get_hooks("setup_wizard_complete"):
  30. frappe.get_attr(method)(args)
  31. disable_future_access()
  32. frappe.db.commit()
  33. frappe.clear_cache()
  34. except:
  35. frappe.db.rollback()
  36. if args:
  37. traceback = frappe.get_traceback()
  38. for hook in frappe.get_hooks("setup_wizard_exception"):
  39. frappe.get_attr(hook)(traceback, args)
  40. raise
  41. else:
  42. for hook in frappe.get_hooks("setup_wizard_success"):
  43. frappe.get_attr(hook)(args)
  44. install_fixtures.install()
  45. def update_system_settings(args):
  46. number_format = get_country_info(args.get("country")).get("number_format", "#,###.##")
  47. # replace these as float number formats, as they have 0 precision
  48. # and are currency number formats and not for floats
  49. if number_format=="#.###":
  50. number_format = "#.###,##"
  51. elif number_format=="#,###":
  52. number_format = "#,###.##"
  53. system_settings = frappe.get_doc("System Settings", "System Settings")
  54. system_settings.update({
  55. "country": args.get("country"),
  56. "language": get_language_code(args.get("language")),
  57. "time_zone": args.get("timezone"),
  58. "float_precision": 3,
  59. 'date_format': frappe.db.get_value("Country", args.get("country"), "date_format"),
  60. 'number_format': number_format,
  61. 'enable_scheduler': 1 if not frappe.flags.in_test else 0,
  62. 'backup_limit': 3 # Default for downloadable backups
  63. })
  64. system_settings.save()
  65. def update_user_name(args):
  66. first_name, last_name = args.get('full_name'), ''
  67. if ' ' in first_name:
  68. first_name, last_name = first_name.split(' ', 1)
  69. if args.get("email"):
  70. if frappe.db.exists('User', args.get('email')):
  71. # running again
  72. return
  73. args['name'] = args.get("email")
  74. _mute_emails, frappe.flags.mute_emails = frappe.flags.mute_emails, True
  75. doc = frappe.get_doc({
  76. "doctype":"User",
  77. "email": args.get("email"),
  78. "first_name": first_name,
  79. "last_name": last_name
  80. })
  81. doc.flags.no_welcome_mail = True
  82. doc.insert()
  83. frappe.flags.mute_emails = _mute_emails
  84. update_password(args.get("email"), args.get("password"))
  85. else:
  86. args.update({
  87. "name": frappe.session.user,
  88. "first_name": first_name,
  89. "last_name": last_name
  90. })
  91. frappe.db.sql("""update `tabUser` SET first_name=%(first_name)s,
  92. last_name=%(last_name)s WHERE name=%(name)s""", args)
  93. if args.get("attach_user"):
  94. attach_user = args.get("attach_user").split(",")
  95. if len(attach_user)==3:
  96. filename, filetype, content = attach_user
  97. fileurl = save_file(filename, content, "User", args.get("name"), decode=True).file_url
  98. frappe.db.set_value("User", args.get("name"), "user_image", fileurl)
  99. add_all_roles_to(args.get("name"))
  100. def process_args(args):
  101. if not args:
  102. args = frappe.local.form_dict
  103. if isinstance(args, basestring):
  104. args = json.loads(args)
  105. args = frappe._dict(args)
  106. # strip the whitespace
  107. for key, value in args.items():
  108. if isinstance(value, basestring):
  109. args[key] = strip(value)
  110. return args
  111. def add_all_roles_to(name):
  112. user = frappe.get_doc("User", name)
  113. for role in frappe.db.sql("""select name from tabRole"""):
  114. if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner", "Employee"]:
  115. d = user.append("roles")
  116. d.role = role[0]
  117. user.save()
  118. def disable_future_access():
  119. frappe.db.set_default('desktop:home_page', 'desktop')
  120. frappe.db.set_value('System Settings', 'System Settings', 'setup_complete', 1)
  121. if not frappe.flags.in_test:
  122. # remove all roles and add 'Administrator' to prevent future access
  123. page = frappe.get_doc('Page', 'setup-wizard')
  124. page.roles = []
  125. page.append('roles', {'role': 'Administrator'})
  126. page.flags.do_not_update_json = True
  127. page.flags.ignore_permissions = True
  128. page.save()
  129. @frappe.whitelist()
  130. def load_messages(language):
  131. """Load translation messages for given language from all `setup_wizard_requires`
  132. javascript files"""
  133. frappe.clear_cache()
  134. set_default_language(get_language_code(language))
  135. m = get_dict("page", "setup-wizard")
  136. for path in frappe.get_hooks("setup_wizard_requires"):
  137. # common folder `assets` served from `sites/`
  138. js_file_path = os.path.abspath(frappe.get_site_path("..", *path.strip("/").split("/")))
  139. m.update(get_dict("jsfile", js_file_path))
  140. m.update(get_dict("boot"))
  141. send_translations(m)
  142. return frappe.local.lang
  143. @frappe.whitelist()
  144. def load_languages():
  145. language_codes = frappe.db.sql('select language_code, language_name from tabLanguage order by name', as_dict=True)
  146. codes_to_names = {}
  147. for d in language_codes:
  148. codes_to_names[d.language_code] = d.language_name
  149. return {
  150. "default_language": frappe.db.get_value('Language', frappe.local.lang, 'language_name') or frappe.local.lang,
  151. "languages": sorted(frappe.db.sql_list('select language_name from tabLanguage order by name')),
  152. "codes_to_names": codes_to_names
  153. }
  154. @frappe.whitelist()
  155. def load_country():
  156. from frappe.sessions import get_geo_ip_country
  157. return get_geo_ip_country(frappe.local.request_ip) if frappe.local.request_ip else None
  158. @frappe.whitelist()
  159. def load_user_details():
  160. return {
  161. "full_name": frappe.cache().hget("full_name", "signup"),
  162. "email": frappe.cache().hget("email", "signup")
  163. }
  164. def prettify_args(args):
  165. # remove attachments
  166. for key, val in args.items():
  167. if isinstance(val, basestring) and "data:image" in val:
  168. filename = val.split("data:image", 1)[0].strip(", ")
  169. size = round((len(val) * 3 / 4) / 1048576.0, 2)
  170. args[key] = "Image Attached: '{0}' of size {1} MB".format(filename, size)
  171. pretty_args = []
  172. for key in sorted(args):
  173. pretty_args.append("{} = {}".format(key, args[key]))
  174. return pretty_args
  175. def email_setup_wizard_exception(traceback, args):
  176. if not frappe.local.conf.setup_wizard_exception_email:
  177. return
  178. pretty_args = prettify_args(args)
  179. if frappe.local.request:
  180. user_agent = UserAgent(frappe.local.request.headers.get('User-Agent', ''))
  181. else:
  182. user_agent = frappe._dict()
  183. message = """
  184. #### Basic Information
  185. - **Site:** {site}
  186. - **User:** {user}
  187. - **Browser:** {user_agent.platform} {user_agent.browser} version: {user_agent.version} language: {user_agent.language}
  188. - **Browser Languages**: `{accept_languages}`
  189. ---
  190. #### Traceback
  191. <pre>{traceback}</pre>
  192. ---
  193. #### Setup Wizard Arguments
  194. <pre>{args}</pre>
  195. ---
  196. #### Request Headers
  197. <pre>{headers}</pre>""".format(
  198. site=frappe.local.site,
  199. traceback=traceback,
  200. args="\n".join(pretty_args),
  201. user=frappe.session.user,
  202. user_agent=user_agent,
  203. headers=frappe.local.request.headers,
  204. accept_languages=", ".join(frappe.local.request.accept_languages.values()))
  205. frappe.sendmail(recipients=frappe.local.conf.setup_wizard_exception_email,
  206. sender=frappe.session.user,
  207. subject="Exception in Setup Wizard - {}".format(frappe.local.site),
  208. message=message,
  209. delayed=False)
  210. def get_language_code(lang):
  211. return frappe.db.get_value('Language', {'language_name':lang})