Created
February 14, 2020 11:18
-
-
Save hosszukalman/b84a8554e82cd6a5f3eb8249a72d253a to your computer and use it in GitHub Desktop.
A POC for permission based field reading in Golang
This file contains hidden or 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
package main | |
import ( | |
"fmt" | |
"reflect" | |
) | |
type User struct { | |
Permissions []string | |
} | |
func (u User) HasPermission(perm string) bool { | |
for _, p := range u.Permissions { | |
if p == perm { | |
return true | |
} | |
} | |
return false | |
} | |
type EmbedType struct { | |
PublicField string | |
LimitedRead string `readpermission:"limited.read"` | |
LimitedEmbedRead string `readpermission:"limited.embed.read"` | |
LimitEmbedEmbedRead EmbedEmbedType | |
} | |
type EmbedEmbedType struct { | |
PublicField string | |
LimitedRead string `readpermission:"limited.read"` | |
LimitedEmbedRead string `readpermission:"limited.embed.read"` | |
LimitedEmbedEmbedRead string `readpermission:"limited.embed.embed.read"` | |
} | |
type HiddenStruct struct { | |
Hidden string | |
} | |
type TestPermission struct { | |
PublicField string | |
LimitedRead string `readpermission:"limited.read"` | |
Embeded EmbedType | |
Hidden HiddenStruct `readpermission:"hidden"` | |
ThisIsPtr *string `readpermission:"limited.read"` | |
} | |
func ClearStruct(object interface{}, u User) { | |
var typ reflect.Type | |
var val reflect.Value | |
if reflect.TypeOf(object).Kind() == reflect.Ptr { | |
typ = reflect.TypeOf(object).Elem() | |
val = reflect.ValueOf(object).Elem() | |
} else { | |
typ = reflect.TypeOf(object) | |
val = reflect.ValueOf(object) | |
} | |
var clearData func(t reflect.Type, v reflect.Value, u User) | |
clearData = func(t reflect.Type, v reflect.Value, u User) { | |
for i := 0; i < v.NumField(); i++ { | |
fieldVal := v.Field(i) | |
fieldTyp := t.Field(i) | |
if fieldVal.CanSet() { | |
if perm := fieldTyp.Tag.Get("readpermission"); perm != "" && !u.HasPermission(perm) { | |
fieldVal.Set(reflect.Zero(fieldTyp.Type)) | |
} | |
if fieldVal.Kind() == reflect.Struct { | |
clearData(fieldTyp.Type, fieldVal, u) | |
} | |
} | |
} | |
} | |
clearData(typ, val, u) | |
} | |
func main() { | |
u1 := User{[]string{"edit", "create", "limited.read", "limited.embed.read", "limited.embed.embed.read"}} | |
u2 := User{[]string{"limited.read", "limited.embed.read"}} | |
u3 := User{} | |
ptrString := "pointerString" | |
t1 := TestPermission{ | |
PublicField: "One", | |
LimitedRead: "Two", | |
Embeded: EmbedType{ | |
PublicField: "Three", | |
LimitedRead: "Four", | |
LimitedEmbedRead: "Five", | |
LimitEmbedEmbedRead: EmbedEmbedType{ | |
PublicField: "Six", | |
LimitedRead: "Seven", | |
LimitedEmbedRead: "Eight", | |
LimitedEmbedEmbedRead: "Nine", | |
}, | |
}, | |
Hidden: HiddenStruct{ | |
Hidden: "Access denied", | |
}, | |
ThisIsPtr: &ptrString, | |
} | |
t2 := t1 | |
t3 := t1 | |
fmt.Printf("Original: %#v\n", t1) | |
ClearStruct(&t1, u1) | |
fmt.Printf("Cleared with all permissions (except hidden): %#v\n", t1) | |
ClearStruct(&t2, u2) | |
fmt.Printf("Cleared with limited permissions: %#v\n", t2) | |
ClearStruct(&t3, u3) | |
fmt.Printf("Cleared without permissions: %#v\n", t3) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment