Merge lp:~chipaca/ubuntu-push/appname-from-dbus-path into lp:ubuntu-push

Proposed by John Lenton
Status: Superseded
Proposed branch: lp:~chipaca/ubuntu-push/appname-from-dbus-path
Merge into: lp:ubuntu-push
Diff against target: 1038 lines (+498/-98)
19 files modified
bus/endpoint.go (+4/-4)
bus/testing/testing_endpoint_test.go (+1/-1)
client/service/service.go (+19/-25)
client/service/service_test.go (+16/-39)
debian/changelog (+14/-0)
debian/rules (+0/-1)
nih/nih.go (+1/-1)
scripts/register (+43/-0)
scripts/unicast (+2/-0)
server/acceptance/acceptanceclient.go (+1/-1)
server/acceptance/cmd/acceptanceclient.go (+3/-1)
server/acceptance/suites/suite.go (+2/-2)
server/acceptance/suites/unicast.go (+11/-3)
server/api/handlers.go (+104/-8)
server/api/handlers_test.go (+193/-2)
server/store/inmemory.go (+26/-0)
server/store/inmemory_test.go (+44/-0)
server/store/store.go (+8/-0)
signing-helper/signing-helper.cpp (+6/-10)
To merge this branch: bzr merge lp:~chipaca/ubuntu-push/appname-from-dbus-path
Reviewer Review Type Date Requested Status
Ubuntu Push Hackers Pending
Review via email: mp+222319@code.launchpad.net

This proposal has been superseded by a proposal from 2014-06-06.

Commit message

switch dbus api to retrieve appname from dbus path

Description of the change

switch dbus api to retrieve appname from dbus path

