Unverified Commit cf43b7da authored by Peter Stanko's avatar Peter Stanko
Browse files

Facades - WIP

parent c4040a3a
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -12,7 +12,9 @@ from management.data.data_prod import init_prod_data
from management.data.data_test import init_test_data
from portal import logger
from portal.database.models import Course, Role, Secret, Submission, SubmissionState, User
from portal.service.find import FindService
from portal.service.rest import RestService
from portal.service.users import UserService
from portal.tools import time

log = logger.get_logger(__name__)
@@ -30,6 +32,10 @@ class DataManagement(object):
        self.creator = shared.DataFactory(self.db)
        self.rest = RestService()

    @property
    def find(self):
        return FindService()

    def reset_db(self):
        """Resets the database
        """
@@ -51,8 +57,8 @@ class DataManagement(object):
            name(str): name of the user
        """
        with self.app.app_context():
            user = self.rest.find.user(name)
            self.rest.users(user).delete()
            user = self.find.user(name)
            UserService()(user).delete()

    def delete_course(self, name: str):
        """Deletes course
+18 −23
Original line number Diff line number Diff line
@@ -3,22 +3,24 @@ from storage import UploadedEntity

from portal import storage
from portal.async_celery import celery_app, submission_processor
from portal.service.find import FindService
from portal.service.general import GeneralService
from portal.service.submissions import SubmissionsService

log = get_task_logger(__name__)


@celery_app.task(name='upload-submission-to-storage')
def process_submission(new_submission_id: str):
    from portal.service.rest import RestService
    rest_service = RestService()
    new_submission = rest_service.find.submission(new_submission_id)
    find_service = FindService()
    new_submission = find_service.submission(new_submission_id)
    project = new_submission.project
    course = project.course
    log.info(f"[SUBMIT] Processing submission: {new_submission.log_name}")
    if not project.config.test_files_commit_hash:
        log.warning(f"Project test files not found: {project.log_name}")
        update_project_test_files(course_id=course.id, project_id=project.id)
    new_submission = rest_service.find.submission(new_submission_id)
    new_submission = find_service.submission(new_submission_id)
    processor = submission_processor.SubmissionProcessor(new_submission)
    processor.process_submission()

@@ -26,24 +28,21 @@ def process_submission(new_submission_id: str):
@celery_app.task(name='upload-results-to-storage')
def upload_results_to_storage(new_submission_id: str, path: str):
    path = str(path)
    from portal.service.rest import RestService
    rest_service = RestService()
    new_submission = rest_service.find.submission(new_submission_id)
    find_service = FindService()
    new_submission = find_service.submission(new_submission_id)
    log.info(f"[SUBMIT] Processing results - upload to the storage for "
             f"{new_submission.log_name}: {path}")
    processor = submission_processor.SubmissionProcessor(new_submission)
    file_params = dict(source=dict(url=path, type='zip'))
    processor.upload_result(path=path, file_params=file_params)
    submission = processor.process_result()
    rest_service.submissions.write_entity(submission)
    SubmissionsService().write_entity(submission)


@celery_app.task(name='clone-submission-files')
def clone_submission_files(source_id: str, target_id: str):
    from portal.service.rest import RestService
    rest_service = RestService()
    source = rest_service.find.submission(source_id)
    target = rest_service.find.submission(target_id)
    source = FindService().submission(source_id)
    target = FindService().submission(target_id)
    log.info(f"[SUBMIT] Copy submission files: {source.log_name} -> {target.log_name}")
    processor = submission_processor.SubmissionProcessor(source)
    processor.clone(target)
@@ -51,9 +50,7 @@ def clone_submission_files(source_id: str, target_id: str):

@celery_app.task(name='start-processing-submission')
def start_processing_submission(submission_id: str, submission_params):
    from portal.service.rest import RestService
    rest_service = RestService()
    submission = rest_service.find.submission(submission_id)
    submission = FindService().submission(submission_id)
    log.info(f"[SUBMIT] Processing submission - send to worker: {submission.log_name}")
    processor = submission_processor.SubmissionProcessor(submission, submission_params)
    processor.send_to_worker()
@@ -61,11 +58,9 @@ def start_processing_submission(submission_id: str, submission_params):

@celery_app.task(name='update-project-test-files')
def update_project_test_files(course_id: str, project_id: str):
    from portal.service.rest import RestService
    rest_service = RestService()

    course = rest_service.find.course(course_id)
    project = rest_service.find.project(course, project_id)
    find_service = FindService()
    course = find_service.course(course_id)
    project = find_service.project(course, project_id)
    log.info(f"[ASYNC] Updating test files for project: {project.log_name}")
    params = {
        'from_dir': project.config.test_files_subdir,
@@ -75,13 +70,13 @@ def update_project_test_files(course_id: str, project_id: str):
        }
    }
    try:
        _update_test_files(rest_service, project, params)
        _update_test_files(project, params)
    except Exception as ex:
        log.error(f"[ASYNC] Cannot update source files {project.log_name}: {ex}")


