Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 5 | package server |
| 6 | |
| 7 | import ( |
| 8 | "strings" |
| 9 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 10 | wire "v.io/syncbase/v23/services/syncbase" |
| 11 | "v.io/syncbase/x/ref/services/syncbase/server/nosql" |
| 12 | "v.io/syncbase/x/ref/services/syncbase/server/util" |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 13 | "v.io/v23/rpc" |
| 14 | "v.io/v23/security" |
| 15 | "v.io/v23/verror" |
| 16 | ) |
| 17 | |
| 18 | type dispatcher struct { |
| 19 | s *service |
| 20 | } |
| 21 | |
| 22 | var _ rpc.Dispatcher = (*dispatcher)(nil) |
| 23 | |
| 24 | func NewDispatcher(s *service) *dispatcher { |
| 25 | return &dispatcher{s: s} |
| 26 | } |
| 27 | |
| 28 | // TODO(sadovsky): Return a real authorizer in various places below. |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 29 | func (disp *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) { |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 30 | suffix = strings.TrimPrefix(suffix, "/") |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 31 | parts := strings.SplitN(suffix, "/", 2) |
| 32 | |
| 33 | if len(suffix) == 0 { |
| 34 | return wire.ServiceServer(disp.s), nil, nil |
| 35 | } |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 36 | |
| 37 | // Validate all key atoms up front, so that we can avoid doing so in all our |
| 38 | // method implementations. |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 39 | appName := parts[0] |
| 40 | if !util.ValidKeyAtom(appName) { |
| 41 | return nil, nil, wire.NewErrInvalidName(nil, suffix) |
| 42 | } |
| 43 | |
| 44 | aExists := false |
| 45 | a, err := disp.s.app(nil, nil, appName) |
| 46 | if err == nil { |
| 47 | aExists = true |
| 48 | } else { |
| 49 | if verror.ErrorID(err) != verror.ErrNoExistOrNoAccess.ID { |
| 50 | return nil, nil, err |
| 51 | } else { |
| 52 | a = &app{ |
| 53 | name: appName, |
| 54 | s: disp.s, |
| 55 | } |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 56 | } |
| 57 | } |
| 58 | |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 59 | if len(parts) == 1 { |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 60 | return wire.AppServer(a), nil, nil |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 61 | } |
| 62 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 63 | // All database, table, and row methods require the app to exist. If it |
| 64 | // doesn't, abort early. |
| 65 | if !aExists { |
| 66 | return nil, nil, verror.New(verror.ErrNoExistOrNoAccess, nil, a.name) |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 67 | } |
| 68 | |
Adam Sadovsky | f3b7abc | 2015-05-04 15:33:22 -0700 | [diff] [blame] | 69 | // Note, it's possible for the app to be deleted concurrently with downstream |
| 70 | // handling of this request. Depending on the order in which things execute, |
| 71 | // the client may not get an error, but in any case ultimately the store will |
| 72 | // end up in a consistent state. |
| 73 | return nosql.NewDispatcher(a).Lookup(parts[1]) |
Adam Sadovsky | b85e353 | 2015-04-08 20:38:27 -0700 | [diff] [blame] | 74 | } |