To post a comment you must log in.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bus/endpoint.go'
--- bus/endpoint.go 2014-05-15 11:28:06 +0000
+++ bus/endpoint.go 2014-06-06 12:14:20 +0000
@@ -29,7 +29,7 @@
29 * Endpoint (and its implementation)29 * Endpoint (and its implementation)
30 */30 */
3131
32type BusMethod func([]interface{}, []interface{}) ([]interface{}, error)32type BusMethod func(string, []interface{}, []interface{}) ([]interface{}, error)
33type DispatchMap map[string]BusMethod33type DispatchMap map[string]BusMethod
3434
35// bus.Endpoint represents the DBus connection itself.35// bus.Endpoint represents the DBus connection itself.
@@ -249,12 +249,12 @@
249 endp.log.Errorf("WatchMethod: unknown method %s", msg.Member)249 endp.log.Errorf("WatchMethod: unknown method %s", msg.Member)
250 } else {250 } else {
251 args := msg.AllArgs()251 args := msg.AllArgs()
252 rvals, err := meth(args, extra)252 rvals, err := meth(string(msg.Path), args, extra)
253 if err != nil {253 if err != nil {
254 reply = dbus.NewErrorMessage(msg, err_iface, err.Error())254 reply = dbus.NewErrorMessage(msg, err_iface, err.Error())
255 endp.log.Errorf("WatchMethod: %s(%#v, %#v) failure: %#v", msg.Member, args, extra, err)255 endp.log.Errorf("WatchMethod: %s(%v, %#v, %#v) failure: %#v", msg.Member, msg.Path, args, extra, err)
256 } else {256 } else {
257 endp.log.Debugf("WatchMethod: %s(%#v, %#v) success: %#v", msg.Member, args, extra, rvals)257 endp.log.Debugf("WatchMethod: %s(%v, %#v, %#v) success: %#v", msg.Member, msg.Path, args, extra, rvals)
258 reply = dbus.NewMethodReturnMessage(msg)258 reply = dbus.NewMethodReturnMessage(msg)
259 err = reply.AppendArgs(rvals...)259 err = reply.AppendArgs(rvals...)
260 if err != nil {260 if err != nil {
261261
=== modified file 'bus/testing/testing_endpoint_test.go'
--- bus/testing/testing_endpoint_test.go 2014-06-02 10:04:34 +0000
+++ bus/testing/testing_endpoint_test.go 2014-06-06 12:14:20 +0000
@@ -229,7 +229,7 @@
229// Test that WatchMethod updates callArgs229// Test that WatchMethod updates callArgs
230func (s *TestingEndpointSuite) TestWatchMethodUpdatesCallArgs(c *C) {230func (s *TestingEndpointSuite) TestWatchMethodUpdatesCallArgs(c *C) {
231 endp := NewTestingEndpoint(nil, condition.Work(true))231 endp := NewTestingEndpoint(nil, condition.Work(true))
232 foo := func([]interface{}, []interface{}) ([]interface{}, error) { return nil, nil }232 foo := func(string, []interface{}, []interface{}) ([]interface{}, error) { return nil, nil }
233 foomp := bus.DispatchMap{"foo": foo}233 foomp := bus.DispatchMap{"foo": foo}
234 endp.WatchMethod(foomp)234 endp.WatchMethod(foomp)
235 c.Check(GetCallArgs(endp), DeepEquals, []callArgs{235 c.Check(GetCallArgs(endp), DeepEquals, []callArgs{
236236
=== modified file 'client/service/service.go'
--- client/service/service.go 2014-05-21 10:03:18 +0000
+++ client/service/service.go 2014-06-06 12:14:20 +0000
@@ -21,10 +21,12 @@
21import (21import (
22 "errors"22 "errors"
23 "os"23 "os"
24 "strings"
24 "sync"25 "sync"
2526
26 "launchpad.net/ubuntu-push/bus"27 "launchpad.net/ubuntu-push/bus"
27 "launchpad.net/ubuntu-push/logger"28 "launchpad.net/ubuntu-push/logger"
29 "launchpad.net/ubuntu-push/nih"
28)30)
2931
30// Service is the dbus api32// Service is the dbus api
@@ -51,7 +53,7 @@
51 AlreadyStarted = errors.New("already started")53 AlreadyStarted = errors.New("already started")
52 BusAddress = bus.Address{54 BusAddress = bus.Address{
53 Interface: "com.ubuntu.PushNotifications",55 Interface: "com.ubuntu.PushNotifications",
54 Path: "/com/ubuntu/PushNotifications",56 Path: "/com/ubuntu/PushNotifications/*",
55 Name: "com.ubuntu.PushNotifications",57 Name: "com.ubuntu.PushNotifications",
56 }58 }
57)59)
@@ -133,31 +135,26 @@
133 BadArgType = errors.New("Bad argument type")135 BadArgType = errors.New("Bad argument type")
134)136)
135137
136func (svc *Service) register(args []interface{}, _ []interface{}) ([]interface{}, error) {138func (svc *Service) register(path string, args, _ []interface{}) ([]interface{}, error) {
137 if len(args) != 1 {139 if len(args) != 0 {
138 return nil, BadArgCount140 return nil, BadArgCount
139 }141 }
140 appname, ok := args[0].(string)142 raw_appname := path[strings.LastIndex(path, "/")+1:]
141 if !ok {143 appname := string(nih.Unquote([]byte(raw_appname)))
142 return nil, BadArgType
143 }
144144
145 rv := os.Getenv("PUSH_REG_" + appname)145 rv := os.Getenv("PUSH_REG_" + raw_appname)
146 if rv == "" {146 if rv == "" {
147 rv = "this-is-an-opaque-block-of-random-bits-i-promise"147 rv = appname + "::this-is-an-opaque-block-of-random-bits-i-promise"
148 }148 }
149149
150 return []interface{}{rv}, nil150 return []interface{}{rv}, nil
151}151}
152152
153func (svc *Service) notifications(args []interface{}, _ []interface{}) ([]interface{}, error) {153func (svc *Service) notifications(path string, args, _ []interface{}) ([]interface{}, error) {
154 if len(args) != 1 {154 if len(args) != 0 {
155 return nil, BadArgCount155 return nil, BadArgCount
156 }156 }
157 appname, ok := args[0].(string)157 appname := string(nih.Unquote([]byte(path[strings.LastIndex(path, "/")+1:])))
158 if !ok {
159 return nil, BadArgType
160 }
161158
162 svc.lock.Lock()159 svc.lock.Lock()
163 defer svc.lock.Unlock()160 defer svc.lock.Unlock()
@@ -171,18 +168,15 @@
171 return []interface{}{msgs}, nil168 return []interface{}{msgs}, nil
172}169}
173170
174func (svc *Service) inject(args []interface{}, _ []interface{}) ([]interface{}, error) {171func (svc *Service) inject(path string, args, _ []interface{}) ([]interface{}, error) {
175 if len(args) != 2 {172 if len(args) != 1 {
176 return nil, BadArgCount173 return nil, BadArgCount
177 }174 }
178 appname, ok := args[0].(string)175 notif, ok := args[0].(string)
179 if !ok {176 if !ok {
180 return nil, BadArgType177 return nil, BadArgType
181 }178 }
182 notif, ok := args[1].(string)179 appname := string(nih.Unquote([]byte(path[strings.LastIndex(path, "/")+1:])))
183 if !ok {
184 return nil, BadArgType
185 }
186180
187 return nil, svc.Inject(appname, notif)181 return nil, svc.Inject(appname, notif)
188}182}
189183
=== modified file 'client/service/service_test.go'
--- client/service/service_test.go 2014-05-21 10:05:24 +0000
+++ client/service/service_test.go 2014-06-06 12:14:20 +0000
@@ -97,23 +97,13 @@
97// registration tests97// registration tests
9898
99func (ss *serviceSuite) TestRegistrationFailsIfBadArgs(c *C) {99func (ss *serviceSuite) TestRegistrationFailsIfBadArgs(c *C) {
100 for i, s := range []struct {100 reg, err := new(Service).register("", []interface{}{1}, nil)
101 args []interface{}101 c.Check(reg, IsNil)
102 errt error102 c.Check(err, Equals, BadArgCount)
103 }{
104 {nil, BadArgCount}, // no args
105 {[]interface{}{}, BadArgCount}, // still no args
106 {[]interface{}{42}, BadArgType}, // bad arg type
107 {[]interface{}{1, 2}, BadArgCount}, // too many args
108 } {
109 reg, err := new(Service).register(s.args, nil)
110 c.Check(reg, IsNil, Commentf("iteration #%d", i))
111 c.Check(err, Equals, s.errt, Commentf("iteration #%d", i))
112 }
113}103}
114104
115func (ss *serviceSuite) TestRegistrationWorks(c *C) {105func (ss *serviceSuite) TestRegistrationWorks(c *C) {
116 reg, err := new(Service).register([]interface{}{"this"}, nil)106 reg, err := new(Service).register("/this", nil, nil)
117 c.Assert(reg, HasLen, 1)107 c.Assert(reg, HasLen, 1)
118 regs, ok := reg[0].(string)108 regs, ok := reg[0].(string)
119 c.Check(ok, Equals, true)109 c.Check(ok, Equals, true)
@@ -125,7 +115,7 @@
125 os.Setenv("PUSH_REG_stuff", "42")115 os.Setenv("PUSH_REG_stuff", "42")
126 defer os.Setenv("PUSH_REG_stuff", "")116 defer os.Setenv("PUSH_REG_stuff", "")
127117
128 reg, err := new(Service).register([]interface{}{"stuff"}, nil)118 reg, err := new(Service).register("/stuff", nil, nil)
129 c.Assert(reg, HasLen, 1)119 c.Assert(reg, HasLen, 1)
130 regs, ok := reg[0].(string)120 regs, ok := reg[0].(string)
131 c.Check(ok, Equals, true)121 c.Check(ok, Equals, true)
@@ -138,10 +128,10 @@
138128
139func (ss *serviceSuite) TestInjectWorks(c *C) {129func (ss *serviceSuite) TestInjectWorks(c *C) {
140 svc := NewService(ss.bus, ss.log)130 svc := NewService(ss.bus, ss.log)
141 rvs, err := svc.inject([]interface{}{"hello", "world"}, nil)131 rvs, err := svc.inject("/hello", []interface{}{"world"}, nil)
142 c.Assert(err, IsNil)132 c.Assert(err, IsNil)
143 c.Check(rvs, IsNil)133 c.Check(rvs, IsNil)
144 rvs, err = svc.inject([]interface{}{"hello", "there"}, nil)134 rvs, err = svc.inject("/hello", []interface{}{"there"}, nil)
145 c.Assert(err, IsNil)135 c.Assert(err, IsNil)
146 c.Check(rvs, IsNil)136 c.Check(rvs, IsNil)
147 c.Assert(svc.mbox, HasLen, 1)137 c.Assert(svc.mbox, HasLen, 1)
@@ -162,7 +152,7 @@
162 condition.Work(false))152 condition.Work(false))
163 svc := NewService(bus, ss.log)153 svc := NewService(bus, ss.log)
164 svc.SetMessageHandler(func([]byte) error { return errors.New("fail") })154 svc.SetMessageHandler(func([]byte) error { return errors.New("fail") })
165 _, err := svc.inject([]interface{}{"hello", "xyzzy"}, nil)155 _, err := svc.inject("/hello", []interface{}{"xyzzy"}, nil)
166 c.Check(err, NotNil)156 c.Check(err, NotNil)
167}157}
168158
@@ -173,13 +163,10 @@
173 }{163 }{
174 {nil, BadArgCount},164 {nil, BadArgCount},
175 {[]interface{}{}, BadArgCount},165 {[]interface{}{}, BadArgCount},
176 {[]interface{}{1}, BadArgCount},166 {[]interface{}{1}, BadArgType},
177 {[]interface{}{1, 2}, BadArgType},167 {[]interface{}{1, 2}, BadArgCount},
178 {[]interface{}{"1", 2}, BadArgType},
179 {[]interface{}{1, "2"}, BadArgType},
180 {[]interface{}{1, 2, 3}, BadArgCount},
181 } {168 } {
182 reg, err := new(Service).inject(s.args, nil)169 reg, err := new(Service).inject("", s.args, nil)
183 c.Check(reg, IsNil, Commentf("iteration #%d", i))170 c.Check(reg, IsNil, Commentf("iteration #%d", i))
184 c.Check(err, Equals, s.errt, Commentf("iteration #%d", i))171 c.Check(err, Equals, s.errt, Commentf("iteration #%d", i))
185 }172 }
@@ -189,7 +176,7 @@
189// Notifications tests176// Notifications tests
190func (ss *serviceSuite) TestNotificationsWorks(c *C) {177func (ss *serviceSuite) TestNotificationsWorks(c *C) {
191 svc := NewService(ss.bus, ss.log)178 svc := NewService(ss.bus, ss.log)
192 nots, err := svc.notifications([]interface{}{"hello"}, nil)179 nots, err := svc.notifications("/hello", nil, nil)
193 c.Assert(err, IsNil)180 c.Assert(err, IsNil)
194 c.Assert(nots, NotNil)181 c.Assert(nots, NotNil)
195 c.Assert(nots, HasLen, 1)182 c.Assert(nots, HasLen, 1)
@@ -198,7 +185,7 @@
198 svc.mbox = make(map[string][]string)185 svc.mbox = make(map[string][]string)
199 }186 }
200 svc.mbox["hello"] = append(svc.mbox["hello"], "this", "thing")187 svc.mbox["hello"] = append(svc.mbox["hello"], "this", "thing")
201 nots, err = svc.notifications([]interface{}{"hello"}, nil)188 nots, err = svc.notifications("/hello", nil, nil)
202 c.Assert(err, IsNil)189 c.Assert(err, IsNil)
203 c.Assert(nots, NotNil)190 c.Assert(nots, NotNil)
204 c.Assert(nots, HasLen, 1)191 c.Assert(nots, HasLen, 1)
@@ -206,19 +193,9 @@
206}193}
207194
208func (ss *serviceSuite) TestNotificationsFailsIfBadArgs(c *C) {195func (ss *serviceSuite) TestNotificationsFailsIfBadArgs(c *C) {
209 for i, s := range []struct {196 reg, err := new(Service).notifications("/foo", []interface{}{1}, nil)
210 args []interface{}197 c.Check(reg, IsNil)
211 errt error198 c.Check(err, Equals, BadArgCount)
212 }{
213 {nil, BadArgCount}, // no args
214 {[]interface{}{}, BadArgCount}, // still no args
215 {[]interface{}{42}, BadArgType}, // bad arg type
216 {[]interface{}{1, 2}, BadArgCount}, // too many args
217 } {
218 reg, err := new(Service).notifications(s.args, nil)
219 c.Check(reg, IsNil, Commentf("iteration #%d", i))
220 c.Check(err, Equals, s.errt, Commentf("iteration #%d", i))
221 }
222}199}
223200
224func (ss *serviceSuite) TestMessageHandler(c *C) {201func (ss *serviceSuite) TestMessageHandler(c *C) {
225202
=== modified file 'debian/changelog'
--- debian/changelog 2014-06-05 09:42:22 +0000
+++ debian/changelog 2014-06-06 12:14:20 +0000
@@ -1,3 +1,17 @@
1ubuntu-push (0.31ubuntu1) UNRELEASED; urgency=medium
2
3 [ Samuele Pedroni ]
4 * Support registering tokens and sending notifications with a token
5 * Register script and scripts unicast support
6
7 [ Roberto Alsina ]
8 * Make signing-helper generate a HTTP header instead of a querystring.
9
10 [ John R. Lenton ]
11 * Switch dbus api to retrieve app name from dbus path.
12
13 -- John R. Lenton <john.lenton@canonical.com> Fri, 06 Jun 2014 12:02:56 +0100
14
1ubuntu-push (0.3+14.10.20140605-0ubuntu1) utopic; urgency=medium15ubuntu-push (0.3+14.10.20140605-0ubuntu1) utopic; urgency=medium
216
3 [ John Lenton ]17 [ John Lenton ]
418
=== modified file 'debian/rules'
--- debian/rules 2014-05-02 12:42:27 +0000
+++ debian/rules 2014-06-06 12:14:20 +0000
@@ -5,7 +5,6 @@
5export UBUNTU_PUSH_TEST_RESOURCES_ROOT := $(CURDIR)5export UBUNTU_PUSH_TEST_RESOURCES_ROOT := $(CURDIR)
66
7override_dh_auto_build:7override_dh_auto_build:
8 cd $$( find ./ -type d -regex '\./[^/]*/src/launchpad.net' -printf "%h\n" | head -n1)
9 dh_auto_build --buildsystem=golang8 dh_auto_build --buildsystem=golang
10 (cd signing-helper && cmake . && make)9 (cd signing-helper && cmake . && make)
1110
1211
=== modified file 'nih/nih.go'
--- nih/nih.go 2014-05-23 12:56:27 +0000
+++ nih/nih.go 2014-06-06 12:14:20 +0000
@@ -45,7 +45,7 @@
45 return out45 return out
46}46}
4747
48// Quote() takes a byte slice and undoes the damage done to it by the quoting.48// Unquote() takes a byte slice and undoes the damage done to it by Quote().
49func Unquote(s []byte) []byte {49func Unquote(s []byte) []byte {
50 out := make([]byte, 0, len(s))50 out := make([]byte, 0, len(s))
5151
5252
=== added file 'scripts/register'
--- scripts/register 1970-01-01 00:00:00 +0000
+++ scripts/register 2014-06-06 12:14:20 +0000
@@ -0,0 +1,43 @@
1#!/usr/bin/python3
2"""
3request a unicast registration
4"""
5import argparse
6import json
7import requests
8import subprocess
9import datetime
10import sys
11
12
13def main():
14 parser = argparse.ArgumentParser(description=__doc__)
15 parser.add_argument('deviceid', nargs=1)
16 parser.add_argument('appid', nargs=1)
17 parser.add_argument('-H', '--host',
18 help="host:port (default: %(default)s)",
19 default="localhost:8080")
20 parser.add_argument('--no-https', action='store_true', default=False)
21 parser.add_argument('--insecure', action='store_true', default=False,
22 help="don't check host/certs with https")
23 parser.add_argument('--auth_helper', default="")
24 args = parser.parse_args()
25 scheme = 'https'
26 if args.no_https:
27 scheme = 'http'
28 url = "%s://%s/register" % (scheme, args.host)
29 body = {
30 'deviceid': args.deviceid[0],
31 'appid': args.appid[0],
32 }
33 headers = {'Content-Type': 'application/json'}
34 if args.auth_helper:
35 auth = subprocess.check_output([args.auth_helper, url]).strip()
36 headers['Authorization'] = auth
37 r = requests.post(url, data=json.dumps(body), headers=headers,
38 verify=not args.insecure)
39 print(r.status_code)
40 print(r.text)
41
42if __name__ == '__main__':
43 main()
044
=== modified file 'scripts/unicast'
--- scripts/unicast 2014-05-29 14:55:19 +0000
+++ scripts/unicast 2014-06-06 12:14:20 +0000
@@ -52,6 +52,8 @@
52 userid, devid = reg.split(':', 1)52 userid, devid = reg.split(':', 1)
53 body['userid'] = userid53 body['userid'] = userid
54 body['deviceid'] = devid54 body['deviceid'] = devid
55 else:
56 body['token'] = reg
55 xauth = {}57 xauth = {}
56 if args.user and args.password:58 if args.user and args.password:
57 xauth = {'auth': requests.auth.HTTPBasicAuth(args.user, args.password)}59 xauth = {'auth': requests.auth.HTTPBasicAuth(args.user, args.password)}
5860
=== modified file 'server/acceptance/acceptanceclient.go'
--- server/acceptance/acceptanceclient.go 2014-05-23 12:30:32 +0000
+++ server/acceptance/acceptanceclient.go 2014-06-06 12:14:20 +0000
@@ -155,7 +155,7 @@
155 return err155 return err
156 }156 }
157 events <- fmt.Sprintf("%sbroadcast chan:%v app:%v topLevel:%d payloads:%s", sess.Prefix, recv.ChanId, recv.AppId, recv.TopLevel, pack)157 events <- fmt.Sprintf("%sbroadcast chan:%v app:%v topLevel:%d payloads:%s", sess.Prefix, recv.ChanId, recv.AppId, recv.TopLevel, pack)
158 case "connwarn":158 case "warn", "connwarn":
159 events <- fmt.Sprintf("%sconnwarn %s", sess.Prefix, recv.Reason)159 events <- fmt.Sprintf("%sconnwarn %s", sess.Prefix, recv.Reason)
160 }160 }
161 }161 }
162162
=== modified file 'server/acceptance/cmd/acceptanceclient.go'
--- server/acceptance/cmd/acceptanceclient.go 2014-05-21 07:58:26 +0000
+++ server/acceptance/cmd/acceptanceclient.go 2014-06-06 12:14:20 +0000
@@ -90,7 +90,9 @@
90 }90 }
91 }91 }
92 if len(cfg.AuthHelper) != 0 {92 if len(cfg.AuthHelper) != 0 {
93 auth, err := exec.Command(cfg.AuthHelper[0], cfg.AuthHelper[1:]...).Output()93 helperArgs := cfg.AuthHelper[1:]
94 helperArgs = append(helperArgs, "https://push.ubuntu.com/")
95 auth, err := exec.Command(cfg.AuthHelper[0], helperArgs...).Output()
94 if err != nil {96 if err != nil {
95 log.Fatalf("auth helper: %v", err)97 log.Fatalf("auth helper: %v", err)
96 }98 }
9799
=== modified file 'server/acceptance/suites/suite.go'
--- server/acceptance/suites/suite.go 2014-05-02 09:56:49 +0000
+++ server/acceptance/suites/suite.go 2014-06-06 12:14:20 +0000
@@ -89,7 +89,7 @@
89 // to kill the server process89 // to kill the server process
90 KillGroup map[string]func(os.Signal)90 KillGroup map[string]func(os.Signal)
91 // hook to adjust requests91 // hook to adjust requests
92 MassageRequest func(req *http.Request) *http.Request92 MassageRequest func(req *http.Request, message interface{}) *http.Request
93 // other state93 // other state
94 httpClient *http.Client94 httpClient *http.Client
95}95}
@@ -124,7 +124,7 @@
124 request.Header.Set("Content-Type", "application/json")124 request.Header.Set("Content-Type", "application/json")
125125
126 if s.MassageRequest != nil {126 if s.MassageRequest != nil {
127 request = s.MassageRequest(request)127 request = s.MassageRequest(request, message)
128 }128 }
129129
130 resp, err := s.httpClient.Do(request)130 resp, err := s.httpClient.Do(request)
131131
=== modified file 'server/acceptance/suites/unicast.go'
--- server/acceptance/suites/unicast.go 2014-05-15 16:41:54 +0000
+++ server/acceptance/suites/unicast.go 2014-06-06 12:14:20 +0000
@@ -40,11 +40,19 @@
40}40}
4141
42func (s *UnicastAcceptanceSuite) TestUnicastToConnected(c *C) {42func (s *UnicastAcceptanceSuite) TestUnicastToConnected(c *C) {
43 userId, auth := s.associatedAuth("DEV1")43 _, auth := s.associatedAuth("DEV1")
44 res, err := s.PostRequest("/register", &api.Registration{
45 DeviceId: "DEV1",
46 AppId: "app1",
47 })
48 c.Assert(err, IsNil)
49 c.Assert(res, Matches, ".*ok.*")
50 var reg map[string]interface{}
51 err = json.Unmarshal([]byte(res), &reg)
52 c.Assert(err, IsNil)
44 events, errCh, stop := s.StartClientAuth(c, "DEV1", nil, auth)53 events, errCh, stop := s.StartClientAuth(c, "DEV1", nil, auth)
45 got, err := s.PostRequest("/notify", &api.Unicast{54 got, err := s.PostRequest("/notify", &api.Unicast{
46 UserId: userId,55 Token: reg["token"].(string),
47 DeviceId: "DEV1",
48 AppId: "app1",56 AppId: "app1",
49 ExpireOn: future,57 ExpireOn: future,
50 Data: json.RawMessage(`{"a": 42}`),58 Data: json.RawMessage(`{"a": 42}`),
5159
=== modified file 'server/api/handlers.go'
--- server/api/handlers.go 2014-05-29 16:22:00 +0000
+++ server/api/handlers.go 2014-06-06 12:14:20 +0000
@@ -51,6 +51,8 @@
51 ioError = "io-error"51 ioError = "io-error"
52 invalidRequest = "invalid-request"52 invalidRequest = "invalid-request"
53 unknownChannel = "unknown-channel"53 unknownChannel = "unknown-channel"
54 unknownToken = "unknown-token"
55 unauthorized = "unauthorized"
54 unavailable = "unavailable"56 unavailable = "unavailable"
55 internalError = "internal"57 internalError = "internal"
56)58)
@@ -121,6 +123,11 @@
121 unknownChannel,123 unknownChannel,
122 "Unknown channel",124 "Unknown channel",
123 }125 }
126 ErrUnknownToken = &APIError{
127 http.StatusBadRequest,
128 unknownToken,
129 "Unknown token",
130 }
124 ErrUnknown = &APIError{131 ErrUnknown = &APIError{
125 http.StatusInternalServerError,132 http.StatusInternalServerError,
126 internalError,133 internalError,
@@ -136,16 +143,33 @@
136 unavailable,143 unavailable,
137 "Could not store notification",144 "Could not store notification",
138 }145 }
146 ErrCouldNotMakeToken = &APIError{
147 http.StatusServiceUnavailable,
148 unavailable,
149 "Could not make token",
150 }
151 ErrCouldNotResolveToken = &APIError{
152 http.StatusServiceUnavailable,
153 unavailable,
154 "Could not resolve token",
155 }
156 ErrUnauthorized = &APIError{
157 http.StatusUnauthorized,
158 unauthorized,
159 "Unauthorized",
160 }
139)161)
140162
141type castCommon struct {163type Registration struct {
164 DeviceId string `json:"deviceid"`
165 AppId string `json:"appid"`
142}166}
143167
144type Unicast struct {168type Unicast struct {
169 Token string `json:"token"`
145 UserId string `json:"userid"`170 UserId string `json:"userid"`
146 DeviceId string `json:"deviceid"`171 DeviceId string `json:"deviceid"`
147 AppId string `json:"appid"`172 AppId string `json:"appid"`
148 //Registration string `json:"registration"`
149 //CoalesceTag string `json:"coalesce_tag"`173 //CoalesceTag string `json:"coalesce_tag"`
150 ExpireOn string `json:"expire_on"`174 ExpireOn string `json:"expire_on"`
151 Data json.RawMessage `json:"data"`175 Data json.RawMessage `json:"data"`
@@ -183,15 +207,15 @@
183}207}
184208
185func checkRequestAsPost(request *http.Request, maxBodySize int64) *APIError {209func checkRequestAsPost(request *http.Request, maxBodySize int64) *APIError {
210 if request.Method != "POST" {
211 return ErrWrongRequestMethod
212 }
186 if err := checkContentLength(request, maxBodySize); err != nil {213 if err := checkContentLength(request, maxBodySize); err != nil {
187 return err214 return err
188 }215 }
189 if request.Header.Get("Content-Type") != JSONMediaType {216 if request.Header.Get("Content-Type") != JSONMediaType {
190 return ErrWrongContentType217 return ErrWrongContentType
191 }218 }
192 if request.Method != "POST" {
193 return ErrWrongRequestMethod
194 }
195 return nil219 return nil
196}220}
197221
@@ -325,7 +349,10 @@
325}349}
326350
327func checkUnicast(ucast *Unicast) (time.Time, *APIError) {351func checkUnicast(ucast *Unicast) (time.Time, *APIError) {
328 if ucast.UserId == "" || ucast.DeviceId == "" || ucast.AppId == "" {352 if ucast.AppId == "" {
353 return zeroTime, ErrMissingIdField
354 }
355 if ucast.Token == "" && (ucast.UserId == "" || ucast.DeviceId == "") {
329 return zeroTime, ErrMissingIdField356 return zeroTime, ErrMissingIdField
330 }357 }
331 return checkCastCommon(ucast.Data, ucast.ExpireOn)358 return checkCastCommon(ucast.Data, ucast.ExpireOn)
@@ -341,9 +368,21 @@
341 if apiErr != nil {368 if apiErr != nil {
342 return apiErr369 return apiErr
343 }370 }
344 chanId := store.UnicastInternalChannelId(ucast.UserId, ucast.DeviceId)371 chanId, err := sto.GetInternalChannelIdFromToken(ucast.Token, ucast.AppId, ucast.UserId, ucast.DeviceId)
372 if err != nil {
373 switch err {
374 case store.ErrUnknownToken:
375 return ErrUnknownToken
376 case store.ErrUnauthorized:
377 return ErrUnauthorized
378 default:
379 h.logger.Errorf("could not resolve token: %v", err)
380 return ErrCouldNotResolveToken
381 }
382 }
383
345 msgId := generateMsgId()384 msgId := generateMsgId()
346 err := sto.AppendToUnicastChannel(chanId, ucast.AppId, ucast.Data, msgId, expire)385 err = sto.AppendToUnicastChannel(chanId, ucast.AppId, ucast.Data, msgId, expire)
347 if err != nil {386 if err != nil {
348 h.logger.Errorf("could not store notification: %v", err)387 h.logger.Errorf("could not store notification: %v", err)
349 return ErrCouldNotStoreNotification388 return ErrCouldNotStoreNotification
@@ -378,6 +417,62 @@
378 fmt.Fprintf(writer, `{"ok":true}`)417 fmt.Fprintf(writer, `{"ok":true}`)
379}418}
380419
420type RegisterHandler struct {
421 *context
422}
423
424func checkRegister(reg *Registration) *APIError {
425 if reg.DeviceId == "" || reg.AppId == "" {
426 return ErrMissingIdField
427 }
428 return nil
429}
430
431func (h *RegisterHandler) doRegister(sto store.PendingStore, reg *Registration) (string, *APIError) {
432 apiErr := checkRegister(reg)
433 if apiErr != nil {
434 return "", apiErr
435 }
436 token, err := sto.Register(reg.DeviceId, reg.AppId)
437 if err != nil {
438 h.logger.Errorf("could not make a token: %v", err)
439 return "", ErrCouldNotMakeToken
440 }
441 return token, nil
442}
443
444func (h *RegisterHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
445 var apiErr *APIError
446 defer func() {
447 if apiErr != nil {
448 RespondError(writer, apiErr)
449 }
450 }()
451
452 reg := &Registration{}
453
454 sto, apiErr := h.prepare(writer, request, reg)
455 if apiErr != nil {
456 return
457 }
458 defer sto.Close()
459
460 token, apiErr := h.doRegister(sto, reg)
461 if apiErr != nil {
462 return
463 }
464
465 writer.Header().Set("Content-Type", "application/json")
466 res, err := json.Marshal(map[string]interface{}{
467 "ok": true,
468 "token": token,
469 })
470 if err != nil {
471 panic(fmt.Errorf("couldn't marshal our own response: %v", err))
472 }
473 writer.Write(res)
474}
475
381// MakeHandlersMux makes a handler that dispatches for the various API endpoints.476// MakeHandlersMux makes a handler that dispatches for the various API endpoints.
382func MakeHandlersMux(storeForRequest StoreForRequest, broker broker.BrokerSending, logger logger.Logger) *http.ServeMux {477func MakeHandlersMux(storeForRequest StoreForRequest, broker broker.BrokerSending, logger logger.Logger) *http.ServeMux {
383 ctx := &context{478 ctx := &context{
@@ -388,5 +483,6 @@
388 mux := http.NewServeMux()483 mux := http.NewServeMux()
389 mux.Handle("/broadcast", &BroadcastHandler{context: ctx})484 mux.Handle("/broadcast", &BroadcastHandler{context: ctx})
390 mux.Handle("/notify", &UnicastHandler{context: ctx})485 mux.Handle("/notify", &UnicastHandler{context: ctx})
486 mux.Handle("/register", &RegisterHandler{context: ctx})
391 return mux487 return mux
392}488}
393489
=== modified file 'server/api/handlers_test.go'
--- server/api/handlers_test.go 2014-05-01 18:58:16 +0000
+++ server/api/handlers_test.go 2014-06-06 12:14:20 +0000
@@ -192,6 +192,16 @@
192 intercept func(meth string, err error) error192 intercept func(meth string, err error) error
193}193}
194194
195func (isto *interceptInMemoryPendingStore) Register(appId, deviceId string) (string, error) {
196 token, err := isto.InMemoryPendingStore.Register(appId, deviceId)
197 return token, isto.intercept("Register", err)
198}
199
200func (isto *interceptInMemoryPendingStore) GetInternalChannelIdFromToken(token, appId, userId, deviceId string) (store.InternalChannelId, error) {
201 chanId, err := isto.InMemoryPendingStore.GetInternalChannelIdFromToken(token, appId, userId, deviceId)
202 return chanId, isto.intercept("GetInternalChannelIdFromToken", err)
203}
204
195func (isto *interceptInMemoryPendingStore) GetInternalChannelId(channel string) (store.InternalChannelId, error) {205func (isto *interceptInMemoryPendingStore) GetInternalChannelId(channel string) (store.InternalChannelId, error) {
196 chanId, err := isto.InMemoryPendingStore.GetInternalChannelId(channel)206 chanId, err := isto.InMemoryPendingStore.GetInternalChannelId(channel)
197 return chanId, isto.intercept("GetInternalChannelId", err)207 return chanId, isto.intercept("GetInternalChannelId", err)
@@ -262,6 +272,14 @@
262272
263 u = unicast()273 u = unicast()
264 u.UserId = ""274 u.UserId = ""
275 u.DeviceId = ""
276 u.Token = "TOKEN"
277 expire, apiErr = checkUnicast(u)
278 c.Assert(apiErr, IsNil)
279 c.Check(expire.Format(time.RFC3339), Equals, future)
280
281 u = unicast()
282 u.UserId = ""
265 expire, apiErr = checkUnicast(u)283 expire, apiErr = checkUnicast(u)
266 c.Check(apiErr, Equals, ErrMissingIdField)284 c.Check(apiErr, Equals, ErrMissingIdField)
267285
@@ -353,6 +371,40 @@
353 c.Check(s.testlog.Captured(), Equals, "ERROR could not store notification: fail\n")371 c.Check(s.testlog.Captured(), Equals, "ERROR could not store notification: fail\n")
354}372}
355373
374func (s *handlersSuite) TestDoUnicastFromTokenFailures(c *C) {
375 fail := errors.New("fail")
376 sto := &interceptInMemoryPendingStore{
377 store.NewInMemoryPendingStore(),
378 func(meth string, err error) error {
379 if meth == "GetInternalChannelIdFromToken" {
380 return fail
381 }
382 return err
383 },
384 }
385 ctx := &context{logger: s.testlog}
386 bh := &UnicastHandler{ctx}
387 u := &Unicast{
388 Token: "tok",
389 AppId: "app1",
390 ExpireOn: future,
391 Data: json.RawMessage(`{"a": 1}`),
392 }
393 apiErr := bh.doUnicast(sto, u)
394 c.Check(apiErr, Equals, ErrCouldNotResolveToken)
395 c.Check(s.testlog.Captured(), Equals, "ERROR could not resolve token: fail\n")
396 s.testlog.ResetCapture()
397
398 fail = store.ErrUnknownToken
399 apiErr = bh.doUnicast(sto, u)
400 c.Check(apiErr, Equals, ErrUnknownToken)
401 c.Check(s.testlog.Captured(), Equals, "")
402 fail = store.ErrUnauthorized
403 apiErr = bh.doUnicast(sto, u)
404 c.Check(apiErr, Equals, ErrUnauthorized)
405 c.Check(s.testlog.Captured(), Equals, "")
406}
407
356func newPostRequest(path string, message interface{}, server *httptest.Server) *http.Request {408func newPostRequest(path string, message interface{}, server *httptest.Server) *http.Request {
357 packedMessage, err := json.Marshal(message)409 packedMessage, err := json.Marshal(message)
358 if err != nil {410 if err != nil {
@@ -427,7 +479,7 @@
427 dest := make(map[string]bool)479 dest := make(map[string]bool)
428 err = json.Unmarshal(body, &dest)480 err = json.Unmarshal(body, &dest)
429 c.Assert(err, IsNil)481 c.Assert(err, IsNil)
430 c.Check(dest, DeepEquals, map[string]bool{"ok": true})482 c.Assert(dest, DeepEquals, map[string]bool{"ok": true})
431483
432 top, _, err := sto.GetChannelSnapshot(store.SystemInternalChannelId)484 top, _, err := sto.GetChannelSnapshot(store.SystemInternalChannelId)
433 c.Assert(err, IsNil)485 c.Assert(err, IsNil)
@@ -639,7 +691,7 @@
639 c.Check(response.Header.Get("Content-Type"), Equals, "application/json")691 c.Check(response.Header.Get("Content-Type"), Equals, "application/json")
640 body, err := getResponseBody(response)692 body, err := getResponseBody(response)
641 c.Assert(err, IsNil)693 c.Assert(err, IsNil)
642 c.Check(string(body), Matches, ".*ok.*")694 c.Assert(string(body), Matches, ".*ok.*")
643695
644 chanId := store.UnicastInternalChannelId("user2", "dev3")696 chanId := store.UnicastInternalChannelId("user2", "dev3")
645 c.Check(<-bsend.chanId, Equals, chanId)697 c.Check(<-bsend.chanId, Equals, chanId)
@@ -682,3 +734,142 @@
682 c.Assert(err, IsNil)734 c.Assert(err, IsNil)
683 checkError(c, response, ErrMissingIdField)735 checkError(c, response, ErrMissingIdField)
684}736}
737
738func (s *handlersSuite) TestCheckRegister(c *C) {
739 registration := func() *Registration {
740 return &Registration{
741 DeviceId: "DEV1",
742 AppId: "app1",
743 }
744 }
745 reg := registration()
746 apiErr := checkRegister(reg)
747 c.Assert(apiErr, IsNil)
748
749 reg = registration()
750 reg.AppId = ""
751 apiErr = checkRegister(reg)
752 c.Check(apiErr, Equals, ErrMissingIdField)
753
754 reg = registration()
755 reg.DeviceId = ""
756 apiErr = checkRegister(reg)
757 c.Check(apiErr, Equals, ErrMissingIdField)
758}
759
760func (s *handlersSuite) TestDoRegisterMissingIdField(c *C) {
761 sto := store.NewInMemoryPendingStore()
762 rh := &RegisterHandler{}
763 token, apiErr := rh.doRegister(sto, &Registration{})
764 c.Check(apiErr, Equals, ErrMissingIdField)
765 c.Check(token, Equals, "")
766}
767
768func (s *handlersSuite) TestDoRegisterCouldNotMakeToken(c *C) {
769 sto := &interceptInMemoryPendingStore{
770 store.NewInMemoryPendingStore(),
771 func(meth string, err error) error {
772 if meth == "Register" {
773 return errors.New("fail")
774 }
775 return err
776 },
777 }
778 ctx := &context{logger: s.testlog}
779 rh := &RegisterHandler{ctx}
780 _, apiErr := rh.doRegister(sto, &Registration{
781 DeviceId: "DEV1",
782 AppId: "app1",
783 })
784 c.Check(apiErr, Equals, ErrCouldNotMakeToken)
785 c.Check(s.testlog.Captured(), Equals, "ERROR could not make a token: fail\n")
786}
787
788func (s *handlersSuite) TestRespondsToRegisterAndUnicast(c *C) {
789 sto := store.NewInMemoryPendingStore()
790 stoForReq := func(http.ResponseWriter, *http.Request) (store.PendingStore, error) {
791 return sto, nil
792 }
793 bsend := testBrokerSending{make(chan store.InternalChannelId, 1)}
794 testServer := httptest.NewServer(MakeHandlersMux(stoForReq, bsend, nil))
795 defer testServer.Close()
796
797 request := newPostRequest("/register", &Registration{
798 DeviceId: "dev3",
799 AppId: "app2",
800 }, testServer)
801
802 response, err := s.client.Do(request)
803 c.Assert(err, IsNil)
804
805 c.Check(response.StatusCode, Equals, http.StatusOK)
806 c.Check(response.Header.Get("Content-Type"), Equals, "application/json")
807 body, err := getResponseBody(response)
808 c.Assert(err, IsNil)
809 c.Assert(string(body), Matches, ".*ok.*")
810 var reg map[string]interface{}
811 err = json.Unmarshal(body, &reg)
812 c.Assert(err, IsNil)
813
814 token, ok := reg["token"].(string)
815 c.Assert(ok, Equals, true)
816 c.Check(token, Not(Equals), nil)
817
818 payload := json.RawMessage(`{"foo":"bar"}`)
819
820 request = newPostRequest("/notify", &Unicast{
821 Token: token,
822 AppId: "app2",
823 ExpireOn: future,
824 Data: payload,
825 }, testServer)
826
827 response, err = s.client.Do(request)
828 c.Assert(err, IsNil)
829
830 c.Check(response.StatusCode, Equals, http.StatusOK)
831 c.Check(response.Header.Get("Content-Type"), Equals, "application/json")
832 body, err = getResponseBody(response)
833 c.Assert(err, IsNil)
834 c.Assert(string(body), Matches, ".*ok.*")
835
836 chanId := store.UnicastInternalChannelId("dev3", "dev3")
837 c.Check(<-bsend.chanId, Equals, chanId)
838 top, notifications, err := sto.GetChannelSnapshot(chanId)
839 c.Assert(err, IsNil)
840 c.Check(top, Equals, int64(0))
841 c.Check(notifications, HasLen, 1)
842}
843
844func (s *handlersSuite) TestCannotRegisterWithMissingFields(c *C) {
845 stoForReq := func(http.ResponseWriter, *http.Request) (store.PendingStore, error) {
846 return store.NewInMemoryPendingStore(), nil
847 }
848 ctx := &context{stoForReq, nil, nil}
849 testServer := httptest.NewServer(&RegisterHandler{ctx})
850 defer testServer.Close()
851
852 request := newPostRequest("/", &Registration{
853 DeviceId: "DEV1",
854 }, testServer)
855
856 response, err := s.client.Do(request)
857 c.Assert(err, IsNil)
858 checkError(c, response, ErrMissingIdField)
859}
860
861func (s *handlersSuite) TestCannotRegisterWithNonPOST(c *C) {
862 stoForReq := func(http.ResponseWriter, *http.Request) (store.PendingStore, error) {
863 return store.NewInMemoryPendingStore(), nil
864 }
865 ctx := &context{stoForReq, nil, nil}
866 testServer := httptest.NewServer(&RegisterHandler{ctx})
867 defer testServer.Close()
868
869 request, err := http.NewRequest("GET", testServer.URL, nil)
870 c.Assert(err, IsNil)
871
872 response, err := s.client.Do(request)
873 c.Assert(err, IsNil)
874 checkError(c, response, ErrWrongRequestMethod)
875}
685876
=== modified file 'server/store/inmemory.go'
--- server/store/inmemory.go 2014-05-02 15:10:18 +0000
+++ server/store/inmemory.go 2014-06-06 12:14:20 +0000
@@ -17,7 +17,10 @@
17package store17package store
1818
19import (19import (
20 "encoding/base64"
20 "encoding/json"21 "encoding/json"
22 "fmt"
23 "strings"
21 "sync"24 "sync"
22 "time"25 "time"
2326
@@ -44,6 +47,29 @@
44 }47 }
45}48}
4649
50func (sto *InMemoryPendingStore) Register(deviceId, appId string) (string, error) {
51 return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s::%s", appId, deviceId))), nil
52}
53
54func (sto *InMemoryPendingStore) GetInternalChannelIdFromToken(token, appId, userId, deviceId string) (InternalChannelId, error) {
55 if token != "" && appId != "" {
56 decoded, err := base64.StdEncoding.DecodeString(token)
57 if err != nil {
58 return "", ErrUnknownToken
59 }
60 token = string(decoded)
61 if !strings.HasPrefix(token, appId+"::") {
62 return "", ErrUnauthorized
63 }
64 deviceId := token[len(appId)+2:]
65 return UnicastInternalChannelId(deviceId, deviceId), nil
66 }
67 if userId != "" && deviceId != "" {
68 return UnicastInternalChannelId(userId, deviceId), nil
69 }
70 return "", ErrUnknownToken
71}
72
47func (sto *InMemoryPendingStore) GetInternalChannelId(name string) (InternalChannelId, error) {73func (sto *InMemoryPendingStore) GetInternalChannelId(name string) (InternalChannelId, error) {
48 if name == "system" {74 if name == "system" {
49 return SystemInternalChannelId, nil75 return SystemInternalChannelId, nil
5076
=== modified file 'server/store/inmemory_test.go'
--- server/store/inmemory_test.go 2014-04-30 17:44:56 +0000
+++ server/store/inmemory_test.go 2014-06-06 12:14:20 +0000
@@ -30,6 +30,50 @@
3030
31var _ = Suite(&inMemorySuite{})31var _ = Suite(&inMemorySuite{})
3232
33func (s *inMemorySuite) TestRegister(c *C) {
34 sto := NewInMemoryPendingStore()
35
36 tok1, err := sto.Register("DEV1", "app1")
37 c.Assert(err, IsNil)
38 tok2, err := sto.Register("DEV1", "app1")
39 c.Assert(err, IsNil)
40 c.Check(len(tok1), Not(Equals), 0)
41 c.Check(tok1, Equals, tok2)
42}
43
44func (s *inMemorySuite) TestGetInternalChannelIdFromToken(c *C) {
45 sto := NewInMemoryPendingStore()
46
47 tok1, err := sto.Register("DEV1", "app1")
48 c.Assert(err, IsNil)
49 chanId, err := sto.GetInternalChannelIdFromToken(tok1, "app1", "", "")
50 c.Assert(err, IsNil)
51 c.Check(chanId, Equals, UnicastInternalChannelId("DEV1", "DEV1"))
52}
53
54func (s *inMemorySuite) TestGetInternalChannelIdFromTokenFallback(c *C) {
55 sto := NewInMemoryPendingStore()
56
57 chanId, err := sto.GetInternalChannelIdFromToken("", "app1", "u1", "d1")
58 c.Assert(err, IsNil)
59 c.Check(chanId, Equals, UnicastInternalChannelId("u1", "d1"))
60}
61
62func (s *inMemorySuite) TestGetInternalChannelIdFromTokenErrors(c *C) {
63 sto := NewInMemoryPendingStore()
64 tok1, err := sto.Register("DEV1", "app1")
65 c.Assert(err, IsNil)
66
67 _, err = sto.GetInternalChannelIdFromToken(tok1, "app2", "", "")
68 c.Assert(err, Equals, ErrUnauthorized)
69
70 _, err = sto.GetInternalChannelIdFromToken("", "app2", "", "")
71 c.Assert(err, Equals, ErrUnknownToken)
72
73 _, err = sto.GetInternalChannelIdFromToken("****", "app2", "", "")
74 c.Assert(err, Equals, ErrUnknownToken)
75}
76
33func (s *inMemorySuite) TestGetInternalChannelId(c *C) {77func (s *inMemorySuite) TestGetInternalChannelId(c *C) {
34 sto := NewInMemoryPendingStore()78 sto := NewInMemoryPendingStore()
3579
3680
=== modified file 'server/store/store.go'
--- server/store/store.go 2014-05-02 15:10:18 +0000
+++ server/store/store.go 2014-06-06 12:14:20 +0000
@@ -52,6 +52,8 @@
52}52}
5353
54var ErrUnknownChannel = errors.New("unknown channel name")54var ErrUnknownChannel = errors.New("unknown channel name")
55var ErrUnknownToken = errors.New("unknown token")
56var ErrUnauthorized = errors.New("unauthorized")
55var ErrFull = errors.New("channel is full")57var ErrFull = errors.New("channel is full")
56var ErrExpected128BitsHexRepr = errors.New("expected 128 bits hex repr")58var ErrExpected128BitsHexRepr = errors.New("expected 128 bits hex repr")
5759
@@ -98,11 +100,17 @@
98100
99// PendingStore let store notifications into channels.101// PendingStore let store notifications into channels.
100type PendingStore interface {102type PendingStore interface {
103 // Register returns a token for a device id, application id pair.
104 Register(deviceId, appId string) (token string, err error)
101 // GetInternalChannelId returns the internal store id for a channel105 // GetInternalChannelId returns the internal store id for a channel
102 // given the name.106 // given the name.
103 GetInternalChannelId(name string) (InternalChannelId, error)107 GetInternalChannelId(name string) (InternalChannelId, error)
104 // AppendToChannel appends a notification to the channel.108 // AppendToChannel appends a notification to the channel.
105 AppendToChannel(chanId InternalChannelId, notification json.RawMessage, expiration time.Time) error109 AppendToChannel(chanId InternalChannelId, notification json.RawMessage, expiration time.Time) error
110 // GetInternalChannelIdFromToken returns the matching internal store
111 // id for a channel given a registered token and application id or
112 // directly a device id, user id pair.
113 GetInternalChannelIdFromToken(token, appId, userId, deviceId string) (InternalChannelId, error)
106 // AppendToUnicastChannel appends a notification to the unicast channel.114 // AppendToUnicastChannel appends a notification to the unicast channel.
107 // GetChannelSnapshot gets all the current notifications and115 // GetChannelSnapshot gets all the current notifications and
108 AppendToUnicastChannel(chanId InternalChannelId, appId string, notification json.RawMessage, msgId string, expiration time.Time) error116 AppendToUnicastChannel(chanId InternalChannelId, appId string, notification json.RawMessage, msgId string, expiration time.Time) error
109117
=== modified file 'signing-helper/signing-helper.cpp'
--- signing-helper/signing-helper.cpp 2014-05-01 10:24:23 +0000
+++ signing-helper/signing-helper.cpp 2014-06-06 12:14:20 +0000
@@ -33,6 +33,7 @@
33#include <QObject>33#include <QObject>
34#include <QString>34#include <QString>
35#include <QTimer>35#include <QTimer>
36#include <QUrlQuery>
3637
37#include "ssoservice.h"38#include "ssoservice.h"
38#include "token.h"39#include "token.h"
@@ -63,12 +64,8 @@
63 void SigningExample::handleCredentialsFound(Token token)64 void SigningExample::handleCredentialsFound(Token token)
64 {65 {
65 qDebug() << "Credentials found, signing url.";66 qDebug() << "Credentials found, signing url.";
6667 std::cout << token.signUrl(this->url, QStringLiteral("POST")).toStdString();
67 QString authHeader = token.signUrl(this->url, QStringLiteral("GET"), true);
68
69 std::cout << authHeader.toStdString() << "\n";
70 QCoreApplication::instance()->exit(0);68 QCoreApplication::instance()->exit(0);
71
72 }69 }
7370
74 void SigningExample::handleCredentialsNotFound()71 void SigningExample::handleCredentialsNotFound()
@@ -84,13 +81,12 @@
84int main(int argc, char *argv[])81int main(int argc, char *argv[])
85{82{
86 QCoreApplication a(argc, argv);83 QCoreApplication a(argc, argv);
8784 if (argc<2) {
88 UbuntuOne::SigningExample *example = new UbuntuOne::SigningExample(&a);85 return 2;
8986 }
87 UbuntuOne::SigningExample *example = new UbuntuOne::SigningExample(&a, argv[1]);
90 QObject::connect(example, SIGNAL(finished()), &a, SLOT(quit()));88 QObject::connect(example, SIGNAL(finished()), &a, SLOT(quit()));
91
92 QTimer::singleShot(0, example, SLOT(doExample()));89 QTimer::singleShot(0, example, SLOT(doExample()));
93
94 return a.exec();90 return a.exec();
95}91}
9692

Subscribers

People subscribed via source and target branches