Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

338 linhas
10 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import datetime
  5. from frappe import _
  6. import frappe
  7. import frappe.database
  8. import frappe.utils
  9. from frappe.utils import cint
  10. import frappe.utils.user
  11. from frappe import conf
  12. from frappe.sessions import Session, clear_sessions, delete_session
  13. from frappe.modules.patch_handler import check_session_stopped
  14. from frappe.translate import get_lang_code
  15. from frappe.utils.password import check_password
  16. from frappe.core.doctype.activity_log.activity_log import add_authentication_log
  17. from frappe.utils.background_jobs import enqueue
  18. from frappe.twofactor import (should_run_2fa, authenticate_for_2factor,
  19. confirm_otp_token, get_cached_user_pass)
  20. from six.moves.urllib.parse import quote
  21. import pyotp, base64, os
  22. class HTTPRequest:
  23. def __init__(self):
  24. # Get Environment variables
  25. self.domain = frappe.request.host
  26. if self.domain and self.domain.startswith('www.'):
  27. self.domain = self.domain[4:]
  28. if frappe.get_request_header('X-Forwarded-For'):
  29. frappe.local.request_ip = (frappe.get_request_header('X-Forwarded-For').split(",")[0]).strip()
  30. elif frappe.get_request_header('REMOTE_ADDR'):
  31. frappe.local.request_ip = frappe.get_request_header('REMOTE_ADDR')
  32. else:
  33. frappe.local.request_ip = '127.0.0.1'
  34. # language
  35. self.set_lang()
  36. # load cookies
  37. frappe.local.cookie_manager = CookieManager()
  38. # set db
  39. self.connect()
  40. # login
  41. frappe.local.login_manager = LoginManager()
  42. if frappe.form_dict._lang:
  43. lang = get_lang_code(frappe.form_dict._lang)
  44. if lang:
  45. frappe.local.lang = lang
  46. self.validate_csrf_token()
  47. # write out latest cookies
  48. frappe.local.cookie_manager.init_cookies()
  49. # check status
  50. check_session_stopped()
  51. def validate_csrf_token(self):
  52. if frappe.local.request and frappe.local.request.method=="POST":
  53. if not frappe.local.session: return
  54. if not frappe.local.session.data.csrf_token \
  55. or frappe.local.session.data.device=="mobile" \
  56. or frappe.conf.get('ignore_csrf', None):
  57. # not via boot
  58. return
  59. csrf_token = frappe.get_request_header("X-Frappe-CSRF-Token")
  60. if not csrf_token and "csrf_token" in frappe.local.form_dict:
  61. csrf_token = frappe.local.form_dict.csrf_token
  62. del frappe.local.form_dict["csrf_token"]
  63. if frappe.local.session.data.csrf_token != csrf_token:
  64. frappe.local.flags.disable_traceback = True
  65. frappe.throw(_("Invalid Request"), frappe.CSRFTokenError)
  66. def set_lang(self):
  67. from frappe.translate import guess_language
  68. frappe.local.lang = guess_language()
  69. def get_db_name(self):
  70. """get database name from conf"""
  71. return conf.db_name
  72. def connect(self, ac_name = None):
  73. """connect to db, from ac_name or db_name"""
  74. frappe.local.db = frappe.database.Database(user = self.get_db_name(), \
  75. password = getattr(conf, 'db_password', ''))
  76. class LoginManager:
  77. def __init__(self):
  78. self.user = None
  79. self.info = None
  80. self.full_name = None
  81. self.user_type = None
  82. if frappe.local.form_dict.get('cmd')=='login' or frappe.local.request.path=="/api/method/login":
  83. if self.login()==False: return
  84. self.resume = False
  85. # run login triggers
  86. self.run_trigger('on_session_creation')
  87. else:
  88. try:
  89. self.resume = True
  90. self.make_session(resume=True)
  91. self.set_user_info(resume=True)
  92. except AttributeError:
  93. self.user = "Guest"
  94. self.make_session()
  95. self.set_user_info()
  96. def login(self):
  97. # clear cache
  98. frappe.clear_cache(user = frappe.form_dict.get('usr'))
  99. user, pwd = get_cached_user_pass()
  100. self.authenticate(user=user, pwd=pwd)
  101. if should_run_2fa(self.user):
  102. authenticate_for_2factor(self.user)
  103. if not confirm_otp_token(self):
  104. return False
  105. self.post_login()
  106. def post_login(self):
  107. self.run_trigger('on_login')
  108. self.validate_ip_address()
  109. self.validate_hour()
  110. self.make_session()
  111. self.set_user_info()
  112. def set_user_info(self, resume=False):
  113. # set sid again
  114. frappe.local.cookie_manager.init_cookies()
  115. self.info = frappe.db.get_value("User", self.user,
  116. ["user_type", "first_name", "last_name", "user_image"], as_dict=1)
  117. self.full_name = " ".join(filter(None, [self.info.first_name,
  118. self.info.last_name]))
  119. self.user_type = self.info.user_type
  120. if self.info.user_type=="Website User":
  121. frappe.local.cookie_manager.set_cookie("system_user", "no")
  122. if not resume:
  123. frappe.local.response["message"] = "No App"
  124. frappe.local.response["home_page"] = get_website_user_home_page(self.user)
  125. else:
  126. frappe.local.cookie_manager.set_cookie("system_user", "yes")
  127. if not resume:
  128. frappe.local.response['message'] = 'Logged In'
  129. frappe.local.response["home_page"] = "/desk"
  130. if not resume:
  131. frappe.response["full_name"] = self.full_name
  132. # redirect information
  133. redirect_to = frappe.cache().hget('redirect_after_login', self.user)
  134. if redirect_to:
  135. frappe.local.response["redirect_to"] = redirect_to
  136. frappe.cache().hdel('redirect_after_login', self.user)
  137. frappe.local.cookie_manager.set_cookie("full_name", self.full_name)
  138. frappe.local.cookie_manager.set_cookie("user_id", self.user)
  139. frappe.local.cookie_manager.set_cookie("user_image", self.info.user_image or "")
  140. def make_session(self, resume=False):
  141. # start session
  142. frappe.local.session_obj = Session(user=self.user, resume=resume,
  143. full_name=self.full_name, user_type=self.user_type)
  144. # reset user if changed to Guest
  145. self.user = frappe.local.session_obj.user
  146. frappe.local.session = frappe.local.session_obj.data
  147. self.clear_active_sessions()
  148. def clear_active_sessions(self):
  149. """Clear other sessions of the current user if `deny_multiple_sessions` is not set"""
  150. if not (cint(frappe.conf.get("deny_multiple_sessions")) or cint(frappe.db.get_system_setting('deny_multiple_sessions'))):
  151. return
  152. if frappe.session.user != "Guest":
  153. clear_sessions(frappe.session.user, keep_current=True)
  154. def authenticate(self, user=None, pwd=None):
  155. if not (user and pwd):
  156. user, pwd = frappe.form_dict.get('usr'), frappe.form_dict.get('pwd')
  157. if not (user and pwd):
  158. self.fail(_('Incomplete login details'), user=user)
  159. if cint(frappe.db.get_value("System Settings", "System Settings", "allow_login_using_mobile_number")):
  160. user = frappe.db.get_value("User", filters={"mobile_no": user}, fieldname="name") or user
  161. if cint(frappe.db.get_value("System Settings", "System Settings", "allow_login_using_user_name")):
  162. user = frappe.db.get_value("User", filters={"username": user}, fieldname="name") or user
  163. self.check_if_enabled(user)
  164. self.user = self.check_password(user, pwd)
  165. def check_if_enabled(self, user):
  166. """raise exception if user not enabled"""
  167. if user=='Administrator': return
  168. if not cint(frappe.db.get_value('User', user, 'enabled')):
  169. self.fail('User disabled or missing', user=user)
  170. def check_password(self, user, pwd):
  171. """check password"""
  172. try:
  173. # returns user in correct case
  174. return check_password(user, pwd)
  175. except frappe.AuthenticationError:
  176. self.fail('Incorrect password', user=user)
  177. def fail(self, message, user=None):
  178. if not user:
  179. user = _('Unknown User')
  180. frappe.local.response['message'] = message
  181. add_authentication_log(message, user, status="Failed")
  182. frappe.db.commit()
  183. raise frappe.AuthenticationError
  184. def run_trigger(self, event='on_login'):
  185. for method in frappe.get_hooks().get(event, []):
  186. frappe.call(frappe.get_attr(method), login_manager=self)
  187. def validate_ip_address(self):
  188. """check if IP Address is valid"""
  189. ip_list = frappe.db.get_value('User', self.user, 'restrict_ip', ignore=True)
  190. if not ip_list:
  191. return
  192. ip_list = ip_list.replace(",", "\n").split('\n')
  193. ip_list = [i.strip() for i in ip_list]
  194. for ip in ip_list:
  195. if frappe.local.request_ip.startswith(ip):
  196. return
  197. frappe.throw(_("Not allowed from this IP Address"), frappe.AuthenticationError)
  198. def validate_hour(self):
  199. """check if user is logging in during restricted hours"""
  200. login_before = int(frappe.db.get_value('User', self.user, 'login_before', ignore=True) or 0)
  201. login_after = int(frappe.db.get_value('User', self.user, 'login_after', ignore=True) or 0)
  202. if not (login_before or login_after):
  203. return
  204. from frappe.utils import now_datetime
  205. current_hour = int(now_datetime().strftime('%H'))
  206. if login_before and current_hour > login_before:
  207. frappe.throw(_("Login not allowed at this time"), frappe.AuthenticationError)
  208. if login_after and current_hour < login_after:
  209. frappe.throw(_("Login not allowed at this time"), frappe.AuthenticationError)
  210. def login_as_guest(self):
  211. """login as guest"""
  212. self.login_as("Guest")
  213. def login_as(self, user):
  214. self.user = user
  215. self.post_login()
  216. def logout(self, arg='', user=None):
  217. if not user: user = frappe.session.user
  218. self.run_trigger('on_logout')
  219. if user == frappe.session.user:
  220. delete_session(frappe.session.sid, user=user, reason="User Manually Logged Out")
  221. self.clear_cookies()
  222. else:
  223. clear_sessions(user)
  224. def clear_cookies(self):
  225. clear_cookies()
  226. class CookieManager:
  227. def __init__(self):
  228. self.cookies = {}
  229. self.to_delete = []
  230. def init_cookies(self):
  231. if not frappe.local.session.get('sid'): return
  232. # sid expires in 3 days
  233. expires = datetime.datetime.now() + datetime.timedelta(days=3)
  234. if frappe.session.sid:
  235. self.cookies["sid"] = {"value": frappe.session.sid, "expires": expires}
  236. if frappe.session.session_country:
  237. self.cookies["country"] = {"value": frappe.session.get("session_country")}
  238. def set_cookie(self, key, value, expires=None):
  239. self.cookies[key] = {"value": value, "expires": expires}
  240. def delete_cookie(self, to_delete):
  241. if not isinstance(to_delete, (list, tuple)):
  242. to_delete = [to_delete]
  243. self.to_delete.extend(to_delete)
  244. def flush_cookies(self, response):
  245. for key, opts in self.cookies.items():
  246. response.set_cookie(key, quote((opts.get("value") or "").encode('utf-8')),
  247. expires=opts.get("expires"))
  248. # expires yesterday!
  249. expires = datetime.datetime.now() + datetime.timedelta(days=-1)
  250. for key in set(self.to_delete):
  251. response.set_cookie(key, "", expires=expires)
  252. @frappe.whitelist()
  253. def get_logged_user():
  254. return frappe.session.user
  255. def clear_cookies():
  256. if hasattr(frappe.local, "session"):
  257. frappe.session.sid = ""
  258. frappe.local.cookie_manager.delete_cookie(["full_name", "user_id", "sid", "user_image", "system_user"])
  259. def get_website_user_home_page(user):
  260. home_page_method = frappe.get_hooks('get_website_user_home_page')
  261. if home_page_method:
  262. home_page = frappe.get_attr(home_page_method[-1])(user)
  263. return '/' + home_page.strip('/')
  264. else:
  265. return '/me'