def _update_test_files(rest_service, project, params):
def _update_test_files(project, params):
    updated_entity: UploadedEntity = storage.test_files.update(entity_id=project.id, **params)
    project.config.test_files_commit_hash = updated_entity.version
    log.debug(f"Updated project config {project.log_name}: {project.config}")
    rest_service.projects.write_entity(project.config)
    GeneralService().write_entity(project.config)
+10 −0
Original line number Diff line number Diff line
from .courses_facade import CoursesFacade
from .groups_facade import GroupsFacade
from .roles_facade import RolesFacade
from .users_facade import UsersFacade
from .submissions_facade import SubmissionsFacade
from .workers_facade import WorkersFacade


class SecretsFacade(object):
    pass
+58 −0
Original line number Diff line number Diff line
import logging
from typing import List

from portal.database import Course
from portal.database.models import Client, ClientType
from portal.facade.general_facade import GeneralCRUDFacade
from portal.service.courses import CourseService

log = logging.getLogger(__name__)


class CoursesFacade(GeneralCRUDFacade):
    def __init__(self):
        super().__init__(CourseService, entity_name='Course')

    def copy_course(self, source: Course, target: Course, **config) -> Course:
        """Copies course and it's other resources (roles, groups, projects)
        The other resources that should be copied are specified in the config

        Args:
            source(Course): Source course which resources will be copied
            target(Course): Target course
            config(dict): Configuration to specify which resource should be copied

        Returns(Course): Copied course instance (target)
        """
        log.info(f"[IMPORT] From {source.log_name} "
                 f"to {target.log_name} by {self.client_name}.")

        result = self._service(source).copy_course(target, config)
        return result

    def update_notes_token(self, course: Course, token: str) -> Course:
        """Updates notes access token of a course.

        Args:
            course(Course): Course instance
            token(str): The new token

        Returns(Course): Course instance
        """
        log.info(f"[UPDATE] Notes access token {course.log_name} "
                 f"by {self.client_name}")
        result = self._service(course).update_notes_token(token)
        return result

    def get_clients_filtered(self, course: Course, groups: List[str],
                             roles: List[str], client_type: ClientType = None) -> List[Client]:
        """Get all users for course filtered
        Args:
            course(Course): Course instance
            groups(list): Group names list
            roles(list):  Role names list
            client_type(ClientType): Client type
        Returns(List[User]):
        """
        clients = self._service(course).get_clients_filtered(groups, roles, client_type)
        return clients
+110 −0
Original line number Diff line number Diff line
import logging
from typing import List

import flask

from portal.database import models
from portal.service import errors
from portal.service.auth import AuthService
from portal.service.find import FindService
from portal.service.general import GeneralService
from portal.service.permissions import PermissionsService

log = logging.getLogger(__name__)


class GeneralFacade:
    def __init__(self, main_service=None, entity_name: str = None):
        """Creates new instance of the general facade and sets the variables
        Args:
            main_service: Main service that is used for managing the resources
            entity_name: Entity name - for logging purposes
        """
        service_klass = main_service or GeneralService
        self._service = service_klass
        self._permissions = PermissionsService()
        self._auth = AuthService()
        self._find = FindService()
        self._entity_name = entity_name

    @property
    def client(self) -> models.Client:
        return self.auth.find_client(throw=False)

    @property
    def client_name(self):
        if self.client:
            return self.client.log_name
        return 'Unknown client'

    @property
    def _request(self) -> flask.Request:
        return flask.request

    @property
    def flask_app(self) -> flask.Flask:
        return flask.current_app

    @property
    def permissions(self):
        return self._permissions

    @property
    def auth(self) -> AuthService:
        return self._auth

    @property
    def find(self) -> FindService:
        return self._find

    def _require_params(self, dictionary, *params):
        for param in params:
            if not dictionary.get(param):
                raise errors.PortalAPIError(400, f'missing param: "{param}" is required')


class GeneralCRUDFacade(GeneralFacade):
    def find_all(self, *args, **kwargs) -> List:
        """Gets a collection of all the entities
        Args:
            *args:
            **kwargs:

        Returns(List): List of entities
        """
        log.debug(f"[GET] Find all ({self.__class__.__name__}): {args} {kwargs}")
        return self._service.find_all(*args, **kwargs)

    def create(self, **data):
        """Creates new instance of the entity

        Returns(User): Created user instance
        """
        log.info(f"[CREATE] New {self._entity_name} by {self.client_name}: {data}")
        new_entity = self._service.create(**data)
        return new_entity

    def delete(self, entity):
        """General delete method called on facade - calls the service delete method
        Args:
            entity: General entity instance (ex. User)

        """
        log.info(f"[DELETE] {entity.__class__.__name__} "
                 f"{entity.log_name} by {self.client_name}")

        self._service(entity).delete()

    def update(self, entity, **data):
        """Updates Entity

        Args:
            entity: Entity instance
            data(dict): Dictionary containing data which should be changed

        Returns: Updated instance instance
        """
        log.info(f"[UPDATE] {entity.__class__.__name__} {entity.log_name} "
                 f"by {self.client_name}: {entity}.")
        updated = self._service(entity).update(**data)
        return updated
Loading