Beispiel #1
0
def create_with_password(moderator: ModeratorModel, password: str):
    """
    Create a moderator account. The password is given unhashed.
    :param moderator: filled in moderator model
    :param password: password to create moderator with
    :raises ArgumentError if the username or password doesn't fit the requirements.
    See {USERNAME,PASSWORD}_{MIN,MAX}_LENGTH and {USERNAME,PASSWORD}_ALLOWED_CHARS
    :raises ArgumentError if the username is already in use. Username checking is done
    case-insensitively
    """
    if not validation.check_username_validity(moderator.username):
        raise ArgumentError(MESSAGE_INVALID_USERNAME)

    if not validation.check_password_validity(password):
        raise ArgumentError(MESSAGE_INVALID_PASSWORD)

    if find_by_username_case_insensitive(moderator.username) is not None:
        raise ArgumentError(MESSAGE_USERNAME_IN_USE)

    with session() as s:
        orm_moderator = moderator.to_orm_model()
        orm_moderator.password = _hash_password(password)
        s.add(orm_moderator)
        s.flush()
        moderator = ModeratorModel.from_orm_model(orm_moderator)
        s.commit()
        return moderator
Beispiel #2
0
def get_all(offset: int, limit: int):
    with session() as s:
        q = s.query(BanOrmModel).order_by(desc(
            BanOrmModel.date)).limit(limit).offset(offset)
        r = list(map(lambda i: BanModel.from_orm_model(i), q.all()))
        s.commit()
        return r
