utils.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 ldap_login_user(name, password):
  99. import ldap
  100. if not config.LDAP_ENABLED:
  101. raise Exception("ldap not enabled")
  102. bind_dn = config.LDAP_BINDDN_FMT
  103. base_dn = config.LDAP_BASE_DN
  104. try:
  105. bind_dn = config.LDAP_BINDDN_FMT %name
  106. except TypeError: pass
  107. search_filter = config.LDAP_SEARCH_FMT
  108. try:
  109. search_filter = config.LDAP_SEARCH_FMT %name
  110. except TypeError: pass
  111. cli = None
  112. try:
  113. 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
  114. 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))
  115. cli = ldap.initialize(ldap_server)
  116. cli.protocol_version = ldap.VERSION3
  117. if config.LDAP_TLS_START_TLS or ldap_server.startswith('ldaps://'):
  118. if config.LDAP_TLS_CACERTFILE:
  119. cli.set_option(ldap.OPT_X_TLS_CACERTFILE, config.LDAP_TLS_CACERTFILE)
  120. if config.LDAP_TLS_CERTFILE:
  121. cli.set_option(ldap.OPT_X_TLS_CERTFILE, config.LDAP_TLS_CERTFILE)
  122. if config.LDAP_TLS_KEYFILE:
  123. cli.set_option(ldap.OPT_X_TLS_KEYFILE, config.LDAP_TLS_KEYFILE)
  124. if config.LDAP_TLS_REQUIRE_CERT:
  125. cli.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, config.LDAP_TLS_REQUIRE_CERT)
  126. if config.LDAP_TLS_CIPHER_SUITE:
  127. cli.set_option(ldap.OPT_X_TLS_CIPHER_SUITE, config.LDAP_TLS_CIPHER_SUITE)
  128. cli.simple_bind_s(bind_dn, password)
  129. result = cli.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, config.LDAP_ATTRS)
  130. log.debug("ldap result: %s" % result)
  131. d = result[0][1]
  132. email = d['mail'][0]
  133. cnname = d['cn'][0]
  134. if 'sn' in d and 'givenName' in d:
  135. cnname = d['givenName'][0] + ' ' + d['sn'][0]
  136. if 'displayName' in d:
  137. cnname = d['displayName'][0]
  138. if 'telephoneNumber' in d:
  139. phone = d['telephoneNumber'] and d['telephoneNumber'][0] or ""
  140. else:
  141. phone = ""
  142. return {
  143. "name": name,
  144. "password": password,
  145. "cnname": cnname,
  146. "email": email,
  147. "phone": phone,
  148. }
  149. except ldap.LDAPError as e:
  150. cli and cli.unbind_s()
  151. raise e
  152. except (IndexError, KeyError) as e:
  153. raise e
  154. finally:
  155. cli and cli.unbind_s()