diff --git a/documentation/docs/Developers_and_Administrators/Robot-submissions.md b/documentation/docs/Developers_and_Administrators/Robot-submissions.md deleted file mode 100644 index edb4fda3e..000000000 --- a/documentation/docs/Developers_and_Administrators/Robot-submissions.md +++ /dev/null @@ -1,257 +0,0 @@ -This script is designed to test the Robot Submissions feature. Robot users should be able to submit to bot-enabled competitions without being admitted as a participant. - -This article will explain how to make a robot submission on your local computer, and how to present the results on the Leaderboard. - -## Pre-requisite -- Python 3 -- Demo bundle: autowsl -- Github download [URL](https://github.com/codalab/competitions-v2/tree/codabench/sample_bundle/src/tests/functional/test_files/AutoWSL_sample) - -![demo bundle](../_attachments/102425038-7d102d80-4047-11eb-9d67-4590426e91f0_17528513079491048.png) - -- Robot submission sample script here: [link](https://github.com/codalab/competitions-v2/tree/develop/docs/example_scripts) - -Brief description for demo bundle: - -- `code_submission`: It contains the sample bundle for the code submission and the code solution for the submission. - - `auto_wsl_code_submission.zip`:This bundle is used for making submission. - - `new_v18_code_mul_mul.zip`: The bundle is multiple phases, each phase has multiple tasks, and between these tasks, they share the same scoring program, that is, there is no need to copy multiple scoring program for hardcode. - - `new_v18_code_mul_mul_sep_scoring.zip`: This bundle is multiple phases, multiple tasks under each phase share a scoring program that is exclusive to their particular phase. - - `new_v18_code_sin_mul.zip`: This is the sample bundle of a single phase multi-task that shares the same scoring program. -![image](../_attachments/102425514-73d39080-4048-11eb-8689-c21d6d1ae4ac_1752851307966413.png) - -- `dataset_submission`: It contains the sample bundle for data submission and the corresponding dataset solution for submission. - - `AutoWSL_dataset_submission.zip`: This is the bundle used for dataset submissions. - - `new_v18_dataset_mul_mul.zip`:This is a multi-phase, each phase has multiple tasks below the sample bundle, multiple tasks, using the same scoring program, do not need to copy multiple scoring program for hardcode - - `new_v18_dataset_mul_mul_sep_scoring.zip`: This is a multi-phase, each phase has multiple tasks below the sample bundle, the task between the different phases, using a different scoring program, that is, each phase has its own independent scoring program. - - `new_v18_dataset_sin_mul.zip`: This is a sample bundle of single-phase multi-task commit datasets. -![image](../_attachments/102425665-b72dff00-4048-11eb-9b65-caa05e2f409d_17528513079724836.png) - -## Getting started - -### Upload a bundle -Use the sample bundle provided above to upload the bundle and create a competition -![image](../_attachments/102425747-e8a6ca80-4048-11eb-9d2d-09a59f63df09_1752851307954863.png) - -### Set the competition to allow robot submissions -On the created competition page, click the EDIT button - -![image](../_attachments/102425807-08d68980-4049-11eb-96ef-2220a7a70bda_17528513079972107.png) - -Then click on the Participation tab, then scroll down to the bottom and click on Allow robot submission and click SAVE button. - -![image](../_attachments/102425846-20157700-4049-11eb-93ed-e38e4db91611_17528513080323348.png) -![image](../_attachments/102425904-43d8bd00-4049-11eb-86c2-870d743baa00_17528513080195067.png) - -After the above steps are done, the Competition is allowed for making robot submission. - -### Set yourself to Is bot -Go to the backend administration page, PROFILES tab bar below the user - -![image](../_attachments/102426012-7b476980-4049-11eb-96f9-f88d716ed4ea_17528513080236058.png) -![image](../_attachments/102426040-8a2e1c00-4049-11eb-9477-3b1b128ef0ef_17528513080496614.png) - -Check the `is bot` box, click save. You can now proceed with your robot submissions. - -### Change CODALAB_URL address -Change CODALAB_URL address in following scripts:`get_competition_details.py`, `example_submission.py`, `get_submission_details.py` -CODALAB_URL = 'https://www.codabench.org/' - -> Find scripts at `docs/example_scripts` - -### Choose the competition -Run the following command on the command line: `python3 get_competition_details.py` -What you're about to see is something like this -![image](../_attachments/102426221-e5600e80-4049-11eb-95ed-3abf37ffd1d5_1752851308257055.png) - -Choose the ID of the competition you are interested in, for example 127. -![image](../_attachments/102426259-f6a91b00-4049-11eb-8e73-54bcd0514099_17528513080718298.png) - -Run the script again with the competition ID as a parameter -`python3 get_competition_details.py 127` -Then you will see the following -![image](../_attachments/102426306-0c1e4500-404a-11eb-8e0a-a056cd9ffdab_17528513080908906.png) - -You can select the phase ID you're interested in, then use it as the second argument and run the script again, this time you'll get the task information associated with that phase. -`python3 get_competition_details.py 127 215` -![image](../_attachments/102426338-1f311500-404a-11eb-9a85-42cfa7b4f34c_17528513081201243.png) - -### Making submission -Inside the `example_submission.py` script, configure these options: -![image](../_attachments/102426374-340da880-404a-11eb-8bf0-e62498560c38_17528513081279504.png) - -- `CODALAB_URL` can be changed if not testing locally. -- `USERNAME` and `PASSWORD` should correspond with the user being tested. -- `PHASE_ID` should correspond with the phase being tested on. -- `TASK_LIST` can be used to submit to specific tasks on a phase. If left blank, the submission will run on all tasks. -- `SUBMISSION_ZIP_PATH` You can fill in the absolute path of the submission directly. - -The idea here is that I'm going to test all the tasks below the competition with phase ID `215`. -Then run the script. -`python3 example_submission.py` -![image](../_attachments/102426590-91095e80-404a-11eb-9b13-3b04b6d7c05d_17528513084907422.png) - -You can see that you have successfully submitted the submission bundle. - -### View submission details -Configure the` get_submission_details.py` options before running. -![image](../_attachments/102426640-a9797900-404a-11eb-9d28-12fe9b6e9544_17528513081428964.png) - -- `CODALAB_URL` can be changed if not testing locally. -- `USERNAME` and `PASSWORD` should correspond with the user being tested. -Run the `get_submission_details`.py script with the ID of the phase containing the desired submission as the first argument. - -Since we chose `215` for our phase ID above, we'll choose `215` here. - -Then run the script. -`python3 get_submission_details.py 215` -![image](../_attachments/102426710-d29a0980-404a-11eb-9ec7-cb9c1d5cb732_17528513082572203.png) - -Find the ID of the desired submission. For example, `542`. - -Then run the script. -`python3 get_submission_details.py 215 542` -![image](../_attachments/102426762-e7769d00-404a-11eb-9f11-9df1039225a2_17528513086615834.png) - -### Finally -Finally, you can go to the competition page, add your submission, and add it to the Leaderboard! -![image](../_attachments/102426802-007f4e00-404b-11eb-88c2-305bcb789a5c_1752851308285328.png) - -On the Leaderboard, you can see the score details of each of your tasks. -![image](../_attachments/102426823-0d9c3d00-404b-11eb-8068-d8fe454dcec2_17528513087142718.png) - - -## Using the Scripts: - -### Setup: - -* Create a competition with robot submissions enabled - - [Example competition bundle](https://github.com/codalab/competitions-v2/blob/develop/src/tests/functional/test_files/competition_v2_wheat_code.zip) - - -![Edit Competition Page Allow Bots Checkbox](../_attachments/87486437-3037af00-c5f0-11ea-8edf-e758c969ab84_1752851308355029.jpeg) - -* Create a user and enable the bot user flag on the Django admin page. - -![Admin Page Is Bot Checkbox](../_attachments/87486786-e9968480-c5f0-11ea-997f-b3a875f7f7d1_17528513083605943.jpeg) - ---- - -### get_competition_details.py: - -* Inside the [`get_competition_details.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/get_competition_details.py) script, configure these options: - -![image](../_attachments/89593505-32aeb280-d804-11ea-9262-7594958f1cfe_17528513083898718.png) - -* `CODALAB_URL` can be changed if not testing locally. - -* Run the `get_competition_details` script with no arguments. - -* Find the competition you want to test on. - -* Run the `get_competition_details` script again with the competition ID as the only argument. - -* Find the phase you want to test on. - -* If you want to use the task selection feature, run the script again with the competition ID as the first argument and the phase ID as the second argument. - -* Select the task you would like to run your submission on. - -* Use the phase ID and task IDs to configure `example_submission.py`. - ---- - -### example_submission.py: - -* Inside the [`example_submission.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/example_submission.py) script, configure these options: - -![Submission Example Options](../_attachments/89591433-03497700-d7ff-11ea-8016-517408ba4a4a_17528513083924172.png) - -* `CODALAB_URL` can be changed if not testing locally. - -* `USERNAME` and `PASSWORD` should correspond with the user being tested. - -* `PHASE_ID` should correspond with the phase being tested on. - -* `TASK_LIST` can be used to submit to specific tasks on a phase. If left blank, the submission will run on all tasks. - -* `SUBMISSION_ZIP_PATH` should be changed if testing on anything but the default "Classify Wheat Seeds" competition. An example submission can be found [here](https://github.com/codalab/competitions-v2/blob/develop/src/tests/functional/test_files/submission.zip). - -* Run this script in a python3 environment with `requests` library installed. - ---- - -### get_submission_details.py - -* Configure the [`get_submission_details.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/get_submission_details.py) options before running. - -![Submission Details Options](../_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png) - -* `CODALAB_URL` can be changed if not testing locally. - -* `USERNAME` and `PASSWORD` should correspond with the user being tested. - -* Run the `get_submission_details.py --phase ` script with the ID of the phase containing the desired submission. - -* Find the ID of the desired submission. - -* Run the `get_submission_details.py --submission ` script with the desired submission ID. - * The output of the script should be a submission object and a submission `get_details` object. This data can be used view scores, get prediction results, ect. - -* Run the `get_submission_details.py --submission -v` to save a zip containing previous info plus the original submission and logs. - * `--output ` can be used to choose where to save the zip file. Otherwise, it will be saved in the current directory. ---- - -### rerun_submission.py -Robot users have the unique permission to rerun anyone's submission on a specific task. This enables clinicians to test pre-made solutions on private datasets that exist on tasks that have no competition. - -* Configure the [`rerun_submission.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/rerun_submission.py) options before running. - -![Rerun Submission Options](../_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png) - -* `CODALAB_URL` can be changed if not testing locally. - -* `USERNAME` and `PASSWORD` should correspond with the user being tested. - -### Running the script - -1. Create a competition that allows robots, and create a user marked as a robot - user. Use that username and password below. - - -2. Get into a python3 environment with requests installed - - -3. Review this script and edit the applicable variables, like... - - ``` - CODALAB_URL - USERNAME - PASSWORD - ... - ``` - - -4. Execute the contents of this script with no additional command line arguments with - the command shown below: - - `./rerun_submission.py` - - The script is built to assist the user in the selection of the submission that will be re-run. - - -5. After selecting a submission ID from the list shown in the previous step, add that ID to - the command as a positional argument as shown below. - - `./rerun_submission.py 42` - - The script will assist the user in the selection of a task ID. - - -6. After selecting both a submission ID and a task ID, run the command again with both arguments to - see a demonstration of a robot user re-running a submission on a specific task. - - e.g. - - `./rerun_submission.py 42 a217a322-6ddf-400c-ac7d-336a42863724` diff --git a/documentation/docs/Project_CodaBench_FAQ.md b/documentation/docs/Project_CodaBench_FAQ.md index e6e7f0fb8..3a6d84b53 100644 --- a/documentation/docs/Project_CodaBench_FAQ.md +++ b/documentation/docs/Project_CodaBench_FAQ.md @@ -6,7 +6,7 @@ Codabench benchmarks are aimed at researchers, scientists and other professional ### Can Codabench be privately hosted? -Yes, you can host your own Codabench instance on a private or hosted server (e.g. Azure, GCP or AWS). For more information, see [how to deploy Codabench on your server](Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md) and [local installation](Developers_and_Administrators/Codabench-Installation.md) guide. However, most benchmark organizers do NOT need to run their own instance. If you run a computationally demanding competition, you can hook up your own [compute workers](Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) in the backend very easily. +Yes, you can host your own Codabench instance on a private or hosted server (e.g. Azure, GCP or AWS). For more information, see [how to deploy Codabench on your server](Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md) and [local installation](Developers_and_Administrators/Codabench-Installation.md) guide. However, most benchmark organizers do NOT need to run their own instance. If you run a computationally demanding competition, you can hook up your own [compute workers](Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) in the backend very easily. ### How to change my username? @@ -74,8 +74,3 @@ When deploying a local instance, the email server is not configured by default, ``` Uncomment and fill in SMPT server credentials. A good suggestion if you've never done this is to use [sendgrid](https://sendgrid.com/). - -### Robots and automated submissions? -What about robot policy, reckless, or malicious behavior? -Codabench does not forbid the use of [robots](Developers_and_Administrators/Robot-submissions.md) (bots) to access the website, provided that it is not done with malicious intentions to disturb the normal use and jam the system. A user who abuses their rights by knowingly, maliciously, or recklessly jamming the system, causing the system to crash, causing loss of data, or gaining access to unauthorized data, will be banned from accessing all Codabench services. - diff --git a/documentation/zensical.toml b/documentation/zensical.toml index e69af2918..f1a6b9a54 100644 --- a/documentation/zensical.toml +++ b/documentation/zensical.toml @@ -7,7 +7,6 @@ nav = [ {"Home" = "index.md"}, {"Participants" = [ {"Participating in a Competition" = "Participants/User_Participating-in-a-Competition.md"}, - {"Robot Submissions" = "Developers_and_Administrators/Robot-submissions.md"}, {"List of Current Benchmarks and Competitions" = "https://www.codabench.org/competitions/public/?page=1"} ]}, {"Organizers" = [ diff --git a/src/apps/api/serializers/competitions.py b/src/apps/api/serializers/competitions.py index a0fb14fda..77c4181cd 100644 --- a/src/apps/api/serializers/competitions.py +++ b/src/apps/api/serializers/competitions.py @@ -265,7 +265,6 @@ class Meta: 'make_programs_available', 'make_input_data_available', 'docker_image', - 'allow_robot_submissions', 'competition_type', 'fact_sheet', 'reward', @@ -409,7 +408,6 @@ class Meta: 'make_programs_available', 'make_input_data_available', 'docker_image', - 'allow_robot_submissions', 'competition_type', 'fact_sheet', 'forum', @@ -507,7 +505,6 @@ class Meta: class CompetitionParticipantSerializer(serializers.ModelSerializer): username = serializers.CharField(source='user.username') - is_bot = serializers.BooleanField(source='user.is_bot') email = serializers.CharField(source='user.email') is_deleted = serializers.BooleanField(source='user.is_deleted') @@ -516,7 +513,6 @@ class Meta: fields = ( 'id', 'username', - 'is_bot', 'email', 'status', 'is_deleted', diff --git a/src/apps/api/tests/test_submissions.py b/src/apps/api/tests/test_submissions.py index 895fa142e..ca79fa97a 100644 --- a/src/apps/api/tests/test_submissions.py +++ b/src/apps/api/tests/test_submissions.py @@ -2,7 +2,6 @@ from unittest import mock from django.urls import reverse -from django.utils.timezone import now from rest_framework.test import APITestCase from competitions.models import Submission, CompetitionParticipant @@ -401,103 +400,6 @@ def test_non_org_participant_cannot_make_submission_as_organization(self): assert resp.status_code == 400 -class BotUserSubmissionTests(APITestCase): - def setUp(self): - self.creator = UserFactory(username='creator', password='creator') - self.bot_user = UserFactory(username='bot_user', password='other', is_bot=True) - self.non_bot_user = UserFactory(username='non_bot', password='other') - self.bot_comp = CompetitionFactory(created_by=self.creator, allow_robot_submissions=True) - self.bot_phase = PhaseFactory(competition=self.bot_comp) - self.bot_phase_day_limited = PhaseFactory(competition=self.bot_comp, has_max_submissions=True, max_submissions_per_day=1) - self.bot_phase_person_limited = PhaseFactory(competition=self.bot_comp, has_max_submissions=True, max_submissions_per_person=1) - CompetitionParticipant(user=self.non_bot_user, competition=self.bot_comp, status=CompetitionParticipant.APPROVED).save() - - def test_bot_users_are_automatically_added_to_participants_on_submission(self): - self.client.login(username="bot_user", password="other") - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase.pk,))) - - assert resp.status_code == 200 - assert resp.data["can"] - - def test_bots_can_exceed_max_submissions_per_day(self): - self.client.login(username='bot_user', password='other') - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_day_limited.pk,))) - - assert resp.status_code == 200 - assert resp.data['can'] - - for _ in range(2): - SubmissionFactory( - phase=self.bot_phase_day_limited, - owner=self.bot_user, - status=Submission.SUBMITTED, - secret='7df3600c-1234-5678-bbc8-bbe91f42d875' - ) - - assert Submission.objects.filter(owner=self.bot_user, phase=self.bot_phase_day_limited).count() > self.bot_phase_day_limited.max_submissions_per_day - - def test_bots_can_exceed_max_submissions_per_person(self): - self.client.login(username='bot_user', password='other') - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_person_limited.pk,))) - - assert resp.status_code == 200 - assert resp.data['can'] - - for _ in range(2): - SubmissionFactory( - phase=self.bot_phase_person_limited, - owner=self.bot_user, - status=Submission.SUBMITTED, - secret='7df3600c-1234-5678-bbc8-bbe91f42d875' - ) - - assert Submission.objects.filter(owner=self.bot_user, phase=self.bot_phase_person_limited).count() > self.bot_phase_person_limited.max_submissions_per_person - - def test_non_bot_users_cannot_exceed_max_submissions_per_day(self): - self.client.login(username='non_bot', password='other') - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_day_limited.pk,))) - - assert resp.status_code == 200 - assert resp.data['can'] - - SubmissionFactory( - phase=self.bot_phase_day_limited, - owner=self.non_bot_user, - status=Submission.SUBMITTED, - secret='7df3600c-1234-5678-bbc8-bbe91f42d875', - created_when=now(), - ) - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_day_limited.pk,))) - - assert resp.status_code == 200 - assert not resp.data['can'] - - def test_non_bot_users_cannot_exceed_max_submissions_per_person(self): - self.client.login(username='non_bot', password='other') - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_person_limited.pk,))) - - assert resp.status_code == 200 - assert resp.data['can'] - - SubmissionFactory( - phase=self.bot_phase_person_limited, - owner=self.non_bot_user, - status=Submission.SUBMITTED, - secret='7df3600c-1234-5678-bbc8-bbe91f42d875' - ) - - resp = self.client.get(reverse("can_make_submission", args=(self.bot_phase_person_limited.pk,))) - - assert resp.status_code == 200 - assert not resp.data['can'] - - class TaskSelectionTests(APITestCase): def setUp(self): # Competition and creator @@ -561,40 +463,9 @@ def test_can_re_run_submissions_with_multiple_tasks(self): # Make sure the selected tasks were run in the duplicate submission's children assert list(sub_copy.children.all().order_by('task__pk').values_list('task', flat=True)) == self.sorted_tasks - def test_can_re_run_submissions_with_specific_task_with_bot_user_without_original_submission_secret(self): - bot_user = UserFactory(username="botman", password="botman", is_bot=True) - self.client.login(username=bot_user.username, password="botman") - - pre_existing_sub = Submission.objects.create(**{ - 'phase': self.phase, - 'owner': self.creator, - 'task': self.phase.tasks.first(), - 'data': self.data, - 'status': Submission.FINISHED, - }) - - new_task = TaskFactory() - - query_params = f'task_key={new_task.key}&private=true' - url = f"{reverse('submission-re-run-submission', args=(pre_existing_sub.pk,))}?{query_params}" - - self.creator.is_bot = True - self.creator.save() - - assert not Submission.objects.filter(task=new_task).exists() - - # Mock _send_to_compute_worker so submissions don't actually run - with mock.patch('competitions.tasks._send_to_compute_worker'): - self.client.post(url) - sub = Submission.objects.get(task=new_task) - assert sub.owner == self.creator - assert sub.phase == self.phase - assert sub.data == self.data - assert sub.is_specific_task_re_run - - def test_cannot_re_run_submissions_with_specific_task_without_bot_user(self): - non_bot_user = UserFactory(username="nonbotman", password="nonbotman") - self.client.login(username=non_bot_user.username, password="nonbotman") + def test_cannot_re_run_submissions_with_specific_task_without_permission(self): + other_user = UserFactory(username="otheruser", password="otheruser") + self.client.login(username=other_user.username, password="otheruser") pre_existing_sub = Submission.objects.create(**{ 'phase': self.phase, diff --git a/src/apps/api/views/submissions.py b/src/apps/api/views/submissions.py index bfd6f8889..d01909d98 100644 --- a/src/apps/api/views/submissions.py +++ b/src/apps/api/views/submissions.py @@ -91,12 +91,10 @@ def check_object_permissions(self, request, obj): except SubmissionDetails.DoesNotExist: logger.error("SubmissionDetails object not found.") - not_bot_user = self.request.user.is_authenticated and not self.request.user.is_bot - if self.action in ['update_fact_sheet', 'run_submission', 're_run_submission']: # get_queryset will stop us from re-running something we're not supposed to pass - elif not self.request.user.is_authenticated or not_bot_user: + else: try: if request.data.get('secret') is None or uuid.UUID(request.data.get('secret')) != obj.secret: raise PermissionDenied("Submission secrets do not match") @@ -142,7 +140,7 @@ def get_queryset(self): # Check if admin is requesting to see soft-deleted submissions show_is_soft_deleted = self.request.query_params.get('show_is_soft_deleted', 'false').lower() == 'true' - if not self.request.user.is_superuser and not self.request.user.is_staff and not self.request.user.is_bot: + if not self.request.user.is_superuser and not self.request.user.is_staff: # if you're the creator of the submission or a collaborator on the competition qs = qs.filter( Q(owner=self.request.user) | @@ -300,7 +298,7 @@ def get_renderer_context(self): def has_admin_permission(self, user, submission): competition = submission.phase.competition - return user.is_authenticated and (user.is_superuser or user in competition.all_organizers or user.is_bot) + return user.is_authenticated and (user.is_superuser or user in competition.all_organizers) @action(detail=True, methods=('POST', 'DELETE')) def submission_leaderboard_connection(self, request, pk): @@ -616,14 +614,6 @@ def can_make_submission(request, phase_id): status=CompetitionParticipant.APPROVED ).exists() - if request.user.is_bot and phase.competition.allow_robot_submissions and not user_is_approved: - CompetitionParticipant.objects.create( - user=request.user, - competition=phase.competition, - status=CompetitionParticipant.APPROVED - ) - user_is_approved = True - if user_is_approved: can_make_submission, reason_why_not = phase.can_user_make_submissions(request.user) else: diff --git a/src/apps/competitions/admin.py b/src/apps/competitions/admin.py index 69bc44229..0f6a3bdb4 100644 --- a/src/apps/competitions/admin.py +++ b/src/apps/competitions/admin.py @@ -228,7 +228,6 @@ class CompetitionExpansion(admin.ModelAdmin): "show_detailed_results_in_leaderboard", "make_programs_available", "make_input_data_available", - "allow_robot_submissions", "auto_run_submissions", "can_participants_make_submissions_public", "is_featured", diff --git a/src/apps/competitions/migrations/0062_remove_competition_allow_robot_submissions.py b/src/apps/competitions/migrations/0062_remove_competition_allow_robot_submissions.py new file mode 100644 index 000000000..8a40466db --- /dev/null +++ b/src/apps/competitions/migrations/0062_remove_competition_allow_robot_submissions.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.13 on 2026-08-10 07:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('competitions', '0061_competition_participant_groups'), + ] + + operations = [ + migrations.RemoveField( + model_name='competition', + name='allow_robot_submissions', + ), + ] diff --git a/src/apps/competitions/models.py b/src/apps/competitions/models.py index f919ae432..327c4baa7 100644 --- a/src/apps/competitions/models.py +++ b/src/apps/competitions/models.py @@ -61,7 +61,6 @@ class Competition(models.Model): queue = models.ForeignKey('queues.Queue', on_delete=models.SET_NULL, null=True, blank=True, related_name='competitions') - allow_robot_submissions = models.BooleanField(default=False) # we use filed type to distinguish 'competition' and 'benchmark' competition_type = models.CharField(max_length=128, choices=COMPETITION_TYPE, default=COMPETITION) @@ -339,7 +338,7 @@ def can_user_make_submissions(self, user): Returns: (can_make_submissions, reason_if_not) """ - if not self.has_max_submissions or (user.is_bot and self.competition.allow_robot_submissions): + if not self.has_max_submissions: return True, None qs = self.submissions.filter(owner=user, parent__isnull=True).exclude(status='Failed') diff --git a/src/apps/profiles/admin.py b/src/apps/profiles/admin.py index b0ae3a7d7..b4bedf556 100644 --- a/src/apps/profiles/admin.py +++ b/src/apps/profiles/admin.py @@ -103,7 +103,6 @@ class UserExpansion(UserAdmin): "is_staff", "is_superuser", "is_deleted", - "is_bot", "is_active", "is_banned", QuotaFilter, @@ -140,7 +139,7 @@ class UserExpansion(UserAdmin): "Checkboxes", { "fields": [ - ("is_active", "is_bot"), + "is_active", ( "organizer_direct_message_updates", "allow_forum_notifications", diff --git a/src/apps/profiles/migrations/0023_remove_user_is_bot.py b/src/apps/profiles/migrations/0023_remove_user_is_bot.py new file mode 100644 index 000000000..c8ccb5391 --- /dev/null +++ b/src/apps/profiles/migrations/0023_remove_user_is_bot.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.13 on 2026-08-10 07:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('profiles', '0022_customgroup'), + ] + + operations = [ + migrations.RemoveField( + model_name='user', + name='is_bot', + ), + ] diff --git a/src/apps/profiles/models.py b/src/apps/profiles/models.py index dee26644d..5f4935f35 100644 --- a/src/apps/profiles/models.py +++ b/src/apps/profiles/models.py @@ -97,9 +97,6 @@ class User(AbstractBaseUser, PermissionsMixin): rabbitmq_username = models.CharField(max_length=36, null=True, blank=True) rabbitmq_password = models.CharField(max_length=36, null=True, blank=True) - # Robot submissions - is_bot = models.BooleanField(default=False) - # Required for social auth and such to create users objects = CodabenchUserManager() diff --git a/src/static/riot/competitions/detail/participant_manager.tag b/src/static/riot/competitions/detail/participant_manager.tag index f3f93b823..2043b6509 100644 --- a/src/static/riot/competitions/detail/participant_manager.tag +++ b/src/static/riot/competitions/detail/participant_manager.tag @@ -31,7 +31,6 @@ Username Email - Is Bot? Status Actions @@ -40,7 +39,6 @@ {username} {email} - {is_bot} {is_deleted ? "account deleted" : _.startCase(status)}