您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

253 行
7.4 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. """
  5. Boot session from cache or build
  6. Session bootstraps info needed by common client side activities including
  7. permission, homepage, control panel variables, system defaults etc
  8. """
  9. import webnotes
  10. import conf
  11. import json
  12. from webnotes.utils import cint
  13. import webnotes.model.doctype
  14. import webnotes.defaults
  15. @webnotes.whitelist()
  16. def clear(user=None):
  17. clear_cache(webnotes.session.user)
  18. webnotes.response['message'] = "Cache Cleared"
  19. def clear_cache(user=None):
  20. cache = webnotes.cache()
  21. # clear doctype cache
  22. webnotes.model.doctype.clear_cache()
  23. if user:
  24. cache.delete_value("bootinfo:" + user)
  25. if webnotes.session and webnotes.session.sid:
  26. cache.delete_value("session:" + webnotes.session.sid)
  27. else:
  28. for sess in webnotes.conn.sql("""select user, sid from tabSessions""", as_dict=1):
  29. cache.delete_value("sesssion:" + sess.sid)
  30. cache.delete_value("bootinfo:" + sess.user)
  31. def clear_sessions(user=None, keep_current=False):
  32. if not user:
  33. user = webnotes.session.user
  34. for sid in webnotes.conn.sql("""select sid from tabSessions where user=%s""", user):
  35. if keep_current and webnotes.session.sid==sid[0]:
  36. pass
  37. else:
  38. webnotes.cache().delete_value("session:" + sid[0])
  39. webnotes.conn.sql("""delete from tabSessions where sid=%s""", sid[0])
  40. def get():
  41. """get session boot info"""
  42. from webnotes.widgets.notification import get_notification_info_for_boot
  43. bootinfo = None
  44. if not getattr(conf,'auto_cache_clear',None):
  45. # check if cache exists
  46. bootinfo = webnotes.cache().get_value('bootinfo:' + webnotes.session.user)
  47. if bootinfo:
  48. bootinfo['from_cache'] = 1
  49. if not bootinfo:
  50. if not webnotes.cache().get_stats():
  51. webnotes.msgprint("memcached is not working / stopped. Please start memcached for best results.")
  52. # if not create it
  53. from webnotes.boot import get_bootinfo
  54. bootinfo = get_bootinfo()
  55. webnotes.cache().set_value('bootinfo:' + webnotes.session.user, bootinfo)
  56. bootinfo["notification_info"] = get_notification_info_for_boot()
  57. return bootinfo
  58. class Session:
  59. def __init__(self, user=None):
  60. self.user = user
  61. self.sid = webnotes.form_dict.get('sid') or webnotes.incoming_cookies.get('sid', 'Guest')
  62. self.data = webnotes._dict({'user':user,'data': webnotes._dict({})})
  63. self.time_diff = None
  64. if webnotes.form_dict.get('cmd')=='login':
  65. self.start()
  66. return
  67. self.load()
  68. def start(self):
  69. """start a new session"""
  70. import os
  71. import webnotes
  72. import webnotes.utils
  73. # generate sid
  74. if webnotes.login_manager.user=='Guest':
  75. sid = 'Guest'
  76. else:
  77. sid = webnotes.generate_hash()
  78. self.data['user'] = webnotes.login_manager.user
  79. self.data['sid'] = sid
  80. self.data['data']['user'] = webnotes.login_manager.user
  81. self.data['data']['session_ip'] = os.environ.get('REMOTE_ADDR')
  82. self.data['data']['last_updated'] = webnotes.utils.now()
  83. self.data['data']['session_expiry'] = self.get_expiry_period()
  84. self.data['data']['session_country'] = get_geo_ip_country(os.environ.get('REMOTE_ADDR'))
  85. # insert session
  86. webnotes.conn.begin()
  87. self.insert_session_record()
  88. # update profile
  89. webnotes.conn.sql("""UPDATE tabProfile SET last_login = '%s', last_ip = '%s'
  90. where name='%s'""" % (webnotes.utils.now(), webnotes.remote_ip, self.data['user']))
  91. webnotes.conn.commit()
  92. # set cookies to write
  93. webnotes.session = self.data
  94. def insert_session_record(self):
  95. webnotes.conn.sql("""insert into tabSessions
  96. (sessiondata, user, lastupdate, sid, status)
  97. values (%s , %s, NOW(), %s, 'Active')""",
  98. (str(self.data['data']), self.data['user'], self.data['sid']))
  99. # also add to memcache
  100. webnotes.cache().set_value("session:" + self.data.sid, self.data)
  101. def load(self):
  102. """non-login request: load a session"""
  103. import webnotes
  104. data = self.get_session_record()
  105. if data:
  106. # set language
  107. if data.lang and self.user!="demo@erpnext.com":
  108. webnotes.lang = data.lang
  109. self.data = webnotes._dict({'data': data,
  110. 'user':data.user, 'sid': self.sid})
  111. else:
  112. self.start_as_guest()
  113. def get_session_record(self):
  114. """get session record, or return the standard Guest Record"""
  115. r = self.get_session_data()
  116. if not r:
  117. webnotes.response["session_expired"] = 1
  118. self.sid = "Guest"
  119. r = self.get_session_data()
  120. return r
  121. def get_session_data(self):
  122. data = self.get_session_data_from_cache()
  123. if not data:
  124. data = self.get_session_data_from_db()
  125. return data
  126. def get_session_data_from_cache(self):
  127. data = webnotes._dict(webnotes.cache().get_value("session:" + self.sid) or {})
  128. if data:
  129. session_data = data.get("data", {})
  130. self.time_diff = webnotes.utils.time_diff_in_seconds(webnotes.utils.now(),
  131. session_data.get("last_updated"))
  132. expiry = self.get_expiry_in_seconds(session_data.get("session_expiry"))
  133. if self.time_diff > expiry:
  134. self.delete_session()
  135. data = None
  136. return data and data.data
  137. def get_session_data_from_db(self):
  138. if self.sid=="Guest":
  139. rec = webnotes.conn.sql("""select user, sessiondata from
  140. tabSessions where sid='Guest' """)
  141. else:
  142. rec = webnotes.conn.sql("""select user, sessiondata
  143. from tabSessions where sid=%s and
  144. TIMEDIFF(NOW(), lastupdate) < TIME(%s)""", (self.sid,
  145. self.get_expiry_period()))
  146. if rec:
  147. data = webnotes._dict(eval(rec and rec[0][1] or '{}'))
  148. data.user = rec[0][0]
  149. else:
  150. self.delete_session()
  151. data = None
  152. return data
  153. def get_expiry_in_seconds(self, expiry):
  154. if not expiry: return 3600
  155. parts = expiry.split(":")
  156. return (cint(parts[0]) * 3600) + (cint(parts[1]) * 60) + cint(parts[2])
  157. def delete_session(self):
  158. webnotes.cache().delete_value("session:" + self.sid)
  159. r = webnotes.conn.sql("""delete from tabSessions where sid=%s""", self.sid)
  160. def start_as_guest(self):
  161. """all guests share the same 'Guest' session"""
  162. webnotes.login_manager.login_as_guest()
  163. self.start()
  164. def update(self):
  165. """extend session expiry"""
  166. self.data['data']['last_updated'] = webnotes.utils.now()
  167. if webnotes.user_lang:
  168. # user language
  169. self.data['data']['lang'] = webnotes.lang
  170. # update session in db
  171. time_diff = None
  172. last_updated = webnotes.cache().get_value("last_db_session_update:" + self.sid)
  173. if last_updated:
  174. time_diff = webnotes.utils.time_diff_in_seconds(webnotes.utils.now(),
  175. last_updated)
  176. if webnotes.session['user'] != 'Guest' and \
  177. ((time_diff==None) or (time_diff > 1800)):
  178. # database persistence is secondary, don't update it too often
  179. webnotes.conn.sql("""update tabSessions set sessiondata=%s,
  180. lastupdate=NOW() where sid=%s""" , (str(self.data['data']),
  181. self.data['sid']))
  182. if webnotes.request.cmd not in ("webnotes.sessions.clear", "logout"):
  183. webnotes.cache().set_value("last_db_session_update:" + self.sid,
  184. webnotes.utils.now())
  185. webnotes.cache().set_value("session:" + self.sid, self.data)
  186. def get_expiry_period(self):
  187. exp_sec = webnotes.defaults.get_global_default("session_expiry") or "06:00:00"
  188. # incase seconds is missing
  189. if exp_sec:
  190. if len(exp_sec.split(':')) == 2:
  191. exp_sec = exp_sec + ':00'
  192. else:
  193. exp_sec = "2:00:00"
  194. return exp_sec
  195. def get_geo_ip_country(ip_addr):
  196. try:
  197. import pygeoip
  198. except ImportError:
  199. return
  200. import os
  201. from webnotes.utils import get_base_path
  202. geo_ip_file = os.path.join(get_base_path(), "lib", "data", "GeoIP.dat")
  203. geo_ip = pygeoip.GeoIP(geo_ip_file, pygeoip.MEMORY_CACHE)
  204. return geo_ip.country_name_by_addr(ip_addr)