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.

__init__.py 16 KiB

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