Beispiel #1
0
def delete_cardbox(_id):
    box = CardBox.fetch(db, _id)

    if not box:
        flash('Invalid Cardbox ID.', 'error')
        return redirect(url_for('index'))

    if box._id not in current_user.cardboxs:
        flash('You can only delete cardboxes that you own.', 'error')
        return redirect(url_for('show_box', _id=_id))

    form = ConfirmationForm()
    form.submit.label.text = 'Delete'
    message = 'Are you sure you want to delete CardBox ' + box.name + '?'

    if form.is_submitted():

        CardBox.delete(db, _id)

        current_user.cardboxs.remove(box._id)

        current_user.store(db)
        User.update_score(db, current_user._id)

        flash("Successfully removed CardBox")
        return redirect(
            url_for('huge_list', foption='owner', fterm=current_user._id))

    return render_template('_confirm.html',
                           message=message,
                           address='show_box',
                           add_kwargs={'_id': _id},
                           form=form)
Beispiel #2
0
def add_cardbox():
    if not request.is_json:
        abort(404)

    # already returns dictionary
    payload = request.get_json()

    req = ('username', 'password', 'tags', 'content', 'name')
    if not payload or not all(r in payload for r in req):
        abort(404)

    if User.exists(db, payload['username']):
        user = User.fetch(db, payload['username'])
        if not user.check_password(payload['password']):
            abort(404)

        new_box = CardBox(CardBox.gen_card_id(),
                          name=payload['name'],
                          owner=user._id,
                          rating=0,
                          tags=payload['tags'],
                          content=payload['content'])
        new_box.store(db)

        user.cardboxs.append(new_box._id)

        user.store(db)

    return 'OK'
Beispiel #3
0
def confirm_challenge(user_id, box_id):
    box = CardBox.fetch(db, box_id)

    if not box:
        flash('Invalid Cardbox ID.', 'error')
        return redirect(url_for('challenge_user', _id=user_id))

    if user_id == current_user._id:
        flash('You can not even challenge yourself. Nice try.', 'error')
        return redirect(url_for('user_list'))

    user = User.fetch(db, user_id)

    if not user:
        flash('Invalid User ID.', 'error')
        return redirect(url_for('user_list'))

    form = ConfirmationForm()
    form.submit.label.text = 'Challenge'
    message = 'Challenge ' + user_id + ' to duel ' + box.name + '?'

    if form.is_submitted():
        challenge.challenge(db, current_user._id, user._id, box._id)
        flash('Challenge request sent!')
        return redirect(url_for('challenge_list', requests='sent'))

    return render_template('_confirm.html',
                           message=message,
                           address='challenge_user',
                           add_kwargs={'_id': user_id},
                           form=form)
Beispiel #4
0
def download_cardbox(_id: str):
    box = CardBox.fetch(db, _id)

    if not box:
        abort(404)

    return jsonify(vars(box))
Beispiel #5
0
def preview_box(_id):
    box = CardBox.fetch(db, _id)

    if not box:
        flash('Invalid Cardbox ID.', 'error')
        return redirect(url_for('huge_list'))

    return render_template('preview_box.html', box=box)
Beispiel #6
0
def show_box(_id):
    box = CardBox.fetch(db, _id)

    if not box:
        flash('Invalid Cardbox ID.', 'error')
        return redirect(url_for('huge_list'))

    owned = box.owner == current_user._id

    return render_template('show_box.html', box=box, owned=owned)
Beispiel #7
0
def download_cardbox(_id: str):
    box = CardBox.fetch(db, _id)

    if not box:
        abort(404)

    content = Card.fetch_content_to_list(db, _id)
    vars_box = vars(box)
    vars_box['content'] = content

    # use flask jsonify to create valid json response
    return jsonify(vars_box)
Beispiel #8
0
def rate_cardbox(_id):
    box = CardBox.fetch(db, _id)

    if not box:
        flash('Invalid Cardbox ID.', 'error')
        return redirect(url_for('index'))

    if box.increment_rating(db, current_user):
        User.update_score(db, box.owner)
        flash('Successfully rated. Thank you for your appreciation! :3')
        return redirect(url_for('show_box', _id=_id))

    flash("Already rated. Don't try to fool us!", 'error')
    return redirect(url_for('show_box', _id=_id))
