view

package
v2.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2022 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package view provides customisable abstractions over collections. Changes to an underlying collection are reflected in its views, and vice-versa.

Example (UrlQuery)
package main

import (
	"fmt"
	"net/url"
	"path"

	"github.com/acarl005/stripansi"
	"github.com/tawesoft/golib/v2/view"
)

// Untrusted applies visible runtime tainting of untrusted values (as
// recommended by OWASP). This means we are unable to use an untrusted
// input accidentally, and must first access it using an escape function.
type Untrusted struct {
	value string
}

func (u Untrusted) Raw() string {
	return u.value
}

func (u Untrusted) Escape(esc ...func(x string) string) string {
	result := u.value
	for _, escaper := range esc {
		result = escaper(result)
	}
	return result
}

func UntrustedString(x string) Untrusted {
	return Untrusted{x}
}

func main() {

	// Assume an input URL query from an intrusted source
	v := url.Values{} // map[string][]string
	v.Set("name", "Ava")
	v.Add("friend", "Jess")
	v.Add("friend", "Sarah")
	v.Add("friend", "Zoe")
	v.Add("filename", "../index.html") // malicious input
	v.Add("fbclid", "nonsense we don't care about")
	// v.Encode() == ...

	onlyRecognised := func(k string, _ []string) bool {
		switch k {
		case "name":
			return true
		case "friend":
			return true
		case "filename":
			return true
		}
		return false
	}

	// Construct a view that can read keys and values from the input query,
	// wrapping them in the Untrusted type. Additionally, we filter only
	// the keys we care about.
	//
	// Like the url.Values.Get method, returns only the first value associated
	// with the given key.
	taintedValues := view.FromMap[string, []string, Untrusted, Untrusted](
		v,
		onlyRecognised,
		view.Keyer[string, Untrusted]{
			To:   func(k string) Untrusted { return UntrustedString(k) },
			From: func(k Untrusted) string { return k.Raw() },
		},
		view.Valuer[[]string, Untrusted]{
			To: func(x []string) Untrusted {
				if len(x) >= 1 {
					return UntrustedString(x[0])
				}
				return Untrusted{}
			},
			// From: omitted as we don't need to map a value back
		},
	)

	if name, ok := taintedValues.Get(UntrustedString("name")); ok {
		fmt.Printf("Hi %s!\n", name.Escape(stripansi.Strip))
	} else {
		fmt.Printf("Hello anonymous!\n")
	}

	if friend, ok := taintedValues.Get(UntrustedString("friend")); ok {
		fmt.Printf("I see that you're friends with %s!\n", friend.Escape(stripansi.Strip))
	}

	if filename, ok := taintedValues.Get(UntrustedString("filename")); ok {
		// NOTE: this is an example only and is not complete as there are still
		// other ways the path could be unsafe.
		fmt.Printf("Safe filename: %s\n", filename.Escape(path.Clean, path.Base, stripansi.Strip))
	} else {
		fmt.Printf("No file specified.\n")
	}

	if _, ok := taintedValues.Get(UntrustedString("fbclid")); ok {
		panic("Didn't expect to see this!")
	}

}
Output:

Hi Ava!
I see that you're friends with Jess!
Safe filename: index.html

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Keyer

type Keyer[A comparable, B comparable] struct {
	To   func(A) B
	From func(B) A
}

Keyer defines a mapping between comparable types A and B.

type Valuer

type Valuer[A any, B any] struct {
	To   func(A) B
	From func(B) A
}

Valuer defines a mapping between any types A and B.

type View

type View[K comparable, V any] interface {
	Get(K) (V, bool)
	Set(K, V)
	Delete(K)
	Iter() iter.It[iter.Pair[K, V]]
}

View is an abstraction over a collection. In the case of a slice, the key is an int.

func FromMap

func FromMap[K comparable, V any, ToK comparable, ToV any](
	m map[K]V,
	filterer func(K, V) bool,
	keyer Keyer[K, ToK],
	valuer Valuer[V, ToV],
) View[ToK, ToV]

FromMap returns a View from a Go map collection type.

Filterer defines a function that "hides" the given value from the view when accessed through Get or Iter. It is implemented in terms of the types of the underlying collection, and should not implement the keyer or valuer logic.

Keyer defines a mapping to and from the keys in the underlying collection to the view.

Valuer defines a mapping to and from the values in the underlying collection to the view.

func FromSlice

func FromSlice[V any, ToV any](
	s []V,
	filterer func(int, V) bool,
	valuer Valuer[V, ToV],
) View[int, ToV]

FromSlice returns a View from a Go list collection type.

Filterer defines a function that "hides" the given value from the view when accessed through Get or Iter. It is implemented in terms of the types of the underlying collection, and should not implement the keyer or valuer logic.

Valuer defines a mapping to and from the values in the underlying collection to the view.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL