增加从环境变量获取配置&修复修改密码失败的bug&增加退出登录&修复新增用户无法登录的bug
This commit is contained in:
13
Dockerfile
13
Dockerfile
@ -8,22 +8,23 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN go env && CGO_ENABLED=0 go build -o next-terminal main.go
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
RUN apk add gcc g++
|
||||||
|
RUN go env && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -ldflags '-linkmode external -extldflags "-static"' -o next-terminal main.go
|
||||||
|
|
||||||
FROM guacamole/guacd:1.2.0
|
FROM guacamole/guacd:1.2.0
|
||||||
|
|
||||||
LABEL MAINTAINER="helloworld1024@foxmail.com"
|
LABEL MAINTAINER="helloworld1024@foxmail.com"
|
||||||
|
|
||||||
|
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
|
||||||
RUN apt-get update && apt-get -y install supervisor
|
RUN apt-get update && apt-get -y install supervisor
|
||||||
RUN mkdir -p /var/log/supervisor
|
RUN mkdir -p /var/log/supervisor
|
||||||
COPY --from=builder /app/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
COPY --from=builder /app/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
|
||||||
ENV MYSQL_HOSTNAME 127.0.0.1
|
ENV DB sqlite
|
||||||
ENV MYSQL_PORT 3306
|
ENV SQLITE_FILE 'next-terminal.db'
|
||||||
ENV MYSQL_USERNAME mysql
|
|
||||||
ENV MYSQL_PASSWORD mysql
|
|
||||||
ENV MYSQL_DATABASE next_terminal
|
|
||||||
ENV SERVER_PORT 8088
|
ENV SERVER_PORT 8088
|
||||||
|
ENV SERVER_ADDR 0.0.0.0:$SERVER_PORT
|
||||||
|
|
||||||
WORKDIR /usr/local/next-terminal
|
WORKDIR /usr/local/next-terminal
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
db: mysql
|
||||||
mysql:
|
mysql:
|
||||||
hostname: 127.0.0.1
|
hostname: 172.16.101.32
|
||||||
port: 3306
|
port: 3306
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: mysql
|
||||||
database: next_terminal
|
database: next-terminal
|
||||||
|
sqlite:
|
||||||
|
file: 'next-terminal.db'
|
||||||
server:
|
server:
|
||||||
addr: 0.0.0.0:8088
|
addr: 0.0.0.0:8088
|
2
go.mod
2
go.mod
@ -9,10 +9,10 @@ require (
|
|||||||
github.com/labstack/gommon v0.3.0
|
github.com/labstack/gommon v0.3.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/sftp v1.12.0
|
github.com/pkg/sftp v1.12.0
|
||||||
github.com/sirupsen/logrus v1.2.0
|
|
||||||
github.com/spf13/pflag v1.0.3
|
github.com/spf13/pflag v1.0.3
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
gorm.io/driver/mysql v1.0.3
|
gorm.io/driver/mysql v1.0.3
|
||||||
|
gorm.io/driver/sqlite v1.1.4 // indirect
|
||||||
gorm.io/gorm v1.20.7
|
gorm.io/gorm v1.20.7
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -135,6 +135,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
@ -355,6 +357,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/mysql v1.0.3 h1:+JKBYPfn1tygR1/of/Fh2T8iwuVwzt+PEJmKaXzMQXg=
|
gorm.io/driver/mysql v1.0.3 h1:+JKBYPfn1tygR1/of/Fh2T8iwuVwzt+PEJmKaXzMQXg=
|
||||||
gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI=
|
gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI=
|
||||||
|
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
|
||||||
|
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
|
||||||
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||||
gorm.io/gorm v1.20.7 h1:rMS4CL3pNmYq1V5/X+nHHjh1Dx6dnf27+Cai5zabo+M=
|
gorm.io/gorm v1.20.7 h1:rMS4CL3pNmYq1V5/X+nHHjh1Dx6dnf27+Cai5zabo+M=
|
||||||
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||||
|
33
main.go
33
main.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
"next-terminal/pkg/api"
|
"next-terminal/pkg/api"
|
||||||
@ -22,19 +23,27 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Run() error {
|
func Run() error {
|
||||||
global.Config = config.SetupConfig()
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
global.Config, err = config.SetupConfig()
|
||||||
global.Config.Mysql.Username,
|
if err != nil {
|
||||||
global.Config.Mysql.Password,
|
return err
|
||||||
global.Config.Mysql.Hostname,
|
}
|
||||||
global.Config.Mysql.Port,
|
|
||||||
global.Config.Mysql.Database,
|
if global.Config.DB == "mysql" {
|
||||||
)
|
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||||
global.DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
|
global.Config.Mysql.Username,
|
||||||
Logger: logger.Default.LogMode(logger.Info),
|
global.Config.Mysql.Password,
|
||||||
})
|
global.Config.Mysql.Hostname,
|
||||||
|
global.Config.Mysql.Port,
|
||||||
|
global.Config.Mysql.Database,
|
||||||
|
)
|
||||||
|
global.DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||||
|
Logger: logger.Default.LogMode(logger.Info),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
global.DB, err = gorm.Open(sqlite.Open(global.Config.Sqlite.File), &gorm.Config{})
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,11 @@ type LoginAccount struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChangePassword struct {
|
||||||
|
NewPassword string `json:"newPassword"`
|
||||||
|
OldPassword string `json:"oldPassword"`
|
||||||
|
}
|
||||||
|
|
||||||
func LoginEndpoint(c echo.Context) error {
|
func LoginEndpoint(c echo.Context) error {
|
||||||
var loginAccount LoginAccount
|
var loginAccount LoginAccount
|
||||||
if err := c.Bind(&loginAccount); err != nil {
|
if err := c.Bind(&loginAccount); err != nil {
|
||||||
@ -21,10 +26,10 @@ func LoginEndpoint(c echo.Context) error {
|
|||||||
|
|
||||||
user, err := model.FindUserByUsername(loginAccount.Username)
|
user, err := model.FindUserByUsername(loginAccount.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Fail(c, -1, "您输入的账号或密码不正确")
|
||||||
}
|
}
|
||||||
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
|
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
|
||||||
return err
|
return Fail(c, -1, "您输入的账号或密码不正确")
|
||||||
}
|
}
|
||||||
|
|
||||||
token := utils.UUID()
|
token := utils.UUID()
|
||||||
@ -43,7 +48,28 @@ func LogoutEndpoint(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ChangePasswordEndpoint(c echo.Context) error {
|
func ChangePasswordEndpoint(c echo.Context) error {
|
||||||
return nil
|
account, _ := GetCurrentAccount(c)
|
||||||
|
|
||||||
|
var changePassword ChangePassword
|
||||||
|
if err := c.Bind(&changePassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := utils.Encoder.Match([]byte(account.Password), []byte(changePassword.OldPassword)); err != nil {
|
||||||
|
return Fail(c, -1, "您输入的原密码不正确")
|
||||||
|
}
|
||||||
|
|
||||||
|
passwd, err := utils.Encoder.Encode([]byte(changePassword.NewPassword))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u := &model.User{
|
||||||
|
Password: string(passwd),
|
||||||
|
}
|
||||||
|
|
||||||
|
model.UpdateUserById(u, account.ID)
|
||||||
|
|
||||||
|
return LogoutEndpoint(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InfoEndpoint(c echo.Context) error {
|
func InfoEndpoint(c echo.Context) error {
|
||||||
|
@ -7,6 +7,16 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ErrorHandler(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
|
||||||
|
if err := next(c); err != nil {
|
||||||
|
return Fail(c, 0, err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
|
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
|
||||||
urls := []string{"download", "recording", "login", "static", "favicon", "logo"}
|
urls := []string{"download", "recording", "login", "static", "favicon", "logo"}
|
||||||
|
@ -36,6 +36,7 @@ func SetupRoutes() *echo.Echo {
|
|||||||
AllowOrigins: []string{"*"},
|
AllowOrigins: []string{"*"},
|
||||||
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
||||||
}))
|
}))
|
||||||
|
e.Use(ErrorHandler)
|
||||||
e.Use(Auth)
|
e.Use(Auth)
|
||||||
|
|
||||||
e.POST("/login", LoginEndpoint)
|
e.POST("/login", LoginEndpoint)
|
||||||
|
@ -16,7 +16,7 @@ func UserCreateEndpoint(c echo.Context) error {
|
|||||||
|
|
||||||
var pass []byte
|
var pass []byte
|
||||||
var err error
|
var err error
|
||||||
if pass, err = utils.Encoder.Encode([]byte("admin")); err != nil {
|
if pass, err = utils.Encoder.Encode([]byte(item.Password)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
item.Password = string(pass)
|
item.Password = string(pass)
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
DB string
|
||||||
Server *Server
|
Server *Server
|
||||||
Mysql *Mysql
|
Mysql *Mysql
|
||||||
|
Sqlite *Sqlite
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mysql struct {
|
type Mysql struct {
|
||||||
@ -21,36 +21,31 @@ type Mysql struct {
|
|||||||
Database string
|
Database string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Sqlite struct {
|
||||||
|
File string
|
||||||
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Addr string
|
Addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupConfig() *Config {
|
func SetupConfig() (*Config, error) {
|
||||||
|
|
||||||
viper.SetConfigName("config")
|
viper.SetConfigName("config")
|
||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yml")
|
||||||
viper.AddConfigPath("/etc/next-terminal/")
|
viper.AddConfigPath("/etc/next-terminal/")
|
||||||
viper.AddConfigPath("$HOME/.next-terminal")
|
viper.AddConfigPath("$HOME/.next-terminal")
|
||||||
viper.AddConfigPath(".")
|
viper.AddConfigPath(".")
|
||||||
viper.AutomaticEnv()
|
viper.AutomaticEnv()
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
|
||||||
//pflag.String("mysql.hostname", "127.0.0.1", "mysql hostname")
|
|
||||||
//pflag.Int("mysql.port", 3306, "mysql port")
|
|
||||||
//pflag.String("mysql.username", "mysql", "mysql username")
|
|
||||||
//pflag.String("mysql.password", "mysql", "mysql password")
|
|
||||||
//pflag.String("mysql.database", "next_terminal", "mysql database")
|
|
||||||
//pflag.String("server.addr", "0.0.0.0:8088", "server listen addr")
|
|
||||||
|
|
||||||
pflag.Parse()
|
|
||||||
_ = viper.BindPFlags(pflag.CommandLine)
|
|
||||||
|
|
||||||
err := viper.ReadInConfig()
|
err := viper.ReadInConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &Config{
|
var config = &Config{
|
||||||
|
DB: viper.GetString("db"),
|
||||||
Mysql: &Mysql{
|
Mysql: &Mysql{
|
||||||
Hostname: viper.GetString("mysql.hostname"),
|
Hostname: viper.GetString("mysql.hostname"),
|
||||||
Port: viper.GetInt("mysql.port"),
|
Port: viper.GetInt("mysql.port"),
|
||||||
@ -58,10 +53,13 @@ func SetupConfig() *Config {
|
|||||||
Password: viper.GetString("mysql.password"),
|
Password: viper.GetString("mysql.password"),
|
||||||
Database: viper.GetString("mysql.database"),
|
Database: viper.GetString("mysql.database"),
|
||||||
},
|
},
|
||||||
|
Sqlite: &Sqlite{
|
||||||
|
File: viper.GetString("sqlite.file"),
|
||||||
|
},
|
||||||
Server: &Server{
|
Server: &Server{
|
||||||
Addr: viper.GetString("server.addr"),
|
Addr: viper.GetString("server.addr"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config, nil
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,4 @@ command=/usr/local/guacamole/sbin/guacd -b 0.0.0.0 -L info -f
|
|||||||
|
|
||||||
[program:next-terminal]
|
[program:next-terminal]
|
||||||
; command=/usr/local/next-terminal/next-terminal --mysql.hostname %(ENV_MYSQL_HOSTNAME)s --mysql.port %(ENV_MYSQL_PORT)s --mysql.username %(ENV_MYSQL_USERNAME)s --mysql.password %(ENV_MYSQL_PASSWORD)s --mysql.database %(ENV_MYSQL_DATABASE)s --server.addr 0.0.0.0:%(ENV_SERVER_PORT)s
|
; command=/usr/local/next-terminal/next-terminal --mysql.hostname %(ENV_MYSQL_HOSTNAME)s --mysql.port %(ENV_MYSQL_PORT)s --mysql.username %(ENV_MYSQL_USERNAME)s --mysql.password %(ENV_MYSQL_PASSWORD)s --mysql.database %(ENV_MYSQL_DATABASE)s --server.addr 0.0.0.0:%(ENV_SERVER_PORT)s
|
||||||
command=/usr/local/next-terminal/next-terminal
|
command=/usr/local/next-terminal/next-terminal --server.addr 0.0.0.0:%(ENV_SERVER_PORT)s
|
@ -1,12 +1,12 @@
|
|||||||
// prod
|
// prod
|
||||||
export const server = '';
|
// export const server = '';
|
||||||
export const wsServer = '';
|
// export const wsServer = '';
|
||||||
export const prefix = '';
|
// export const prefix = '';
|
||||||
|
|
||||||
// dev
|
// dev
|
||||||
// export const server = '//127.0.0.1:8088';
|
export const server = '//127.0.0.1:8088';
|
||||||
// export const wsServer = 'ws://127.0.0.1:8088';
|
export const wsServer = 'ws://127.0.0.1:8088';
|
||||||
// export const prefix = '';
|
export const prefix = '';
|
||||||
|
|
||||||
// export const server = '//172.16.101.32:8080';
|
// export const server = '//172.16.101.32:8080';
|
||||||
// export const wsServer = 'ws://172.16.101.32:8080';
|
// export const wsServer = 'ws://172.16.101.32:8080';
|
||||||
|
@ -12,9 +12,20 @@ const {Title} = Typography;
|
|||||||
class LoginForm extends Component {
|
class LoginForm extends Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
inLogin: false
|
inLogin: false,
|
||||||
|
height: window.innerHeight,
|
||||||
|
width: window.innerWidth
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
this.setState({
|
||||||
|
height: window.innerHeight,
|
||||||
|
width: window.innerWidth
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handleSubmit = async params => {
|
handleSubmit = async params => {
|
||||||
this.setState({
|
this.setState({
|
||||||
inLogin: true
|
inLogin: true
|
||||||
@ -50,7 +61,8 @@ class LoginForm extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='login-bg' style={{width: window.innerWidth, height: window.innerHeight, backgroundColor: '#F0F2F5'}}>
|
<div className='login-bg'
|
||||||
|
style={{width: this.state.width, height: this.state.height, backgroundColor: '#F0F2F5'}}>
|
||||||
<Card className='login-card' title={null}>
|
<Card className='login-card' title={null}>
|
||||||
<div style={{textAlign: "center", margin: '15px auto 30px auto', color: '#1890ff'}}>
|
<div style={{textAlign: "center", margin: '15px auto 30px auto', color: '#1890ff'}}>
|
||||||
<Title level={1}>Next Terminal</Title>
|
<Title level={1}>Next Terminal</Title>
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {itemRender} from "../../utils/utils";
|
import {itemRender} from "../../utils/utils";
|
||||||
import {PROTOCOL_COLORS} from "../../common/constants";
|
import {PROTOCOL_COLORS} from "../../common/constants";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -384,6 +385,9 @@ class Asset extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="资产"
|
subTitle="资产"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -2,6 +2,7 @@ import React, {Component} from 'react';
|
|||||||
import {List, Card, Input, PageHeader} from "antd";
|
import {List, Card, Input, PageHeader} from "antd";
|
||||||
import Console from "../access/Console";
|
import Console from "../access/Console";
|
||||||
import {itemRender} from "../../utils/utils";
|
import {itemRender} from "../../utils/utils";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -55,6 +56,9 @@ class BatchCommand extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="动态指令"
|
subTitle="动态指令"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -30,6 +30,7 @@ import {
|
|||||||
UndoOutlined
|
UndoOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {itemRender} from "../../utils/utils";
|
import {itemRender} from "../../utils/utils";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -359,6 +360,9 @@ class DynamicCommand extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="批量动态指令执行"
|
subTitle="批量动态指令执行"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
UndoOutlined
|
UndoOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {itemRender} from "../../utils/utils";
|
import {itemRender} from "../../utils/utils";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -280,6 +281,9 @@ class Credential extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="访问资产的账户、密钥等"
|
subTitle="访问资产的账户、密钥等"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Card, Col, PageHeader, Radio, Row, Statistic} from "antd";
|
import {Button, Card, Col, PageHeader, Radio, Row, Statistic} from "antd";
|
||||||
import {DesktopOutlined, IdcardOutlined, LinkOutlined, UserOutlined} from '@ant-design/icons';
|
import {DesktopOutlined, IdcardOutlined, LinkOutlined, UserOutlined} from '@ant-design/icons';
|
||||||
import {itemRender} from '../../utils/utils'
|
import {itemRender} from '../../utils/utils'
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import './Dashboard.css'
|
import './Dashboard.css'
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Area} from '@ant-design/charts';
|
import {Area} from '@ant-design/charts';
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
@ -86,6 +87,9 @@ class Dashboard extends Component {
|
|||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
subTitle="仪表盘"
|
subTitle="仪表盘"
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
UndoOutlined
|
UndoOutlined
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import {PROTOCOL_COLORS} from "../../common/constants";
|
import {PROTOCOL_COLORS} from "../../common/constants";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -357,6 +358,9 @@ class OfflineSession extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="离线会话管理"
|
subTitle="离线会话管理"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
UndoOutlined
|
UndoOutlined
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import Monitor from "../access/Monitor";
|
import Monitor from "../access/Monitor";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -348,6 +349,9 @@ class OnlineSession extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="查询实时在线会话"
|
subTitle="查询实时在线会话"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -3,6 +3,7 @@ import {Button, Form, Input, Layout, PageHeader, Select, Switch, Tabs, Typograph
|
|||||||
import {itemRender} from '../../utils/utils'
|
import {itemRender} from '../../utils/utils'
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
|
import Logout from "../user/Logout";
|
||||||
|
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
@ -107,6 +108,9 @@ class Setting extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="系统设置"
|
subTitle="系统设置"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
@ -3,6 +3,7 @@ import {Button, Form, Input, Layout, PageHeader} from "antd";
|
|||||||
import {itemRender} from '../../utils/utils'
|
import {itemRender} from '../../utils/utils'
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
|
import Logout from "./Logout";
|
||||||
|
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
|
|
||||||
@ -61,7 +62,8 @@ class Info extends Component {
|
|||||||
changePassword = async (values) => {
|
changePassword = async (values) => {
|
||||||
let result = await request.post('/change-password', values);
|
let result = await request.post('/change-password', values);
|
||||||
if (result.code === 1) {
|
if (result.code === 1) {
|
||||||
message.success('密码修改成功');
|
message.success('密码修改成功,即将跳转至登录页面');
|
||||||
|
window.location.href = '/#';
|
||||||
} else {
|
} else {
|
||||||
message.error(result.message);
|
message.error(result.message);
|
||||||
}
|
}
|
||||||
@ -77,6 +79,9 @@ class Info extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="个人中心"
|
subTitle="个人中心"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
37
web/src/components/user/Logout.js
Normal file
37
web/src/components/user/Logout.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Button, message, Popconfirm} from "antd";
|
||||||
|
import request from "../../common/request";
|
||||||
|
|
||||||
|
class Logout extends Component {
|
||||||
|
|
||||||
|
confirm = async (e) => {
|
||||||
|
let result = await request.post('/logout');
|
||||||
|
if (result['code'] !== 1) {
|
||||||
|
message.error(result['message']);
|
||||||
|
} else {
|
||||||
|
message.success('退出登录成功,即将跳转至登录页面。');
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Popconfirm
|
||||||
|
title="您确定要退出登录吗?"
|
||||||
|
onConfirm={this.confirm}
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
placement="left"
|
||||||
|
>
|
||||||
|
<Button key="login-btn" type="dashed">
|
||||||
|
退出登录
|
||||||
|
</Button>,
|
||||||
|
</Popconfirm>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Logout;
|
@ -28,6 +28,7 @@ import {
|
|||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
UndoOutlined
|
UndoOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
import Logout from "./Logout";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -308,6 +309,9 @@ class User extends Component {
|
|||||||
routes: routes,
|
routes: routes,
|
||||||
itemRender: itemRender
|
itemRender: itemRender
|
||||||
}}
|
}}
|
||||||
|
extra={[
|
||||||
|
<Logout/>
|
||||||
|
]}
|
||||||
subTitle="平台用户管理"
|
subTitle="平台用户管理"
|
||||||
>
|
>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
Reference in New Issue
Block a user