In my code, I want to disable some inputs fields based on the user authentication level, I was able to do it in JavaScript, but this is unrecommended solution, and I want to make it from the server side.
Below is my go
code;
package main
import (
"context"
"html/template"
"net/http"
"strings"
"time"
)
type User struct {
Flags string
Title string
}
type UsersPageData struct {
PageTitle string
Users []User
}
func requestTime(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "requestTime", time.Now().Format(time.RFC3339))
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
func helloHandler(name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var title string
if requestTime := r.Context().Value("requestTime"); requestTime != nil {
if str, ok := requestTime.(string); ok {
title = "\ngenerated at: " str
}
}
master := strings.Join([]string{"admin", "user", "superuser", "read"}, " ")
admin := strings.Join([]string{"admin"}, " ")
user := strings.Join([]string{"user"}, " ")
tmpl := template.Must(template.ParseFiles("index.html"))
data := UsersPageData{
PageTitle: "Users list: " title,
Users: []User{
{Flags: master, Title: "Everything"},
{Flags: admin, Title: "Administrator"},
{Flags: user, Title: "Normal user"},
},
}
tmpl.Execute(w, data)
})
}
func main() {
http.Handle("/john", requestTime(helloHandler("John")))
http.ListenAndServe(":8080", nil)
}
And here is my template including the JS code;
<style>
.admin {
color: green;
}
.user {
color: red;
--btn-disable: 0;
}
[data-authorized="no"] {
/* Attribute has this exact value */
cursor: not-allowed;
pointer-events: none;
/*Button disabled - CSS color class*/
color: #c0c0c0;
background-color: rgb(229, 229, 229) !important;
}
</style>
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Users}}
<input type="text" data-permissions={{.Flags}} data-authorized="no">{{.Title}}</s>
{{end}}
</ul>
<script>
var flags = ["admin", "super user"]
var elements = document.querySelectorAll("input");
elements.forEach((element, index, array) => {
if(element.hasAttribute("data-permissions")){
console.log(element.dataset.permissions)
var perm = element.dataset.permissions.split(" ");
var found = false;
for (var i = 0; i < perm.length; i ) {
if (flags.indexOf(perm[i]) > -1) {
element.dataset.authorized = "yes"
element.removeAttribute("data-permissions")
break;
}
}
}
});
</script>
Any thought?
CodePudding user response:
I was able to do it, with the help of template custom functions, below the full code:
package main
import (
"html/template"
"net/http"
)
type User struct {
Flags []flag //string
Title string
}
type UsersPageData struct {
PageTitle string
Users []User
}
type flag int
const (
Admin flag = iota 1 // iota = 0
Editer
Superuser
Viewer
Dummy
)
func subtract(arg1, arg2 int) int {
return arg1 - arg2
}
func helloHandler(name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Map the `subtract` custom function in the template
funcMap := map[string]interface{}{"subtract": subtract}
master := []flag{Admin, Editer, Superuser, Viewer}
admin := []flag{Admin, Superuser, Viewer}
user := []flag{Viewer, Dummy}
tmpl := template.New("").Funcs(template.FuncMap(funcMap))
template.Must(tmpl.ParseFiles("index.html"))
data := UsersPageData{
PageTitle: "Users list: ",
Users: []User{
{Flags: master, Title: "Everything"},
{Flags: admin, Title: "Administrator"},
{Flags: user, Title: "Normal user"},
},
}
tmpl.ExecuteTemplate(w, "index.html", data)
})
}
func main() {
fs := http.StripPrefix("/www/", http.FileServer(http.Dir("./www")))
http.Handle("/www/", fs)
http.Handle("/", helloHandler("John"))
http.ListenAndServe(":8080", nil)
}
The index.html
is:
<html>
{{/* This is a comment
{{$flags := []flag{Admin, Editer, Superuser, Viewer};}}
Admin Flag = iota 1 // iota = 0
Editer
Superuser
Viewer
}}
*/}}
<ul>
{{range .Users}}
<span>{{.Title}}</span>
{{ $done := false}} {{$length := len .Flags}}
{{range $i, $v := .Flags}}
{{ if $done }}
{{ else }}
{{if or (eq $v 1) (eq $v 3)}}
<input type="text" name="subject" placeholder= {{$v}} required>
{{ $done = true }}
{{else}}
{{ if eq $i (subtract $length 1)}}
<input type="text" name="subject" placeholder= {{$v}} disabled>
{{ end }}
{{end}}
{{end}}
{{end}}
{{end}}
</ul>
</html>