Beispiel #9
0
def show_user(_id):
    if not User.exists(db, _id):
        flash('Invalid User Name.'
              'Be the first User to have this name! :D', 'error')
        return redirect(url_for('index'))

    score = User.update_score(db, _id)

    user = User.fetch(db, _id)
    picture_filepath = utils.profile_img_path(app, user._id)

    # <-- Showcase -->
    showcase = dict(info=False, cardbox=False, rank=False)

    infocase = user.showcase
    if infocase['show_info']:
        showcase['info'] = infocase['info']
    if infocase['show_cardbox']:
        box = CardBox.fetch(db, infocase['cardbox'])
        if box:
            showcase['cardbox'] = box
        else:
            showcase['cardbox'] = 'string'
    if infocase['show_rank']:
        showcase['rank'] = user.get_rank(db)

    # <-- my own profile? -->
    if user._id == current_user._id:
        return render_template('show_user_myself.html',
                               user=user,
                               showcase=showcase,
                               picture_filepath=picture_filepath,
                               score=score,
                               active='profile')

    return render_template('show_user.html',
                           user=user,
                           active='community',
                           picture_filepath=picture_filepath,
                           showcase=showcase,
                           score=score,
                           following=current_user.is_following(_id))
Beispiel #10
0
def challenge(db, challenger_id, challenged_id, box_id):
    new_duel_id = gen_duel_id()

    box = CardBox.fetch(db, box_id)
    content = Card.fetch_content(db, box_id)

    vs_dict = dict(duel_id=new_duel_id,
                   challenger=challenger_id,
                   challenged=challenged_id,
                   box_id=box_id,
                   box_name=box.name,
                   box_content=content,
                   started=False,
                   finish_time=None,
                   winner='')

    db.hset(TABLE_VS, new_duel_id, json.dumps(vs_dict))
    db.rpush(challenger_id + CHALLENGE_SUFFIX, new_duel_id)
    db.rpush(challenged_id + CHALLENGE_SUFFIX, new_duel_id)

    return new_duel_id
Beispiel #11
0
    def update_score(db, _id) -> int:
        user = User.fetch(db, _id)

        score_likes = 0

        boxes = CardBox.fetch_multiple(db, user.cardboxs)
        for box in boxes:
            score_likes = score_likes + box.rating

        score_followers = 0

        users = User.fetch_all(db)
        for u in users:
            if u.is_following(user._id):
                score_followers += 1

        score_boxes = len(user.cardboxs)

        score = (user.offline_score + score_likes * 100 +
                 score_followers * 200 + score_boxes * 100)

        db.zadd(TABLE_SCORE, {_id: score})

        return score
Beispiel #12
0
def challenge_user(_id):
    if _id == current_user._id:
        flash('You can not even challenge yourself. Nice try.', 'error')
        return redirect(url_for('user_list'))

    args = request.args

    # <-- receive parameters -->
    sort_key = args.get('sort')
    sort_direction = args.get('direction')
    page = args.get('page')
    filter_option = args.get('foption')
    filter_term = args.get('fterm')

    # <-- validate parameters and set fallback values -->
    sort_key_possible = ('name', 'owner', 'rating')
    sort_key = sort_key if sort_key in sort_key_possible else 'rating'

    sort_direction_possible = ('desc', 'asc')
    sort_direction = (sort_direction
                      if sort_direction in sort_direction_possible else 'desc')
    sort_direction_bool = sort_direction == 'desc'

    filter_option_possible = ('name', 'owner')
    filter_option = (filter_option
                     if filter_option in filter_option_possible else 'name')

    # filter_term: filter only applied if non-empty string given (None case)
    # TODO: filter_term validation analogous to tags/user input sanitization

    page = page or 1  # equals 1 if None; else: stays the same
    try:
        page = int(page)
    except ValueError:
        page = 1

    # <-- filter form -->
    form = ChallengeFilterForm()
    if form.validate_on_submit():
        filter_option = form.option.data
        filter_term = form.term.data

        kwargs = {key: value for key, value in args.items()}
        kwargs.update(sort=sort_key,
                      direction=sort_direction,
                      foption=filter_option,
                      fterm=filter_term,
                      page=1)

        return redirect(url_for('challenge_user', _id=_id, **kwargs))

    form.term.data = filter_term
    form.option.data = filter_option

    cardboxes = CardBox.fetch_all(db)

    # <-- filter process -->
    # checks for filter_option = 'name', 'owner' if term is part of string
    if filter_term:
        if filter_option == 'name' or filter_option == 'owner':
            cardboxes = [
                box for box in cardboxes
                if filter_term.lower() in getattr(box, filter_option).lower()
            ]
        else:
            cardboxes = [
                box for box in cardboxes
                if filter_term in getattr(box, filter_option)
            ]

    # <-- sort process -->
    def _sort_key_of(box):
        if sort_key == 'name':
            return box.name.lower()
        if sort_key == 'owner':
            return box.owner.lower()

        return getattr(box, sort_key)

    if cardboxes:
        cardboxes.sort(key=_sort_key_of, reverse=sort_direction_bool)

    # <-- pagination -->
    per_page = 50
    cardbox_count = len(cardboxes)
    page_range = utils.page_range(total_count=cardbox_count, per_page=per_page)
    page = (page if page in page_range else 1)

    pagination = utils.Pagination(parent=cardboxes,
                                  page=page,
                                  per_page=per_page,
                                  total_count=cardbox_count)

    # <-- standard values-->
    kwargs = {key: value for key, value in args.items()}
    kwargs.update(sort=sort_key,
                  direction=sort_direction,
                  foption=filter_option,
                  fterm=filter_term,
                  page=page,
                  _id=_id)

    # <-- creation of dynamic content -->
    pag_kwargs = dict(pagination=pagination,
                      endpoint='challenge_user',
                      prev='<',
                      next='>',
                      ellipses='...',
                      size='lg',
                      args=kwargs)

    def partner_id_producer(item):
        return _id

    wrapper = utils.TableItemWrapper(dict(partner_id=partner_id_producer))

    table = ChooseBoxTable(wrapper(pagination.items),
                           _id,
                           sort_reverse=sort_direction_bool,
                           sort_by=sort_key)

    return render_template('challenge.html',
                           _id=_id,
                           table=table,
                           filter_form=form,
                           pagination_kwargs=pag_kwargs,
                           active='versus')
