user.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from flask import Blueprint, g, make_response
  4. from flask import request
  5. from flask import session
  6. import json
  7. import jimit as ji
  8. from api.base import Base
  9. from models import app_config
  10. from models import User
  11. from models import Utils
  12. from models import Rules
  13. __author__ = 'James Iter'
  14. __date__ = '2017/9/14'
  15. __contact__ = 'james.iter.cn@gmail.com'
  16. __copyright__ = '(c) 2017 by James Iter.'
  17. blueprint = Blueprint(
  18. 'api_user',
  19. __name__,
  20. url_prefix='/api/user'
  21. )
  22. blueprints = Blueprint(
  23. 'api_users',
  24. __name__,
  25. url_prefix='/api/users'
  26. )
  27. user_base = Base(the_class=User, the_blueprint=blueprint, the_blueprints=blueprints)
  28. @Utils.dumps2response
  29. def r_sign_in():
  30. args_rules = [
  31. Rules.LOGIN_NAME.value,
  32. Rules.PASSWORD.value
  33. ]
  34. user = User()
  35. user.login_name = request.json.get('login_name')
  36. user.password = request.json.get('password')
  37. try:
  38. ji.Check.previewing(args_rules, user.__dict__)
  39. plain_password = user.password
  40. user.get_by('login_name')
  41. if not ji.Security.ji_pbkdf2_check(password=plain_password, password_hash=user.password):
  42. ret = dict()
  43. ret['state'] = ji.Common.exchange_state(40101)
  44. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 鉴权失败'])
  45. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  46. token = Utils.generate_token(user.id)
  47. session['token'] = token
  48. rep = make_response()
  49. rep.data = json.dumps({'state': ji.Common.exchange_state(20000)}, ensure_ascii=False)
  50. return rep
  51. except ji.PreviewingError, e:
  52. return json.loads(e.message)
  53. @Utils.dumps2response
  54. def r_sign_out():
  55. for key in session.keys():
  56. session.pop(key=key)
  57. @Utils.dumps2response
  58. def r_change_password():
  59. args_rules = [
  60. Rules.ID.value
  61. ]
  62. user = User()
  63. user.id = g.token.get('uid', 0).__str__()
  64. try:
  65. ji.Check.previewing(args_rules, user.__dict__)
  66. user.get()
  67. old_password = request.json.get('old_password', '')
  68. if not ji.Security.ji_pbkdf2_check(password=old_password, password_hash=user.password):
  69. ret = dict()
  70. ret['state'] = ji.Common.exchange_state(40101)
  71. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 鉴权失败'])
  72. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  73. args_rules = [
  74. Rules.PASSWORD.value
  75. ]
  76. user.password = request.json.get('password')
  77. ji.Check.previewing(args_rules, user.__dict__)
  78. user.password = ji.Security.ji_pbkdf2(user.password)
  79. user.update()
  80. except ji.PreviewingError, e:
  81. return json.loads(e.message)
  82. @Utils.dumps2response
  83. def r_reset_password(token):
  84. args_rules = [
  85. Rules.TOKEN.value
  86. ]
  87. try:
  88. ji.Check.previewing(args_rules, {'token': token})
  89. token = Utils.verify_token(token, audience='r_reset_password')
  90. user = User()
  91. user.id = token['uid']
  92. user.get()
  93. args_rules = [
  94. Rules.PASSWORD.value
  95. ]
  96. user.password = request.json.get('password')
  97. ji.Check.previewing(args_rules, user.__dict__)
  98. user.password = ji.Security.ji_pbkdf2(user.password)
  99. user.update()
  100. except (ji.PreviewingError, ji.JITError), e:
  101. return json.loads(e.message)
  102. @Utils.dumps2response
  103. def r_send_reset_password_email(login_name):
  104. args_rules = [
  105. Rules.LOGIN_NAME.value
  106. ]
  107. try:
  108. ji.Check.previewing(args_rules, {'login_name': login_name})
  109. user = User()
  110. try:
  111. user.login_name = login_name
  112. user.get_by('login_name')
  113. except ji.PreviewingError, e:
  114. # 如果 login_name 没有找到,则尝试从email里面查找
  115. # 因为用户可能会把登录名理解成email
  116. user.email = login_name
  117. user.get_by('email')
  118. host_url = request.host_url.rstrip('/')
  119. # 5 分钟有效期
  120. token = Utils.generate_token(uid=user.id, ttl=300, audience='r_reset_password')
  121. reset_password_url = '/'.join([host_url, 'reset_password', token])
  122. smtp_server = ji.NetUtils.smtp_init(host=app_config['smtp_host'], port=app_config.get('smtp_port', None),
  123. login_name=app_config['smtp_user'], password=app_config['smtp_password'],
  124. tls=app_config['smtp_starttls'])
  125. ji.NetUtils.send_mail(smtp_server=smtp_server, sender=app_config['smtp_user'],
  126. receivers=[user.email], title=u'重置登录密码',
  127. message=u'请复制以下地址到浏览器中打开:' + reset_password_url)
  128. ret = dict()
  129. ret['state'] = ji.Common.exchange_state(20000)
  130. ret['data'] = {'email': user.email}
  131. return ret
  132. except ji.PreviewingError, e:
  133. return json.loads(e.message)