Skip to content

Commit

Permalink
Merge pull request #54 from isabelcosta/remove-admin-role
Browse files Browse the repository at this point in the history
Revoke a user's admin role
  • Loading branch information
m-murad committed Jun 25, 2018
2 parents b56f632 + 5c1f067 commit 0d51cd3
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 38 deletions.
34 changes: 30 additions & 4 deletions app/api/dao/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,45 @@
class AdminDAO:

@staticmethod
def assign_new_user(data):
def assign_new_user(assigner_user_id, data):

new_admin_user_id = data['user_id']

if assigner_user_id is new_admin_user_id:
return {"message": "You cannot assign yourself as an Admin."}, 403

new_admin_user = UserModel.find_by_id(new_admin_user_id)

if new_admin_user:

if new_admin_user.is_admin:
return {"message": "User is already an Admin"}, 201
return {"message": "User is already an Admin."}, 400

new_admin_user.is_admin = True
new_admin_user.save_to_db()

return {"message": "User is now an Admin"}, 201
return {"message": "User is now an Admin."}, 200

return {"message": "User does not exist."}, 404

@staticmethod
def revoke_admin_user(revoker_user_id, data):

admin_user_id = data['user_id']

if revoker_user_id is admin_user_id:
return {"message": "You cannot revoke your admin status."}, 403

new_admin_user = UserModel.find_by_id(admin_user_id)

if new_admin_user:

if not new_admin_user.is_admin:
return {"message": "User is not an Admin."}, 400

new_admin_user.is_admin = False
new_admin_user.save_to_db()

return {"message": "User admin status was revoked."}, 200

return {"message": "User does not exist"}, 401
return {"message": "User does not exist."}, 404
4 changes: 2 additions & 2 deletions app/api/dao/mentorship_relation.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def create_mentorship_relation(self, user_id, data):
# validate if mentor user exists
mentor_user = UserModel.find_by_id(mentor_id)
if mentor_user is None:
return {'message': 'Mentor user does not exist.'}, 400
return {'message': 'Mentor user does not exist.'}, 404

# validate if mentor is available to mentor
if not mentor_user.available_to_mentor:
Expand All @@ -53,7 +53,7 @@ def create_mentorship_relation(self, user_id, data):
# validate if mentee user exists
mentee_user = UserModel.find_by_id(mentee_id)
if mentee_user is None:
return {'message': 'Mentee user does not exist.'}, 400
return {'message': 'Mentee user does not exist.'}, 404

# validate if mentee is wants to be mentored
if not mentee_user.need_mentoring:
Expand Down
17 changes: 13 additions & 4 deletions app/api/dao/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
class UserDAO:
FAIL_USER_ALREADY_EXISTS = "FAIL_USER_ALREADY_EXISTS"
SUCCESS_USER_CREATED = "SUCCESS_USER_CREATED"
MIN_NUMBER_OF_ADMINS = 1

@staticmethod
def create_user(data):
Expand All @@ -29,12 +30,20 @@ def create_user(data):

@staticmethod
def delete_user(user_id):
user = UserModel.find_by_id(user_id).one()
user = UserModel.find_by_id(user_id)

# check if this user is the only admin
if user.is_admin:

admins_list_count = len(UserModel.get_all_admins())
if admins_list_count <= UserDAO.MIN_NUMBER_OF_ADMINS:
return {"message": "You cannot delete your account, since you are the only Admin left."}, 400

if user:
user.delete_from_db()
return {"message": "User was deleted successfully"}, 201

return {"message": "User does not exist"}, 201
return {"message": "User does not exist"}, 404

@staticmethod
def get_user(user_id):
Expand All @@ -59,7 +68,7 @@ def update_user_profile(user_id, data):
user = UserModel.find_by_id(user_id)

if not user:
return {"message": "User does not exist"}, 201
return {"message": "User does not exist"}, 404

if 'name' in data and data['name']:
user.name = data['name']
Expand Down Expand Up @@ -117,7 +126,7 @@ def change_password(user_id, data):
user.save_to_db()
return {"message": "Password was updated successfully."}, 201

return {"message": "Current password is incorrect."}, 201
return {"message": "Current password is incorrect."}, 400

@staticmethod
def confirm_registration(user_id, data):
Expand Down
4 changes: 2 additions & 2 deletions app/api/models/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@


def add_models_to_namespace(api_namespace):
api_namespace.models[assign_new_admin_request_body.name] = assign_new_admin_request_body
api_namespace.models[assign_and_revoke_user_admin_request_body.name] = assign_and_revoke_user_admin_request_body