Beispiel #13
0
def user_settings():

    # <-- Change profile picture -->
    picture_form = PictureForm()

    if picture_form.submit.data and picture_form.validate_on_submit():
        filename = utils.sha1_of(current_user._id) + '.jpg'
        filepath = os.path.join(app.static_folder, 'img', filename)

        utils.save_file_field_img(picture_form.picture, filepath)

        flash('Successfully changed profile picture!')

        return (redirect(url_for('user_settings')))

    elif picture_form.submit.data and picture_form.is_submitted():
        for message in picture_form.picture.errors:
            flash(message, category='error')

        return (redirect(url_for('user_settings')))

    picture_filepath = utils.profile_img_path(app, current_user._id)

    # <-- Change Showcase -->
    boxes = CardBox.fetch_multiple(db, current_user.cardboxs)

    showcase_form = ShowcaseForm()
    choices = [(b._id, b.name) for b in boxes]
    choices = [('', '---')] + choices
    showcase_form.cardbox_input.choices = choices

    if (showcase_form.submit_showcase.data
            and showcase_form.validate_on_submit()):
        new_showcase = dict(info=showcase_form.info_input.data,
                            cardbox=showcase_form.cardbox_input.data,
                            show_info=showcase_form.check_info.data,
                            show_cardbox=showcase_form.check_cardbox.data,
                            show_rank=showcase_form.check_rank.data)

        current_user.showcase = new_showcase
        current_user.store(db)

        flash('Showcase adjusted!')

        return redirect(url_for('user_settings'))

    showcase_form.check_info.data = current_user.showcase['show_info']
    showcase_form.info_input.data = current_user.showcase['info']
    showcase_form.check_cardbox.data = current_user.showcase['show_cardbox']
    showcase_form.cardbox_input.data = current_user.showcase['cardbox']
    showcase_form.check_rank.data = current_user.showcase['show_rank']
    showcase_form.rank_token.data = current_user.get_rank(db)

    # <-- Change Password -->
    password_form = ChangePasswordForm()

    if (password_form.submit_password.data
            and password_form.validate_on_submit()):

        if not current_user.check_password(password_form.old_password.data):
            flash('Old passwort not correct.', 'error')
            return redirect(url_for('user_settings'))

        current_user.set_password(password_form.new_password.data)
        current_user.store(db)

        flash('Successfully changed password!')

        return redirect(url_for('user_settings'))

    return render_template('profile_settings.html',
                           user=current_user,
                           picture_form=picture_form,
                           showcase_form=showcase_form,
                           password_form=password_form,
                           picture_filepath=picture_filepath)
