""" One-time OAuth2 setup command for Google Calendar integration. Run this locally (not in Docker) to authorize the app and generate the credentials token file (calendarCredentials.dat). Usage: python manage.py gcal_setup --client-secrets /path/to/client_secret_*.json The command opens a browser for the OAuth2 consent flow, then saves the access+refresh token to the path configured in settings.GCAL_COUPLING['credentials_file']. Copy that file to the server afterwards. """ import os import pickle from django.conf import settings from django.core.management.base import BaseCommand, CommandError SCOPES = ["https://www.googleapis.com/auth/calendar"] class Command(BaseCommand): help = ( "Perform one-time OAuth2 authorization for Google Calendar. " "Run locally, then copy the resulting credentials file to the server." ) def add_arguments(self, parser): parser.add_argument( "--client-secrets", required=True, metavar="FILE", help="Path to the client_secret_*.json downloaded from Google Cloud Console", ) def handle(self, *args, **options): try: from google_auth_oauthlib.flow import InstalledAppFlow except ImportError: raise CommandError( "google-auth-oauthlib is not installed. " "Run: pip install google-auth-oauthlib" ) client_secrets = options["client_secrets"] if not os.path.exists(client_secrets): raise CommandError(f"Client secrets file not found: {client_secrets}") credentials_file = settings.GCAL_COUPLING["credentials_file"] self.stdout.write( "Starting OAuth2 flow. A browser window will open for authorization." ) self.stdout.write( "Make sure you are authorizing with the Google account whose " "calendar you want to use.\n" ) flow = InstalledAppFlow.from_client_secrets_file(client_secrets, SCOPES) creds = flow.run_local_server(port=0) os.makedirs(os.path.dirname(credentials_file), exist_ok=True) if os.path.dirname(credentials_file) else None with open(credentials_file, "wb") as token: pickle.dump(creds, token) self.stdout.write( self.style.SUCCESS( f"Credentials saved to: {credentials_file}\n" f"Copy this file to the server at the same path inside the container." ) ) self.stdout.write( "\nTo copy to server (adjust paths as needed):\n" f" docker cp {credentials_file} blechreiz:/app/calendarCredentials.dat\n" "Or via scp:\n" f" scp {credentials_file} core@server.fritz.box:/docker/blechreiz-website/calendarCredentials.dat" )