1package mobile_service
2
3import (
4	"context"
5	"encoding/json"
6	"fmt"
7	"github.com/couchbase/cbauth/metakv"
8	"github.com/couchbase/cbauth/service"
9	"github.com/couchbase/mobile-service/mobile_service_grpc"
10	"path"
11)
12
13// Implements the MobileServiceAdmin grpc service defined in mobile_service_admin.proto
14type mobileServiceAdmin struct {
15
16	// The node UUID for this mobile service node.  Provided by ns-server during startup
17	NodeUuid service.NodeID
18}
19
20func NewMobileServiceAdmin(nodeUuid service.NodeID) *mobileServiceAdmin {
21
22	s := mobileServiceAdmin{
23		NodeUuid: nodeUuid,
24	}
25
26	return &s
27}
28
29func (self *mobileServiceAdmin) ListSyncGateways(context.Context, *mobile_service_grpc.Empty) (*mobile_service_grpc.SyncGateways, error) {
30
31	uniqueGateways := map[string]*mobile_service_grpc.SyncGateway{}
32
33	knownSyncGateways, err := metakv.ListAllChildren(AddTrailingSlash(KeyMobileState))
34	if err != nil {
35		return nil, err
36	}
37
38	for _, knownSyncGateway := range knownSyncGateways {
39
40		syncGateway := &mobile_service_grpc.SyncGateway{}
41		syncGateway.SyncGatewayUUID = path.Base(knownSyncGateway.Path)
42		syncGateway.LastSeenTimestamp = string(knownSyncGateway.Value)
43		uniqueGateways[syncGateway.SyncGatewayUUID] = syncGateway
44
45	}
46
47	gatewayList := []*mobile_service_grpc.SyncGateway{}
48	for _, uniqueGateway := range uniqueGateways {
49		gatewayList = append(gatewayList, uniqueGateway)
50	}
51	gateways := &mobile_service_grpc.SyncGateways{}
52	gateways.Items = gatewayList
53
54	return gateways, nil
55
56}
57
58func (self *mobileServiceAdmin) ImportConfig(ctx context.Context, config *mobile_service_grpc.ConfigJson) (empty *mobile_service_grpc.Empty, err error) {
59
60	configImportExport := ConfigImportExport{}
61
62	if err := json.Unmarshal([]byte(config.Body), &configImportExport); err != nil {
63		return &mobile_service_grpc.Empty{}, err
64	}
65
66	// Set general config
67	if err := metakv.Set(KeyMobileGatewayGeneral, configImportExport.General, nil); err != nil {
68		return &mobile_service_grpc.Empty{}, err
69	}
70
71	// Set listener config
72	if err := metakv.Set(KeyMobileGatewayListener, configImportExport.Listener, nil); err != nil {
73		return &mobile_service_grpc.Empty{}, err
74	}
75
76	// Set databases config
77	for dbName, dbVal := range configImportExport.Databases {
78		metakvPath := fmt.Sprintf("%s/%s", KeyMobileGatewayDatabases, dbName)
79		if err := metakv.Set(metakvPath, dbVal, nil); err != nil {
80			return &mobile_service_grpc.Empty{}, err
81		}
82	}
83
84	return &mobile_service_grpc.Empty{}, nil
85
86}
87
88func (self *mobileServiceAdmin) ExportConfig(ctx context.Context, empty *mobile_service_grpc.Empty) (config *mobile_service_grpc.ConfigJson, err error) {
89
90	config = &mobile_service_grpc.ConfigJson{}
91
92	configImportExport := ConfigImportExport{}
93	configImportExport.Databases = map[string]json.RawMessage{}
94
95	var val []byte
96
97	val, _, err = metakv.Get(KeyMobileGatewayGeneral)
98	if err != nil {
99		return config, err
100	}
101	configImportExport.General = val
102
103	val, _, err = metakv.Get(KeyMobileGatewayListener)
104	if err != nil {
105		return config, err
106	}
107	configImportExport.Listener = val
108
109	// List all the chidren of the metakvDatabases key
110	kvEntriesDbs, err := metakv.ListAllChildren(AddTrailingSlash(KeyMobileGatewayDatabases))
111	if err != nil {
112		return config, err
113	}
114
115	// Loop over entries and add to configImportExport
116	for _, dbKvEntry := range kvEntriesDbs {
117		configImportExport.Databases[path.Base(dbKvEntry.Path)] = dbKvEntry.Value
118	}
119
120	marshalled, err := json.Marshal(configImportExport)
121	if err != nil {
122		return config, err
123	}
124
125	config.Body = string(marshalled)
126
127	return config, nil
128}
129