Beispiel #14
0
def add_cardbox():
    if not request.is_json:
        print('not json')
        abort(404)

    # already returns dictionary
    payload = request.get_json()

    # <-- validate payload -->
    req = ('username', 'password', 'tags', 'content', 'name', 'info')
    if not payload or not all(r in payload for r in req):
        print('missing key in payload')
        abort(404)

    # None check
    if any(payload[key] is None for key in req):
        print('key is None')
        abort(404)

    # type check
    if not all([
            isinstance(payload['tags'], list),
            isinstance(payload['name'], str),
            isinstance(payload['info'], str)
    ]):
        print('key wrong type')
        abort(404)

    if any(' ' in tag for tag in payload['tags']):
        print('whitespace in tag')
        abort(404)

    # <-- validate content -->
    if not isinstance(payload['content'], list):
        print('content not list')
        abort(404)

    attrs = ('question', 'answers', 'correct_answer', 'explanation')
    if not all(a in _dict for a in attrs for _dict in payload['content']):
        print('missing key in card')
        abort(404)

    number_of_answers = 3

    for card in payload['content']:

        q, a, ca, e = (card['question'], card['answers'],
                       card['correct_answer'], card['explanation'])

        if not isinstance(q, str) or not isinstance(e, str):
            abort(404)

        if not (isinstance(a, list) and len(a) == number_of_answers):
            abort(404)

        if not (isinstance(ca, int) and ca in range(number_of_answers)):
            abort(404)

    # check authorization
    if User.exists(db, payload['username']):
        user = User.fetch(db, payload['username'])
        if not user.check_password(payload['password']):
            print('unauthorized')
            abort(404)

        cardbox_id = CardBox.gen_card_id()

        # 'Update'-Function
        boxes = CardBox.fetch_multiple(db, user.cardboxs)

        for box in boxes:
            if box.name == payload['name']:
                cardbox_id = box._id
                break
        else:
            user.cardboxs.append(cardbox_id)

        # store content in separate redis table
        Card.save_content(db, cardbox_id, payload['content'])

        # create CardBox object for metadata
        new_box = CardBox(cardbox_id,
                          name=payload['name'],
                          owner=user._id,
                          rating=0,
                          info=payload['info'],
                          tags=payload['tags'])

        new_box.store(db)
        user.store(db)
        User.update_score(db, user._id)

    return 'OK'
Beispiel #15
0
def huge_list():

    args = request.args

    sort_key = args.get('sort') or 'rating'
    sort_direction = args.get('direction')
    page = int(args.get('page')) if args.get('page') else 1

    if not sort_direction:
        sort_direction = True
    else:
        sort_direction = sort_direction == 'desc'

    filter_option = args.get('foption')
    filter_term = args.get('fterm')

    form = FilterForm()
    if form.validate_on_submit():
        filter_option = form.option.data
        filter_term = form.term.data

        kwargs = {key: value for key, value in args.items()}
        kwargs.update(foption=filter_option, fterm=filter_term, page=1)

        return redirect(url_for('huge_list', **kwargs))

    form.term.data = filter_term
    filter_option = filter_option or 'tags'
    form.option.data = filter_option

    def sort_key_of(box):
        if sort_key == 'name':
            return box.name.lower()
        if sort_key == 'owner':
            return box.owner.lower()

        return getattr(box, sort_key)

    cardboxes = CardBox.fetch_all(db)

    if filter_term:
        cardboxes = [
            c for c in cardboxes if filter_term in getattr(c, filter_option)
        ]

    if sort_key and cardboxes and hasattr(cardboxes[0], sort_key):
        cardboxes.sort(key=sort_key_of, reverse=sort_direction)
    else:
        sort_key = None

    pagination = utils.Pagination(parent=cardboxes,
                                  page=page,
                                  per_page=50,
                                  total_count=len(cardboxes))

    kwargs = {key: value for key, value in args.items()}
    kwargs.update(page=page, foption=filter_option, direction=sort_direction)

    pag_kwargs = dict(pagination=pagination,
                      endpoint='huge_list',
                      prev='<',
                      next='>',
                      ellipses='...',
                      size='lg',
                      args=kwargs)

    table = CardBoxTable(pagination.items,
                         sort_reverse=sort_direction,
                         sort_by=sort_key)

    return render_template('huge_list.html',
                           table=table,
                           filter_form=form,
                           pagination_kwargs=pag_kwargs)