mirror of
https://gitee.com/goploy/goploy.git
synced 2024-11-29 18:57:59 +08:00
A ext login
This commit is contained in:
parent
bcd20d37b1
commit
1372f06931
@ -5,13 +5,16 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-ldap/ldap/v3"
|
"github.com/go-ldap/ldap/v3"
|
||||||
"github.com/zhenorzz/goploy/middleware"
|
"github.com/zhenorzz/goploy/middleware"
|
||||||
"github.com/zhenorzz/goploy/permission"
|
"github.com/zhenorzz/goploy/permission"
|
||||||
"github.com/zhenorzz/goploy/response"
|
"github.com/zhenorzz/goploy/response"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zhenorzz/goploy/config"
|
"github.com/zhenorzz/goploy/config"
|
||||||
@ -24,6 +27,7 @@ type User Controller
|
|||||||
func (u User) Routes() []core.Route {
|
func (u User) Routes() []core.Route {
|
||||||
return []core.Route{
|
return []core.Route{
|
||||||
core.NewWhiteRoute("/user/login", http.MethodPost, u.Login).LogFunc(middleware.AddLoginLog),
|
core.NewWhiteRoute("/user/login", http.MethodPost, u.Login).LogFunc(middleware.AddLoginLog),
|
||||||
|
core.NewWhiteRoute("/user/extLogin", http.MethodPost, u.ExtLogin).LogFunc(middleware.AddLoginLog),
|
||||||
core.NewRoute("/user/info", http.MethodGet, u.Info),
|
core.NewRoute("/user/info", http.MethodGet, u.Info),
|
||||||
core.NewRoute("/user/changePassword", http.MethodPut, u.ChangePassword),
|
core.NewRoute("/user/changePassword", http.MethodPut, u.ChangePassword),
|
||||||
core.NewRoute("/user/getList", http.MethodGet, u.GetList).Permissions(permission.ShowMemberPage),
|
core.NewRoute("/user/getList", http.MethodGet, u.GetList).Permissions(permission.ShowMemberPage),
|
||||||
@ -36,7 +40,7 @@ func (u User) Routes() []core.Route {
|
|||||||
|
|
||||||
func (User) Login(gp *core.Goploy) core.Response {
|
func (User) Login(gp *core.Goploy) core.Response {
|
||||||
type ReqData struct {
|
type ReqData struct {
|
||||||
Account string `json:"account" validate:"min=5,max=25"`
|
Account string `json:"account" validate:"min=1,max=25"`
|
||||||
Password string `json:"password" validate:"password"`
|
Password string `json:"password" validate:"password"`
|
||||||
}
|
}
|
||||||
var reqData ReqData
|
var reqData ReqData
|
||||||
@ -126,6 +130,69 @@ func (User) Login(gp *core.Goploy) core.Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (User) ExtLogin(gp *core.Goploy) core.Response {
|
||||||
|
type ReqData struct {
|
||||||
|
Account string `json:"account" validate:"min=1,max=25"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
Token string `json:"token" validate:"len=32"`
|
||||||
|
}
|
||||||
|
var reqData ReqData
|
||||||
|
if err := decodeJson(gp.Body, &reqData); err != nil {
|
||||||
|
return response.JSON{Code: response.IllegalParam, Message: err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Unix() > reqData.Time+30 {
|
||||||
|
return response.JSON{Code: response.IllegalParam, Message: "request time expired"}
|
||||||
|
}
|
||||||
|
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(reqData.Account + config.Toml.JWT.Key + strconv.FormatInt(reqData.Time, 10)))
|
||||||
|
signedToken := hex.EncodeToString(h.Sum(nil))
|
||||||
|
|
||||||
|
if signedToken != reqData.Token {
|
||||||
|
return response.JSON{Code: response.IllegalParam, Message: "sign error"}
|
||||||
|
}
|
||||||
|
|
||||||
|
userData, err := model.User{Account: reqData.Account}.GetDataByAccount()
|
||||||
|
if err != nil {
|
||||||
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userData.State == model.Disable {
|
||||||
|
return response.JSON{Code: response.AccountDisabled, Message: "Account is disabled"}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaceList, err := model.Namespace{UserID: userData.ID}.GetAllByUserID()
|
||||||
|
if err != nil {
|
||||||
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
|
} else if len(namespaceList) == 0 {
|
||||||
|
return response.JSON{Code: response.Error, Message: "No space assigned, please contact the administrator"}
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := userData.CreateToken()
|
||||||
|
if err != nil {
|
||||||
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = model.User{ID: userData.ID, LastLoginTime: time.Now().Format("20060102150405")}.UpdateLastLoginTime()
|
||||||
|
|
||||||
|
cookie := http.Cookie{
|
||||||
|
Name: config.Toml.Cookie.Name,
|
||||||
|
Value: token,
|
||||||
|
Path: "/",
|
||||||
|
MaxAge: config.Toml.Cookie.Expire,
|
||||||
|
HttpOnly: true,
|
||||||
|
}
|
||||||
|
http.SetCookie(gp.ResponseWriter, &cookie)
|
||||||
|
|
||||||
|
return response.JSON{
|
||||||
|
Data: struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
NamespaceList model.Namespaces `json:"namespaceList"`
|
||||||
|
}{Token: token, NamespaceList: namespaceList},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (User) Info(gp *core.Goploy) core.Response {
|
func (User) Info(gp *core.Goploy) core.Response {
|
||||||
type RespData struct {
|
type RespData struct {
|
||||||
UserInfo struct {
|
UserInfo struct {
|
||||||
@ -180,7 +247,7 @@ func (User) GetOption(*core.Goploy) core.Response {
|
|||||||
|
|
||||||
func (User) Add(gp *core.Goploy) core.Response {
|
func (User) Add(gp *core.Goploy) core.Response {
|
||||||
type ReqData struct {
|
type ReqData struct {
|
||||||
Account string `json:"account" validate:"min=5,max=25"`
|
Account string `json:"account" validate:"min=1,max=25"`
|
||||||
Password string `json:"password" validate:"omitempty,password"`
|
Password string `json:"password" validate:"omitempty,password"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Contact string `json:"contact" validate:"omitempty,len=11,numeric"`
|
Contact string `json:"contact" validate:"omitempty,len=11,numeric"`
|
||||||
|
@ -42,7 +42,7 @@ type RouteApi interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Response interface {
|
type Response interface {
|
||||||
Write(http.ResponseWriter) error
|
Write(http.ResponseWriter, *http.Request) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
@ -149,7 +149,7 @@ func (rt Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, resp := rt.doRequest(w, r)
|
_, resp := rt.doRequest(w, r)
|
||||||
if err := resp.Write(w); err != nil {
|
if err := resp.Write(w, r); err != nil {
|
||||||
Log(ERROR, err.Error())
|
Log(ERROR, err.Error())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -10,5 +10,4 @@ import (
|
|||||||
|
|
||||||
type Empty struct{}
|
type Empty struct{}
|
||||||
|
|
||||||
//JSON response
|
func (Empty) Write(http.ResponseWriter, *http.Request) error { return nil }
|
||||||
func (Empty) Write(http.ResponseWriter) error { return nil }
|
|
||||||
|
@ -15,8 +15,7 @@ type File struct {
|
|||||||
Filename string
|
Filename string
|
||||||
}
|
}
|
||||||
|
|
||||||
//JSON response
|
func (f File) Write(w http.ResponseWriter, _ *http.Request) error {
|
||||||
func (f File) Write(w http.ResponseWriter) error {
|
|
||||||
file, err := os.Open(f.Filename)
|
file, err := os.Open(f.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -15,7 +15,6 @@ type JSON struct {
|
|||||||
Data interface{} `json:"data"`
|
Data interface{} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// response code
|
|
||||||
const (
|
const (
|
||||||
Pass = 0
|
Pass = 0
|
||||||
Deny = 1
|
Deny = 1
|
||||||
@ -28,6 +27,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//JSON response
|
//JSON response
|
||||||
func (j JSON) Write(w http.ResponseWriter) error {
|
func (j JSON) Write(w http.ResponseWriter, _ *http.Request) error {
|
||||||
return json.NewEncoder(w).Encode(j)
|
return json.NewEncoder(w).Encode(j)
|
||||||
}
|
}
|
||||||
|
19
response/Redirect.go
Normal file
19
response/Redirect.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2022 The Goploy Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a GPLv3-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package response
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Redirect struct {
|
||||||
|
URL string
|
||||||
|
Code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rdr Redirect) Write(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
http.Redirect(w, r, rdr.URL, rdr.Code)
|
||||||
|
return nil
|
||||||
|
}
|
@ -18,8 +18,7 @@ type SftpFile struct {
|
|||||||
Disposition string // attachment | inline
|
Disposition string // attachment | inline
|
||||||
}
|
}
|
||||||
|
|
||||||
//JSON response
|
func (sf SftpFile) Write(w http.ResponseWriter, _ *http.Request) error {
|
||||||
func (sf SftpFile) Write(w http.ResponseWriter) error {
|
|
||||||
defer sf.Client.Close()
|
defer sf.Client.Close()
|
||||||
|
|
||||||
sftpClient, err := sftp.NewClient(sf.Client)
|
sftpClient, err := sftp.NewClient(sf.Client)
|
||||||
|
@ -29,6 +29,23 @@ export class Login extends Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class extLogin extends Request {
|
||||||
|
readonly url = '/user/extLogin'
|
||||||
|
readonly method = 'post'
|
||||||
|
public param: {
|
||||||
|
account: string
|
||||||
|
token: string
|
||||||
|
time: number
|
||||||
|
}
|
||||||
|
public declare datagram: {
|
||||||
|
namespaceList: { id: number; name: string; roleId: number }[]
|
||||||
|
}
|
||||||
|
constructor(param: extLogin['param']) {
|
||||||
|
super()
|
||||||
|
this.param = param
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Info extends Request {
|
export class Info extends Request {
|
||||||
readonly url = '/user/info'
|
readonly url = '/user/info'
|
||||||
readonly method = 'get'
|
readonly method = 'get'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Module, MutationTree, ActionTree } from 'vuex'
|
import { Module, MutationTree, ActionTree } from 'vuex'
|
||||||
import { UserState } from './types'
|
import { UserState } from './types'
|
||||||
import { RootState } from '../../types'
|
import { RootState } from '../../types'
|
||||||
import { Login, Info } from '@/api/user'
|
import { Login, extLogin, Info } from '@/api/user'
|
||||||
import { setLogin, logout } from '@/utils/auth'
|
import { setLogin, logout } from '@/utils/auth'
|
||||||
import { getNamespaceId, setNamespace } from '@/utils/namespace'
|
import { getNamespaceId, setNamespace } from '@/utils/namespace'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
@ -51,6 +51,27 @@ const actions: ActionTree<UserState, RootState> = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// user ext login
|
||||||
|
extLogin(_, userInfo) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
new extLogin(userInfo)
|
||||||
|
.request()
|
||||||
|
.then((response) => {
|
||||||
|
const { data } = response
|
||||||
|
if (!getNamespaceId()) {
|
||||||
|
const namespace = data.namespaceList[data.namespaceList.length - 1]
|
||||||
|
setNamespace(namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
setLogin('ok')
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
// get user info
|
// get user info
|
||||||
getInfo({ commit }) {
|
getInfo({ commit }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -15,7 +15,7 @@ export function isExternal(path: string): boolean {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
export function validUsername(str: string): boolean {
|
export function validUsername(str: string): boolean {
|
||||||
return str.trim().length >= 5
|
return str.trim().length >= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validPassword(str: string): boolean {
|
export function validPassword(str: string): boolean {
|
||||||
@ -29,6 +29,7 @@ export function validPassword(str: string): boolean {
|
|||||||
|
|
||||||
/* 合法uri*/
|
/* 合法uri*/
|
||||||
export function validateURL(textval: string): boolean {
|
export function validateURL(textval: string): boolean {
|
||||||
const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
const urlregex =
|
||||||
|
/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
||||||
return urlregex.test(textval)
|
return urlregex.test(textval)
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,14 @@ watch(
|
|||||||
useRoute(),
|
useRoute(),
|
||||||
(route) => {
|
(route) => {
|
||||||
redirect.value = route.query?.redirect
|
redirect.value = route.query?.redirect
|
||||||
|
console.log(route.query)
|
||||||
|
if (route.query['account'] && route.query['time'] && route.query['token']) {
|
||||||
|
handleExtLogin(
|
||||||
|
route.query['account'] as string,
|
||||||
|
Number(route.query['time']),
|
||||||
|
route.query['token'] as string
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
@ -133,6 +141,21 @@ function showPwd() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleExtLogin(account: string, time: number, token: string) {
|
||||||
|
store
|
||||||
|
.dispatch('user/extLogin', { account, time, token })
|
||||||
|
.then(() => {
|
||||||
|
router.push({
|
||||||
|
path: redirect.value || '/',
|
||||||
|
query: redirect.value ? param2Obj(redirect.value) : {},
|
||||||
|
})
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function handleLogin() {
|
function handleLogin() {
|
||||||
form.value?.validate((valid) => {
|
form.value?.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
Loading…
Reference in New Issue
Block a user