AppManager: Report env vars as part of access

Change-Id: Ibc488b86b4b3968efb00a8ef0eda3c7f0f1c4a41
diff --git a/core/auth/proxy/unauthorized.html b/core/auth/proxy/unauthorized.html
index 28c8913..c57f87c 100644
--- a/core/auth/proxy/unauthorized.html
+++ b/core/auth/proxy/unauthorized.html
@@ -15,7 +15,7 @@
             <p>
                 Only members of
                 {{ range $index, $group := .Groups }}
-                <a href="{{ $.MembershipPublicAddr }}/group/{{ $group.Id }}">{{ $group.Title }}</a>{{ if not (IsLast $index $.Groups) }},{{ end }}
+                <a href="{{ $.MembershipPublicAddr }}/group/{{ $group.Id }}">{{ $group.Title }}</a> 
                 {{ end }}
                 are authorized to access this page.
             </p>
diff --git a/core/installer/app.go b/core/installer/app.go
index c9c7ced..656b992 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -40,6 +40,7 @@
 	UDP        *AccessUDP
 	PostgreSQL *AccessPostgreSQL
 	MongoDB    *AccessMongoDB
+	EnvVar     *AccessEnvVar
 }
 
 func (a Access) MarshalJSON() ([]byte, error) {
@@ -93,6 +94,14 @@
 		}{*a.MongoDB, a.Type, a.Name}); err != nil {
 			return nil, err
 		}
+	case "env_var":
+		if err := json.NewEncoder(&buf).Encode(struct {
+			AccessEnvVar
+			Type string `json:"type"`
+			Name string `json:"name"`
+		}{*a.EnvVar, a.Type, a.Name}); err != nil {
+			return nil, err
+		}
 	default:
 		panic("MUST NOT REACH!")
 	}
@@ -135,6 +144,10 @@
 	Password string `json:"password"`
 }
 
+type AccessEnvVar struct {
+	Var string `json:"var"`
+}
+
 type EnvVar struct {
 	Name  string `json:"name"`
 	Value string `json:"value"`
@@ -408,6 +421,9 @@
 	if err != nil {
 		return cueApp{}, fmt.Errorf(errors.Details(err, nil))
 	}
+	if err := config.Err(); err != nil {
+		return cueApp{}, fmt.Errorf(errors.Details(err, nil))
+	}
 	return newCueApp(config, data)
 }
 
@@ -657,6 +673,14 @@
 				}
 				ret = append(ret, Access{Type: "mongodb", Name: nn, MongoDB: &q})
 			}
+		case "env_var":
+			{
+				var q AccessEnvVar
+				if err := i.Value().Decode(&q); err != nil {
+					return nil, err
+				}
+				ret = append(ret, Access{Type: "env_var", Name: nn, EnvVar: &q})
+			}
 		}
 	}
 	for _, sub := range []string{"ingress", "postgresql", "mongodb", "services", "vm"} {
@@ -707,9 +731,9 @@
 func NewDodoApp(appCfg []byte) (EnvApp, error) {
 	return NewCueEnvApp(CueAppData{
 		"app.cue":  appCfg,
-		"base.cue": []byte(cueBaseConfig),
+		"base.cue": cueBaseConfig,
 		"dodo.cue": dodoAppCue,
-		"env.cue":  []byte(cueEnvAppGlobal),
+		"env.cue":  cueEnvAppGlobal,
 	})
 }
 
diff --git a/core/installer/app_configs/dodo_app.cue b/core/installer/app_configs/dodo_app.cue
index 89c5944..3fb651f 100644
--- a/core/installer/app_configs/dodo_app.cue
+++ b/core/installer/app_configs/dodo_app.cue
@@ -1027,9 +1027,15 @@
 	...
 }
 
+#EnvVarAccess: #Access & {
+	type: "env_var"
+	name: string
+	var:  string
+}
+
 #Service: {
 	svc: name: string
-	access: [...(#TCPAccess | #UDPAccess)]
+	access: [...(#TCPAccess | #UDPAccess | #EnvVarAccess)]
 	access: [
 		for i in openPort {
 			name: svc.name
@@ -1037,6 +1043,11 @@
 			host: i.network.domain
 			port: i.port
 		},
+		for i in svc.lastCmdEnv {
+			name: svc.name
+			type: "env_var"
+			var:  i
+		},
 	]
 	openPort: [...#PortForward]
 }
diff --git a/core/installer/schema.go b/core/installer/schema.go
index 12a79b0..d8b3a74 100644
--- a/core/installer/schema.go
+++ b/core/installer/schema.go
@@ -47,6 +47,7 @@
 	fields: []Field{
 		Field{"enabled", basicSchema{"Enabled", KindBoolean, false, nil}},
 		Field{"groups", basicSchema{"Groups", KindString, false, nil}},
+		Field{"noAuthPathPatterns", basicSchema{"Optional Auth Paths", KindArrayString, false, nil}},
 	},
 	advanced: false,
 }
diff --git a/core/installer/server/launcher/server.go b/core/installer/server/launcher/server.go
index e4483e1..c68f11c 100644
--- a/core/installer/server/launcher/server.go
+++ b/core/installer/server/launcher/server.go
@@ -132,7 +132,8 @@
 }
 
 func shortenURL(url, domain string) string {
-	return strings.Replace(url, domain, "..", 1)
+	return url
+	// return strings.Replace(url, domain, "..", 1)
 }
 
 func getLoggedInUser(r *http.Request) (string, error) {