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.
haproxy-wi/app/views/user/views.py

537 lines
18 KiB

from typing import Union
from flask.views import MethodView
from flask_pydantic import validate
from flask import render_template, jsonify, g
from flask_jwt_extended import jwt_required
from flask_jwt_extended import set_access_cookies
from playhouse.shortcuts import model_to_dict
import app.modules.db.sql as sql
import app.modules.db.user as user_sql
import app.modules.db.group as group_sql
import app.modules.roxywi.user as roxywi_user
import app.modules.roxywi.auth as roxywi_auth
import app.modules.roxywi.common as roxywi_common
from app.modules.db.db_model import User as User_DB
from app.modules.roxywi.class_models import UserPost, UserPut, IdResponse, IdDataResponse, BaseResponse, AddUserToGroup
from app.modules.roxywi.exception import RoxywiResourceNotFound
from app.middleware import get_user_params, page_for_admin, check_group
class UserView(MethodView):
methods = ["GET", "POST", "PUT", "DELETE"]
decorators = [jwt_required(), get_user_params(), page_for_admin(level=2), check_group()]
def __init__(self, is_api=False):
"""
Initialize UserView instance
---
parameters:
- name: is_api
in: path
type: boolean
description: is api
"""
self.is_api = is_api
@staticmethod
def get(user_id: int):
"""
Get User information by ID
---
tags:
- 'User'
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to retrieve'
required: true
type: 'integer'
responses:
'200':
description: 'Successful Operation'
schema:
type: 'object'
id: 'User'
properties:
group_id:
type: 'integer'
user_id:
type: 'integer'
email:
type: 'string'
description: 'User email'
enabled:
type: 'integer'
description: 'User activation status'
last_login_date:
type: 'string'
format: 'date-time'
description: 'User last login date'
last_login_ip:
type: 'string'
description: 'User last login IP'
ldap_user:
type: 'integer'
description: 'Is User a LDAP user'
role_id:
type: 'integer'
description: 'User role'
username:
type: 'string'
description: 'Username'
role_id:
type: 'integer'
description: 'User role ID'
'404':
description: 'User not found'
schema:
id: 'NotFound'
properties:
message:
type: 'string'
description: 'Error message'
"""
try:
user = user_sql.get_user_id(user_id)
except Exception as e:
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot get user')
try:
roxywi_common.is_user_has_access_to_its_group(user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot find user'), 404
return jsonify(model_to_dict(user, exclude={User_DB.password, User_DB.user_services}))
@validate(body=UserPost)
def post(self, body: UserPost) -> Union[dict, tuple]:
"""
Create a new user
---
tags:
- User
parameters:
- name: body
in: body
schema:
id: NewUser
required:
- email
- password
- username
- enabled
properties:
email:
type: string
description: The email of the user
password:
type: string
description: The password of the user
role_id:
type: integer
description: The role of the user
username:
type: string
description: The username of the user
enabled:
type: integer
description: 'Enable status (1 for enabled)'
group_id:
type: integer
description: The ID of the user's group
responses:
200:
description: user created
schema:
id: CreateUserResponse
properties:
status:
type: string
description: The status of the user creation
id:
type: integer
description: The ID of the created user
"""
if g.user_params['role'] > body.role_id:
return roxywi_common.handle_json_exceptions('Wrong role', 'Cannot create user')
try:
user_id = roxywi_user.create_user(body.username, body.email, body.password, body.role_id, body.enabled, body.group_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot create a new user')
else:
if self.is_api:
return IdResponse(id=user_id), 201
else:
lang = roxywi_common.get_user_lang_for_flask()
data = render_template(
'ajax/new_user.html', users=user_sql.select_users(user=body.username), groups=group_sql.select_groups(),
roles=sql.select_roles(), adding=1, lang=lang
)
return IdDataResponse(id=user_id, data=data), 201
@validate(body=UserPut)
def put(self, user_id: int, body: UserPut) -> Union[dict, tuple]:
"""
Update User Information
---
tags:
- User
description: Update the information of a user based on the provided user ID.
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to retrieve'
required: true
type: 'integer'
- in: body
name: body
schema:
id: UserUpdate
required:
- id
- username
- email
- enabled
properties:
email:
type: string
description: The email of the user
username:
type: string
description: The username of the user
password:
type: string
description: The password of the user
enabled:
type: integer
description: 'Enable status (1 for enabled)'
responses:
400:
description: Invalid request
201:
description: User information update successful
"""
try:
_ = user_sql.get_user_id(user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user'), 404
try:
user_sql.update_user_from_admin_area(user_id, **body.model_dump(mode='json', exclude={'password'}))
user_sql.update_user_password(body.password, user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot update user')
roxywi_common.logging(body.username, 'has been updated user', roxywi=1, login=1)
return BaseResponse(), 201
@validate()
def delete(self, user_id: int):
"""
Delete a User
---
tags:
- User
Description: Delete a user based on the provided user ID.
parameters:
- in: 'path'
name: 'user_id'
description: 'User ID to delete'
required: true
type: 'integer'
responses:
204:
description: User deletion successful
400:
description: Invalid request
404:
description: User not found
"""
try:
roxywi_common.is_user_has_access_to_its_group(user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot find user'), 404
try:
user = user_sql.get_user_id(user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user'), 404
if g.user_params['role'] > int(user.role_id):
return roxywi_common.handle_json_exceptions('Wrong role', 'Cannot delete user'), 404
try:
roxywi_user.delete_user(user_id)
return BaseResponse().model_dump(mode='json'), 204
except Exception as e:
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete the user')
class UserGroupView(MethodView):
methods = ["GET", "POST", "PUT", "DELETE", "PATCH"]
decorators = [jwt_required(), get_user_params(), page_for_admin(level=4), check_group()]
@staticmethod
def get(user_id: int):
"""
Fetch a specific User Group.
---
tags:
- User group
parameters:
- in: 'path'
name: 'user_id'
description: 'User ID to get'
required: true
type: 'integer'
responses:
200:
description: A list of user's groups
schema:
type: array
items:
id: UserGet
properties:
user_group_id:
type: integer
description: User group ID
example: 1
user_role_id:
type: integer
description: User role ID
example: 1
"""
try:
users = user_sql.select_user_groups_with_names(user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get group')
json_data = []
for user in users:
json_data.append(model_to_dict(user, exclude=[User_DB.password, User_DB.user_services]))
return jsonify(json_data)
@validate(body=AddUserToGroup)
def post(self, user_id: int, group_id: int, body: AddUserToGroup):
"""
Add a User to a specific Group
---
tags:
- 'User group'
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to be added'
required: true
type: 'integer'
- in: 'path'
name: 'group_id'
description: 'ID of the Group which will have a new user'
required: true
type: 'integer'
- in: body
name: role_id
required: true
schema:
properties:
role_id:
type: integer
description: A role inside the group
responses:
'201':
description: 'User successfully added to the group'
'404':
description: 'User or Group not found'
"""
page_for_admin(level=2)
try:
self._check_is_user_and_group(user_id, group_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user or group'), 404
try:
user_sql.update_user_role(user_id, group_id, body.role_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot add user to group'), 500
else:
return BaseResponse().model_dump(mode='json'), 201
@validate(body=AddUserToGroup)
def put(self, user_id: int, group_id: int, body: AddUserToGroup):
"""
Update a User to a specific Group
---
tags:
- 'User group'
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to be added'
required: true
type: 'integer'
- in: 'path'
name: 'group_id'
description: 'ID of the Group where updating the user'
required: true
type: 'integer'
- in: body
name: role_id
required: true
schema:
properties:
role_id:
type: integer
description: A role inside the group
responses:
'201':
description: 'User successfully added to the group'
'404':
description: 'User or Group not found'
"""
page_for_admin(level=2)
try:
self._check_is_user_and_group(user_id, group_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user or group'), 404
try:
user_sql.delete_user_from_group(group_id, user_id)
user_sql.update_user_role(user_id, group_id, body.role_id)
return BaseResponse().model_dump(mode='json'), 201
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot delete user')
def patch(self, user_id: int, group_id: int):
"""
Assign a User to a specific Group
---
tags:
- 'User group'
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to be assigned to the group'
required: true
type: 'integer'
- in: 'path'
name: 'group_id'
description: 'ID of the Group which the user will be assigned to'
required: true
type: 'integer'
responses:
201:
description: 'User successfully assigned to the group'
404:
description: 'User or Group not found'
schema:
id: 'NotFound'
properties:
error:
type: 'string'
description: 'Error message'
"""
try:
self._check_is_user_and_group(user_id, group_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user or group'), 404
user_param = {"user": user_id, "group": group_id}
access_token = roxywi_auth.create_jwt_token(user_param)
response = jsonify({'status': 'Ok'})
set_access_cookies(response, access_token)
try:
user_sql.update_user_current_groups(group_id, user_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot update user or group'), 500
return response
def delete(self, user_id: int, group_id: int):
"""
Delete a User from a specific Group
---
tags:
- 'User group'
parameters:
- in: 'path'
name: 'user_id'
description: 'ID of the User to be deleted'
required: true
type: 'integer'
- in: 'path'
name: 'group_id'
description: 'ID of the Group from which user will be deleted'
required: true
type: 'integer'
responses:
'204':
description: 'User successfully deleted'
'404':
description: 'User or Group not found'
"""
try:
roxywi_auth.page_for_admin(level=2)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user or group'), 404
try:
self._check_is_user_and_group(user_id, group_id)
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get user or group'), 404
try:
user_sql.delete_user_from_group(group_id, user_id)
return BaseResponse().model_dump(mode='json'), 204
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot delete user')
@staticmethod
def _check_is_user_and_group(user_id: int, group_id: int):
try:
_ = user_sql.get_user_id(user_id)
group_sql.get_group(group_id)
except Exception as e:
raise e
class UserRoles(MethodView):
methods = ['GET']
decorators = [jwt_required(), get_user_params(), page_for_admin()]
@staticmethod
def get():
"""
User Roles
---
tags:
- User Roles
summary: Get All User Role Information
description: This method is used to retrieve all available user roles along with their descriptions and corresponding role_ids.
produces:
- application/json
responses:
200:
description: User Roles Returned
schema:
type: array
items:
type: object
properties:
name:
type: string
description: The name of the user role.
example: "superAdmin"
role_id:
type: integer
description: The ID of the user role.
example: 1
description:
type: string
description: The description of the user role.
example: "Has the highest level of administrative..."
"""
try:
roles = sql.select_roles()
except Exception as e:
return roxywi_common.handle_json_exceptions(e, 'Cannot get roles')
roles_list = []
for role in roles:
roles_list.append(model_to_dict(role))
return jsonify(roles_list)