def test_null_start_date(self):
        ch4 = Challenge(title='Challenge 4', external_id=12)
        ch4.save()

        response = self.client.get('/')

        challenge = response.data['challenge']
        self.assertEqual(3, challenge['id'])
    def test_all_ended_one_null(self):
        ch4 = Challenge(title='Challenge 4', external_id=12)
        ch4.save()
        self.timezone_mock.now.return_value = datetime(2020, 10, 1)

        response = self.client.get('/')

        challenge = response.data['challenge']
        self.assertEqual(5, challenge['id'])
def challenge_setup():
    """Set up some sample data to test with.
    
    This is a bit clearer and hopefully more flexible than using fixtures.
    
    """
    challenge_teardown()  # In case other tests didn't clean up

    p = Project()
    p.name = 'My Project'
    p.slug = getattr(settings, 'IGNITE_PROJECT_SLUG', 'my-project')
    p.description = 'My super awesome project of awesomeness.'
    p.long_description = 'Did I mention how awesome it was?'
    p.allow_participation = True
    p.save()

    c = Challenge()
    c.project = p
    c.title, 'My Challenge'
    c.slug = getattr(settings, 'IGNITE_CHALLENGE_SLUG', 'my-challenge')
    c.summary = 'Are you up to it?'
    c.description = 'This is a challenge of supreme challengingness.'
    c.end_date = datetime.utcnow() + timedelta(days=365)
    c.save()

    ph = Phase()
    ph.challenge = c
    ph.name = 'Ideation'
    ph.order = 1
    ph.save()

    cat = Category()
    cat.name = 'Beer'
    cat.slug = 'beer'
    cat.save()
    def test_all_ended_one_upcoming(self):
        ch4 = Challenge(title='Challenge 4',
                        external_id=12,
                        start_date=date(2021, 1, 1),
                        end_date=date(2021, 1, 30))
        ch4.save()
        self.timezone_mock.now.return_value = datetime(2020, 10, 1)

        response = self.client.get('/')

        challenge = response.data['challenge']
        self.assertEqual(2, challenge['id'])
    def test_non_final_challenges(self):
        ch = Challenge(title='Challenge Recently Ended', external_id=30, start_date=date(2020, 2, 1), end_date=date(2020, 2, 25))
        ch.save()

        challenges = Challenge.objects.get_non_final()

        eids = set(ch.external_id for ch in challenges)
        # 5, 6: ongoing
        # 12: upcoming
        # 14: no date
        # 30: recendly ended
        self.assertEqual({5, 6, 12, 14, 30}, eids)
Exemple #6
0
    def post(self, request, challenge: Challenge, *args, **kwargs):
        comment_content = request.data.get('content', None)
        if not isinstance(comment_content, str):
            return Response(status=400,
                            data={'error': 'Invalid comment content!'})
        if len(comment_content) < 5 or len(comment_content) > 500:
            return Response(status=400,
                            data={
                                'error':
                                'Comment must be between 5 and 500 characters!'
                            })

        challenge.add_comment(author=request.user, content=comment_content)
        return Response(status=201)
def challenge_setup():
    """Set up some sample data to test with.
    
    This is a bit clearer and hopefully more flexible than using fixtures.
    
    """
    challenge_teardown()  # In case other tests didn't clean up
    
    p = Project()
    p.name = 'My Project'
    p.slug = getattr(settings, 'IGNITE_PROJECT_SLUG', 'my-project')
    p.description = 'My super awesome project of awesomeness.'
    p.long_description = 'Did I mention how awesome it was?'
    p.allow_participation = True
    p.save()
    
    c = Challenge()
    c.project = p
    c.title, 'My Challenge'
    c.slug = getattr(settings, 'IGNITE_CHALLENGE_SLUG', 'my-challenge')
    c.summary = 'Are you up to it?'
    c.description = 'This is a challenge of supreme challengingness.'
    c.end_date = datetime.utcnow() + timedelta(days=365)
    c.save()
    
    ph = Phase()
    ph.challenge = c
    ph.name = 'Ideation'
    ph.order = 1
    ph.save()

    cat = Category()
    cat.name = 'Beer'
    cat.slug = 'beer'
    cat.save()
Exemple #8
0
    def setUp(self):
        super().setUp()
        challenge = Challenge(external_id=10)
        self.challenge = challenge
        challenge.save()

        challenge_page = Mock()
        self.challenge_page = challenge_page
        self.challenge_title = 'My Challenge!'
        self.start_date = date(2019, 10, 20)
        self.end_date = date(2020, 1, 22)
        challenge_page.title = self.challenge_title
        challenge_page.end_date = self.end_date
        challenge_page.start_date = self.start_date
        challenge_page.competitors = []
