diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev index 76bc0886a..410059677 100644 --- a/backend/Dockerfile.dev +++ b/backend/Dockerfile.dev @@ -19,11 +19,11 @@ RUN apk update && apk add --no-cache \ mariadb-dev \ python3-dev -COPY requirements.txt /app/requirements.txt +# Copy and install Python dependencies +COPY requirements.txt dev-requirements.txt /app/ -# Install Python dependencies RUN pip install --upgrade pip && \ - pip install -r requirements.txt + pip install -r requirements.txt -r dev-requirements.txt COPY . /app diff --git a/backend/README.md b/backend/README.md index 003dea55d..9197a9f29 100644 --- a/backend/README.md +++ b/backend/README.md @@ -16,4 +16,37 @@ docker compose -f dev-docker-compose.yml exec backend python manage.py graphql_s Overwrite the schema in `/frontend/apollo/schema.graphql`. -You will also need to generate Typescript types, please see `frontend/README.md`. \ No newline at end of file +You will also need to generate Typescript types, please see `frontend/README.md`. + + +### Create dummy users + +To mock various UI screens and workflows, you may want to create dummy users on the backend. To create fake users: + +1. Install the dev dependencies in your venv: + +```bash +pip install -r dev-requirements.txt +``` +2. Signup and create an organisation. + +3. Run the `create_dummy_users` management command: + +Get the container id of the backend container: + +```bash +docker ps +``` + +Shell into the backend: + +```bash +docker exec -it /bin/sh +``` + +Create users and add them to your org. You may want to optionally specify the email domain used for the fake users. This makes it easier to identify these users for cleanup later. + +```bash +python manage.py create_dummy_users --count 10 --org "OrgName" --domain "example.com" +``` + diff --git a/backend/api/management/commands/create_dummy_users.py b/backend/api/management/commands/create_dummy_users.py new file mode 100644 index 000000000..bc187b36b --- /dev/null +++ b/backend/api/management/commands/create_dummy_users.py @@ -0,0 +1,77 @@ +from django.core.management.base import BaseCommand +from faker import Faker +from django.contrib.auth import get_user_model +from api.models import Organisation, OrganisationMember, Role # Adjust as needed +from allauth.socialaccount.models import SocialAccount + +fake = Faker() + +class Command(BaseCommand): + help = "Create dummy users and associate them with an existing organisation" + + def add_arguments(self, parser): + parser.add_argument("--count", type=int, default=50) + parser.add_argument("--org", type=str, required=True, help="Name of the organisation to assign users to") + parser.add_argument("--domain", type=str, default="example.org", help="Domain name for user emails (e.g. 'example.org')") + + def handle(self, *args, **options): + count = options["count"] + org_name = options["org"] + domain = options["domain"] + + User = get_user_model() + + try: + org = Organisation.objects.get(name=org_name) + except Organisation.DoesNotExist: + self.stderr.write(self.style.ERROR(f"Organisation '{org_name}' does not exist.")) + return + + original_member = OrganisationMember.objects.filter(organisation=org).first() + if not original_member: + self.stderr.write(self.style.ERROR(f"No existing organisation member found in '{org_name}'.")) + return + + try: + role = Role.objects.get(organisation=org, name__iexact="developer") + except Role.DoesNotExist: + self.stderr.write(self.style.ERROR(f"No 'developer' role found in organisation '{org_name}'.")) + return + + for i in range(count): + first_name = fake.first_name() + last_name = fake.last_name() + full_name = f"{first_name} {last_name}" + + username = f"{first_name.lower()}.{last_name.lower()}" + email = f"{username}@{domain}" + + + user = User.objects.create_user( + username=username, + email=email, + password="not-needed", + ) + + SocialAccount.objects.create( + user=user, + provider="google", + uid=email, + extra_data={ + "email": email, + "name": full_name, + "picture": None, + }, + ) + + OrganisationMember.objects.create( + user=user, + organisation=org, + role=role, + identity_key=original_member.identity_key, + wrapped_keyring=original_member.wrapped_keyring, + wrapped_recovery=original_member.wrapped_recovery, + ) + + self.stdout.write(self.style.SUCCESS(f"Created {count} dummy users and added them to '{org_name}'.")) + diff --git a/backend/dev-requirements.txt b/backend/dev-requirements.txt index 1c987370a..8989d1486 100644 --- a/backend/dev-requirements.txt +++ b/backend/dev-requirements.txt @@ -1 +1,4 @@ -pytest==8.3.4 \ No newline at end of file +pytest==8.3.4 +Faker==37.4.0 +colorama==0.4.6 +tzdata==2025.2