LILiK login and user managment web interface
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.3 KiB

8 years ago
  1. #!/usr/bin/env python3
  2. import lilikusers
  3. import json
  4. from flask import Flask, jsonify
  5. from flask import request, Response, redirect, url_for
  6. from functools import wraps
  7. app = Flask(__name__)
  8. lilik_ldap = lilikusers.LILiK_LDAP()
  9. def check_auth(user_name, password):
  10. """This function is called to check if a username /
  11. password combination is valid.
  12. """
  13. if lilik_ldap.login(user_name, password):
  14. return lilik_ldap.get_user(user_name)
  15. raise ValueError
  16. def authenticate():
  17. """Sends a 401 response that enables basic auth"""
  18. return Response(
  19. 'Could not verify your access level for that URL.\n'
  20. 'You have to login with proper credentials\n', 401)
  21. def admin_required():
  22. """Sends a 401 response that enables basic auth"""
  23. return Response(
  24. 'Could not verify your access level for that URL.\n'
  25. 'You have to login with admin rights\n', 401)
  26. def requires_auth(f):
  27. @wraps(f)
  28. def decorated(*args, **kwargs):
  29. auth = request.authorization
  30. if not auth:
  31. return authenticate()
  32. try:
  33. user = check_auth(auth.username, auth.password)
  34. except ValueError:
  35. app.logger.warning("Authentication failed for %s" % auth.username)
  36. return authenticate()
  37. return f(user, *args, **kwargs)
  38. return decorated
  39. def requires_admin_auth(f):
  40. @wraps(f)
  41. def decorated(user, *args, **kwargs):
  42. if not user.services['admin']:
  43. app.logger.warning("Admin privilege required for user %s" % user.uid)
  44. return admin_required()
  45. return f(user, *args, **kwargs)
  46. return decorated
  47. def requires_same_user_or_admin_auth(f):
  48. @wraps(f)
  49. def decorated(user, user_name, *args, **kwargs):
  50. if not user.services['admin'] and user.uid != user_name:
  51. app.logger.warning("Admin privilege required for user %s" % user.uid)
  52. return admin_required()
  53. return f(user, user_name, *args, **kwargs)
  54. return decorated
  55. @app.route('/api/users', methods=['GET'])
  56. @requires_auth
  57. @requires_admin_auth
  58. def get_users(user):
  59. ''' return the list of users'''
  60. return jsonify(lilik_ldap.get_users())
  61. @app.route('/api/users/<user_name>', methods=['GET'])
  62. @requires_auth
  63. @requires_same_user_or_admin_auth
  64. def get_user(user, user_name):
  65. ''' return the list of users'''
  66. return jsonify(lilik_ldap.get_user(user_name).to_dict())
  67. @app.route('/api/users/<user_name>', methods=['PUT'])
  68. @requires_auth
  69. @requires_same_user_or_admin_auth
  70. def update_user(user, user_name):
  71. new_lilik_user = request.get_json()
  72. user_to_edit = lilik_ldap.get_user(user_name)
  73. diff = user_to_edit.diff(new_lilik_user)
  74. is_permitted_self_changes = diff.changed() <= set(['cn']) and diff.removed() == set() and diff.added() <= set(['userPassword'])
  75. print(user.uid)
  76. if user.services['admin'] or is_permitted_self_changes:
  77. user_to_edit.update(new_lilik_user)
  78. return jsonify(lilik_ldap.get_user(user_name).to_dict())
  79. @app.route('/api/users', methods=['POST'])
  80. @requires_auth
  81. @requires_admin_auth
  82. def new_user(user):
  83. new_lilik_user = request.get_json()
  84. print(lilik_ldap.new_user(new_lilik_user))
  85. return jsonify(lilik_ldap.get_user(new_lilik_user['uid']).to_dict())
  86. @app.route('/')
  87. def home():
  88. return redirect(url_for('static', filename='index.html'))
  89. if __name__ == '__main__':
  90. app.run(debug=True)