Exemple #1
0
def create_or_update_program(program_id=None):
	action = 'update' if program_id else 'create'

	user = get_user()

	if not permitted(user, action, 'program', program_id):
		return "Not authorized", 401

	if program_id:
		program = db_session.query(MonitoringProgram).get(program_id)
	else:
		program = MonitoringProgram()

	if not program:
		return "Not found", 400

	body = request.json

	errors = validate_fields(program_fields, body)

	if len(errors):
		return jsonify(errors), 400

	update_program_from_json(program, body)
	db_session.add(program)
	db_session.flush()

	if action == 'create':
		db_session.execute("""INSERT INTO user_program_manager (user_id, monitoring_program_id) VALUES (:user_id, :program_id)""",
				{ 'program_id': program.id, 'user_id': user.id })


	db_session.commit()

	return jsonify(program_to_json(program)), 200 if program_id else 201
Exemple #2
0
def get_source_processing_notes(source_id=None):
	user = get_user()

	if not permitted(user, 'get', 'source', source_id):
		return "Not authorized", 401

	source = db_session.query(Source).get(source_id) if source_id else None

	if source == None:
		return "Not found", 404

	db_session.execute("SET time_zone = '+00:00'")

	rows = db_session.execute("""SELECT
		notes.id,
		user.first_name,
		user.last_name,
		user.email,
		notes.source_id,
		notes.time_created,
		notes.notes,
		user.id = :user_id AS editable
		FROM data_processing_notes notes
		JOIN user ON notes.user_id = user.id
		WHERE notes.source_id = :source_id
	""", { 'source_id': source_id, 'user_id': user.id })

	return jsonify_rows(rows)
Exemple #3
0
def add_manager_to_monitoring_program(program_id = None):
	if program_id == None:
		return "Not found", 404

	user = get_user()

	if not permitted(user, 'mangage_managers', 'program', program_id):
		return "Not authorized", 401

	body = request.json

	email = body["email"]

	if not re.match(email_regex, email):
		return jsonify({ 'error' : '"%s" is not a valid email address' % email }), 400

	manager = db_session.query(User).filter(User.email == email).one_or_none()

	if not manager:
		manager = User(email=email)
		db_session.add(manager)
		db_session.flush()

	db_session.execute("""REPLACE INTO user_program_manager (user_id, monitoring_program_id) VALUES (:user_id, :program_id)""",
		{ 'user_id': manager.id, 'program_id': program_id })
	db_session.commit()

	return "OK", 201
Exemple #4
0
def get_source_imports(source_id=None):
	user = get_user()

	if not permitted(user, 'get', 'source', source_id):
		return "Not authorized", 401

	source = db_session.query(Source).get(source_id) if source_id else None

	if source == None:
		return "Not found", 404

	db_session.execute("SET time_zone = '+00:00'")

	rows = db_session.execute("""SELECT
		data_import.id,
		data_import.filename,
		data_import.data_type,
		data_import_status.code AS status,
		data_import.time_created,
		data_import.upload_uuid
		FROM data_import
		LEFT JOIN data_import_status ON data_import_status.id = data_import.status_id
		WHERE data_import.source_id = :source_id
	""", { 'source_id': source_id })

	return jsonify_rows(rows)
Exemple #5
0
def create_user():
	body = request.json

	fields = [
		Field(name='email', title='Email address', validators=[validate_required, validate_email]),
		Field(name='first_name', title='First name', validators=[validate_required, validate_max_chars(255)]),
		Field(name='last_name', title='Last name', validators=[validate_required, validate_max_chars(255)]),
		Field(name='phone_number', title='Phone number', validators=[validate_max_chars(32)]),
		Field(name='password', title='Password', validators=[validate_required, validate_min_chars(8)])
	]

	errors = validate_fields(fields, body)

	if len(errors):
		return jsonify(errors), 400

	user = db_session.query(User).filter(User.email == body['email']).one_or_none()
	if user:
		if user.password_hash:
			# User already has an ccount
			return jsonify({ 'email': "An account with this email address already exists" }), 400
	else:
		user = User(email=body['email'].strip())

	user.first_name=body['first_name'].strip()
	user.last_name=body['last_name'].strip()
	user.phone_number=body['phone_number'].strip()
	user.password_hash=pwd_context.hash(body['password'])

	try:
		db_session.add(user)
		db_session.flush()
	except exc.IntegrityError:
		# User already exists
		pass

	db_session.execute("""INSERT INTO user_role (user_id, role_id)
		VALUES (:user_id, (SELECT id FROM role WHERE description = 'Custodian'))""",
		{'user_id': user.id})

	db_session.commit()

	try:
		email_body = new_account_body.substitute(name=user.first_name)
		send_email(user.email, 'TSX Account Created', email_body)
	except Exception as e:
		print('Error sending email to %s' % user.email)
		print('Error: %s' % e)

	return "OK", 204 # Success