Exemple #9
0
def get_next_challenge(current_challenge: Challenge, current_running_challenge: RunningChallenges):
    all_challenges = Challenge.objects.all()

    current_challenge_proba = current_challenge.solve_proba()

    print("Current challenge proba: {}".format(current_challenge_proba))

    if current_running_challenge.get_solve_duration_min() > 5:
        print("Players are too dumb")
        next_challenges = filter(lambda c: c.solve_proba() >= current_challenge_proba, all_challenges)
    else:
        print("Players are too smart")
        next_challenges = filter(lambda c: c.solve_proba() <= current_challenge_proba, all_challenges)

    next_challenges = [n for n in next_challenges if n.id != current_challenge.id]

    if not next_challenges:
        next_challenges=list(Challenge.objects.all())

        next_challenges = [n for n in next_challenges if n.id != current_challenge.id]

    next_challenge = random.choice(next_challenges)

    print("Next challenge is {}".format(next_challenge))

    return next_challenge
Exemple #10
0
def createChallenge(request):
    context = standardContext(request)
    user = User.from_authuser(request.user)

    if not user.allow_create:
        raise exceptions.PermissionDenied()

    if request.method == "POST":
        form = CreateChallengeForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['challenge_name'].strip()
            category = form.cleaned_data['category']
            if Challenge.objects.filter(name=name).count() > 0:
                context[
                    'error_msg'] = "A challenge with this name already exists."
            else:
                challenge = Challenge.create_challenge(name, 'SomeFlag', user,
                                                       100, category)
                try:
                    backend.create_challenge(challenge, user)
                except Exception as e:
                    challenge.delete()
                    raise e
                return redirect("challenges:edit", challenge_id=challenge.id)
        else:
            context['error_msg'] = "Bad data"
    else:
        form = CreateChallengeForm()
    context['form'] = form

    return render(request, 'challenges/create.html', context)
def download(request):
    # Load data
    users = User.objects.filter(is_staff=False).exclude(username='******')
    user_ids = [user.id for user in users]
    submissions = ChallengeSubmission.objects.all()
    challenges = Challenge.all_published()

    # Create the zip file
    zipped_file = io.BytesIO()
    with zipfile.ZipFile(zipped_file, 'w', zipfile.ZIP_DEFLATED) as zipped:
        user_header = ['id', 'username', 'first_name', 'last_name', 'email', 'classes']
        user_values = [[u.id, u.username, u.first_name, u.last_name, u.email, LIST_DELIMITER.join(c.name for c in u.class_set.all())] for u in users]
        zipped.writestr('users.csv', csv_str(user_header, user_values))

        submission_header = ['author_id', 'challenge_id', 'created', 'result']
        date_fmt = '%Y-%m-%d:%H:%M:%S'
        submission_values = [[s.author_id, s.challenge_id, s.created.strftime(date_fmt), s.result] for s in submissions if s.author_id in user_ids]
        zipped.writestr('submissions.csv', csv_str(submission_header, submission_values))

        challenge_header = ['id', 'title', 'problem', 'tags']
        challenge_values = [[c.id, c.title, c.problem, LIST_DELIMITER.join([str(t) for t in c.tags.all()])] for c in challenges]
        zipped.writestr('challenges.csv', csv_str(challenge_header, challenge_values))

    zipped_file.seek(0)
    response = HttpResponse(zipped_file, content_type='application/zip')
    response['Content-Disposition'] = 'attachment; filename=report_data.zip'
    return response
Exemple #12
0
    def post(self, request, challenge: Challenge, submission: Submission,
             submission_comment: SubmissionComment, *args, **kwargs):
        if challenge.id != submission.challenge_id:
            return Response(
                status=400,
                data={
                    'error':
                    f'Submission {submission.id} does not belong to Challenge {challenge.id}'
                })
        if submission_comment.submission_id != submission.id:
            return Response(
                status=400,
                data={
                    'error':
                    f'Comment {submission_comment.id} does not belong to Submission {submission.id}'
                })
        # validate that the current User is either the author or has solved it perfectly
        if submission.author_id != request.user.id and not challenge.is_solved_by_user(
                request.user):
            # User has not fully solved this and as such does not have access to the solution
            return Response(
                data={'error': 'You have not fully solved the challenge'},
                status=401)

        ser = SubmissionCommentSerializer(data=request.data)
        if not ser.is_valid():
            return Response(data={'error': ser.errors}, status=400)

        submission_comment.add_reply(author=request.user,
                                     content=request.data['content'],
                                     to_notify=True)

        return Response(status=201)
