mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
Delete data part 1 (#360)
This commit is contained in:
29
cache/handler/cache.go
vendored
29
cache/handler/cache.go
vendored
@@ -9,7 +9,10 @@ import (
|
|||||||
"github.com/micro/micro/v3/service/errors"
|
"github.com/micro/micro/v3/service/errors"
|
||||||
log "github.com/micro/micro/v3/service/logger"
|
log "github.com/micro/micro/v3/service/logger"
|
||||||
pb "github.com/micro/services/cache/proto"
|
pb "github.com/micro/services/cache/proto"
|
||||||
|
pauth "github.com/micro/services/pkg/auth"
|
||||||
"github.com/micro/services/pkg/cache"
|
"github.com/micro/services/pkg/cache"
|
||||||
|
adminpb "github.com/micro/services/pkg/service/proto"
|
||||||
|
"github.com/micro/services/pkg/tenant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cache struct{}
|
type Cache struct{}
|
||||||
@@ -133,3 +136,29 @@ func (c *Cache) ListKeys(ctx context.Context, req *pb.ListKeysRequest, rsp *pb.L
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) DeleteData(ctx context.Context, request *adminpb.DeleteDataRequest, response *adminpb.DeleteDataResponse) error {
|
||||||
|
method := "admin.DeleteData"
|
||||||
|
_, err := pauth.VerifyMicroAdmin(ctx, method)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(request.TenantId) == 0 {
|
||||||
|
return errors.BadRequest(method, "Missing tenant ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
split := strings.Split(request.TenantId, "/")
|
||||||
|
tctx := tenant.NewContext(split[1], split[0], split[1])
|
||||||
|
keys, err := cache.Context(tctx).ListKeys()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, k := range keys {
|
||||||
|
if err := cache.Context(tctx).Delete(k); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Infof("Deleted %d keys for %s", len(keys), request.TenantId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
5
cache/main.go
vendored
5
cache/main.go
vendored
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/micro/services/cache/handler"
|
"github.com/micro/services/cache/handler"
|
||||||
pb "github.com/micro/services/cache/proto"
|
pb "github.com/micro/services/cache/proto"
|
||||||
|
adminpb "github.com/micro/services/pkg/service/proto"
|
||||||
"github.com/micro/services/pkg/tracing"
|
"github.com/micro/services/pkg/tracing"
|
||||||
|
|
||||||
"github.com/micro/micro/v3/service"
|
"github.com/micro/micro/v3/service"
|
||||||
@@ -17,7 +18,9 @@ func main() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Register handler
|
// Register handler
|
||||||
pb.RegisterCacheHandler(srv.Server(), new(handler.Cache))
|
c := new(handler.Cache)
|
||||||
|
pb.RegisterCacheHandler(srv.Server(), c)
|
||||||
|
adminpb.RegisterAdminHandler(srv.Server(), c)
|
||||||
|
|
||||||
traceCloser := tracing.SetupOpentracing("cache")
|
traceCloser := tracing.SetupOpentracing("cache")
|
||||||
defer traceCloser.Close()
|
defer traceCloser.Close()
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import (
|
|||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/micro/micro/v3/service/errors"
|
"github.com/micro/micro/v3/service/errors"
|
||||||
|
"github.com/micro/micro/v3/service/logger"
|
||||||
|
pauth "github.com/micro/services/pkg/auth"
|
||||||
|
adminpb "github.com/micro/services/pkg/service/proto"
|
||||||
|
"github.com/micro/services/pkg/tenant"
|
||||||
|
|
||||||
"github.com/micro/services/contact/domain"
|
"github.com/micro/services/contact/domain"
|
||||||
pb "github.com/micro/services/contact/proto"
|
pb "github.com/micro/services/contact/proto"
|
||||||
@@ -125,3 +129,42 @@ func (c *contact) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListRes
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *contact) DeleteData(ctx context.Context, request *adminpb.DeleteDataRequest, response *adminpb.DeleteDataResponse) error {
|
||||||
|
method := "admin.DeleteData"
|
||||||
|
_, err := pauth.VerifyMicroAdmin(ctx, method)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(request.TenantId) == 0 {
|
||||||
|
return errors.BadRequest(method, "Missing tenant ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
split := strings.Split(request.TenantId, "/")
|
||||||
|
tctx := tenant.NewContext(split[1], split[0], split[1])
|
||||||
|
// load all keys
|
||||||
|
keys := []string{}
|
||||||
|
offset := uint(0)
|
||||||
|
for {
|
||||||
|
res, err := c.contact.List(tctx, offset, 100)
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "not found") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, r := range res {
|
||||||
|
keys = append(keys, r.Id)
|
||||||
|
}
|
||||||
|
if len(res) < 100 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offset += 100
|
||||||
|
}
|
||||||
|
for _, k := range keys {
|
||||||
|
if err := c.contact.Delete(tctx, k); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Infof("Deleted %d keys for %s", len(keys), request.TenantId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/micro/micro/v3/service/store"
|
"github.com/micro/micro/v3/service/store"
|
||||||
|
admin "github.com/micro/services/pkg/service/proto"
|
||||||
|
|
||||||
"github.com/micro/services/contact/domain"
|
"github.com/micro/services/contact/domain"
|
||||||
"github.com/micro/services/contact/handler"
|
"github.com/micro/services/contact/handler"
|
||||||
@@ -20,9 +21,10 @@ func main() {
|
|||||||
|
|
||||||
contactDomain := domain.NewContactDomain(store.DefaultStore)
|
contactDomain := domain.NewContactDomain(store.DefaultStore)
|
||||||
|
|
||||||
|
h := handler.NewContact(contactDomain)
|
||||||
// Register handler
|
// Register handler
|
||||||
pb.RegisterContactHandler(srv.Server(), handler.NewContact(contactDomain))
|
pb.RegisterContactHandler(srv.Server(), h)
|
||||||
|
admin.RegisterAdminHandler(srv.Server(), h)
|
||||||
// Run service
|
// Run service
|
||||||
if err := srv.Run(); err != nil {
|
if err := srv.Run(); err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import (
|
|||||||
"github.com/micro/micro/v3/service/errors"
|
"github.com/micro/micro/v3/service/errors"
|
||||||
"github.com/micro/micro/v3/service/logger"
|
"github.com/micro/micro/v3/service/logger"
|
||||||
db "github.com/micro/services/db/proto"
|
db "github.com/micro/services/db/proto"
|
||||||
|
pauth "github.com/micro/services/pkg/auth"
|
||||||
gorm2 "github.com/micro/services/pkg/gorm"
|
gorm2 "github.com/micro/services/pkg/gorm"
|
||||||
|
adminpb "github.com/micro/services/pkg/service/proto"
|
||||||
"github.com/micro/services/pkg/tenant"
|
"github.com/micro/services/pkg/tenant"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"google.golang.org/protobuf/types/known/structpb"
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
@@ -441,3 +443,44 @@ func (e *Db) ListTables(ctx context.Context, req *db.ListTablesRequest, rsp *db.
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Db) DeleteData(ctx context.Context, request *adminpb.DeleteDataRequest, response *adminpb.DeleteDataResponse) error {
|
||||||
|
method := "admin.DeleteData"
|
||||||
|
_, err := pauth.VerifyMicroAdmin(ctx, method)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(request.TenantId) == 0 {
|
||||||
|
return errors.BadRequest(method, "Missing tenant ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
split := strings.Split(request.TenantId, "/")
|
||||||
|
tctx := tenant.NewContext(split[1], split[0], split[1])
|
||||||
|
|
||||||
|
tenantId := request.TenantId
|
||||||
|
tenantId = strings.Replace(strings.Replace(tenantId, "/", "_", -1), "-", "_", -1)
|
||||||
|
|
||||||
|
db, err := e.GetDBConn(tctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tables []string
|
||||||
|
if err := db.Table("information_schema.tables").Select("table_name").Where("table_schema = ?", "public").Find(&tables).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dropCount := 0
|
||||||
|
for _, v := range tables {
|
||||||
|
if !strings.HasPrefix(v, tenantId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := db.Exec(fmt.Sprintf(dropTableStmt, v)).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dropCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Infof("Deleted %d tables for %s", dropCount, request.TenantId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
pb "github.com/micro/services/db/proto"
|
pb "github.com/micro/services/db/proto"
|
||||||
|
admin "github.com/micro/services/pkg/service/proto"
|
||||||
"github.com/micro/services/pkg/tracing"
|
"github.com/micro/services/pkg/tracing"
|
||||||
|
|
||||||
"github.com/micro/services/db/handler"
|
"github.com/micro/services/db/handler"
|
||||||
@@ -40,9 +41,7 @@ func main() {
|
|||||||
|
|
||||||
// Register handler
|
// Register handler
|
||||||
pb.RegisterDbHandler(srv.Server(), h)
|
pb.RegisterDbHandler(srv.Server(), h)
|
||||||
|
admin.RegisterAdminHandler(srv.Server(), h)
|
||||||
// Register handler
|
|
||||||
pb.RegisterDbHandler(srv.Server(), &handler.Db{})
|
|
||||||
|
|
||||||
traceCloser := tracing.SetupOpentracing("db")
|
traceCloser := tracing.SetupOpentracing("db")
|
||||||
defer traceCloser.Close()
|
defer traceCloser.Close()
|
||||||
|
|||||||
34
pkg/auth/auth.go
Normal file
34
pkg/auth/auth.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/micro/micro/v3/service/auth"
|
||||||
|
"github.com/micro/micro/v3/service/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VerifyMicroAdmin(ctx context.Context, method string) (*auth.Account, error) {
|
||||||
|
acc, ok := auth.AccountFromContext(ctx)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Unauthorized(method, "Unauthorized")
|
||||||
|
}
|
||||||
|
if err := doVerifyMicroAdmin(acc, method); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return acc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doVerifyMicroAdmin(acc *auth.Account, method string) error {
|
||||||
|
errForbid := errors.Forbidden(method, "Forbidden")
|
||||||
|
if acc.Issuer != "micro" {
|
||||||
|
return errForbid
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range acc.Scopes {
|
||||||
|
if (s == "admin" && acc.Type == "user") || (s == "service" && acc.Type == "service") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errForbid
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,10 @@ import (
|
|||||||
"github.com/micro/micro/v3/service/auth"
|
"github.com/micro/micro/v3/service/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
metaOwner = "apikey_owner"
|
||||||
|
)
|
||||||
|
|
||||||
// FromContext returns a tenant from the context
|
// FromContext returns a tenant from the context
|
||||||
func FromContext(ctx context.Context) (string, bool) {
|
func FromContext(ctx context.Context) (string, bool) {
|
||||||
acc, ok := auth.AccountFromContext(ctx)
|
acc, ok := auth.AccountFromContext(ctx)
|
||||||
@@ -21,7 +25,7 @@ func FromContext(ctx context.Context) (string, bool) {
|
|||||||
func FromAccount(acc *auth.Account) string {
|
func FromAccount(acc *auth.Account) string {
|
||||||
id := acc.ID
|
id := acc.ID
|
||||||
issuer := acc.Issuer
|
issuer := acc.Issuer
|
||||||
owner := acc.Metadata["apikey_owner"]
|
owner := acc.Metadata[metaOwner]
|
||||||
|
|
||||||
if len(id) == 0 {
|
if len(id) == 0 {
|
||||||
id = "micro"
|
id = "micro"
|
||||||
@@ -47,3 +51,14 @@ func CreateKey(ctx context.Context, key string) string {
|
|||||||
// return a tenant prefixed key e.g micro/asim/foobar
|
// return a tenant prefixed key e.g micro/asim/foobar
|
||||||
return fmt.Sprintf("%s/%s", t, key)
|
return fmt.Sprintf("%s/%s", t, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewContext returns a context that will encapsulate the given tenant
|
||||||
|
func NewContext(id, issuer, owner string) context.Context {
|
||||||
|
return auth.ContextWithAccount(context.Background(), &auth.Account{
|
||||||
|
ID: id,
|
||||||
|
Issuer: issuer,
|
||||||
|
Metadata: map[string]string{
|
||||||
|
metaOwner: owner,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/micro/micro/v3/service/auth"
|
|
||||||
"github.com/micro/micro/v3/service/errors"
|
"github.com/micro/micro/v3/service/errors"
|
||||||
"github.com/micro/micro/v3/service/logger"
|
"github.com/micro/micro/v3/service/logger"
|
||||||
"github.com/micro/micro/v3/service/store"
|
"github.com/micro/micro/v3/service/store"
|
||||||
|
pauth "github.com/micro/services/pkg/auth"
|
||||||
adminpb "github.com/micro/services/pkg/service/proto"
|
adminpb "github.com/micro/services/pkg/service/proto"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
@@ -510,7 +510,7 @@ func (s *User) VerifyToken(ctx context.Context, req *pb.VerifyTokenRequest, rsp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *User) DeleteData(ctx context.Context, request *adminpb.DeleteDataRequest, response *adminpb.DeleteDataResponse) error {
|
func (s *User) DeleteData(ctx context.Context, request *adminpb.DeleteDataRequest, response *adminpb.DeleteDataResponse) error {
|
||||||
if _, err := verifyMicroAdmin(ctx, "user.DeleteData"); err != nil {
|
if _, err := pauth.VerifyMicroAdmin(ctx, "user.DeleteData"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,29 +519,3 @@ func (s *User) DeleteData(ctx context.Context, request *adminpb.DeleteDataReques
|
|||||||
}
|
}
|
||||||
return s.domain.DeleteTenantData(request.TenantId)
|
return s.domain.DeleteTenantData(request.TenantId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyMicroAdmin(ctx context.Context, method string) (*auth.Account, error) {
|
|
||||||
acc, ok := auth.AccountFromContext(ctx)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Unauthorized(method, "Unauthorized")
|
|
||||||
}
|
|
||||||
if err := doVerifyMicroAdmin(acc, method); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return acc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func doVerifyMicroAdmin(acc *auth.Account, method string) error {
|
|
||||||
errForbid := errors.Forbidden(method, "Forbidden")
|
|
||||||
if acc.Issuer != "micro" {
|
|
||||||
return errForbid
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range acc.Scopes {
|
|
||||||
if (s == "admin" && acc.Type == "user") || (s == "service" && acc.Type == "service") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errForbid
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user