Ejemplo n.º 1
0
def register_user(user_data, session):
    """

    :param user_data:
        Example
        user_data={
            'username': '******',
            'email': '*****@*****.**',
            'password': '******',
            'project_string_id': 'myproject'

        }
    :return:
    """
    # User registration
    password_hash = hashing_functions.make_password_hash(
        user_data['email'],
        user_data['password'])

    # TODO could insert logic here to attach a user to a project based on say the sigup code
    # ie signup_code.something?

    username = user_data['username']
    user_email = user_data['email']

    new_user = User(
        email = user_email,
        password_hash = password_hash,
        username = username,
        api_enabled_builder = True,
        api_enabled_trainer = True,
        security_email_verified = True,
        last_builder_or_trainer_mode = 'builder',
        permissions_general = {'general': ['normal_user']}

    )

    new_user.permissions_projects = {}  # I don't like having this here but alternative of committing object seems worse
    session.add(new_user)

    if 'project_string_id' in user_data:
        new_user.current_project_string_id = user_data['project_string_id']
        project = Project.get(session, user_data['project_string_id'])
        if project is not None:
            new_user.projects.append(project)
            new_user_working_dir = WorkingDir.new_user_working_dir(
                session,
                None,
                project,
                new_user
            )

            permission_result, permission_error = Project_permissions.add(user_data['project_string_id'],
                                                                          new_user,
                                                                          user_data['project_string_id'])
    return new_user
Ejemplo n.º 2
0
def task_trainer_request_api(job_id):
	"""

	"""
	log = regular_input.regular_log.default_api_log()

	with sessionMaker.session_scope() as session:

		# Job id will have already been checked in permissions
		job = Job.get_by_id(session, job_id)

		### MAIN
		user = User.get(session)
		member = user.member
		
		result, task = task_trainer_request( session = session,
											 user = user,
											 job = job)
		####

		if result is True:
			task_serialized = task.serialize_trainer_annotate(session)

			log['success'] = True
			return jsonify( log = log,
						   task = task_serialized), 200

		# TODO front end handling on this
		log['error']['task_request'] = "No tasks available."
		return jsonify( log = log), 200
Ejemplo n.º 3
0
def add_event_data_to_input(input, session, connector_id):
    user = User.get_current_user(session)
    input['opts']['event_data'] = {
        'request_user': user.id,
        'date_time': datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S'),
        'connection_id': connector_id
    }
    return input
Ejemplo n.º 4
0
def user_view():
    with sessionMaker.session_scope() as s:

        user = User.get(s)
        if user is None:
            return jsonify({"none_found": True}), 400, {
                'ContentType': 'application/json'
            }

        out = jsonify(user=user.serialize())
        return out, 200, {'ContentType': 'application/json'}
Ejemplo n.º 5
0
def verify_otp_from_web():

    with sessionMaker.session_scope() as session:

        data = request.get_json(force=True)

        proposed_otp_code = data.get('otp', None)
        otp_current_session = data.get('otp_current_session', None)
        email = data.get('email', None)

        user = User.get_by_email(session, email)
        if user is None:
            return jsonify(error="No user"), 200, {
                'ContentType': 'application/json'
            }

        if user.otp_current_session_expiry <= time.time():
            User.new_login_history(session=session,
                                   success=False,
                                   otp_success=False,
                                   remote_address=request.remote_addr,
                                   user_id=user.id)
            return jsonify(error="Please login again, session expired"), 200, {
                'ContentType': 'application/json'
            }

        if user.otp_current_session != otp_current_session:
            User.new_login_history(session=session,
                                   success=False,
                                   otp_success=False,
                                   remote_address=request.remote_addr,
                                   user_id=user.id)
            return jsonify(error="Please login again, session invalid"), 200, {
                'ContentType': 'application/json'
            }

        if OneTimePass.verify_otp(user, proposed_otp_code) is True:

            User.new_login_history(session=session,
                                   success=True,
                                   otp_success=True,
                                   remote_address=request.remote_addr,
                                   user_id=user.id)

            setSecureCookie(user)

            return jsonify(user=user.serialize(), success=True), 200, {
                'ContentType': 'application/json'
            }

        return jsonify(error="Invalid code"), 200, {
            'ContentType': 'application/json'
        }
