From 2f2658da9a27ea9697fedbca6e9e4a3c4bdf5067 Mon Sep 17 00:00:00 2001 From: ben-toogood Date: Wed, 20 Jan 2021 14:02:41 +0000 Subject: [PATCH] Groups Service (#40) --- groups/.gitignore | 2 + groups/Dockerfile | 3 + groups/Makefile | 22 + groups/README.md | 31 + groups/generate.go | 2 + groups/handler/handler.go | 209 ++++++ groups/handler/handler_test.go | 288 ++++++++ groups/main.go | 46 ++ groups/micro.mu | 1 + groups/proto/groups.pb.go | 1096 +++++++++++++++++++++++++++++++ groups/proto/groups.pb.micro.go | 209 ++++++ groups/proto/groups.proto | 81 +++ 12 files changed, 1990 insertions(+) create mode 100644 groups/.gitignore create mode 100644 groups/Dockerfile create mode 100644 groups/Makefile create mode 100644 groups/README.md create mode 100644 groups/generate.go create mode 100644 groups/handler/handler.go create mode 100644 groups/handler/handler_test.go create mode 100644 groups/main.go create mode 100644 groups/micro.mu create mode 100644 groups/proto/groups.pb.go create mode 100644 groups/proto/groups.pb.micro.go create mode 100644 groups/proto/groups.proto diff --git a/groups/.gitignore b/groups/.gitignore new file mode 100644 index 0000000..a2409d8 --- /dev/null +++ b/groups/.gitignore @@ -0,0 +1,2 @@ + +groups diff --git a/groups/Dockerfile b/groups/Dockerfile new file mode 100644 index 0000000..65aec26 --- /dev/null +++ b/groups/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine +ADD groups /groups +ENTRYPOINT [ "/groups" ] diff --git a/groups/Makefile b/groups/Makefile new file mode 100644 index 0000000..43d931e --- /dev/null +++ b/groups/Makefile @@ -0,0 +1,22 @@ + +GOPATH:=$(shell go env GOPATH) +.PHONY: init +init: + go get -u github.com/golang/protobuf/proto + go get -u github.com/golang/protobuf/protoc-gen-go + go get github.com/micro/micro/v3/cmd/protoc-gen-micro +.PHONY: proto +proto: + protoc --proto_path=. --micro_out=. --go_out=:. proto/groups.proto + +.PHONY: build +build: + go build -o groups *.go + +.PHONY: test +test: + go test -v ./... -cover + +.PHONY: docker +docker: + docker build . -t groups:latest diff --git a/groups/README.md b/groups/README.md new file mode 100644 index 0000000..ee43a0c --- /dev/null +++ b/groups/README.md @@ -0,0 +1,31 @@ +# Groups Service + +The group serivce is a basic CRUD service for groups. You can use it to create groups, add members and lookup which groups a user is a member of. + +Example usage: + +```bash +$ micro groups create --name=Micro +{ + "group": { + "id": "e35562c9-b6f6-459a-b52d-7e6159465fd6", + "name": "Micro" + } +} +$ micro groups addMember --group_id=e35562c9-b6f6-459a-b52d-7e6159465fd6 --member_id=Asim +{} +$ micro groups list --member_id=Asim +{ + "groups": [ + { + "id": "e35562c9-b6f6-459a-b52d-7e6159465fd6", + "name": "Micro", + "member_ids": [ + "Asim" + ] + } + ] +} +$ micro groups list --member_id=Boris +{} +``` diff --git a/groups/generate.go b/groups/generate.go new file mode 100644 index 0000000..96f431a --- /dev/null +++ b/groups/generate.go @@ -0,0 +1,2 @@ +package main +//go:generate make proto diff --git a/groups/handler/handler.go b/groups/handler/handler.go new file mode 100644 index 0000000..45da8ce --- /dev/null +++ b/groups/handler/handler.go @@ -0,0 +1,209 @@ +package handler + +import ( + "context" + "strings" + + "github.com/google/uuid" + "github.com/micro/micro/v3/service/errors" + pb "github.com/micro/services/groups/proto" + "gorm.io/gorm" +) + +var ( + ErrMissingName = errors.BadRequest("MISSING_NAME", "Missing name") + ErrMissingID = errors.BadRequest("MISSING_ID", "Missing ID") + ErrMissingIDs = errors.BadRequest("MISSING_IDS", "One or more IDs are required") + ErrMissingGroupID = errors.BadRequest("MISSING_GROUP_ID", "Missing Group ID") + ErrMissingMemberID = errors.BadRequest("MISSING_MEMBER_ID", "Missing Member ID") + ErrNotFound = errors.BadRequest("NOT_FOUND", "No group found with this ID") + ErrStore = errors.InternalServerError("STORE_ERROR", "Error connecting to the store") +) + +type Group struct { + ID string + Name string + Memberships []Membership +} + +type Membership struct { + MemberID string `gorm:"uniqueIndex:idx_membership"` + GroupID string `gorm:"uniqueIndex:idx_membership"` + Group Group +} + +func (g *Group) Serialize() *pb.Group { + memberIDs := make([]string, len(g.Memberships)) + for i, m := range g.Memberships { + memberIDs[i] = m.MemberID + } + return &pb.Group{Id: g.ID, Name: g.Name, MemberIds: memberIDs} +} + +type Groups struct { + DB *gorm.DB +} + +func (g *Groups) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { + // validate the request + if len(req.Name) == 0 { + return ErrMissingName + } + + // create the group object + group := &Group{ID: uuid.New().String(), Name: req.Name} + if err := g.DB.Create(group).Error; err != nil { + return ErrStore + } + + // return the group + rsp.Group = group.Serialize() + return nil +} + +func (g *Groups) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { + // validate the request + if len(req.Ids) == 0 { + return ErrMissingIDs + } + + // query the database + var groups []Group + if err := g.DB.Model(&Group{}).Preload("Memberships").Where("id IN (?)", req.Ids).Find(&groups).Error; err != nil { + return ErrStore + } + + // serialize the response + rsp.Groups = make(map[string]*pb.Group, len(groups)) + for _, g := range groups { + rsp.Groups[g.ID] = g.Serialize() + } + + return nil +} + +func (g *Groups) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { + // validate the request + if len(req.Id) == 0 { + return ErrMissingID + } + if len(req.Name) == 0 { + return ErrMissingName + } + + return g.DB.Transaction(func(tx *gorm.DB) error { + // find the group + var group Group + if err := tx.Where(&Group{ID: req.Id}).First(&group).Error; err == gorm.ErrRecordNotFound { + return ErrNotFound + } else if err != nil { + return ErrStore + } + + // update the group + group.Name = req.Name + if err := tx.Save(&group).Error; err != nil { + return ErrStore + } + + // serialize the response + rsp.Group = group.Serialize() + return nil + }) +} + +func (g *Groups) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { + // validate the request + if len(req.Id) == 0 { + return ErrMissingID + } + + // delete from the database + if err := g.DB.Delete(&Group{ID: req.Id}).Error; err == gorm.ErrRecordNotFound { + return nil + } else if err != nil { + return ErrStore + } + + return nil +} + +func (g *Groups) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error { + if len(req.MemberId) > 0 { + // only list groups the user is a member of + var ms []Membership + q := g.DB.Where(&Membership{MemberID: req.MemberId}).Preload("Group.Memberships") + if err := q.Find(&ms).Error; err != nil { + return err + } + rsp.Groups = make([]*pb.Group, len(ms)) + for i, m := range ms { + rsp.Groups[i] = m.Group.Serialize() + } + return nil + } + + // load all groups + var groups []Group + if err := g.DB.Model(&Group{}).Preload("Memberships").Find(&groups).Error; err != nil { + return ErrStore + } + + // serialize the response + rsp.Groups = make([]*pb.Group, len(groups)) + for i, g := range groups { + rsp.Groups[i] = g.Serialize() + } + + return nil +} + +func (g *Groups) AddMember(ctx context.Context, req *pb.AddMemberRequest, rsp *pb.AddMemberResponse) error { + // validate the request + if len(req.GroupId) == 0 { + return ErrMissingGroupID + } + if len(req.MemberId) == 0 { + return ErrMissingMemberID + } + + return g.DB.Transaction(func(tx *gorm.DB) error { + // check the group exists + var group Group + if err := tx.Where(&Group{ID: req.GroupId}).First(&group).Error; err == gorm.ErrRecordNotFound { + return ErrNotFound + } else if err != nil { + return err + } + + // create the membership + m := &Membership{MemberID: req.MemberId, GroupID: req.GroupId} + err := tx.Create(m).Error + // check for membership already existing (unique index violation) + if err != nil && strings.Contains(err.Error(), "fk_groups_memberships") { + return nil + } else if err != nil { + return ErrStore + } + + return nil + }) +} + +func (g *Groups) RemoveMember(ctx context.Context, req *pb.RemoveMemberRequest, rsp *pb.RemoveMemberResponse) error { + // validate the request + if len(req.GroupId) == 0 { + return ErrMissingGroupID + } + if len(req.MemberId) == 0 { + return ErrMissingMemberID + } + + // delete the membership + m := &Membership{MemberID: req.MemberId, GroupID: req.GroupId} + if err := g.DB.Where(m).Delete(m).Error; err != nil { + return ErrStore + } + + return nil +} diff --git a/groups/handler/handler_test.go b/groups/handler/handler_test.go new file mode 100644 index 0000000..fe8409f --- /dev/null +++ b/groups/handler/handler_test.go @@ -0,0 +1,288 @@ +package handler_test + +import ( + "context" + "sort" + "testing" + + "github.com/google/uuid" + "github.com/micro/services/groups/handler" + pb "github.com/micro/services/groups/proto" + "github.com/stretchr/testify/assert" + "gorm.io/driver/postgres" + "gorm.io/gorm" +) + +func testHandler(t *testing.T) *handler.Groups { + // connect to the database + db, err := gorm.Open(postgres.Open("postgresql://postgres@localhost:5432/groups?sslmode=disable"), &gorm.Config{}) + if err != nil { + t.Fatalf("Error connecting to database: %v", err) + } + + // migrate the database + if err := db.AutoMigrate(&handler.Group{}, &handler.Membership{}); err != nil { + t.Fatalf("Error migrating database: %v", err) + } + + // clean any data from a previous run + if err := db.Exec("TRUNCATE TABLE groups CASCADE").Error; err != nil { + t.Fatalf("Error cleaning database: %v", err) + } + + return &handler.Groups{DB: db} +} +func TestCreate(t *testing.T) { + h := testHandler(t) + + t.Run("MissingName", func(t *testing.T) { + err := h.Create(context.TODO(), &pb.CreateRequest{}, &pb.CreateResponse{}) + assert.Equal(t, handler.ErrMissingName, err) + }) + + t.Run("Valid", func(t *testing.T) { + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Doe Family Group", + }, &pb.CreateResponse{}) + assert.NoError(t, err) + }) +} + +func TestUpdate(t *testing.T) { + h := testHandler(t) + + t.Run("MissingID", func(t *testing.T) { + err := h.Update(context.TODO(), &pb.UpdateRequest{ + Name: "Doe Family Group", + }, &pb.UpdateResponse{}) + assert.Equal(t, handler.ErrMissingID, err) + }) + + t.Run("MissingName", func(t *testing.T) { + err := h.Update(context.TODO(), &pb.UpdateRequest{ + Id: uuid.New().String(), + }, &pb.UpdateResponse{}) + assert.Equal(t, handler.ErrMissingName, err) + }) + + t.Run("NotFound", func(t *testing.T) { + err := h.Update(context.TODO(), &pb.UpdateRequest{ + Id: uuid.New().String(), + Name: "Bar Family Group", + }, &pb.UpdateResponse{}) + assert.Equal(t, handler.ErrNotFound, err) + }) + + t.Run("Valid", func(t *testing.T) { + // create a demo group + var cRsp pb.CreateResponse + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Doe Family Group", + }, &cRsp) + assert.NoError(t, err) + + err = h.Update(context.TODO(), &pb.UpdateRequest{ + Id: cRsp.Group.Id, + Name: "Bar Family Group", + }, &pb.UpdateResponse{}) + assert.NoError(t, err) + + var rRsp pb.ReadResponse + err = h.Read(context.TODO(), &pb.ReadRequest{ + Ids: []string{cRsp.Group.Id}, + }, &rRsp) + assert.NoError(t, err) + + g := rRsp.Groups[cRsp.Group.Id] + if g == nil { + t.Errorf("Group not returned") + } else { + assert.Equal(t, "Bar Family Group", g.Name) + } + }) +} + +func TestDelete(t *testing.T) { + h := testHandler(t) + + t.Run("MissingID", func(t *testing.T) { + err := h.Delete(context.TODO(), &pb.DeleteRequest{}, &pb.DeleteResponse{}) + assert.Equal(t, handler.ErrMissingID, err) + }) + + t.Run("NotFound", func(t *testing.T) { + err := h.Delete(context.TODO(), &pb.DeleteRequest{ + Id: uuid.New().String(), + }, &pb.DeleteResponse{}) + assert.NoError(t, err) + }) + + // create a demo group + var cRsp pb.CreateResponse + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Doe Family Group", + }, &cRsp) + assert.NoError(t, err) + + t.Run("Valid", func(t *testing.T) { + err := h.Delete(context.TODO(), &pb.DeleteRequest{ + Id: cRsp.Group.Id, + }, &pb.DeleteResponse{}) + assert.NoError(t, err) + + var rRsp pb.ReadResponse + err = h.Read(context.TODO(), &pb.ReadRequest{ + Ids: []string{cRsp.Group.Id}, + }, &rRsp) + assert.Nil(t, rRsp.Groups[cRsp.Group.Id]) + }) +} +func TestList(t *testing.T) { + h := testHandler(t) + + // create two demo groups + var cRsp1 pb.CreateResponse + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Alpha Group", + }, &cRsp1) + assert.NoError(t, err) + + var cRsp2 pb.CreateResponse + err = h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Bravo Group", + }, &cRsp2) + assert.NoError(t, err) + + // add a member to the first group + uid := uuid.New().String() + err = h.AddMember(context.TODO(), &pb.AddMemberRequest{ + GroupId: cRsp1.Group.Id, MemberId: uid, + }, &pb.AddMemberResponse{}) + assert.NoError(t, err) + + t.Run("Unscoped", func(t *testing.T) { + var rsp pb.ListResponse + err = h.List(context.TODO(), &pb.ListRequest{}, &rsp) + assert.NoError(t, err) + assert.Lenf(t, rsp.Groups, 2, "Two groups should be returned") + if len(rsp.Groups) != 2 { + return + } + + sort.Slice(rsp.Groups, func(i, j int) bool { + return rsp.Groups[i].Name < rsp.Groups[j].Name + }) + assert.Equal(t, cRsp1.Group.Id, rsp.Groups[0].Id) + assert.Equal(t, cRsp1.Group.Name, rsp.Groups[0].Name) + assert.Len(t, rsp.Groups[0].MemberIds, 1) + assert.Contains(t, rsp.Groups[0].MemberIds, uid) + assert.Equal(t, cRsp2.Group.Id, rsp.Groups[1].Id) + assert.Equal(t, cRsp2.Group.Name, rsp.Groups[1].Name) + assert.Len(t, rsp.Groups[1].MemberIds, 0) + }) + + t.Run("Scoped", func(t *testing.T) { + var rsp pb.ListResponse + err = h.List(context.TODO(), &pb.ListRequest{MemberId: uid}, &rsp) + assert.NoError(t, err) + assert.Lenf(t, rsp.Groups, 1, "One group should be returned") + if len(rsp.Groups) != 1 { + return + } + + assert.Equal(t, cRsp1.Group.Id, rsp.Groups[0].Id) + assert.Equal(t, cRsp1.Group.Name, rsp.Groups[0].Name) + assert.Len(t, rsp.Groups[0].MemberIds, 1) + assert.Contains(t, rsp.Groups[0].MemberIds, uid) + }) +} + +func TestAddMember(t *testing.T) { + h := testHandler(t) + + t.Run("MissingGroupID", func(t *testing.T) { + err := h.AddMember(context.TODO(), &pb.AddMemberRequest{ + MemberId: uuid.New().String(), + }, &pb.AddMemberResponse{}) + assert.Equal(t, handler.ErrMissingGroupID, err) + }) + + t.Run("MissingMemberID", func(t *testing.T) { + err := h.AddMember(context.TODO(), &pb.AddMemberRequest{ + GroupId: uuid.New().String(), + }, &pb.AddMemberResponse{}) + assert.Equal(t, handler.ErrMissingMemberID, err) + }) + + t.Run("GroupNotFound", func(t *testing.T) { + err := h.AddMember(context.TODO(), &pb.AddMemberRequest{ + GroupId: uuid.New().String(), + MemberId: uuid.New().String(), + }, &pb.AddMemberResponse{}) + assert.Equal(t, handler.ErrNotFound, err) + }) + + // create a test group + var cRsp pb.CreateResponse + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Alpha Group", + }, &cRsp) + assert.NoError(t, err) + + t.Run("Valid", func(t *testing.T) { + err := h.AddMember(context.TODO(), &pb.AddMemberRequest{ + GroupId: cRsp.Group.Id, + MemberId: uuid.New().String(), + }, &pb.AddMemberResponse{}) + assert.NoError(t, err) + }) + + t.Run("Retry", func(t *testing.T) { + err := h.AddMember(context.TODO(), &pb.AddMemberRequest{ + GroupId: cRsp.Group.Id, + MemberId: uuid.New().String(), + }, &pb.AddMemberResponse{}) + assert.NoError(t, err) + }) +} + +func TestRemoveMember(t *testing.T) { + h := testHandler(t) + + t.Run("MissingGroupID", func(t *testing.T) { + err := h.RemoveMember(context.TODO(), &pb.RemoveMemberRequest{ + MemberId: uuid.New().String(), + }, &pb.RemoveMemberResponse{}) + assert.Equal(t, handler.ErrMissingGroupID, err) + }) + + t.Run("MissingMemberID", func(t *testing.T) { + err := h.RemoveMember(context.TODO(), &pb.RemoveMemberRequest{ + GroupId: uuid.New().String(), + }, &pb.RemoveMemberResponse{}) + assert.Equal(t, handler.ErrMissingMemberID, err) + }) + + // create a test group + var cRsp pb.CreateResponse + err := h.Create(context.TODO(), &pb.CreateRequest{ + Name: "Alpha Group", + }, &cRsp) + assert.NoError(t, err) + + t.Run("Valid", func(t *testing.T) { + err := h.RemoveMember(context.TODO(), &pb.RemoveMemberRequest{ + GroupId: cRsp.Group.Id, + MemberId: uuid.New().String(), + }, &pb.RemoveMemberResponse{}) + assert.NoError(t, err) + }) + + t.Run("Retry", func(t *testing.T) { + err := h.RemoveMember(context.TODO(), &pb.RemoveMemberRequest{ + GroupId: cRsp.Group.Id, + MemberId: uuid.New().String(), + }, &pb.RemoveMemberResponse{}) + assert.NoError(t, err) + }) +} diff --git a/groups/main.go b/groups/main.go new file mode 100644 index 0000000..a4cbd28 --- /dev/null +++ b/groups/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "github.com/micro/services/groups/handler" + pb "github.com/micro/services/groups/proto" + "gorm.io/driver/postgres" + "gorm.io/gorm" + + "github.com/micro/micro/v3/service" + "github.com/micro/micro/v3/service/config" + "github.com/micro/micro/v3/service/logger" +) + +var dbAddress = "postgresql://postgres@localhost:5432/groups?sslmode=disable" + +func main() { + // Create service + srv := service.New( + service.Name("groups"), + service.Version("latest"), + ) + + // Connect to the database + cfg, err := config.Get("groups.database") + if err != nil { + logger.Fatalf("Error loading config: %v", err) + } + addr := cfg.String(dbAddress) + db, err := gorm.Open(postgres.Open(addr), &gorm.Config{}) + if err != nil { + logger.Fatalf("Error connecting to database: %v", err) + } + + // Migrate the database + if err := db.AutoMigrate(&handler.Group{}, &handler.Membership{}); err != nil { + logger.Fatalf("Error migrating database: %v", err) + } + + // Register handler + pb.RegisterGroupsHandler(srv.Server(), &handler.Groups{DB: db}) + + // Run service + if err := srv.Run(); err != nil { + logger.Fatal(err) + } +} diff --git a/groups/micro.mu b/groups/micro.mu new file mode 100644 index 0000000..157cef6 --- /dev/null +++ b/groups/micro.mu @@ -0,0 +1 @@ +service groups diff --git a/groups/proto/groups.pb.go b/groups/proto/groups.pb.go new file mode 100644 index 0000000..d7844b1 --- /dev/null +++ b/groups/proto/groups.pb.go @@ -0,0 +1,1096 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.23.0 +// protoc v3.13.0 +// source: proto/groups.proto + +package groups + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type Group struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + MemberIds []string `protobuf:"bytes,3,rep,name=member_ids,json=memberIds,proto3" json:"member_ids,omitempty"` +} + +func (x *Group) Reset() { + *x = Group{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Group) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Group) ProtoMessage() {} + +func (x *Group) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Group.ProtoReflect.Descriptor instead. +func (*Group) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{0} +} + +func (x *Group) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Group) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Group) GetMemberIds() []string { + if x != nil { + return x.MemberIds + } + return nil +} + +type CreateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *CreateRequest) Reset() { + *x = CreateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRequest) ProtoMessage() {} + +func (x *CreateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRequest.ProtoReflect.Descriptor instead. +func (*CreateRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type CreateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Group *Group `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` +} + +func (x *CreateResponse) Reset() { + *x = CreateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateResponse) ProtoMessage() {} + +func (x *CreateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateResponse.ProtoReflect.Descriptor instead. +func (*CreateResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateResponse) GetGroup() *Group { + if x != nil { + return x.Group + } + return nil +} + +type ReadRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` +} + +func (x *ReadRequest) Reset() { + *x = ReadRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadRequest) ProtoMessage() {} + +func (x *ReadRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReadRequest.ProtoReflect.Descriptor instead. +func (*ReadRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{3} +} + +func (x *ReadRequest) GetIds() []string { + if x != nil { + return x.Ids + } + return nil +} + +type ReadResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Groups map[string]*Group `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ReadResponse) Reset() { + *x = ReadResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadResponse) ProtoMessage() {} + +func (x *ReadResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReadResponse.ProtoReflect.Descriptor instead. +func (*ReadResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{4} +} + +func (x *ReadResponse) GetGroups() map[string]*Group { + if x != nil { + return x.Groups + } + return nil +} + +type UpdateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *UpdateRequest) Reset() { + *x = UpdateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRequest) ProtoMessage() {} + +func (x *UpdateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateRequest.ProtoReflect.Descriptor instead. +func (*UpdateRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{5} +} + +func (x *UpdateRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UpdateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Group *Group `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` +} + +func (x *UpdateResponse) Reset() { + *x = UpdateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateResponse) ProtoMessage() {} + +func (x *UpdateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateResponse.ProtoReflect.Descriptor instead. +func (*UpdateResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{6} +} + +func (x *UpdateResponse) GetGroup() *Group { + if x != nil { + return x.Group + } + return nil +} + +type DeleteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *DeleteRequest) Reset() { + *x = DeleteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest) ProtoMessage() {} + +func (x *DeleteRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead. +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{7} +} + +func (x *DeleteRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type DeleteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeleteResponse) Reset() { + *x = DeleteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse) ProtoMessage() {} + +func (x *DeleteResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead. +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{8} +} + +type ListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // passing a member id will restrict the groups to that which the member is part of + MemberId string `protobuf:"bytes,1,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"` +} + +func (x *ListRequest) Reset() { + *x = ListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest) ProtoMessage() {} + +func (x *ListRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead. +func (*ListRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{9} +} + +func (x *ListRequest) GetMemberId() string { + if x != nil { + return x.MemberId + } + return "" +} + +type ListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Groups []*Group `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` +} + +func (x *ListResponse) Reset() { + *x = ListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse) ProtoMessage() {} + +func (x *ListResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead. +func (*ListResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{10} +} + +func (x *ListResponse) GetGroups() []*Group { + if x != nil { + return x.Groups + } + return nil +} + +type AddMemberRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GroupId string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + MemberId string `protobuf:"bytes,2,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"` +} + +func (x *AddMemberRequest) Reset() { + *x = AddMemberRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddMemberRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMemberRequest) ProtoMessage() {} + +func (x *AddMemberRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddMemberRequest.ProtoReflect.Descriptor instead. +func (*AddMemberRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{11} +} + +func (x *AddMemberRequest) GetGroupId() string { + if x != nil { + return x.GroupId + } + return "" +} + +func (x *AddMemberRequest) GetMemberId() string { + if x != nil { + return x.MemberId + } + return "" +} + +type AddMemberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AddMemberResponse) Reset() { + *x = AddMemberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddMemberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddMemberResponse) ProtoMessage() {} + +func (x *AddMemberResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddMemberResponse.ProtoReflect.Descriptor instead. +func (*AddMemberResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{12} +} + +type RemoveMemberRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GroupId string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + MemberId string `protobuf:"bytes,2,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"` +} + +func (x *RemoveMemberRequest) Reset() { + *x = RemoveMemberRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveMemberRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveMemberRequest) ProtoMessage() {} + +func (x *RemoveMemberRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveMemberRequest.ProtoReflect.Descriptor instead. +func (*RemoveMemberRequest) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{13} +} + +func (x *RemoveMemberRequest) GetGroupId() string { + if x != nil { + return x.GroupId + } + return "" +} + +func (x *RemoveMemberRequest) GetMemberId() string { + if x != nil { + return x.MemberId + } + return "" +} + +type RemoveMemberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RemoveMemberResponse) Reset() { + *x = RemoveMemberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_groups_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveMemberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveMemberResponse) ProtoMessage() {} + +func (x *RemoveMemberResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_groups_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveMemberResponse.ProtoReflect.Descriptor instead. +func (*RemoveMemberResponse) Descriptor() ([]byte, []int) { + return file_proto_groups_proto_rawDescGZIP(), []int{14} +} + +var File_proto_groups_proto protoreflect.FileDescriptor + +var file_proto_groups_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x4a, 0x0a, 0x05, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x23, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x35, 0x0a, + 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0x1f, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, + 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x1a, 0x48, 0x0a, 0x0b, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x33, 0x0a, 0x0d, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x35, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x23, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x49, 0x64, 0x22, 0x35, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x4a, 0x0a, 0x10, + 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, 0x0a, + 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x22, 0x16, 0x0a, 0x14, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa6, 0x03, 0x0a, 0x06, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, + 0x37, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, + 0x12, 0x13, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x52, + 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x15, + 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, + 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x40, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x2e, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0e, 0x5a, + 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_groups_proto_rawDescOnce sync.Once + file_proto_groups_proto_rawDescData = file_proto_groups_proto_rawDesc +) + +func file_proto_groups_proto_rawDescGZIP() []byte { + file_proto_groups_proto_rawDescOnce.Do(func() { + file_proto_groups_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_groups_proto_rawDescData) + }) + return file_proto_groups_proto_rawDescData +} + +var file_proto_groups_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_proto_groups_proto_goTypes = []interface{}{ + (*Group)(nil), // 0: groups.Group + (*CreateRequest)(nil), // 1: groups.CreateRequest + (*CreateResponse)(nil), // 2: groups.CreateResponse + (*ReadRequest)(nil), // 3: groups.ReadRequest + (*ReadResponse)(nil), // 4: groups.ReadResponse + (*UpdateRequest)(nil), // 5: groups.UpdateRequest + (*UpdateResponse)(nil), // 6: groups.UpdateResponse + (*DeleteRequest)(nil), // 7: groups.DeleteRequest + (*DeleteResponse)(nil), // 8: groups.DeleteResponse + (*ListRequest)(nil), // 9: groups.ListRequest + (*ListResponse)(nil), // 10: groups.ListResponse + (*AddMemberRequest)(nil), // 11: groups.AddMemberRequest + (*AddMemberResponse)(nil), // 12: groups.AddMemberResponse + (*RemoveMemberRequest)(nil), // 13: groups.RemoveMemberRequest + (*RemoveMemberResponse)(nil), // 14: groups.RemoveMemberResponse + nil, // 15: groups.ReadResponse.GroupsEntry +} +var file_proto_groups_proto_depIdxs = []int32{ + 0, // 0: groups.CreateResponse.group:type_name -> groups.Group + 15, // 1: groups.ReadResponse.groups:type_name -> groups.ReadResponse.GroupsEntry + 0, // 2: groups.UpdateResponse.group:type_name -> groups.Group + 0, // 3: groups.ListResponse.groups:type_name -> groups.Group + 0, // 4: groups.ReadResponse.GroupsEntry.value:type_name -> groups.Group + 1, // 5: groups.Groups.Create:input_type -> groups.CreateRequest + 3, // 6: groups.Groups.Read:input_type -> groups.ReadRequest + 5, // 7: groups.Groups.Update:input_type -> groups.UpdateRequest + 7, // 8: groups.Groups.Delete:input_type -> groups.DeleteRequest + 9, // 9: groups.Groups.List:input_type -> groups.ListRequest + 11, // 10: groups.Groups.AddMember:input_type -> groups.AddMemberRequest + 13, // 11: groups.Groups.RemoveMember:input_type -> groups.RemoveMemberRequest + 2, // 12: groups.Groups.Create:output_type -> groups.CreateResponse + 4, // 13: groups.Groups.Read:output_type -> groups.ReadResponse + 6, // 14: groups.Groups.Update:output_type -> groups.UpdateResponse + 8, // 15: groups.Groups.Delete:output_type -> groups.DeleteResponse + 10, // 16: groups.Groups.List:output_type -> groups.ListResponse + 12, // 17: groups.Groups.AddMember:output_type -> groups.AddMemberResponse + 14, // 18: groups.Groups.RemoveMember:output_type -> groups.RemoveMemberResponse + 12, // [12:19] is the sub-list for method output_type + 5, // [5:12] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_proto_groups_proto_init() } +func file_proto_groups_proto_init() { + if File_proto_groups_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_groups_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Group); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReadRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReadResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddMemberRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddMemberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveMemberRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_groups_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveMemberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_groups_proto_rawDesc, + NumEnums: 0, + NumMessages: 16, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_groups_proto_goTypes, + DependencyIndexes: file_proto_groups_proto_depIdxs, + MessageInfos: file_proto_groups_proto_msgTypes, + }.Build() + File_proto_groups_proto = out.File + file_proto_groups_proto_rawDesc = nil + file_proto_groups_proto_goTypes = nil + file_proto_groups_proto_depIdxs = nil +} diff --git a/groups/proto/groups.pb.micro.go b/groups/proto/groups.pb.micro.go new file mode 100644 index 0000000..23f6157 --- /dev/null +++ b/groups/proto/groups.pb.micro.go @@ -0,0 +1,209 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: proto/groups.proto + +package groups + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + api "github.com/micro/micro/v3/service/api" + client "github.com/micro/micro/v3/service/client" + server "github.com/micro/micro/v3/service/server" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ api.Endpoint +var _ context.Context +var _ client.Option +var _ server.Option + +// Api Endpoints for Groups service + +func NewGroupsEndpoints() []*api.Endpoint { + return []*api.Endpoint{} +} + +// Client API for Groups service + +type GroupsService interface { + // Create a group + Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) + // Read a group using ID + Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) + // Update a groups name + Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) + // Delete a group + Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) + // List all groups + List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) + // AddMember to a group + AddMember(ctx context.Context, in *AddMemberRequest, opts ...client.CallOption) (*AddMemberResponse, error) + // RemoveMember from a group + RemoveMember(ctx context.Context, in *RemoveMemberRequest, opts ...client.CallOption) (*RemoveMemberResponse, error) +} + +type groupsService struct { + c client.Client + name string +} + +func NewGroupsService(name string, c client.Client) GroupsService { + return &groupsService{ + c: c, + name: name, + } +} + +func (c *groupsService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) { + req := c.c.NewRequest(c.name, "Groups.Create", in) + out := new(CreateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) { + req := c.c.NewRequest(c.name, "Groups.Read", in) + out := new(ReadResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) { + req := c.c.NewRequest(c.name, "Groups.Update", in) + out := new(UpdateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) { + req := c.c.NewRequest(c.name, "Groups.Delete", in) + out := new(DeleteResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) { + req := c.c.NewRequest(c.name, "Groups.List", in) + out := new(ListResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) AddMember(ctx context.Context, in *AddMemberRequest, opts ...client.CallOption) (*AddMemberResponse, error) { + req := c.c.NewRequest(c.name, "Groups.AddMember", in) + out := new(AddMemberResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *groupsService) RemoveMember(ctx context.Context, in *RemoveMemberRequest, opts ...client.CallOption) (*RemoveMemberResponse, error) { + req := c.c.NewRequest(c.name, "Groups.RemoveMember", in) + out := new(RemoveMemberResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Groups service + +type GroupsHandler interface { + // Create a group + Create(context.Context, *CreateRequest, *CreateResponse) error + // Read a group using ID + Read(context.Context, *ReadRequest, *ReadResponse) error + // Update a groups name + Update(context.Context, *UpdateRequest, *UpdateResponse) error + // Delete a group + Delete(context.Context, *DeleteRequest, *DeleteResponse) error + // List all groups + List(context.Context, *ListRequest, *ListResponse) error + // AddMember to a group + AddMember(context.Context, *AddMemberRequest, *AddMemberResponse) error + // RemoveMember from a group + RemoveMember(context.Context, *RemoveMemberRequest, *RemoveMemberResponse) error +} + +func RegisterGroupsHandler(s server.Server, hdlr GroupsHandler, opts ...server.HandlerOption) error { + type groups interface { + Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error + Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error + Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error + Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error + List(ctx context.Context, in *ListRequest, out *ListResponse) error + AddMember(ctx context.Context, in *AddMemberRequest, out *AddMemberResponse) error + RemoveMember(ctx context.Context, in *RemoveMemberRequest, out *RemoveMemberResponse) error + } + type Groups struct { + groups + } + h := &groupsHandler{hdlr} + return s.Handle(s.NewHandler(&Groups{h}, opts...)) +} + +type groupsHandler struct { + GroupsHandler +} + +func (h *groupsHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error { + return h.GroupsHandler.Create(ctx, in, out) +} + +func (h *groupsHandler) Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error { + return h.GroupsHandler.Read(ctx, in, out) +} + +func (h *groupsHandler) Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error { + return h.GroupsHandler.Update(ctx, in, out) +} + +func (h *groupsHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { + return h.GroupsHandler.Delete(ctx, in, out) +} + +func (h *groupsHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error { + return h.GroupsHandler.List(ctx, in, out) +} + +func (h *groupsHandler) AddMember(ctx context.Context, in *AddMemberRequest, out *AddMemberResponse) error { + return h.GroupsHandler.AddMember(ctx, in, out) +} + +func (h *groupsHandler) RemoveMember(ctx context.Context, in *RemoveMemberRequest, out *RemoveMemberResponse) error { + return h.GroupsHandler.RemoveMember(ctx, in, out) +} diff --git a/groups/proto/groups.proto b/groups/proto/groups.proto new file mode 100644 index 0000000..0790e93 --- /dev/null +++ b/groups/proto/groups.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; + +package groups; +option go_package = "proto;groups"; + +service Groups { + // Create a group + rpc Create(CreateRequest) returns (CreateResponse); + // Read a group using ID + rpc Read(ReadRequest) returns (ReadResponse); + // Update a groups name + rpc Update(UpdateRequest) returns (UpdateResponse); + // Delete a group + rpc Delete(DeleteRequest) returns (DeleteResponse); + // List all groups + rpc List(ListRequest) returns (ListResponse); + // AddMember to a group + rpc AddMember(AddMemberRequest) returns (AddMemberResponse); + // RemoveMember from a group + rpc RemoveMember(RemoveMemberRequest) returns (RemoveMemberResponse); +} + +message Group { + string id = 1; + string name = 2; + repeated string member_ids = 3; +} + +message CreateRequest { + string name = 1; +} + +message CreateResponse { + Group group = 1; +} + +message ReadRequest { + repeated string ids = 1; +} + +message ReadResponse { + map groups = 1; +} + +message UpdateRequest { + string id = 1; + string name = 2; +} + +message UpdateResponse { + Group group = 1; +} + +message DeleteRequest { + string id = 1; +} + +message DeleteResponse {} + +message ListRequest { + // passing a member id will restrict the groups to that which the member is part of + string member_id = 1; +} + +message ListResponse { + repeated Group groups = 1; +} + +message AddMemberRequest { + string group_id = 1; + string member_id = 2; +} + +message AddMemberResponse {} + +message RemoveMemberRequest { + string group_id = 1; + string member_id = 2; +} + +message RemoveMemberResponse {} \ No newline at end of file