blob: e844b1b9e6ee6e5eb42f582babdcd271b71f6875 [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"crypto/hmac"
"encoding/base64"
"errors"
"fmt"
"net/http"
"v.io/x/ref/services/allocator"
)
func handleHome(ss *serverState, rs *requestState) error {
ctx := ss.ctx
instances, err := serverInstances(ctx, rs.email)
if err != nil {
return fmt.Errorf("list error: %v", err)
}
type instanceArg struct {
Instance allocator.Instance
DestroyURL,
DebugURL,
DashboardURL string
}
tmplArgs := struct {
AssetsPrefix,
ServerName,
Email,
CreateURL,
Message string
Instances []instanceArg
}{
AssetsPrefix: ss.args.staticAssetsPrefix,
ServerName: ss.args.serverName,
Email: rs.email,
CreateURL: makeURL(ctx, routeCreate, params{paramCSRF: rs.csrfToken}),
Message: rs.r.FormValue(paramMessage),
}
for _, instance := range instances {
tmplArgs.Instances = append(tmplArgs.Instances, instanceArg{
Instance: instance,
DestroyURL: makeURL(ctx, routeDestroy, params{paramInstance: instance.Handle, paramCSRF: rs.csrfToken}),
DashboardURL: makeURL(ctx, routeDashboard, params{paramInstance: instance.Handle}),
DebugURL: makeURL(
ctx,
routeDebug+"/",
params{
paramInstance: instance.Handle,
paramMountName: instance.MountName,
paramHMAC: base64.URLEncoding.EncodeToString(computeHMAC(instance.Handle, instance.MountName))}),
})
}
if err := ss.args.assets.executeTemplate(rs.w, homeTmpl, tmplArgs); err != nil {
return fmt.Errorf("failed to render home template: %v", err)
}
return nil
}
func handleCreate(ss *serverState, rs *requestState) error {
ctx := ss.ctx
instance, err := create(ctx, rs.email, ss.args.baseBlessings, ss.args.baseBlessingNames)
if err != nil {
return fmt.Errorf("create failed: %v", err)
}
redirectTo := makeURL(ctx, routeHome, params{paramMessage: "created " + instance})
http.Redirect(rs.w, rs.r, redirectTo, http.StatusFound)
return nil
}
func handleDestroy(ss *serverState, rs *requestState) error {
ctx := ss.ctx
instance := rs.r.FormValue(paramInstance)
if instance == "" {
return fmt.Errorf("parameter %q required for instance name", paramInstance)
}
if err := destroy(ctx, rs.email, instance); err != nil {
return fmt.Errorf("destroy failed: %v", err)
}
redirectTo := makeURL(ctx, routeHome, params{paramMessage: "destroyed " + instance})
http.Redirect(rs.w, rs.r, redirectTo, http.StatusFound)
return nil
}
func handleDebug(ss *serverState, rs *requestState, debugBrowserServeMux *http.ServeMux) error {
instance := rs.r.FormValue(paramInstance)
if instance == "" {
return fmt.Errorf("parameter %q required for instance name", paramInstance)
}
mountName := rs.r.FormValue(paramMountName)
if mountName == "" {
return fmt.Errorf("parameter %q required for instance mount name", paramMountName)
}
hmacBase64 := rs.r.FormValue(paramHMAC)
if hmacBase64 == "" {
return fmt.Errorf("parameter %q required for name signature", paramHMAC)
}
hmacSignature, err := base64.URLEncoding.DecodeString(hmacBase64)
if err != nil {
return fmt.Errorf("invalid signature: %v", err)
}
if !hmac.Equal(hmacSignature, computeHMAC(instance, mountName)) {
return errors.New("mismatching signature")
}
if err := checkOwner(ss.ctx, rs.email, instance); err != nil {
return err
}
http.StripPrefix(routeDebug, debugBrowserServeMux).ServeHTTP(rs.w, rs.r)
return nil
}