create logs page

This commit is contained in:
mahyargdz
2024-11-18 18:56:14 +03:30
parent 7583fe1cb9
commit f75f890fa5
8 changed files with 688 additions and 371 deletions
+87 -66
View File
@@ -3,10 +3,8 @@
fixed fixed
:minimize="minimize" :minimize="minimize"
:show="show" :show="show"
@update:show=" @update:show="(value) => $store.commit('admin/set', ['sidebarShow', value])"
(value) => >
$store.commit('admin/set', ['sidebarShow', value])
">
<CSidebarBrand class="d-md-down-none"> <CSidebarBrand class="d-md-down-none">
<a href="/" target="_blank"> <a href="/" target="_blank">
<span style="color: #fff">پرتال خبری</span> <span style="color: #fff">پرتال خبری</span>
@@ -20,68 +18,86 @@
<CSidebarNavItem <CSidebarNavItem
name="صفحه اصلی" name="صفحه اصلی"
:to="{ name: 'admin' }" :to="{ name: 'admin' }"
font-icon="fal fa-home" /> font-icon="fal fa-home"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت کاربران" name="مدیریت کاربران"
:to="{ name: 'admin-users' }" :to="{ name: 'admin-users' }"
v-if="hasPermission('superAdmin')" v-if="hasPermission('superAdmin')"
fontIcon="fal fa-users" fontIcon="fal fa-users"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت صفحات" name="مدیریت صفحات"
:to="{ name: 'admin-pages' }" :to="{ name: 'admin-pages' }"
v-if="hasPermission('categories')" v-if="hasPermission('categories')"
fontIcon="fal fa-file" fontIcon="fal fa-file"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت عملکرد" name="مدیریت عملکرد"
:to="{ name: 'admin-pdfManagement' }" :to="{ name: 'admin-pdfManagement' }"
v-if="hasPermission('categories')" v-if="hasPermission('categories')"
fontIcon="fal fa-file" fontIcon="fal fa-file"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت پرونده خبری" name="مدیریت پرونده خبری"
:to="{ name: 'admin-newsFile' }" :to="{ name: 'admin-newsFile' }"
v-if="hasPermission('newsFile')" v-if="hasPermission('newsFile')"
font-icon="fal fa-cabinet-filing" font-icon="fal fa-cabinet-filing"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت اخبار" name="مدیریت اخبار"
:to="{ name: 'admin-news' }" :to="{ name: 'admin-news' }"
v-if="hasPermission('news')" v-if="hasPermission('news')"
font-icon="fal fa-newspaper" font-icon="fal fa-newspaper"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت چند رسانه ای ها" name="مدیریت چند رسانه ای ها"
v-if="hasPermission('gallery')" v-if="hasPermission('gallery')"
:to="{ name: 'admin-gallery' }" :to="{ name: 'admin-gallery' }"
font-icon="fal fa-images" font-icon="fal fa-images"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت نظرسنجی ها" name="مدیریت نظرسنجی ها"
:to="{ name: 'admin-polls', query: { page: 1 } }" :to="{ name: 'admin-polls', query: { page: 1 } }"
font-icon="fal fa-poll-people" font-icon="fal fa-poll-people"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت انتخابات" name="مدیریت انتخابات"
:exact="false" :exact="false"
:to="{ name: 'admin-elections' }" :to="{ name: 'admin-elections' }"
v-if="hasPermission('elections')" v-if="hasPermission('elections')"
font-icon="fal fa-box-ballot" /> font-icon="fal fa-box-ballot"
/>
<CSidebarNavItem
name="مدیریت نشست ها"
:exact="false"
:to="{ name: 'admin-sessions' }"
v-if="hasPermission('superAdmin')"
font-icon="fal fa-solid fa-user"
/>
<CSidebarNavDropdown <CSidebarNavDropdown
name="میز خدمت" name="میز خدمت"
:show="Boolean(unreadMeetingReq)" :show="Boolean(unreadMeetingReq)"
v-if="hasPermission('superAdmin')" v-if="hasPermission('superAdmin')"
font-icon="fal fa-browser"> font-icon="fal fa-browser"
>
<CSidebarNavItem <CSidebarNavItem
name="درخواست های ملاقات با استاندار" name="درخواست های ملاقات با استاندار"
:exact="false" :exact="false"
@@ -90,7 +106,8 @@
? { text: unreadMeetingReq, color: 'danger' } ? { text: unreadMeetingReq, color: 'danger' }
: null : null
" "
:to="{ name: 'admin-meeting' }" /> :to="{ name: 'admin-meeting' }"
/>
</CSidebarNavDropdown> </CSidebarNavDropdown>
<!-- <CSidebarNavItem <!-- <CSidebarNavItem
@@ -102,16 +119,12 @@
<CSidebarNavDropdown <CSidebarNavDropdown
name="مدیریت پیام ها" name="مدیریت پیام ها"
:show=" :show="Boolean(unreadContactMessages + unreadNewsMessages)"
Boolean(
unreadContactMessages + unreadNewsMessages
)
"
v-if=" v-if="
hasPermission('comment-News') || hasPermission('comment-News') || hasPermission('comment-ContactUs')
hasPermission('comment-ContactUs')
" "
fontIcon="fal fa-envelope"> fontIcon="fal fa-envelope"
>
<CSidebarNavItem <CSidebarNavItem
v-if="hasPermission('comment-News')" v-if="hasPermission('comment-News')"
name="کامنت های اخبار" name="کامنت های اخبار"
@@ -127,7 +140,8 @@
:to="{ :to="{
name: 'admin-comments-type', name: 'admin-comments-type',
params: { type: 'News' }, params: { type: 'News' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
v-if="hasPermission('comment-ContactUs')" v-if="hasPermission('comment-ContactUs')"
name="پیام های تماس با ما" name="پیام های تماس با ما"
@@ -143,83 +157,100 @@
:to="{ :to="{
name: 'admin-comments-type', name: 'admin-comments-type',
params: { type: 'ContactUs' }, params: { type: 'ContactUs' },
}" /> }"
/>
</CSidebarNavDropdown> </CSidebarNavDropdown>
<CSidebarNavDropdown <CSidebarNavDropdown
name="تنظیمات" name="تنظیمات"
v-if="hasPermission('superAdmin')" v-if="hasPermission('superAdmin')"
fontIcon="fal fa-cog"> fontIcon="fal fa-cog"
>
<CSidebarNavItem <CSidebarNavItem
name="اخباری روی صفحه اصلی" name="اخباری روی صفحه اصلی"
:to="{ :to="{
name: 'admin-homePageNews', name: 'admin-homePageNews',
query: { portal: 'ostandari' }, query: { portal: 'ostandari' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت پیوندها" name="مدیریت پیوندها"
:to="{ name: 'admin-links' }" :to="{ name: 'admin-links' }"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="استاندار" name="استاندار"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'manager' }, params: { details: 'manager' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت اسلایدر" name="مدیریت اسلایدر"
:to="{ name: 'admin-slider' }" :to="{ name: 'admin-slider' }"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="عکس شعار سال" name="عکس شعار سال"
:to="{ name: 'admin-yearBanner' }" /> :to="{ name: 'admin-yearBanner' }"
/>
<CSidebarNavItem <CSidebarNavItem
name="دکمه ستاد انتخابات" name="دکمه ستاد انتخابات"
:to="{ name: 'admin-electionBtn' }" /> :to="{ name: 'admin-electionBtn' }"
/>
<CSidebarNavItem <CSidebarNavItem
name="آدرس ایمیل و شبکه های اجتماعی" name="آدرس ایمیل و شبکه های اجتماعی"
:to="{ name: 'admin-socialLinks' }" /> :to="{ name: 'admin-socialLinks' }"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت مناسبت ها" name="مدیریت مناسبت ها"
:to="{ name: 'admin-occasion' }" :to="{ name: 'admin-occasion' }"
:exact="false" /> :exact="false"
/>
<CSidebarNavItem <CSidebarNavItem
name="مدیریت روز شمار" name="مدیریت روز شمار"
:to="{ name: 'admin-counterDay' }" /> :to="{ name: 'admin-counterDay' }"
/>
<CSidebarNavItem <CSidebarNavItem
name="پشتیبان گیری از سایت" name="پشتیبان گیری از سایت"
:to="{ name: 'admin-backup' }" /> :to="{ name: 'admin-backup' }"
/>
</CSidebarNavDropdown> </CSidebarNavDropdown>
<CSidebarNavDropdown <CSidebarNavDropdown
name="مدیریت صفحات خاص" name="مدیریت صفحات خاص"
v-if="hasPermission('contents')" v-if="hasPermission('contents')"
fontIcon="fal fa-file-alt"> fontIcon="fal fa-file-alt"
>
<CSidebarNavItem <CSidebarNavItem
name="صفحه اصلی" name="صفحه اصلی"
:to="{ :to="{
name: 'admin-homePageManagement', name: 'admin-homePageManagement',
query: { portal: 'ostandari' }, query: { portal: 'ostandari' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="صفحه عملکرد" name="صفحه عملکرد"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'performance' }, params: { details: 'performance' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="صفحه سیمای استان" name="صفحه سیمای استان"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'sima' }, params: { details: 'sima' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="صفحه درباره ما" name="صفحه درباره ما"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'aboutus' }, params: { details: 'aboutus' },
}" /> }"
/>
<!-- <CSidebarNavItem--> <!-- <CSidebarNavItem-->
<!-- name="صفحه خدمات"--> <!-- name="صفحه خدمات"-->
<!-- :to="{ name: 'admin-contents-details' , params : {details : 'services'} }"--> <!-- :to="{ name: 'admin-contents-details' , params : {details : 'services'} }"-->
@@ -233,7 +264,8 @@
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'privacy' }, params: { details: 'privacy' },
}" /> }"
/>
<!-- <CSidebarNavItem--> <!-- <CSidebarNavItem-->
<!-- name="صفحه کوکی ها"--> <!-- name="صفحه کوکی ها"-->
<!-- :to="{ name: 'admin-contents-details' , params : {details : 'cookies'} }"--> <!-- :to="{ name: 'admin-contents-details' , params : {details : 'cookies'} }"-->
@@ -251,31 +283,30 @@
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'faq' }, params: { details: 'faq' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="صفحه قوانین و مقررات" name="صفحه قوانین و مقررات"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'rules' }, params: { details: 'rules' },
}" /> }"
/>
<CSidebarNavItem <CSidebarNavItem
name="صفحه نقشه سایت" name="صفحه نقشه سایت"
:to="{ :to="{
name: 'admin-contents-details', name: 'admin-contents-details',
params: { details: 'sitemap' }, params: { details: 'sitemap' },
}" /> }"
/>
</CSidebarNavDropdown> </CSidebarNavDropdown>
</CSidebarNav> </CSidebarNav>
<!-- sidebar content --> <!-- sidebar content -->
<CSidebarMinimizer <CSidebarMinimizer
class="d-md-down-none" class="d-md-down-none"
@click.native=" @click.native="$store.commit('admin/set', ['sidebarMinimize', !minimize])"
$store.commit('admin/set', [ />
'sidebarMinimize',
!minimize,
])
" />
</CSidebar> </CSidebar>
</template> </template>
@@ -294,11 +325,7 @@ export default {
"مشکلی هنگام خروج از سیسیتم بوجود امده لطفا دوباره تلاش کنید", "مشکلی هنگام خروج از سیسیتم بوجود امده لطفا دوباره تلاش کنید",
}; };
}, },
mixins: [ mixins: [unreadNewsMessages, unreadContactMessages, unreadMeetingReq],
unreadNewsMessages,
unreadContactMessages,
unreadMeetingReq,
],
computed: { computed: {
show() { show() {
return this.$store.state.admin.sidebarShow; return this.$store.state.admin.sidebarShow;
@@ -307,12 +334,10 @@ export default {
return this.$store.state.admin.sidebarMinimize; return this.$store.state.admin.sidebarMinimize;
}, },
unreadNewsMessages() { unreadNewsMessages() {
return this.$store.state.admin return this.$store.state.admin.unreadNewsMessagesCount;
.unreadNewsMessagesCount;
}, },
unreadContactMessages() { unreadContactMessages() {
return this.$store.state.admin return this.$store.state.admin.unreadContactMessagesCount;
.unreadContactMessagesCount;
}, },
unreadMeetingReq() { unreadMeetingReq() {
return this.$store.state.admin.unreadMeetingReqCount; return this.$store.state.admin.unreadMeetingReqCount;
@@ -321,13 +346,9 @@ export default {
methods: { methods: {
hasPermission(permission) { hasPermission(permission) {
if (this.$auth.loggedIn) { if (this.$auth.loggedIn) {
if ( if (this.$auth.user.permissions.includes("superAdmin")) {
this.$auth.user.permissions.includes("superAdmin")
) {
return true; return true;
} else if ( } else if (this.$auth.user.permissions.includes(permission)) {
this.$auth.user.permissions.includes(permission)
) {
return true; return true;
} else { } else {
return false; return false;
+18 -14
View File
@@ -1,9 +1,8 @@
const webpack = require("webpack"); const webpack = require("webpack");
const serverPort = 3756; const serverPort = 3756;
export default { export default {
// Global page headers: https://go.nuxtjs.dev/config-head // Global page headers: https://go.nuxtjs.dev/config-head
head: { head: {
title: "پورتال خبری استانداری", title: "پورتال خبری استانداری",
@@ -39,23 +38,32 @@ export default {
type: "text/css", type: "text/css",
href: "/js/flipBook/flipbook.style.css", href: "/js/flipBook/flipbook.style.css",
}, },
{ {
rel: "stylesheet", rel: "stylesheet",
type: "text/css", type: "text/css",
href: "/js/flipBook/font-awesome.css", href: "/js/flipBook/font-awesome.css",
}, },
{ rel: 'stylesheet', {
href: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js' } rel: "stylesheet",
href: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js",
},
], ],
script: [ script: [
{ src: "https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js" }, { src: "https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js" },
{ src: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js" }, {
src: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js",
},
{ src: "/js/flipBook/flipbook.min.js" }, { src: "/js/flipBook/flipbook.min.js" },
{ src: "/js/lightBox/simple-lightbox.min.js" }, { src: "/js/lightBox/simple-lightbox.min.js" },
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js', defer: true }, {
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-flipbook/1.0.5/jquery.flipbook.min.js', defer: true } src: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js",
defer: true,
},
{
src: "https://cdnjs.cloudflare.com/ajax/libs/jquery-flipbook/1.0.5/jquery.flipbook.min.js",
defer: true,
},
], ],
}, },
loading: "~/components/pageLoad.vue", loading: "~/components/pageLoad.vue",
@@ -68,7 +76,6 @@ export default {
"~/assets/scss/main.scss", "~/assets/scss/main.scss",
], ],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [ plugins: [
"@/plugins/element-ui", "@/plugins/element-ui",
@@ -85,10 +92,7 @@ export default {
], ],
// Auto import components: https://go.nuxtjs.dev/config-components // Auto import components: https://go.nuxtjs.dev/config-components
components: [ components: ["~/components/", { path: "~/components/admin/", prefix: "" }],
"~/components/",
{ path: "~/components/admin/", prefix: "" },
],
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [], buildModules: [],
+127 -89
View File
@@ -4,23 +4,23 @@
<CCardGroup> <CCardGroup>
<CCard class="p-4"> <CCard class="p-4">
<CCardBody> <CCardBody>
<CForm <CForm v-if="step === 1" @submit.prevent="doLogin">
v-if="step === 1"
@submit.prevent="doLogin">
<h1 class="text-muted text-center mb-5">پنل مدیریت</h1> <h1 class="text-muted text-center mb-5">پنل مدیریت</h1>
<CInput <CInput
:class="validation.username ? 'err' : null" :class="validation.username ? 'err' : null"
placeholder="شماره موبایل" placeholder="شماره موبایل"
:description="validation.username ? validation.username.msg : null" :description="
autocomplete="username email" validation.username ? validation.username.msg : null
v-model="phone" "
> autocomplete="username email"
<template #prepend-content> v-model="phone"
<CIcon name="cil-user"/> >
</template> <template #prepend-content>
</CInput> <CIcon name="cil-user" />
<!-- </template>
</CInput>
<!--
<CInput <CInput
:class="validation.username ? 'err' : null" :class="validation.username ? 'err' : null"
@@ -52,42 +52,40 @@
</div> </div>
<CInputCheckbox label="مرا به خاطر بسپار" @update:checked="val => login.remember_me = val"/> --> <CInputCheckbox label="مرا به خاطر بسپار" @update:checked="val => login.remember_me = val"/> -->
<CRow> <CRow>
<CCol col="12" class="text-right mt-2"> <CCol col="12" class="text-right mt-2">
<CButton color="primary" @click="send_number" class="px-4">ارسال کد</CButton> <CButton color="primary" @click="send_number" class="px-4"
>ارسال کد</CButton
>
</CCol> </CCol>
</CRow> </CRow>
<!-- <p class="text-muted mt-3" style="font-size: 11px;">*درصورتی که گزینه "مرا به خاطر بسپار" را فعال نکنید بعد از 1 ساعت باید دوباره وارد سیستم شوید.</p> --> <!-- <p class="text-muted mt-3" style="font-size: 11px;">*درصورتی که گزینه "مرا به خاطر بسپار" را فعال نکنید بعد از 1 ساعت باید دوباره وارد سیستم شوید.</p> -->
</CForm> </CForm>
<CForm v-if="step === 2" @submit.prevent="doLogin">
<CForm
v-if="step === 2"
@submit.prevent="doLogin">
<h1 class="text-muted text-center mb-5">پنل مدیریت</h1> <h1 class="text-muted text-center mb-5">پنل مدیریت</h1>
<CInput <CInput
:class="validation.username ? 'err' : null" :class="validation.username ? 'err' : null"
placeholder="کد ورود را وارد کنید" placeholder="کد ورود را وارد کنید"
:description="validation.username ? validation.username.msg : null" :description="
autocomplete="username email" validation.username ? validation.username.msg : null
v-model="otp" "
> autocomplete="username email"
<template #prepend-content> v-model="otp"
<CIcon name="cil-user"/> >
</template> <template #prepend-content>
</CInput> <CIcon name="cil-user" />
</template>
</CInput>
<CRow> <CRow>
<CCol col="12" class="text-right mt-2"> <CCol col="12" class="text-right mt-2">
<CButton color="primary" type="submit" class="px-4">ارسال کد</CButton> <CButton color="primary" type="submit" class="px-4"
>ورود</CButton
>
</CCol> </CCol>
</CRow> </CRow>
</CForm> </CForm>
</CCardBody> </CCardBody>
</CCard> </CCard>
</CCardGroup> </CCardGroup>
@@ -96,71 +94,111 @@
</template> </template>
<script> <script>
import { ref } from 'vue'; import { ref } from "vue";
export default { export default {
data() { data() {
return { return {
showPass: false, showPass: false,
step: 1, step: 1,
phone: '', phone: "",
otp: '', otp: "",
login: { login: {
username: '', username: "",
password: '', password: "",
remember_me: false remember_me: false,
}, },
validation: {} validation: {},
} };
}, },
computed: { computed: {
passwordState() { passwordState() {
return this.showPass ? "text" : "password" return this.showPass ? "text" : "password";
} },
}, },
methods: { methods: {
async send_number(){ async send_number() {
console.log(this.phone) if (!this.phone) {
const phoneNumber = this.phone this.$message({
const send_request = await fetch('/api/auth/otp', { type: "warning",
method: 'POST', message: "شماره تماس را وارد کنید !",
headers: { });
'Accept' : 'application/json', return;
'content-type' : 'application/json' }
},
body: JSON.stringify({phone: phoneNumber})
}) try {
//if (send_request.status === 200) { const phoneNumber = this.phone;
this.step = 2 const send_request = await fetch("/api/auth/otp", {
//} method: "POST",
headers: {
Accept: "application/json",
"content-type": "application/json",
},
body: JSON.stringify({ phone: phoneNumber }),
});
}, if (send_request.status === 429 || send_request.status === 406) {
doLogin() { this.$message({
this.validation = {} type: "warning",
message: "شما دسترسی ورود ندارید !",
this.$auth.loginWith('local', { });
data: { return;
phone: this.phone,
code: this.otp
} }
})
.then(response => {
window.location.replace(window.location.origin + "/admin" )
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
if (err.response.status === 403) {
this.$message({
type: 'warning',
message: err.response.data.message
})
} else console.log(err.response.data)
})
}
},
layout: 'admin-auth',
} if (send_request.status === 200 || send_request.status === 201) {
this.$message({
type: "success",
message: "کد ورود ارسال شد",
});
this.step = 2;
return;
} else {
this.$message({
type: "warning",
message: "مشکل در برقرای ارتباط",
});
}
} catch (error) {
console.log("err", error);
this.$message({
type: "warning",
message: "خطای ناشناخته",
});
return;
}
},
doLogin() {
this.validation = {};
this.$auth
.loginWith("local", {
data: {
phone: this.phone,
code: this.otp,
},
})
.then((response) => {
window.location.replace(window.location.origin + "/admin");
})
.catch((err) => {
if (err.response.status === 422)
this.validation = err.response.data.validation;
if (err.response.status === 403) {
this.$message({
type: "warning",
message: err.response.data.message,
});
} else {
this.$message({
type: "warning",
message: err?.response?.data?.validation?.code?.msg,
});
console.log(err.response.data.validation.code.msg);
}
});
},
},
layout: "admin-auth",
};
</script> </script>
<style lang="scss"> <style lang="scss">
+245
View File
@@ -0,0 +1,245 @@
<template>
<div>
<CCard>
<CCardHeader>
<slot name="header">
<i class="fal fa-bars"></i>
<span>{{ list_title }}</span>
</slot>
<slot></slot>
</CCardHeader>
<CCardBody>
<el-table v-loading="loading" :data="sessions" style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column label="نام کاربر">
<template slot-scope="scope">
<span class="title">
<el-popover
placement="top-end"
trigger="hover"
:content="scope.row.title"
>
</el-popover>
{{ scope.row?.user?.firstName + scope?.row?.user?.lastName }}
</span>
</template>
</el-table-column>
<el-table-column label="شماره موبایل">
<template slot-scope="scope">
<span class="title">
<el-popover
placement="top-end"
trigger="hover"
:content="scope.row.title"
>
</el-popover>
{{ scope.row?.user?.mobileNumber }}
</span>
</template>
</el-table-column>
<el-table-column label="آی پی">
<template slot-scope="scope">
<span class="title">
<el-popover
placement="top-end"
trigger="hover"
:content="scope.row.title"
>
</el-popover>
{{ scope.row?.ip }}
</span>
</template>
</el-table-column>
<el-table-column label="تاریخ ورود" width="">
<template slot-scope="scope">
<span>{{ scope.row.LastLogin }}</span>
</template>
</el-table-column>
</el-table>
</CCardBody>
</CCard>
<CCard class="col">
<CRow alignHorizontal="center" style="padding: 10px">
<el-pagination
:hide-on-single-page="true"
layout="prev, pager, next"
page-size="10"
@current-change="change_page"
:current-page.sync="elections.page"
:total="length"
>
</el-pagination>
</CRow>
</CCard>
</div>
</template>
<script>
import moment from "moment-jalaali";
export default {
data() {
return {
title: "لیست انتخابات",
list_title: "لیست",
elections: null,
search: {},
parent: null,
loading: false,
sessions: [],
length: null,
page: 1,
};
},
computed: {
pageQuery() {
return this.$route.query.page;
},
},
watch: {
pageQuery(newPage, oldPage) {
this.$nuxt.refresh();
},
},
mounted() {
this.getData();
},
methods: {
jDate(date) {
return moment(date).format("jYYYY/jMM/jDD");
},
async change_page(value) {
this.page = value;
this.getData();
},
async getData() {
try {
const response = await this.$axios.get(
`/api/admin/logs?page=${this.page}&limit=10`
);
// const data = await response.json(); // if you want to parse JSON response
console.log(response, "res");
this.sessions = response?.data?.logs;
this.length = response?.data?.totalLogs;
} catch (error) {
console.error("Failed to fetch data:", error);
}
},
deletePoll(id) {
this.$confirm("انتخابات حذف شود؟", "اخطار", {
confirmButtonText: "بله",
cancelButtonText: "لغو",
type: "warning",
})
.then(async () => {
this.$axios
.delete(`/api/admin/election/${id}`)
.then((res) => {
this.$message({
type: "success",
message: "انتخابات با موفقیت حذف شد",
});
this.elections.docs = this.elections.docs.filter(
(item) => item._id !== id
);
})
.catch((err) => {
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 403) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
if (err.response.status === 422) {
return this.$message({
type: "error",
message: err.response.data.message,
});
}
console.log(err.response.data);
});
})
.catch(() => {
this.$message({
type: "warning",
message: "عملیات لغو شد",
});
});
},
handleCurrentChange(page) {
this.handleSearch(page);
},
handleSearch(page) {
this.loading = true;
const data = {
term: this.search.term,
catId: this.search.catId,
showInHome: this.search.showInHome,
};
this.$axios
.post(`/api/admin/election/search?page=${page}`, data, this.axiosConfig)
.then((result) => {
this.elections = result.data;
this.loading = false;
})
.catch((err) => {
this.loading = false;
if (err.response.status === 401) {
return this.$message({
type: "error",
message: "لطفا دوباره وارد سیستم شوید.",
});
}
if (err.response.status === 422)
this.validation = err.response.data.validation;
else console.log(err.response.data);
});
},
},
head() {
return {
title: this.title,
};
},
layout: "admin",
async asyncData({ $axios, query, error }) {
try {
const requests = [
$axios.get(`/api/admin/election?page=${query.page}`),
$axios.get("/api/admin/category/getParent"),
];
const fetch = await Promise.all(requests);
let [elections, parents] = fetch;
return {
elections: elections.data,
parents: parents.data,
};
} catch (e) {
if (e?.response?.status === 401)
error({
status: 401,
message: "شما اجازه دسترسی به این صفحه را ندارید",
});
else
error({
status: 500,
message: "مشکلی در گرفتن اطلاعات بوجود آمده است",
});
}
},
};
</script>
+159 -152
View File
@@ -1,166 +1,173 @@
const jwt = require('jsonwebtoken') const jwt = require("jsonwebtoken");
const User = require('./models/User'); const User = require("./models/User");
const {res500} = require('./plugins/controllersHelperFunctions'); const { res500 } = require("./plugins/controllersHelperFunctions");
const Category = require('./models/Category'); const Category = require("./models/Category");
const Election = require('./models/Election'); const Election = require("./models/Election");
const authentication = { const authentication = {
// secret for generating jwt token // secret for generating jwt token
secretKey: 'kyQa8pFI5BJnj7LCVPlSfoATTSZuS5DMSjgBPxQo2zkcdKnxKCPzWs1DEBgMfnXFsjgT0YWgqn8HgLLcmdIgSR6fSQpy6vchmY3kUSD564J', secretKey:
// check if just logged in (admin-or-user) (middleware) "kyQa8pFI5BJnj7LCVPlSfoATTSZuS5DMSjgBPxQo2zkcdKnxKCPzWs1DEBgMfnXFsjgT0YWgqn8HgLLcmdIgSR6fSQpy6vchmY3kUSD564J",
isLoggedIn: async function (req, res, next) { // check if just logged in (admin-or-user) (middleware)
isLoggedIn: async function (req, res, next) {
try {
const token = req.headers.authorization?.replace(/^Bearer\s/, "");
if (token) {
// check if token is not destroyed
var user = await User.findOne({ token: token });
if (!user) {
return res.status(401).json({ message: "unauthorized" });
}
if (!user.registration_done) {
return res500(res, "user is disable please contact to support");
}
//verifies secret and checks if the token is expired
try { try {
const token = req.headers.authorization?.replace(/^Bearer\s/, ''); var checkToken = await jwt.verify(
if (token) { user.token.replace(/^Bearer\s/, ""),
// check if token is not destroyed authentication.secretKey
var user = await User.findOne({token: token}); );
if (!user) { if (!checkToken) {
return res.status(401).json({message: 'unauthorized'}); return res.status(401).json({ message: "unauthorized" });
} }
if (!user.registration_done) {
return res500(res, 'user is disable please contact to support');
}
//verifies secret and checks if the token is expired
try {
var checkToken = await jwt.verify(user.token.replace(/^Bearer\s/, ''), authentication.secretKey);
if (!checkToken) {
return res.status(401).json({message: 'unauthorized'});
}
} catch (error) {
return res.status(401).json({message: 'unauthorized'});
}
req.user = {
_id: user._id,
scope: user.scope,
portals: user.portals,
permissions: user.permissions,
specialPermissions: user.specialPermissions,
private: user.private
};
return next();
} else {
return res.status(401).json({message: 'unauthorized'});
}
} catch (error) { } catch (error) {
return res500(res, error.message); return res.status(401).json({ message: "unauthorized" });
} }
},
// check if admin logged in (middleware)
isAdmin: async function (req, res, next) {
/** if req.user exist find user and check scope */
/** req.user send from isLoggedIn */
try {
if (req.user) {
const scope = req.user.scope;
if (!scope.includes('admin')) { req.user = {
return res.status(401).json({message: 'unauthorized'}); _id: user._id,
} scope: user.scope,
portals: user.portals,
permissions: user.permissions,
specialPermissions: user.specialPermissions,
private: user.private,
};
return next() return next();
} else { } else {
return res.status(401).json({message: 'unauthorized'}); return res.status(401).json({ message: "unauthorized" });
} }
} catch (error) { } catch (error) {
return res.status(401).json({message: 'unauthorized'}); return res500(res, error.message);
}
},
// check if admin logged in (middleware)
isAdmin: async function (req, res, next) {
/** if req.user exist find user and check scope */
/** req.user send from isLoggedIn */
try {
if (req.user) {
const scope = req.user.scope;
if (!scope.includes("admin")) {
return res.status(401).json({ message: "unauthorized" });
} }
},
// check if user has permission (middleware) return next();
hasPermission: (permission) => { } else {
return (req, res, next) => { return res.status(401).json({ message: "unauthorized" });
if (req.user && req.user.permissions) { }
const permissions = req.user.permissions; } catch (error) {
if (permissions.includes('superAdmin')) { return res.status(401).json({ message: "unauthorized" });
return next(); }
} },
if (!permissions.includes(permission)) { // check if user has permission (middleware)
return res.status(401).json({message: 'unauthorized'}); hasPermission: (permission) => {
} else { return (req, res, next) => {
return next(); if (req.user && req.user.permissions) {
} const permissions = req.user.permissions;
} else { if (permissions.includes("superAdmin")) {
return res.status(401).json({message: 'unauthorized'}); return next();
}
} }
}, if (!permissions.includes(permission)) {
// hasSpecPermission: () => { return res.status(401).json({ message: "unauthorized" });
// return async (req, res, next) => { } else {
// if (req.user && req.user.specialPermissions.length) { return next();
// const specialPermissions = req.user.specialPermissions;
// if (req.user.permissions.includes('superAdmin')) {
// return next();
// }
// let tempSpec = [];
// for (const spec of specialPermissions) {
// const check = await Category.findById(spec);
//
// if (check){
// tempSpec.push(check._id);
// }
// }
//
// if (tempSpec.length){
// req.user.allSpecialPermissions = tempSpec;
// next();
// }else {
// return res.status(401).json({message: 'unauthorized'});
// }
// } else {
// return next();
// }
// }
// },
hasSubPermission: () => {
return (req, res, next, value) => {
if (req.user && req.user.permissions) {
var permissions = req.user.permissions;
if (permissions.includes('superAdmin')) {
return next();
}
if (!permissions.some(item => new RegExp(value, 'i').test(item))) {
return res.status(401).json({message: 'unauthorized'});
} else {
return next();
}
} else {
return res.status(401).json({message: 'unauthorized'});
}
} }
}, } else {
isVoter: async function (req, res, next) { return res.status(401).json({ message: "unauthorized" });
try { }
const token = req.headers.authorization?.replace(/^Bearer\s/, ''); };
if (token) { },
// check if token is not destroyed // hasSpecPermission: () => {
const user = await Election.findOne({'voters': {$elemMatch: {_id: token}}}); // return async (req, res, next) => {
// if (req.user && req.user.specialPermissions.length) {
// const specialPermissions = req.user.specialPermissions;
// if (req.user.permissions.includes('superAdmin')) {
// return next();
// }
// let tempSpec = [];
// for (const spec of specialPermissions) {
// const check = await Category.findById(spec);
//
// if (check){
// tempSpec.push(check._id);
// }
// }
//
// if (tempSpec.length){
// req.user.allSpecialPermissions = tempSpec;
// next();
// }else {
// return res.status(401).json({message: 'unauthorized'});
// }
// } else {
// return next();
// }
// }
// },
if (!user) { hasSubPermission: () => {
return res.status(401).json({message: 'unauthorized'}); return (req, res, next, value) => {
} if (req.user && req.user.permissions) {
var permissions = req.user.permissions;
const voter = user.voters.id(token); if (permissions.includes("superAdmin")) {
return next();
req.voter = {
_id: voter._id,
username: voter.username,
password: voter.password,
voted: voter.voted
};
return next();
} else {
return res.status(401).json({message: 'unauthorized'});
}
} catch (error) {
return res500(res, error.message);
} }
}, if (!permissions.some((item) => new RegExp(value, "i").test(item))) {
} return res.status(401).json({ message: "unauthorized" });
} else {
return next();
}
} else {
return res.status(401).json({ message: "unauthorized" });
}
};
},
isVoter: async function (req, res, next) {
try {
const token = req.headers.authorization?.replace(/^Bearer\s/, "");
if (token) {
// check if token is not destroyed
const user = await Election.findOne({
voters: { $elemMatch: { _id: token } },
});
module.exports = authentication if (!user) {
return res.status(401).json({ message: "unauthorized" });
}
const voter = user.voters.id(token);
req.voter = {
_id: voter._id,
username: voter.username,
password: voter.password,
voted: voter.voted,
};
return next();
} else {
return res.status(401).json({ message: "unauthorized" });
}
} catch (error) {
return res500(res, error.message);
}
},
};
module.exports = authentication;
+1 -1
View File
@@ -34,7 +34,7 @@ module.exports.getAdminLoginLogs = [
try { try {
const { const {
page = 1, page = 1,
limit = 1000, limit = 10,
sort = "desc", sort = "desc",
fromDate, fromDate,
toDate, toDate,
+50 -48
View File
@@ -1,77 +1,79 @@
const mongoose = require('mongoose'); const mongoose = require("mongoose");
function autoPopulateSubs(next) { function autoPopulateSubs(next) {
this.populate({ this.populate({
path: 'childs', path: "childs",
select: 'title childs navIndex url modelType treeCat parent defaultPageType', select:
options:{ "title childs navIndex url modelType treeCat parent defaultPageType",
sort : 'navIndex' options: {
} sort: "navIndex",
},
// sort: {navIndex: -1}, // sort: {navIndex: -1},
}); });
next(); next();
} }
function file(file) { function file(file) {
return '/uploads/files/terms/' + file return "/uploads/files/terms/" + file;
} }
function image(img) { function image(img) {
if (img) return '/uploads/images/category/' + img if (img) return "/uploads/images/category/" + img;
else return '/img/no-cover.jpg' else return "/img/no-cover.jpg";
} }
const CategoryTermsFile = mongoose.Schema({ const CategoryTermsFile = mongoose.Schema({
file: {type: String, get: file}, file: { type: String, get: file },
title: String title: String,
}) });
const CategorySchema = mongoose.Schema({ const CategorySchema = mongoose.Schema({
title: String, title: String,
parent: {type: mongoose.Schema.Types.ObjectId, ref: 'Category', default: null}, parent: {
childs: [{type: mongoose.Schema.Types.ObjectId, ref: 'Category'}], type: mongoose.Schema.Types.ObjectId,
treeCat: [{type: mongoose.Schema.Types.ObjectId, ref: 'Category'}], ref: "Category",
rootParent: {type: mongoose.Schema.Types.ObjectId, ref: 'Category'}, default: null,
priority: {type: Number, default: 0}, },
childs: [{ type: mongoose.Schema.Types.ObjectId, ref: "Category" }],
treeCat: [{ type: mongoose.Schema.Types.ObjectId, ref: "Category" }],
rootParent: { type: mongoose.Schema.Types.ObjectId, ref: "Category" },
priority: { type: Number, default: 0 },
showInMenu: Boolean, showInMenu: Boolean,
navIndex: {type: Number, default: null}, navIndex: { type: Number, default: null },
news: {type: Boolean, default: true}, news: { type: Boolean, default: true },
child: {type: Boolean, default: true}, child: { type: Boolean, default: true },
special: {type: Boolean, default: false}, special: { type: Boolean, default: false },
allowComment: {type: Boolean, default: false}, allowComment: { type: Boolean, default: false },
level: {type: Number, default: 1}, level: { type: Number, default: 1 },
siteMap: {type: Boolean, default: true}, siteMap: { type: Boolean, default: true },
modelType: String, modelType: String,
_creator: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}, _creator: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
_updatedBy: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}, _updatedBy: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
haveNews: {type: Boolean, default: false}, haveNews: { type: Boolean, default: false },
///// for client ///// for client
hasNewsTab: {type: Boolean, default: true}, hasNewsTab: { type: Boolean, default: true },
hasContentTab: {type: Boolean, default: true}, hasContentTab: { type: Boolean, default: true },
hasMediaTab: {type: Boolean, default: true}, hasMediaTab: { type: Boolean, default: true },
hasSubMenusTab: {type: Boolean, default: true}, hasSubMenusTab: { type: Boolean, default: true },
hasTermsTab: {type: Boolean, default: true}, hasTermsTab: { type: Boolean, default: true },
hasNotificationsTab: {type: Boolean, default: true}, hasNotificationsTab: { type: Boolean, default: true },
hasSpecNewsTab: {type: Boolean, default: true}, hasSpecNewsTab: { type: Boolean, default: true },
hasNazarTab: {type: Boolean, default: true}, hasNazarTab: { type: Boolean, default: true },
hasNewsFileTab: {type: Boolean, default: true}, hasNewsFileTab: { type: Boolean, default: true },
defaultPageType: {type: String, default: 'news'}, defaultPageType: { type: String, default: "news" },
/** page */ /** page */
showInFooter: {type: Number, enum: [0, 1, 2, 3], default: 0}, showInFooter: { type: Number, enum: [0, 1, 2, 3], default: 0 },
url: {type: String, default: null}, url: { type: String, default: null },
pageContent: String, pageContent: String,
terms: [CategoryTermsFile], terms: [CategoryTermsFile],
hasManagerInfo: {type: Boolean, default: true}, hasManagerInfo: { type: Boolean, default: true },
managerCover: {type: String, get: image}, managerCover: { type: String, get: image },
managerName: String, managerName: String,
managerDescription: String managerDescription: String,
}); });
CategorySchema.index({parent: 1, childs: 1}); CategorySchema.index({ parent: 1, childs: 1 });
CategorySchema CategorySchema.pre("findOne", autoPopulateSubs).pre("find", autoPopulateSubs);
.pre('findOne', autoPopulateSubs)
.pre('find', autoPopulateSubs);
module.exports = mongoose.model('Category', CategorySchema); module.exports = mongoose.model("Category", CategorySchema);
+1 -1
View File
@@ -28,7 +28,6 @@ module.exports.sms = async (phoneNumber, message) => {
SendDateTime: "", SendDateTime: "",
CanContinueInCaseOfError: "false", CanContinueInCaseOfError: "false",
}; };
const response = await axios.post( const response = await axios.post(
`http://RestfulSms.com/api/MessageSend`, `http://RestfulSms.com/api/MessageSend`,
data, data,
@@ -39,6 +38,7 @@ module.exports.sms = async (phoneNumber, message) => {
}, },
} }
); );
return response.data; return response.data;
} catch (e) { } catch (e) {
console.log(e); console.log(e);