Beispiel #3
0
def is_verified(verifying_client: VerifyingClient) -> bool:
    verification_model = None
    verification_model_cache = cache.get(
        cache_key('verifications', verifying_client.verification_id))
    if verification_model_cache:
        verification_model = VerificationsModel.from_cache(
            verification_model_cache)

    if not verification_model:
        with session() as s:
            q = s.query(VerificationOrmModel)
            q = q.filter_by(verification_id=verifying_client.verification_id)

            verifications_orm_model = q.one_or_none()
            if verifications_orm_model:
                verification_model = VerificationsModel.from_orm_model(
                    verifications_orm_model)

                cached = verification_model.to_cache()
                timeout = max(1, (verification_model.expires - now()) // 1000)
                cache.set(cache_key('verifications', verification_model.id),
                          cached,
                          timeout=timeout)
            s.commit()

    return verification_model and _is_verifications_valid(
        verifying_client, verification_model)
Beispiel #4
0
def find_post_by_id(post_id: int, include_thread=False) -> Optional[PostModel]:
    with session() as s:
        m = s.query(PostOrmModel).filter_by(id=post_id).one_or_none()
        res = None
        if m:
            res = PostModel.from_orm_model(m, include_thread=include_thread)
        return res
Beispiel #5
0
def find_thread_by_board_thread_refno_with_posts(
        board: BoardModel, thread_refno: int) -> Optional[ThreadModel]:
    thread_cache = cache.get(cache_key('thread', board.name, thread_refno))
    if not thread_cache:
        with session() as s:
            q = s.query(ThreadOrmModel)
            q = q.options(lazyload('posts'))
            q = q.filter(ThreadOrmModel.refno == thread_refno,
                         ThreadOrmModel.board_id == BoardOrmModel.id,
                         BoardOrmModel.name == board.name)
            thread_orm_model = q.one_or_none()

            if not thread_orm_model or not thread_orm_model.posts:
                return None

            # TODO: also load board in q above
            thread = ThreadModel.from_orm_model(thread_orm_model,
                                                include_board=True,
                                                include_posts=True)
            thread_cache = thread.to_cache(include_board=True,
                                           include_posts=True)
            cache.set(cache_key('thread', thread.board.name, thread.refno),
                      thread_cache,
                      timeout=0)
            return thread

    if thread_cache:
        return ThreadModel.from_cache(thread_cache)
    return None
Beispiel #6
0
def find_by_id(page_id: int) -> PageModel:
    with session() as s:
        m = s.query(PageOrmModel).filter_by(id=page_id).one_or_none()
        res = None
        if m:
            res = PageModel.from_orm_model(m)
        return res
Beispiel #7
0
def create_with_password(moderator: ModeratorModel, password: str):
    """
    Create a moderator account. The password is given unhashed.
    :param moderator: filled in moderator model
    :param password: password to create moderator with
    :raises ArgumentError if the username or password doesn't fit the requirements.
    See {USERNAME,PASSWORD}_{MIN,MAX}_LENGTH and {USERNAME,PASSWORD}_ALLOWED_CHARS
    :raises ArgumentError if the username is already in use. Username checking is done
    case-insensitively
    """
    if not validation.check_username_validity(moderator.username):
        raise ArgumentError(MESSAGE_INVALID_USERNAME)

    if not validation.check_password_validity(password):
        raise ArgumentError(MESSAGE_INVALID_PASSWORD)

    if find_by_username_case_insensitive(moderator.username) is not None:
        raise ArgumentError(MESSAGE_USERNAME_IN_USE)

    with session() as s:
        orm_moderator = moderator.to_orm_model()
        orm_moderator.password = _hash_password(password)
        s.add(orm_moderator)
        s.flush()
        moderator = ModeratorModel.from_orm_model(orm_moderator)
        s.commit()
        return moderator
Beispiel #8
0
def moderator_has_board_id(moderator: ModeratorModel, board_id: int) -> bool:
    with session() as s:
        m = s.query(BoardModeratorOrmModel).filter_by(
            moderator_id=moderator.id, board_id=board_id).one_or_none()
        res = m is not None
        s.commit()
        return res
Beispiel #9
0
def find_by_type(page_type: str) -> 'List[PageModel]':
    _check_page_type(page_type)

    lc = local_cache.get(cache_key('type', page_type))
    if lc:
        return list(map(lambda i: i.copy(), lc))

    pages_by_type_cached = cache.get(cache_key('pages_by_type', page_type))
    if pages_by_type_cached is not None:
        res = list(map(lambda i: PageModel.from_cache(i),
                       pages_by_type_cached))
    else:
        with session() as s:
            q = s.query(PageOrmModel).filter_by(type=page_type)
            q = q.order_by(asc(PageOrmModel.order))
            res = list(map(lambda i: PageModel.from_orm_model(i), q.all()))

            cache.set(cache_key('pages_by_type', page_type),
                      list(map(lambda i: i.to_cache(), res)))

            s.commit()

    local_cache.set(cache_key('type', page_type), res)

    return res
Beispiel #10
0
def find_by_id(page_id: int) -> PageModel:
    with session() as s:
        m = s.query(PageOrmModel).filter_by(id=page_id).one_or_none()
        res = None
        if m:
            res = PageModel.from_orm_model(m)
        return res
Beispiel #11
0
def create(board: BoardModel) -> BoardModel:
    if not validation.check_board_name_validity(board.name):
        raise ArgumentError(MESSAGE_INVALID_NAME)

    with session() as s:
        existing = s.query(BoardOrmModel).filter_by(name=board.name).one_or_none()
        if existing:
            raise ArgumentError(MESSAGE_DUPLICATE_BOARD_NAME)

        orm_board = board.to_orm_model()

        board_config = BoardConfigModel.from_defaults()
        board_config_orm = board_config.to_orm_model()
        s.add(board_config_orm)
        s.flush()

        orm_board.config_id = board_config_orm.id

        s.add(orm_board)
        s.commit()

        board = board.from_orm_model(orm_board)

        cache.set(cache_key('board_and_config', board.name), board.to_cache())

        _set_all_board_names_cache(s)

        s.commit()

        return board
Beispiel #12
0
def board_remove_moderator(board: BoardModel, moderator: ModeratorModel):
    with session() as s:
        bm = s.query(BoardModeratorOrmModel).filter_by(board_id=board.id, moderator_id=moderator.id).one_or_none()
        if not bm:
            raise ArgumentError(MESSAGE_BOARD_NOT_ADDED)
        s.delete(bm)
        s.commit()
Beispiel #13
0
def find_post_by_id(post_id: int, include_thread=False) -> Optional[PostModel]:
    with session() as s:
        m = s.query(PostOrmModel).filter_by(id=post_id).one_or_none()
        res = None
        if m:
            res = PostModel.from_orm_model(m, include_thread=include_thread)
        return res
Beispiel #14
0
def board_remove_moderator(board: BoardModel, moderator: ModeratorModel):
    with session() as s:
        bm = s.query(BoardModeratorOrmModel).filter_by(
            board_id=board.id, moderator_id=moderator.id).one_or_none()
        if not bm:
            raise ArgumentError(MESSAGE_BOARD_NOT_ADDED)
        s.delete(bm)
        s.commit()
Beispiel #15
0
def get_all_board_moderators_by_board(
        board: BoardModel) -> 'List[BoardModeratorModel]':
    with session() as s:
        bms = s.query(BoardModeratorOrmModel).filter_by(
            board_id=board.id).all()
        res = list(map(lambda i: BoardModeratorModel.from_orm_model(i), bms))
        s.commit()
        return res
Beispiel #16
0
def has_role(moderator: ModeratorModel, role: str) -> bool:
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        res = role in moderator_orm_model.roles
        s.commit()
        return res
Beispiel #17
0
def create_ban(ban: BanModel) -> BanModel:
    with session() as s:
        eq = s.query(BanOrmModel)

        m = ban.to_orm_model()
        s.add(m)
        s.commit()
        return BanModel.from_orm_model(m)
Beispiel #18
0
def get_catalog(board: BoardModel) -> CatalogModel:
    catalog_cache = cache.get(cache_key('board', board.name))
    if not catalog_cache:
        with session() as s:
            catalog, board_pages = _invalidate_board_pages_catalog_cache(s, board)
            return catalog

    return CatalogModel.from_cache(catalog_cache)
Beispiel #19
0
def find_by_id(ban_id: int) -> Optional[BanModel]:
    with session() as s:
        m = s.query(BanOrmModel).filter_by(id=ban_id).one_or_none()
        res = None
        if m:
            res = BanModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #20
0
def get_board_page(board: BoardModel, page: int) -> BoardPageModel:
    board_page_cache = cache.get(cache_key('board', board.name, page))
    if not board_page_cache:
        with session() as s:
            catalog, board_pages = _invalidate_board_pages_catalog_cache(s, board)
            return board_pages[page]

    return BoardPageModel.from_cache(board_page_cache)
Beispiel #21
0
def create(report: ReportModel):
    with session() as s:
        m = report.to_orm_model()
        s.add(m)
        s.commit()
        r = ReportModel.from_orm_model(m)
        s.commit()
        return r
Beispiel #22
0
def find_by_id(ban_id: int) -> Optional[BanModel]:
    with session() as s:
        m = s.query(BanOrmModel).filter_by(id=ban_id).one_or_none()
        res = None
        if m:
            res = BanModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #23
0
def find_by_id(moderator_id: int) -> ModeratorModel:
    with session() as s:
        m = s.query(ModeratorOrmModel).filter_by(id=moderator_id).one_or_none()
        res = None
        if m:
            res = ModeratorModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #24
0
def find_by_id(report_id: int) -> Optional[ReportModel]:
    with session() as s:
        m = s.query(ReportOrmModel).filter_by(id=report_id).one()
        res = None
        if m:
            res = ReportModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #25
0
def find_by_id(moderator_id: int) -> ModeratorModel:
    with session() as s:
        m = s.query(ModeratorOrmModel).filter_by(id=moderator_id).one_or_none()
        res = None
        if m:
            res = ModeratorModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #26
0
def get_board_moderator(board: BoardModel, moderator: ModeratorModel) -> BoardModeratorModel:
    with session() as s:
        m = s.query(BoardModeratorOrmModel).filter_by(moderator_id=moderator.id, board_id=board.id).one_or_none()
        res = None
        if m:
            res = BoardModeratorModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #27
0
def has_any_of_board_roles(moderator: ModeratorModel, board: BoardModel, role_list: 'List[str]') -> bool:
    _check_board_roles(role_list)

    with session() as s:
        board_moderator = s.query(BoardModeratorOrmModel).filter_by(moderator_id=moderator.id, board_id=board.id).one()
        res = any(role in board_moderator.roles for role in role_list)
        s.commit()
        return res
Beispiel #28
0
def create_ban(ban: BanModel) -> BanModel:
    with session() as s:
        eq = s.query(BanOrmModel)

        m = ban.to_orm_model()
        s.add(m)
        s.commit()
        return BanModel.from_orm_model(m)
Beispiel #29
0
def find_by_post(post: PostModel) -> Optional[ReportModel]:
    with session() as s:
        m = s.query(ReportOrmModel).filter_by(post_id=post.id).one_or_none()
        res = None
        if m:
            res = ReportModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #30
0
def get_catalog(board: BoardModel) -> CatalogModel:
    catalog_cache = cache.get(cache_key('board', board.name))
    if not catalog_cache:
        with session() as s:
            catalog, board_pages = _invalidate_board_pages_catalog_cache(
                s, board)
            return catalog

    return CatalogModel.from_cache(catalog_cache)
Beispiel #31
0
def get_all(include_boards=False) -> 'List[ModeratorModel]':
    with session() as s:
        q = s.query(ModeratorOrmModel)
        # TODO: fix this optimisation, it now requires way too many queries
        # if include_boards:
        #    q = q.options(joinedload(ModeratorOrmModel.boards.of_type(BoardOrmModel.moderators)))
        all_moderators = list(map(lambda m: ModeratorModel.from_orm_model(m, include_boards), q.all()))
        s.commit()
        return all_moderators
Beispiel #32
0
def add_role(moderator: ModeratorModel, role: str):
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        if role in moderator_orm_model.roles:
            raise ArgumentError('Role already added')
        moderator_orm_model.roles.append(role)
        s.commit()
Beispiel #33
0
def get_board_page(board: BoardModel, page: int) -> BoardPageModel:
    board_page_cache = cache.get(cache_key('board', board.name, page))
    if not board_page_cache:
        with session() as s:
            catalog, board_pages = _invalidate_board_pages_catalog_cache(
                s, board)
            return board_pages[page]

    return BoardPageModel.from_cache(board_page_cache)
Beispiel #34
0
def remove_role(moderator: ModeratorModel, role: str):
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        if role not in moderator_orm_model.roles:
            raise ArgumentError('Role not added')
        moderator_orm_model.roles.remove(role)
        s.commit()
Beispiel #35
0
def has_role(moderator: ModeratorModel, role: str) -> bool:
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(
            id=moderator.id).one()
        res = role in moderator_orm_model.roles
        s.commit()
        return res
Beispiel #36
0
def add_board_role(moderator: ModeratorModel, board: BoardModel, role: str):
    _check_board_roles([role])

    with session() as s:
        board_moderator = s.query(BoardModeratorOrmModel).filter_by(moderator_id=moderator.id, board_id=board.id).one()
        if role in board_moderator.roles:
            raise ArgumentError('Role already added')
        board_moderator.roles.append(role)
        s.commit()
Beispiel #37
0
def board_add_moderator(board: BoardModel, moderator: ModeratorModel):
    with session() as s:
        bm = s.query(BoardModeratorOrmModel).filter_by(moderator_id=moderator.id, board_id=board.id).one_or_none()
        if bm:
            raise ArgumentError(MESSAGE_BOARD_ALREADY_ADDED)
        m = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        b = s.query(BoardOrmModel).filter_by(id=board.id).one()
        b.moderators.append(m)
        s.commit()
Beispiel #38
0
def create_post(board: BoardModel, thread: ThreadModel, post: PostModel, sage: bool) \
        -> Tuple[PostResultModel, int, int]:
    start_time = now()
    with session() as s:
        post_orm_model = post.to_orm_model()

        s.add(post_orm_model)

        to_thread_orm_model = s.query(ThreadOrmModel).filter_by(
            id=thread.id).one()

        post_orm_model.thread = to_thread_orm_model
        post_orm_model.refno = 0

        # Atomically update the refno counter
        to_thread_orm_model.refno_counter = ThreadOrmModel.refno_counter + 1
        s.commit()

        # Set it to the post after the commit to make sure there aren't any duplicates
        post_refno = post_orm_model.refno = to_thread_orm_model.refno_counter
        post_id = post_orm_model.id

        # Attach file to the post id
        if post.file:
            file_orm_model = post.file.to_orm_model()
            file_orm_model.post_id = post_id
            s.add(file_orm_model)

        if post.moderator:
            post_orm_model.moderator_id = post.moderator.id

        modify_date = now()

        # Use the refno to avoid a count(*)
        if not sage and post_refno <= board.config.bump_limit:
            to_thread_orm_model.last_modified = modify_date
        s.commit()

        insert_time = now() - start_time
        start_time = now()

        _invalidate_thread_cache(s, thread, board)
        _invalidate_board_pages_catalog_cache(s, board)

        purge_thread_future = document_cache.purge_thread(board, thread)
        # Wait for the thread to be purged, otherwise the chance exists that the client reloads a cached version.
        # This only holds up the posting client, others have the updated memcache available.
        purge_thread_future.result()
        # Don't wait for this
        document_cache.purge_board(board)

        cache_time = now() - start_time

        res = PostResultModel.from_board_name_thread_refno_post_refno(
            board.name, thread.refno, post_refno)
        return res, insert_time, cache_time
Beispiel #39
0
def create_thread(board: BoardModel, post: PostModel) \
        -> Tuple[PostResultModel, int, int]:
    start_time = now()
    with session() as s:
        board_orm_model = s.query(BoardOrmModel).filter_by(id=board.id).one()

        thread_orm_model = ThreadOrmModel()
        thread_orm_model.last_modified = now()
        thread_orm_model.refno = 0
        thread_orm_model.board_id = board.id

        post_orm_model = post.to_orm_model()

        post_orm_model.thread = thread_orm_model
        post_orm_model.refno = 1
        s.add(thread_orm_model)

        # Atomically update the refno counter
        board_orm_model.refno_counter = BoardOrmModel.refno_counter + 1
        s.commit()

        # Set it to the board after the commit to make sure there aren't any duplicates
        thread_refno = thread_orm_model.refno = board_orm_model.refno_counter

        # Attach file to the post id
        if post.file:
            file_orm_model = post.file.to_orm_model()
            file_orm_model.post_id = post_orm_model.id
            s.add(file_orm_model)

        if post.moderator:
            post_orm_model.moderator_id = post.moderator.id

        # Purge overflowed threads
        threads_refnos_to_purge = _purge_threads(s, board, board.config.pages,
                                                 board.config.per_page)
        s.commit()

        insert_time = now() - start_time
        start_time = now()

        for purging_refno in threads_refnos_to_purge:
            cache.delete(cache_key('thread', board.name, purging_refno))
            cache.delete(cache_key('thread_stub', board.name, purging_refno))

        thread = ThreadModel.from_orm_model(thread_orm_model)
        _invalidate_thread_cache(s, thread, board)
        _invalidate_board_pages_catalog_cache(s, board)

        document_cache.purge_board(board)

        cache_time = now() - start_time

        res = PostResultModel.from_board_name_thread_refno_post_refno(
            board.name, thread_refno, 1)
        return res, insert_time, cache_time
Beispiel #40
0
def remove_role(moderator: ModeratorModel, role: str):
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(
            id=moderator.id).one()
        if role not in moderator_orm_model.roles:
            raise ArgumentError('Role not added')
        moderator_orm_model.roles.remove(role)
        s.commit()
Beispiel #41
0
def add_role(moderator: ModeratorModel, role: str):
    _check_roles([role])

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(
            id=moderator.id).one()
        if role in moderator_orm_model.roles:
            raise ArgumentError('Role already added')
        moderator_orm_model.roles.append(role)
        s.commit()
Beispiel #42
0
def remove_board_role(moderator: ModeratorModel, board: BoardModel, role: str):
    _check_board_roles([role])

    with session() as s:
        board_moderator = s.query(BoardModeratorOrmModel).filter_by(
            moderator_id=moderator.id, board_id=board.id).one()
        if role not in board_moderator.roles:
            raise ArgumentError('Role not added')
        board_moderator.roles.remove(role)
        s.commit()
Beispiel #43
0
def delete(page: PageModel):
    with session() as s:
        m = s.query(PageOrmModel).filter_by(id=page.id).one()
        s.delete(m)
        s.flush()

        cache.delete(cache_key('page_by_link_name', page.link_name))
        _cache_pages_by_type(s, page.type)

        s.commit()
Beispiel #44
0
def get_board_moderator(board: BoardModel,
                        moderator: ModeratorModel) -> BoardModeratorModel:
    with session() as s:
        m = s.query(BoardModeratorOrmModel).filter_by(
            moderator_id=moderator.id, board_id=board.id).one_or_none()
        res = None
        if m:
            res = BoardModeratorModel.from_orm_model(m)
        s.commit()
        return res
Beispiel #45
0
def delete(page: PageModel):
    with session() as s:
        m = s.query(PageOrmModel).filter_by(id=page.id).one()
        s.delete(m)
        s.flush()

        cache.delete(cache_key('page_by_link_name', page.link_name))
        _cache_pages_by_type(s, page.type)

        s.commit()
Beispiel #46
0
def board_add_moderator(board: BoardModel, moderator: ModeratorModel):
    with session() as s:
        bm = s.query(BoardModeratorOrmModel).filter_by(
            moderator_id=moderator.id, board_id=board.id).one_or_none()
        if bm:
            raise ArgumentError(MESSAGE_BOARD_ALREADY_ADDED)
        m = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        b = s.query(BoardOrmModel).filter_by(id=board.id).one()
        b.moderators.append(m)
        s.commit()
Beispiel #47
0
def has_any_of_board_roles(moderator: ModeratorModel, board: BoardModel,
                           role_list: 'List[str]') -> bool:
    _check_board_roles(role_list)

    with session() as s:
        board_moderator = s.query(BoardModeratorOrmModel).filter_by(
            moderator_id=moderator.id, board_id=board.id).one()
        res = any(role in board_moderator.roles for role in role_list)
        s.commit()
        return res
Beispiel #48
0
def get_all(include_boards=False) -> 'List[ModeratorModel]':
    with session() as s:
        q = s.query(ModeratorOrmModel)
        # TODO: fix this optimisation, it now requires way too many queries
        # if include_boards:
        #    q = q.options(joinedload(ModeratorOrmModel.boards.of_type(BoardOrmModel.moderators)))
        all_moderators = list(
            map(lambda m: ModeratorModel.from_orm_model(m, include_boards),
                q.all()))
        s.commit()
        return all_moderators
Beispiel #49
0
def update_thread_locked(thread: ThreadModel, locked: bool):
    with session() as s:
        existing = s.query(ThreadOrmModel).filter_by(id=thread.id).one()
        existing.locked = locked
        s.commit()

        _invalidate_thread_cache(s, thread, thread.board)
        _invalidate_board_pages_catalog_cache(s, thread.board)

        document_cache.purge_thread(thread.board, thread)
        document_cache.purge_board(thread.board)
Beispiel #50
0
def create_post(board: BoardModel, thread: ThreadModel, post: PostModel, sage: bool) \
        -> Tuple[PostResultModel, int, int]:
    start_time = now()
    with session() as s:
        post_orm_model = post.to_orm_model()

        s.add(post_orm_model)

        to_thread_orm_model = s.query(ThreadOrmModel).filter_by(id=thread.id).one()

        post_orm_model.thread = to_thread_orm_model
        post_orm_model.refno = 0

        # Atomically update the refno counter
        to_thread_orm_model.refno_counter = ThreadOrmModel.refno_counter + 1
        s.commit()

        # Set it to the post after the commit to make sure there aren't any duplicates
        post_refno = post_orm_model.refno = to_thread_orm_model.refno_counter
        post_id = post_orm_model.id

        # Attach file to the post id
        if post.file:
            file_orm_model = post.file.to_orm_model()
            file_orm_model.post_id = post_id
            s.add(file_orm_model)

        if post.moderator:
            post_orm_model.moderator_id = post.moderator.id

        modify_date = now()

        # Use the refno to avoid a count(*)
        if not sage and post_refno <= board.config.bump_limit:
            to_thread_orm_model.last_modified = modify_date
        s.commit()

        insert_time = now() - start_time
        start_time = now()

        _invalidate_thread_cache(s, thread, board)
        _invalidate_board_pages_catalog_cache(s, board)

        purge_thread_future = document_cache.purge_thread(board, thread)
        # Wait for the thread to be purged, otherwise the chance exists that the client reloads a cached version.
        # This only holds up the posting client, others have the updated memcache available.
        purge_thread_future.result()
        # Don't wait for this
        document_cache.purge_board(board)

        cache_time = now() - start_time

        res = PostResultModel.from_board_name_thread_refno_post_refno(board.name, thread.refno, post_refno)
        return res, insert_time, cache_time
Beispiel #51
0
def delete_thread(thread: ThreadModel):
    with session() as s:
        thread_orm_model = s.query(ThreadOrmModel).filter_by(id=thread.id).one()
        s.delete(thread_orm_model)
        s.commit()

        _invalidate_thread_cache(s, thread, thread.board)
        _invalidate_board_pages_catalog_cache(s, thread.board)

        document_cache.purge_thread(thread.board, thread)
        document_cache.purge_board(thread.board)
Beispiel #52
0
def update_thread_locked(thread: ThreadModel, locked: bool):
    with session() as s:
        existing = s.query(ThreadOrmModel).filter_by(id=thread.id).one()
        existing.locked = locked
        s.commit()

        _invalidate_thread_cache(s, thread, thread.board)
        _invalidate_board_pages_catalog_cache(s, thread.board)

        document_cache.purge_thread(thread.board, thread)
        document_cache.purge_board(thread.board)
Beispiel #53
0
def check_password_match(moderator: ModeratorModel, password: str):
    if not validation.check_password_validity(password):
        raise ArgumentError(MESSAGE_INVALID_PASSWORD)

    with session() as s:
        moderator_orm_model = s.query(ModeratorOrmModel).filter_by(id=moderator.id).one()
        moderator_hashed_password = moderator_orm_model.password
        s.commit()

        if not bcrypt.checkpw(password.encode(), moderator_hashed_password):
            raise ArgumentError(MESSAGE_PASSWORD_INCORRECT)
Beispiel #54
0
def create_thread(board: BoardModel, post: PostModel) \
        -> Tuple[PostResultModel, int, int]:
    start_time = now()
    with session() as s:
        board_orm_model = s.query(BoardOrmModel).filter_by(id=board.id).one()

        thread_orm_model = ThreadOrmModel()
        thread_orm_model.last_modified = now()
        thread_orm_model.refno = 0
        thread_orm_model.board_id = board.id

        post_orm_model = post.to_orm_model()

        post_orm_model.thread = thread_orm_model
        post_orm_model.refno = 1
        s.add(thread_orm_model)

        # Atomically update the refno counter
        board_orm_model.refno_counter = BoardOrmModel.refno_counter + 1
        s.commit()

        # Set it to the board after the commit to make sure there aren't any duplicates
        thread_refno = thread_orm_model.refno = board_orm_model.refno_counter

        # Attach file to the post id
        if post.file:
            file_orm_model = post.file.to_orm_model()
            file_orm_model.post_id = post_orm_model.id
            s.add(file_orm_model)

        if post.moderator:
            post_orm_model.moderator_id = post.moderator.id

        # Purge overflowed threads
        threads_refnos_to_purge = _purge_threads(s, board, board.config.pages, board.config.per_page)
        s.commit()

        insert_time = now() - start_time
        start_time = now()

        for purging_refno in threads_refnos_to_purge:
            cache.delete(cache_key('thread', board.name, purging_refno))
            cache.delete(cache_key('thread_stub', board.name, purging_refno))

        thread = ThreadModel.from_orm_model(thread_orm_model)
        _invalidate_thread_cache(s, thread, board)
        _invalidate_board_pages_catalog_cache(s, board)

        document_cache.purge_board(board)

        cache_time = now() - start_time

        res = PostResultModel.from_board_name_thread_refno_post_refno(board.name, thread_refno, 1)
        return res, insert_time, cache_time
Beispiel #55
0
def update(page: PageModel):
    _validate(page)

    with session() as s:
        existing = s.query(PageOrmModel).filter_by(id=page.id).one_or_none()
        if not existing:
            raise ArgumentError(MESSAGE_PAGE_NOT_FOUND)
        s.merge(page.to_orm_model())

        _cache_page(s, page)

        s.commit()
Beispiel #56
0
def get_all_logs_by_board(board: BoardModel, offset: int, limit: int) -> 'List[ModeratorLogModel]':
    with session() as s:
        ls = s.query(ModeratorLogOrmModel) \
            .filter_by(board_id=board.id) \
            .order_by(desc(ModeratorLogOrmModel.date)) \
            .options(joinedload('moderator')) \
            .offset(offset).limit(limit) \
            .all()

        res = list(map(lambda i: ModeratorLogModel.from_orm_model(i, with_moderator=True), ls))
        s.commit()
        return res
Beispiel #57
0
def find_by_username_case_insensitive(username: str) -> ModeratorModel:
    if not validation.check_username_validity(username):
        raise ArgumentError(MESSAGE_INVALID_USERNAME)

    with session() as s:
        # Username chars are safe because it is checked above
        m = s.query(ModeratorOrmModel).filter(ModeratorOrmModel.username.ilike(username)).one_or_none()
        res = None
        if m:
            res = ModeratorModel.from_orm_model(m)
        s.commit()
        return res