def validate_meeting_general(meeting: Dict) -> ResultWithData[MeetingJsonData]:
    date_res = validate_date(meeting, "date")
    if date_res.is_error:
        return get_result_with_error(date_res.message)
    date = date_res.data

    last_upload_res = validate_date(meeting, "last_upload_date")
    if last_upload_res.is_error:
        return get_result_with_error(last_upload_res.message)
    last_upload = last_upload_res.data

    lp_res = validate_int(meeting, "lp")
    if lp_res.is_error:
        return get_result_with_error(lp_res.message)
    lp = lp_res.data

    meeting_no_res = validate_int(meeting, "meeting_no")
    if meeting_no_res.is_error:
        return get_result_with_error(meeting_no_res.message)
    meeting_no = meeting_no_res.data

    if not 0 < lp <= 4:
        return get_result_with_error("Invalid lp {0}".format(lp))

    if not 0 <= meeting_no:
        return get_result_with_error(
            "Invalid meeting number {0}".format(meeting_no))

    return get_result_with_data(
        MeetingJsonData(id=None,
                        date=date,
                        last_upload=last_upload,
                        lp=lp,
                        meeting_no=meeting_no,
                        groups_tasks=[]))
Exemple #2
0
def validate_configs(data: Dict) -> ResultWithData[List[ConfigData]]:
    configs = []

    if "config" not in data:
        return get_result_with_error("Missing config array")

    config = data["config"]

    for entry in config:
        if "key" not in entry or "value" not in entry:
            return get_result_with_error("Missing key or value")
        key = entry["key"]
        value = entry["value"]
        db_config = get_config(key)
        if db_config is None:
            return get_result_with_error("Config {0} not found".format(key))

        if db_config.config_type == "number":
            if not value.isdigit():
                return get_result_with_error(
                    "Config {0} must be a number, got {1}".format(key, value))

        configs.append(ConfigData(key=key, value=value))

    return get_result_with_data(configs)
def update_groups_tasks(
        meeting_id: uuid,
        groups_tasks: List[GroupTaskData]) -> ResultWithData[str]:
    # Remove group_tasks
    existing_group_tasks = get_tasks_for_meeting(meeting_id)
    for existing_group_task in existing_group_tasks:
        found = False
        for group_task in groups_tasks:
            if group_task.is_same(existing_group_task):
                found = True
                break

        if not found:
            # Remove the group_task
            res = remove_group_meeting_task(meeting_id,
                                            existing_group_task.group_name,
                                            "active",
                                            existing_group_task.task_type)
            if res.is_error:
                return get_result_with_error(res.message)

    # Add new group_tasks
    for group_task in groups_tasks:
        create_group_meeting(meeting_id, group_task.group_name, "active")
        create_group_meeting_task(meeting_id, group_task.group_name, "active",
                                  group_task.task_type)

    return get_result_with_data("")
Exemple #4
0
def validate_stories(
        config: Dict[str, object]) -> ResultWithData[List[StoryData]]:
    story_groups_res = validate_list(config, "storyGroups")
    if story_groups_res.is_error:
        return get_result_with_error(story_groups_res.message)
    story_groups = story_groups_res.data

    story_groups_list = []

    for sg in story_groups:
        group_res = validate_str(sg, "group")
        if group_res.is_error:
            return get_result_with_error(group_res.message)
        group = group_res.data

        year_res = validate_int(sg, "year")
        if year_res.is_error:
            return get_result_with_error(year_res.message)
        year = year_res.data

        finished_res = validate_bool(sg, "finished")
        if finished_res.is_error:
            return get_result_with_error(finished_res.message)
        finished = finished_res.data

        story_groups_list.append(StoryData(group, str(year), finished))

    return get_result_with_data(story_groups_list)
