|
13 | 13 | class DriveAuthenticator: |
14 | 14 | def __init__(self): |
15 | 15 | self.creds = None |
16 | | - # Ruta donde guardaremos la sesión del usuario para no pedirla siempre |
17 | 16 | self.token_path = os.path.join(os.path.dirname(__file__), 'user_token.pickle') |
18 | | - # Tu archivo maestro (que el usuario no toca) |
19 | 17 | self.secrets_path = resource_path('client_secrets.json') |
20 | 18 |
|
21 | | - def get_service(self): |
22 | | - """Intenta loguear silenciosamente, o abre navegador si hace falta.""" |
| 19 | + def has_credentials(self): |
| 20 | + """Verifica si existe el archivo de token.""" |
| 21 | + return os.path.exists(self.token_path) |
23 | 22 |
|
24 | | - # 1. Cargar sesión guardada si existe |
| 23 | + def logout(self): |
| 24 | + """Cierra sesión borrando el token local.""" |
| 25 | + self.creds = None |
| 26 | + if os.path.exists(self.token_path): |
| 27 | + try: |
| 28 | + os.remove(self.token_path) |
| 29 | + return True |
| 30 | + except Exception as e: |
| 31 | + print(f"Error borrando token: {e}") |
| 32 | + return False |
| 33 | + return True |
| 34 | + |
| 35 | + def get_service(self, silent=False): |
| 36 | + """ |
| 37 | + Obtiene el servicio de Drive. |
| 38 | + Si silent=True, NO abrirá el navegador si el token es inválido, |
| 39 | + simplemente devolverá None. |
| 40 | + """ |
| 41 | + # 1. Cargar sesión guardada |
25 | 42 | if os.path.exists(self.token_path): |
26 | | - with open(self.token_path, 'rb') as token: |
27 | | - self.creds = pickle.load(token) |
| 43 | + try: |
| 44 | + with open(self.token_path, 'rb') as token: |
| 45 | + self.creds = pickle.load(token) |
| 46 | + except Exception: |
| 47 | + self.creds = None |
28 | 48 |
|
29 | | - # 2. Si no hay credenciales válidas, hacemos el login visual |
| 49 | + # 2. Validar credenciales |
30 | 50 | if not self.creds or not self.creds.valid: |
31 | 51 | if self.creds and self.creds.expired and self.creds.refresh_token: |
32 | 52 | try: |
33 | | - # Intenta refrescar el token sin abrir el navegador |
34 | 53 | self.creds.refresh(Request()) |
35 | 54 | except Exception: |
36 | | - self._start_browser_login() |
| 55 | + self.creds = None |
37 | 56 | else: |
| 57 | + self.creds = None |
| 58 | + |
| 59 | + # 3. Si no hay credenciales válidas: |
| 60 | + if not self.creds: |
| 61 | + if silent: |
| 62 | + # Si es modo silencioso (arranque), no hacemos nada más |
| 63 | + return None |
| 64 | + else: |
| 65 | + # Si NO es silencioso (botón conectar), abrimos navegador |
38 | 66 | self._start_browser_login() |
39 | 67 |
|
40 | | - # 3. Guardar la sesión para la próxima vez |
| 68 | + # Guardar token refrescado o nuevo |
| 69 | + if self.creds and self.creds.valid: |
41 | 70 | with open(self.token_path, 'wb') as token: |
42 | 71 | pickle.dump(self.creds, token) |
| 72 | + return build('drive', 'v3', credentials=self.creds) |
43 | 73 |
|
44 | | - # 4. Retornar el servicio listo para usar |
45 | | - return build('drive', 'v3', credentials=self.creds) |
| 74 | + return None |
46 | 75 |
|
47 | 76 | def _start_browser_login(self): |
48 | | - """Lanza el flujo de 'Logueate con Google' en el navegador.""" |
49 | 77 | if not os.path.exists(self.secrets_path): |
50 | | - raise FileNotFoundError("Falta el archivo de configuración interna (client_secrets.json).") |
51 | | - |
52 | | - flow = InstalledAppFlow.from_client_secrets_file( |
53 | | - self.secrets_path, SCOPES) |
| 78 | + raise FileNotFoundError("Falta client_secrets.json") |
54 | 79 |
|
55 | | - # CAMBIO CLAVE: Especificar success_message para asegurar que el usuario vea que acabó |
56 | | - # y el servidor sepa que debe cerrarse. |
| 80 | + flow = InstalledAppFlow.from_client_secrets_file(self.secrets_path, SCOPES) |
57 | 81 | self.creds = flow.run_local_server( |
58 | 82 | port=0, |
59 | | - success_message='La autenticación se ha completado. Puedes cerrar esta ventana.' |
| 83 | + success_message='Autenticación completada. Puedes cerrar esta ventana.' |
60 | 84 | ) |
61 | 85 |
|
62 | 86 |
|
|
0 commit comments