mirror of
				https://github.com/ClusterCockpit/cc-backend
				synced 2025-11-04 01:25:06 +01:00 
			
		
		
		
	Merge branch 'master' of github.com:ClusterCockpit/cc-backend
This commit is contained in:
		
							
								
								
									
										13
									
								
								auth/ldap.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								auth/ldap.go
									
									
									
									
									
								
							@@ -1,7 +1,6 @@
 | 
				
			|||||||
package auth
 | 
					package auth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/tls"
 | 
					 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -18,10 +17,7 @@ type LdapConfig struct {
 | 
				
			|||||||
	SearchDN        string `json:"search_dn"`
 | 
						SearchDN        string `json:"search_dn"`
 | 
				
			||||||
	UserBind        string `json:"user_bind"`
 | 
						UserBind        string `json:"user_bind"`
 | 
				
			||||||
	UserFilter      string `json:"user_filter"`
 | 
						UserFilter      string `json:"user_filter"`
 | 
				
			||||||
	TLS        bool   `json:"tls"`
 | 
						SyncInterval    string `json:"sync_interval"` // Parsed using time.ParseDuration.
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Parsed using time.ParseDuration.
 | 
					 | 
				
			||||||
	SyncInterval    string `json:"sync_interval"`
 | 
					 | 
				
			||||||
	SyncDelOldUsers bool   `json:"sync_del_old_users"`
 | 
						SyncDelOldUsers bool   `json:"sync_del_old_users"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,13 +60,6 @@ func (auth *Authentication) getLdapConnection(admin bool) (*ldap.Conn, error) {
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if auth.ldapConfig.TLS {
 | 
					 | 
				
			||||||
		if err := conn.StartTLS(&tls.Config{InsecureSkipVerify: true}); err != nil {
 | 
					 | 
				
			||||||
			conn.Close()
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if admin {
 | 
						if admin {
 | 
				
			||||||
		if err := conn.Bind(auth.ldapConfig.SearchDN, auth.ldapSyncUserPassword); err != nil {
 | 
							if err := conn.Bind(auth.ldapConfig.SearchDN, auth.ldapSyncUserPassword); err != nil {
 | 
				
			||||||
			conn.Close()
 | 
								conn.Close()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								frontend
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								frontend
									
									
									
									
									
								
							 Submodule frontend updated: 42f56f0a0a...cb0447516b
									
								
							
							
								
								
									
										21
									
								
								routes.go
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								routes.go
									
									
									
									
									
								
							@@ -86,27 +86,20 @@ func setupRoutes(router *mux.Router, routes []Route) {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			infos := map[string]interface{}{
 | 
								infos := route.Setup(map[string]interface{}{}, r)
 | 
				
			||||||
				"admin": true,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if user := auth.GetUser(r.Context()); user != nil {
 | 
					 | 
				
			||||||
				infos["loginId"] = user.Username
 | 
					 | 
				
			||||||
				infos["admin"] = user.HasRole(auth.RoleAdmin)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				infos["loginId"] = false
 | 
					 | 
				
			||||||
				infos["admin"] = false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			infos = route.Setup(infos, r)
 | 
					 | 
				
			||||||
			if id, ok := infos["id"]; ok {
 | 
								if id, ok := infos["id"]; ok {
 | 
				
			||||||
				route.Title = strings.Replace(route.Title, "<ID>", id.(string), 1)
 | 
									route.Title = strings.Replace(route.Title, "<ID>", id.(string), 1)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			infos["clusters"] = config.Clusters
 | 
								username, isAdmin := "", true
 | 
				
			||||||
 | 
								if user := auth.GetUser(r.Context()); user != nil {
 | 
				
			||||||
 | 
									username = user.Username
 | 
				
			||||||
 | 
									isAdmin = user.HasRole(auth.RoleAdmin)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			page := templates.Page{
 | 
								page := templates.Page{
 | 
				
			||||||
				Title:  route.Title,
 | 
									Title:  route.Title,
 | 
				
			||||||
 | 
									User:   templates.User{Username: username, IsAdmin: isAdmin},
 | 
				
			||||||
				Config: conf,
 | 
									Config: conf,
 | 
				
			||||||
				Infos:  infos,
 | 
									Infos:  infos,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								server.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								server.go
									
									
									
									
									
								
							@@ -95,13 +95,7 @@ var programConfig ProgramConfig = ProgramConfig{
 | 
				
			|||||||
	JobArchive:            "./var/job-archive",
 | 
						JobArchive:            "./var/job-archive",
 | 
				
			||||||
	AsyncArchiving:        true,
 | 
						AsyncArchiving:        true,
 | 
				
			||||||
	DisableArchive:        false,
 | 
						DisableArchive:        false,
 | 
				
			||||||
	LdapConfig: &auth.LdapConfig{
 | 
						LdapConfig:            nil,
 | 
				
			||||||
		Url:        "ldap://localhost",
 | 
					 | 
				
			||||||
		UserBase:   "ou=hpc,dc=rrze,dc=uni-erlangen,dc=de",
 | 
					 | 
				
			||||||
		SearchDN:   "cn=admin,dc=rrze,dc=uni-erlangen,dc=de",
 | 
					 | 
				
			||||||
		UserBind:   "uid={username},ou=hpc,dc=rrze,dc=uni-erlangen,dc=de",
 | 
					 | 
				
			||||||
		UserFilter: "(&(objectclass=posixAccount)(uid=*))",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	HttpsCertFile:         "",
 | 
						HttpsCertFile:         "",
 | 
				
			||||||
	HttpsKeyFile:          "",
 | 
						HttpsKeyFile:          "",
 | 
				
			||||||
	UiDefaults: map[string]interface{}{
 | 
						UiDefaults: map[string]interface{}{
 | 
				
			||||||
@@ -401,6 +395,29 @@ func main() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	secured.Handle("/query", graphQLEndpoint)
 | 
						secured.Handle("/query", graphQLEndpoint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						secured.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
							conf, err := config.GetUIConfig(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								http.Error(rw, err.Error(), http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							username, isAdmin := "", true
 | 
				
			||||||
 | 
							if user := auth.GetUser(r.Context()); user != nil {
 | 
				
			||||||
 | 
								username = user.Username
 | 
				
			||||||
 | 
								isAdmin = user.HasRole(auth.RoleAdmin)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							templates.Render(rw, r, "home.tmpl", &templates.Page{
 | 
				
			||||||
 | 
								Title:  "ClusterCockpit",
 | 
				
			||||||
 | 
								User:   templates.User{Username: username, IsAdmin: isAdmin},
 | 
				
			||||||
 | 
								Config: conf,
 | 
				
			||||||
 | 
								Infos: map[string]interface{}{
 | 
				
			||||||
 | 
									"clusters": config.Clusters,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	secured.HandleFunc("/search", func(rw http.ResponseWriter, r *http.Request) {
 | 
						secured.HandleFunc("/search", func(rw http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		if search := r.URL.Query().Get("searchId"); search != "" {
 | 
							if search := r.URL.Query().Get("searchId"); search != "" {
 | 
				
			||||||
			job, username, err := api.JobRepository.FindJobOrUser(r.Context(), search)
 | 
								job, username, err := api.JobRepository.FindJobOrUser(r.Context(), search)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,101 +13,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        {{block "stylesheets" .}}
 | 
					        {{block "stylesheets" .}}
 | 
				
			||||||
        {{end}}
 | 
					        {{end}}
 | 
				
			||||||
 | 
					        <script>
 | 
				
			||||||
 | 
					            const header = {
 | 
				
			||||||
 | 
					                "username": "{{ .User.Username }}",
 | 
				
			||||||
 | 
					                "isAdmin":  "{{ .User.IsAdmin }}",
 | 
				
			||||||
 | 
					                "clusters": {{ .Clusters }},
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        </script>
 | 
				
			||||||
    </head>
 | 
					    </head>
 | 
				
			||||||
    <body  class="Site">
 | 
					    <body  class="Site">
 | 
				
			||||||
        <header>
 | 
					        <header id="svelte-header"></header>
 | 
				
			||||||
            <nav class="navbar navbar-expand-lg navbar-light fixed-top bg-light">
 | 
					 | 
				
			||||||
                <div class="container-fluid">
 | 
					 | 
				
			||||||
                    <a class="navbar-brand" href="/">
 | 
					 | 
				
			||||||
                        {{block "brand" .}}
 | 
					 | 
				
			||||||
                            <img alt="ClusterCockpit Logo" src="/img/logo.png" class="d-inline-block align-top">
 | 
					 | 
				
			||||||
                        {{end}}
 | 
					 | 
				
			||||||
                    </a>
 | 
					 | 
				
			||||||
                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
 | 
					 | 
				
			||||||
                        <span class="navbar-toggler-icon"></span>
 | 
					 | 
				
			||||||
                    </button>
 | 
					 | 
				
			||||||
                    <div class="collapse navbar-collapse" id="navbarSupportedContent">
 | 
					 | 
				
			||||||
                        {{block "navigation" .}}
 | 
					 | 
				
			||||||
                            <ul class="navbar-nav mr-auto">
 | 
					 | 
				
			||||||
                                {{block "navitem_joblist" .}}
 | 
					 | 
				
			||||||
                                    <li class="nav-item">
 | 
					 | 
				
			||||||
                                        <a class="nav-link fs-5" href="/monitoring/jobs/">
 | 
					 | 
				
			||||||
                                            <span class="cc-nav-text">Joblist</span>
 | 
					 | 
				
			||||||
                                            <i class="bi-card-list"></i>
 | 
					 | 
				
			||||||
                                        </a>
 | 
					 | 
				
			||||||
                                    </li>
 | 
					 | 
				
			||||||
                                {{end}}
 | 
					 | 
				
			||||||
                                {{if .Infos.admin }}
 | 
					 | 
				
			||||||
                                    {{block "navitem_analysis" .}}
 | 
					 | 
				
			||||||
                                        <li class="nav-item ">
 | 
					 | 
				
			||||||
                                            <a class="nav-link disabled fs-5" href="/monitoring/analysis/">
 | 
					 | 
				
			||||||
                                                <span class="cc-nav-text">Analysis</span>
 | 
					 | 
				
			||||||
                                                <i class="bi-graph-up"></i>
 | 
					 | 
				
			||||||
                                            </a>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    {{end}}
 | 
					 | 
				
			||||||
                                    {{block "navitem_systems" .}}
 | 
					 | 
				
			||||||
                                        <li class="nav-item ">
 | 
					 | 
				
			||||||
                                            <a class="nav-link disabled fs-5" href="/monitoring/systems/">
 | 
					 | 
				
			||||||
                                                <span class="cc-nav-text">Systems</span>
 | 
					 | 
				
			||||||
                                                <i class="bi-graph-up"></i>
 | 
					 | 
				
			||||||
                                            </a>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    {{end}}
 | 
					 | 
				
			||||||
                                    {{block "navitem_users" .}}
 | 
					 | 
				
			||||||
                                        <li class="nav-item">
 | 
					 | 
				
			||||||
                                            <a class="nav-link fs-5" href="/monitoring/users/">
 | 
					 | 
				
			||||||
                                                <span class="cc-nav-text">Users</span>
 | 
					 | 
				
			||||||
                                                <i class="bi-people-fill"></i>
 | 
					 | 
				
			||||||
                                            </a>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    {{end}}
 | 
					 | 
				
			||||||
                                    {{block "navitem_tags" .}}
 | 
					 | 
				
			||||||
                                        <li class="nav-item">
 | 
					 | 
				
			||||||
                                            <a class="nav-link fs-5" href="/monitoring/tags/">
 | 
					 | 
				
			||||||
                                                <span class="cc-nav-text">Tags</span>
 | 
					 | 
				
			||||||
                                                <i class="bi-tag-fill"></i>
 | 
					 | 
				
			||||||
                                            </a>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    {{end}}
 | 
					 | 
				
			||||||
                                {{else}}
 | 
					 | 
				
			||||||
                                    {{block "navitem_stats" .}}
 | 
					 | 
				
			||||||
                                        <li class="nav-item">
 | 
					 | 
				
			||||||
                                            <a class="nav-link fs-5" href="/monitoring/user/admin">
 | 
					 | 
				
			||||||
                                                <span class="cc-nav-text">Statistics</span>
 | 
					 | 
				
			||||||
                                                <i class="bi-bar-chart-line-fill"></i>
 | 
					 | 
				
			||||||
                                            </a>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    {{end}}
 | 
					 | 
				
			||||||
                                {{end}}
 | 
					 | 
				
			||||||
                            </ul>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                            {{if .Infos.loginId }}
 | 
					 | 
				
			||||||
                                <div class="d-flex align-items-end">
 | 
					 | 
				
			||||||
                                    <ul class="navbar-nav ml-auto">
 | 
					 | 
				
			||||||
                                        <li class="nav-item">
 | 
					 | 
				
			||||||
                                            <form method="post" action="/logout">
 | 
					 | 
				
			||||||
                                                <button type="submit" class="btn btn-link nav-link fs-5">
 | 
					 | 
				
			||||||
                                                    <span class="cc-nav-text">{{ .Infos.loginId }} Logout</span>
 | 
					 | 
				
			||||||
                                                    <i class="bi-box-arrow-right"></i>
 | 
					 | 
				
			||||||
                                                </button>
 | 
					 | 
				
			||||||
                                            </form>
 | 
					 | 
				
			||||||
                                        </li>
 | 
					 | 
				
			||||||
                                    </ul>
 | 
					 | 
				
			||||||
                                    <form class="d-flex my-0" onsubmit="this.action='/search';">
 | 
					 | 
				
			||||||
                                        {{if .Infos.admin }}
 | 
					 | 
				
			||||||
                                            <input class="form-control me-2" type="search" name="searchId" placeholder="jobId / userId" id="searchId" aria-label="Search">
 | 
					 | 
				
			||||||
                                        {{else}}
 | 
					 | 
				
			||||||
                                            <input class="form-control me-2" type="search" name="searchId" placeholder="jobId" id="searchId" aria-label="Search">
 | 
					 | 
				
			||||||
                                        {{end}}
 | 
					 | 
				
			||||||
                                        <button class="btn btn-outline-success fs-6" type="submit">Search</button>
 | 
					 | 
				
			||||||
                                    </form>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            {{end}}
 | 
					 | 
				
			||||||
                        {{end}}
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </nav>
 | 
					 | 
				
			||||||
        </header>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <main class="Site-content">
 | 
					        <main class="Site-content">
 | 
				
			||||||
            <div class="container">
 | 
					            <div class="container">
 | 
				
			||||||
@@ -127,6 +42,7 @@
 | 
				
			|||||||
        {{end}}
 | 
					        {{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {{block "javascript" .}}
 | 
					        {{block "javascript" .}}
 | 
				
			||||||
 | 
					            <script src='/build/header.js'></script>
 | 
				
			||||||
        {{end}}
 | 
					        {{end}}
 | 
				
			||||||
    </body>
 | 
					    </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{{define "content"}}
 | 
					{{define "content"}}
 | 
				
			||||||
<div class="row">
 | 
					<div class="row">
 | 
				
			||||||
    <div class="col-8">
 | 
					    <div class="col">
 | 
				
			||||||
        <h2>Clusters</h2>
 | 
					        <h2>Clusters</h2>
 | 
				
			||||||
        <table class="table">
 | 
					        <table class="table">
 | 
				
			||||||
            <thead>
 | 
					            <thead>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,5 +38,7 @@
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'analysis';
 | 
				
			||||||
        const cluster = {{ .Infos.cluster }};
 | 
					        const cluster = {{ .Infos.cluster }};
 | 
				
			||||||
        const filterPresets = {{ .FilterPresets }};
 | 
					        const filterPresets = {{ .FilterPresets }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'job';
 | 
				
			||||||
        const jobInfos = {
 | 
					        const jobInfos = {
 | 
				
			||||||
            id: "{{ .Infos.id }}",
 | 
					            id: "{{ .Infos.id }}",
 | 
				
			||||||
            jobId: "{{ .Infos.jobId }}",
 | 
					            jobId: "{{ .Infos.jobId }}",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'jobs';
 | 
				
			||||||
        const filterPresets = {{ .FilterPresets }};
 | 
					        const filterPresets = {{ .FilterPresets }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = {{ .Infos.listType }}.toLowerCase() + 's';
 | 
				
			||||||
        const listType = {{ .Infos.listType }};
 | 
					        const listType = {{ .Infos.listType }};
 | 
				
			||||||
        const filterPresets = {{ .FilterPresets }};
 | 
					        const filterPresets = {{ .FilterPresets }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'node';
 | 
				
			||||||
        const infos = {{ .Infos }};
 | 
					        const infos = {{ .Infos }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'system';
 | 
				
			||||||
        const infos = {{ .Infos }};
 | 
					        const infos = {{ .Infos }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,9 @@
 | 
				
			|||||||
 | 
					{{define "javascript"}}
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'tags';
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					    <script src='/build/header.js'></script>
 | 
				
			||||||
 | 
					{{end}}
 | 
				
			||||||
{{define "content"}}
 | 
					{{define "content"}}
 | 
				
			||||||
    <div class="container">
 | 
					    <div class="container">
 | 
				
			||||||
        <div class="row  justify-content-center">
 | 
					        <div class="row  justify-content-center">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{define "javascript"}}
 | 
					{{define "javascript"}}
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
 | 
					        header.currentView = 'user';
 | 
				
			||||||
        const userInfos = {{ .Infos }};
 | 
					        const userInfos = {{ .Infos }};
 | 
				
			||||||
        const filterPresets = {{ .FilterPresets }};
 | 
					        const filterPresets = {{ .FilterPresets }};
 | 
				
			||||||
        const clusterCockpitConfig = {{ .Config }};
 | 
					        const clusterCockpitConfig = {{ .Config }};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ClusterCockpit/cc-backend/config"
 | 
				
			||||||
	"github.com/ClusterCockpit/cc-backend/log"
 | 
						"github.com/ClusterCockpit/cc-backend/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,13 +13,20 @@ var templatesDir string
 | 
				
			|||||||
var debugMode bool = os.Getenv("DEBUG") == "1"
 | 
					var debugMode bool = os.Getenv("DEBUG") == "1"
 | 
				
			||||||
var templates map[string]*template.Template = map[string]*template.Template{}
 | 
					var templates map[string]*template.Template = map[string]*template.Template{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type User struct {
 | 
				
			||||||
 | 
						Username string // Username of the currently logged in user
 | 
				
			||||||
 | 
						IsAdmin  bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Page struct {
 | 
					type Page struct {
 | 
				
			||||||
	Title         string
 | 
						Title         string                 // Page title
 | 
				
			||||||
	Error         string
 | 
						Error         string                 // For generic use (e.g. the exact error message on /login)
 | 
				
			||||||
	Info          string
 | 
						Info          string                 // For generic use (e.g. "Logout successfull" on /login)
 | 
				
			||||||
	FilterPresets map[string]interface{}
 | 
						User          User                   // Information about the currently logged in user
 | 
				
			||||||
	Infos         map[string]interface{}
 | 
						Clusters      []string               // List of all clusters for use in the Header
 | 
				
			||||||
	Config        map[string]interface{}
 | 
						FilterPresets map[string]interface{} // For pages with the Filter component, this can be used to set initial filters.
 | 
				
			||||||
 | 
						Infos         map[string]interface{} // For generic use (e.g. username for /monitoring/user/<id>, job id for /monitoring/job/<id>)
 | 
				
			||||||
 | 
						Config        map[string]interface{} // UI settings for the currently logged in user (e.g. line width, ...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
@@ -58,6 +66,12 @@ func Render(rw http.ResponseWriter, r *http.Request, file string, page *Page) {
 | 
				
			|||||||
		t = template.Must(template.ParseFiles(templatesDir+"base.tmpl", templatesDir+file))
 | 
							t = template.Must(template.ParseFiles(templatesDir+"base.tmpl", templatesDir+file))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if page.Clusters == nil {
 | 
				
			||||||
 | 
							for _, c := range config.Clusters {
 | 
				
			||||||
 | 
								page.Clusters = append(page.Clusters, c.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := t.Execute(rw, page); err != nil {
 | 
						if err := t.Execute(rw, page); err != nil {
 | 
				
			||||||
		log.Errorf("template error: %s", err.Error())
 | 
							log.Errorf("template error: %s", err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user