Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

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