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.
 
 
 
 
 
 

630 wiersze
16 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  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. from MySQLdb import ProgrammingError as SQLError
  11. import os
  12. import json
  13. import semantic_version
  14. local = Local()
  15. class _dict(dict):
  16. """dict like object that exposes keys as attributes"""
  17. def __getattr__(self, key):
  18. return self.get(key)
  19. def __setattr__(self, key, value):
  20. self[key] = value
  21. def __getstate__(self):
  22. return self
  23. def __setstate__(self, d):
  24. self.update(d)
  25. def update(self, d):
  26. """update and return self -- the missing dict feature in python"""
  27. super(_dict, self).update(d)
  28. return self
  29. def copy(self):
  30. return _dict(dict(self).copy())
  31. def __getattr__(self, key):
  32. return local.get("key", None)
  33. def _(msg):
  34. """translate object in current lang, if exists"""
  35. if hasattr(local, 'translations'):
  36. return local.translations.get(lang, {}).get(msg, msg)
  37. return msg
  38. def set_user_lang(user, user_language=None):
  39. from webnotes.translate import get_lang_dict
  40. if not user_language:
  41. user_language = conn.get_value("Profile", user, "language")
  42. if user_language:
  43. lang_dict = get_lang_dict()
  44. if user_language in lang_dict:
  45. local.lang = lang_dict[user_language]
  46. def load_translations(module, doctype, name):
  47. from webnotes.translate import load_doc_messages
  48. load_doc_messages(module, doctype, name)
  49. # local-globals
  50. conn = local("conn")
  51. conf = local("conf")
  52. form = form_dict = local("form_dict")
  53. request = local("request")
  54. request_method = local("request_method")
  55. response = local("response")
  56. _response = local("_response")
  57. session = local("session")
  58. user = local("user")
  59. flags = local("flags")
  60. error_log = local("error_log")
  61. debug_log = local("debug_log")
  62. message_log = local("message_log")
  63. lang = local("lang")
  64. def init(site=None):
  65. if getattr(local, "initialised", None):
  66. return
  67. local.error_log = []
  68. local.site = site
  69. local.message_log = []
  70. local.debug_log = []
  71. local.response = _dict({})
  72. local.lang = "en"
  73. local.request_method = request.method if request else None
  74. local.conf = get_conf(site)
  75. local.initialised = True
  76. local.flags = _dict({})
  77. local.rollback_observers = []
  78. def destroy():
  79. """closes connection and releases werkzeug local"""
  80. if conn:
  81. conn.close()
  82. from werkzeug.local import release_local
  83. release_local(local)
  84. _memc = None
  85. test_objects = {}
  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 UnknownDomainError(Exception): pass
  98. class SessionStopped(Exception): pass
  99. class MappingMismatchError(ValidationError): pass
  100. class InvalidStatusError(ValidationError): pass
  101. class DoesNotExistError(ValidationError): pass
  102. class MandatoryError(ValidationError): pass
  103. class InvalidSignatureError(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 flags.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 flags.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 flags.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. try:
  143. os.makedirs(path)
  144. except OSError, e:
  145. if e.args[0]!=17:
  146. raise
  147. def create_symlink(source_path, link_path):
  148. try:
  149. os.symlink(source_path, link_path)
  150. except OSError, e:
  151. if e.args[0]!=17:
  152. raise
  153. def remove_file(path):
  154. try:
  155. os.remove(path)
  156. except OSError, e:
  157. if e.args[0]!=2:
  158. raise
  159. def connect(db_name=None, password=None, site=None):
  160. import webnotes.db
  161. init(site=site)
  162. local.conn = webnotes.db.Database(user=db_name, password=password)
  163. local.response = _dict()
  164. local.form_dict = _dict()
  165. local.session = _dict()
  166. set_user("Administrator")
  167. def set_user(username):
  168. import webnotes.profile
  169. local.session["user"] = username
  170. local.user = webnotes.profile.Profile(username)
  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):
  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. return fn
  200. return innerfn
  201. def only_for(roles):
  202. if not isinstance(roles, (tuple, list)):
  203. roles = (roles,)
  204. roles = set(roles)
  205. myroles = set(get_roles())
  206. if not roles.intersection(myroles):
  207. raise PermissionError
  208. class HashAuthenticatedCommand(object):
  209. def __init__(self):
  210. if hasattr(self, 'command'):
  211. import inspect
  212. self.fnargs, varargs, varkw, defaults = inspect.getargspec(self.command)
  213. self.fnargs.append('signature')
  214. def __call__(self, *args, **kwargs):
  215. signature = kwargs.pop('signature')
  216. if self.verify_signature(kwargs, signature):
  217. return self.command(*args, **kwargs)
  218. else:
  219. self.signature_error()
  220. def command(self):
  221. raise NotImplementedError
  222. def signature_error(self):
  223. raise InvalidSignatureError
  224. def get_signature(self, params, ignore_params=None):
  225. import hmac
  226. params = self.get_param_string(params, ignore_params=ignore_params)
  227. secret = "secret"
  228. signature = hmac.new(self.get_nonce())
  229. signature.update(secret)
  230. signature.update(params)
  231. return signature.hexdigest()
  232. def get_param_string(self, params, ignore_params=None):
  233. if not ignore_params:
  234. ignore_params = []
  235. params = [unicode(param) for param in params if param not in ignore_params]
  236. params = ''.join(params)
  237. return params
  238. def get_nonce():
  239. raise NotImplementedError
  240. def verify_signature(self, params, signature):
  241. if signature == self.get_signature(params):
  242. return True
  243. return False
  244. def clear_cache(user=None, doctype=None):
  245. """clear cache"""
  246. if doctype:
  247. from webnotes.model.doctype import clear_cache
  248. clear_cache(doctype)
  249. reset_metadata_version()
  250. elif user:
  251. from webnotes.sessions import clear_cache
  252. clear_cache(user)
  253. else: # everything
  254. from webnotes.sessions import clear_cache
  255. clear_cache()
  256. reset_metadata_version()
  257. def get_roles(username=None):
  258. import webnotes.profile
  259. if not username or username==session.user:
  260. return user.get_roles()
  261. else:
  262. return webnotes.profile.Profile(username).get_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.utils import cint
  270. if session.user=="Administrator" or conn.get_value("DocType", doctype, "istable")==1:
  271. return True
  272. meta = get_doctype(doctype)
  273. # get user permissions
  274. user_roles = get_roles()
  275. perms = [p for p in meta.get({"doctype": "DocPerm"})
  276. if cint(p.get(ptype))==1 and cint(p.permlevel)==0 and (p.role=="All" or p.role in user_roles)]
  277. if refdoc:
  278. return has_match(meta, perms, refdoc)
  279. else:
  280. return perms and True or False
  281. def has_match(meta, perms, refdoc):
  282. from webnotes.defaults import get_user_default_as_list
  283. if isinstance(refdoc, basestring):
  284. refdoc = doc(meta[0].name, refdoc)
  285. match_failed = {}
  286. for p in perms:
  287. if p.match:
  288. if ":" in p.match:
  289. keys = p.match.split(":")
  290. else:
  291. keys = [p.match, p.match]
  292. if refdoc.fields.get(keys[0],"[No Value]") in get_user_default_as_list(keys[1]):
  293. return True
  294. else:
  295. match_failed[keys[0]] = refdoc.fields.get(keys[0],"[No Value]")
  296. else:
  297. # found a permission without a match
  298. return True
  299. # no valid permission found
  300. if match_failed:
  301. msg = _("Not allowed for: ")
  302. for key in match_failed:
  303. msg += "\n" + (meta.get_field(key) and meta.get_label(key) or key) \
  304. + " = " + (match_failed[key] or "None")
  305. msgprint(msg)
  306. return False
  307. def generate_hash():
  308. """Generates random hash for session id"""
  309. import hashlib, time
  310. return hashlib.sha224(str(time.time())).hexdigest()
  311. def reset_metadata_version():
  312. v = generate_hash()
  313. cache().set_value("metadata_version", v)
  314. return v
  315. def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = True):
  316. from webnotes.model.code import get_obj
  317. return get_obj(dt, dn, doc, doclist, with_children)
  318. def doc(doctype=None, name=None, fielddata=None):
  319. from webnotes.model.doc import Document
  320. return Document(doctype, name, fielddata)
  321. def new_doc(doctype, parent_doc=None, parentfield=None):
  322. from webnotes.model.create_new import get_new_doc
  323. return get_new_doc(doctype, parent_doc, parentfield)
  324. def new_bean(doctype):
  325. from webnotes.model.create_new import get_new_doc
  326. return bean([get_new_doc(doctype)])
  327. def doclist(lst=None):
  328. from webnotes.model.doclist import DocList
  329. return DocList(lst)
  330. def bean(doctype=None, name=None, copy=None):
  331. """return an instance of the object, wrapped as a Bean (webnotes.model.bean)"""
  332. from webnotes.model.bean import Bean
  333. if copy:
  334. return Bean(copy_doclist(copy))
  335. else:
  336. return Bean(doctype, name)
  337. def set_value(doctype, docname, fieldname, value):
  338. import webnotes.client
  339. return webnotes.client.set_value(doctype, docname, fieldname, value)
  340. def get_doclist(doctype, name=None):
  341. return bean(doctype, name).doclist
  342. def get_doctype(doctype, processed=False):
  343. import webnotes.model.doctype
  344. return webnotes.model.doctype.get(doctype, processed)
  345. def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False):
  346. import webnotes.model.utils
  347. if not ignore_doctypes:
  348. ignore_doctypes = []
  349. if isinstance(name, list):
  350. for n in name:
  351. webnotes.model.utils.delete_doc(doctype, n, doclist, force, ignore_doctypes, for_reload, ignore_permissions)
  352. else:
  353. webnotes.model.utils.delete_doc(doctype, name, doclist, force, ignore_doctypes, for_reload, ignore_permissions)
  354. def clear_perms(doctype):
  355. conn.sql("""delete from tabDocPerm where parent=%s""", doctype)
  356. def reset_perms(doctype):
  357. clear_perms(doctype)
  358. reload_doc(conn.get_value("DocType", doctype, "module"), "DocType", doctype, force=True)
  359. def reload_doc(module, dt=None, dn=None, plugin=None, force=False):
  360. import webnotes.modules
  361. return webnotes.modules.reload_doc(module, dt, dn, plugin=plugin, force=force)
  362. def rename_doc(doctype, old, new, debug=0, force=False, merge=False):
  363. from webnotes.model.rename_doc import rename_doc
  364. return rename_doc(doctype, old, new, force=force, merge=merge)
  365. def insert(doclist):
  366. import webnotes.model
  367. return webnotes.model.insert(doclist)
  368. def get_module(modulename):
  369. __import__(modulename)
  370. import sys
  371. return sys.modules[modulename]
  372. def get_method(method_string):
  373. modulename = '.'.join(method_string.split('.')[:-1])
  374. methodname = method_string.split('.')[-1]
  375. return getattr(get_module(modulename), methodname)
  376. def make_property_setter(args):
  377. args = _dict(args)
  378. bean([{
  379. 'doctype': "Property Setter",
  380. 'doctype_or_field': args.doctype_or_field or "DocField",
  381. 'doc_type': args.doctype,
  382. 'field_name': args.fieldname,
  383. 'property': args.property,
  384. 'value': args.value,
  385. 'property_type': args.property_type or "Data",
  386. '__islocal': 1
  387. }]).save()
  388. def get_application_home_page(user='Guest'):
  389. """get home page for user"""
  390. hpl = conn.sql("""select home_page
  391. from `tabDefault Home Page`
  392. where parent='Control Panel'
  393. and role in ('%s') order by idx asc limit 1""" % "', '".join(get_roles(user)))
  394. if hpl:
  395. return hpl[0][0]
  396. else:
  397. return conn.get_value("Control Panel", None, "home_page")
  398. def copy_doclist(in_doclist):
  399. new_doclist = []
  400. parent_doc = None
  401. for i, d in enumerate(in_doclist):
  402. is_dict = False
  403. if isinstance(d, dict):
  404. is_dict = True
  405. values = _dict(d.copy())
  406. else:
  407. values = _dict(d.fields.copy())
  408. newd = new_doc(values.doctype, parent_doc=(None if i==0 else parent_doc), parentfield=values.parentfield)
  409. newd.fields.update(values)
  410. if i==0:
  411. parent_doc = newd
  412. new_doclist.append(newd.fields if is_dict else newd)
  413. return doclist(new_doclist)
  414. def compare(val1, condition, val2):
  415. import webnotes.utils
  416. return webnotes.utils.compare(val1, condition, val2)
  417. def repsond_as_web_page(title, html):
  418. local.message_title = title
  419. local.message = "<h3>" + title + "</h3>" + html
  420. local.response['type'] = 'page'
  421. local.response['page_name'] = 'message.html'
  422. def load_json(obj):
  423. if isinstance(obj, basestring):
  424. try:
  425. obj = json.loads(obj)
  426. except ValueError:
  427. pass
  428. return obj
  429. def build_match_conditions(doctype, fields=None, as_condition=True):
  430. import webnotes.widgets.reportview
  431. return webnotes.widgets.reportview.build_match_conditions(doctype, fields, as_condition)
  432. def get_list(doctype, filters=None, fields=None, docstatus=None,
  433. group_by=None, order_by=None, limit_start=0, limit_page_length=None,
  434. as_list=False, debug=False):
  435. import webnotes.widgets.reportview
  436. return webnotes.widgets.reportview.execute(doctype, filters=filters, fields=fields, docstatus=docstatus,
  437. group_by=group_by, order_by=order_by, limit_start=limit_start, limit_page_length=limit_page_length,
  438. as_list=as_list, debug=debug)
  439. def get_jenv():
  440. from jinja2 import Environment, FileSystemLoader
  441. from webnotes.utils import get_base_path, global_date_format
  442. from markdown2 import markdown
  443. from json import dumps
  444. jenv = Environment(loader = FileSystemLoader(get_base_path()))
  445. jenv.filters["global_date_format"] = global_date_format
  446. jenv.filters["markdown"] = markdown
  447. jenv.filters["json"] = dumps
  448. return jenv
  449. def get_template(path):
  450. return get_jenv().get_template(path)
  451. _config = None
  452. def get_config():
  453. global _config
  454. if not _config:
  455. import webnotes.utils, json
  456. _config = _dict()
  457. def update_config(path):
  458. try:
  459. with open(path, "r") as configfile:
  460. this_config = json.loads(configfile.read())
  461. for key, val in this_config.items():
  462. if isinstance(val, dict):
  463. _config.setdefault(key, _dict()).update(val)
  464. else:
  465. _config[key] = val
  466. except IOError:
  467. pass
  468. update_config(webnotes.utils.get_path("lib", "config.json"))
  469. update_config(webnotes.utils.get_path("app", "config.json"))
  470. return _config
  471. def get_conf(site):
  472. # TODO Should be heavily cached!
  473. import conf
  474. site_config = _dict({})
  475. conf = site_config.update(conf.__dict__)
  476. if not conf.get("files_path"):
  477. conf["files_path"] = os.path.join("public", "files")
  478. if not conf.get("plugins_path"):
  479. conf["plugins_path"] = "plugins"
  480. if conf.sites_dir and site:
  481. out = get_site_config(conf.sites_dir, site)
  482. if not out:
  483. raise NotFound()
  484. site_config.update(out)
  485. site_config["site_config"] = out
  486. site_config['site'] = site
  487. return site_config
  488. else:
  489. return conf
  490. def get_site_config(sites_dir, site):
  491. conf_path = get_conf_path(sites_dir, site)
  492. if os.path.exists(conf_path):
  493. with open(conf_path, 'r') as f:
  494. return json.load(f)
  495. def get_conf_path(sites_dir, site):
  496. from webnotes.utils import get_site_base_path
  497. return os.path.join(get_site_base_path(sites_dir=sites_dir,
  498. hostname=site), 'site_config.json')
  499. def validate_versions():
  500. config = get_config()
  501. framework_version = semantic_version.Version(config['framework_version'])
  502. spec = semantic_version.Spec(config['requires_framework_version'])
  503. if not spec.match(framework_version):
  504. raise Exception, "Framework version out of sync"