mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 10:54:28 +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"
|
||||
log "github.com/micro/micro/v3/service/logger"
|
||||
pb "github.com/micro/services/cache/proto"
|
||||
pauth "github.com/micro/services/pkg/auth"
|
||||
"github.com/micro/services/pkg/cache"
|
||||
adminpb "github.com/micro/services/pkg/service/proto"
|
||||
"github.com/micro/services/pkg/tenant"
|
||||
)
|
||||
|
||||
type Cache struct{}
|
||||
@@ -133,3 +136,29 @@ func (c *Cache) ListKeys(ctx context.Context, req *pb.ListKeysRequest, rsp *pb.L
|
||||
|
||||
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 (
|
||||
"github.com/micro/services/cache/handler"
|
||||
pb "github.com/micro/services/cache/proto"
|
||||
adminpb "github.com/micro/services/pkg/service/proto"
|
||||
"github.com/micro/services/pkg/tracing"
|
||||
|
||||
"github.com/micro/micro/v3/service"
|
||||
@@ -17,7 +18,9 @@ func main() {
|
||||
)
|
||||
|
||||
// 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")
|
||||
defer traceCloser.Close()
|
||||
|
||||
@@ -6,6 +6,10 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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"
|
||||
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
|
||||
}
|
||||
|
||||
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 (
|
||||
"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/handler"
|
||||
@@ -20,9 +21,10 @@ func main() {
|
||||
|
||||
contactDomain := domain.NewContactDomain(store.DefaultStore)
|
||||
|
||||
h := handler.NewContact(contactDomain)
|
||||
// Register handler
|
||||
pb.RegisterContactHandler(srv.Server(), handler.NewContact(contactDomain))
|
||||
|
||||
pb.RegisterContactHandler(srv.Server(), h)
|
||||
admin.RegisterAdminHandler(srv.Server(), h)
|
||||
// Run service
|
||||
if err := srv.Run(); err != nil {
|
||||
logger.Fatal(err)
|
||||
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
"github.com/micro/micro/v3/service/errors"
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
db "github.com/micro/services/db/proto"
|
||||
pauth "github.com/micro/services/pkg/auth"
|
||||
gorm2 "github.com/micro/services/pkg/gorm"
|
||||
adminpb "github.com/micro/services/pkg/service/proto"
|
||||
"github.com/micro/services/pkg/tenant"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"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
|
||||
}
|
||||
|
||||
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 (
|
||||
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/db/handler"
|
||||
@@ -40,9 +41,7 @@ func main() {
|
||||
|
||||
// Register handler
|
||||
pb.RegisterDbHandler(srv.Server(), h)
|
||||
|
||||
// Register handler
|
||||
pb.RegisterDbHandler(srv.Server(), &handler.Db{})
|
||||
admin.RegisterAdminHandler(srv.Server(), h)
|
||||
|
||||
traceCloser := tracing.SetupOpentracing("db")
|
||||
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"
|
||||
)
|
||||
|
||||
const (
|
||||
metaOwner = "apikey_owner"
|
||||
)
|
||||
|
||||
// FromContext returns a tenant from the context
|
||||
func FromContext(ctx context.Context) (string, bool) {
|
||||
acc, ok := auth.AccountFromContext(ctx)
|
||||
@@ -21,7 +25,7 @@ func FromContext(ctx context.Context) (string, bool) {
|
||||
func FromAccount(acc *auth.Account) string {
|
||||
id := acc.ID
|
||||
issuer := acc.Issuer
|
||||
owner := acc.Metadata["apikey_owner"]
|
||||
owner := acc.Metadata[metaOwner]
|
||||
|
||||
if len(id) == 0 {
|
||||
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 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"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/micro/v3/service/auth"
|
||||
"github.com/micro/micro/v3/service/errors"
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
"github.com/micro/micro/v3/service/store"
|
||||
pauth "github.com/micro/services/pkg/auth"
|
||||
adminpb "github.com/micro/services/pkg/service/proto"
|
||||
"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 {
|
||||
if _, err := verifyMicroAdmin(ctx, "user.DeleteData"); err != nil {
|
||||
if _, err := pauth.VerifyMicroAdmin(ctx, "user.DeleteData"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -519,29 +519,3 @@ func (s *User) DeleteData(ctx context.Context, request *adminpb.DeleteDataReques
|
||||
}
|
||||
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