Ejemplo n.º 6
0
def user_exists(email):
    if settings.DIFFGRAM_SYSTEM_MODE not in [
            'testing_e2e', 'testing', 'sandbox'
    ]:
        return jsonify(message='Invalid System Mode'), 400

    with sessionMaker.session_scope() as session:
        user = User.get_by_email(session, email)
        if user is None:
            return jsonify({"none_found": True}), 400, {
                'ContentType': 'application/json'
            }

        out = jsonify(found=True)

        return out, 200, {'ContentType': 'application/json'}
Ejemplo n.º 7
0
def disable_otp_from_web():

    with sessionMaker.session_scope() as session:

        user = User.get(session)

        if not user:
            return "no user", 400, {'ContentType': 'application/json'}

        session.add(user)

        user.otp_enabled = False

        out = jsonify(success=True, user=user.serialize())

        return out, 200, {'ContentType': 'application/json'}
Ejemplo n.º 8
0
def enable_otp_from_web():

    with sessionMaker.session_scope() as session:

        user = User.get(session)

        if not user:
            return "no user", 400, {'ContentType': 'application/json'}

        otp, qr_code_url, backup_code_list = OneTimePass.new(session, user)

        out = jsonify(success=True,
                      otp=otp,
                      qr_code_url=qr_code_url,
                      backup_code_list=backup_code_list,
                      user=user.serialize())

        return out, 200, {'ContentType': 'application/json'}
Ejemplo n.º 9
0
def get_member(session):
    """
	An issue of this being part of auth is that we may want the actual 
	member object available in the session,
	and at least our current process is to close / not pass the 
	session used in auth. That perhaps is a good area to change
	but either way core logic here is similar.
	"""
    member = None

    # Potential to be outside of request context
    if not request:
        return member

    user = User.get(session)
    if user:
        member = user.member
    else:
        client_id = request.authorization.get('username', None)
        auth = Auth_api.get(session, client_id)
        member = auth.member

    return member
Ejemplo n.º 10
0
def job_info_builder_api(job_id):
    """

	"""

    spec_list = [
        {
            'mode_data': None
        },  # Default of None is ok, if data, then type str
        {
            'refresh_stats': {
                'default': True,
                'kind': bool,
                'required': False
            }
        }
    ]

    log, input, untrusted_input = regular_input.master(request=request,
                                                       spec_list=spec_list)

    if len(log["error"].keys()) >= 1:
        return jsonify(log=log), 400

    with sessionMaker.session_scope() as session:

        job = Job.get_by_id(session, job_id)

        user = User.get(session=session)

        job_serialized = job_info_builder_core(session=session,
                                               job=job,
                                               user=user,
                                               input=input)

        log['success'] = True
        return jsonify(log=log, job=job_serialized), 200