Exemple #13
0
    def post(self, request, challenge: Challenge, submission: Submission,
             *args, **kwargs):
        ser = SubmissionCommentSerializer(data=request.data)
        if not ser.is_valid():
            return Response(status=400,
                            data={'error': 'Invalid comment content!'})
        if submission.challenge_id != challenge.id:
            return Response(
                status=400,
                data={
                    'error':
                    f'Submission with ID {submission.id} does not belong to Challenge with ID {challenge.id}'
                })
        # validate that the current User is either the author or has solved it perfectly
        if submission.author_id != request.user.id and not challenge.is_solved_by_user(
                request.user):
            # User has not fully solved this and as such does not have access to the solution
            return Response(
                data={'error': 'You have not fully solved the challenge'},
                status=401)

        self.add_comment(submission=submission,
                         author=request.user,
                         content=request.data['content'])

        return Response(status=201)
 def test_cannot_save_duplicate_challenge(self):
     c = Challenge.objects.create(name='Hello',
                                  difficulty=5,
                                  score=10,
                                  test_case_count=5,
                                  category=self.sub_cat,
                                  description=self.sample_desc)
     c.save()
     with self.assertRaises(ValidationError):
         c = Challenge(name='Hello',
                       difficulty=5,
                       score=10,
                       test_case_count=5,
                       category=self.sub_cat,
                       description=self.sample_desc)
         c.full_clean()
Exemple #15
0
def createChallenge(request):
    context = standardContext(request)
    user = User.from_authuser(request.user)

    if not user.allow_create:
        raise exceptions.PermissionDenied()

    if request.method == "POST":
        form = CreateChallengeForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['challenge_name'].strip()
            category = form.cleaned_data['category']
            if Challenge.objects.filter(name=name).count() > 0:
                context['error_msg'] = "A challenge with this name already exists."
            else:
                challenge = Challenge.create_challenge(name, 'SomeFlag', user, 100, category)
                try:
                    backend.create_challenge(challenge, user)
                except Exception as e:
                    challenge.delete()
                    raise e
                return redirect("challenges:edit", challenge_id=challenge.id)
        else:
            context['error_msg'] = "Bad data"
    else:
        form = CreateChallengeForm()
    context['form'] = form

    return render(request, 'challenges/create.html', context)
Exemple #16
0
def list_challenges(request):
    challenges = Challenge.objects.all()
    solved = request.session.get('solved', [])
    points = Challenge.total_points(solved)
    context = {
        'challenges': challenges, 'solved': set(solved), 'points': points
    }
    return render(request, 'challenges/list.html', context)
Exemple #17
0
def makeChallenges():
    ctf_categories = ['Web', 'Pwn', 'Crypto', 'Reverse', 'Triva', 'Script']
    ctf_challenge_points = [100, 200, 300, 400, 500]

    for category in ctf_categories:
        cat = Category.objects.get(name=category)
        for challenge_points in ctf_challenge_points:
            chal_str = "%s %s" % (category, str(challenge_points))
            chal = Challenge(category=cat,
                             name=chal_str,
                             description="{0} challenge".format(chal_str),
                             points=challenge_points,
                             hidden=True)
            chal.save()
            flag = Flag(value=hashlib.md5('flag'.encode('utf-8')).hexdigest(),
                        challenge=chal)
            flag.save()
Exemple #18
0
def add_challenge():
    host_user, host_team = get_team_and_host()
    ChallengeHost.objects.create(user=host_user, team_name=host_team, status=ChallengeHost.SELF, permissions=ChallengeHost.ADMIN)
    challenge_zip = open(
        os.path.join(settings.BASE_DIR, 'forest_clfy_challenge/challenge_config.zip'), 'rb'
    )
    challenge = Challenge.load_from_zip(challenge_zip, host_team)
    challenge.approved_by_admin = True
    challenge.save()
Exemple #19
0
    def mutate(self, info, name, description, category, flag, precomputed, hashed, points=0, encoded=False, hidden=False):
        validate_user_is_admin(info.context.user)
        get_category = Category.objects.get(name=category)
        
        newChallenge = Challenge(name=name, description=description, encoded=encoded, points=points, hidden=hidden, category=get_category)
        newChallenge.save()

        if hashed:
            if precomputed:
                flag = Flag(value=flag, challenge=newChallenge)
            else:
                flag = Flag(value=hashlib.sha256(flag.encode('utf-8')).hexdigest(), challenge=newChallenge)
        else:
            flag = Flag(value=flag, challenge=newChallenge)

        flag.save()

        return AddChallenge(code=0)
