Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

579 righe
15 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. # MIT License. See license.txt
  3. """
  4. globals attached to webnotes module
  5. + some utility functions that should probably be moved
  6. """
  7. from __future__ import unicode_literals
  8. from werkzeug.local import Local
  9. from werkzeug.exceptions import NotFound
  10. import os
  11. import json
  12. local = Local()
  13. class _dict(dict):
  14. """dict like object that exposes keys as attributes"""
  15. def __getattr__(self, key):
  16. return self.get(key)
  17. def __setattr__(self, key, value):
  18. self[key] = value
  19. def __getstate__(self):
  20. return self
  21. def __setstate__(self, d):
  22. self.update(d)
  23. def update(self, d):
  24. """update and return self -- the missing dict feature in python"""
  25. super(_dict, self).update(d)
  26. return self
  27. def copy(self):
  28. return _dict(super(_dict, self).copy())
  29. def __getattr__(self, key):
  30. return local.get("key", None)
  31. def _(msg):
  32. """translate object in current lang, if exists"""
  33. if hasattr(local, 'translations'):
  34. return local.translations.get(lang, {}).get(msg, msg)
  35. return msg
  36. def set_user_lang(user, user_language=None):
  37. from webnotes.translate import get_lang_dict
  38. if not user_language:
  39. user_language = conn.get_value("Profile", user, "language")
  40. if user_language:
  41. lang_dict = get_lang_dict()
  42. if user_language in lang_dict:
  43. local.lang = lang_dict[user_language]
  44. def load_translations(module, doctype, name):
  45. from webnotes.translate import load_doc_messages
  46. load_doc_messages(module, doctype, name)
  47. # local-globals
  48. conn = local("conn")
  49. conf = local("conf")
  50. form = form_dict = local("form_dict")
  51. request = local("request")
  52. request_method = local("request_method")
  53. response = local("response")
  54. _response = local("_response")
  55. session = local("session")
  56. user = local("user")
  57. error_log = local("error_log")
  58. debug_log = local("debug_log")
  59. message_log = local("message_log")
  60. lang = local("lang")
  61. def init(site=None):
  62. if getattr(local, "initialised", None):
  63. return
  64. local.error_log = []
  65. local.message_log = []
  66. local.debug_log = []
  67. local.response = _dict({})
  68. local.lang = "en"
  69. local.request_method = request.method if request else None
  70. local.conf = get_conf(site)
  71. local.initialised = True
  72. def destroy():
  73. """closes connection and releases werkzeug local"""
  74. if conn:
  75. conn.close()
  76. from werkzeug.local import release_local
  77. release_local(local)
  78. _memc = None
  79. mute_emails = False
  80. mute_messages = False
  81. test_objects = {}
  82. print_messages = False
  83. in_import = False
  84. in_test = False
  85. rollback_on_exception = False
  86. # memcache
  87. def cache():
  88. global _memc
  89. if not _memc:
  90. from webnotes.memc import MClient
  91. _memc = MClient(['localhost:11211'])
  92. return _memc
  93. class DuplicateEntryError(Exception): pass
  94. class ValidationError(Exception): pass
  95. class AuthenticationError(Exception): pass
  96. class PermissionError(Exception): pass
  97. class OutgoingEmailError(ValidationError): pass
  98. class UnknownDomainError(Exception): pass
  99. class SessionStopped(Exception): pass
  100. class MappingMismatchError(ValidationError): pass
  101. class InvalidStatusError(ValidationError): pass
  102. class DoesNotExistError(ValidationError): pass
  103. class MandatoryError(ValidationError): pass
  104. def getTraceback():
  105. import utils
  106. return utils.getTraceback()
  107. def errprint(msg):
  108. from utils import cstr
  109. if not request:
  110. print cstr(msg)
  111. error_log.append(cstr(msg))
  112. def log(msg):
  113. if not request:
  114. import conf
  115. if conf.get("logging") or False:
  116. print repr(msg)
  117. from utils import cstr
  118. debug_log.append(cstr(msg))
  119. def msgprint(msg, small=0, raise_exception=0, as_table=False):
  120. def _raise_exception():
  121. if raise_exception:
  122. if rollback_on_exception:
  123. conn.rollback()
  124. import inspect
  125. if inspect.isclass(raise_exception) and issubclass(raise_exception, Exception):
  126. raise raise_exception, msg
  127. else:
  128. raise ValidationError, msg
  129. if mute_messages:
  130. _raise_exception()
  131. return
  132. from utils import cstr
  133. if as_table and type(msg) in (list, tuple):
  134. msg = '<table border="1px" style="border-collapse: collapse" cellpadding="2px">' + ''.join(['<tr>'+''.join(['<td>%s</td>' % c for c in r])+'</tr>' for r in msg]) + '</table>'
  135. if print_messages:
  136. print "Message: " + repr(msg)
  137. message_log.append((small and '__small:' or '')+cstr(msg or ''))
  138. _raise_exception()
  139. def throw(msg, exc=ValidationError):
  140. msgprint(msg, raise_exception=exc)
  141. def create_folder(path):
  142. import os
  143. try:
  144. os.makedirs(path)
  145. except OSError, e:
  146. if e.args[0]!=17:
  147. raise e
  148. def create_symlink(source_path, link_path):
  149. import os
  150. try:
  151. os.symlink(source_path, link_path)
  152. except OSError, e:
  153. if e.args[0]!=17:
  154. raise e
  155. def remove_file(path):
  156. import os
  157. try:
  158. os.remove(path)
  159. except OSError, e:
  160. if e.args[0]!=2:
  161. raise e
  162. def connect(db_name=None, password=None, site=None):
  163. import webnotes.db
  164. init(site=site)
  165. local.conn = webnotes.db.Database(user=db_name, password=password)
  166. local.session = _dict({'user':'Administrator'})
  167. local.response = _dict()
  168. local.form_dict = _dict()
  169. import webnotes.profile
  170. local.user = webnotes.profile.Profile('Administrator')
  171. def get_request_header(key, default=None):
  172. try:
  173. return request.headers.get(key, default)
  174. except Exception, e:
  175. return None
  176. logger = None
  177. def get_db_password(db_name):
  178. """get db password from conf"""
  179. if 'get_db_password' in conf:
  180. return conf.get_db_password(db_name)
  181. elif 'db_password' in conf:
  182. return conf.db_password
  183. else:
  184. return db_name
  185. whitelisted = []
  186. guest_methods = []
  187. def whitelist(allow_guest=False, allow_roles=None):
  188. """
  189. decorator for whitelisting a function
  190. Note: if the function is allowed to be accessed by a guest user,
  191. it must explicitly be marked as allow_guest=True
  192. for specific roles, set allow_roles = ['Administrator'] etc.
  193. """
  194. def innerfn(fn):
  195. global whitelisted, guest_methods
  196. whitelisted.append(fn)
  197. if allow_guest:
  198. guest_methods.append(fn)
  199. if allow_roles:
  200. roles = get_roles()
  201. allowed = False
  202. for role in allow_roles:
  203. if role in roles:
  204. allowed = True
  205. break
  206. if not allowed:
  207. raise PermissionError, "Method not allowed"
  208. return fn
  209. return innerfn
  210. def clear_cache(user=None, doctype=None):
  211. """clear cache"""
  212. if doctype:
  213. from webnotes.model.doctype import clear_cache
  214. clear_cache(doctype)
  215. elif user:
  216. from webnotes.sessions import clear_cache
  217. clear_cache(user)
  218. else:
  219. from webnotes.sessions import clear_cache
  220. clear_cache()
  221. def get_roles(user=None, with_standard=True):
  222. """get roles of current user"""
  223. if not user:
  224. user = session.user
  225. if user=='Guest':
  226. return ['Guest']
  227. roles = [r[0] for r in conn.sql("""select role from tabUserRole
  228. where parent=%s and role!='All'""", user)] + ['All']
  229. # filter standard if required
  230. if not with_standard:
  231. roles = filter(lambda x: x not in ['All', 'Guest', 'Administrator'], roles)
  232. return roles
  233. def check_admin_or_system_manager():
  234. if ("System Manager" not in get_roles()) and \
  235. (session.user!="Administrator"):
  236. msgprint("Only Allowed for Role System Manager or Administrator", raise_exception=True)
  237. def has_permission(doctype, ptype="read", refdoc=None):
  238. """check if user has permission"""
  239. from webnotes.defaults import get_user_default_as_list
  240. if session.user=="Administrator":
  241. return True
  242. if conn.get_value("DocType", doctype, "istable"):
  243. return True
  244. if isinstance(refdoc, basestring):
  245. refdoc = doc(doctype, refdoc)
  246. perms = conn.sql("""select `name`, `match` from tabDocPerm p
  247. where p.parent = %s
  248. and ifnull(p.`%s`,0) = 1
  249. and ifnull(p.permlevel,0) = 0
  250. and (p.role="All" or p.role in (select `role` from tabUserRole where `parent`=%s))
  251. """ % ("%s", ptype, "%s"), (doctype, session.user), as_dict=1)
  252. if refdoc:
  253. match_failed = {}
  254. for p in perms:
  255. if p.match:
  256. if ":" in p.match:
  257. keys = p.match.split(":")
  258. else:
  259. keys = [p.match, p.match]
  260. if refdoc.fields.get(keys[0],"[No Value]") in get_user_default_as_list(keys[1]):
  261. return True
  262. else:
  263. match_failed[keys[0]] = refdoc.fields.get(keys[0],"[No Value]")
  264. else:
  265. # found a permission without a match
  266. return True
  267. # no valid permission found
  268. if match_failed:
  269. doctypelist = get_doctype(doctype)
  270. msg = _("Not allowed for: ")
  271. for key in match_failed:
  272. msg += "\n" + (doctypelist.get_field(key) and doctypelist.get_label(key) or key) \
  273. + " = " + (match_failed[key] or "None")
  274. msgprint(msg)
  275. return False
  276. else:
  277. return perms and True or False
  278. def generate_hash():
  279. """Generates random hash for session id"""
  280. import hashlib, time
  281. return hashlib.sha224(str(time.time())).hexdigest()
  282. def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = True):
  283. from webnotes.model.code import get_obj
  284. return get_obj(dt, dn, doc, doclist, with_children)
  285. def doc(doctype=None, name=None, fielddata=None):
  286. from webnotes.model.doc import Document
  287. return Document(doctype, name, fielddata)
  288. def new_doc(doctype, parent_doc=None, parentfield=None):
  289. from webnotes.model.create_new import get_new_doc
  290. return get_new_doc(doctype, parent_doc, parentfield)
  291. def new_bean(doctype):
  292. from webnotes.model.create_new import get_new_doc
  293. return bean([get_new_doc(doctype)])
  294. def doclist(lst=None):
  295. from webnotes.model.doclist import DocList
  296. return DocList(lst)
  297. def bean(doctype=None, name=None, copy=None):
  298. """return an instance of the object, wrapped as a Bean (webnotes.model.bean)"""
  299. from webnotes.model.bean import Bean
  300. if copy:
  301. return Bean(copy_doclist(copy))
  302. else:
  303. return Bean(doctype, name)
  304. def set_value(doctype, docname, fieldname, value):
  305. import webnotes.client
  306. return webnotes.client.set_value(doctype, docname, fieldname, value)
  307. def get_doclist(doctype, name=None):
  308. return bean(doctype, name).doclist
  309. def get_doctype(doctype, processed=False):
  310. import webnotes.model.doctype
  311. return webnotes.model.doctype.get(doctype, processed)
  312. def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False):
  313. import webnotes.model.utils
  314. if not ignore_doctypes:
  315. ignore_doctypes = []
  316. if isinstance(name, list):
  317. for n in name:
  318. webnotes.model.utils.delete_doc(doctype, n, doclist, force, ignore_doctypes, for_reload, ignore_permissions)
  319. else:
  320. webnotes.model.utils.delete_doc(doctype, name, doclist, force, ignore_doctypes, for_reload, ignore_permissions)
  321. def clear_perms(doctype):
  322. conn.sql("""delete from tabDocPerm where parent=%s""", doctype)
  323. def reset_perms(doctype):
  324. clear_perms(doctype)
  325. reload_doc(conn.get_value("DocType", doctype, "module"), "DocType", doctype, force=True)
  326. def reload_doc(module, dt=None, dn=None, force=False):
  327. import webnotes.modules
  328. return webnotes.modules.reload_doc(module, dt, dn, force)
  329. def rename_doc(doctype, old, new, debug=0, force=False, merge=False):
  330. from webnotes.model.rename_doc import rename_doc
  331. rename_doc(doctype, old, new, force=force, merge=merge)
  332. def insert(doclist):
  333. import webnotes.model
  334. return webnotes.model.insert(doclist)
  335. def get_module(modulename):
  336. __import__(modulename)
  337. import sys
  338. return sys.modules[modulename]
  339. def get_method(method_string):
  340. modulename = '.'.join(method_string.split('.')[:-1])
  341. methodname = method_string.split('.')[-1]
  342. return getattr(get_module(modulename), methodname)
  343. def make_property_setter(args):
  344. args = _dict(args)
  345. bean([{
  346. 'doctype': "Property Setter",
  347. 'doctype_or_field': args.doctype_or_field or "DocField",
  348. 'doc_type': args.doctype,
  349. 'field_name': args.fieldname,
  350. 'property': args.property,
  351. 'value': args.value,
  352. 'property_type': args.property_type or "Data",
  353. '__islocal': 1
  354. }]).save()
  355. def get_application_home_page(user='Guest'):
  356. """get home page for user"""
  357. hpl = conn.sql("""select home_page
  358. from `tabDefault Home Page`
  359. where parent='Control Panel'
  360. and role in ('%s') order by idx asc limit 1""" % "', '".join(get_roles(user)))
  361. if hpl:
  362. return hpl[0][0]
  363. else:
  364. # no app
  365. try:
  366. from startup import application_home_page
  367. return application_home_page
  368. except ImportError:
  369. return "desktop"
  370. def copy_doclist(in_doclist):
  371. new_doclist = []
  372. parent_doc = None
  373. for i, d in enumerate(in_doclist):
  374. is_dict = False
  375. if isinstance(d, dict):
  376. is_dict = True
  377. values = _dict(d.copy())
  378. else:
  379. values = _dict(d.fields.copy())
  380. newd = new_doc(values.doctype, parent_doc=(None if i==0 else parent_doc), parentfield=values.parentfield)
  381. newd.fields.update(values)
  382. if i==0:
  383. parent_doc = newd
  384. new_doclist.append(newd.fields if is_dict else newd)
  385. return doclist(new_doclist)
  386. def compare(val1, condition, val2):
  387. import webnotes.utils
  388. return webnotes.utils.compare(val1, condition, val2)
  389. def repsond_as_web_page(title, html):
  390. local.message_title = title
  391. local.message = "<h3>" + title + "</h3>" + html
  392. local.response['type'] = 'page'
  393. local.response['page_name'] = 'message.html'
  394. def load_json(obj):
  395. if isinstance(obj, basestring):
  396. import json
  397. try:
  398. obj = json.loads(obj)
  399. except ValueError:
  400. pass
  401. return obj
  402. def build_match_conditions(doctype, fields=None, as_condition=True, match_filters=None):
  403. import webnotes.widgets.reportview
  404. return webnotes.widgets.reportview.build_match_conditions(doctype, fields, as_condition, match_filters)
  405. def get_list(doctype, filters=None, fields=None, docstatus=None,
  406. group_by=None, order_by=None, limit_start=0, limit_page_length=None,
  407. as_list=False, debug=False):
  408. import webnotes.widgets.reportview
  409. return webnotes.widgets.reportview.execute(doctype, filters=filters, fields=fields, docstatus=docstatus,
  410. group_by=group_by, order_by=order_by, limit_start=limit_start, limit_page_length=limit_page_length,
  411. as_list=as_list, debug=debug)
  412. def get_jenv():
  413. from jinja2 import Environment, FileSystemLoader
  414. from webnotes.utils import get_base_path, global_date_format
  415. from markdown2 import markdown
  416. from json import dumps
  417. jenv = Environment(loader = FileSystemLoader(get_base_path()))
  418. jenv.filters["global_date_format"] = global_date_format
  419. jenv.filters["markdown"] = markdown
  420. jenv.filters["json"] = dumps
  421. return jenv
  422. def get_template(path):
  423. return get_jenv().get_template(path)
  424. _config = None
  425. def get_config():
  426. global _config
  427. if not _config:
  428. import webnotes.utils, json
  429. _config = _dict()
  430. def update_config(path):
  431. try:
  432. with open(path, "r") as configfile:
  433. this_config = json.loads(configfile.read())
  434. for key, val in this_config.items():
  435. if isinstance(val, dict):
  436. _config.setdefault(key, _dict()).update(val)
  437. else:
  438. _config[key] = val
  439. except IOError:
  440. pass
  441. update_config(webnotes.utils.get_path("lib", "config.json"))
  442. update_config(webnotes.utils.get_path("app", "config.json"))
  443. return _config
  444. def get_conf(site):
  445. # TODO Should be heavily cached!
  446. import conf
  447. from webnotes.utils import get_site_base_path
  448. site_config = _dict({})
  449. conf = site_config.update(conf.__dict__)
  450. if conf.sites_dir and site:
  451. out = get_site_config(conf.sites_dir, site)
  452. if not out:
  453. raise NotFound()
  454. site_config.update(out)
  455. site_config['site'] = site
  456. return site_config
  457. else:
  458. return conf
  459. def get_site_config(sites_dir, site):
  460. conf_path = get_conf_path(sites_dir, site)
  461. if os.path.exists(conf_path):
  462. with open(conf_path, 'r') as f:
  463. return json.load(f)
  464. def get_conf_path(sites_dir, site):
  465. return os.path.join(get_site_base_path(sites_dir=sites_dir,
  466. hostname=site), 'site_config.json')