def update_import(import_id=None): body = request.json data_import = load_import(import_id) if not data_import: return "Not found", 404 new_status = body['status'] old_status = status_codes[data_import.status_id] # Make sure this is a valid state transition if (old_status, new_status) not in (('checked_ok', 'checking'), ('checked_ok', 'importing'), ('checked_error', 'checking'), ('import_error', 'checking')): return "Invalid status change %s -> %s" % (old_status, new_status), 400 if new_status == 'importing' and data_import.upload_uuid != body['upload_uuid']: return "Attempting to import unchecked upload", 400 data_import.upload_uuid = body['upload_uuid'] data_import.filename = get_upload_name(body['upload_uuid']) data_import.data_type = body.get('data_type', 1) db_session.commit() process_import_async(import_id, new_status) return jsonify(data_import_json(data_import))
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
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
def update_import_statuses_after_restart(): db_session.execute("""UPDATE data_import SET status_id = (SELECT id FROM data_import_status WHERE code = 'checked_error') WHERE status_id = (SELECT id FROM data_import_status WHERE code = 'checking')""") db_session.execute("""UPDATE data_import SET status_id = (SELECT id FROM data_import_status WHERE code = 'import_error') WHERE status_id = (SELECT id FROM data_import_status WHERE code = 'importing')""") db_session.commit()
def delete_source_custodian(source_id=None, user_id=None): user = get_user() if not permitted(user, 'manage_custodians', 'source', source_id): return "Not authorized", 401 db_session.execute("""DELETE FROM user_source WHERE user_id = :user_id AND source_id = :source_id""", { 'source_id': source_id, 'user_id': user_id }) db_session.commit() return "OK", 200
def delete_source(source_id=None): user = get_user() if not permitted(user, 'delete', 'source', source_id): return "Not authorized", 401 db_session.execute("""DELETE FROM user_source WHERE source_id = :source_id""", { 'source_id': source_id }) db_session.execute("""DELETE FROM data_import WHERE source_id = :source_id""", { 'source_id': source_id }) db_session.execute("""DELETE FROM source WHERE id = :source_id""", { 'source_id': source_id }) remove_orphaned_monitoring_programs() db_session.commit() return "OK", 200
def remove_manager_from_monitoring_program(program_id = None, user_id = None): if program_id == None or user_id == None: return "Not found", 404 user = get_user() if not permitted(user, 'mangage_managers', 'program', program_id): return "Not authorized", 401 db_session.execute("""DELETE FROM user_program_manager WHERE user_id = :user_id AND monitoring_program_id = :program_id""", { 'program_id': program_id, 'user_id': user_id }) db_session.commit() return "OK", 200
def delete_monitoring_program(program_id = None): if program_id == None: return "Not found", 404 user = get_user() if not permitted(user, 'delete', 'program', program_id): return "Not authorized", 401 db_session.execute("""DELETE FROM monitoring_program WHERE id = :program_id""", { 'program_id': program_id }) db_session.commit() return "OK", 200
def remove_source_from_monitoring_program(program_id = None, source_id = None): if program_id == None or source_id == None: return "Not found", 404 user = get_user() if not permitted(user, 'update', 'source', program_id): return "Not authorized", 401 db_session.execute("""UPDATE source SET monitoring_program_id = NULL WHERE id = :source_id AND monitoring_program_id = :program_id""", { 'program_id': program_id, 'source_id': source_id }) db_session.commit() return "OK", 200
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
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
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
def post_import(): user = get_user() body = request.json try: source_id = body['source_id'] except KeyError: return jsonify('source_id is required'), 400 if not permitted(user, 'update', 'source', source_id): return 'Not authorized', 401 # Check upload parameter if 'upload_uuid' not in body: return jsonify("upload_uuid is required"), 400 upload_uuid = body['upload_uuid'] file_path = get_upload_path(upload_uuid) if not os.path.exists(file_path): return jsonify("invalid upload_uuid"), 400 # Create new working directory for the import data_import = DataImport( source_id = source_id, status_id = 1, upload_uuid = body['upload_uuid'], filename = get_upload_name(upload_uuid), data_type = body.get('data_type'), user_id = user.id ) db_session.add(data_import) db_session.commit() import_id = data_import.id # working_path = os.path.join(imports_path, "%04d" % import_id) # working_path, import_id = next_path(os.path.join(imports_path, "%04d")) # os.makedirs(working_path) process_import_async(import_id, 'checking') # TODO - Ideally should return 201 Created and URL of new resource return jsonify(data_import_json(load_import(import_id)))
def create_source_processing_notes(source_id=None): user = get_user() if not permitted(user, 'update', 'source', source_id): return "Not authorized", 401 body = request.json # TODO: validate json notes = DataProcessingNotes() notes.notes = body['notes'] notes.user_id = user.id notes.source_id = source_id db_session.add(notes) db_session.commit() return "OK", 201
def result_callback(result): is_admin = running_imports[import_id]['is_admin'] with lock: del running_imports[import_id] success = result['errors'] == 0 if status == 'checking': new_status = 'checked_ok' if success else 'checked_error' elif status == 'importing': new_status = ('approved' if is_admin else 'imported') if success else 'import_error' info = load_import(import_id) info.status_id = status_ids[new_status] info.error_count = result['errors'] info.warning_count = result['warnings'] db_session.commit()
def update_user_role(user_id): user = get_user() if 'Administrator' not in get_roles(user): return "Forbidden", 403 body = request.json try: new_role = body['role'] except KeyError: return "Missing role", 400 db_session.execute("DELETE FROM user_role WHERE user_id = :user_id", { 'user_id': user_id }) print(new_role) print(user_id) db_session.execute("INSERT INTO user_role (user_id, role_id) SELECT :user_id, (SELECT id FROM role WHERE description = :role)", { 'user_id': user_id, 'role': new_role }) db_session.commit() return "OK", 200
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
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
def approve_import(import_id=None): data_import = load_import(import_id) if not data_import: return "Not found", 404 old_status = status_codes[data_import.status_id] if old_status != 'imported': return "Cannot approve import with status '%s'" % old_status, 400 user = get_user() if not permitted(user, 'approve', 'import', import_id): return 'Not authorized', 401 db_session.execute("UPDATE data_import SET status_id = :status_id WHERE id = :import_id", { 'status_id': status_ids['approved'], 'import_id': import_id }) db_session.commit() data_import.status_id = status_ids['approved'] return jsonify(data_import_json(data_import))
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
def update_programs(user_id=None): user = get_user() if not permitted(user, 'update_programs', 'user', user_id): return "Not authorized", 401 if user_id == None: return "Not found", 404 body = request.json db_session.execute( """DELETE FROM user_program_manager WHERE user_id = :user_id""", {"user_id": user_id}) for program_id in body: db_session.execute( """INSERT INTO user_program_manager (user_id, monitoring_program_id) VALUES (:user_id, :program_id)""", { "user_id": user_id, "program_id": program_id }) db_session.commit() return "OK", 201
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