| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Measured methods for syncgroup management. |
| |
| package measure |
| |
| import ( |
| "fmt" |
| |
| "v.io/v23" |
| "v.io/v23/context" |
| "v.io/v23/security/access" |
| nosql_wire "v.io/v23/services/syncbase/nosql" |
| "v.io/v23/syncbase/nosql" |
| "v.io/v23/verror" |
| "v.io/x/sensorlog/internal/config" |
| "v.io/x/sensorlog/internal/sbmodel" |
| "v.io/x/sensorlog/internal/sbmodel/keyutil" |
| "v.io/x/sensorlog/internal/sbutil" |
| ) |
| |
| // InitSyncgroup creates the syncgroup for the measuring device devId, giving |
| // full configuration access to admin. The syncgroup uses sgPublishSb and |
| // sgMountTables for publishing (create/join) and syncing, respectively. |
| // InitSyncgroup must not be called concurrently for the same devId, or |
| // retried with different parameters for the same devId, otherwise behaviour |
| // is unspecified. |
| // TODO(ivanpi): Remove Resolve permissions when v.io/i/1110 is fixed. |
| func InitSyncgroup(ctx *context.T, db nosql.Database, devId, admin, sgPublishSb string, sgMountTables []string) error { |
| if err := keyutil.ValidateId(devId); err != nil { |
| return fmt.Errorf("invalid devId: %v", err) |
| } |
| |
| sgName := config.SyncgroupName(sgPublishSb, devId) |
| // Check for syncgroup. If it already exists, we have nothing to do. |
| if sgs, err := db.GetSyncgroupNames(ctx); err != nil { |
| return err |
| } else { |
| for _, sg := range sgs { |
| if sg == sgName { |
| return nil |
| } |
| } |
| } |
| |
| // Both measured and admin client have full permissions on the syncgroup. |
| sgAcl := access.Permissions{} |
| sbutil.AddPermsForPrincipal(&sgAcl, v23.GetPrincipal(ctx), access.Read, access.Admin) |
| sbutil.AddPermsForPattern(&sgAcl, admin, access.Read, access.Admin) |
| |
| // Maps all syncgroup prefixes to ACLs. |
| prefixSpec := make(map[nosql_wire.TableRow]access.Permissions) |
| |
| // StreamDef : <devId> |
| // Admin client has full permissions, measured drops to readonly. |
| prefixStreamDef := nosql_wire.TableRow{ |
| TableName: sbmodel.KStreamDef{}.Table(), |
| Row: devId, |
| } |
| aclStreamDef := access.Permissions{} |
| sbutil.AddPermsForPrincipal(&aclStreamDef, v23.GetPrincipal(ctx), access.Resolve, access.Read) |
| sbutil.AddPermsForPattern(&aclStreamDef, admin, access.Resolve, access.Read, access.Write, access.Admin) |
| prefixSpec[prefixStreamDef] = aclStreamDef |
| |
| // DataPoint : <devId> |
| // Admin client has full permissions, measured drops to read/write. |
| prefixDataPoint := nosql_wire.TableRow{ |
| TableName: sbmodel.KDataPoint{}.Table(), |
| Row: devId, |
| } |
| aclDataPoint := access.Permissions{} |
| sbutil.AddPermsForPrincipal(&aclDataPoint, v23.GetPrincipal(ctx), access.Resolve, access.Read, access.Write) |
| sbutil.AddPermsForPattern(&aclDataPoint, admin, access.Resolve, access.Read, access.Write, access.Admin) |
| prefixSpec[prefixDataPoint] = aclDataPoint |
| |
| var prefixes []nosql_wire.TableRow |
| // Apply prefix ACLs to all syncgroup prefixes. |
| for prefix, prefixAcl := range prefixSpec { |
| // Ignore ErrNoAccess, assume we already dropped permissions. |
| err := db.Table(prefix.TableName).SetPrefixPermissions(ctx, nosql.Prefix(prefix.Row), prefixAcl) |
| if err != nil && verror.ErrorID(err) != verror.ErrNoAccess.ID { |
| return err |
| } |
| prefixes = append(prefixes, prefix) |
| } |
| |
| sgSpec := nosql_wire.SyncgroupSpec{ |
| Description: fmt.Sprintf("measured-main-%s", devId), |
| Perms: sgAcl, |
| Prefixes: prefixes, |
| MountTables: sgMountTables, |
| } |
| sgMemberInfo := nosql_wire.SyncgroupMemberInfo{SyncPriority: config.SyncPriority} |
| |
| return db.Syncgroup(sgName).Create(ctx, sgSpec, sgMemberInfo) |
| } |