From 447cb1df40aab2eb961cfe293ba73a3930cc315b Mon Sep 17 00:00:00 2001 From: razr Date: Thu, 19 Nov 2015 23:16:34 +0800 Subject: [PATCH] httpaccess auth device api. --- pkg/server/server.go | 9 +++++ pkg/server/server_test.go | 2 +- services/apiprovider/actions.go | 1 + services/apiprovider/response.go | 1 + services/apiprovider/router.go | 1 + services/httpaccess/actions.go | 62 +++++++++++++++++++++++++++++- services/httpaccess/flags.go | 15 ++++++++ services/httpaccess/response.go | 6 +-- services/httpaccess/router.go | 2 +- services/registry/registry.go | 17 ++++++++ services/registry/registry_test.go | 17 ++++++++ 11 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 services/apiprovider/actions.go create mode 100644 services/apiprovider/response.go create mode 100644 services/apiprovider/router.go create mode 100644 services/httpaccess/flags.go diff --git a/pkg/server/server.go b/pkg/server/server.go index 3670a67..636239d 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -169,6 +169,15 @@ func RPCCallByName(serverName string, serverMethod string, args interface{}, rep return serverInstance.rpccli.Call(serverName, serverMethod, args, reply) } +// get server's hosts by server name and service type +func GetServerHosts(serverName string, hostType string) ([]string, error) { + if serverInstance == nil { + return nil, errorf(errServerNotInit) + } + + return serverInstance.svrmgr.GetServerHosts(serverName, hostType) +} + // start service func Run() error { if serverInstance == nil { diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 6cce721..ddd445d 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -20,7 +20,7 @@ func (t *testTimer) DoTask() { } func validateGetServerHosts(t *testing.T, flag string, want string) { - hosts, err := serverInstance.svrmgr.GetServerHosts("test", flag) + hosts, err := GetServerHosts("test", flag) if err != nil { t.Error(err) } diff --git a/services/apiprovider/actions.go b/services/apiprovider/actions.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/services/apiprovider/actions.go @@ -0,0 +1 @@ +package main diff --git a/services/apiprovider/response.go b/services/apiprovider/response.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/services/apiprovider/response.go @@ -0,0 +1 @@ +package main diff --git a/services/apiprovider/router.go b/services/apiprovider/router.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/services/apiprovider/router.go @@ -0,0 +1 @@ +package main diff --git a/services/httpaccess/actions.go b/services/httpaccess/actions.go index 652235a..1aad292 100644 --- a/services/httpaccess/actions.go +++ b/services/httpaccess/actions.go @@ -1,16 +1,23 @@ package main import ( + "encoding/hex" + "errors" "github.com/PandoCloud/pando-cloud/pkg/models" "github.com/PandoCloud/pando-cloud/pkg/rpcs" "github.com/PandoCloud/pando-cloud/pkg/server" + "github.com/PandoCloud/pando-cloud/pkg/token" "github.com/martini-contrib/render" + "math/rand" "net/http" ) const ( - ErrOK = 0 - ErrSystemFault = 10001 + ErrOK = 0 + ErrSystemFault = 10001 + ErrDeviceNotFound = 10002 + ErrWrongSecret = 10003 + ErrProtocolNotSuported = 10004 ) func renderError(code int, err error) Common { @@ -60,3 +67,54 @@ func RegisterDevice(args DeviceRegisterArgs, r render.Render) { r.JSON(http.StatusOK, result) return } + +func AuthDevice(args DeviceAuthArgs, r render.Render) { + server.Log.Printf("ACTION AuthDevice, args:: %v", args) + device := &models.Device{} + err := server.RPCCallByName("registry", "Registry.FindDeviceById", int64(args.DeviceId), device) + if err != nil { + r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err)) + return + } + + if device.DeviceSecret != args.DeviceSecret { + // device secret is wrong. + r.JSON(http.StatusOK, renderError(ErrWrongSecret, errors.New("wrong device secret."))) + return + } + + hepler := token.NewHelper(*confRedisHost) + token, err := hepler.GenerateToken(uint64(device.ID)) + if err != nil { + r.JSON(http.StatusOK, renderError(ErrSystemFault, err)) + return + } + + var hosts []string + switch args.Protocol { + case "http": + hosts, err = server.GetServerHosts(args.Protocol+"access", "httphost") + case "mqtt": + hosts, err = server.GetServerHosts(args.Protocol+"access", "tcphost") + default: + err = errors.New("unsuported protocol: " + args.Protocol) + } + if err != nil { + r.JSON(http.StatusOK, renderError(ErrProtocolNotSuported, err)) + return + } + + // just get a random host + host := hosts[rand.Intn(len(hosts))] + + result := DeviceAuthResponse{} + result.Data = DeviceAuthData{ + AccessToken: hex.EncodeToString(token), + AccessAddr: host, + } + + server.Log.Infof("auth device success: %v, token: %x, access: %v", device, token, host) + + r.JSON(http.StatusOK, result) + return +} diff --git a/services/httpaccess/flags.go b/services/httpaccess/flags.go new file mode 100644 index 0000000..835801d --- /dev/null +++ b/services/httpaccess/flags.go @@ -0,0 +1,15 @@ +package main + +import ( + "flag" +) + +const ( + flagRedisHost = "redishost" + + defaultRedisHost = "localhost:6379" +) + +var ( + confRedisHost = flag.String(flagRedisHost, defaultRedisHost, "redis host address, ip:port") +) diff --git a/services/httpaccess/response.go b/services/httpaccess/response.go index 723adb7..f29eed0 100644 --- a/services/httpaccess/response.go +++ b/services/httpaccess/response.go @@ -22,10 +22,8 @@ type DeviceRegisterResponse struct { // device auth response data field type DeviceAuthData struct { - AccessToken string `json:"access_token"` - AccessAddr string `json:"access_addr"` - EventSequence uint64 `json:"event_sequence"` - DataSequence uint64 `json:"data_sequence"` + AccessToken string `json:"access_token"` + AccessAddr string `json:"access_addr"` } // device auth response diff --git a/services/httpaccess/router.go b/services/httpaccess/router.go index 609a020..30e9068 100644 --- a/services/httpaccess/router.go +++ b/services/httpaccess/router.go @@ -11,6 +11,6 @@ func route(m *martini.ClassicMartini) { m.Post("/v1/devices/registration", binding.Json(DeviceRegisterArgs{}), RegisterDevice) // auth device - // m.Post("v1/devices/authentication", binding.Json(DeviceAuthArgs{}), actions.AuthDevice) + m.Post("/v1/devices/authentication", binding.Json(DeviceAuthArgs{}), AuthDevice) } diff --git a/services/registry/registry.go b/services/registry/registry.go index e6ec0f3..1476aaa 100644 --- a/services/registry/registry.go +++ b/services/registry/registry.go @@ -182,6 +182,23 @@ func (r *Registry) FindDeviceByIdentifier(identifier string, reply *models.Devic return nil } +// FindDeviceById will find the device with given id +func (r *Registry) FindDeviceById(id int64, reply *models.Device) error { + db, err := getDB() + if err != nil { + return err + } + + err = db.Where(&models.Device{ + ID: id, + }).First(reply).Error + + if err != nil { + return err + } + return nil +} + // UpdateDevice will update a device info by identifier func (r *Registry) UpdateDeviceInfo(args *rpcs.ArgsDeviceUpdate, reply *models.Device) error { db, err := getDB() diff --git a/services/registry/registry_test.go b/services/registry/registry_test.go index 3ffa7d6..2af18c2 100644 --- a/services/registry/registry_test.go +++ b/services/registry/registry_test.go @@ -71,6 +71,23 @@ func testDevice(t *testing.T, r *Registry) { } t.Log(device) + founddev := &models.Device{} + err = r.FindDeviceById(device.ID, founddev) + if err != nil { + t.Error(err) + } + if device.DeviceIdentifier != founddev.DeviceIdentifier { + t.Errorf("FindDeviceById not match, want %v, got %v", device, founddev) + } + + err = r.FindDeviceByIdentifier(device.DeviceIdentifier, founddev) + if err != nil { + t.Error(err) + } + if device.ID != founddev.ID { + t.Errorf("FindDeviceByIdentifier not match, want %v, got %v", device, founddev) + } + device.DeviceDescription = "test change device info." args2 := &rpcs.ArgsDeviceUpdate{