Exemple #20
0
def create_challenge(
    title,
    start_date,
    end_date,
    host_team,
    participant_host_team,
    anon_leaderboard=False,
    is_featured=False,
):
    """
    Creates a challenge.
    """
    evaluation_script = open(
        os.path.join(
            settings.BASE_DIR,
            "examples",
            "example1",
            "sample_evaluation_script.zip",
        ),
        "rb",
    )
    queue = "".join(random.choice(string.ascii_letters) for _ in range(75))
    year = datetime.date.today().year
    # add UUID here
    uuid_stamp = uuid.uuid4().hex[0:10]
    slug = "{t}-{y}-{z}".format(t=title, y=year, z=uuid_stamp)
    slug = slug.lower().replace(" ", "-")[:198]
    image_file = ContentFile(get_file_content(CHALLENGE_IMAGE_PATH, "rb"),
                             "logo.png")
    challenge = Challenge(
        title=title,
        short_description=fake.paragraph(),
        description=fake.paragraph(),
        terms_and_conditions=fake.paragraph(),
        submission_guidelines=fake.paragraph(),
        evaluation_details=fake.paragraph(),
        evaluation_script=SimpleUploadedFile(evaluation_script.name,
                                             evaluation_script.read()),
        approved_by_admin=True,
        leaderboard_description=fake.paragraph(),
        creator=host_team,
        published=True,
        enable_forum=True,
        anonymous_leaderboard=anon_leaderboard,
        start_date=start_date,
        end_date=end_date,
        queue=queue,
        featured=is_featured,
        image=image_file,
    )
    challenge.save()

    challenge.slug = slug
    challenge.participant_teams.add(participant_host_team)
    challenge.save()

    print(
        "Challenge created with title: {} creator: {} start_date: {} end_date: {}"
        .format(title, host_team.team_name, start_date, end_date))
Exemple #21
0
def list_challenges(request):
    challenges = Challenge.objects.all()
    solved = request.session.get('solved', [])
    points = Challenge.total_points(solved)
    context = {
        'challenges': challenges,
        'solved': set(solved),
        'points': points
    }
    return render(request, 'challenges/list.html', context)
Exemple #22
0
def view_dashboard(request, me):
    announcements = []
    try:
        board = DiscussionBoard.objects.get(slug="news")
        topics = list(DiscussionTopic.objects.filter(board=board, hidden=False))[:5]
        for t in topics:
            announcements.append( (DiscussionPost.objects.filter(topic=t, hidden=False)[0]) )
    except: pass
    return render(request,
                  "dashboard.html",
                  {'challenges': Challenge.show_for(me),
                   'announcements': announcements,
                   'alerts': request.session.pop('alerts', []) })
def _make_add_or_change_context(extra_context, class_id=None):
    extra_context = extra_context or {}
    challenges = Challenge.all_published()
    blocks = ChallengeBlock.objects.filter(block_class__id=class_id)
    unavailable_challenges_ids = set(
        [c['id'] for b in blocks for c in b.challenges.values()])
    available_challenges = [
        c for c in challenges if c.id not in unavailable_challenges_ids
    ]
    extra_context['challenges'] = challenges
    extra_context['blocks'] = blocks
    extra_context['available_challenges'] = available_challenges
    return extra_context
Exemple #24
0
    def mutate(self,
               info,
               name,
               description,
               points=0,
               flag="",
               show=False,
               category=None):
        validate_user_is_admin(info.context.user)

        try:
            if category:
                try:
                    category = Category.objects.get(name=category)
                    newChallenge = Challenge(name=name,
                                             description=description,
                                             points=points,
                                             show=show,
                                             category=category)
                    newChallenge.save()
                    flag = Flag(value=hashlib.md5(
                        flag.encode('utf-8')).hexdigest(),
                                challenge=newChallenge)
                    flag.save()
                except:
                    # Category not found
                    message = "failure"
            else:
                newChallenge = Challenge(name=name,
                                         description=description,
                                         points=points,
                                         show=show)
                newChallenge.save()
                flag = Flag(value=flag, challenge=newChallenge)
                flag.save()

            message = "success"
        except:
            message = "failure"

        return AddChallenge(message)
Exemple #25
0
def user_profile(request, username):
    try: student = User.objects.get(username=username).student
    except exceptions.ObjectDoesNotExist:
        request.session["alerts"].append(("alert-error","That user does not exist."))
        return redirect("index")
    me = Student.from_request(request)
    
    if request.method == "POST":
        if me.ta and "ban" in request.POST:
            student.banned = not student.banned
            student.agreed = False
            student.save()
        return redirect("profile", username=username)
    
    return render(request,
                  "profile.html",
                  {'student': student,
                   'challenges': Challenge.show_for(student),
                   'published': CodeSubmission.objects.filter(published__gt=0, student=student).order_by('-timestamp'),
                   'alerts': request.session.pop('alerts', []) })
