Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

sessions.py 8.3 KiB

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