Exemple #6
0
def update_user(user_id):
	body = request.json

	fields = [
		Field(name='email', title='Email address', validators=[validate_required, validate_email]),
		Field(name='first_name', title='First name', validators=[validate_required, validate_max_chars(255)]),
		Field(name='last_name', title='Last name', validators=[validate_required, validate_max_chars(255)]),
		Field(name='phone_number', title='Phone number', validators=[validate_max_chars(32)])
		# Field(name='password', title='Password', validators=[validate_required, validate_min_chars(8)])
	]

	errors = validate_fields(fields, body)

	if len(errors):
		return jsonify(errors), 400

	user = db_session.query(User).filter(User.id == user_id).one_or_none()

	if not user:
		return 'Not found', 404

	email = body['email'].strip()

	email_user = db_session.query(User).filter(User.email == email).one_or_none()

	if user != email_user:
		return jsonify({ 'email': 'Email is used by another account' }), 400

	user.email = email
	user.first_name = body['first_name'].strip()
	user.last_name = body['last_name'].strip()
	user.phone_number = body['phone_number'].strip()
	# user.password_hash=pwd_context.hash(body['password'])

	db_session.commit()

	return "OK", 204 # Success
Exemple #7
0
def delete_source_processing_notes(source_id=None, note_id=None):
	user = get_user()

	if not permitted(user, 'delete', 'source', source_id):
		return "Not authorized", 401

	notes = db_session.query(DataProcessingNotes).get(note_id)

	if notes.source_id != source_id:
		return "Source id doesn't match", 400

	db_session.delete(notes)
	db_session.commit()

	return "OK", 200
Exemple #8
0
def update_source_processing_notes(source_id=None, note_id=None):
	user = get_user()

	if not permitted(user, 'update', 'source', source_id):
		return "Not authorized", 401

	notes = db_session.query(DataProcessingNotes).get(note_id)

	if notes.source_id != source_id:
		return "Source id doesn't match", 400

	body = request.json # TODO: validate json
	notes.notes = body['notes']
	db_session.add(notes)
	db_session.commit()

	return "OK", 201
Exemple #9
0
def permitted(user, action, resource_type, resource_id=None):
    if user == None:
        return False

    user_roles = get_roles(user)
    if 'Administrator' in user_roles:
        return True

    if resource_type == 'source':
        if 'Program manager' in user_roles:
            if action in ('create', 'list'):
                return True
            if action in ('get', 'update',
                          'download_data') and is_program_manager_of_source(
                              user.id, resource_id):
                return True

        if 'Custodian' in user_roles:
            if action in ('create', 'list'):
                return True
            if action in ('get', 'update', 'delete', 'import_data',
                          'manage_custodians',
                          'download_data') and is_custodian_of_source(
                              user.id, resource_id):
                return True

    if resource_type == 'user':
        if action in ('list_programs'):
            return True

    if resource_type == 'program':
        if action in ('list_managers'):
            return True
        if action in ('download_data', 'update'):
            return is_program_manager_of_program(user.id, resource_id)
        if action in ('create'):
            return 'Program manager' in user_roles

    if resource_type == 'notes' and 'Custodian' in user_roles:
        try:
            notes = db_session.query(DataProcessingNotes).get(resource_id)
            return notes.user_id == user.id
        except:
            return False

    return False
Exemple #10
0
def get_program(program_id=None):
	user = get_user()

	if not permitted(user, 'get', 'program', program_id):
		return "Not authorized", 401

	program = db_session.query(MonitoringProgram).get(program_id) if program_id else None

	if program == None:
		return "Not found", 404

	result = program_to_json(program)

	result['can_delete'] = permitted(user, 'delete', 'program', program_id)
	result['can_manage_managers'] = permitted(user, 'manage_managers', 'program', program_id)

	return jsonify(result), 200
Exemple #11
0
def get_source(source_id=None):
	user = get_user()

	if not permitted(user, 'get', 'source', source_id):
		return "Not authorized", 401

	source = db_session.query(Source).get(source_id) if source_id else None

	if source == None:
		return "Not found", 404

	result = source_to_json(source)

	result['can_delete'] = permitted(user, 'delete', 'source', source_id)
	result['can_import_data'] = permitted(user, 'import_data', 'source', source_id)
	result['can_manage_custodians'] = permitted(user, 'manage_custodians', 'source', source_id)

	return jsonify(result), 200
Exemple #12
0
def login():
	body = request.json

	fields = [
		Field(name='email', title='Email address', validators=[validate_required, validate_email]),
		Field(name='password', title='Password', validators=[validate_required])
	]

	errors = validate_fields(fields, body)

	if len(errors):
		return jsonify(errors), 400

	user = db_session.query(User).filter(User.email == body['email']).one_or_none()

	if user is not None and pwd_context.verify(body['password'], user.password_hash):
		session['user_id'] = user.id
		return "OK", 200
	else:
		return jsonify({ 'password': "******" }), 400
