Download scripts/create_batch_users.py from dn-scribe/attstore: direct link, hf CLI and curl.
- Browser
- Download file 11.7 kB
-
https://huggingface.co/spaces/dn-scribe/attstore/resolve/main/scripts/create_batch_users.py
- Command line
-
hf download hf://spaces/dn-scribe/attstore/scripts/create_batch_users.py
-
curl -L -o create_batch_users.py https://huggingface.co/spaces/dn-scribe/attstore/resolve/main/scripts/create_batch_users.py
11.7 kB
| #!/usr/bin/env python3 | |
| """ | |
| Batch User Creation Script for Attestation Store | |
| This script demonstrates creating multiple users via the API. | |
| It reads user data from a CSV file andef get_token_with_api_token(base_url, api_token): | |
| """ | |
| import argparse | |
| import csv | |
| import os | |
| import sys | |
| import requests | |
| import json | |
| from urllib.parse import urljoin | |
| DEFAULT_URL = "http://127.0.0.1:5003" | |
| DEFAULT_CSV_FILE = "scripts/users.csv" | |
| def parse_args(): | |
| """Parse command line arguments""" | |
| parser = argparse.ArgumentParser(description="Create batch users in Attestation Store") | |
| parser.add_argument("--url", default=DEFAULT_URL, help=f"Base URL of the Attestation Store API (default: {DEFAULT_URL})") | |
| parser.add_argument("--file", default=DEFAULT_CSV_FILE, help=f"CSV file containing user data (default: {DEFAULT_CSV_FILE})") | |
| # Authentication options | |
| auth_group = parser.add_argument_group('Authentication options (one is required)') | |
| auth_group.add_argument("--username", help="Admin username for authentication") | |
| auth_group.add_argument("--password", help="Admin password for authentication") | |
| auth_group.add_argument("--token", default=os.getenv("SCRIBE_TOKEN"), help="API token for authentication (alternative to username/password)") | |
| args = parser.parse_args() | |
| # Validate that either (username and password) or token is provided | |
| if not ((args.username and args.password) or args.token): | |
| parser.error("Either --username and --password OR --token must be provided") | |
| return args | |
| def read_users_from_csv(filename): | |
| """Read user data from CSV file""" | |
| users = [] | |
| try: | |
| with open(filename, 'r') as csvfile: | |
| reader = csv.DictReader(csvfile) | |
| for row in reader: | |
| # Validate required fields | |
| if 'username' not in row or not row['username']: | |
| print(f"Warning: Skipping row with missing username: {row}") | |
| continue | |
| # Create a user object with defaults for missing fields | |
| user = { | |
| 'username': row['username'], | |
| 'email': row.get('email', f"{row['username']}@example.com"), | |
| 'password': row.get('password', ''), | |
| 'role': row.get('role', 'user'), | |
| 'active': row.get('active', 'true').lower() == 'true', | |
| 'require_password_change': row.get('require_password_change', 'false').lower() == 'true' | |
| } | |
| users.append(user) | |
| except FileNotFoundError: | |
| print(f"Error: CSV file '{filename}' not found") | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"Error reading CSV file: {str(e)}") | |
| sys.exit(1) | |
| return users | |
| def create_users(base_url, users, token): | |
| """Create users in batch via API""" | |
| api_url = urljoin(base_url, "/v1/users/bulk") | |
| # Always use Bearer prefix for authorization | |
| auth_header = f"Bearer {token}" | |
| headers = { | |
| "Authorization": auth_header, | |
| "Content-Type": "application/json" | |
| } | |
| # Format data for the API - API expects a list of users, not a dictionary | |
| payload = users | |
| print(f"Sending request to {api_url}") | |
| print(f"Using Authorization: Bearer {token[:5]}...{token[-5:] if len(token) > 10 else ''}") | |
| try: | |
| response = requests.post(api_url, json=payload, headers=headers) | |
| if response.status_code == 200 or response.status_code == 201: | |
| result = response.json() | |
| print(f"Successfully created {len(result.get('success', []))} users") | |
| # Show details of created users | |
| for user in result.get('success', []): | |
| print(f" - Created: {user.get('username')} ({user.get('email')})") | |
| # Show any errors | |
| for error in result.get('failed', []): | |
| username = error.get('data', {}).get('username', 'Unknown user') | |
| error_msg = error.get('error', 'Unknown error') | |
| print(f" - Error: {username}: {error_msg}") | |
| return True | |
| else: | |
| print(f"Error: API returned status code {response.status_code}") | |
| print(f"Response: {response.text}") | |
| print(f"\nFull request details:") | |
| print(f"URL: {api_url}") | |
| # Additional troubleshooting info for common errors | |
| if response.status_code == 401: | |
| print("\nThis looks like an authentication error. Possible causes:") | |
| print(" - The token may have expired") | |
| print(" - The token may not be valid") | |
| elif response.status_code == 403: | |
| print("\nThis looks like a permission error. Possible causes:") | |
| print(" - The authenticated user may not have admin privileges") | |
| elif response.status_code == 422 and "Not enough segments" in response.text: | |
| print("\nThis is a JWT validation error.") | |
| print("The bulk user creation endpoint requires a valid JWT token (not an API key).") | |
| print("Please try again with:") | |
| print(" - Use the --username and --password options to log in directly") | |
| print(" - Use a valid JWT token obtained from logging in, not an API key") | |
| elif response.status_code == 422: | |
| print("\nThis looks like a validation error. Possible causes:") | |
| print(" - The request payload format may be incorrect") | |
| print(" - If using a token from SCRIBE_TOKEN, make sure it's a JWT token, not an API key") | |
| return False | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error connecting to API: {str(e)}") | |
| return False | |
| def generate_sample_csv(filename): | |
| """Generate a sample CSV file if it doesn't exist""" | |
| if os.path.exists(filename): | |
| return | |
| # Create directory if it doesn't exist | |
| os.makedirs(os.path.dirname(filename), exist_ok=True) | |
| with open(filename, 'w', newline='') as csvfile: | |
| writer = csv.writer(csvfile) | |
| writer.writerow(['username', 'email', 'password', 'role', 'active', 'require_password_change']) | |
| writer.writerow(['user1', 'user1@example.com', 'password123', 'user', 'true', 'true']) | |
| writer.writerow(['user2', 'user2@example.com', 'password456', 'user', 'true', 'false']) | |
| writer.writerow(['user3', 'user3@example.com', '', 'user', 'true', 'true']) | |
| print(f"Generated sample CSV file: {filename}") | |
| def get_token_with_api_token(base_url, api_token): | |
| """Get a JWT access token from the API using an API token""" | |
| login_url = urljoin(base_url, "/v1/login") | |
| # For API token auth, we use a different payload format | |
| payload = { | |
| "api_token": api_token | |
| } | |
| headers = { | |
| "Content-Type": "application/json" | |
| } | |
| try: | |
| print(f"Sending login request to {login_url} using API token...") | |
| response = requests.post(login_url, json=payload, headers=headers) | |
| # Print raw response for debugging | |
| print(f"Status code: {response.status_code}") | |
| print(f"Raw response content: {response.content.decode('utf-8', errors='replace')}") | |
| if response.status_code == 200: | |
| try: | |
| # Try to parse JSON response | |
| result = response.json() | |
| print(f"JSON parsed successfully: {result}") | |
| token = result.get('access_token') | |
| if token: | |
| print(f"Successfully obtained JWT access token using API token") | |
| # Verify it's actually a JWT token (should have 2 dots) | |
| if token.count('.') < 2: | |
| print("Warning: The obtained token does not appear to be a valid JWT token") | |
| return token | |
| else: | |
| print("Error: Token not found in API response") | |
| print(f"Response keys: {result.keys()}") | |
| # Check for alternative token field names | |
| if 'token' in result: | |
| token = result.get('token') | |
| print(f"Found token in 'token' field instead") | |
| return token | |
| return None | |
| except json.JSONDecodeError as e: | |
| print(f"Error decoding JSON response: {str(e)}") | |
| print(f"Response might not be valid JSON: {response.text[:100]}...") | |
| return None | |
| else: | |
| print(f"Error: Login API returned status code {response.status_code}") | |
| print(f"Response: {response.text}") | |
| return None | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error connecting to API: {str(e)}") | |
| return None | |
| def get_token(base_url, username, password): | |
| """Get a JWT access token from the API using username and password""" | |
| login_url = urljoin(base_url, "/v1/login") | |
| payload = { | |
| "username": username, | |
| "password": password | |
| } | |
| try: | |
| print(f"Sending login request to {login_url}...") | |
| response = requests.post(login_url, json=payload) | |
| if response.status_code == 200: | |
| result = response.json() | |
| token = result.get('access_token') | |
| if token: | |
| print(f"Successfully obtained JWT access token") | |
| # Verify it's actually a JWT token (should have 2 dots) | |
| if token.count('.') < 2: | |
| print("Warning: The obtained token does not appear to be a valid JWT token") | |
| return token | |
| else: | |
| print("Error: Token not found in API response") | |
| print(f"Response: {json.dumps(result, indent=2)}") | |
| return None | |
| else: | |
| print(f"Error: Login API returned status code {response.status_code}") | |
| print(f"Response: {response.text}") | |
| return None | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error connecting to API: {str(e)}") | |
| return None | |
| def main(): | |
| args = parse_args() | |
| # Get JWT token using either username/password or API token | |
| token = None | |
| if args.token: | |
| # Use API token to get JWT token | |
| print(f"Using provided API token to get a JWT token...") | |
| token = get_token_with_api_token(args.url, args.token) | |
| elif args.username and args.password: | |
| # Use username/password to get JWT token | |
| print(f"Logging in as {args.username} to get JWT token...") | |
| token = get_token(args.url, args.username, args.password) | |
| if not token: | |
| print("\nError: Failed to obtain JWT token") | |
| print("Please check your credentials and try again") | |
| sys.exit(1) | |
| # Generate sample CSV if file doesn't exist | |
| generate_sample_csv(args.file) | |
| # Read users from CSV | |
| users = read_users_from_csv(args.file) | |
| if not users: | |
| print("No valid users found in CSV file") | |
| sys.exit(1) | |
| print(f"Found {len(users)} users in CSV file") | |
| # Create users via API | |
| success = create_users(args.url, users, token) | |
| if success: | |
| print("Batch user creation completed successfully") | |
| else: | |
| print("Batch user creation failed") | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main() | |