def create_archive(id: UUID) -> ResultWithData[UUID]:
    folder_location = "src/b"

    meeting = get_meeting_data_by_id(id)

    if os.path.exists(folder_location):
        # Delete any old files.
        shutil.rmtree(folder_location)

    os.makedirs(folder_location)
    file_paths = get_file_paths(id)

    for path in file_paths:
        shutil.copy(path, folder_location)

    archives_location = "archives"
    folder_name = f"src/{archives_location}"
    if not os.path.exists(folder_name):
        os.makedirs(folder_name)

    archive_name = f"{archives_location}/documents_lp{meeting.lp}_{meeting.meeting_no}_{meeting.year}"
    print(f"Archiving folder: {folder_location}\nTo file: {archive_name}")
    shutil.make_archive(f"src/{archive_name}", "zip", folder_location)

    old_archive = get_archive_data_by_meeting_id(meeting.id)
    if old_archive is None:
        # Create a new archive.
        new_archive = create_archive_code(meeting.id, archive_name)
    else:
        # Update the archive for this meeting with the new zip file.
        new_archive = update_archive_location(old_archive.code, archive_name)

    if new_archive is None:
        return get_result_with_error("Failed creating/updating archive")
    return get_result_with_data(new_archive.code)
Exemple #6
0
def validate_dict(json: Dict, key: str) -> ResultWithData[Dict]:
    if key not in json:
        return get_result_with_error("Missing {0}".format(key))

    value = json[key]
    if type(value) is not dict:
        return get_result_with_error("{0} must be an object".format(key))

    return get_result_with_data(value)
Exemple #7
0
def get_meeting_json_data(code: UUID) -> ResultWithData[MeetingJsonData]:
    meeting = get_meeting_by_id(code)
    if meeting is None:
        return get_result_with_error("No meeting with code {0}".format(code))

    groups_tasks = get_tasks_for_meeting(code)
    return get_result_with_data(
        MeetingJsonData(meeting.id, meeting.date, meeting.last_upload,
                        meeting.lp, meeting.meeting_no, groups_tasks))
Exemple #8
0
def validate_bool(json: Dict, key: str) -> ResultWithData[bool]:
    if key not in json:
        return get_result_with_error("Missing {0}".format(key))

    bool_str = json[key]
    try:
        val = bool(bool_str)
        return get_result_with_data(val)
    except ValueError:
        get_result_with_error("{0} is not a valid boolean".format(bool_str))
Exemple #9
0
def get_years() -> ResultWithData[dict]:
    years = []
    curr_year = datetime.utcnow().year
    years_back_res = get_config_value_int("possible_years_back_for_stories")
    if years_back_res.is_error:
        return get_result_with_error(years_back_res.message)

    for i in range(years_back_res.data):
        years.append(curr_year - i)
    return get_result_with_data(years)
Exemple #10
0
def get_meetings(meeting_ids: List[UUID]) -> ResultWithData[List[dict]]:
    meetings = []
    for meeting_id in meeting_ids:
        meeting_data_res = get_meeting_json_data(meeting_id)
        if meeting_data_res.is_error:
            return get_result_with_error(meeting_data_res.message)

        meetings.append(meeting_data_res.data.to_json())

    return get_result_with_data(meetings)
def send_board_email(meeting: MeetingData) -> ResultWithData:
    archive_id_res = create_archive(meeting.id)
    if archive_id_res.is_error:
        return get_result_with_error(archive_id_res.message)

    archive = get_archive_data_by_code(archive_id_res.data)
    print(f"Archive should now be available at '{archive.get_archive_location()}'")

    mail_data = get_board_email_data(meeting, archive)
    send_email(mail_data)
    return get_result_with_data("")
Exemple #12
0
def handle_file(code: uuid, task: str, file) -> ResultWithData[bool]:
    """
    Saves the file to the disk and stores it's location in the database
    """

    task_obj = get_task_by_name(task)
    if task_obj is None:
        return get_result_with_error("Report type not found {0}".format(task))

    save_location = save_file(code, task, file)
    group_file = get_group_meeting_file_from_code(code, task)
    if group_file is None:
        create_group_meeting_file(code, task, save_location)
        return get_result_with_data(False)

    print("Overwriting file {0} from {1} (GMT)".format(
        group_file.file_location, group_file.date))
    new_date = datetime.utcnow()
    update_upload_date_for_file(code, task, new_date)
    return get_result_with_data(True)
