def delete_user(reader_email): """Permanently deletes a reader, approver or admin and all attached information from the database.""" reader = Reader.query.filter_by(email=reader_email).first() email = get_jwt_identity() if not reader: return bad_request("Reader {} does not exist.".format(reader_email)) if reader_email == email: return bad_request( "Deleting own account not allowed." ) # a safety to prevent the system from having no admins approver = Approver.query.filter_by(reader_id=reader.id).first() admin = Admin.query.filter_by(approver_id=reader.id).first() if admin: db.session.delete(admin) elif approver: db.session.delete(approver) # TODO move approvals to next approver else: db.session.delete(reader) db.session.commit() return ok("Reader was successfully deleted")
def revoke_ag_access(): """Revokes a readers access to a access group""" schema = {"ag_id": {"type": "integer"}, "email": {"type": "string"}} email = request.json.get("email") ag_id = request.json.get("ag_id") # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exist!") gives_access = db.session.query(gives_access_to, BelongsTo).filter( gives_access_to.c.ag_id == BelongsTo.ag_id, BelongsTo.ag_id == ag_id, BelongsTo.reader_id == reader.id).all() if not gives_access: return bad_request( "The reader does not have access to this access group") BelongsTo.query.filter_by(reader_id=reader.id, ag_id=ag_id).delete() db.session.commit() return ok("Access to {0} has been removed for {1}".format(ag_id, email))
def upgrade_to_approver(): schema = { "email": { "type": "string" }, } email = request.json.get("email") # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) reader_to_upgrade = Reader.query.filter_by(email=email).first() if not reader_to_upgrade: return bad_request("No user with email {0} exists.".format(email)) if Approver.query.filter_by( reader_id=reader_to_upgrade.id).first() is not None: return bad_request( "User with email {0} already have the role of approver (at least)." .format(email)) # Insert a new row in the Approver table, where reader_id is set to that of the specified reader. # To circumvent Flask object problems (inheritance etc.), this is done in "pure" SQL syntax. db.session.execute("INSERT INTO approver (reader_id) VALUES ({0});".format( reader_to_upgrade.id)) db.session.commit() return ok("Reader is now an approver!")
def remove_ag(): """Remove the access group from the approvers approval area""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = { "approver": { "type": "integer" }, ## varför är det integer här? är det approver_id? "ag": { "type": "integer" } } # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) approver_id = request.json.get("approver") ag_id = request.json.get("ag") responsible_for_ag = ResponsibleForAg.query.filter_by( approver_id=approver_id, ag_id=ag_id).first() if not responsible_for_ag: return bad_request( "No approver {} is responsible for access group {}.".format( approver_id, ag_id)) db.session.delete(responsible_for_ag) db.session.commit() return ok("Access group removed from approver.")
def remove_room(): """Remove the room from the approvers approval area""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = { "approver": { "type": "integer" }, ## varför är det integer här? är det approver_id? "room": { "type": "string" } } # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) approver_id = request.json.get("approver") room_text_id = request.json.get("room") responsible_for_room = ResponsibleForRoom.query \ .join(Room, Room.id == ResponsibleForRoom.room_id) \ .filter(ResponsibleForRoom.approver_id == approver_id, Room.text_id == room_text_id).first() if not responsible_for_room: return bad_request("No approver {} is responsible for room {}.".format( approver_id, room_text_id)) db.session.delete(responsible_for_room) db.session.commit() return ok("Room removed from approver.")
def create_user(Role): """Creates a new user and adds to the database if correct input is given.""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = { "email": { "type": "string", "regex": "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$" }, "name": { "type": "string", "regex": "[a-zA-Z]+$", "minlength": 2, "maxlength": 12 }, "surname": { "type": "string", "regex": "[a-zA-Z]+$", "minlength": 2, "maxlength": 12 }, "password": { "type": "string" } } # Checks if input is illegal if not validator(request.json, schema): s = validator return bad_request(validator.errors) # Get the email, password, name and surname from the client email = request.json.get("email") password = request.json.get("password") name = request.json.get("name") surname = request.json.get("surname") # Checks if the email already is in use if Reader.query.filter_by(email=email).first() is not None: return bad_request("This email is already in use!") # Checks if the password is illegal not_fulfilled = validate_password(password) if not_fulfilled: return bad_request({"password": not_fulfilled}) # Returns a new user new_user = Role(email=email, password=password, name=name, surname=surname) db.session.add(new_user) db.session.commit() return created("{} successfully created!".format( Role.__tablename__.capitalize()))
def is_admin(): """ Checks if the request comes from a user that is admin.""" try: email = decode_token( request.headers.get('Authorization')[7:])["identity"] current_admin = Admin.query.filter_by(email=email).first() except IndexError: return bad_request("User is not an admin") if current_admin is None: return bad_request("User is not an admin")
def remove_card(email): reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("No reader with email {}.".format(email)) if not reader.card_id: return bad_request("Card has already been cleared.") reader.block_card() db.session.commit() return ok("Card for reader was cleared.")
def approve_ag_request(current_approver, ag_request_id): """Approves a request to an access group""" # get the approves_ag_request, access_group_request and reader objects related to the given access_group_request res = db.session.query(ApprovesAgRequest, AccessGroupRequest, AccessGroup, Reader) \ .join(AccessGroupRequest, AccessGroupRequest.id == ApprovesAgRequest.ag_request_id) \ .join(AccessGroup, AccessGroup.id == AccessGroupRequest.ag_id) \ .join(Reader, Reader.id == AccessGroupRequest.reader_id) \ .filter(ApprovesAgRequest.approver_id == current_approver.id, AccessGroupRequest.id == ag_request_id, AccessGroupRequest.status == RequestStatus.PENDING).first() if res is None: return bad_request( "{} not a valid ag request for approver.".format(ag_request_id)) approves_request = res[0] ag_req = res[1] ag = res[2] reader = res[3] expire_date = date.today() + timedelta(days=HALF_YEAR) new_belongs_to = BelongsTo(reader, ag, expire_date) db.session.add(new_belongs_to) db.session.delete(approves_request) ag_req.status = RequestStatus.APPROVED db.session.commit() return ok('Request for ag was approved')
def approve_request(): """Approves or denies a request to a room or an access group""" schema = { "request_id": { "type": "integer" }, "type": { "type": "string" }, "is_access_granted": { "type": "boolean" } } # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) request_id = request.json.get("request_id") type = request.json.get("type") is_access_granted = request.json.get("is_access_granted") # Checks if the approver exists in the database email = get_jwt_identity() current_approver = Approver.query.filter_by(email=email).first() if current_approver is None: return bad_request("{} is not in the database.".format(email)) if type == "Room": if is_access_granted: return approve_room_request(current_approver, request_id) else: return deny_room_request(current_approver, request_id) elif type == "AG": if is_access_granted: return approve_ag_request(current_approver, request_id) else: return deny_ag_request(current_approver, request_id) else: return bad_request("{} is not a valid type.".format(type))
def save_map(): """Saves the representation of the map in locale file""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") pickle.dump(request.json, open("map_repr.pickle", "wb")) return ok("File has been saved!")
def get_readers_for_room(): """Get all the readers with access to a room.""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = {"room_text_id": {"type": "string"}} # Get the email for the access to said room. email = get_jwt_identity() room_text_id = request.json.get("room_text_id") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) # Checks if the approver exists in the database approver = Approver.query.filter_by(email=email).first() if not approver: return bad_request("Approver does not exist!") # Checks if the room exists in the database room = Room.query.filter_by(text_id=room_text_id).first() if not room: return bad_request("Room: {} does not exist!".format(room_text_id)) # Query reader_access = db.session.query( Room, CardReader, HasAccessTo, Reader).filter( HasAccessTo.card_reader_id == CardReader.id, HasAccessTo.reader_id == Reader.id, CardReader.room_b_id == Room.id, Room.text_id == room_text_id, ).all() # Format return message reader_order = [{ "name": x.Reader.name, "surname": x.Reader.surname, "email": x.Reader.email, "id": x.Reader.id } for x in reader_access] return ok({"reader_access": reader_order})
def get_reader(reader_id): """Returns a reader with given id.""" # Checks if the reader exist in the database reader = Reader.query.filter_by(id=reader_id).first() if not reader: return bad_request("Reader does not exist!") return reader.serialize
def get_all_access_helper(email, room_filter=None): """ Returns a list of all access of the reader with the given email""" # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exist.") # get room and belongsto for all rooms current user has access to from access groups as a list of tuples ag_access = db.session.query(Room, BelongsTo) \ .join(CardReader, CardReader.room_b_id == Room.id) \ .join(gives_access_to, gives_access_to.c.cr_id == CardReader.id) \ .join(AccessGroup, AccessGroup.id == gives_access_to.c.ag_id) \ .join(BelongsTo, BelongsTo.ag_id == AccessGroup.id) \ .filter_by(reader_id=reader.id) \ .all() # get room and belongs to for all rooms current user has access to as a list of tuples room_access = db.session.query(Room, HasAccessTo) \ .join(CardReader, CardReader.room_b_id == Room.id) \ .join(HasAccessTo, HasAccessTo.card_reader_id == CardReader.id) \ .filter_by(reader_id=reader.id) \ .all() # build a dict to return in JSON format return_dict = {} date_next_month = date.today() + relativedelta(months=+1) all_rooms = Room.query.all() if room_filter == None: # equals is intended, empty list should not enter. room_filter = [r.text_id for r in all_rooms] for room in all_rooms: ag = _find_room_helper(ag_access, room) r = _find_room_helper(room_access, room) has_access = ((ag is not None) or (r is not None)) and room.text_id in room_filter # python or takes object when using "ag or r"... room_json = {} # dictionay object for this room's metadata #room_json["approvers"] = [approver.approver.serialize for approver in room.approvers] room_json["access"] = has_access room_json["name"] = room.name if has_access: if ag: room_json["expires"] = ag.expiration_datetime room_json["ag_id"] = ag.ag_id else: room_json["expires"] = r.expiration_datetime if room_json["expires"].date() < date_next_month: room_json["warn_date"] = True return_dict[room.text_id] = room_json return ok(return_dict)
def get_current_reader(): """Returns the current users data""" # Get the email from the reader email = get_jwt_identity() current_reader = Reader.query.filter_by(email=email).first() # Checks if the reader is in the database if current_reader is None: return bad_request("{} is not in the database.".format(email)) return ok(current_reader.serialize)
def get_responsibilities(): """Returns a list of the rooms in the approvers responsibility.""" email = get_jwt_identity() # Checks if the reader is an approver approver = Approver.query.filter_by(email=email).first() if not approver: return bad_request("This user does not have the approver role!") room_list = get_responsibilites_helper(approver) return ok({"responsibilities": room_list})
def order_room(): """Order access to a room for the logged in user""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = { "room_text_id": { "type": "string" }, "justification": { "type": "string", "maxlength": 800 } } # Get the email, room and the justification for the access to said room. email = get_jwt_identity() room_text_id = request.json.get("room_text_id") justification = request.json.get("justification") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exist." "") # Checks if the room exists in the database room = Room.query.filter_by(text_id=room_text_id).first() if not room: return bad_request("Room: {} does not exist." "".format(room_text_id)) # Checks if the reader has already sent a request for this room rr = RoomRequest.query.filter_by(reader_id=reader.id, room_id=room.id, status=RequestStatus.PENDING).first() if rr: return bad_request("A request for this room already exists." "") # Gets the approver with the highest priority for this room rfr = ResponsibleForRoom.query \ .filter_by(room_id=room.id) \ .order_by(ResponsibleForRoom.priority) \ .first() if rfr is None: return bad_request("There is no approver in charge of this room") # Creates a new request for the room room_request = RoomRequest(reader=reader, room=room, justification=justification) approves_room_request = ApprovesRoomRequest(room_request=room_request, approver=rfr.approver) db.session.add(room_request) db.session.add(approves_room_request) db.session.commit() return ok("Request for room {} has been sent." "".format(room_text_id))
def revoke_room_access(): """Revokes a readers access to a room """ schema = {"room_text_id": {"type": "string"}, "email": {"type": "string"}} email = request.json.get("email") room_text_id = request.json.get("room_text_id") # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exist!") has_access = db.session.query(Room, CardReader, HasAccessTo).filter( Room.text_id == room_text_id, or_(CardReader.room_b_id == Room.id, CardReader.room_a_id == Room.id), HasAccessTo.card_reader_id == CardReader.id, HasAccessTo.reader_id == reader.id).all() if not has_access: return bad_request("The reader does not have access to this room") for a in has_access: cr_id = a.CardReader.id # Delete access HasAccessTo.query.filter_by(card_reader_id=cr_id, reader_id=reader.id).delete() db.session.commit() return ok("Access to {0} has been removed for {1}".format( room_text_id, email))
def get_all_access_for_reader(email): """Get a list of all access the reader with the given email has.""" approver_email = get_jwt_identity() approver = Approver.query.filter_by(email=approver_email).first() if not approver: return bad_request("This user does not have the approver role!") # if the user is an admin display all rooms regardless admin = Admin.query.filter_by(approver_id=approver.id).first() if admin: return get_all_access_helper(email) # display all rooms that the approver has responsibility over approver_rooms = get_responsibilites_helper(approver) return get_all_access_helper(email, approver_rooms)
def approve_room_request(current_approver, room_request_id): """Approves a request to a room""" # get the approves_room_request, room_request and reader objects related to the given room_request res = db.session.query(ApprovesRoomRequest, RoomRequest, Reader) \ .join(RoomRequest, RoomRequest.id == ApprovesRoomRequest.room_request_id) \ .join(Reader, Reader.id == RoomRequest.reader_id) \ .filter(ApprovesRoomRequest.approver_id == current_approver.id, RoomRequest.id == room_request_id, RoomRequest.status == RequestStatus.PENDING).first() if res is None: return bad_request("{} not a valid room request for approver.".format( room_request_id)) approves_request = res[0] room_req = res[1] reader = res[2] # request is valid, add access to card readers for the user that lead to the room reader_ids = _find_accesible_doors_to_room_helper(reader.id, room_req.room_id) opposites = _find_opposite_reader_helper(reader_ids) expire_date = date.today() + timedelta(days=HALF_YEAR) for card_reader_pair in opposites: reader_to = card_reader_pair[0] reader_from = card_reader_pair[1] new_access_to = HasAccessTo(reader, reader_to, expire_date) new_access_from = HasAccessTo(reader, reader_from, expire_date) db.session.add(new_access_to) db.session.add(new_access_from) for card_reader in CardReader.query.filter_by(room_b_id=room_req.room_id, room_a_id=None).all(): new_access_to = HasAccessTo(reader, card_reader, expire_date) db.session.add(new_access_to) db.session.delete(approves_request) room_req.status = RequestStatus.APPROVED db.session.commit() return ok('Request for room was approved')
def get_orders(): """Returns a list of all requests done""" # Get the email from the user making the request email = get_jwt_identity() # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exist.") # Gets a list of all the users requested rooms room_relation = RoomRequest.query \ .filter_by(reader_id=reader.id) \ .join(Room, Room.id == RoomRequest.room_id) \ .join(ApprovesRoomRequest, ApprovesRoomRequest.room_request_id == RoomRequest.id) \ .join(Reader, Reader.id == ApprovesRoomRequest.approver_id) \ .all() room_orders = [{ "room_id": x.room_id, "name": x.room.name.capitalize(), "approver": x.request_approver.approver.email, "date": x.datetime_requested, "type": "Room" } for x in room_relation] # Gets a list of all the users requested access groups ag_relation = AccessGroupRequest.query \ .filter_by(reader_id=reader.id) \ .join(AccessGroup, AccessGroup.id == AccessGroupRequest.ag_id) \ .join(ApprovesAgRequest, ApprovesAgRequest.ag_request_id == AccessGroupRequest.id) \ .join(Reader, Reader.id == ApprovesAgRequest.approver_id) \ .all() ag_orders = [{ "ag_id": x.ag_id, "name": x.ag.name.capitalize(), "approver": x.request_approver.approver.email, "date": x.datetime_requested, "type": "Access group" } for x in ag_relation] return ok({"orders": room_orders + ag_orders})
def deny_room_request(current_approver, room_request_id): """Denies a request to a room""" # get the approves_room_request, room_request and reader objects related to the given room_request res = db.session.query(ApprovesRoomRequest, RoomRequest) \ .join(RoomRequest, RoomRequest.id == ApprovesRoomRequest.room_request_id) \ .filter(ApprovesRoomRequest.approver_id == current_approver.id, RoomRequest.id == room_request_id, RoomRequest.status == RequestStatus.PENDING).first() if res is None: return bad_request("{} not a valid room request for approver.".format( room_request_id)) approves_request = res[0] room_req = res[1] db.session.delete(approves_request) room_req.status = RequestStatus.DENIED db.session.commit() return ok('Request for room was denied')
def deny_ag_request(current_approver, ag_request_id): """Denies a request to an access group""" # get the approves_ag_request, access_group_request and reader objects related to the given access_group_request res = db.session.query(ApprovesAgRequest, AccessGroupRequest) \ .join(AccessGroupRequest, AccessGroupRequest.id == ApprovesAgRequest.ag_request_id) \ .filter(ApprovesAgRequest.approver_id == current_approver.id, AccessGroupRequest.id == ag_request_id, AccessGroupRequest.status == RequestStatus.PENDING).first() if res is None: return bad_request( "{} not a valid ag request for approver.".format(ag_request_id)) approves_request = res[0] ag_req = res[1] db.session.delete(approves_request) ag_req.status = RequestStatus.DENIED db.session.commit() return ok('Request for access group was denied')
def order_ag(): """Order access to a access group for the logged in user""" # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") schema = { "ag_id": { "type": "integer" }, "justification": { "type": "string", "maxlength": 220 } } # Get the email, access group and the justification for the access to said access group. email = get_jwt_identity() ag_id = request.json.get("ag_id") justification = request.json.get("justification") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) # Checks if the reader exists in the database reader = Reader.query.filter_by(email=email).first() if not reader: return bad_request("Reader does not exists.") # Checks if the access group exists in the database ag = AccessGroup.query.filter_by(id=ag_id).first() if not ag: return bad_request("Access group does not exist.".format(ag_id)) # Checks if the reader has already sent a request for this access group agr = AccessGroupRequest.query.filter_by( ag_id=ag_id, reader_id=reader.id, status=RequestStatus.PENDING).first() if agr: return bad_request("A request for this access group already exists.") # Gets the approver with the highest priority for this access group rfag = ResponsibleForAg.query \ .filter_by(ag_id=ag_id) \ .order_by(ResponsibleForAg.priority) \ .first() if rfag is None: return bad_request( "There is no approver in charge of this access group.") # Creates a new request for the access group ag_request = AccessGroupRequest(reader=reader, ag=ag, justification=justification) approves_ag_request = ApprovesAgRequest(ag_request=ag_request, approver=rfag.approver) db.session.add(ag_request) db.session.add(approves_ag_request) db.session.commit() return ok("Request for access group {} has been sent.".format(ag_id))
def create_ag(): """Creates a new (or changes an already existing) access group""" # name: The (String) name of the access group, as will be displayed. # approvers: a list of email addresses belonging to approvers. # rooms: a list of room text_ids. schema = { "ag_name": { "type": "string", "minlength": 2 }, "approvers": { "type": "list", "schema": { "type": "string", "regex": "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$" } }, "room_text_ids": { "type": "list", "schema": { "type": "string", "minlength": 2 } }, } # Checks if the request is a json if not request.is_json: return bad_request("Missing JSON in request") # Checks if any of the input is illegal if not validator(request.json, schema): return bad_request(validator.errors) ag_name = request.json.get("ag_name") approvers = request.json.get("approvers") room_text_ids = request.json.get("room_text_ids") if not approvers: return bad_request("The list of approvers can not be empty!") if not room_text_ids: return bad_request("The list of rooms can not be empty!") # If the access group DOES NOT exist create it ag = AccessGroup.query.filter_by(name=ag_name).first() if not ag: ag = AccessGroup(name=ag_name) db.session.add(ag) # If the access group DOES exist remove the existing card readers and approvers, # Move all currently tasked requests to the first new approver else: ag.card_readers.clear() ag.approvers.clear() approver = Approver.query.filter_by(email=approvers[0]).first() if not approver: return bad_request("Approver does not exist!") for agr in AccessGroupRequest.query.filter_by(ag_id=ag.id).all(): aagr = ApprovesAgRequest.query.filter_by( ag_request_id=agr.id).first() aagr.approver_id = approver.id # update approves_ag_request by taking all request_ids from ag request with this ag_id # change the approver id in approves request to the new approver with the highest priority priority = 1 # First approver in list get highest priority, and so on. for approver_email in request.json.get("approvers"): approver = Approver.query.filter_by(email=approver_email).first() if not approver: return bad_request("Approver does not exist!") rfag = ResponsibleForAg(approver=approver, ag=ag, priority=priority) # Add and commit? db.session.add(rfag) priority += 1 # Check if all rooms does exist list_of_rooms = [] for room_text_id in room_text_ids: room = Room.query.filter_by(text_id=room_text_id).first() if not room: return bad_request("Room {} does not exist!".format(room_text_id)) list_of_rooms.append(room) # Get a list of all card readers that link the rooms together list_of_room_ids = [room.id for room in list_of_rooms] list_of_card_readers = CardReader.query.filter( and_(CardReader.room_b_id.in_(list_of_room_ids), CardReader.room_a_id.in_(list_of_room_ids))).all() # Check if the rooms are connected to eachother by card readers temp_rooms = Room.query.filter( Room.id.in_([cr.room_b_id for cr in list_of_card_readers])).all() requested_rooms = [room.text_id for room in list_of_rooms] resulting_rooms = [room.text_id for room in temp_rooms] diff = [room for room in requested_rooms if room not in resulting_rooms] if diff: return bad_request( "The room(s) {} has no card readers connecting to the rest of the rooms!" .format(diff)) ag.card_readers = list_of_card_readers db.session.commit() return ok("Access Group was successfully created!")