Exemple #26
0
def insertChallengeBoard():
    i = 1
    # Push test challenges to rethinkdb database
    connection = r.connect(host=RDB_HOST, port=RDB_PORT)
    try:
        for category in Category.objects.all():
            # Save the challenge flag to the database
            challenge_50 = Challenge(category=category,
                                     flag="flag{0}".format(i),
                                     points=50,
                                     title='Test Title',
                                     description='Test Description',
                                     hosted=True,
                                     fileUpload=False,
                                     imageName='tutum/hello-world:latest',
                                     ports='80',
                                     pathPrefix="path{0}".format(i))
            challenge_50.save()
            i += 1

            # Save the challenge flag to the database
            challenge_100 = Challenge(category=category,
                                      flag="flag{0}".format(i),
                                      points=100,
                                      title='Test Title',
                                      description='Test Description',
                                      hosted=True,
                                      fileUpload=False,
                                      imageName='tutum/hello-world:latest',
                                      ports='80',
                                      pathPrefix="path{0}".format(i))
            challenge_100.save()
            i += 1

            # Save the challenge flag to the database
            challenge_200 = Challenge(category=category,
                                      flag="flag{0}".format(i),
                                      points=200,
                                      title='Test Title',
                                      description='Test Description',
                                      hosted=True,
                                      fileUpload=False,
                                      imageName='tutum/hello-world:latest',
                                      ports='80',
                                      pathPrefix="path{0}".format(i))
            challenge_200.save()
            i += 1

            # Save the challenge flag to the database
            challenge_300 = Challenge(category=category,
                                      flag="flag{0}".format(i),
                                      points=300,
                                      title='Test Title',
                                      description='Test Description',
                                      hosted=False,
                                      fileUpload=True)
            challenge_300.save()
            i += 1

            # Save the challenge flag to the database
            challenge_400 = Challenge(category=category,
                                      flag="flag{0}".format(i),
                                      points=400,
                                      title='Test Title',
                                      description='Test Description',
                                      hosted=False,
                                      fileUpload=False)
            challenge_400.save()
            i += 1

            # Save the challenge flag to the database
            challenge_500 = Challenge(category=category,
                                      flag="flag{0}".format(i),
                                      points=500,
                                      title='Test Title',
                                      description='Test Description',
                                      hosted=False,
                                      fileUpload=False)
            challenge_500.save()
            i += 1

            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_50.id,
                'category':
                challenge_50.category.id,
                'title':
                'Test Title',
                'points':
                challenge_50.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                True,
                'fileUpload':
                False,
                'imageName':
                'tutum/hello-world:latest',
                'ports':
                '80',
                'pathPrefix':
                challenge_50.pathPrefix,
                'created':
                format(challenge_50.created, 'U')
            }).run(connection)
            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_100.id,
                'category':
                challenge_100.category.id,
                'title':
                'Test Title',
                'points':
                challenge_100.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                True,
                'fileUpload':
                False,
                'imageName':
                'tutum/hello-world:latest',
                'ports':
                '80',
                'pathPrefix':
                challenge_100.pathPrefix,
                'created':
                format(challenge_100.created, 'U')
            }).run(connection)
            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_200.id,
                'category':
                challenge_200.category.id,
                'title':
                'Test Title',
                'points':
                challenge_200.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                True,
                'fileUpload':
                False,
                'imageName':
                'tutum/hello-world:latest',
                'ports':
                '80',
                'pathPrefix':
                challenge_200.pathPrefix,
                'created':
                format(challenge_200.created, 'U')
            }).run(connection)
            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_300.id,
                'category':
                challenge_300.category.id,
                'title':
                'Test Title',
                'points':
                challenge_300.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                False,
                'fileUpload':
                True,
                'created':
                format(challenge_300.created, 'U')
            }).run(connection)
            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_400.id,
                'category':
                challenge_400.category.id,
                'title':
                'Test Title',
                'points':
                challenge_400.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                False,
                'fileUpload':
                False,
                'created':
                format(challenge_400.created, 'U')
            }).run(connection)
            r.db(CTF_DB).table('challenges').insert({
                'sid':
                challenge_500.id,
                'category':
                challenge_500.category.id,
                'title':
                'Test Title',
                'points':
                challenge_500.points,
                'description':
                'Test Description',
                'solved_count':
                0,
                'hosted':
                False,
                'fileUpload':
                False,
                'created':
                format(challenge_500.created, 'U')
            }).run(connection)

    except RqlRuntimeError as e:
        raise Exception('Error adding challenges to realtime database: %s' %
                        (e))
    finally:
        connection.close()
