mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
optimized user auth
This commit is contained in:
@@ -1,28 +1,53 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"crawlab/constants"
|
||||
"crawlab/routes"
|
||||
"crawlab/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AuthorizationMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
tokenStr := c.GetHeader("Authorization")
|
||||
if c.Request.URL.Path == "/login" || (c.Request.URL.Path == "/users" && c.Request.Method == "PUT") {
|
||||
// 如果为登录或注册,不用校验
|
||||
if c.Request.URL.Path == "/login" ||
|
||||
(c.Request.URL.Path == "/users" && c.Request.Method == "PUT") ||
|
||||
strings.HasSuffix(c.Request.URL.Path, "download") {
|
||||
c.Next()
|
||||
} else {
|
||||
_, err := services.CheckToken(tokenStr)
|
||||
if err == nil {
|
||||
c.Next()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取token string
|
||||
tokenStr := c.GetHeader("Authorization")
|
||||
|
||||
// 校验token
|
||||
user, err := services.CheckToken(tokenStr)
|
||||
|
||||
// 校验失败,返回错误响应
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, routes.Response{
|
||||
Status: "ok",
|
||||
Message: "unauthorized",
|
||||
Error: "unauthorized",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 如果为普通权限,校验请求地址是否符合要求
|
||||
if user.Role == constants.RoleNormal {
|
||||
if strings.HasPrefix(strings.ToLower(c.Request.URL.Path), "/users") {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, routes.Response{
|
||||
Status: "ok",
|
||||
Message: "unauthorized",
|
||||
Error: "unauthorized",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 校验成功
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"crawlab/database"
|
||||
"crawlab/utils"
|
||||
"github.com/apex/log"
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
@@ -127,6 +128,12 @@ func UpdateUser(id bson.ObjectId, item User) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if item.Password == "" {
|
||||
item.Password = result.Password
|
||||
} else {
|
||||
item.Password = utils.EncryptPassword(item.Password)
|
||||
}
|
||||
|
||||
if err := item.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import router from '../router'
|
||||
|
||||
let baseUrl = process.env.VUE_APP_BASE_URL ? process.env.VUE_APP_BASE_URL : 'http://localhost:8000/api'
|
||||
|
||||
@@ -16,7 +17,13 @@ const request = (method, path, params, data) => {
|
||||
headers
|
||||
})
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
if (error.response.status === 401) {
|
||||
router.push('/login')
|
||||
}
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,24 @@ const user = {
|
||||
roles: [],
|
||||
userList: [],
|
||||
userForm: {},
|
||||
userInfo: undefined,
|
||||
adminPaths: [
|
||||
'/users'
|
||||
],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0
|
||||
},
|
||||
|
||||
getters: {
|
||||
userInfo (state) {
|
||||
if (state.userInfo) return state.userInfo
|
||||
const userInfoStr = window.localStorage.getItem('user_info')
|
||||
if (!userInfoStr) return {}
|
||||
return JSON.parse(userInfoStr)
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
@@ -34,6 +47,9 @@ const user = {
|
||||
SET_USER_FORM: (state, value) => {
|
||||
state.userForm = value
|
||||
},
|
||||
SET_USER_INFO: (state, value) => {
|
||||
state.userInfo = value
|
||||
},
|
||||
SET_PAGE_NUM: (state, value) => {
|
||||
state.pageNum = value
|
||||
},
|
||||
@@ -64,23 +80,13 @@ const user = {
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
// getInfo ({ commit, state }) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// getInfo(state.token).then(response => {
|
||||
// const data = response.data
|
||||
// if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
// commit('SET_ROLES', data.roles)
|
||||
// } else {
|
||||
// reject(new Error('getInfo: roles must be a non-null array !'))
|
||||
// }
|
||||
// commit('SET_NAME', data.name)
|
||||
// commit('SET_AVATAR', data.avatar)
|
||||
// resolve(response)
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
getInfo ({ commit, state }) {
|
||||
return request.get('/me')
|
||||
.then(response => {
|
||||
commit('SET_USER_INFO', response.data.data)
|
||||
window.localStorage.setItem('user_info', JSON.stringify(response.data.data))
|
||||
})
|
||||
},
|
||||
|
||||
// 注册
|
||||
register ({ dispatch, commit, state }, userInfo) {
|
||||
@@ -99,6 +105,8 @@ const user = {
|
||||
logout ({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.localStorage.removeItem('token')
|
||||
window.localStorage.removeItem('user_info')
|
||||
commit('SET_USER_INFO', undefined)
|
||||
commit('SET_TOKEN', '')
|
||||
commit('SET_ROLES', [])
|
||||
resolve()
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import variables from '@/styles/variables.scss'
|
||||
import SidebarItem from './SidebarItem'
|
||||
|
||||
export default {
|
||||
components: { SidebarItem },
|
||||
computed: {
|
||||
...mapState('user', [
|
||||
'adminPaths'
|
||||
]),
|
||||
...mapGetters([
|
||||
'sidebar'
|
||||
]),
|
||||
@@ -30,8 +33,12 @@ export default {
|
||||
return `/${pathArray[1]}`
|
||||
},
|
||||
routes () {
|
||||
// console.log(this.$router.options.routes.filter(d => !d.hidden))
|
||||
return this.$router.options.routes
|
||||
return this.$router.options.routes.filter(d => {
|
||||
const role = this.$store.getters['user/userInfo'].role
|
||||
if (role === 'admin') return true
|
||||
console.log(role)
|
||||
return !this.adminPaths.includes(d.path)
|
||||
})
|
||||
},
|
||||
variables () {
|
||||
return variables
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
name="password"
|
||||
auto-complete="on"
|
||||
:placeholder="$t('Password')"
|
||||
@keyup.enter.native="isSignUp ? handleSignup : handleLogin"/>
|
||||
@keyup.enter.native="onKeyEnter"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isSignUp" prop="confirmPassword" style="margin-bottom: 28px;">
|
||||
<el-input
|
||||
@@ -31,7 +31,7 @@
|
||||
name="password"
|
||||
auto-complete="on"
|
||||
:placeholder="$t('Confirm Password')"
|
||||
@keyup.enter.native="isSignUp ? handleSignup : handleLogin"
|
||||
@keyup.enter.native="onKeyEnter"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="border: none">
|
||||
@@ -105,13 +105,15 @@ export default {
|
||||
confirmPassword: [{ required: true, trigger: 'blur', validator: validateConfirmPass }]
|
||||
},
|
||||
loading: false,
|
||||
pwdType: 'password',
|
||||
redirect: undefined
|
||||
pwdType: 'password'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isSignUp () {
|
||||
return this.$route.path === '/signup'
|
||||
},
|
||||
redirect () {
|
||||
return this.$route.query.redirect
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -122,6 +124,7 @@ export default {
|
||||
this.$store.dispatch('user/login', this.loginForm).then(() => {
|
||||
this.loading = false
|
||||
this.$router.push({ path: this.redirect || '/' })
|
||||
this.$store.dispatch('user/getInfo')
|
||||
}).catch(() => {
|
||||
this.$message.error(this.$t('Error when logging in (Please check username and password)'))
|
||||
this.loading = false
|
||||
@@ -142,6 +145,10 @@ export default {
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onKeyEnter () {
|
||||
const func = this.isSignUp ? this.handleSignup : this.handleLogin
|
||||
func()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -95,7 +95,7 @@ export default {
|
||||
this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
},
|
||||
downloadCSV () {
|
||||
window.location.href = this.$request.baseUrl + '/tasks/' + this.$route.params.id + '/download_results'
|
||||
window.location.href = this.$request.baseUrl + '/tasks/' + this.$route.params.id + '/results/download'
|
||||
this.$st.sendEv('任务详情-结果', '下载CSV')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<div class="app-container">
|
||||
<!--dialog-->
|
||||
<el-dialog :visible.sync="dialogVisible" :title="$t('Edit User')">
|
||||
<el-form label-width="80px">
|
||||
<el-form ref="form" :model="userForm" label-width="80px" :rules="rules" inline-message>
|
||||
<el-form-item :label="$t('Username')">
|
||||
<el-input v-model="userForm.username" disabled></el-input>
|
||||
</el-form-item>
|
||||
<!--<el-form-item :label="$t('Password')">-->
|
||||
<!--<el-input type="password" v-model="userForm.password" :placeholder="$t('Password')"></el-input>-->
|
||||
<!--</el-form-item>-->
|
||||
<el-form-item prop="password" :label="$t('Password')">
|
||||
<el-input type="password" v-model="userForm.password" :placeholder="$t('Password')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Role')">
|
||||
<el-select v-model="userForm.role">
|
||||
<el-option value="admin" :label="$t('admin')"></el-option>
|
||||
@@ -92,8 +92,19 @@ import dayjs from 'dayjs'
|
||||
export default {
|
||||
name: 'UserList',
|
||||
data () {
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (!value) return callback()
|
||||
if (value.length < 5) {
|
||||
callback(new Error(this.$t('Password length should be no shorter than 5')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
dialogVisible: false
|
||||
dialogVisible: false,
|
||||
rules: {
|
||||
password: [{ validator: validatePass }]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -149,13 +160,17 @@ export default {
|
||||
},
|
||||
onConfirm () {
|
||||
this.dialogVisible = false
|
||||
this.$store.dispatch('user/editUser')
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Saved successfully')
|
||||
})
|
||||
})
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
this.$store.dispatch('user/editUser')
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Saved successfully')
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
this.$st.sendEv('用户', '编辑')
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user