Ejemplo n.º 11
0
def job_view_core(session,
                  metadata_proposed,
                  output_mode="serialize",
                  user=None):
    """
		output_mode
			serialize is in context of web, ie serialize the resulting list
				currently defaults to this context
			objects returns the database objects, ie for auto commit

		"""

    # CAUTION some of these settings get overriden / effected by
    # default_metadata below!!!
    meta = default_metadata(metadata_proposed)

    start_time = time.time()
    output_file_list = []
    limit_counter = 0

    # CAUTION
    # Multiple "modes", for output and trainer builder, maybe more in future
    builder_or_trainer_mode = meta['builder_or_trainer']['mode']

    # It doesn't really make sense to have this here
    # Should be part of some other meta data checking or something.
    if builder_or_trainer_mode not in ["builder", "trainer"]:
        raise Forbidden("Invalid builder_or_trainer_mode mode.")

    query = session.query(Job)

    # TODO may want to make this a flag, ie in case
    # super admin wants to see it.
    query = query.filter(Job.hidden == False)

    # Caution there's "Status" check query things buried at the bottom
    # here

    # May also want to view jobs by multiple users!!!

    user = User.get(session)

    if user.last_builder_or_trainer_mode != builder_or_trainer_mode:
        raise Forbidden(
            "Invalid user relation to builder_or_trainer_mode mode.")

    ### START FILTERS ###

    job_type = None
    if meta["type"]:
        if meta["type"] != "All":
            job_type = meta["type"]

    if builder_or_trainer_mode == "trainer":
        pass

    if job_type:
        query = query.filter(Job.type == job_type)
    if meta.get('members'):
        members = session.query(Member).filter(
            Member.id.in_(meta.get('members')))
        user_ids = [m.user_id for m in members]
        rels = session.query(User_To_Job).filter(
            User_To_Job.user_id.in_(user_ids))
        job_ids = [rel.job_id for rel in rels]
        query = query.filter(Job.id.in_(job_ids))

    if meta["my_jobs_only"]:

        if builder_or_trainer_mode == "builder":
            query = query.filter(Job.member_created == user.member)

        if builder_or_trainer_mode == "trainer":
            attached_query = session.query(User_To_Job).filter(
                User_To_Job.user_id == user.id).subquery('sub_query')

            query = query.filter(Job.id == attached_query.c.job_id)
        """
			# Prior combo method for both builder and trainer
			query = query.filter(or_(Job.member_created == user.member,
									Job.id == attached_query.c.job_id))
			"""

    else:

        # Trainers should be able to see their instance of an exam
        # And the templates of other exams?

        # TODO not clear how this should effect builders

        if builder_or_trainer_mode == "trainer" and job_type == "Exam":
            query = query.filter(Job.is_template == True)

    # Disable field, till fully supported.
    """
		if meta["field"]:
			if meta["field"] != "All":

				field = Field.get_by_name(session = session,
										  name = meta["field"])

				if field:
					query = query.filter(Job.field == field)
		"""
    # TODO could we combine these methods seems like repetition

    if meta["instance_type"]:
        if meta["instance_type"] != "All":

            query = query.filter(Job.instance_type == meta["instance_type"])

    if meta["job_ids"]:
        query = query.filter(Job.id.in_(meta["job_ids"]))

    if builder_or_trainer_mode == "builder":

        # Permissions in wrapper on this function
        # Note: the function filter_by_project() is taking almost 1s (most of this thanks to permissions)
        if meta["share_type"] == "project":
            query = filter_by_project(
                session=session,
                project_string_id=meta["project_string_id"],
                query=query)

        # Status can be seperate from project...
        if meta["status"]:
            if meta["status"] != "All":
                if not isinstance(meta["status"], list):
                    meta["status"] = [meta["status"]]
                query = query.filter(Job.status.in_(meta["status"]))

        # Also assumes org is None.
        # Actually this should be complimentary still
        if meta["share_type"] == "Market":
            query = query.filter(Job.status.in_(("active", "complete")))

    if builder_or_trainer_mode == "trainer":

        query = query.filter(Job.status.in_(("active", "complete")))

        # The by API thing is not yet supported and this is confusing things
        # For user level search
        #if meta["org"] == "None":
        # Restrict trainers to market only jobs. (if no org is present)
        # A user that wants to share the job with project should be a builder...

        # TODO review this, confusing / if shared with org...
        # One part of the issue is need better checking on what's an allowed shared type...

        # CAUTION market is caps senstive
        #	query = query.filter(Job.share_type == "market")

    # If mode is trainer then force to use org id

    if meta["search"] is not None:
        search_text = '%{}%'.format(meta['search'])
        query = query.filter(Job.name.ilike(search_text))

    query = query.order_by(Job.time_created.desc())

    #### END FILTERS ###

    query = query.limit(meta["limit"])
    query = query.offset(meta["start_index"])

    # Avoid multiple queries on serializer by fetching joined data
    query = query.options(joinedload(Job.completion_directory))

    job_list = query.all()

    if output_mode == "serialize":

        for job in job_list:

            # optional place can re run this
            # more for edge cases
            #job.update_file_count_statistic(session)

            if meta["data_mode"] == "name_and_id_only":
                serialized = job.serialize_minimal_info()
            else:
                serialized = job.serialize_for_list_view(session=session)

            output_file_list.append(serialized)
            limit_counter += 1

    timer = time.time()

    meta['end_index'] = meta['start_index'] + len(job_list)
    meta['length_current_page'] = len(output_file_list)

    if limit_counter == 0:
        meta['no_results_match_meta'] = True

    end_time = time.time()
    print("Job meta time", end_time - start_time)

    return output_file_list, meta
