mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-09-08 15:41:20 +02:00
- Added support for Two-Factor Authentication, including setup, verification, and disabling features. - Introduced new components for 2FA setup and verification, enhancing user security. - Updated user model to include fields for 2FA secret, status, and backup codes. - Created migration to add necessary database fields for 2FA. - Enhanced authentication handlers to manage 2FA processes during login and profile updates. - Updated routes to include 2FA-related endpoints for setup and verification.
216 lines
12 KiB
Templ
216 lines
12 KiB
Templ
package destination
|
|
|
|
templ GooglePhotosDestinationForm() {
|
|
<div class="space-y-6" x-init="$watch('useBuiltinAuthDest', value => {
|
|
if(value) {
|
|
destClientId = '';
|
|
destClientSecret = '';
|
|
}
|
|
})">
|
|
<div class="mb-6">
|
|
<label for="use_builtin_auth_dest" class="flex items-center cursor-pointer">
|
|
<div class="relative">
|
|
<input id="use_builtin_auth_dest" name="use_builtin_auth_dest" type="checkbox"
|
|
class="sr-only"
|
|
x-model="useBuiltinAuthDest"
|
|
:value="useBuiltinAuthDest ? 'true' : 'false'"
|
|
/>
|
|
<div class="block bg-secondary-200 dark:bg-secondary-700 w-14 h-8 rounded-full"></div>
|
|
<div class="dot absolute left-1 top-1 bg-white dark:bg-secondary-100 w-6 h-6 rounded-full transition"
|
|
:class="useBuiltinAuthDest ? 'transform translate-x-6 bg-primary-500' : ''"></div>
|
|
</div>
|
|
<div class="ml-3 text-secondary-700 dark:text-secondary-300 font-medium">
|
|
Use rclone's built-in Google authentication (recommended)
|
|
</div>
|
|
</label>
|
|
<p class="mt-1 ml-14 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Simple one-click authentication using rclone's shared credentials
|
|
</p>
|
|
</div>
|
|
|
|
<div x-bind:class="{ 'opacity-50': useBuiltinAuthDest }">
|
|
<div>
|
|
<label for="dest_client_id" class="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">
|
|
Google Client ID
|
|
<span x-show="useBuiltinAuthDest" class="text-secondary-400 dark:text-secondary-600 text-xs font-normal">(Using rclone default)</span>
|
|
</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<i class="fas fa-id-card text-secondary-400 dark:text-secondary-600"></i>
|
|
</div>
|
|
<input type="text" id="dest_client_id" name="dest_client_id" x-model="destClientId"
|
|
class="form-input pl-10 w-full rounded-lg border-secondary-300 dark:border-secondary-700 dark:bg-secondary-800 dark:text-secondary-100 focus:ring-primary-500 focus:border-primary-500"
|
|
x-bind:disabled="useBuiltinAuthDest"
|
|
placeholder="Google Photos OAuth Client ID" />
|
|
</div>
|
|
<p class="mt-1 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Client ID from Google Cloud Console
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<label for="dest_client_secret" class="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">
|
|
Google Client Secret
|
|
<span x-show="useBuiltinAuthDest" class="text-secondary-400 dark:text-secondary-600 text-xs font-normal">(Using rclone default)</span>
|
|
</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<i class="fas fa-key text-secondary-400 dark:text-secondary-600"></i>
|
|
</div>
|
|
<input type="password" id="dest_client_secret" name="dest_client_secret" x-model="destClientSecret"
|
|
class="form-input pl-10 w-full rounded-lg border-secondary-300 dark:border-secondary-700 dark:bg-secondary-800 dark:text-secondary-100 focus:ring-primary-500 focus:border-primary-500"
|
|
x-bind:disabled="useBuiltinAuthDest"
|
|
placeholder="Google Photos OAuth Client Secret" />
|
|
</div>
|
|
<p class="mt-1 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Client Secret from Google Cloud Console
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<label for="dest_read_only" class="flex items-center cursor-pointer">
|
|
<div class="relative">
|
|
<input id="dest_read_only" name="dest_read_only" type="checkbox"
|
|
class="sr-only"
|
|
x-model="destReadOnly"
|
|
:value="destReadOnly ? 'true' : 'false'"
|
|
/>
|
|
<div class="block bg-secondary-200 dark:bg-secondary-700 w-14 h-8 rounded-full"></div>
|
|
<div class="dot absolute left-1 top-1 bg-white dark:bg-secondary-100 w-6 h-6 rounded-full transition"
|
|
:class="destReadOnly ? 'transform translate-x-6 bg-primary-500' : ''"></div>
|
|
</div>
|
|
<div class="ml-3 text-secondary-700 dark:text-secondary-300 font-medium">
|
|
Read-only mode
|
|
</div>
|
|
</label>
|
|
<p class="mt-1 ml-14 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Only request read-only access to your photos
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<label for="dest_start_year" class="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Start Year (Optional)</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<i class="fas fa-calendar text-secondary-400 dark:text-secondary-600"></i>
|
|
</div>
|
|
<input type="number" id="dest_start_year" name="dest_start_year" x-model="destStartYear"
|
|
class="form-input pl-10 w-full rounded-lg border-secondary-300 dark:border-secondary-700 dark:bg-secondary-800 dark:text-secondary-100 focus:ring-primary-500 focus:border-primary-500"
|
|
placeholder="Only include photos after this year (default: 2000)" min="1900" max="2100" />
|
|
</div>
|
|
<p class="mt-1 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Only include photos uploaded after this year
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<label for="dest_include_archived" class="flex items-center cursor-pointer">
|
|
<div class="relative">
|
|
<input id="dest_include_archived" name="dest_include_archived" type="checkbox"
|
|
class="sr-only"
|
|
x-model="destIncludeArchived"
|
|
:value="destIncludeArchived ? 'true' : 'false'"
|
|
/>
|
|
<div class="block bg-secondary-200 dark:bg-secondary-700 w-14 h-8 rounded-full"></div>
|
|
<div class="dot absolute left-1 top-1 bg-white dark:bg-secondary-100 w-6 h-6 rounded-full transition"
|
|
:class="destIncludeArchived ? 'transform translate-x-6 bg-primary-500' : ''"></div>
|
|
</div>
|
|
<div class="ml-3 text-secondary-700 dark:text-secondary-300 font-medium">
|
|
Include archived media
|
|
</div>
|
|
</label>
|
|
<p class="mt-1 ml-14 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Include archived photos and videos in media listings
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<label for="destination_path" class="block text-sm font-medium text-secondary-700 dark:text-secondary-300 mb-1">Album Path</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<i class="fas fa-images text-secondary-400 dark:text-secondary-600"></i>
|
|
</div>
|
|
<input type="text" id="destination_path" name="destination_path" x-model="destinationPath"
|
|
class="form-input pl-10 w-full rounded-lg border-secondary-300 dark:border-secondary-700 dark:bg-secondary-800 dark:text-secondary-100 focus:ring-primary-500 focus:border-primary-500"
|
|
placeholder="Album path (e.g., album/my-photos)" />
|
|
</div>
|
|
<p class="mt-1 text-xs text-secondary-500 dark:text-secondary-400">
|
|
Path within Google Photos where files will be uploaded.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="p-4 bg-amber-50 dark:bg-amber-900/50 rounded-lg border border-amber-100 dark:border-amber-700">
|
|
<div class="flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-exclamation-triangle text-amber-500 dark:text-amber-400"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<h3 class="text-sm font-medium text-amber-800 dark:text-amber-200">Authentication Required</h3>
|
|
<div class="mt-2 text-sm text-amber-700 dark:text-amber-300">
|
|
<p>After saving this configuration, you'll need to authenticate with Google Photos:</p>
|
|
<ol class="list-decimal list-inside mt-2 space-y-1">
|
|
<li>Go to the configurations page</li>
|
|
<li>Click the "Authenticate" button for this configuration</li>
|
|
<li>You'll be redirected to Google to grant access permissions</li>
|
|
<li>After granting permission, you'll be automatically redirected back to GoMFT</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="p-4 bg-blue-50 dark:bg-blue-900/50 rounded-lg border border-blue-100 dark:border-blue-700">
|
|
<div class="flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-info-circle text-blue-400 dark:text-blue-300"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<h3 class="text-sm font-medium text-blue-800 dark:text-blue-200">Authentication Information</h3>
|
|
<div class="mt-2 text-sm text-blue-700 dark:text-blue-300">
|
|
<template x-if="useBuiltinAuthDest">
|
|
<div>
|
|
<p>You're using rclone's built-in authentication, which simplifies the setup process:</p>
|
|
<ul class="list-disc list-inside mt-1 space-y-1">
|
|
<li>No need to create your own Google API credentials</li>
|
|
<li>Authentication happens through Google's secure OAuth flow</li>
|
|
<li>Automatic redirection back to GoMFT after authentication</li>
|
|
</ul>
|
|
<p class="mt-2 text-xs text-amber-600 dark:text-amber-400">
|
|
<i class="fas fa-exclamation-triangle mr-1"></i>
|
|
Note: The built-in authentication uses shared credentials which have rate limits across all rclone users.
|
|
If you plan to transfer large amounts of data or run many concurrent transfers, consider creating your own credentials.
|
|
</p>
|
|
</div>
|
|
</template>
|
|
<template x-if="!useBuiltinAuthDest">
|
|
<div>
|
|
<p>To use Google Photos with your own credentials:</p>
|
|
<ol class="list-decimal list-inside mt-1 space-y-1">
|
|
<li>Go to the <a href="https://console.cloud.google.com/" target="_blank" class="text-blue-600 dark:text-blue-400 underline">Google Cloud Console</a></li>
|
|
<li>Create a project and enable the Google Photos API</li>
|
|
<li>Create OAuth 2.0 credentials (Client ID & Secret)</li>
|
|
<li>Set authorized redirect URI to <code class="bg-blue-100 dark:bg-blue-800 px-1 py-0.5 rounded">http://localhost:53682/</code></li>
|
|
</ol>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="p-4 bg-yellow-50 dark:bg-yellow-900/50 rounded-lg border border-yellow-100 dark:border-yellow-700">
|
|
<div class="flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-exclamation-circle text-yellow-500 dark:text-yellow-400"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-200">Important Note About Google Photos</h3>
|
|
<div class="mt-2 text-sm text-yellow-700 dark:text-yellow-300">
|
|
<p>All media items uploaded to Google Photos with rclone are stored in full resolution at original quality. These uploads will count towards storage in your Google Account.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
} |