Exemple #27
0
def bulk_update(request: HttpRequest):
    try:
        challenges_data = json.loads(request.body.decode())
        challenges = challenges_data["challenges"]
    except Exception:
        logger.exception("Couldn't load json")
        return JsonResponse({"message": "Couldn't load json data"}, status=400)

    try:
        assert isinstance(challenges, list)
        assert len(challenges) > 0 and isinstance(challenges[0], dict)
    except AssertionError:
        logger.exception(
            "Expected a list of dict, representing the challenges")
        return JsonResponse(
            {
                "message":
                "Expected a list of dict, representing the challenges"
            },
            status=400)

    try:
        challenge_slugs = {chal["slug"] for chal in challenges}
        assert len(challenge_slugs) == len(challenges)
    except (KeyError, AssertionError):
        return JsonResponse(
            {
                "message":
                "`slug` should be present and unique in all challenges"
            },
            status=400)

    expected_data = """Challenges should be of this form (following documentation may not be up to date): {
              "difficulty": 0-4 (0 easier, 4 harder),
              "name": "bla bla" (len<50),
              "slug": "bla-bla" (extracted from name, identifies the challenge),
              "description": "Fun story in html",
              "category": Any of: "MIC", "WEB", "PPC", "FOR", "REV", "PWN", "CRY", "NET",
              "flag": "INSA{the flag}" (len<=255),
              "static_url": null OR "url of the static files for the chal",
              "company_logo_url": null OR "the URL of the company who wrote the chal, if any",
              "nb_points_override": integer, if greater then -3, it will override the automagic points calculus 
            }"""

    for chal in challenges:
        try:
            difficulty = chal["difficulty"]
            name = chal["name"]
            slug = chal["slug"]
            description = chal["description"]
            category = chal["category"]
            flag = sha256(chal["flag"].encode('utf-8')).hexdigest()
            static_url = chal["static_url"]
            company_logo_url = chal["company_logo_url"]
            nb_points_override = chal["nb_points_override"]
        except KeyError:
            logger.exception("Wrong challenge format")
            return JsonResponse({"message": expected_data}, status=400)

        try:
            try:
                chal = Challenge.all_objects.get(slug=slug)
                chal.difficulty = difficulty
                chal.name = name
                chal.description = description
                chal.category = category
                chal.flag = flag
                chal.static_url = static_url
                chal.company_logo_url = company_logo_url
                chal.nb_points_override = nb_points_override
                chal.full_clean()
                chal.save()
            except ObjectDoesNotExist:
                chal = Challenge(difficulty=difficulty,
                                 name=name,
                                 slug=slug,
                                 description=description,
                                 category=category,
                                 flag=flag,
                                 static_url=static_url,
                                 company_logo_url=company_logo_url,
                                 nb_points_override=nb_points_override)
                chal.full_clean()
                chal.save()
        except ValidationError as e:
            logger.exception("Wrong challenge format")
            return JsonResponse(
                {
                    "message":
                    "Challenge `{}` doesn't have the right form: {}.\n{}".
                    format(name, e, expected_data)
                },
                status=400)
        except Exception as e:
            logger.exception("Exception creating the challenge")
            return JsonResponse(
                {
                    "message":
                    "Error while updating {}, please check the serverlogs. err: {}"
                    "\nFor reference: {}".format(name, e, expected_data)
                },
                status=500)

    Challenge.all_objects.exclude(slug__in=challenge_slugs).delete()
    return JsonResponse({"message": "OK"}, status=200)
    def setUp(self):
        super().setUp()
        ch4 = Challenge(title='Challenge 4', external_id=12, start_date=date(2020, 6, 1), end_date=date(2020, 6, 30))
        ch5 = Challenge(title='Challenge 5', external_id=13, start_date=date(2018, 1, 1), end_date=date(2018, 1, 30))
        ch6 = Challenge(title='Challenge 6', external_id=14)
        ch4.save()
        ch5.save()
        ch6.save()

        datetime_patch = patch('challenges.views.timezone')
        self.timezone_mock = datetime_patch.start()
        self.timezone_mock.now.return_value = datetime(2020, 2, 25)
        datetime2_patch = patch('challenges.models.challenge.timezone')
        self.timezone2_mock = datetime2_patch.start()
        self.timezone2_mock.now.return_value = datetime(2020, 2, 25)
 def test_cannot_save_blank_challenge(self):
     c = Challenge()
     with self.assertRaises(Exception):
         c.full_clean()
Exemple #30
0
def insertRealChallenges():
    connection = r.connect(host=RDB_HOST, port=RDB_PORT)
    try:
        with open('challenges.json') as f:
            data = json.load(f)
            for c in data:
                category = Category.objects.filter(
                    name__icontains=c['category'])
                if c['hosted']:
                    challenge = Challenge(category=category[0],
                                          flag=c['flag'],
                                          points=c['points'],
                                          title=c['title'],
                                          description=c['description'],
                                          hosted=c['hosted'],
                                          fileUpload=c['fileUpload'],
                                          imageName=c['imageName'],
                                          ports=c['ports'],
                                          pathPrefix=c['pathPrefix'])
                else:
                    challenge = Challenge(category=category[0],
                                          flag=c['flag'],
                                          points=c['points'],
                                          title=c['title'],
                                          description=c['description'],
                                          hosted=c['hosted'],
                                          fileUpload=c['fileUpload'])
                challenge.save()

                if c['hosted']:
                    r.db(CTF_DB).table('challenges').insert({
                        'sid':
                        challenge.id,
                        'category':
                        challenge.category.id,
                        'title':
                        c['title'],
                        'points':
                        challenge.points,
                        'description':
                        c['description'],
                        'solved_count':
                        0,
                        'hosted':
                        c['hosted'],
                        'fileUpload':
                        c['fileUpload'],
                        'imageName':
                        c['imageName'],
                        'ports':
                        c['ports'],
                        'pathPrefix':
                        c['pathPrefix'],
                        'created':
                        format(challenge.created, 'U')
                    }).run(connection)
                else:
                    r.db(CTF_DB).table('challenges').insert({
                        'sid':
                        challenge.id,
                        'category':
                        challenge.category.id,
                        'title':
                        c['title'],
                        'points':
                        challenge.points,
                        'description':
                        c['description'],
                        'solved_count':
                        0,
                        'hosted':
                        c['hosted'],
                        'fileUpload':
                        c['fileUpload'],
                        'created':
                        format(challenge.created, 'U')
                    }).run(connection)

    except RqlRuntimeError as e:
        raise Exception('Error adding challenges to realtime database: %s' %
                        (e))
    finally:
        connection.close()
    def test_subcategory_max_score_is_updated(self):
        """
        Test if the SubCategory's max score is updated on Challenge creation
        This is done to capture the fact that sometimes we'll have new challenges added or removed and
        it needs to reflex the max score in a subcategory
        """
        c1 = Challenge(name='Sub1', difficulty=5, score=200, description=ChallengeDescFactory(),
                       test_case_count=5, category=self.sub1)
        c2 = Challenge(name='Sub1_2', difficulty=5, score=200, description=ChallengeDescFactory(),
                       test_case_count=5, category=self.sub1)
        c3 = Challenge(name='Sub2', difficulty=5, score=200, description=ChallengeDescFactory(),
                       test_case_count=5, category=self.sub2)
        c1.save(); c2.save(); c3.save()

        self.sub1.refresh_from_db()
        self.sub2.refresh_from_db()
        self.sub3.refresh_from_db()
        self.assertEqual(self.sub1.max_score, 400)
        self.assertEqual(self.sub2.max_score, 200)
        self.assertEqual(self.sub3.max_score, 0)
