You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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