-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix(cli,api) complex filter with typed attrs * fix(cli) tests and doc * fix(api) mongo not operator needs regex * fix(api) add trim and tes * refactor(api) adjust pattern * refactor(api) extract cursor * refactor(api) get many objects * refacto(api) get hierarchy * refactor(api) get hierarchy * refactor(api) update * refactor(api) fill hierarchy * refactor(api) get hierarchy * refactor(api) refactor propagate * refactor(api) lastupdated filter
- Loading branch information
1 parent
276764e
commit 60fa4fa
Showing
39 changed files
with
1,502 additions
and
1,479 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package models | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"p3/repository" | ||
u "p3/utils" | ||
"strings" | ||
|
||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
) | ||
|
||
func CommandRunner(cmd interface{}) *mongo.SingleResult { | ||
ctx, cancel := u.Connect() | ||
result := repository.GetDB().RunCommand(ctx, cmd, nil) | ||
defer cancel() | ||
return result | ||
} | ||
|
||
func GetDBName() string { | ||
name := repository.GetDB().Name() | ||
|
||
//Remove the preceding 'ogree' at beginning of name | ||
if strings.Index(name, "ogree") == 0 { | ||
name = name[5:] //5=len('ogree') | ||
} | ||
return name | ||
} | ||
|
||
func ExtractCursor(c *mongo.Cursor, ctx context.Context, entity int, userRoles map[string]Role) ([]map[string]interface{}, error) { | ||
ans := []map[string]interface{}{} | ||
for c.Next(ctx) { | ||
x := map[string]interface{}{} | ||
err := c.Decode(x) | ||
if err != nil { | ||
fmt.Println(err.Error()) | ||
return nil, err | ||
} | ||
// Remove _id | ||
x = fixID(x) | ||
// Check permissions | ||
if u.IsEntityHierarchical(entity) && userRoles != nil { | ||
permission := CheckUserPermissionsWithObject(userRoles, entity, x) | ||
if permission == READONLYNAME { | ||
x = FixReadOnlyName(x) | ||
} | ||
if permission >= READONLYNAME { | ||
ans = append(ans, x) | ||
} | ||
} else { | ||
ans = append(ans, x) | ||
} | ||
} | ||
return ans, nil | ||
} | ||
|
||
func WithTransaction[T any](callback func(mongo.SessionContext) (T, error)) (T, *u.Error) { | ||
ctx, cancel := u.Connect() | ||
defer cancel() | ||
|
||
var nilT T | ||
|
||
// Start a session and run the callback to update db | ||
session, err := repository.GetClient().StartSession() | ||
if err != nil { | ||
return nilT, &u.Error{Type: u.ErrDBError, Message: "Unable to start session: " + err.Error()} | ||
} | ||
defer session.EndSession(ctx) | ||
|
||
callbackWrapper := func(ctx mongo.SessionContext) (any, error) { | ||
result, err := callback(ctx) | ||
if err != nil { | ||
// support returning u.Error even if nil | ||
if errCasted, ok := err.(*u.Error); ok { | ||
if errCasted != nil { | ||
return nilT, errCasted // u.Error not nil -> return u.Error not nil | ||
} | ||
|
||
return result, nil // u.Error nil -> return error nil | ||
} | ||
|
||
return result, err // error not nil -> return error not nil | ||
} | ||
|
||
return result, nil // error nil -> return error nil | ||
} | ||
|
||
result, err := session.WithTransaction(ctx, callbackWrapper) | ||
if err != nil { | ||
if errCasted, ok := err.(*u.Error); ok { | ||
return nilT, errCasted | ||
} | ||
|
||
return nilT, &u.Error{Type: u.ErrDBError, Message: "Unable to complete transaction: " + err.Error()} | ||
} | ||
|
||
return castResult[T](result), nil | ||
} | ||
|
||
func castResult[T any](result any) T { | ||
if result == nil { | ||
var nilT T | ||
return nilT | ||
} | ||
|
||
return result.(T) | ||
} | ||
|
||
func GetIdReqByEntity(entityStr, id string) primitive.M { | ||
var idFilter primitive.M | ||
if u.IsEntityNonHierarchical(u.EntityStrToInt(entityStr)) { | ||
idFilter = bson.M{"slug": id} | ||
} else { | ||
idFilter = bson.M{"id": id} | ||
} | ||
return idFilter | ||
} |
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package models | ||
|
||
import ( | ||
"p3/repository" | ||
u "p3/utils" | ||
|
||
"go.mongodb.org/mongo-driver/mongo" | ||
) | ||
|
||
func CreateEntity(entity int, t map[string]interface{}, userRoles map[string]Role) (map[string]interface{}, *u.Error) { | ||
tags, tagsPresent := getTags(t) | ||
if tagsPresent { | ||
err := verifyTagList(tags) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
if err := prepareCreateEntity(entity, t, userRoles); err != nil { | ||
return nil, err | ||
} | ||
|
||
return WithTransaction(func(ctx mongo.SessionContext) (map[string]any, error) { | ||
if entity == u.TAG { | ||
err := createTagImage(ctx, t) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
entStr := u.EntityToString(entity) | ||
|
||
_, err := repository.CreateObject(ctx, entStr, t) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
fixID(t) | ||
return t, nil | ||
}) | ||
} | ||
|
||
func prepareCreateEntity(entity int, t map[string]interface{}, userRoles map[string]Role) *u.Error { | ||
if err := ValidateEntity(entity, t); err != nil { | ||
return err | ||
} | ||
|
||
// Check user permissions | ||
if u.IsEntityHierarchical(entity) { | ||
if permission := CheckUserPermissionsWithObject(userRoles, entity, t); permission < WRITE { | ||
return &u.Error{Type: u.ErrUnauthorized, | ||
Message: "User does not have permission to create this object"} | ||
} | ||
} | ||
|
||
delete(t, "parentId") | ||
|
||
return nil | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package models | ||
|
||
import ( | ||
"os" | ||
"p3/repository" | ||
u "p3/utils" | ||
|
||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/bson/primitive" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
) | ||
|
||
func DeleteObject(entityStr string, id string, userRoles map[string]Role) *u.Error { | ||
entity := u.EntityStrToInt(entityStr) | ||
if entity == u.TAG { | ||
return DeleteTag(id) | ||
} else if u.IsEntityNonHierarchical(entity) { | ||
return DeleteNonHierarchicalObject(entityStr, id) | ||
} else { | ||
return DeleteHierarchicalObject(entityStr, id, userRoles) | ||
} | ||
} | ||
|
||
// DeleteHierarchicalObject: delete object of given hierarchyName | ||
// search for all its children and delete them too, return: | ||
// - success or fail message map | ||
func DeleteHierarchicalObject(entity string, id string, userRoles map[string]Role) *u.Error { | ||
// Special check for delete domain | ||
if entity == "domain" { | ||
if id == os.Getenv("db") { | ||
return &u.Error{Type: u.ErrForbidden, Message: "Cannot delete tenant's default domain"} | ||
} | ||
if domainHasObjects(id) { | ||
return &u.Error{Type: u.ErrForbidden, Message: "Cannot delete domain if it has at least one object"} | ||
} | ||
} | ||
|
||
// Delete with given id | ||
req, ok := GetRequestFilterByDomain(userRoles) | ||
if !ok { | ||
return &u.Error{Type: u.ErrUnauthorized, Message: "User does not have permission to delete"} | ||
} | ||
|
||
req["id"] = id | ||
|
||
_, err := WithTransaction(func(ctx mongo.SessionContext) (any, error) { | ||
err := repository.DeleteObject(ctx, entity, req) | ||
if err != nil { | ||
// Unable to delete given id | ||
return nil, err | ||
} | ||
|
||
// Delete possible children | ||
rangeEntities := getChildrenCollections(u.GROUP, entity) | ||
for _, childEnt := range rangeEntities { | ||
childEntName := u.EntityToString(childEnt) | ||
pattern := primitive.Regex{Pattern: "^" + id + u.HN_DELIMETER, Options: ""} | ||
|
||
repository.GetDB().Collection(childEntName).DeleteMany(ctx, | ||
bson.M{"id": pattern}) | ||
} | ||
|
||
return nil, nil | ||
}) | ||
|
||
return err | ||
} | ||
|
||
func DeleteNonHierarchicalObject(entity, slug string) *u.Error { | ||
req := bson.M{"slug": slug} | ||
ctx, cancel := u.Connect() | ||
defer cancel() | ||
return repository.DeleteObject(ctx, entity, req) | ||
} | ||
|
||
// Helper functions | ||
|
||
func domainHasObjects(domain string) bool { | ||
data := map[string]interface{}{} | ||
// Get all collections names | ||
ctx, cancel := u.Connect() | ||
db := repository.GetDB() | ||
collNames, _ := db.ListCollectionNames(ctx, bson.D{}) | ||
|
||
// Check if at least one object belongs to domain | ||
for _, collName := range collNames { | ||
pattern := primitive.Regex{Pattern: "^" + domain, Options: ""} | ||
e := db.Collection(collName).FindOne(ctx, bson.M{"domain": pattern}).Decode(&data) | ||
if e == nil { | ||
// Found one! | ||
return true | ||
} | ||
} | ||
|
||
defer cancel() | ||
return false | ||
} |
Oops, something went wrong.