Loading common_lib/schema/types.py +15 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ from common_lib.schema.inputs import TimeIntervalType from common_lib.utils import ensure_all_exist, ensure_exists from exercise.models import ( Exercise, OpenSearchAccess, Team, MilestoneState, EmailParticipant, Loading Loading @@ -369,6 +370,7 @@ class TeamType(DjangoObjectType): team_questionnaire_states = graphene.List( graphene.NonNull(_("TeamQuestionnaireStateInterface")), required=True ) open_search_access = graphene.Field(_("OpenSearchAccessType"), required=False) def resolve_users(self, info): access = get_access_for(info.context, self.exercise_id) Loading Loading @@ -409,6 +411,19 @@ class TeamType(DjangoObjectType): return logs class OpenSearchAccessType(DjangoObjectType): class Meta: model = OpenSearchAccess team = graphene.Field(TeamType, required=True) index_name = graphene.String(required=True) username = graphene.String(required=True) password = graphene.String(required=True) def resolve_team(self, info): return self.team class ControlType(DjangoObjectType): class Meta: model = Control Loading exercise/lib/exercise_manager.py +6 −17 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from exercise.graphql_inputs import ( ) from exercise.models import ( Exercise, OpenSearchUser, OpenSearchAccess, Team, TeamInjectState, MilestoneState, Loading Loading @@ -213,25 +213,16 @@ def create_exercise( create_drive_permissions(teams, definition.files.filter(is_drive=True)) if exercise.technical: from running_exercise.lib.opensearch_client import create_opensearch_exercise from running_exercise.lib.opensearch_client import create_opensearch_exercise, create_opensearch_access opensearch_credentials = create_opensearch_exercise([team.id for team in teams]) # TODO: save the credentials of opensearch users in the team models print("=== credentials ===") print(opensearch_credentials) # if len(opensearch_credentials) != len(teams): # print("Failed to create OpenSearch users for all teams") # return exercise create_opensearch_access(teams, opensearch_credentials) # opensearch_users = OpenSearchUser.objects.bulk_create( # OpenSearchUser(username=user["username"], password=user["password"]) # for user in opensearch_credentials # ) # for team, user in zip(teams, opensearch_users): # team.opensearch_user = user # team.save() print(f"✓ OpenSearchAccess") return exercise Loading @@ -241,13 +232,12 @@ def create_teams( team_count: int, team_names: List[str], allowed_start_interval: TimeIntervalInput, opensearch_users: Optional[List[Dict[str, str]]] = None, ) -> List[Team]: if exercise.config.has_enabled(Feature.enable_roles()): return create_teams_roles(exercise, team_count, allowed_start_interval) return create_teams_basic( exercise, team_count, team_names, allowed_start_interval, opensearch_users exercise, team_count, team_names, allowed_start_interval ) Loading Loading @@ -313,7 +303,6 @@ def create_teams_basic( team_count: int, team_names: List[str], allowed_start_interval: TimeIntervalInput, opensearch_users: Optional[List[Dict[str, str]]] = None, ) -> List[Team]: if len(team_names) == 0: team_names = [f"team-{i+1}" for i in range(team_count)] Loading exercise/migrations/0018_auto_20250708_1350.py→exercise/migrations/0017_auto_20250723_0608.py +32 −0 Original line number Diff line number Diff line # Generated by Django 3.2.25 on 2025-07-08 13:50 # Generated by Django 3.2.25 on 2025-07-23 06:08 from django.db import migrations, models import django.db.models.deletion Loading @@ -7,21 +7,26 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ ('exercise', '0017_exercise_technical'), ('exercise', '0016_auto_20250522_0941'), ] operations = [ migrations.AddField( model_name='exercise', name='technical', field=models.BooleanField(default=False), ), migrations.CreateModel( name='OpenSearchUser', name='OpenSearchAccess', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('username', models.TextField(unique=True)), ('password', models.TextField()), ('index_name', models.TextField()), ('team', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opensearch_access', to='exercise.team')), ], ), migrations.AddField( model_name='team', name='opensearch_user', field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team', to='exercise.opensearchuser'), options={ 'default_permissions': (), }, ), ] exercise/migrations/0017_exercise_technical.pydeleted 100644 → 0 +0 −18 Original line number Diff line number Diff line # Generated by Django 3.2.25 on 2025-07-08 12:39 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('exercise', '0016_auto_20250522_0941'), ] operations = [ migrations.AddField( model_name='exercise', name='technical', field=models.BooleanField(default=False), ), ] exercise/models.py +16 −12 Original line number Diff line number Diff line Loading @@ -110,11 +110,6 @@ class ExerciseState(models.Model): return self class OpenSearchUser(models.Model): username = models.TextField(unique=True) password = models.TextField() class Team(models.Model): exercise = models.ForeignKey( Exercise, Loading @@ -130,13 +125,6 @@ class Team(models.Model): ExerciseState, on_delete=models.CASCADE, related_name="teams" ) finish_time = models.DateTimeField(null=True, blank=True) opensearch_user = models.OneToOneField( OpenSearchUser, on_delete=models.SET_NULL, related_name="team", null=True, blank=True, ) class Meta: ordering = ["id"] Loading @@ -155,6 +143,22 @@ class Team(models.Model): ) class OpenSearchAccess(models.Model): username = models.TextField(unique=True) password = models.TextField() index_name = models.TextField() team = models.OneToOneField( Team, on_delete=models.SET_NULL, related_name="opensearch_access", null=True, blank=True, ) class Meta: default_permissions = () class ExerciseAccess(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="+") exercise = models.ForeignKey( Loading Loading
common_lib/schema/types.py +15 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ from common_lib.schema.inputs import TimeIntervalType from common_lib.utils import ensure_all_exist, ensure_exists from exercise.models import ( Exercise, OpenSearchAccess, Team, MilestoneState, EmailParticipant, Loading Loading @@ -369,6 +370,7 @@ class TeamType(DjangoObjectType): team_questionnaire_states = graphene.List( graphene.NonNull(_("TeamQuestionnaireStateInterface")), required=True ) open_search_access = graphene.Field(_("OpenSearchAccessType"), required=False) def resolve_users(self, info): access = get_access_for(info.context, self.exercise_id) Loading Loading @@ -409,6 +411,19 @@ class TeamType(DjangoObjectType): return logs class OpenSearchAccessType(DjangoObjectType): class Meta: model = OpenSearchAccess team = graphene.Field(TeamType, required=True) index_name = graphene.String(required=True) username = graphene.String(required=True) password = graphene.String(required=True) def resolve_team(self, info): return self.team class ControlType(DjangoObjectType): class Meta: model = Control Loading
exercise/lib/exercise_manager.py +6 −17 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from exercise.graphql_inputs import ( ) from exercise.models import ( Exercise, OpenSearchUser, OpenSearchAccess, Team, TeamInjectState, MilestoneState, Loading Loading @@ -213,25 +213,16 @@ def create_exercise( create_drive_permissions(teams, definition.files.filter(is_drive=True)) if exercise.technical: from running_exercise.lib.opensearch_client import create_opensearch_exercise from running_exercise.lib.opensearch_client import create_opensearch_exercise, create_opensearch_access opensearch_credentials = create_opensearch_exercise([team.id for team in teams]) # TODO: save the credentials of opensearch users in the team models print("=== credentials ===") print(opensearch_credentials) # if len(opensearch_credentials) != len(teams): # print("Failed to create OpenSearch users for all teams") # return exercise create_opensearch_access(teams, opensearch_credentials) # opensearch_users = OpenSearchUser.objects.bulk_create( # OpenSearchUser(username=user["username"], password=user["password"]) # for user in opensearch_credentials # ) # for team, user in zip(teams, opensearch_users): # team.opensearch_user = user # team.save() print(f"✓ OpenSearchAccess") return exercise Loading @@ -241,13 +232,12 @@ def create_teams( team_count: int, team_names: List[str], allowed_start_interval: TimeIntervalInput, opensearch_users: Optional[List[Dict[str, str]]] = None, ) -> List[Team]: if exercise.config.has_enabled(Feature.enable_roles()): return create_teams_roles(exercise, team_count, allowed_start_interval) return create_teams_basic( exercise, team_count, team_names, allowed_start_interval, opensearch_users exercise, team_count, team_names, allowed_start_interval ) Loading Loading @@ -313,7 +303,6 @@ def create_teams_basic( team_count: int, team_names: List[str], allowed_start_interval: TimeIntervalInput, opensearch_users: Optional[List[Dict[str, str]]] = None, ) -> List[Team]: if len(team_names) == 0: team_names = [f"team-{i+1}" for i in range(team_count)] Loading
exercise/migrations/0018_auto_20250708_1350.py→exercise/migrations/0017_auto_20250723_0608.py +32 −0 Original line number Diff line number Diff line # Generated by Django 3.2.25 on 2025-07-08 13:50 # Generated by Django 3.2.25 on 2025-07-23 06:08 from django.db import migrations, models import django.db.models.deletion Loading @@ -7,21 +7,26 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ ('exercise', '0017_exercise_technical'), ('exercise', '0016_auto_20250522_0941'), ] operations = [ migrations.AddField( model_name='exercise', name='technical', field=models.BooleanField(default=False), ), migrations.CreateModel( name='OpenSearchUser', name='OpenSearchAccess', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('username', models.TextField(unique=True)), ('password', models.TextField()), ('index_name', models.TextField()), ('team', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opensearch_access', to='exercise.team')), ], ), migrations.AddField( model_name='team', name='opensearch_user', field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team', to='exercise.opensearchuser'), options={ 'default_permissions': (), }, ), ]
exercise/migrations/0017_exercise_technical.pydeleted 100644 → 0 +0 −18 Original line number Diff line number Diff line # Generated by Django 3.2.25 on 2025-07-08 12:39 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('exercise', '0016_auto_20250522_0941'), ] operations = [ migrations.AddField( model_name='exercise', name='technical', field=models.BooleanField(default=False), ), ]
exercise/models.py +16 −12 Original line number Diff line number Diff line Loading @@ -110,11 +110,6 @@ class ExerciseState(models.Model): return self class OpenSearchUser(models.Model): username = models.TextField(unique=True) password = models.TextField() class Team(models.Model): exercise = models.ForeignKey( Exercise, Loading @@ -130,13 +125,6 @@ class Team(models.Model): ExerciseState, on_delete=models.CASCADE, related_name="teams" ) finish_time = models.DateTimeField(null=True, blank=True) opensearch_user = models.OneToOneField( OpenSearchUser, on_delete=models.SET_NULL, related_name="team", null=True, blank=True, ) class Meta: ordering = ["id"] Loading @@ -155,6 +143,22 @@ class Team(models.Model): ) class OpenSearchAccess(models.Model): username = models.TextField(unique=True) password = models.TextField() index_name = models.TextField() team = models.OneToOneField( Team, on_delete=models.SET_NULL, related_name="opensearch_access", null=True, blank=True, ) class Meta: default_permissions = () class ExerciseAccess(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="+") exercise = models.ForeignKey( Loading