mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-24 03:57:22 +08:00
[admin] add setting backup
This commit is contained in:
+3
-3
@@ -38,9 +38,9 @@
|
|||||||
<el-menu-item-group>
|
<el-menu-item-group>
|
||||||
<el-menu-item index="/exam-user"><i class="el-icon-menu" />Exam user</el-menu-item>
|
<el-menu-item index="/exam-user"><i class="el-icon-menu" />Exam user</el-menu-item>
|
||||||
</el-menu-item-group>
|
</el-menu-item-group>
|
||||||
<!-- <el-menu-item-group>-->
|
<el-menu-item-group>
|
||||||
<!-- <el-menu-item index="/setting"><i class="el-icon-menu" />Setting</el-menu-item>-->
|
<el-menu-item index="/setting"><i class="el-icon-menu" />Setting</el-menu-item>
|
||||||
<!-- </el-menu-item-group>-->
|
</el-menu-item-group>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
|
|||||||
Vendored
+3
@@ -5,3 +5,6 @@
|
|||||||
.nexus-help-text {
|
.nexus-help-text {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
.pre-line {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+21
@@ -32,9 +32,24 @@ const api = {
|
|||||||
getUserBase: (params = {}) => {
|
getUserBase: (params = {}) => {
|
||||||
return axios.get('user-base', {params: params});
|
return axios.get('user-base', {params: params});
|
||||||
},
|
},
|
||||||
|
getInviteInfo: (params = {}) => {
|
||||||
|
return axios.get('user-invite-info', {params: params});
|
||||||
|
},
|
||||||
|
getUserModComment: (params = {}) => {
|
||||||
|
return axios.get('user-mod-comment', {params: params});
|
||||||
|
},
|
||||||
storeUser: (params = {}) => {
|
storeUser: (params = {}) => {
|
||||||
return axios.post('users', params);
|
return axios.post('users', params);
|
||||||
},
|
},
|
||||||
|
disableUser: (params = {}) => {
|
||||||
|
return axios.post('user-disable', params);
|
||||||
|
},
|
||||||
|
enableUser: (params = {}) => {
|
||||||
|
return axios.post('user-enable', params);
|
||||||
|
},
|
||||||
|
resetPassword: (params = {}) => {
|
||||||
|
return axios.post('user-reset-password', params);
|
||||||
|
},
|
||||||
listUserMatchExams: (params = {}) => {
|
listUserMatchExams: (params = {}) => {
|
||||||
return axios.get('user-match-exams', {params: params});
|
return axios.get('user-match-exams', {params: params});
|
||||||
},
|
},
|
||||||
@@ -69,6 +84,12 @@ const api = {
|
|||||||
storeExamUser: (params) => {
|
storeExamUser: (params) => {
|
||||||
return axios.post('exam-users', params);
|
return axios.post('exam-users', params);
|
||||||
},
|
},
|
||||||
|
storeSetting: (params) => {
|
||||||
|
return axios.post('settings', params);
|
||||||
|
},
|
||||||
|
listSetting: (params) => {
|
||||||
|
return axios.get('settings', {params});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
<template>
|
||||||
|
<el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData">
|
||||||
|
<el-form-item label="Enabled" prop="backup.enabled">
|
||||||
|
<el-radio v-model="formData.backup.enabled" label="yes">Yes</el-radio>
|
||||||
|
<el-radio v-model="formData.backup.enabled" label="no">No</el-radio>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Enable backup or not.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Frequency" prop="backup.frequency">
|
||||||
|
<el-radio v-model="formData.backup.frequency" label="daily">Daily</el-radio>
|
||||||
|
<el-radio v-model="formData.backup.frequency" label="hourly">Hourly</el-radio>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Backup Frequency.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Hour" prop="backup.hour">
|
||||||
|
<el-select v-model="formData.backup.hour" filterable >
|
||||||
|
<el-option
|
||||||
|
v-for="item in 24"
|
||||||
|
:key="item"
|
||||||
|
:label="item-1"
|
||||||
|
:value="item-1">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Do backup at this hour, If frequency = 'hourly', this value will be ignore.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Minute" prop="backup.minute">
|
||||||
|
<el-select v-model="formData.backup.minute" filterable >
|
||||||
|
<el-option
|
||||||
|
v-for="item in 60"
|
||||||
|
:key="item"
|
||||||
|
:label="item-1"
|
||||||
|
:value="item-1">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Do backup at this minute.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Google drive client ID" prop="backup.google_drive_client_id">
|
||||||
|
<el-input v-model="formData.backup.google_drive_client_id" label="Google drive client ID"></el-input>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Google drive client ID.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Google drive client secret" prop="backup.google_drive_client_secret">
|
||||||
|
<el-input v-model="formData.backup.google_drive_client_secret" label="Google drive client secret"></el-input>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Google drive client secret.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Google drive refresh token" prop="backup.google_drive_refresh_token">
|
||||||
|
<el-input v-model="formData.backup.google_drive_refresh_token" label="Google drive refresh token"></el-input>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Google drive refresh token.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Google drive folder ID" prop="backup.google_drive_folder_id">
|
||||||
|
<el-input v-model="formData.backup.google_drive_folder_id" label="Google drive folder ID"></el-input>
|
||||||
|
<div class="nexus-help-text">
|
||||||
|
Google drive folder ID. If not set, will store in root.
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { localGet } from '../../utils'
|
||||||
|
import api from "../../utils/api";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingFormBasic',
|
||||||
|
setup() {
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const formRef = ref(null)
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const { id } = route.query
|
||||||
|
const state = reactive({
|
||||||
|
token: localGet('token') || '',
|
||||||
|
id: id,
|
||||||
|
allClasses: [],
|
||||||
|
formData: {
|
||||||
|
backup: {
|
||||||
|
enabled: '',
|
||||||
|
frequency: '',
|
||||||
|
hour: '',
|
||||||
|
minute: '',
|
||||||
|
google_drive_client_id: '',
|
||||||
|
google_drive_client_secret: '',
|
||||||
|
google_drive_refresh_token: '',
|
||||||
|
google_drive_folder_id: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'backup.enabled': [{ required: 'true', }],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
onMounted( () => {
|
||||||
|
|
||||||
|
})
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
const submitAdd = () => {
|
||||||
|
formRef.value.validate(async (vaild) => {
|
||||||
|
if (vaild) {
|
||||||
|
let params = state.formData;
|
||||||
|
console.log(params)
|
||||||
|
let res = await api.storeSetting(params)
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleBeforeUpload = (file) => {
|
||||||
|
const sufix = file.name.split('.')[1] || ''
|
||||||
|
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||||
|
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const listSetting = async () => {
|
||||||
|
let res = await api.listSetting({prefix: "backup"})
|
||||||
|
console.log("listSetting", res)
|
||||||
|
state.formData = res.data
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
formRef,
|
||||||
|
submitAdd,
|
||||||
|
handleBeforeUpload,
|
||||||
|
listSetting,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -24,7 +24,6 @@ export default {
|
|||||||
name: 'SettingFormBasic',
|
name: 'SettingFormBasic',
|
||||||
setup() {
|
setup() {
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
console.log('proxy', proxy)
|
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -45,8 +44,6 @@ export default {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
onMounted( () => {
|
onMounted( () => {
|
||||||
listAllClass()
|
|
||||||
listAllIndex()
|
|
||||||
if (id) {
|
if (id) {
|
||||||
api.getExam(id).then(res => {
|
api.getExam(id).then(res => {
|
||||||
state.formData.name = res.data.name
|
state.formData.name = res.data.name
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-tabs type="border-card">
|
<el-tabs type="border-card" @tab-click="handleTabClick">
|
||||||
|
<el-tab-pane label="Backup"><FormBackup ref="backup" /></el-tab-pane>
|
||||||
<el-tab-pane label="Basic"><FormBasic /></el-tab-pane>
|
<el-tab-pane label="Basic"><FormBasic /></el-tab-pane>
|
||||||
<el-tab-pane label="Main"><FormMain /></el-tab-pane>
|
|
||||||
<el-tab-pane label="Smtp">Smtp</el-tab-pane>
|
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -14,21 +13,22 @@ import api from '../../utils/api'
|
|||||||
import { useTable, renderTableData } from '../../utils/table'
|
import { useTable, renderTableData } from '../../utils/table'
|
||||||
import FormBasic from './form-basic.vue'
|
import FormBasic from './form-basic.vue'
|
||||||
import FormMain from './form-main.vue'
|
import FormMain from './form-main.vue'
|
||||||
|
import FormBackup from './form-backup.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Setting',
|
name: 'Setting',
|
||||||
components: {
|
components: {
|
||||||
FormBasic, FormMain,
|
FormBasic, FormMain, FormBackup
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const multipleTable = ref(null)
|
const multipleTable = ref(null)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const backup = ref(null)
|
||||||
const state = useTable()
|
const state = useTable()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('ExamTable onMounted')
|
console.log('Setting onMounted')
|
||||||
fetchTableData()
|
backup.value.listSetting()
|
||||||
})
|
})
|
||||||
const fetchTableData = async () => {
|
const fetchTableData = async () => {
|
||||||
state.loading = true
|
state.loading = true
|
||||||
@@ -55,6 +55,9 @@ export default {
|
|||||||
state.query.page = val
|
state.query.page = val
|
||||||
fetchTableData()
|
fetchTableData()
|
||||||
}
|
}
|
||||||
|
const handleTabClick = (val) => {
|
||||||
|
console.log('handleTabClick', val)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
multipleTable,
|
multipleTable,
|
||||||
@@ -62,8 +65,10 @@ export default {
|
|||||||
handleAdd,
|
handleAdd,
|
||||||
handleEdit,
|
handleEdit,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
|
handleTabClick,
|
||||||
fetchTableData,
|
fetchTableData,
|
||||||
changePage,
|
changePage,
|
||||||
|
backup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
<td></td>
|
<td></td>
|
||||||
<td colspan="7">
|
<td colspan="7">
|
||||||
<div class="other-actions">
|
<div class="other-actions">
|
||||||
<el-button type="primary" size="mini">Reset password</el-button>
|
<el-button type="primary" size="mini" @click="handleGetModComment">Mod comment</el-button>
|
||||||
<el-button type="primary" size="mini">PM</el-button>
|
<el-button type="primary" size="mini" @click="handleResetPassword">Reset password</el-button>
|
||||||
<el-button type="primary" size="mini" @click="handleAssignExam">Assign exam</el-button>
|
<el-button type="primary" size="mini" @click="handleAssignExam">Assign exam</el-button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -30,6 +30,25 @@
|
|||||||
<td>{{baseInfo.email}}</td>
|
<td>{{baseInfo.email}}</td>
|
||||||
<td><el-button size="mini">Change</el-button></td>
|
<td><el-button size="mini">Change</el-button></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Enabled</td>
|
||||||
|
<td>{{baseInfo.enabled}}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="baseInfo.enabled && baseInfo.enabled == 'yes'">
|
||||||
|
<el-button size="mini" @click="handleDisableUser">Disable</el-button>
|
||||||
|
</template>
|
||||||
|
<template v-if="baseInfo.enabled && baseInfo.enabled == 'no'">
|
||||||
|
<el-popconfirm
|
||||||
|
title="Confirm Enable ?"
|
||||||
|
@confirm="handleEnableUser"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button size="mini">Enable</el-button>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Added</td>
|
<td>Added</td>
|
||||||
<td>{{baseInfo.added}}</td>
|
<td>{{baseInfo.added}}</td>
|
||||||
@@ -38,6 +57,11 @@
|
|||||||
<td>Class</td>
|
<td>Class</td>
|
||||||
<td>{{baseInfo.class_text}}</td>
|
<td>{{baseInfo.class_text}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Invite by</td>
|
||||||
|
<td>{{baseInfo.inviter && baseInfo.inviter.username}}</td>
|
||||||
|
<td><el-button size="mini" @click="handleViewInviteInfo">View</el-button></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Uploaded</td>
|
<td>Uploaded</td>
|
||||||
<td>{{baseInfo.uploaded_text}}</td>
|
<td>{{baseInfo.uploaded_text}}</td>
|
||||||
@@ -113,6 +137,11 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<DialogAssignExam ref="assignExam" :reload="fetchPageData"/>
|
<DialogAssignExam ref="assignExam" :reload="fetchPageData"/>
|
||||||
|
<DialogViewInviteInfo ref="viewInviteInfo" />
|
||||||
|
<DialogDisableUser ref="disableUser" :reload="fetchPageData" />
|
||||||
|
<DialogModComment ref="modComment" />
|
||||||
|
<DialogModComment ref="modComment" />
|
||||||
|
<DialogResetPassword ref="resetPassword" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -121,17 +150,25 @@ import { ElMessage } from 'element-plus'
|
|||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import api from '../../utils/api'
|
import api from '../../utils/api'
|
||||||
import DialogAssignExam from './dialog-assign-exam.vue'
|
import DialogAssignExam from './dialog-assign-exam.vue'
|
||||||
|
import DialogViewInviteInfo from './dialog-invite-info.vue'
|
||||||
|
import DialogDisableUser from './dialog-disable-user.vue'
|
||||||
|
import DialogModComment from './dialog-mod-comment.vue'
|
||||||
|
import DialogResetPassword from './dialog-reset-password.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "UserDetail",
|
name: "UserDetail",
|
||||||
components: {
|
components: {
|
||||||
DialogAssignExam
|
DialogAssignExam, DialogViewInviteInfo, DialogDisableUser, DialogModComment, DialogResetPassword
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { id } = route.query
|
const { id } = route.query
|
||||||
const assignExam = ref(null)
|
const assignExam = ref(null)
|
||||||
|
const viewInviteInfo = ref(null)
|
||||||
|
const disableUser = ref(null)
|
||||||
|
const modComment = ref(null)
|
||||||
|
const resetPassword = ref(null)
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
baseInfo: {},
|
baseInfo: {},
|
||||||
@@ -152,15 +189,43 @@ export default {
|
|||||||
ElMessage.success(res.msg)
|
ElMessage.success(res.msg)
|
||||||
await fetchPageData()
|
await fetchPageData()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAssignExam = async () => {
|
const handleAssignExam = async () => {
|
||||||
assignExam.value.open(id)
|
assignExam.value.open(id)
|
||||||
}
|
}
|
||||||
|
const handleViewInviteInfo = async () => {
|
||||||
|
viewInviteInfo.value.open(id)
|
||||||
|
}
|
||||||
|
const handleDisableUser = async () => {
|
||||||
|
disableUser.value.open(id)
|
||||||
|
}
|
||||||
|
const handleEnableUser = async () => {
|
||||||
|
let res = await api.enableUser({uid: id})
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
await fetchPageData()
|
||||||
|
}
|
||||||
|
const handleGetModComment = async () => {
|
||||||
|
modComment.value.open(id)
|
||||||
|
}
|
||||||
|
const handleResetPassword = async () => {
|
||||||
|
resetPassword.value.open(id)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
handleRemoveExam,
|
handleRemoveExam,
|
||||||
handleAssignExam,
|
handleAssignExam,
|
||||||
|
handleEnableUser,
|
||||||
|
handleViewInviteInfo,
|
||||||
|
handleDisableUser,
|
||||||
|
handleGetModComment,
|
||||||
|
handleResetPassword,
|
||||||
|
fetchPageData,
|
||||||
assignExam,
|
assignExam,
|
||||||
fetchPageData
|
viewInviteInfo,
|
||||||
|
disableUser,
|
||||||
|
modComment,
|
||||||
|
resetPassword,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="Disable user"
|
||||||
|
v-model="visible"
|
||||||
|
center
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
:model="formData"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="loading"
|
||||||
|
ref="formRef"
|
||||||
|
:rules="rules">
|
||||||
|
<el-form-item label="Reason" prop="reason">
|
||||||
|
<el-input type="textarea" v-model="formData.reason"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">Cancel</el-button>
|
||||||
|
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
import api from '../../utils/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DialogDisableUser",
|
||||||
|
props: {
|
||||||
|
reload: Function
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const formRef = ref(null)
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
visible: false,
|
||||||
|
formData: {
|
||||||
|
uid: 0,
|
||||||
|
reason: '',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
reason: [{ required: 'true'}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const open = (uid) => {
|
||||||
|
state.formData.uid = uid
|
||||||
|
state.visible = true
|
||||||
|
|
||||||
|
}
|
||||||
|
const handleSubmit = () => {
|
||||||
|
formRef.value.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
let res = await api.disableUser(state.formData)
|
||||||
|
state.visible = false
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
if (props.reload) {
|
||||||
|
props.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
handleSubmit,
|
||||||
|
formRef,
|
||||||
|
open,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="Invite info"
|
||||||
|
v-model="visible"
|
||||||
|
center
|
||||||
|
width="60%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-table :data="inviteInfo" v-loading="loading">
|
||||||
|
<el-table-column prop="id" label="ID" width="55"></el-table-column>
|
||||||
|
<el-table-column prop="inviter_user.username" label="Inviter"></el-table-column>
|
||||||
|
<el-table-column prop="invitee" label="Receive email"></el-table-column>
|
||||||
|
<el-table-column prop="hash" label="Hash"></el-table-column>
|
||||||
|
<el-table-column prop="valid_text" label="Hash valid" width="100"></el-table-column>
|
||||||
|
<el-table-column prop="invitee_register_email" label="Register email"></el-table-column>
|
||||||
|
<el-table-column prop="time_invited" label="Time invited"></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
import api from '../../utils/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DialogInviteInfo",
|
||||||
|
props: {
|
||||||
|
reload: Function
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const formRef = ref(null)
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
visible: false,
|
||||||
|
uid: 0,
|
||||||
|
inviteInfo: [],
|
||||||
|
})
|
||||||
|
const getInviteInfo = async () => {
|
||||||
|
let res = await api.getInviteInfo({uid: state.uid})
|
||||||
|
state.inviteInfo.push(res.data)
|
||||||
|
}
|
||||||
|
const open = (uid) => {
|
||||||
|
state.uid = uid
|
||||||
|
if (state.inviteInfo.length == 0) {
|
||||||
|
state.loading = true
|
||||||
|
getInviteInfo()
|
||||||
|
state.loading = false
|
||||||
|
}
|
||||||
|
state.visible = true
|
||||||
|
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
formRef,
|
||||||
|
open,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="Mod comment"
|
||||||
|
v-model="visible"
|
||||||
|
center
|
||||||
|
width="40%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-card v-loading="loading">
|
||||||
|
<div v-html="modComment" class="pre-line"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
import api from '../../utils/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DialogModComment",
|
||||||
|
props: {
|
||||||
|
reload: Function
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const formRef = ref(null)
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
visible: false,
|
||||||
|
uid: 0,
|
||||||
|
modComment: ''
|
||||||
|
})
|
||||||
|
const getUserModComment = async () => {
|
||||||
|
let res = await api.getUserModComment({uid: state.uid})
|
||||||
|
state.modComment = res.data
|
||||||
|
}
|
||||||
|
const open = (uid) => {
|
||||||
|
state.uid = uid
|
||||||
|
if (!state.modComment) {
|
||||||
|
state.loading = true
|
||||||
|
getUserModComment()
|
||||||
|
state.loading = false
|
||||||
|
}
|
||||||
|
state.visible = true
|
||||||
|
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
formRef,
|
||||||
|
open,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
title="Reset password"
|
||||||
|
v-model="visible"
|
||||||
|
center
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
:model="formData"
|
||||||
|
label-width="200px"
|
||||||
|
v-loading="loading"
|
||||||
|
ref="formRef"
|
||||||
|
:rules="rules">
|
||||||
|
<el-form-item label="Password" prop="password">
|
||||||
|
<el-input v-model="formData.password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Password confirmation" prop="password_confirmation">
|
||||||
|
<el-input v-model="formData.password_confirmation"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">Cancel</el-button>
|
||||||
|
<el-button type="primary" @click="handleSubmit">Save</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
import api from '../../utils/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DialogResetPassword",
|
||||||
|
props: {
|
||||||
|
reload: Function
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const formRef = ref(null)
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
visible: false,
|
||||||
|
formData: {
|
||||||
|
uid: 0,
|
||||||
|
password: '',
|
||||||
|
password_confirmation: ''
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
password: [{ required: 'true'}],
|
||||||
|
password_confirmation: [{ required: 'true'}],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const open = (uid) => {
|
||||||
|
state.formData.uid = uid
|
||||||
|
state.visible = true
|
||||||
|
|
||||||
|
}
|
||||||
|
const handleSubmit = () => {
|
||||||
|
formRef.value.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
let res = await api.resetPassword(state.formData)
|
||||||
|
state.visible = false
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
if (props.reload) {
|
||||||
|
props.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
handleSubmit,
|
||||||
|
formRef,
|
||||||
|
open,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -57,9 +57,9 @@ class Test extends Command
|
|||||||
// dd($r);
|
// dd($r);
|
||||||
// $rep->assignCronjob();
|
// $rep->assignCronjob();
|
||||||
// $r = $rep->cronjobCheckout();
|
// $r = $rep->cronjobCheckout();
|
||||||
$disk = Storage::disk('google_dirve');
|
// $disk = Storage::disk('google_dirve');
|
||||||
$r = $disk->put('/', base_path('composer.json'));
|
// $r = $disk->put('/', base_path('composer.json'));
|
||||||
dd($r);
|
// $r = DB::table('users')->where('id', 1)->update(['modcomment' => DB::raw("concat_ws(',', 'ddddd', modcomment)")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ class UserResetPassword extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'user:reset_password {username} {password} {password_confirmation}';
|
protected $signature = 'user:reset_password {uid} {password} {password_confirmation}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Reset user password, arguments: username password password_comfirmation';
|
protected $description = 'Reset user password, arguments: uid password password_comfirmation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
@@ -38,15 +38,15 @@ class UserResetPassword extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$username = $this->argument('username');
|
$uid = $this->argument('uid');
|
||||||
$password = $this->argument('password');
|
$password = $this->argument('password');
|
||||||
$passwordConfirmation = $this->argument('password_confirmation');
|
$passwordConfirmation = $this->argument('password_confirmation');
|
||||||
$log = "username: $username, password: $password, passwordConfirmation: $passwordConfirmation";
|
$log = "uid: $uid, password: $password, passwordConfirmation: $passwordConfirmation";
|
||||||
$this->info($log);
|
$this->info($log);
|
||||||
do_log($log);
|
do_log($log);
|
||||||
|
|
||||||
$rep = new UserRepository();
|
$rep = new UserRepository();
|
||||||
$result = $rep->resetPassword($username, $password, $passwordConfirmation);
|
$result = $rep->resetPassword($uid, $password, $passwordConfirmation);
|
||||||
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
$log = sprintf('[%s], %s, result: %s', REQUEST_ID, __METHOD__, var_export($result, true));
|
||||||
$this->info($log);
|
$this->info($log);
|
||||||
do_log($log);
|
do_log($log);
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Repositories\SettingRepository;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class SettingController extends Controller
|
||||||
|
{
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
public function __construct(SettingRepository $repository)
|
||||||
|
{
|
||||||
|
$this->repository = $repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$result = $this->repository->getList($request->all());
|
||||||
|
return $this->success($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$result = $this->repository->store($request->all());
|
||||||
|
return $this->success($result, 'Save setting success!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Resources\ExamResource;
|
use App\Http\Resources\ExamResource;
|
||||||
|
use App\Http\Resources\InviteResource;
|
||||||
use App\Http\Resources\UserResource;
|
use App\Http\Resources\UserResource;
|
||||||
use App\Repositories\ExamRepository;
|
use App\Repositories\ExamRepository;
|
||||||
use App\Repositories\UserRepository;
|
use App\Repositories\UserRepository;
|
||||||
@@ -90,14 +91,13 @@ class UserController extends Controller
|
|||||||
public function resetPassword(Request $request)
|
public function resetPassword(Request $request)
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'username' => 'required|string|exists:users',
|
'uid' => 'required',
|
||||||
'password' => 'required|string|min:6|max:40',
|
'password' => 'required|string|min:6|max:40',
|
||||||
'password_confirmation' => 'required|same:password',
|
'password_confirmation' => 'required|same:password',
|
||||||
];
|
];
|
||||||
$request->validate($rules);
|
$request->validate($rules);
|
||||||
$result = $this->repository->resetPassword($request->repositoryname, $request->password, $request->password_confirmation);
|
$result = $this->repository->resetPassword($request->uid, $request->password, $request->password_confirmation);
|
||||||
$resource = new UserResource($result);
|
return $this->success($result, 'Reset password success!');
|
||||||
return $this->success($resource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function classes()
|
public function classes()
|
||||||
@@ -132,6 +132,35 @@ class UserController extends Controller
|
|||||||
'reason' => 'required',
|
'reason' => 'required',
|
||||||
]);
|
]);
|
||||||
$result = $this->repository->disableUser(Auth::user(), $request->uid, $request->reason);
|
$result = $this->repository->disableUser(Auth::user(), $request->uid, $request->reason);
|
||||||
|
return $this->success($result, 'Disable user success!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enable(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'uid' => 'required',
|
||||||
|
]);
|
||||||
|
$result = $this->repository->enableUser(Auth::user(), $request->uid);
|
||||||
|
return $this->success($result, 'Enable user success!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function inviteInfo(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'uid' => 'required',
|
||||||
|
]);
|
||||||
|
$result = $this->repository->getInviteInfo($request->uid);
|
||||||
|
$resource = $result ? (new InviteResource($result)) : null;
|
||||||
|
return $this->success($resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function modComment(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'uid' => 'required',
|
||||||
|
]);
|
||||||
|
$result = $this->repository->getModComment($request->uid);
|
||||||
return $this->success($result);
|
return $this->success($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class InviteResource extends JsonResource
|
|||||||
'invitee_register_uid' => $this->invitee_register_uid,
|
'invitee_register_uid' => $this->invitee_register_uid,
|
||||||
'invitee_register_email' => $this->invitee_register_email,
|
'invitee_register_email' => $this->invitee_register_email,
|
||||||
'invitee_register_username' => $this->invitee_register_username,
|
'invitee_register_username' => $this->invitee_register_username,
|
||||||
|
'inviter_user' => new UserResource($this->whenLoaded('inviter_user')),
|
||||||
|
'invitee_user' => new UserResource($this->whenLoaded('invitee_user')),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class UserResource extends JsonResource
|
|||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
'username' => $this->username,
|
'username' => $this->username,
|
||||||
'status' => $this->status,
|
'status' => $this->status,
|
||||||
|
'enabled' => $this->enabled,
|
||||||
'added' => format_datetime($this->added),
|
'added' => format_datetime($this->added),
|
||||||
'class' => $this->class,
|
'class' => $this->class,
|
||||||
'class_text' => $this->class_text,
|
'class_text' => $this->class_text,
|
||||||
|
|||||||
@@ -24,4 +24,14 @@ class Invite extends NexusModel
|
|||||||
return self::$validInfo[$this->valid]['text'] ?? '';
|
return self::$validInfo[$this->valid]['text'] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function inviter_user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'inviter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invitee_user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'invitee_register_uid');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -65,7 +65,6 @@ class User extends Authenticatable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 为数组 / JSON 序列化准备日期。
|
* 为数组 / JSON 序列化准备日期。
|
||||||
*
|
*
|
||||||
@@ -82,7 +81,9 @@ class User extends Authenticatable
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['username', 'email', 'passhash', 'secret', 'editsecret', 'added'];
|
protected $fillable = [
|
||||||
|
'username', 'email', 'passhash', 'secret', 'stylesheet', 'editsecret', 'added', 'modcomment', 'enabled', 'status'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be hidden for arrays.
|
* The attributes that should be hidden for arrays.
|
||||||
@@ -105,7 +106,7 @@ class User extends Authenticatable
|
|||||||
public static $commonFields = [
|
public static $commonFields = [
|
||||||
'id', 'username', 'email', 'class', 'status', 'added', 'avatar',
|
'id', 'username', 'email', 'class', 'status', 'added', 'avatar',
|
||||||
'uploaded', 'downloaded', 'seedbonus', 'seedtime', 'leechtime',
|
'uploaded', 'downloaded', 'seedbonus', 'seedtime', 'leechtime',
|
||||||
'invited_by',
|
'invited_by', 'enabled',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function checkIsNormal(array $fields = ['status', 'enabled'])
|
public function checkIsNormal(array $fields = ['status', 'enabled'])
|
||||||
@@ -160,7 +161,9 @@ class User extends Authenticatable
|
|||||||
if (!$this->exists) {
|
if (!$this->exists) {
|
||||||
throw new \RuntimeException('This mehtod only works when user exists!');
|
throw new \RuntimeException('This mehtod only works when user exists!');
|
||||||
}
|
}
|
||||||
$update['modcomment'] = DB::raw("concat_ws('\n', $modComment, modcomment)");
|
//@todo how to do prepare bindings here ?
|
||||||
|
$modComment = addslashes($modComment);
|
||||||
|
$update['modcomment'] = DB::raw("concat_ws('\n', '$modComment', modcomment)");
|
||||||
return $this->update($update);
|
return $this->update($update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Exceptions\NexusException;
|
||||||
|
use App\Models\Setting;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class SettingRepository extends BaseRepository
|
||||||
|
{
|
||||||
|
public function getList(array $params)
|
||||||
|
{
|
||||||
|
$query = Setting::query();
|
||||||
|
if (!empty($params['prefix'])) {
|
||||||
|
$query->where('name', 'like', "{$params['prefix']}%");
|
||||||
|
}
|
||||||
|
$settings = $query->get();
|
||||||
|
$results = [];
|
||||||
|
foreach ($settings as $setting) {
|
||||||
|
$value = $setting->value;
|
||||||
|
$arr = json_decode($value, true);
|
||||||
|
if (is_array($arr)) {
|
||||||
|
$value = $arr;
|
||||||
|
}
|
||||||
|
Arr::set($results, $setting->name, $value);
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(array $params)
|
||||||
|
{
|
||||||
|
$settingModel = new Setting();
|
||||||
|
$values = [];
|
||||||
|
foreach ($params as $prefix => $nameValues) {
|
||||||
|
if (!is_array($nameValues)) {
|
||||||
|
throw new \InvalidArgumentException("Unsupported parameter format.");
|
||||||
|
}
|
||||||
|
foreach ($nameValues as $name => $value) {
|
||||||
|
$valueArr = Arr::wrap($value);
|
||||||
|
array_walk_recursive($valueArr, function ($item) {return addslashes($item);});
|
||||||
|
if (is_array($value)) {
|
||||||
|
$valueStr = json_encode($valueArr);
|
||||||
|
} else {
|
||||||
|
$valueStr = Arr::first($valueArr);
|
||||||
|
}
|
||||||
|
$values[] = sprintf("('%s', '%s')", addslashes("$prefix.$name"), addslashes($valueStr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty($values)) {
|
||||||
|
do_log("no values");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$sql = sprintf(
|
||||||
|
"insert into `%s` (`name`, `value`) values %s on duplicate key update `value` = values(`value`)",
|
||||||
|
$settingModel->getTable(), implode(', ', $values)
|
||||||
|
);
|
||||||
|
$result = DB::insert($sql);
|
||||||
|
do_log("sql: $sql, result: $result");
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Exceptions\NexusException;
|
||||||
use App\Http\Resources\ExamUserResource;
|
use App\Http\Resources\ExamUserResource;
|
||||||
use App\Http\Resources\UserResource;
|
use App\Http\Resources\UserResource;
|
||||||
use App\Models\ExamUser;
|
use App\Models\ExamUser;
|
||||||
@@ -74,12 +75,12 @@ class UserRepository extends BaseRepository
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetPassword($username, $password, $passwordConfirmation)
|
public function resetPassword($id, $password, $passwordConfirmation)
|
||||||
{
|
{
|
||||||
if ($password != $passwordConfirmation) {
|
if ($password != $passwordConfirmation) {
|
||||||
throw new \InvalidArgumentException("password confirmation != password");
|
throw new \InvalidArgumentException("password confirmation != password");
|
||||||
}
|
}
|
||||||
$user = User::query()->where('username', $username)->firstOrFail(['id', 'username']);
|
$user = User::query()->findOrFail($id, ['id', 'username']);
|
||||||
$secret = mksecret();
|
$secret = mksecret();
|
||||||
$passhash = md5($secret . $password . $secret);
|
$passhash = md5($secret . $password . $secret);
|
||||||
$update = [
|
$update = [
|
||||||
@@ -87,7 +88,7 @@ class UserRepository extends BaseRepository
|
|||||||
'passhash' => $passhash,
|
'passhash' => $passhash,
|
||||||
];
|
];
|
||||||
$user->update($update);
|
$user->update($update);
|
||||||
return $user;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listClass()
|
public function listClass()
|
||||||
@@ -101,7 +102,10 @@ class UserRepository extends BaseRepository
|
|||||||
|
|
||||||
public function disableUser(User $operator, $uid, $reason)
|
public function disableUser(User $operator, $uid, $reason)
|
||||||
{
|
{
|
||||||
$targetUser = User::query()->findOrFail(['id', 'username']);
|
$targetUser = User::query()->findOrFail($uid, ['id', 'enabled', 'username']);
|
||||||
|
if ($targetUser->enabled == User::ENABLED_NO) {
|
||||||
|
throw new NexusException('Already disabled!');
|
||||||
|
}
|
||||||
$banLog = [
|
$banLog = [
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
'username' => $targetUser->username,
|
'username' => $targetUser->username,
|
||||||
@@ -110,9 +114,34 @@ class UserRepository extends BaseRepository
|
|||||||
];
|
];
|
||||||
$modCommentText = sprintf("Disable by %s, reason: %s.", $operator->username, $reason);
|
$modCommentText = sprintf("Disable by %s, reason: %s.", $operator->username, $reason);
|
||||||
DB::transaction(function () use ($targetUser, $banLog, $modCommentText) {
|
DB::transaction(function () use ($targetUser, $banLog, $modCommentText) {
|
||||||
$targetUser->updateWithModComment(['enable' => User::ENABLED_NO], $modCommentText);
|
$targetUser->updateWithModComment(['enabled' => User::ENABLED_NO], $modCommentText);
|
||||||
UserBanLog::query()->insert($banLog);
|
UserBanLog::query()->insert($banLog);
|
||||||
});
|
});
|
||||||
|
do_log("user: $uid, $modCommentText");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function enableUser(User $operator, $uid)
|
||||||
|
{
|
||||||
|
$targetUser = User::query()->findOrFail($uid, ['id', 'enabled', 'username']);
|
||||||
|
if ($targetUser->enabled == User::ENABLED_YES) {
|
||||||
|
throw new NexusException('Already enabled!');
|
||||||
|
}
|
||||||
|
$modCommentText = sprintf("Enable by %s.", $operator->username);
|
||||||
|
$targetUser->updateWithModComment(['enabled' => User::ENABLED_YES], $modCommentText);
|
||||||
|
do_log("user: $uid, $modCommentText");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInviteInfo($id)
|
||||||
|
{
|
||||||
|
$user = User::query()->findOrFail($id, ['id']);
|
||||||
|
return $user->invitee_code()->with('inviter_user')->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getModComment($id)
|
||||||
|
{
|
||||||
|
$user = User::query()->findOrFail($id, ['modcomment']);
|
||||||
|
return $user->modcomment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ function nexus_json_encode($data)
|
|||||||
|
|
||||||
function api(...$args)
|
function api(...$args)
|
||||||
{
|
{
|
||||||
if (!isset($args[2])) {
|
if (func_num_args() < 3) {
|
||||||
//参数少于3个时,默认为错误状态。
|
//参数少于3个时,默认为错误状态。
|
||||||
$ret = -1;
|
$ret = -1;
|
||||||
$msg = isset($args[0]) ? $args[0] : 'ERROR';
|
$msg = isset($args[0]) ? $args[0] : 'ERROR';
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ Route::group(['middleware' => ['auth:sanctum', 'permission', 'locale']], functio
|
|||||||
Route::resource('users', \App\Http\Controllers\UserController::class);
|
Route::resource('users', \App\Http\Controllers\UserController::class);
|
||||||
Route::get('user-base', [\App\Http\Controllers\UserController::class, 'base']);
|
Route::get('user-base', [\App\Http\Controllers\UserController::class, 'base']);
|
||||||
Route::get('user-classes', [\App\Http\Controllers\UserController::class, 'classes']);
|
Route::get('user-classes', [\App\Http\Controllers\UserController::class, 'classes']);
|
||||||
|
Route::get('user-invite-info', [\App\Http\Controllers\UserController::class, 'inviteInfo']);
|
||||||
Route::get('user-match-exams', [\App\Http\Controllers\UserController::class, 'matchExams']);
|
Route::get('user-match-exams', [\App\Http\Controllers\UserController::class, 'matchExams']);
|
||||||
|
Route::get('user-mod-comment', [\App\Http\Controllers\UserController::class, 'modComment']);
|
||||||
Route::post('user-disable', [\App\Http\Controllers\UserController::class, 'disable']);
|
Route::post('user-disable', [\App\Http\Controllers\UserController::class, 'disable']);
|
||||||
|
Route::post('user-enable', [\App\Http\Controllers\UserController::class, 'enable']);
|
||||||
|
Route::post('user-reset-password', [\App\Http\Controllers\UserController::class, 'resetPassword']);
|
||||||
|
|
||||||
Route::resource('exams', \App\Http\Controllers\ExamController::class);
|
Route::resource('exams', \App\Http\Controllers\ExamController::class);
|
||||||
Route::get('exam-indexes', [\App\Http\Controllers\ExamController::class, 'indexes']);
|
Route::get('exam-indexes', [\App\Http\Controllers\ExamController::class, 'indexes']);
|
||||||
@@ -32,6 +36,8 @@ Route::group(['middleware' => ['auth:sanctum', 'permission', 'locale']], functio
|
|||||||
|
|
||||||
Route::get('system-info', [\App\Http\Controllers\ToolController::class, 'systemInfo']);
|
Route::get('system-info', [\App\Http\Controllers\ToolController::class, 'systemInfo']);
|
||||||
|
|
||||||
|
Route::resource('settings', \App\Http\Controllers\SettingController::class);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::post('login', [\App\Http\Controllers\AuthenticateController::class, 'login']);
|
Route::post('login', [\App\Http\Controllers\AuthenticateController::class, 'login']);
|
||||||
|
|||||||
Reference in New Issue
Block a user