Exemple #13
0
def remove_group_meeting_task(meeting_id: UUID, group_name: str, year: str,
                              task_name: str) -> ResultWithData[str]:
    group_meeting_task = get_group_meeting_task(meeting_id, group_name, year,
                                                task_name)
    if group_meeting_task is None:
        return get_result_with_data(
            "No group_meeting_task was found for meeting_id: {0}, group: {1}, year: {2}, task_name: {3}"
            .format(meeting_id, group_name, year, task_name))

    try:
        group_meeting_task.delete()
        return get_result_with_data("")
    except ConstraintError:
        if year == "active":
            year_txt = ""
        else:
            year_txt = str(year)
        return get_result_with_error(
            f"Cannot remove task {task_name} for group {group_name}{year_txt} as there is files already uploaded for it."
        )
Exemple #14
0
def update_meeting(meeting_data: MeetingJsonData) -> ResultWithData[str]:
    try:
        meeting = Meeting.get(id=meeting_data.id)
        meeting.date = meeting_data.date
        meeting.last_upload = meeting_data.last_upload
        meeting.lp = meeting_data.lp
        meeting.meeting_no = meeting_data.meeting_no
    except Exception as e:
        return get_result_with_error("Failed to update meeting {0}".format(e))

    return get_result_with_data("")
Exemple #15
0
def validate_meeting_id_from_str(id: str) -> ResultWithData[UUID]:
    code_res = validate_code(id)
    if code_res.is_error:
        return get_result_with_error(code_res.message)

    code = code_res.data
    meeting = get_meeting_by_id(code)
    if meeting is None:
        return get_result_with_error("No meeting exists with id {0}")

    return get_result_with_data(meeting.id)
Exemple #16
0
def validate_int(json: Dict, key: str) -> ResultWithData[int]:
    if key not in json:
        return get_result_with_error("Missing {0}".format(key))

    int_str = json[key]
    try:
        val = int(int_str)
        return get_result_with_data(val)
    except ValueError:
        return get_result_with_error(
            "{0} is not a valid integer".format(int_str))
Exemple #17
0
def create_new_meeting(date: datetime, last_upload: datetime, lp: int,
                       meeting_no: int) -> ResultWithData[UUID]:
    try:
        meeting = Meeting(year=date.year,
                          date=date,
                          last_upload=last_upload,
                          lp=lp,
                          meeting_no=meeting_no,
                          check_for_deadline=False)
    except Exception as e:
        print("Failed to create meeting due to '{0}'".format(e))
        return get_result_with_error("Failed to create meeting")
    return get_result_with_data(meeting.id)
Exemple #18
0
def validate_date(json: Dict, key: str) -> ResultWithData[datetime]:
    if key not in json:
        return get_result_with_error("Missing {0}".format(key))
    date_str = json[key]

    try:
        date = parse(date_str)
        return get_result_with_data(date)
    except ValueError:
        return get_result_with_error(
            "{0} is not a valid date".format(date_str))
    except OverflowError:
        return get_result_with_error("{0} is too large ".format(date_str))
Exemple #19
0
def update_stories(story_groups: List[StoryData]) -> ResultWithData[str]:
    for story_group in story_groups:
        group_year = get_group_year(story_group.group, story_group.year)
        if group_year is None:
            create_res = create_group_year(story_group.group, story_group.year,
                                           story_group.finished)
            if create_res is None:
                return get_result_with_error(
                    "Failed to create group year for {0} {1} {2}".format(
                        story_group.group, story_group.year,
                        story_group.finished))
        else:
            update_group_year(story_group.group, story_group.year,
                              story_group.finished)

    return get_result_with_data("")
Exemple #20
0
def get_data_for_code(code: uuid) -> ResultWithData[Dict]:
    group_meeting = get_group_meeting_by_code(code)

    if group_meeting is None:
        return get_result_with_error("Unable to find meeting for code {0}".format(str(code)))

    tasks = get_tasks_dict_for_code(code)
    meeting = get_meeting_data_from_code(code)
    group_year = get_group_year_data_from_code(code)

    return get_result_with_data({
        "group": group_year.to_json(),
        "study_period": meeting.lp,
        "year": meeting.year,
        "meeting_no": meeting.meeting_no,
        "tasks": tasks
    })