assign_new_admin_request_body = Model('Assign User model', {
assign_and_revoke_user_admin_request_body = Model('Assign User model', {
'user_id': fields.Integer(
required=True,
description='The unique identifier of a user'
Expand Down
30 changes: 26 additions & 4 deletions app/api/resources/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from flask import request
from flask_restplus import Resource
from flask_jwt import jwt_required, current_identity

from run import api
from app.api.models.admin import *
from app.api.dao.admin import AdminDAO
Expand All @@ -17,17 +18,38 @@ class AssignNewUserAdmin(Resource):

@classmethod
@jwt_required()
@admin_ns.expect(auth_header_parser, assign_new_admin_request_body, validate=True)
@admin_ns.expect(auth_header_parser, assign_and_revoke_user_admin_request_body, validate=True)
def post(cls):
"""
Assigns a User as a new Admin.
"""

if current_identity.is_admin:
data = request.json
return DAO.assign_new_user(data)
return DAO.assign_new_user(current_identity.id, data)

else:
return {
"message": "You don't have admin status. You can't assign other user as admin."
}, 403


@admin_ns.route('admin/remove')
class RevokeUserAdmin(Resource):

@classmethod
@jwt_required()
@admin_ns.expect(auth_header_parser, assign_and_revoke_user_admin_request_body, validate=True)
def post(cls):
"""
Revoke admin status from another User Admin.
"""

if current_identity.is_admin:
data = request.json
return DAO.revoke_admin_user(current_identity.id, data)

else:
return {
"message": "You don't have admin status. You can't assign another admin"
}, 401
"message": "You don't have admin status. You can't revoke other admin user."
}, 403
4 changes: 4 additions & 0 deletions app/database/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ def find_by_email(cls, email):
def find_by_id(cls, _id):
return cls.query.filter_by(id=_id).first()

@classmethod
def get_all_admins(cls, is_admin=True):
return cls.query.filter_by(is_admin=is_admin).all()

@classmethod
def is_empty(cls):
return cls.query.first() is None
Expand Down
25 changes: 25 additions & 0 deletions docs/Mentorship Backend.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,31 @@
},
"response": []
},
{
"name": "POST /admin/remove",
"request": {
"url": "http://127.0.0.1:5000/admin/new",
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mjc4NTI3NzEsImlhdCI6MTUyNzg1MjQ3MSwibmJmIjoxNTI3ODUyNDcxLCJpZGVudGl0eSI6MX0.bXm5OrEvZnS6PxI4XQkOF4z-ZcFbYZreanutmYTUWyA",
"description": ""
},
{
"key": "Content-Type",
"value": "application/json",
"description": ""
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"user_id\": 2\n}"
},
"description": "Assign a new user as an Admin"
},
"response": []
},
{
"name": "GET /mentorship-relations",
"request": {
Expand Down
71 changes: 51 additions & 20 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@
]
}
},
"/admin/remove": {
"post": {
"responses": {
"200": {
"description": "Success"
}
},
"summary": "Revoke admin status from another User Admin",
"operationId": "post_revoke_user_admin",
"parameters": [
{
"name": "Authorization",
"in": "header",
"type": "string",
"required": true,
"description": "Authentication access token. E.g.: JWT <access_token>"
},
{
"name": "payload",
"required": true,
"in": "body",
"schema": {
"$ref": "#/definitions/Assign User model"
}
}
],
"tags": [
"Admins"
]
}
},
"/login": {
"post": {
"responses": {
Expand Down Expand Up @@ -153,34 +184,24 @@
}
},
"/user": {
"get": {
"delete": {
"responses": {
"404": {
"description": "User not found."
},
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/User list model"
}
"204": {
"description": "User successfully deleted."
}
},
"summary": "Returns a user",
"operationId": "get_user",
"summary": "Deletes user",
"operationId": "delete_user",
"parameters": [
{
"name": "Authorization",
"in": "header",
"type": "string",
"required": true,
"description": "Authentication access token. E.g.: JWT <access_token>"
},
{
"name": "X-Fields",
"in": "header",
"type": "string",
"format": "mask",
"description": "An optional fields mask"
}
],
"tags": [
Expand Down Expand Up @@ -219,24 +240,34 @@
"Users"
]
},
"delete": {
"get": {
"responses": {
"404": {
"description": "User not found."
},
"204": {
"description": "User successfully deleted."
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/User list model"
}
}
},
"summary": "Deletes user",
"operationId": "delete_user",
"summary": "Returns a user",
"operationId": "get_user",
"parameters": [
{
"name": "Authorization",
"in": "header",
"type": "string",
"required": true,
"description": "Authentication access token. E.g.: JWT <access_token>"
},
{
"name": "X-Fields",
"in": "header",
"type": "string",
"format": "mask",
"description": "An optional fields mask"
}
],
"tags": [
Expand Down

0 comments on commit 0d51cd3

Please sign in to comment.