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

291 lines
9.7 KiB
Vue
Raw Normal View History

<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>