def validate_meeting(data: Dict) -> ResultWithData[MeetingJsonData]:
    meeting_res = validate_dict(data, "meeting")
    if meeting_res.is_error:
        return get_result_with_error(meeting_res.message)
    meeting = meeting_res.data

    if "id" not in meeting:
        return get_result_with_error("Missing id")
    id_str = meeting["id"]

    general_res = validate_meeting_general(meeting)
    if general_res.is_error:
        return get_result_with_error(general_res.message)
    meeting_data = general_res.data

    if id_str == "new":
        same_period_meeting = get_meeting_for_period(meeting_data.date.year,
                                                     meeting_data.lp,
                                                     meeting_data.meeting_no)
        if same_period_meeting is not None:
            return get_result_with_error(
                "A meeting already exists for {0}-lp{1}-{2}".format(
                    meeting_data.date.year, meeting_data.lp,
                    meeting_data.meeting_no))
    else:
        code_res = validate_code(id_str)
        if code_res.is_error:
            return get_result_with_error(
                "Invalid meeting id {0}".format(id_str))
        code = code_res.data

        # Validate that the meeting exists
        meeting_res = get_meeting_by_id(code)
        if meeting_res is None:
            return get_result_with_error("No meeting with id {0}".format(code))

        meeting_data.id = meeting_res.id

    groups_tasks_res = validate_groups_tasks(meeting)
    if groups_tasks_res.is_error:
        return get_result_with_error(groups_tasks_res.message)

    meeting_data.groups_tasks = groups_tasks_res.data
    return get_result_with_data(meeting_data)
def update_meeting_data(meeting_data: MeetingJsonData) -> ResultWithData[str]:
    if meeting_data.id is None:
        # The meeting does not yet exist, create it.
        create_meeting_res = create_new_meeting(
            date=meeting_data.date,
            last_upload=meeting_data.last_upload,
            lp=meeting_data.lp,
            meeting_no=meeting_data.meeting_no)
        if create_meeting_res.is_error:
            return get_result_with_error(create_meeting_res.message)

        meeting_data.id = create_meeting_res.data
    else:
        update_res = update_meeting(meeting_data)
        if update_res.is_error:
            return get_result_with_error(update_res.message)

    gt_res = update_groups_tasks(meeting_data.id, meeting_data.groups_tasks)
    if gt_res.is_error:
        return get_result_with_error(gt_res.message)

    return get_result_with_data("")
def validate_groups_tasks(
        meeting: Dict) -> ResultWithData[List[GroupTaskData]]:
    groups_tasks_res = validate_dict(meeting, "groups_tasks")
    if groups_tasks_res.is_error:
        return get_result_with_error(groups_tasks_res.message)

    groups_tasks = groups_tasks_res.data

    group_task_datas = []

    for task_type in groups_tasks:
        task = get_task_by_name(task_type)
        if task is None:
            return get_result_with_error("Invalid task {0}".format(task_type))

        task_groups_res = validate_list(groups_tasks, task_type)
        if task_groups_res.is_error:
            return get_result_with_error(task_groups_res.message)
        task_groups = task_groups_res.data

        for group_task in task_groups:
            name_res = validate_str(group_task, "name")
            if name_res.is_error:
                return get_result_with_error(name_res.message)
            name = name_res.data

            group = get_group_by_name(name)
            if group is None:
                return get_result_with_error("No such group {0}".format(name))

            group_task_datas.append(
                GroupTaskData(code=None,
                              group_name=group.name,
                              task_type=task.name))

    return get_result_with_data(group_task_datas)
Exemple #24
0
def validate_code(code: str) -> ResultWithData[UUID]:
    try:
        return get_result_with_data(UUID(code))
    except ValueError:
        return get_result_with_error("Invalid code format")
def get_config_value_int(config_key: str) -> ResultWithData[int]:
    value = get_config_value(config_key)
    try:
        return get_result_with_data(int(value))
    except ValueError:
        return get_result_with_error(f"Config value {value} for key {config_key} is not a valid integer")
Exemple #26
0
def validate_str(json: Dict, key: str) -> ResultWithData[str]:
    if key not in json:
        return get_result_with_error("Missing {0}".format(key))
    return get_result_with_data(json[key])