25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sessions.py 7.7 KiB

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