hesabixCore/webUI/src/views/oauth/authorize.vue

291 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="oauth-authorize-container">
<v-container class="fill-height">
<v-row justify="center" align="center">
<v-col cols="12" sm="8" md="6" lg="4">
<v-card class="oauth-card" elevation="8">
<v-card-title class="text-center pa-6">
<v-icon size="48" color="primary" class="mb-4">mdi-shield-check</v-icon>
<h2 class="text-h4 font-weight-bold">مجوزدهی OAuth</h2>
</v-card-title>
<v-card-text class="pa-6">
<!-- Loading State -->
<div v-if="loading" class="text-center">
<v-progress-circular indeterminate color="primary" size="64"></v-progress-circular>
<p class="mt-4 text-body-1">در حال بارگذاری...</p>
</div>
<!-- Error State -->
<div v-else-if="error" class="text-center">
<v-icon size="64" color="error" class="mb-4">mdi-alert-circle</v-icon>
<h3 class="text-h6 text-error mb-2">خطا در مجوزدهی</h3>
<p class="text-body-1 mb-4">{{ error }}</p>
<v-btn color="primary" @click="goBack">بازگشت</v-btn>
</div>
<!-- Authorization Form -->
<div v-else-if="application" class="authorization-form">
<!-- Application Info -->
<div class="application-info mb-6">
<div class="d-flex align-center mb-4">
<v-avatar size="64" color="primary" class="mr-4">
<v-icon size="32" color="white">{{ getApplicationIcon() }}</v-icon>
</v-avatar>
<div>
<h3 class="text-h5 font-weight-bold">{{ application.name }}</h3>
<p class="text-body-2 text-medium-emphasis">{{ application.description }}</p>
<v-chip size="small" color="info" variant="outlined" class="mt-1">
{{ application.website }}
</v-chip>
</div>
</div>
</div>
<!-- Scopes -->
<div class="scopes-section mb-6">
<h4 class="text-h6 font-weight-bold mb-3">این برنامه درخواست دسترسی به:</h4>
<v-list class="scopes-list">
<v-list-item v-for="scope in scopes" :key="scope" class="scope-item">
<template v-slot:prepend>
<v-icon color="success" size="20">mdi-check-circle</v-icon>
</template>
<v-list-item-title class="text-body-1">
{{ getScopeDescription(scope) }}
</v-list-item-title>
</v-list-item>
<v-list-item v-if="scopes.length === 0" class="scope-item">
<template v-slot:prepend>
<v-icon color="info" size="20">mdi-information</v-icon>
</template>
<v-list-item-title class="text-body-1">
هیچ مجوز خاصی درخواست نشده است
</v-list-item-title>
</v-list-item>
</v-list>
</div>
<!-- Security Notice -->
<v-alert type="info" variant="tonal" class="mb-6">
<template v-slot:prepend>
<v-icon>mdi-shield-lock</v-icon>
</template>
<div>
<strong>امنیت:</strong> این برنامه فقط به اطلاعات مشخص شده دسترسی خواهد داشت و نمی‌تواند رمز عبور شما را ببیند.
</div>
</v-alert>
<!-- Action Buttons -->
<div class="action-buttons d-flex gap-3">
<v-btn
block
variant="outlined"
color="error"
size="large"
@click="denyAccess"
:loading="processing"
>
<v-icon start>mdi-close</v-icon>
رد کردن
</v-btn>
<v-btn
block
color="primary"
size="large"
@click="approveAccess"
:loading="processing"
>
<v-icon start>mdi-check</v-icon>
تایید و ادامه
</v-btn>
</div>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'OAuthAuthorize',
data() {
return {
loading: true,
processing: false,
error: null,
application: null,
scopes: [],
state: null,
clientId: null,
redirectUri: null,
scope: null
};
},
async mounted() {
await this.initializeAuthorization();
},
methods: {
async initializeAuthorization() {
try {
// دریافت پارامترها از URL
const urlParams = new URLSearchParams(window.location.search);
this.clientId = urlParams.get('client_id');
this.redirectUri = urlParams.get('redirect_uri');
this.scope = urlParams.get('scope');
this.state = urlParams.get('state');
// بررسی پارامترهای اجباری
if (!this.clientId || !this.redirectUri) {
throw new Error('پارامترهای اجباری موجود نیست');
}
// بررسی وضعیت لاگین کاربر
const loginCheck = await axios.post('/api/user/check/login');
if (!loginCheck.data.Success) {
// اگر کاربر لاگین نیست، به صفحه لاگین هدایت شود
this.redirectToLogin();
return;
}
// دریافت اطلاعات برنامه OAuth
await this.loadApplicationInfo();
// پردازش scope ها
this.scopes = this.scope ? this.scope.split(' ') : [];
this.loading = false;
} catch (error) {
console.error('Error initializing authorization:', error);
this.error = error.response?.data?.message || error.message || 'خطا در بارگذاری اطلاعات';
this.loading = false;
}
},
async loadApplicationInfo() {
try {
const response = await axios.get(`/api/admin/oauth/applications/client/${this.clientId}`);
if (response.data.Success) {
this.application = response.data.data;
} else {
throw new Error('برنامه یافت نشد');
}
} catch (error) {
throw new Error('خطا در دریافت اطلاعات برنامه');
}
},
redirectToLogin() {
const loginUrl = `/user/login?redirect=${encodeURIComponent(window.location.href)}`;
this.$router.push(loginUrl);
},
async approveAccess() {
await this.processAuthorization(true);
},
async denyAccess() {
await this.processAuthorization(false);
},
async processAuthorization(approved) {
this.processing = true;
try {
const response = await axios.post('/api/oauth/authorize', {
client_id: this.clientId,
redirect_uri: this.redirectUri,
scope: this.scope,
state: this.state,
approved: approved
});
if (response.data.Success) {
// هدایت به redirect_uri
const redirectUrl = response.data.redirect_url;
window.location.href = redirectUrl;
} else {
throw new Error(response.data.message || 'خطا در پردازش مجوز');
}
} catch (error) {
console.error('Authorization error:', error);
this.error = error.response?.data?.message || error.message || 'خطا در پردازش مجوز';
this.processing = false;
}
},
getApplicationIcon() {
// آیکون پیش‌فرض برای برنامه‌ها
return 'mdi-application';
},
getScopeDescription(scope) {
const scopeDescriptions = {
'read_profile': 'خواندن اطلاعات پروفایل',
'write_profile': 'تغییر اطلاعات پروفایل',
'read_business': 'خواندن اطلاعات کسب و کار',
'write_business': 'تغییر اطلاعات کسب و کار',
'read_financial': 'خواندن اطلاعات مالی',
'write_financial': 'تغییر اطلاعات مالی',
'read_contacts': 'خواندن لیست مخاطبین',
'write_contacts': 'تغییر لیست مخاطبین',
'read_documents': 'خواندن اسناد',
'write_documents': 'تغییر اسناد',
'admin_access': 'دسترسی مدیریتی'
};
return scopeDescriptions[scope] || scope;
},
goBack() {
window.history.back();
}
}
};
</script>
<style scoped>
.oauth-authorize-container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.oauth-card {
border-radius: 16px;
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.95);
}
.scopes-list {
background: transparent;
}
.scope-item {
border-radius: 8px;
margin-bottom: 8px;
background: rgba(0, 0, 0, 0.02);
}
.application-info {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding-bottom: 16px;
}
.action-buttons {
gap: 12px;
}
/* Responsive Design */
@media (max-width: 600px) {
.action-buttons {
flex-direction: column;
}
.oauth-card {
margin: 16px;
}
}
</style>