Closed yznts closed 2 years ago
Would be good is this design incorporates security.
For example what pages can a user see based on their roles.
One approach is https://github.com/cerbos/cerbos
You dont have to use a DB BTW. you can just define things on the file system.
Example usage: Policy definition: https://github.com/cerbos/demo-rest/blob/main/cerbos/policies/store_roles.yaml
Using that policy: https://github.com/cerbos/demo-rest/blob/main/service/service.go#L142
Because its pure golang this can be used server side and client side thanks to WASM, etc.
You can use this to also define pages and components perhaps too but i have not done that before.
You can also use cerbos through you whole stack to do things like "this user can see this data if they are of role X and their first name starts with "bob", etc. Its really agnostic
One thing to note is that Cerbos does NOT support GRPCWebProxy. https://github.com/cerbos/cerbos/blob/main/go.mod If you use GRPCWebProxy like i highlighted in the other issue then it will work with no other servers and also client side as wasm. here is the lib for that: https://github.com/golioth/grpc-websocket-proxy
Roles and policies are definetely out of scope of this issue (and this library). It would be nice to see this functionality as an external module (just like uikit).
In this issue I'd like to provide a new way to define pages and components (with full backward compatibility and support of a structs approach). I also in process of refactoring the project architecture during this time (related issue https://github.com/kyoto-framework/kyoto/issues/93). Current working prototype looks similar to this:
...
func PageIndex(b *kyoto.Builder) {
b.Template(func() *template.Template {
return template.Must(template.New("page.index.html").ParseGlob("*.html"))
})
b.Init(func() {
b.State.Set("Title", "Kyoto in a functional way")
b.Component("UUID1", ComponentUUID)
b.Component("UUID2", ComponentUUID)
})
}
func ComponentUUID(b *kyoto.Builder) {
b.Async(func() error {
// Execute request
resp, err := http.Get("http://httpbin.org/uuid")
if err != nil {
return err
}
// Defer closing of response body
defer resp.Body.Close()
// Decode response
data := map[string]string{}
json.NewDecoder(resp.Body).Decode(&data)
// Set state
b.State.Set("UUID", data["uuid"])
// Return
return nil
})
}
I'm still thinking about possible issues related to this approach and solving compatibility issues, but overall idea is similar to code I provided. It would be nice to have feature you're asking for. But first, let's wait for architecture migration to scheduler because it will provide more abilities for external integrations.
Ok Security is later.
Here is a virtual structure ( in your case golang structs) Sites have Pages ( one to many ) Pages have Sections ( one to many ). You map a Role array to this later as a property of a Section. Sections have Components ( one to many )
It looks alot like a CMS pattern, and you are sort of boarding on it. You can use this approach for Design time or Runtime based systems.
The idea is that you define a Section in a page as a Placeholder. Then you can map Components into that Section.
Security can then easily be added, because you have a loose coupling between virtual structure ( Pages and Sections and Roles/Users) and the components. Because of this you can change the Security at runtime, which is def a need even for kyoto.
Forgot that a Pages has Pages ( one to many ) .. ..
Functional definitions will be delivered with a new architecture refactor as par of the issue https://github.com/kyoto-framework/kyoto/issues/93
@gedw99 It would be possible to implement Roles as a separate module with a new architecture. Now, main lib idea is to provide extendable core.
:)
Current working prototype looks like this: