Skip to content

Commit

Permalink
Merge pull request #447 from bittorrent/feat/dashboard-login
Browse files Browse the repository at this point in the history
Feat/dashboard login
  • Loading branch information
mengcody authored Aug 27, 2024
2 parents 7c46c3c + 133e1bc commit 408ea68
Show file tree
Hide file tree
Showing 6 changed files with 532 additions and 4 deletions.
14 changes: 11 additions & 3 deletions core/commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ func TestCommands(t *testing.T) {
"/config/replace",
"/config/reset",
"/config/show",
//"/config/profile",
//"/config/profile/apply",
// "/config/profile",
// "/config/profile/apply",
"/config/storage-host-enable",
"/config/sync-chain-info",
"/config/sync-simple-mode",
Expand Down Expand Up @@ -332,7 +332,7 @@ func TestCommands(t *testing.T) {
"/statuscontract/lastinfo",
"/statuscontract/config",
"/statuscontract/report_online_server",
//"/statuscontract/report_status_contract",
// "/statuscontract/report_status_contract",
"/statuscontract/daily_report_online_server",
"/statuscontract/daily_report_list",
"/statuscontract/daily_total",
Expand Down Expand Up @@ -361,6 +361,14 @@ func TestCommands(t *testing.T) {
"/cheque/fix_cheque_cashout",
"/encrypt",
"/decrypt",
"/dashboard",
"/dashboard/check",
"/dashboard/set",
"/dashboard/reset",
"/dashboard/login",
"/dashboard/logout",
"/dashboard/change",
"/dashboard/validate",
}

cmdSet := make(map[string]struct{})
Expand Down
234 changes: 234 additions & 0 deletions core/commands/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package commands

import (
"encoding/hex"
"errors"
cmds "github.com/bittorrent/go-btfs-cmds"
"github.com/bittorrent/go-btfs/core/commands/cmdenv"
"github.com/bittorrent/go-btfs/utils"
ds "github.com/ipfs/go-datastore"
)

const DashboardPasswordPrefix = "/dashboard_password"
const TokenExpire = 60 * 60 * 24 * 1

var IsLogin bool

type DashboardResponse struct {
Success bool
Text string
}

var dashboardCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "dashboard password operation",
},

Subcommands: map[string]*cmds.Command{
"check": checkCmd,
"set": setCmd,
"reset": resetCmd,
"change": changeCmd,
"login": loginCmd,
"logout": logoutCmd,
"validate": validateCmd,
},
}

var checkCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "check if password is set",
},
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}

_, err = node.Repo.Datastore().Get(req.Context, ds.NewKey(DashboardPasswordPrefix))

if err != nil && errors.Is(err, ds.ErrNotFound) {
return re.Emit(&DashboardResponse{Success: false, Text: "passwd is not set"})
}

if err != nil {
log.Info("check password error", err)
return err
}
return re.Emit(DashboardResponse{Success: true, Text: "password was set"})
},
}

var setCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "set password",
},
Arguments: []cmds.Argument{
cmds.StringArg("password", true, false, "set password"),
},
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}
// check if password has set
_, err = node.Repo.Datastore().Get(req.Context, ds.NewKey(DashboardPasswordPrefix))
if err != nil && !errors.Is(err, ds.ErrNotFound) {
log.Info("set password error", err)
return err
}

if err == nil {
return re.Emit(&DashboardResponse{
Success: false,
Text: "password has set, if you want to reset your password, please use reset command instead",
})
}

datastore := node.Repo.Datastore()
key := ds.NewKey(DashboardPasswordPrefix)
err = datastore.Put(req.Context, key, []byte(req.Arguments[0]))
if err != nil {
return err
}
return re.Emit(&DashboardResponse{Success: true, Text: "password set success!"})
},
}

var loginCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "login with passwd and get the token",
},
Arguments: []cmds.Argument{
cmds.StringArg("password", true, false, "set password"),
},
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}
value, err := node.Repo.Datastore().Get(req.Context, ds.NewKey(DashboardPasswordPrefix))
if errors.Is(err, ds.ErrNotFound) {
return re.Emit(&DashboardResponse{Success: false, Text: "password has not set, please set passwd first"})
}
if err != nil {
return err
}
if string(value) != req.Arguments[0] {
log.Info("login password is correct")
return re.Emit(&DashboardResponse{Success: false, Text: "password is not correct"})
}

config, err := node.Repo.Config()

publicKey := config.Identity.PeerID

token, err := utils.GenerateToken(publicKey, string(value), TokenExpire)
if err != nil {
return err
}

IsLogin = true

return re.Emit(&DashboardResponse{
Success: true,
Text: token,
})
},
}

var resetCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "reset password",
},
Arguments: []cmds.Argument{
cmds.StringArg("privateKey", true, false, "private key"),
cmds.StringArg("newPassword", true, false, "new password"),
},

Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}

raw, err := node.PrivateKey.Raw()
if err != nil {
return err
}

if hex.EncodeToString(raw) != req.Arguments[0] {
return re.Emit(&DashboardResponse{Success: false, Text: "private key is not correct"})
}
datastore := node.Repo.Datastore()
err = datastore.Put(req.Context, ds.NewKey(DashboardPasswordPrefix), []byte(req.Arguments[1]))
if err != nil {
return err
}
return re.Emit(&DashboardResponse{Success: true, Text: "password reset success!"})
},
}

var changeCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "change password",
},
Arguments: []cmds.Argument{
cmds.StringArg("oldPassword", true, false, "change password"),
cmds.StringArg("newPassword", true, false, "change password"),
},
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}
datastore := node.Repo.Datastore()
value, err := datastore.Get(req.Context, ds.NewKey(DashboardPasswordPrefix))
if err != nil {
return err
}
if string(value) != req.Arguments[0] {
return re.Emit(&DashboardResponse{Success: false, Text: "the old password is not correct"})
}
err = datastore.Put(req.Context, ds.NewKey(DashboardPasswordPrefix), []byte(req.Arguments[1]))
if err != nil {
return err
}
return re.Emit(&DashboardResponse{Success: true, Text: "password change success!"})
},
}

var logoutCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "logout",
},
Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
IsLogin = false
return re.Emit(&DashboardResponse{Success: true, Text: "logout success!"})
},
}

var validateCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "validate passwd",
},
Arguments: []cmds.Argument{
cmds.StringArg("password", true, false, "validate passwd"),
},
Run: func(r *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}
datastore := node.Repo.Datastore()
value, err := datastore.Get(r.Context, ds.NewKey(DashboardPasswordPrefix))
if err != nil {
return err
}

if string(value) != r.Arguments[0] {
return re.Emit(&DashboardResponse{Success: false, Text: "password is not correct"})
}
return re.Emit(&DashboardResponse{Success: true, Text: "password is correct"})
},
}
3 changes: 2 additions & 1 deletion core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ var rootSubcommands = map[string]*cmds.Command{
"vault": vault.VaultCmd,
"bttc": bttc.BttcCmd,
"settlement": settlement.SettlementCmd,
//"update": ExternalBinary(),
// "update": ExternalBinary(),
"network": NetworkCmd,
"statuscontract": StatusContractCmd,
"bittorrent": bittorrentCmd,
Expand All @@ -185,6 +185,7 @@ var rootSubcommands = map[string]*cmds.Command{
"accesskey": AccessKeyCmd,
"encrypt": encryptCmd,
"decrypt": decryptCmd,
"dashboard": dashboardCmd,
}

// RootRO is the readonly version of Root
Expand Down
20 changes: 20 additions & 0 deletions core/corehttp/corehttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,27 @@ func makeHandler(n *core.IpfsNode, l net.Listener, options ...ServeOption) (http
w.WriteHeader(http.StatusOK)
return
}

err := interceptorBeforeReq(r, n)
if err != nil {
// set allow origin
w.Header().Set("Access-Control-Allow-Origin", "*")
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-Stream-Output, X-Chunked-Output, X-Content-Length")
return
}
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}

topMux.ServeHTTP(w, r)

err = interceptorAfterResp(r, w, n)
if err != nil {
return
}

})
return handler, nil
}
Expand Down
Loading

0 comments on commit 408ea68

Please sign in to comment.