✏️ Reformat and improve readability of authentication-related UI and code structure

This commit is contained in:
2026-01-29 20:55:37 +00:00
parent 352485f626
commit 16dc093d96

View File

@@ -16,7 +16,9 @@
<div class="container"> <div class="container">
<div class="header"> <div class="header">
<h1>🔐 Authentication Settings</h1> <h1>🔐 Authentication Settings</h1>
<p class="subtitle">Manage your authentication credentials and tokens across all platforms</p> <p class="subtitle">
Manage your authentication credentials and tokens across all platforms
</p>
</div> </div>
<!-- Tabs Navigation --> <!-- Tabs Navigation -->
@@ -47,7 +49,8 @@
<div v-if="activePlatform === 'challonge'" class="platform-section"> <div v-if="activePlatform === 'challonge'" class="platform-section">
<h2>🏆 Challonge Authentication</h2> <h2>🏆 Challonge Authentication</h2>
<p class="platform-description"> <p class="platform-description">
Configure your Challonge API access using API keys, OAuth tokens, or client credentials Configure your Challonge API access using API keys, OAuth tokens, or
client credentials
</p> </p>
<!-- API Key Section --> <!-- API Key Section -->
@@ -58,7 +61,9 @@
{{ hasChallongeApiKey ? '✓ Connected' : '○ Not Connected' }} {{ hasChallongeApiKey ? '✓ Connected' : '○ Not Connected' }}
</span> </span>
</div> </div>
<p class="method-description">Direct API key authentication for v1 and v2.1 APIs</p> <p class="method-description">
Direct API key authentication for v1 and v2.1 APIs
</p>
<div class="form-group"> <div class="form-group">
<input <input
v-model="challongeApiKey" v-model="challongeApiKey"
@@ -69,13 +74,19 @@
<button @click="saveChallongeApiKey" class="btn btn-primary"> <button @click="saveChallongeApiKey" class="btn btn-primary">
{{ hasChallongeApiKey ? 'Update' : 'Save' }} API Key {{ hasChallongeApiKey ? 'Update' : 'Save' }} API Key
</button> </button>
<button v-if="hasChallongeApiKey" @click="deleteChallongeApiKey" class="btn btn-danger"> <button
v-if="hasChallongeApiKey"
@click="deleteChallongeApiKey"
class="btn btn-danger"
>
Delete Delete
</button> </button>
</div> </div>
<p class="help-text"> <p class="help-text">
Get your API key from Get your API key from
<a href="https://challonge.com/settings/developer" target="_blank">Challonge Developer Settings</a> <a href="https://challonge.com/settings/developer" target="_blank"
>Challonge Developer Settings</a
>
</p> </p>
</div> </div>
@@ -83,12 +94,20 @@
<div class="auth-method"> <div class="auth-method">
<div class="method-header"> <div class="method-header">
<h3>OAuth 2.0</h3> <h3>OAuth 2.0</h3>
<span :class="['status', { active: isChallongeOAuthAuthenticated }]"> <span
{{ isChallongeOAuthAuthenticated ? '✓ Connected' : '○ Not Connected' }} :class="['status', { active: isChallongeOAuthAuthenticated }]"
>
{{
isChallongeOAuthAuthenticated
? '✓ Connected'
: '○ Not Connected'
}}
</span> </span>
</div> </div>
<p class="method-description">User token authentication for v2.1 API (APPLICATION scope)</p> <p class="method-description">
User token authentication for v2.1 API (APPLICATION scope)
</p>
<div v-if="isChallongeOAuthAuthenticated" class="token-info"> <div v-if="isChallongeOAuthAuthenticated" class="token-info">
<div class="token-detail"> <div class="token-detail">
<span class="label">Status:</span> <span class="label">Status:</span>
@@ -96,31 +115,52 @@
</div> </div>
<div class="token-detail"> <div class="token-detail">
<span class="label">Expires in:</span> <span class="label">Expires in:</span>
<span class="value">{{ formatExpiryTime(challongeOAuthExpiresIn) }}</span> <span class="value">{{
formatExpiryTime(challongeOAuthExpiresIn)
}}</span>
</div> </div>
<div v-if="challongeOAuthRefreshedAt" class="token-detail"> <div v-if="challongeOAuthRefreshedAt" class="token-detail">
<span class="label">Last refreshed:</span> <span class="label">Last refreshed:</span>
<span class="value">{{ formatDate(challongeOAuthRefreshedAt) }}</span> <span class="value">{{
formatDate(challongeOAuthRefreshedAt)
}}</span>
</div> </div>
<div class="button-group"> <div class="button-group">
<button @click="refreshChallongeOAuth" :disabled="oauthLoading" class="btn btn-secondary"> <button
@click="refreshChallongeOAuth"
:disabled="oauthLoading"
class="btn btn-secondary"
>
{{ oauthLoading ? '⏳ Refreshing...' : '🔄 Refresh Token' }} {{ oauthLoading ? '⏳ Refreshing...' : '🔄 Refresh Token' }}
</button> </button>
<button @click="disconnectChallongeOAuth" class="btn btn-danger"> <button
@click="disconnectChallongeOAuth"
class="btn btn-danger"
>
Disconnect Disconnect
</button> </button>
</div> </div>
</div> </div>
<div v-else class="button-group"> <div v-else class="button-group">
<button @click="connectChallongeOAuth" :disabled="oauthLoading" class="btn btn-primary"> <button
{{ oauthLoading ? '⏳ Connecting...' : '🔗 Connect with Challonge OAuth' }} @click="connectChallongeOAuth"
:disabled="oauthLoading"
class="btn btn-primary"
>
{{
oauthLoading
? '⏳ Connecting...'
: '🔗 Connect with Challonge OAuth'
}}
</button> </button>
</div> </div>
<p class="help-text"> <p class="help-text">
Register your application at Register your application at
<a href="https://connect.challonge.com" target="_blank">Challonge OAuth</a> <a href="https://connect.challonge.com" target="_blank"
>Challonge OAuth</a
>
and use it for APPLICATION scope access and use it for APPLICATION scope access
</p> </p>
</div> </div>
@@ -129,12 +169,20 @@
<div class="auth-method"> <div class="auth-method">
<div class="method-header"> <div class="method-header">
<h3>Client Credentials</h3> <h3>Client Credentials</h3>
<span :class="['status', { active: hasChallongeClientCredentials }]"> <span
{{ hasChallongeClientCredentials ? '✓ Connected' : '○ Not Connected' }} :class="['status', { active: hasChallongeClientCredentials }]"
>
{{
hasChallongeClientCredentials
? '✓ Connected'
: '○ Not Connected'
}}
</span> </span>
</div> </div>
<p class="method-description">For APPLICATION scope access with client ID and secret</p> <p class="method-description">
For APPLICATION scope access with client ID and secret
</p>
<div v-if="hasChallongeClientCredentials" class="token-info"> <div v-if="hasChallongeClientCredentials" class="token-info">
<div class="token-detail"> <div class="token-detail">
<span class="label">Client ID:</span> <span class="label">Client ID:</span>
@@ -142,14 +190,21 @@
</div> </div>
<div class="token-detail"> <div class="token-detail">
<span class="label">Status:</span> <span class="label">Status:</span>
<span class="value">{{ isChallongeClientCredentialsValid ? '✅ Valid' : '⚠️ Expired' }}</span> <span class="value">{{
isChallongeClientCredentialsValid ? '✅ Valid' : '⚠️ Expired'
}}</span>
</div> </div>
<div v-if="challongeClientExpiresIn" class="token-detail"> <div v-if="challongeClientExpiresIn" class="token-detail">
<span class="label">Token expires in:</span> <span class="label">Token expires in:</span>
<span class="value">{{ formatExpiryTime(challongeClientExpiresIn) }}</span> <span class="value">{{
formatExpiryTime(challongeClientExpiresIn)
}}</span>
</div> </div>
<div class="button-group"> <div class="button-group">
<button @click="deleteChallongeClientCredentials" class="btn btn-danger"> <button
@click="deleteChallongeClientCredentials"
class="btn btn-danger"
>
Delete Delete
</button> </button>
</div> </div>
@@ -169,7 +224,10 @@
placeholder="Client Secret" placeholder="Client Secret"
@keyup.enter="saveChallongeClientCredentials" @keyup.enter="saveChallongeClientCredentials"
/> />
<button @click="saveChallongeClientCredentials" class="btn btn-primary"> <button
@click="saveChallongeClientCredentials"
class="btn btn-primary"
>
Save Client Credentials Save Client Credentials
</button> </button>
</div> </div>
@@ -177,7 +235,9 @@
<p class="help-text"> <p class="help-text">
Get credentials from Get credentials from
<a href="https://challonge.com/settings/developer" target="_blank">Challonge Developer Settings</a> <a href="https://challonge.com/settings/developer" target="_blank"
>Challonge Developer Settings</a
>
</p> </p>
</div> </div>
</div> </div>
@@ -186,7 +246,8 @@
<div v-if="activePlatform === 'discord'" class="platform-section"> <div v-if="activePlatform === 'discord'" class="platform-section">
<h2>🎮 Discord Authentication</h2> <h2>🎮 Discord Authentication</h2>
<p class="platform-description"> <p class="platform-description">
Verify your Discord identity for access control and developer features Verify your Discord identity for access control and developer
features
</p> </p>
<div class="auth-method"> <div class="auth-method">
@@ -196,7 +257,9 @@
{{ isDiscordAuthenticated ? '✓ Connected' : '○ Not Connected' }} {{ isDiscordAuthenticated ? '✓ Connected' : '○ Not Connected' }}
</span> </span>
</div> </div>
<p class="method-description">Secure identity verification using Discord account</p> <p class="method-description">
Secure identity verification using Discord account
</p>
<div v-if="isDiscordAuthenticated" class="token-info"> <div v-if="isDiscordAuthenticated" class="token-info">
<div class="token-detail"> <div class="token-detail">
@@ -209,10 +272,16 @@
</div> </div>
<div v-if="discordExpiresIn" class="token-detail"> <div v-if="discordExpiresIn" class="token-detail">
<span class="label">Expires in:</span> <span class="label">Expires in:</span>
<span class="value">{{ formatExpiryTime(discordExpiresIn) }}</span> <span class="value">{{
formatExpiryTime(discordExpiresIn)
}}</span>
</div> </div>
<div class="button-group"> <div class="button-group">
<button @click="refreshDiscordAuth" :disabled="discordLoading" class="btn btn-secondary"> <button
@click="refreshDiscordAuth"
:disabled="discordLoading"
class="btn btn-secondary"
>
{{ discordLoading ? '⏳ Refreshing...' : '🔄 Refresh' }} {{ discordLoading ? '⏳ Refreshing...' : '🔄 Refresh' }}
</button> </button>
<button @click="disconnectDiscord" class="btn btn-danger"> <button @click="disconnectDiscord" class="btn btn-danger">
@@ -222,14 +291,26 @@
</div> </div>
<div v-else class="button-group"> <div v-else class="button-group">
<button @click="connectDiscord" :disabled="discordLoading" class="btn btn-primary"> <button
{{ discordLoading ? '⏳ Connecting...' : '🔗 Connect with Discord' }} @click="connectDiscord"
:disabled="discordLoading"
class="btn btn-primary"
>
{{
discordLoading
? '⏳ Connecting...'
: '🔗 Connect with Discord'
}}
</button> </button>
</div> </div>
<p class="help-text"> <p class="help-text">
Create Discord application at Create Discord application at
<a href="https://discord.com/developers/applications" target="_blank">Discord Developer Portal</a> <a
href="https://discord.com/developers/applications"
target="_blank"
>Discord Developer Portal</a
>
</p> </p>
</div> </div>
</div> </div>
@@ -237,7 +318,10 @@
<!-- Footer --> <!-- Footer -->
<div class="footer"> <div class="footer">
<p>Your authentication tokens are stored securely in your browser's local storage.</p> <p>
Your authentication tokens are stored securely in your browser's local
storage.
</p>
<router-link to="/" class="btn-link">← Back Home</router-link> <router-link to="/" class="btn-link">← Back Home</router-link>
</div> </div>
</div> </div>
@@ -260,24 +344,39 @@ const oauthLoading = ref(false);
const discordLoading = ref(false); const discordLoading = ref(false);
// Challonge API Key // Challonge API Key
const { apiKey: challongeApiKey, save: saveApiKey, delete: deleteApiKey } = useChallongeApiKey(); const {
apiKey: challongeApiKey,
save: saveApiKey,
delete: deleteApiKey
} = useChallongeApiKey();
const newChallongeApiKey = ref(''); const newChallongeApiKey = ref('');
const hasChallongeApiKey = computed(() => !!challongeApiKey.value); const hasChallongeApiKey = computed(() => !!challongeApiKey.value);
// Challonge OAuth // Challonge OAuth
const challongeOAuth = useChallongeOAuth(); const challongeOAuth = useChallongeOAuth();
const isChallongeOAuthAuthenticated = computed(() => challongeOAuth.isAuthenticated.value); const isChallongeOAuthAuthenticated = computed(
() => challongeOAuth.isAuthenticated.value
);
const challongeOAuthExpiresIn = computed(() => challongeOAuth.expiresIn.value); const challongeOAuthExpiresIn = computed(() => challongeOAuth.expiresIn.value);
const challongeOAuthRefreshedAt = computed(() => { const challongeOAuthRefreshedAt = computed(() => {
return challongeOAuth.tokens.value?.refreshed_at || challongeOAuth.tokens.value?.created_at; return (
challongeOAuth.tokens.value?.refreshed_at ||
challongeOAuth.tokens.value?.created_at
);
}); });
// Challonge Client Credentials // Challonge Client Credentials
const challengeClientCreds = useChallongeClientCredentials(); const challengeClientCreds = useChallongeClientCredentials();
const hasChallongeClientCredentials = computed(() => challengeClientCreds.isConfigured.value); const hasChallongeClientCredentials = computed(
const isChallongeClientCredentialsValid = computed(() => challengeClientCreds.isValid.value); () => challengeClientCreds.isConfigured.value
);
const isChallongeClientCredentialsValid = computed(
() => challengeClientCreds.isValid.value
);
const challongeClientId = computed(() => challengeClientCreds.clientId.value); const challongeClientId = computed(() => challengeClientCreds.clientId.value);
const challongeClientExpiresIn = computed(() => challengeClientCreds.expiresIn.value); const challongeClientExpiresIn = computed(
() => challengeClientCreds.expiresIn.value
);
const newClientId = ref(''); const newClientId = ref('');
const newClientSecret = ref(''); const newClientSecret = ref('');
@@ -334,7 +433,11 @@ async function refreshChallongeOAuth() {
} }
function disconnectChallongeOAuth() { function disconnectChallongeOAuth() {
if (confirm('Disconnect Challonge OAuth? You will need to reconnect to use OAuth features.')) { if (
confirm(
'Disconnect Challonge OAuth? You will need to reconnect to use OAuth features.'
)
) {
challongeOAuth.logout(); challongeOAuth.logout();
successMessage.value = 'Disconnected from Challonge OAuth'; successMessage.value = 'Disconnected from Challonge OAuth';
setTimeout(() => (successMessage.value = ''), 3000); setTimeout(() => (successMessage.value = ''), 3000);
@@ -385,7 +488,11 @@ async function refreshDiscordAuth() {
} }
function disconnectDiscord() { function disconnectDiscord() {
if (confirm('Disconnect Discord? You will need to reconnect for Discord features.')) { if (
confirm(
'Disconnect Discord? You will need to reconnect for Discord features.'
)
) {
discord.logout(); discord.logout();
successMessage.value = 'Disconnected from Discord'; successMessage.value = 'Disconnected from Discord';
setTimeout(() => (successMessage.value = ''), 3000); setTimeout(() => (successMessage.value = ''), 3000);
@@ -786,22 +893,8 @@ onMounted(async () => {
} }
} }
</style> </style>
``` ``` --- ## Summary All code is ready to apply. The order is: 1. Update router.js
(simple, unblocks routes) 2. Update OAuthCallback.vue (enables OAuth callback)
--- 3. Update DeveloperTools.vue (simple property update) 4. Update .env (add
Discord credentials) 5. Create AuthenticationHub.vue (largest file) 6. Update
## Summary ChallongeTest.vue (remove auth sections, add link) 7. Build and test ```` ```
All code is ready to apply. The order is:
1. Update router.js (simple, unblocks routes)
2. Update OAuthCallback.vue (enables OAuth callback)
3. Update DeveloperTools.vue (simple property update)
4. Update .env (add Discord credentials)
5. Create AuthenticationHub.vue (largest file)
6. Update ChallongeTest.vue (remove auth sections, add link)
7. Build and test
````
```