Ejemplo n.º 12
0
def job_launch_list_core(session, metadata_proposed, output_mode="serialize"):
    """
        Get the job_launch objects based on filters in
        metadata_proposed.

    """

    meta = default_metadata(metadata_proposed)
    output_job_launch_list = []
    limit_counter = 0

    # CAUTION
    # Multiple "modes", for output and trainer builder, maybe more in future
    builder_or_trainer_mode = meta['builder_or_trainer']['mode']

    # It doesn't really make sense to have this here
    # Should be part of some other meta data checking or something.
    if builder_or_trainer_mode not in ["builder", "trainer"]:
        raise Forbidden("Invalid builder_or_trainer_mode mode.")

    query = session.query(JobLaunch).join(Job)

    user = User.get(session)

    if user.last_builder_or_trainer_mode != builder_or_trainer_mode:
        raise Forbidden(
            "Invalid user relation to builder_or_trainer_mode mode.")

    ### START FILTERS ###

    if meta["status"]:
        if meta["status"] != "All":
            query = query.filter(JobLaunch.status == meta["status"])
    if meta["date_from"]:
        date_from = datetime.datetime.strptime(meta["date_from"], "%Y-%m-%d")
        date_from = date_from.replace(hour=0,
                                      minute=0,
                                      second=0,
                                      microsecond=0)
        query = query.filter(JobLaunch.time_created >= date_from)
    if meta["date_to"]:
        date_to = datetime.datetime.strptime(meta["date_to"], "%Y-%m-%d")
        date_to = date_to.replace(hour=0, minute=0, second=0, microsecond=0)

        query = query.filter(JobLaunch.time_created <= date_to)

    if meta["job_ids"]:
        query = query.filter(Job.id.in_(meta["job_ids"]))

    # Also assumes org is None.
    # Actually this should be complimentary still
    if meta["project_string_id"]:
        project = Project.get_by_string_id(
            session=session, project_string_id=meta["project_string_id"])
        query = query.filter(Job.project_id == project.id)
    #### END FILTERS ###

    query = query.order_by(Job.time_created.desc())
    query = query.limit(meta["limit"])
    query = query.offset(meta["start_index"])

    job_launch_list = query.all()

    if output_mode == "serialize":

        for job_launch in job_launch_list:
            serialized = job_launch.serialize_for_list_view(session=session)

            output_job_launch_list.append(serialized)
            limit_counter += 1

    meta['end_index'] = meta['start_index'] + len(output_job_launch_list)
    meta['length_current_page'] = len(output_job_launch_list)

    if limit_counter == 0:
        meta['no_results_match_meta'] = True

    return output_job_launch_list, meta
Ejemplo n.º 13
0
    def update_member_list(self,
                           member_list_ids: list,
                           session,
                           log: dict,
                           add_to_session: bool = True):

        # TODO feel like this could be a more generic pattern
        # main id is given a list of ids handle updating the attachments
        # TODO abstract more functions here...

        # TODO optimize by caching
        # / checking existing_member_list_ids

        # An empty list is OK because that indicates clearing all
        if member_list_ids is None:
            log['info']['member_list_ids'] = 'Provide member lists IDs'
            return log

        log['info']['update_user_list'] = {}
        log['info']['update_member_list'] = {}

        user_list = []
        user_added_id_list = []

        if 'all' in member_list_ids:
            user_list = self.project.users

        else:
            for member_id in member_list_ids:

                user = User.get_by_member_id(session=session,
                                             member_id=member_id)

                if not user:
                    log['error']['update_member_list'] = {}
                    log['error']['update_member_list'][
                        member_id] = "Invalid member_id " + str(member_id)
                    return log

        for user in user_list:

            user_added_id_list.append(user.id)

            existing_user_to_job = User_To_Job.get_single_by_ids(
                session=session, user_id=user.id, job_id=self.id)

            if existing_user_to_job:
                # Add user back into job
                if existing_user_to_job.status == 'removed':
                    existing_user_to_job.status = 'active'
                    log['info']['update_member_list'][user.member_id] = "Added"
                    if add_to_session is True:
                        session.add(existing_user_to_job)
                else:
                    log['info']['update_member_list'][
                        user.member_id] = "Unchanged."
                continue

            user_to_job = self.attach_user_to_job(
                session=session, user=user, add_to_session=add_to_session)

            log['info']['update_member_list'][user.member_id] = "Added"

        remaining_user_to_job_list = User_To_Job.list(
            session=session, user_id_ignore_list=user_added_id_list
        )  # careful, user_id not member_id

        for user_to_job in remaining_user_to_job_list:
            if user_to_job.status != 'removed':
                user_to_job.status = 'removed'
                if add_to_session is True: session.add(user_to_job)
                # TODO this should be uniform, it's not right now
                # this is update_user_list but we need to add member_id to user_to_job
                # it sounds like this needed to be member_list for current tests so just leaving it for now.
                log['info']['update_member_list'][
                    user_to_job.user_id] = "Removed"

        self.set_cache_by_key(cache_key='member_list_ids',
                              value=member_list_ids)
        if add_to_session is True: session.add(self)

        return log