A multipurpose python flask API server and administration SPA
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.

154 lines
4.7 KiB

  1. import base64
  2. import logging
  3. import random
  4. import string
  5. from os import path
  6. from typing import Optional
  7. import click
  8. from click import Context
  9. from corvus import corvus
  10. from corvus.model import User
  11. from corvus.service import user_service
  12. from corvus.service.role_service import ROLE_LIST
  13. logging.basicConfig()
  14. ENCODING = 'utf-8'
  15. @click.group()
  16. def main():
  17. pass
  18. @click.group(name='user')
  19. def user_command_group():
  20. pass
  21. @click.group(name='base64')
  22. def base64_command_group():
  23. pass
  24. @click.command(name='delete')
  25. @click.argument('name')
  26. def delete_user(name: str):
  27. logging.info('Deleting user with name \'%s\'', name)
  28. existing_user = User.query.filter_by(name=name).first()
  29. if existing_user is not None:
  30. successful = user_service.delete(existing_user)
  31. if successful:
  32. logging.warning('Deleted user with name \'%s\'', name)
  33. else:
  34. logging.error('Failed to delete user with name \'%s\'', name)
  35. else:
  36. logging.warning('User with name \'%s\' doesn\'t exist', name)
  37. @click.command('register')
  38. @click.argument('name')
  39. @click.argument('password', required=False)
  40. @click.option('--role',
  41. default=User.ROLE_USER,
  42. envvar='ROLE',
  43. help='Role to assign to the user. '
  44. + 'default=[USER] acceptable values = ['
  45. + ','.join(sorted(set(map(lambda rt: str(rt), ROLE_LIST))))
  46. + ']')
  47. def register_user(
  48. name: str,
  49. role: str,
  50. password: Optional[str] = None):
  51. logging.info('Registering user with name \'%s\'', name)
  52. existing_user = User.query.filter_by(name=name).first()
  53. if existing_user is None:
  54. user_password = password if password else ''.join(
  55. random.choices(string.ascii_letters + string.digits, k=24))
  56. new_user = user_service.register(name, user_password, role, False)
  57. logging.warning(
  58. 'Created new user: \'%s\' with password \'%s\' and role %s',
  59. new_user.name,
  60. user_password,
  61. new_user.role)
  62. else:
  63. logging.warning('User \'%s\' already exists. Did you mean to update?',
  64. name)
  65. @click.command(name='register-admin')
  66. @click.pass_context
  67. def register_admin_user(ctx: Context):
  68. admin_users = User.query.filter_by(role=User.ROLE_ADMIN).all()
  69. if len(admin_users) == 0:
  70. name = 'corvus_administrator'
  71. password = ''.join(
  72. random.choices(string.ascii_letters + string.digits, k=32))
  73. ctx.invoke(
  74. register_user,
  75. name=name,
  76. role=User.ROLE_ADMIN,
  77. password=password)
  78. admin_credential_file = '.admin_credentials'
  79. with open(admin_credential_file, 'w') as f:
  80. f.write('{}:{}'.format(name, password))
  81. logging.info(
  82. 'These credentials can also be retrieved from {}'.format(
  83. path.abspath(admin_credential_file)))
  84. @click.command(name='reset-password')
  85. @click.argument('name')
  86. @click.argument('password', required=False)
  87. def reset_user_password(name: str, password: Optional[str] = None):
  88. logging.info('Resetting user password for \'%s\'', name)
  89. existing_user = User.query.filter_by(name=name).first()
  90. if existing_user is not None:
  91. user_password = password if password else ''.join(
  92. random.choices(string.ascii_letters + string.digits, k=24))
  93. user_service.update_password(existing_user, user_password)
  94. logging.warning(
  95. 'Updated user: \'%s\' with password \'%s\'',
  96. name,
  97. user_password)
  98. else:
  99. logging.warning('User with name \'%s\' doesn\'t exist', name)
  100. @click.command(name='list')
  101. def list_users():
  102. all_users = User.query.all()
  103. [click.echo(user.name) for user in all_users]
  104. @click.command(name='encode')
  105. @click.argument('text')
  106. def convert_to_base64(text: str):
  107. encoded_text = base64.standard_b64encode(text.encode(ENCODING)).decode(ENCODING)
  108. logging.info('Encoded base64: \'%s\'', encoded_text)
  109. @click.command(name='decode')
  110. @click.argument('text')
  111. def convert_from_base64(text: str):
  112. decoded_text = base64.standard_b64decode(text.encode(ENCODING)).decode(ENCODING)
  113. logging.info('Decoded base64: \'%s\'', decoded_text)
  114. main.add_command(base64_command_group)
  115. base64_command_group.add_command(convert_to_base64)
  116. base64_command_group.add_command(convert_from_base64)
  117. main.add_command(user_command_group)
  118. user_command_group.add_command(register_user)
  119. user_command_group.add_command(register_admin_user)
  120. user_command_group.add_command(delete_user)
  121. user_command_group.add_command(reset_user_password)
  122. user_command_group.add_command(list_users)
  123. if __name__ == '__main__':
  124. logging.debug('Managing: %s', corvus.name)
  125. with corvus.app_context():
  126. main()