Exemple #13
0
def get_source_custodians(source_id=None):
	user = get_user()

	if not permitted(user, 'manage_custodians', 'source', source_id):
		return "Not authorized", 401

	source = db_session.query(Source).get(source_id) if source_id else None

	if source == None:
		return "Not found", 404

	rows = db_session.execute("""SELECT
		user.first_name,
		user.last_name,
		user.email,
		user.id
		FROM user_source
		JOIN user ON user_source.user_id = user.id
		WHERE user_source.source_id = :source_id
	""", { 'source_id': source_id })

	return jsonify_rows(rows)
Exemple #14
0
def create_or_update_source(source_id=None):
	action = 'update' if source_id else 'create'

	user = get_user()

	if not permitted(user, action, 'source', source_id):
		return "Not authorized", 401

	if source_id:
		source = db_session.query(Source).get(source_id)
	else:
		source = Source()

	if not source:
		return "Not found", 400

	body = request.json

	errors = validate_fields(source_fields, body)

	if len(errors):
		return jsonify(errors), 400

	update_source_from_json(source, body)
	db_session.add(source)
	db_session.flush()

	if action == 'create':
		db_session.execute("""INSERT INTO user_source (user_id, source_id) VALUES (:user_id, :source_id)""",
				{ 'source_id': source.id, 'user_id': user.id })

	else:
		remove_orphaned_monitoring_programs()

	db_session.commit()

	return jsonify(source_to_json(source)), 200 if source_id else 201
Exemple #15
0
def create_source_custodian(source_id=None):
	user = get_user()

	if not permitted(user, 'manage_custodians', 'source', source_id):
		return "Not authorized", 401

	body = request.json

	email = body["email"]

	if not re.match(email_regex, email):
		return jsonify({ 'error' : '"%s" is not a valid email address' % email }), 400

	custodian = db_session.query(User).filter(User.email == email).one_or_none()

	if not custodian:
		if auto_create_custodians:
			custodian = User(email=email)
			db_session.add(custodian)
			db_session.flush()
		else:
			error_message = 'No user found with the email address "%s". (Note: custodians must first create an account before they can be added)' % email
			return jsonify({ 'error': error_message }), 400

	rows = db_session.execute("""SELECT 1
		FROM user_source
		WHERE user_id = :user_id
		AND source_id = :source_id
	""", { 'source_id': source_id, 'user_id': custodian.id })

	if len(list(rows)) == 0:
		db_session.execute("""INSERT INTO user_source (user_id, source_id) VALUES (:user_id, :source_id)""",
			{ 'source_id': source_id, 'user_id': custodian.id })
		db_session.commit()

	return "OK", 201
Exemple #16
0
def reset_password():
	body = request.json

	if 'code' in body:
		# User already has a code - actually reset the password
		fields = [
			Field(name='password', title='Password', validators=[validate_required, validate_min_chars(8)])
		]

		errors = validate_fields(fields, body)

		if len(errors):
			return jsonify(errors), 400

		code = body['code'].strip()
		user = db_session.query(User).filter(User.password_reset_code == code).one_or_none()

		if user == None:
			return jsonify({ 'invalid_code': True }), 400
		else:
			user.password_hash = pwd_context.hash(body['password'])
			user.password_reset_code = None
			db_session.commit()
			return "OK", 200

	else:
		# User doesn't have a code - need to send user a reset link
		fields = [
			Field(name='email', title='Email address', validators=[validate_required, validate_email])
		]

		errors = validate_fields(fields, body)

		if len(errors):
			return jsonify(errors), 400

		email = body['email'].strip()

		user = db_session.query(User).filter(User.email == email).one_or_none()

		if user.password_hash == None:
			user = None

		if user == None:
			root_url = config.get("api", "root_url")
			email_body = reset_email_no_account_body.substitute(email=email, root_url=root_url)
		else:
			# Update reset code in database
			user.password_reset_code = secrets.token_urlsafe(16)
			db_session.commit()

			# Send reset email
			root_url = config.get("api", "root_url")
			reset_url = "%s#/reset_password?code=%s" % (root_url, user.password_reset_code)
			email_body = reset_email_body.substitute(name=user.first_name, reset_url=reset_url, root_url=root_url)

		try:
			send_email(email, 'TSX Password Reset Request', email_body)
			return "OK", 200
		except:
			return jsonify('There was a problem sending the password reset email. Please try again later.'), 500
Exemple #17
0
def load_import(import_id):
	try:
		return db_session.query(DataImport).get(int(import_id))
	except:
		return None