Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

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