Exemple #32
0
def list_challenges(request):
    challenges = Challenge.objects.all()
    solved, points = Challenge.solved_by_user(request.user)
    context = {'challenges': challenges, 'solved': solved, 'points': points}

    return render(request, 'challenges/list.html', context)
Exemple #33
0
    def mutate(self, info, category, title, points, description, flag, hosted, ports, image_name=None, upload=None):
        user = info.context.user
        # Validate user is admin
        validate_user_is_admin(user)

        # sanitize all the input fields
        validate_flag(flag)
        validate_flag_unique(flag)
        validate_points(points)
        validate_title(title)
        validate_description(description)
        validate_category_exists(category)
        if image_name:
            validate_imageName(image_name)
        if ports:
            validate_ports(ports)
        # if path_prefix:
        #     validate_pathPrefix(path_prefix)
        #     validate_pathPrefix_unique(path_prefix)

        # parse dockerfile for list of ports
        if upload:
            try:
                ports = list()
                for line in upload:
                    line = line.decode('utf-8')
                    start = 'EXPOSE '

                    if (start in line):
                        possible_port = (line[line.find(start)+len(start):])
                        ports.append(possible_port.split())

                # flatten list
                flattened_ports = list(
                    set([val for sublist in ports for val in sublist]))
                print(flattened_ports)

            except Exception as e:
                raise Exception('Error parsing uploaded Dockerfile: ', e)

        challenge_category = Category.objects.get(id=category)

        # Save the challenge flag to the database
        challenge = Challenge(category=challenge_category, title=title, description=description,
                              flag=flag, points=points, hosted=hosted, imageName=image_name, ports=ports)
        challenge.save()

        # set var for pathPrefix and tag
        path_tag = str(challenge.id)
        challenge.pathPrefix = path_tag

        if upload:
            image_name = path_tag + ':latest'

            # build image
            build = d.buildImage(fileobj=upload.file, tag=path_tag)

            # delete already saved challenge if build fails
            if not build:
                chall_id = challenge.id
                try:
                    challenge.delete()
                except:
                    # raise exception if unable to delete already saved challenge requiring manual intervention
                    raise Exception(
                        'Unable to delete challenge ID: %i. Manual deletion necessary.' % (chall_id))

                raise Exception(
                    'Unable to build image.  Reverted challenge creation.')

            challenge.upload = upload
            challenge.imageName = image_name

        challenge.save()

        # Push the realtime data to rethinkdb
        connection = r.connect(host=RDB_HOST, port=RDB_PORT)
        try:
            r.db(CTF_DB).table('challenges').insert({'sid': challenge.id, 'category': challenge.category.id, 'title': title, 'points': points, 'description': description,
                                                     'hosted': hosted, 'imageName': image_name, 'ports': ports, 'pathPrefix': path_tag, 'created': format(challenge.created, 'U')}).run(connection)
        except RqlRuntimeError as e:
            raise Exception(
                'Error adding challenge to realtime database: %s' % (e))
        finally:
            connection.close()

        return AddChallenge(status='Challenge Created')
 def handle(self, *args, **options):
     if len(args) < 1:
         self.stderr.write('Please provide a directory containing the files '+
                           'relative to PROJECT_DIR.')
     
     base_dir = os.path.join(settings.PROJECT_DIR, '..', args[0])
     
     # Go through all of the challenges and compile them. This will update
     # existing challenges and add new ones.
     for slug in os.listdir( os.path.join(base_dir) ):
         try:
             data = ""
             f = open(os.path.join(base_dir, slug))
             data = f.read()
             f.close()
             
             # If the challenge is already there, update it!
             try: c = Challenge.objects.get(slug=slug)
             except: c = Challenge(slug=slug)
             
             c.description = ""
             c.preamble = ""
             c.postamble = ""
             c.autograde = ""
             
             stage = "description"
             for l in data.splitlines():
                 if l.startswith("%% "):
                     l = l[3:].strip()
                     if l.startswith("name:"): c.name = l[5:].strip()
                     elif l.startswith("pattern:"): c.pattern = Pattern.objects.get(name=l[8:].strip())
                     elif l.startswith("autograde:"): c.autograde = l[10:].strip()
                     elif l.startswith("ordering:"): c.ordering = int(l[9:].strip())
                 elif l.startswith("% "):
                     stage = l[2:].strip()
                 elif stage == "description": c.description += l+"\n"
                 elif stage == "preamble": c.preamble += l+"\n"
                 elif stage == "postamble": c.postamble += l+"\n"
             c.save()
             self.stdout.write('Wrote challenge: %s\n'%(slug))
             
         except: self.stderr.write('Skipped challenge: %s\n'%(slug))
     
     self.stdout.write('Successfully compiled challenges!\n')
