def put(cls, logged_activity_id=None): """Put method for rejecting logged activity resource.""" if logged_activity_id is None: return response_builder(dict( message='loggedActivitiesIds is required'), 400) logged_activity = LoggedActivity.query.filter_by( uuid=logged_activity_id).first() if not logged_activity: return response_builder(dict(message='Logged activity not found'), 404) if logged_activity.status == 'pending': logged_activity.status = 'rejected' user_logged_activity = single_logged_activity_schema.dump( logged_activity).data user_logged_activity['society'] = { 'id': user_logged_activity['societyId'], 'name': user_logged_activity['society'] } del user_logged_activity['societyId'] return response_builder(dict( data=user_logged_activity, message='Activity successfully rejected'), 200) else: return response_builder(dict( status='failed', message='This logged activity is either in-review,' ' approved or already rejected'), 403)
def get(cls, user_id): """Get a user's logged activities by user_id URL parameter.""" user = User.query.get(user_id) if not user: return response_builder(dict(message="User not found"), 404) message = "Logged activities fetched successfully" user_logged_activities = user.logged_activities.all() if not user_logged_activities: message = "There are no logged activities for that user." points_earned = db.session.query( func.sum(LoggedActivity.value) ).filter( LoggedActivity.user_id == user_id, LoggedActivity.status == 'approved' ).scalar() return response_builder(dict( data=user_logged_activities_schema.dump( user_logged_activities).data, society=user.society.name if user.society else None, societyId=user.society.uuid if user.society else None, activitiesLogged=len(user_logged_activities), pointsEarned=points_earned if points_earned else 0, message=message ), 200)
def post(self): """Create a society.""" payload = request.get_json(silent=True) if payload: try: name = payload["name"] color_scheme = payload["colorScheme"] logo = payload["logo"] photo = payload["photo"] except KeyError: return response_builder(dict( status="fail", message="Name, color scheme and logo are required" " to create a society." ), 400) # if no errors occur in assigning above society = self.Society( name=name, color_scheme=color_scheme, logo=logo, photo=photo ) society.save() return response_builder(dict( status="success", data=society.serialize(), message="Society created successfully." ), 201) return response_builder(dict( status="fail", message="Data for creation must be provided"), 400)
def post(self): """Create new activity type.""" payload = request.get_json(silent=True) if not payload: return response_builder(dict( message="Data for creation must " "be provided.", status="fail", ), 400) result, errors = new_activity_type_schema.load(payload) if errors: status_code = new_activity_type_schema.context.get( 'status_code') validation_status_code = status_code or 400 return response_builder(errors, validation_status_code) support_multiple = result.get("supports_multiple_participants") activity_type = self.ActivityType( name=result["name"], description=result["description"], value=result["value"], supports_multiple_participants=support_multiple ) activity_type.save() return response_builder(dict( status="success", data=activity_type.serialize(), message="Activity type created successfully." ), 201)
def get(self, society_id=None): """Get Society(ies) details.""" if society_id: society = self.Society.query.get(society_id) elif request.args.get('name'): society = self.Society.query.filter_by( name=request.args.get('name')).first() else: # if no search term has been passed, return all societies in DB societies = self.Society.query return paginate_items(societies) if society: society_logged_activities = society.logged_activities.all() data, _ = society_schema.dump(society) data['loggedActivities'], _ = user_logged_activities_schema.dump( society_logged_activities) return response_builder(dict( societyDetails=data, message="{} fetched successfully.".format(society.name) ), 200) else: return response_builder(dict( data=None, message="Resource does not exist." ), 404)
def edit_role(payload, search_term): """Find and edit the role.""" role = Role.query.get(search_term) # if edit request == stored value if not role: return response_builder( dict(status="fail", message="Role does not exist."), 404) try: if payload["name"] == role.name: return response_builder( dict(data=dict(path=role.serialize()), message="No change specified."), 200) else: old_role_name = role.name role.name = payload["name"] role.save() return response_builder( dict(data=dict(path=role.serialize()), message="Role {} has been changed" " to {}.".format(old_role_name, role.name)), 200) except KeyError: return response_builder( dict(status="fail", message="Name to edit to must be provided."), 400)
def post(cls): """Create an activity.""" payload = request.get_json(silent=True) if payload: result, errors = activity_schema.load(payload) if errors: status_code = activity_schema.context.get('status_code') activity_schema.context = {} validation_status_code = status_code or 400 return response_builder(errors, validation_status_code) else: activity = Activity( name=result['name'], description=result['description'], activity_type_id=result['activity_type_id'], activity_date=result['activity_date'], added_by_id=g.current_user.uuid) activity.save() return response_builder( dict(message='Activity created' ' successfully.', data=result), 201) return response_builder( dict(message="Data for creation must be provided."), 400)
def put(self, logged_activity_id): """Put method on logged Activity resource.""" payload = request.get_json(silent=True) if 'status' not in payload: return response_builder(dict(message='status is required.'), 400) logged_activity = self.LoggedActivity.query.filter_by( uuid=logged_activity_id).first() if not logged_activity: return response_builder(dict(message='Logged activity not found'), 404) if logged_activity.society.uuid != g.current_user.society.uuid: society = logged_activity.society.name return response_builder(dict( message=f"Permission denied, you are not a secretary of {society}" ), 403) if not (payload.get('status') in ['pending', 'rejected']): return response_builder(dict(message='Invalid status value.'), 400) logged_activity.status = payload.get('status') logged_activity.save() return response_builder( dict(data=single_logged_activity_schema.dump(logged_activity).data, message="successfully changed status"), 200)
def put(self, redeem_id=None): """Complete Redemption Requests and mark them so.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Data for editing must be provided", status="fail"), 400) if not redeem_id: return response_builder( dict(status="fail", message="RedemptionRequest id must be provided."), 400) redemp_request = self.RedemptionRequest.query.get(redeem_id) if not redemp_request: return response_builder( dict(data=None, status="fail", message="Resource does not exist."), 404) status = payload.get("status") if status == "completed": redemp_request.status = status CIO = self.Role.query.filter_by(name='cio').first() if CIO and CIO.users.all(): # TODO Add logging here email_payload = dict( sender=current_app.config["SENDER_CREDS"], subject="RedemptionRequest for {}".format( redemp_request.user.society.name), message= "Redemption Request on {} has been completed. Finance" " has wired the money to the reciepient.".format( redemp_request.name), recipients=([user.email for user in CIO.users] + [redemp_request.user.email])) self.email.send(current_app._get_current_object(), payload=email_payload, mail=self.mail) else: return response_builder( dict( status="Failed", message="Invalid status.", ), 400) redemp_request.save() mes = f"Redemption request status changed to {redemp_request.status}." serialized_redemption = serialize_redmp(redemp_request) serialized_completed_by, _ = basic_info_schema.dump(g.current_user) serialized_redemption["completedBy"] = serialized_completed_by return response_builder( dict(status="success", data=serialized_redemption, message=mes), 200)
def decorated(*args, **kwargs): # check that the Authorization header is set authorization_token = request.headers.get('Authorization') if not authorization_token: return response_builder( dict(message="Bad request. Header does" "not contain authorization token"), 400) unauthorized_message = "Unauthorized. The authorization token " \ "supplied is invalid" try: # decode token public_key = base64.b64decode( current_app.config['PUBLIC_KEY']).decode("utf-8") payload = verify_token(authorization_token, public_key, current_app.config['API_AUDIENCE'], current_app.config['API_ISSUER']) except ExpiredSignatureError: expired_response = "The authorization token supplied is expired" return response_builder(dict(message=expired_response), 401) except JWTError: return response_builder(dict(message=unauthorized_message), 401) expected_user_info_format = { "id": "user_id", "email": "gmail", "first_name": "test", "last_name": "user", "name": "test user", "picture": "link", "roles": { "Andelan": "unique_id", "Fellow": "unique_id" } } expected_user_keys = expected_user_info_format.keys() payload_user_keys = payload.get("UserInfo").keys() # confirm that payload and UserInfo has required keys if ("UserInfo" and "exp") not in payload.keys(): return response_builder(dict(message=unauthorized_message), 401) elif not all(item in payload_user_keys for item in expected_user_keys): return response_builder(dict(message=unauthorized_message), 401) else: user = User.query.get(payload["UserInfo"]["id"]) if not user: user = store_user_details(payload, authorization_token) g.current_user = user g.current_user_token = authorization_token # attempt to link user to society if not g.current_user.society and g.current_user.cohort: user.society = g.current_user.cohort.society user.save() return f(*args, **kwargs)
def post(cls): """Log a new activity.""" payload = request.get_json(silent=True) if payload: result, errors = log_edit_activity_schema.load(payload) if errors: return response_builder(dict(validationErrors=errors), 400) society = g.current_user.society if not society: return response_builder(dict( message='You are not a member of any society yet' ), 422) parsed_result = parse_log_activity_fields(result) if not isinstance(parsed_result, ParsedResult): return parsed_result # log activity logged_activity = LoggedActivity( name=result.get('name'), description=result.get('description'), society=society, user=g.current_user, activity=parsed_result.activity, photo=result.get('photo'), value=parsed_result.activity_value, activity_type=parsed_result.activity_type, activity_date=parsed_result.activity_date ) if logged_activity.activity_type.name == 'Bootcamp Interviews': if not result['no_of_participants']: return response_builder(dict( message="Data for creation must be" " provided. (no_of_" "participants)"), 400) else: logged_activity.no_of_participants = result[ 'no_of_participants' ] logged_activity.save() return response_builder(dict( data=single_logged_activity_schema.dump(logged_activity).data, message='Activity logged successfully' ), 201) return response_builder(dict( message="Data for creation must be provided."), 400)
def post(cls): """Create Redemption Request.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Redemption request must have data.", status="fail"), 400) result, errors = redemption_request_schema.load(payload) if errors: return response_builder(errors, 400) if result.get('value') > g.current_user.society.remaining_points: return response_builder( dict(message="Redemption request value exceeds your society's " "remaining points", status="fail"), 403) center = Center.query.filter_by(name=result.get('center')).first() if center: redemp_request = RedemptionRequest( name=result.get('name'), value=result.get('value'), description=result.get('description'), user=g.current_user, center=center, society=g.current_user.society) redemp_request.save() data, _ = redemption_schema.dump(redemp_request) data["center"], _ = basic_info_schema.dump(center) send_email.delay(sender=current_app.config["SENDER_CREDS"], subject="RedemptionRequest for {}".format( g.current_user.society.name), message="Redemption Request reason:{}." "Redemption Request value: {} points".format( redemp_request.name, redemp_request.value), recipients=[current_app.config["CIO"]]) return response_builder( dict( message="Redemption request created. Success Ops will be in" " touch soon.", status="success", data=serialize_redmp(redemp_request)), 201) else: return response_builder( dict(message= "Redemption request name, value and center required", status="fail"), 400)
def put(self, redeem_id=None): """Complete Redemption Requests and mark them so.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Data for editing must be provided", status="fail"), 400) if not redeem_id: return response_builder( dict(status="fail", message="RedemptionRequest id must be provided."), 400) redemp_request = RedemptionRequest.query.get(redeem_id) if not redemp_request: return response_builder( dict(data=None, status="fail", message="Resource does not exist."), 404) status = payload.get("status") if status == "completed": redemp_request.status = status send_email.delay( sender=current_app.config["SENDER_CREDS"], subject="RedemptionRequest for {}".format( redemp_request.user.society.name), message="Redemption Request on {} has been completed. Finance" " has wired the money to the reciepient.".format( redemp_request.name), recipients=[ redemp_request.user.email, current_app.config["CIO"] ]) else: return response_builder( dict( status="Failed", message="Invalid status.", ), 400) redemp_request.save() mes = f"Redemption request status changed to {redemp_request.status}." serialized_redemption = serialize_redmp(redemp_request) serialized_completed_by, _ = basic_info_schema.dump(g.current_user) serialized_redemption["completedBy"] = serialized_completed_by return response_builder( dict(status="success", data=serialized_redemption, message=mes), 200)
def put(cls, logged_activity_id=None): """Edit an activity.""" payload = request.get_json(silent=True) if payload: log_edit_activity_schema.context = {'edit': True} result, errors = log_edit_activity_schema.load(payload) log_edit_activity_schema.context = {} if errors: return response_builder(dict(validationErrors=errors), 400) logged_activity = LoggedActivity.query.filter_by( uuid=logged_activity_id, user_id=g.current_user.uuid).one_or_none() if not logged_activity: return response_builder(dict( message='Logged activity does not exist' ), 404) if logged_activity.status != 'in review': return response_builder(dict( message='Not allowed. Activity is already in pre-approval.' ), 401) if not result.get('activity_type_id'): result['activity_type_id'] = logged_activity.activity_type_id if not result.get('date'): result['date'] = logged_activity.activity_date parsed_result = parse_log_activity_fields(result) if not isinstance(parsed_result, ParsedResult): return parsed_result # update fields logged_activity.name = result.get('name') logged_activity.description = result.get('description') logged_activity.activity = parsed_result.activity logged_activity.photo = result.get('photo') logged_activity.value = parsed_result.activity_value logged_activity.activity_type = parsed_result.activity_type logged_activity.activity_date = parsed_result.activity_date logged_activity.save() return response_builder(dict( data=single_logged_activity_schema.dump(logged_activity).data, message='Activity edited successfully' ), 200) return response_builder(dict( message="Data for creation must be provided."), 400)
def put(cls, role_query=None): """Edit a role's details.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Data for editing must " "be provided"), 400) if not role_query: return response_builder( dict(status="fail", message="Role id/name must be provided."), 400) return edit_role(payload, role_query)
def delete(cls, role_query=None): """Delete a role.""" if not role_query: return response_builder( dict(status="fail", message="Role id must be provided."), 400) role = Role.query.get(role_query) if not role: return response_builder( dict(status="fail", message="Role does not exist."), 404) role.delete() return response_builder( dict(status="success", message="Role deleted successfully."), 200)
def delete(self, redeem_id=None): """Delete Redemption Requests.""" if not redeem_id: return response_builder( dict(status="fail", message="RedemptionRequest id must be provided."), 400) redemp_request = get_redemption_request(redeem_id) if not isinstance(redemp_request, self.RedemptionRequest): return redemp_request redemp_request.delete() return response_builder( dict(status="success", message="RedemptionRequest deleted successfully."), 200)
def put(self, logged_activity_id=None): """Put method for requesting more info on a logged activity.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Data for editing must be provided", status="fail"), 400) if not logged_activity_id: return response_builder( dict(status="fail", message="LoggedActivity id must be provided."), 400) logged_activity = self.LoggedActivity.query.get(logged_activity_id) if not logged_activity: return response_builder(dict(message='Logged activity not found'), 404) comment = payload.get("comment") if comment: email_payload = dict( sender=current_app.config["SENDER_CREDS"], recipients=[logged_activity.user.email], subject="More Info on Logged Activity for {}".format( logged_activity.user.society.name), message="Success Ops needs more information on this" " logged activity: {}.\\n Context: {}." "\\nClick <a href='{}'>here</a>" " to view the logged activity and edit the" " description to give more informaton.".format( logged_activity.name, comment, request.host_url + '/api/v1/logged-activities/' + logged_activity.uuid), ) self.email.send(current_app._get_current_object(), payload=email_payload, mail=self.mail) else: return response_builder( dict(status="fail", message="Context for extra informaton must be provided."), 400) return response_builder( dict(status='success', message='Extra information has been successfully requested'), 200)
def delete(cls, act_types_id=None): """Delete an activity type.""" if not act_types_id: return response_builder( dict(status="fail", message="Activity type must be provided."), 400) activity_type = ActivityType.query.get(act_types_id) if not activity_type: return response_builder( dict(message="Resource not found.", status="fail"), 404) activity_type.delete() return response_builder( dict(status="success", message="Activity type deleted successfully."), 200)
def get(cls): """Get all logged activities.""" paginate = request.args.get("paginate", "true") message = "all Logged activities fetched successfully" if paginate.lower() == "false": logged_activities = LoggedActivity.query.all() count = LoggedActivity.query.count() data = {"count": count} else: logged_activities = LoggedActivity.query pagination_result = paginate_items(logged_activities, serialize=False) logged_activities = pagination_result.data data = { "count": pagination_result.count, "page": pagination_result.page, "pages": pagination_result.pages, "previous_url": pagination_result.previous_url, "next_url": pagination_result.next_url } data.update(dict( loggedActivities=logged_activities_schema.dump( logged_activities ).data)) return response_builder(dict(data=data, message=message, status="success"), 200)
def delete(cls, society_id=None): """Delete Society.""" if not society_id: return response_builder( dict(status="fail", message="Society id must be provided."), 400) society = Society.query.get(society_id) if not society: return response_builder( dict(status="fail", message="Society does not exist."), 404) society.delete() return response_builder( dict(status="success", message="Society deleted successfully."), 200)
def put(self, act_types_id=None): """Edit information on an activity type.""" payload = request.get_json(silent=True) if not payload: return response_builder(dict( message="Data for editing must " "be provided.", status="fail", ), 400) if not act_types_id: return response_builder(dict( message="Activity type to be edited" " must be provided", status="fail", ), 400) target_activity_type = self.ActivityType.query.get(act_types_id) if not target_activity_type: return response_builder(dict( status="fail", message="Resource not found." ), 404) result, errors = edit_activity_type_schema.load(payload, partial=True) new_data = [ (key, result[key]) for key in result if getattr(target_activity_type, key) != result[key] ] if errors: status_code = edit_activity_type_schema.context.get( 'status_code') validation_status_code = status_code or 400 return response_builder(errors, validation_status_code) for data in new_data: setattr(target_activity_type, *data) # save the model here target_activity_type.save() return response_builder(dict( message="Edit successful", data=target_activity_type.serialize(), status="success", ), 200)
def delete(self, logged_activity_id=None): """Delete a logged activity.""" logged_activity = self.LoggedActivity.query.filter_by( uuid=logged_activity_id, user_id=g.current_user.uuid).one_or_none() if not logged_activity: return response_builder( dict(message='Logged Activity does not exist!'), 404) if logged_activity.status != 'in review': return response_builder( dict(message='You are not allowed to perform this operation'), 403) logged_activity.delete() return response_builder(dict(), 204)
def put(cls): """Change the a society executives.""" payload = request.get_json(silent=True) if not payload: return response_builder( dict(message="Executive for change must be provided"), 400) if not (payload.get("role") and payload.get("society") and payload.get("name")): return response_builder( dict(message="Role, society and individual for change " "must be provided"), 400) society = Society.query.filter_by(name=payload.get("society")).first() role_change = Role.query.filter_by(name=payload.get("role")).first() if not role_change: return response_builder( dict(message="Create role to be appended.", status="fail"), 404) if not society: return response_builder( dict(message="Society not found", status="fail"), 404) query_user_role_changing = role_change.users.filter_by( society=society).one_or_none() if query_user_role_changing and \ query_user_role_changing.society_id == society.uuid: old_exec = query_user_role_changing else: old_exec = None new_exec = User.query.filter_by(name=payload.get("name"), society=society).first() if not new_exec: return response_builder( dict(message="New Executive member not found or does not" " belong to society.", status="fail"), 404) # Remove the old role from the outgoing executive if not old_exec: return response_builder( dict(message="Previous Executive not found.", status="fail"), 404) for role in old_exec.roles.all(): if role.uuid == role_change.uuid: old_exec.roles.remove(role) new_exec.roles.append(role_change) new_exec.save() return response_builder( dict(data=new_exec.serialize(), message="{} has been appointed {} of {}".format( new_exec.name, payload.get("role"), society.name), status="success"), 200)
def get_redemption_request(redeem_id): if "society president" in [role.name for role in g.current_user.roles]: redemp_request = g.current_user.society.redemptions.filter_by( uuid=redeem_id).one_or_none() else: redemp_request = RedemptionRequest.query.get(redeem_id) if not redemp_request: return response_builder( dict(status="fail", message="RedemptionRequest does not exist."), 404) if redemp_request.status != "pending": return response_builder( dict(status="fail", message="RedemptionRequest already approved or rejected"), 403) return redemp_request
def put(cls): """Assign a cohort to a society. Return response (dict): key:status """ payload = request.get_json(silent=True) if not payload or not ('societyId' in payload and 'cohortId' in payload): return response_builder( dict(message="Error societyId and cohortId are required."), 400) society = Society.query.filter_by( uuid=payload.get('societyId')).first() if not society: return response_builder(dict(message="Error Invalid societyId."), 400) cohort = Cohort.query.filter_by(uuid=payload.get('cohortId')).first() if not cohort: return response_builder(dict(message="Error Invalid cohortId."), 400) if cohort.society_id == society.uuid: return response_builder(dict(message="Cohort already in society."), 409) society.cohorts.append(cohort) society.save() cohort.save() cohort_data = cohort_schema.dump(cohort).data cohort_meta_data = { 'society': base_schema.dump(society).data, 'center': base_schema.dump(cohort.center).data } cohort_data['meta'] = cohort_meta_data return response_builder( dict(message="Cohort added to society succesfully", data=cohort_data), 200)
def put(self, society_id=None): """Edit Society details.""" payload = request.get_json(silent=True) if payload: if not society_id: return response_builder(dict( status="fail", message="Society to be edited must be provided"), 400) society = self.Society.query.get(society_id) if society: try: name = payload["name"] or None color_scheme = payload["colorScheme"] or None logo = payload["logo"] or None photo = payload["photo"]or None if name: society.name = name if color_scheme: society.color = color_scheme if photo: society.photo = logo if logo: society.logo = photo society.save() return response_builder(dict( data=society.serialize(), status="success", message="Society edited successfully." ), 200) except KeyError as e: return response_builder(dict( module="Society Module", errors=e), 500) return response_builder(dict( status="fail", message="Society does not exist."), 404) # if payload does not exist return response_builder(dict( status="fail", message="Data for editing must be provided"), 400)
def post(cls): """Create a Role.""" payload = request.get_json(silent=True) if payload: result, errors = role_schema.load(payload) if errors: status_code = role_schema.context.get('status_code') validation_status_code = status_code or 400 return response_builder(errors, validation_status_code) role = Role(name=result['name']) role.save() return response_builder( dict(message='Role created successfully.', data=role.serialize()), 201) return response_builder( dict(message="Data for creation must be provided."), 400)
def parse_log_activity_fields(result, activity_model, activity_type_model): """Parse the fields of the Log Activity Fields.""" if result.get('activity_id'): activity = activity_model.query.get(result['activity_id']) if not activity: return response_builder(dict(message='Invalid activity id'), 422) activity_type = activity.activity_type if activity_type.supports_multiple_participants and \ not (result.get('no_of_participants') and result.get('description')): return response_builder( dict(message='Please send the number of interviewees and' ' their names in the description'), 400) activity_date = activity.activity_date time_difference = datetime.date.today() - activity_date else: activity_date = result['date'] if activity_date > datetime.date.today(): return response_builder(dict(message='Invalid activity date'), 422) activity_type = activity_type_model.query.get( result['activity_type_id']) if not activity_type: return response_builder(dict(message='Invalid activity type id'), 422) activity = None time_difference = datetime.date.today() - activity_date if time_difference.days > 30: return response_builder( dict(message='You\'re late. That activity' ' happened more than 30 days ago'), 422) activity_value = activity_type.value if not \ activity_type.supports_multiple_participants else \ activity_type.value * result['no_of_participants'] return ParsedResult(activity, activity_type, activity_date, activity_value)
def decorated(*args, **kwargs): route_roles = list( filter(lambda r: r is not None, [ Role.query.filter_by(name=role).first() for role in roles ])) for role in g.current_user.roles: if role in route_roles: break else: return response_builder( dict(message="You're unauthorized" " to perform this operation"), 401) return f(*args, **kwargs)