1
0

utils.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #-*- coding:utf-8 -*-
  2. # Copyright 2017 Xiaomi, Inc.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import json
  16. import requests
  17. from flask import g, redirect, session, abort, request
  18. from functools import wraps
  19. from rrd import config
  20. from rrd import corelib
  21. from rrd.utils import randbytes
  22. from rrd.model.user import User, UserToken
  23. from rrd.utils.logger import logging
  24. log = logging.getLogger(__file__)
  25. def remote_ip():
  26. if not request.headers.getlist("X-Forward-For"):
  27. return request.remote_addr
  28. else:
  29. return request.headers.getlist("X-Forward-For")[0]
  30. def require_login(redir="/auth/login"):
  31. def _(f):
  32. @wraps(f)
  33. def __(*a, **kw):
  34. if not g.user:
  35. return redirect(redir or "/auth/login")
  36. return f(*a, **kw)
  37. return __
  38. return _
  39. def require_login_abort(status_code=403, msg="login first"):
  40. def _(f):
  41. @wraps(f)
  42. def __(*a, **kw):
  43. if not g.user:
  44. return abort(status_code, msg)
  45. return f(*a, **kw)
  46. return __
  47. return _
  48. def require_login_json(json_msg={"ok":False, "msg":"login first"}):
  49. def _(f):
  50. @wraps(f)
  51. def __(*a, **kw):
  52. if not g.user:
  53. return json.dumps(json_msg)
  54. return f(*a, **kw)
  55. return __
  56. return _
  57. def set_user_cookie(user_token, session_):
  58. if not user_token:
  59. return None
  60. session_[config.SITE_COOKIE] = "%s:%s" % (user_token.name, user_token.sig)
  61. def clear_user_cookie(session_):
  62. session_[config.SITE_COOKIE] = ""
  63. def get_usertoken_from_session(session_):
  64. if config.SITE_COOKIE in session_:
  65. cookies = session_[config.SITE_COOKIE]
  66. if not cookies:
  67. return None
  68. name, sig = cookies.split(":")
  69. return UserToken(name, sig)
  70. def get_current_user_profile(user_token):
  71. if not user_token:
  72. return
  73. h = {"Content-type": "application/json"}
  74. r = corelib.auth_requests("GET", "%s/user/current" %config.API_ADDR, headers=h)
  75. if r.status_code != 200:
  76. return
  77. j = r.json()
  78. return User(j["id"], j["name"], j["cnname"], j["email"], j["phone"], j["im"], j["qq"], j["role"])
  79. def logout_user(user_token):
  80. if not user_token:
  81. return
  82. r = corelib.auth_requests("GET", "%s/user/logout" %config.API_ADDR)
  83. if r.status_code != 200:
  84. raise Exception("%s:%s" %(r.status_code, r.text))
  85. clear_user_cookie(session)
  86. def login_user(name, password):
  87. params = {
  88. "name": name,
  89. "password": password,
  90. }
  91. r = requests.post("%s/user/login" %config.API_ADDR, data=params)
  92. if r.status_code != 200:
  93. raise Exception("%s : %s" %(r.status_code, r.text))
  94. j = r.json()
  95. ut = UserToken(j["name"], j["sig"])
  96. set_user_cookie(ut, session)
  97. return ut
  98. def admin_login_user(name, Apitoken):
  99. params = {
  100. "name": name,
  101. }
  102. h = {
  103. "Apitoken": Apitoken
  104. }
  105. r = requests.post("%s/admin/login" %config.API_ADDR, data=params, headers=h)
  106. log.debug("%s:%s" %(r.status_code, r.text))
  107. if r.status_code != 200:
  108. if json.loads(r.text)["error"] == "no such user":
  109. return None
  110. else:
  111. raise Exception("%s : %s" %(r.status_code, r.text))
  112. j = r.json()
  113. ut = UserToken(j["name"], j["sig"])
  114. set_user_cookie(ut, session)
  115. return ut
  116. def ldap_login_user(name, password):
  117. import ldap
  118. if not config.LDAP_ENABLED:
  119. raise Exception("ldap not enabled")
  120. bind_dn = config.LDAP_BINDDN
  121. bind_pass = config.LDAP_BIND_PASS
  122. base_dn = config.LDAP_BASE_DN
  123. search_filter = config.LDAP_SEARCH_FMT
  124. try:
  125. search_filter = config.LDAP_SEARCH_FMT %name
  126. except TypeError: pass
  127. cli = None
  128. try:
  129. ldap_server = config.LDAP_SERVER if (config.LDAP_SERVER.startswith("ldap://") or config.LDAP_SERVER.startswith("ldaps://")) else "ldaps://%s" % config.LDAP_SERVER if config.LDAP_TLS_START_TLS else "ldap://%s" % config.LDAP_SERVER
  130. log.debug("ldap_server:%s bind_dn:%s base_dn:%s filter:%s attrs:%s" %(ldap_server, bind_dn, config.LDAP_BASE_DN, search_filter, config.LDAP_ATTRS))
  131. cli = ldap.initialize(ldap_server)
  132. cli.protocol_version = ldap.VERSION3
  133. if config.LDAP_TLS_START_TLS or ldap_server.startswith('ldaps://'):
  134. if config.LDAP_TLS_CACERTFILE:
  135. cli.set_option(ldap.OPT_X_TLS_CACERTFILE, config.LDAP_TLS_CACERTFILE)
  136. if config.LDAP_TLS_CERTFILE:
  137. cli.set_option(ldap.OPT_X_TLS_CERTFILE, config.LDAP_TLS_CERTFILE)
  138. if config.LDAP_TLS_KEYFILE:
  139. cli.set_option(ldap.OPT_X_TLS_KEYFILE, config.LDAP_TLS_KEYFILE)
  140. if config.LDAP_TLS_REQUIRE_CERT:
  141. cli.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, config.LDAP_TLS_REQUIRE_CERT)
  142. if config.LDAP_TLS_CIPHER_SUITE:
  143. cli.set_option(ldap.OPT_X_TLS_CIPHER_SUITE, config.LDAP_TLS_CIPHER_SUITE)
  144. cli.bind_s(bind_dn, bind_pass, ldap.AUTH_SIMPLE)
  145. result = cli.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, config.LDAP_ATTRS)
  146. log.debug("ldap result: %s" % result)
  147. user_dn = result[0][0]
  148. cli.bind_s(user_dn, password, ldap.AUTH_SIMPLE)
  149. d = result[0][1]
  150. email = d['mail'][0]
  151. cnname = d['cn'][0]
  152. if 'sn' in d and 'givenName' in d:
  153. cnname = d['givenName'][0] + ' ' + d['sn'][0]
  154. if 'displayName' in d:
  155. cnname = d['displayName'][0]
  156. if 'telephoneNumber' in d:
  157. phone = d['telephoneNumber'] and d['telephoneNumber'][0] or ""
  158. else:
  159. phone = ""
  160. return {
  161. "name": name,
  162. "password": password,
  163. "cnname": cnname,
  164. "email": email,
  165. "phone": phone,
  166. }
  167. except ldap.LDAPError as e:
  168. if "desc" in e[0]:
  169. raise NameError(e[0]["desc"])
  170. cli and cli.unbind_s()
  171. raise e
  172. except (IndexError, KeyError) as e:
  173. if str(e) == "list index out of range":
  174. raise IndexError("no such user")
  175. # result = [], so result out of range
  176. raise e
  177. finally:
  178. cli and cli.unbind_s()
  179. def get_Apitoken(name, password):
  180. d = {
  181. "name": name, "password": password,
  182. }
  183. h = {"Content-type":"application/json"}
  184. r = requests.post("%s/user/login" %(config.API_ADDR,), \
  185. data=json.dumps(d), headers=h)
  186. log.debug("%s:%s" %(r.status_code, r.text))
  187. if r.status_code != 200:
  188. raise Exception("%s %s" %(r.status_code, r.text))
  189. sig = json.loads(r.text)["sig"]
  190. return json.dumps({"name":name,"sig":sig})
  191. def create_user(user_info):
  192. h = {"Content-type":"application/json"}
  193. r = requests.post("%s/user/create" %(config.API_ADDR,), \
  194. data=json.dumps(user_info), headers=h)
  195. log.debug("%s:%s" %(r.status_code, r.text))
  196. if r.status_code != 200:
  197. raise Exception("%s %s" %(r.status_code, r.text))
  198. return