Exemple #35
0
    def setUp(self):
        self.ch1_start = date(2020, 2, 1)
        self.ch1_end = date(2020, 3, 15)
        ch0 = Challenge(title='Challenge 0',
                        external_id=4,
                        start_date=date(2019, 11, 20),
                        end_date=date(2019, 11, 25))
        ch1 = Challenge(title='Challenge 1',
                        external_id=5,
                        start_date=self.ch1_start,
                        end_date=self.ch1_end)
        ch2 = Challenge(title='Challenge 2',
                        external_id=6,
                        start_date=date(2020, 2, 10),
                        end_date=date(2020, 2, 29))
        ch3 = Challenge(title='Challenge 3',
                        external_id=2,
                        start_date=date(2019, 6, 1),
                        end_date=date(2019, 6, 30))
        ch0.save()
        ch1.save()
        ch2.save()
        ch3.save()
        t1 = Team(name='Team A', challenge=ch1)
        t2 = Team(name='Team B', challenge=ch1)
        t3 = Team(name='Team C', challenge=ch2)
        t1.save()
        t2.save()
        t3.save()
        comp1 = Competitor(external_id=10, name='Competitor 1')
        comp2 = Competitor(external_id=20, name='Competitor 2')
        comp3 = Competitor(external_id=25,
                           name='Competitor 3',
                           display_name='Competitor C')
        comp4 = Competitor(external_id=26, name='Competitor 4')
        comp5 = Competitor(external_id=27, name='Competitor 5')
        comp6 = Competitor(external_id=28, name='Competitor 6')
        comp7 = Competitor(external_id=29, name='Competitor 7')
        comp1.save()
        comp2.save()
        comp3.save()
        comp4.save()
        comp5.save()
        comp6.save()
        comp7.save()
        comp1.teams.add(t1)
        comp3.teams.add(t1)
        comp4.teams.add(t1)
        comp5.teams.add(t3)
        comp6.teams.add(t2)
        comp7.teams.add(t2)
        comp1.save()
        comp3.save()
        comp4.save()
        comp5.save()
        comp6.save()
        comp7.save()

        comp1_stats = Stats(calories=1001, competitor=comp1, challenge=ch1)
        comp2_stats = Stats(calories=500, competitor=comp3, challenge=ch1)
        comp5_stats = Stats(calories=2000, competitor=comp5, challenge=ch2)
        comp6_stats = Stats(calories=100, competitor=comp6, challenge=ch1)
        comp7_stats = Stats(calories=20, competitor=comp7, challenge=ch1)
        comp1_stats.save()
        comp2_stats.save()
        comp5_stats.save()
        comp6_stats.save()
        comp7_stats.save()
Exemple #36
0
        cap.save()

    for cat in data['board']['categories']:
        print(cat['name'])

        ca = Category(name=cat['name'], description=cat['description'])
        ca.save()
        '''
            Challenge create. 
            Required: Category, Name, Description, Points, Flag 
        '''
        for challenge in cat['challenges']:
            print(" |--", challenge['name'])

            if challenge['name'] and challenge['description'] and challenge[
                    'points'] and challenge['flag']:
                chal = Challenge(category=ca,
                                 name=challenge['name'],
                                 description=challenge['description'],
                                 points=challenge['points'],
                                 hidden=False)
                chal.save()
                flag_v = compute_flag(challenge['flag'])
                flag = Flag(value=flag_v,
                            hashed=challenge['flag']['hashed'],
                            challenge=chal)
                flag.save()
            else:
                print("Failed", challenge)
                exit()