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.
 
 
 
 
 
 

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