選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

457 行
13 KiB

  1. import webnotes
  2. import webnotes.db
  3. import webnotes.utils
  4. import webnotes.profile
  5. import webnotes.defs
  6. # =================================================================================
  7. # HTTPRequest
  8. # =================================================================================
  9. class HTTPRequest:
  10. def __init__(self):
  11. # Get Environment variables
  12. self.domain = webnotes.get_env_vars('HTTP_HOST')
  13. if self.domain and self.domain.startswith('www.'):
  14. self.domain = self.domain[4:]
  15. webnotes.remote_ip = webnotes.get_env_vars('REMOTE_ADDR')
  16. # load cookies
  17. webnotes.cookie_manager = CookieManager()
  18. # set db
  19. self.set_db()
  20. # check status
  21. if webnotes.conn.get_global("__session_status")=='stop':
  22. webnotes.msgprint(webnotes.conn.get_global("__session_status_message"))
  23. raise Exception
  24. # -----------------------------
  25. # start transaction
  26. webnotes.conn.begin()
  27. # login
  28. webnotes.login_manager = LoginManager()
  29. # start session
  30. webnotes.session_obj = Session()
  31. webnotes.session = webnotes.session_obj.data
  32. # write out cookies if sid is supplied (this is a pre-logged in redirect)
  33. if webnotes.form_dict.get('sid'):
  34. webnotes.cookie_manager.set_cookies()
  35. # run login triggers
  36. if webnotes.form_dict.get('cmd')=='login':
  37. webnotes.login_manager.run_trigger('on_login_post_session')
  38. # load profile
  39. self.setup_profile()
  40. webnotes.conn.commit()
  41. # end transaction
  42. # -----------------------------
  43. # setup profile
  44. # -------------
  45. def setup_profile(self):
  46. webnotes.user = webnotes.profile.Profile()
  47. # load the profile data
  48. if webnotes.session['data'].get('profile'):
  49. webnotes.user.load_from_session(webnotes.session['data']['profile'])
  50. else:
  51. webnotes.user.load_profile()
  52. # set database login
  53. # ------------------
  54. def get_db_name(self):
  55. # highest priority if comes via form
  56. if webnotes.form_dict.get('ac_name'):
  57. db_name = webnotes.form_dict.get('ac_name')
  58. elif webnotes.form_dict.get('acx'):
  59. db_name = webnotes.form_dict.get('acx')
  60. # then from cookie
  61. elif webnotes.incoming_cookies.get('account_id'):
  62. db_name = webnotes.incoming_cookies.get('account_id')
  63. # then via defs
  64. elif hasattr(webnotes.defs, 'get_db_name'):
  65. db_name = webnotes.defs.get_db_name()
  66. # then default
  67. else:
  68. db_name = getattr(webnotes.defs,'default_db_name','')
  69. if not db_name:
  70. raise Exception, "Unable to resolve database name"
  71. return db_name
  72. def set_db(self, ac_name = None):
  73. """connect to db, from ac_name or db_name"""
  74. webnotes.conn = webnotes.db.Database(user = self.get_db_name(), \
  75. password = getattr(webnotes.defs,'db_password', ''))
  76. # =================================================================================
  77. # Login Manager
  78. # =================================================================================
  79. class LoginManager:
  80. def __init__(self):
  81. self.cp = None
  82. if webnotes.form_dict.get('cmd')=='login':
  83. # clear cache
  84. from webnotes.session_cache import clear_cache
  85. clear_cache(webnotes.form_dict.get('usr'))
  86. self.authenticate()
  87. self.post_login()
  88. webnotes.response['message'] = 'Logged In'
  89. # run triggers, write cookies
  90. # ---------------------------
  91. def post_login(self):
  92. self.run_trigger()
  93. self.validate_ip_address()
  94. self.validate_hour()
  95. # check password
  96. # --------------
  97. def authenticate(self, user=None, pwd=None):
  98. if not (user and pwd):
  99. user, pwd = webnotes.form_dict.get('usr'), webnotes.form_dict.get('pwd')
  100. if not (user and pwd):
  101. webnotes.response['message'] = 'Incomplete Login Details'
  102. raise Exception
  103. # custom authentication (for single-sign on)
  104. self.load_control_panel()
  105. if hasattr(self.cp, 'authenticate'):
  106. self.user = self.cp.authenticate()
  107. # check the password
  108. if user=='Administrator':
  109. p = webnotes.conn.sql("""select name, first_name, last_name
  110. from tabProfile where name=%s
  111. and (`password`=%s OR `password`=PASSWORD(%s))""", (user, pwd, pwd), as_dict=1)
  112. else:
  113. p = webnotes.conn.sql("""select name, first_name, last_name
  114. from tabProfile where name=%s
  115. and (`password`=%s OR `password`=PASSWORD(%s))
  116. and IFNULL(enabled,0)=1""", (user, pwd, pwd), as_dict=1)
  117. if not p:
  118. webnotes.response['message'] = 'Authentication Failed'
  119. raise Exception
  120. #webnotes.msgprint('Authentication Failed',raise_exception=1)
  121. p = p[0]
  122. self.user = p['name']
  123. self.user_fullname = (p.get('first_name') and (p.get('first_name') + ' ') or '') \
  124. + (p.get('last_name') or '')
  125. # triggers
  126. # --------
  127. def load_control_panel(self):
  128. import webnotes.model.code
  129. try:
  130. if not self.cp:
  131. self.cp = webnotes.model.code.get_obj('Control Panel')
  132. except Exception, e:
  133. webnotes.response['Control Panel Exception'] = webnotes.utils.getTraceback()
  134. # --------
  135. def run_trigger(self, method='on_login'):
  136. try:
  137. from startup import event_handlers
  138. if hasattr(event_handlers, method):
  139. getattr(event_handlers, method)(self)
  140. return
  141. except ImportError, e:
  142. webnotes.errprint(str(e))
  143. # deprecated
  144. self.load_control_panel()
  145. if self.cp and hasattr(self.cp, method):
  146. getattr(self.cp, method)(self)
  147. # ip validation
  148. # -------------
  149. def validate_ip_address(self):
  150. ip_list = webnotes.conn.get_value('Profile', self.user, 'restrict_ip', ignore=True)
  151. if not ip_list:
  152. return
  153. ip_list = ip_list.replace(",", "\n").split('\n')
  154. ip_list = [i.strip() for i in ip_list]
  155. for ip in ip_list:
  156. if webnotes.remote_ip.startswith(ip):
  157. return
  158. elif webnotes.form_dict.get('via_ip') and webnotes.form_dict.get('via_ip').startswith(ip):
  159. return
  160. webnotes.msgprint('Not allowed from this IP Address', raise_exception=1)
  161. def validate_hour(self):
  162. """
  163. check if user is logging in during restricted hours
  164. """
  165. login_before = int(webnotes.conn.get_value('Profile', self.user, 'login_before', ignore=True) or 0)
  166. login_after = int(webnotes.conn.get_value('Profile', self.user, 'login_after', ignore=True) or 0)
  167. if not (login_before or login_after):
  168. return
  169. from webnotes.utils import now_datetime
  170. current_hour = int(now_datetime().strftime('%H'))
  171. if login_before and current_hour > login_before:
  172. webnotes.msgprint('Not allowed to login after restricted hour', raise_exception=1)
  173. if login_after and current_hour < login_after:
  174. webnotes.msgprint('Not allowed to login before restricted hour', raise_exception=1)
  175. # login as guest
  176. # --------------
  177. def login_as_guest(self):
  178. self.user = 'Guest'
  179. self.post_login()
  180. # Logout
  181. # ------
  182. def call_on_logout_event(self):
  183. import webnotes.model.code
  184. cp = webnotes.model.code.get_obj('Control Panel', 'Control Panel')
  185. if hasattr(cp, 'on_logout'):
  186. cp.on_logout(self)
  187. def logout(self, arg='', user=None):
  188. if not user: user = webnotes.session.get('user')
  189. self.user = user
  190. self.run_trigger('on_logout')
  191. webnotes.conn.sql('delete from tabSessions where user=%s', user)
  192. # =================================================================================
  193. # Cookie Manager
  194. # =================================================================================
  195. class CookieManager:
  196. def __init__(self):
  197. import Cookie
  198. webnotes.cookies = Cookie.SimpleCookie()
  199. self.get_incoming_cookies()
  200. # get incoming cookies
  201. # --------------------
  202. def get_incoming_cookies(self):
  203. import os
  204. cookies = {}
  205. if 'HTTP_COOKIE' in os.environ:
  206. c = os.environ['HTTP_COOKIE']
  207. webnotes.cookies.load(c)
  208. for c in webnotes.cookies.values():
  209. cookies[c.key] = c.value
  210. webnotes.incoming_cookies = cookies
  211. # Set cookies
  212. # -----------
  213. def set_cookies(self):
  214. if webnotes.form_dict.get('cmd')=='logout':
  215. webnotes.cookies['account_id'] = ''
  216. else:
  217. webnotes.cookies['account_id'] = webnotes.conn.cur_db_name
  218. if webnotes.session.get('sid'):
  219. webnotes.cookies['sid'] = webnotes.session['sid']
  220. # sid expires in 3 days
  221. import datetime
  222. expires = datetime.datetime.now() + datetime.timedelta(days=3)
  223. webnotes.cookies['sid']['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S')
  224. # Set Remember Me
  225. # ---------------
  226. def set_remember_me(self):
  227. if webnotes.utils.cint(webnotes.form_dict.get('remember_me')):
  228. remember_days = webnotes.conn.get_value('Control Panel',None,'remember_for_days') or 7
  229. webnotes.cookies['remember_me'] = 1
  230. import datetime
  231. expires = datetime.datetime.now() + datetime.timedelta(days=remember_days)
  232. for k in webnotes.cookies.keys():
  233. webnotes.cookies[k]['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S')
  234. # =================================================================================
  235. # Session
  236. # =================================================================================
  237. class Session:
  238. def __init__(self, user=None):
  239. self.user = user
  240. self.sid = webnotes.form_dict.get('sid') or webnotes.incoming_cookies.get('sid')
  241. self.data = {'user':user,'data':{}}
  242. if webnotes.form_dict.get('cmd')=='login':
  243. self.start()
  244. return
  245. self.load()
  246. # start a session
  247. # ---------------
  248. def get_session_record(self):
  249. """get session record, or return the standard Guest Record"""
  250. r = webnotes.conn.sql("""select user, sessiondata, status from
  251. tabSessions where sid='%s'""" % self.sid)
  252. if not r:
  253. # return guest record if present
  254. self.sid = 'Guest'
  255. r = webnotes.conn.sql("""select user, sessiondata, status from
  256. tabSessions where sid='%s'""" % self.sid)
  257. return r
  258. def load(self):
  259. import webnotes
  260. r = self.get_session_record()
  261. if r:
  262. r=r[0]
  263. # ExipredSession
  264. if r[2]=='Expired' and (webnotes.form_dict.get('cmd')!='resume_session'):
  265. if r[0]=='Guest' or (not webnotes.form_dict.get('cmd')) or webnotes.form_dict.get('cmd')=='logout':
  266. self.start_as_guest()
  267. else:
  268. webnotes.response['session_status'] = 'Session Expired'
  269. raise Exception, 'Session Expired'
  270. elif r[2]=='Logged Out':
  271. self.start_as_guest()
  272. # allow refresh or logout
  273. if webnotes.form_dict.get('cmd') and webnotes.form_dict.get('cmd')!='logout':
  274. webnotes.response['session_status'] = 'Logged Out'
  275. raise Exception, 'Logged Out'
  276. else:
  277. self.data = {'data': (r[1] and eval(r[1]) or {}),
  278. 'user':r[0], 'sid': self.sid}
  279. else:
  280. self.start_as_guest()
  281. def start_as_guest(self):
  282. """all guests share the same 'Guest' session"""
  283. webnotes.login_manager.login_as_guest()
  284. self.start()
  285. # start a session
  286. # ---------------
  287. def start(self):
  288. import os
  289. import webnotes
  290. import webnotes.utils
  291. # generate sid
  292. if webnotes.login_manager.user=='Guest':
  293. sid = 'Guest'
  294. else:
  295. sid = webnotes.utils.generate_hash()
  296. self.data['user'] = webnotes.login_manager.user
  297. self.data['sid'] = sid
  298. self.data['data']['session_ip'] = os.environ.get('REMOTE_ADDR');
  299. self.data['data']['tenant_id'] = webnotes.form_dict.get('tenant_id', 0)
  300. # get ipinfo
  301. if webnotes.conn.get_global('get_ip_info'):
  302. self.get_ipinfo()
  303. # insert session
  304. try:
  305. self.insert_session_record()
  306. except Exception, e:
  307. if e.args[0]==1054:
  308. self.add_status_column()
  309. self.insert_session_record()
  310. else:
  311. raise e
  312. # update profile
  313. webnotes.conn.sql("UPDATE tabProfile SET last_login = '%s', last_ip = '%s' where name='%s'" % (webnotes.utils.now(), webnotes.remote_ip, self.data['user']))
  314. # set cookies to write
  315. webnotes.session = self.data
  316. webnotes.cookie_manager.set_cookies()
  317. # resume session
  318. # --------------
  319. def resume(self):
  320. pwd = webnotes.form_dict.get('pwd')
  321. webnotes.login_manager.authenticate(self.data['user'], pwd)
  322. webnotes.conn.sql("update tabSessions set status='Active' where sid=%s", self.data['sid'])
  323. return 'Logged In'
  324. # update session
  325. # --------------
  326. def update(self):
  327. # update session
  328. if webnotes.session['user'] != 'Guest':
  329. webnotes.conn.sql("""update tabSessions set sessiondata=%s, user=%s, lastupdate=NOW()
  330. where sid=%s""" , (str(self.data['data']), self.data['user'], self.data['sid']))
  331. self.check_expired()
  332. # check expired
  333. # -------------
  334. def check_expired(self):
  335. """expire non-guest sessions"""
  336. exp_sec = webnotes.conn.get_value('Control Panel', None, 'session_expiry') or '6:00:00'
  337. # set sessions as expired
  338. try:
  339. webnotes.conn.sql("""update tabSessions where TIMEDIFF(NOW(), lastupdate) >
  340. %s and sid!='Guest' SET `status`='Expired'""", exp_sec)
  341. except Exception, e:
  342. if e.args[0]==1054:
  343. self.add_status_column()
  344. # clear out old sessions
  345. webnotes.conn.sql("""delete from tabSessions where TIMEDIFF(NOW(), lastupdate)
  346. > '72:00:00' and sid!='Guest'""")
  347. # Get IP Info from ipinfodb.com
  348. # -----------------------------
  349. def get_ipinfo(self):
  350. import os
  351. try:
  352. import pygeoip
  353. except:
  354. return
  355. gi = pygeoip.GeoIP('data/GeoIP.dat')
  356. self.data['data']['ipinfo'] = {'countryName': gi.country_name_by_addr(os.environ.get('REMOTE_ADDR'))}
  357. # -----------------------------
  358. def insert_session_record(self):
  359. webnotes.conn.sql("insert into tabSessions (sessiondata, user, lastupdate, sid, status) values (%s , %s, NOW(), %s, 'Active')", (str(self.data['data']), self.data['user'], self.data['sid']))