Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

390 рядки
10 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. """
  24. globals attached to webnotes module
  25. + some utility functions that should probably be moved
  26. """
  27. code_fields_dict = {
  28. 'Page':[('script', 'js'), ('content', 'html'), ('style', 'css'), ('static_content', 'html'), ('server_code', 'py')],
  29. 'DocType':[('server_code_core', 'py'), ('client_script_core', 'js')],
  30. 'Search Criteria':[('report_script', 'js'), ('server_script', 'py'), ('custom_query', 'sql')],
  31. 'Patch':[('patch_code', 'py')],
  32. 'Stylesheet':['stylesheet', 'css'],
  33. 'Page Template':['template', 'html'],
  34. 'Control Panel':[('startup_code', 'js'), ('startup_css', 'css')]
  35. }
  36. class _dict(dict):
  37. """dict like object that exposes keys as attributes"""
  38. def __getattr__(self, key):
  39. return self.get(key)
  40. def __setattr__(self, key, value):
  41. self[key] = value
  42. def __getstate__(self):
  43. return self
  44. def __setstate__(self, d):
  45. self.update(d)
  46. def update(self, d):
  47. """update and return self -- the missing dict feature in python"""
  48. super(_dict, self).update(d)
  49. return self
  50. def copy(self):
  51. return _dict(super(_dict, self).copy())
  52. def _(msg):
  53. """translate object in current lang, if exists"""
  54. from webnotes.translate import messages
  55. return messages.get(lang, {}).get(msg, msg)
  56. request = form_dict = _dict()
  57. conn = None
  58. _memc = None
  59. form = None
  60. session = None
  61. user = None
  62. incoming_cookies = {}
  63. add_cookies = {} # append these to outgoing request
  64. cookies = {}
  65. response = _dict({'message':'', 'exc':''})
  66. debug_log = []
  67. message_log = []
  68. lang = 'en'
  69. # memcache
  70. def cache():
  71. global _memc
  72. if not _memc:
  73. from webnotes.memc import MClient
  74. _memc = MClient(['localhost:11211'])
  75. return _memc
  76. class ValidationError(Exception):
  77. pass
  78. class AuthenticationError(Exception):
  79. pass
  80. class PermissionError(Exception):
  81. pass
  82. class OutgoingEmailError(ValidationError):
  83. pass
  84. class UnknownDomainError(Exception):
  85. def __init__(self, value):
  86. self.value = value
  87. def __str__(self):
  88. return repr(self.value)
  89. class SessionStopped(Exception):
  90. def __init__(self, value):
  91. self.value = value
  92. def __str__(self):
  93. return repr(self.value)
  94. def getTraceback():
  95. import utils
  96. return utils.getTraceback()
  97. def errprint(msg):
  98. """
  99. Append to the :data:`debug log`
  100. """
  101. from utils import cstr
  102. debug_log.append(cstr(msg or ''))
  103. def msgprint(msg, small=0, raise_exception=0, as_table=False):
  104. """
  105. Append to the :data:`message_log`
  106. """
  107. from utils import cstr
  108. if as_table and type(msg) in (list, tuple):
  109. 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>'
  110. message_log.append((small and '__small:' or '')+cstr(msg or ''))
  111. if raise_exception:
  112. import inspect
  113. if inspect.isclass(raise_exception) and issubclass(raise_exception, Exception):
  114. raise raise_exception, msg
  115. else:
  116. raise ValidationError, msg
  117. def create_folder(path):
  118. """
  119. Wrapper function for os.makedirs (does not throw exception if directory exists)
  120. """
  121. import os
  122. try:
  123. os.makedirs(path)
  124. except OSError, e:
  125. if e.args[0]!=17:
  126. raise e
  127. def create_symlink(source_path, link_path):
  128. """
  129. Wrapper function for os.symlink (does not throw exception if directory exists)
  130. """
  131. import os
  132. try:
  133. os.symlink(source_path, link_path)
  134. except OSError, e:
  135. if e.args[0]!=17:
  136. raise e
  137. def remove_file(path):
  138. """
  139. Wrapper function for os.remove (does not throw exception if file/symlink does not exists)
  140. """
  141. import os
  142. try:
  143. os.remove(path)
  144. except OSError, e:
  145. if e.args[0]!=2:
  146. raise e
  147. def connect(db_name=None, password=None):
  148. """
  149. Connect to this db (or db), if called from command prompt
  150. """
  151. import webnotes.db
  152. global conn
  153. conn = webnotes.db.Database(user=db_name, password=password)
  154. global session
  155. session = _dict({'user':'Administrator'})
  156. import webnotes.profile
  157. global user
  158. user = webnotes.profile.Profile('Administrator')
  159. def get_env_vars(env_var):
  160. import os
  161. return os.environ.get(env_var,'None')
  162. remote_ip = get_env_vars('REMOTE_ADDR') #Required for login from python shell
  163. logger = None
  164. def get_db_password(db_name):
  165. """get db password from conf"""
  166. import conf
  167. if hasattr(conf, 'get_db_password'):
  168. return conf.get_db_password(db_name)
  169. elif hasattr(conf, 'db_password'):
  170. return conf.db_password
  171. else:
  172. return db_name
  173. whitelisted = []
  174. guest_methods = []
  175. def whitelist(allow_guest=False, allow_roles=[]):
  176. """
  177. decorator for whitelisting a function
  178. Note: if the function is allowed to be accessed by a guest user,
  179. it must explicitly be marked as allow_guest=True
  180. for specific roles, set allow_roles = ['Administrator'] etc.
  181. """
  182. def innerfn(fn):
  183. global whitelisted, guest_methods
  184. whitelisted.append(fn)
  185. if allow_guest:
  186. guest_methods.append(fn)
  187. if allow_roles:
  188. roles = get_roles()
  189. allowed = False
  190. for role in allow_roles:
  191. if role in roles:
  192. allowed = True
  193. break
  194. if not allowed:
  195. raise PermissionError, "Method not allowed"
  196. return fn
  197. return innerfn
  198. def clear_cache(user=None, doctype=None):
  199. """clear cache"""
  200. if doctype:
  201. from webnotes.model.doctype import clear_cache
  202. clear_cache(doctype)
  203. elif user:
  204. from webnotes.sessions import clear_cache
  205. clear_cache(user)
  206. else:
  207. from webnotes.sessions import clear_cache
  208. clear_cache()
  209. def get_roles(user=None, with_standard=True):
  210. """get roles of current user"""
  211. if not user:
  212. user = session.user
  213. if user=='Guest':
  214. return ['Guest']
  215. roles = [r[0] for r in conn.sql("""select role from tabUserRole
  216. where parent=%s and role!='All'""", user)] + ['All']
  217. # filter standard if required
  218. if not with_standard:
  219. roles = filter(lambda x: x not in ['All', 'Guest', 'Administrator'], roles)
  220. return roles
  221. def has_permission(doctype, ptype="read", doc=None):
  222. """check if user has permission"""
  223. if session.user=="Administrator":
  224. return True
  225. if conn.get_value("DocType", doctype, "istable"):
  226. return True
  227. perms = conn.sql("""select `name`, `match` from tabDocPerm p
  228. where p.parent = %s
  229. and ifnull(p.`%s`,0) = 1
  230. and ifnull(p.permlevel,0) = 0
  231. and (p.role="All" or p.role in (select `role` from tabUserRole where `parent`=%s))
  232. """ % ("%s", ptype, "%s"), (doctype, session.user), as_dict=1)
  233. if doc:
  234. match_failed = {}
  235. for p in perms:
  236. if p.match:
  237. if ":" in p.match:
  238. keys = p.match.split(":")
  239. else:
  240. keys = [p.match, p.match]
  241. if doc.fields.get(keys[0],"[No Value]") \
  242. in conn.get_defaults_as_list(keys[1], session.user):
  243. return True
  244. else:
  245. match_failed[keys[0]] = doc.fields.get(keys[0],"[No Value]")
  246. else:
  247. # found a permission without a match
  248. return True
  249. # no valid permission found
  250. if match_failed:
  251. key = match_failed.keys()[0]
  252. msgprint(_("Not allowed for: ") + key + "=" + match_failed[key])
  253. return False
  254. else:
  255. return perms and True or False
  256. def generate_hash():
  257. """Generates random hash for session id"""
  258. import hashlib, time
  259. return hashlib.sha224(str(time.time())).hexdigest()
  260. def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = 0):
  261. from webnotes.model.code import get_obj
  262. return get_obj(dt, dn, doc, doclist, with_children)
  263. def doc(doctype=None, name=None, fielddata=None):
  264. from webnotes.model.doc import Document
  265. return Document(doctype, name, fielddata)
  266. def doclist(lst=None):
  267. from webnotes.model.doclist import DocList
  268. return DocList(lst)
  269. def model_wrapper(doctype=None, name=None):
  270. from webnotes.model.wrapper import ModelWrapper
  271. return ModelWrapper(doctype, name)
  272. def get_doclist(doctype, name=None):
  273. return model_wrapper(doctype, name).doclist
  274. def get_doctype(doctype, processed=False):
  275. import webnotes.model.doctype
  276. return webnotes.model.doctype.get(doctype, processed)
  277. def delete_doc(doctype=None, name=None, doclist = None, force=0):
  278. import webnotes.model
  279. webnotes.model.delete_doc(doctype, name, doclist, force)
  280. def clear_perms(doctype):
  281. conn.sql("""delete from tabDocPerm where parent=%s""", doctype)
  282. def reset_perms(doctype):
  283. clear_perms(doctype)
  284. reload_doc(conn.get_value("DocType", doctype, "module"), "DocType", doctype)
  285. def reload_doc(module, dt=None, dn=None):
  286. import webnotes.modules
  287. return webnotes.modules.reload_doc(module, dt, dn)
  288. def rename_doc(doctype, old, new, is_doctype=0, debug=0):
  289. from webnotes.model.rename_doc import rename_doc
  290. rename_doc(doctype, old, new, is_doctype, debug)
  291. def insert(doclist):
  292. import webnotes.model
  293. return webnotes.model.insert(doclist)
  294. def get_method(method_string):
  295. modulename = '.'.join(method_string.split('.')[:-1])
  296. methodname = method_string.split('.')[-1]
  297. __import__(modulename)
  298. import sys
  299. moduleobj = sys.modules[modulename]
  300. return getattr(moduleobj, methodname)
  301. def make_property_setter(args):
  302. args = _dict(args)
  303. model_wrapper([{
  304. 'doctype': "Property Setter",
  305. 'doctype_or_field': args.doctype_or_field or "DocField",
  306. 'doc_type': args.doctype,
  307. 'field_name': args.fieldname,
  308. 'property': args.property,
  309. 'value': args.value,
  310. 'property_type': args.property_type or "Data",
  311. '__islocal': 1
  312. }]).save()
  313. def get_application_home_page(user='Guest'):
  314. """get home page for user"""
  315. hpl = conn.sql("""select home_page
  316. from `tabDefault Home Page`
  317. where parent='Control Panel'
  318. and role in ('%s') order by idx asc limit 1""" % "', '".join(get_roles(user)))
  319. if hpl:
  320. return hpl[0][0]
  321. else:
  322. return conn.get_value('Control Panel',None,'home_page') or 'Login Page'