func notificationPage(w http.ResponseWriter, panelType, title string, err interface{}, btnType, btnPath, btnText string) {
	data := templates.NotificationPage{
		PanelColor: panelType,
		Title:      title,
		Message:    err,
		BtnColor:   btnType,
		LinkHref:   btnPath,
		BtnText:    btnText,
	}
	templates.Load(w, "notifications", data)
}
notificationPage is used to show html page for errors
same as pages.notificationPage but have to have separate function b/c of dependency circle
package users
import (
	"context"
	"database/sql"
	"errors"
	"net/http"
	"strconv"
	"github.com/coreymgilmore/stripe-appengine-frontend/pkgs/sqliteutils"
	"cloud.google.com/go/datastore"
	"github.com/coreymgilmore/stripe-appengine-frontend/pkgs/datastoreutils"
	"github.com/coreymgilmore/stripe-appengine-frontend/pkgs/output"
	"github.com/coreymgilmore/stripe-appengine-frontend/pkgs/templates"
	"google.golang.org/api/iterator"
)
const (
	adminUsername = "administrator"
	minPwdLength = 10
)
var (
	ErrAdminDoesNotExist   = errors.New("users: admin user does not exist")
	ErrUserDoesNotExist    = errors.New("users: user does not exist")
	errUserAlreadyExists   = errors.New("users: user already exists")
	errPasswordsDoNotMatch = errors.New("users: passwords do not match")
	errPasswordTooShort    = errors.New("users: password too short")
	errSessionMismatch        = errors.New("users: session mismatch")
	errCannotUpdateSelf       = errors.New("users: cannot update yourself")
	errCannotUpdateSuperAdmin = errors.New("users: cannot update super admin")
)
type User struct {
	Username      string `json:"username"`          
	Password      string `json:"-"`                 
	AddCards      bool   `json:"add_cards"`         
	RemoveCards   bool   `json:"remove_cards"`      
	ChargeCards   bool   `json:"charge_cards"`      
	ViewReports   bool   `json:"view_reports"`      
	Administrator bool   `json:"is_admin"`          
	Active        bool   `json:"is_active"`         
	Created       string `json:"datetime_created"`  
	ID int64 `json:"sqlite_user_id"`
}
type userList struct {
	ID       int64  `json:"id"`        
	Username string `json:"username"`  
}
func GetAll(w http.ResponseWriter, r *http.Request) {
	list := []userList{}
	if sqliteutils.Config.UseSQLite {
		c := sqliteutils.Connection
		q := `
			SELECT ID, Username
			FROM ` + sqliteutils.TableUsers
		err := c.Select(&list, q)
		if err != nil {
			output.Error(err, "Error retreiving list of users from sqlite.", w)
			return
		}
	} else {
		c := r.Context()
		client, err := datastoreutils.Connect(c)
		if err != nil {
			output.Error(err, "Could not connect to datastore", w)
			return
		}
		q := datastore.NewQuery(datastoreutils.EntityUsers).Order("Username").Project("Username")
		i := client.Run(c, q)
		for {
			one := User{}
			key, err := i.Next(&one)
			if err == iterator.Done {
				break
			}
			if err != nil {
				output.Error(err, "Error retrieving list of users from datastore.", w)
				return
			}
			l := userList{
				Username: one.Username,
				ID:       key.ID,
			}
			list = append(list, l)
		}
	}
	output.Success("userList", list, w)
}
func GetOne(w http.ResponseWriter, r *http.Request) {
	userIDInt, _ := strconv.ParseInt(r.FormValue("userId"), 10, 64)
	c := r.Context()
	data, err := Find(c, userIDInt)
	if err != nil {
		output.Error(err, "Could not look up user's data.", w)
		return
	}
	output.Success("findUser", data, w)
}
func DoesAdminExist(r *http.Request) error {
	c := r.Context()
	_, _, err := getDataByUsername(c, adminUsername)
	if err == nil {
		return nil
	} else if err == ErrUserDoesNotExist {
		return ErrAdminDoesNotExist
	} else {
		return err
	}
}
func getDataByUsername(c context.Context, username string) (int64, User, error) {
	u := User{}
	if sqliteutils.Config.UseSQLite {
		c := sqliteutils.Connection
		q := `
			SELECT *
			FROM ` + sqliteutils.TableUsers + `
			WHERE Username = ?
		`
		err := c.Get(&u, q, username)
		if err == sql.ErrNoRows {
			return 0, u, ErrUserDoesNotExist
		} else if err != nil {
			return 0, u, err
		}
	} else {
		client, err := datastoreutils.Connect(c)
		if err != nil {
			return 0, u, err
		}
		q := datastore.NewQuery(datastoreutils.EntityUsers).Filter("Username = ", username).Limit(1)
		i := client.Run(c, q)
		var numResults int
		var fullKey *datastore.Key
		for {
			var tempUserData User
			tempKey, err := i.Next(&tempUserData)
			if err == iterator.Done {
				break
			}
			if err != nil {
				return 0, u, err
			}
			fullKey = tempKey
			u = tempUserData
			numResults++
		}
		if numResults == 0 {
			return 0, u, ErrUserDoesNotExist
		}
		u.ID = fullKey.ID
	}
	return u.ID, u, nil
}
func Find(c context.Context, userID int64) (u User, err error) {
	if sqliteutils.Config.UseSQLite {
		c := sqliteutils.Connection
		q := `
			SELECT * 
			FROM ` + sqliteutils.TableUsers + `
			WHERE ID = ?
		`
		err = c.Get(&u, q, userID)
	} else {
		client, innerErr := datastoreutils.Connect(c)
		if innerErr != nil {
			err = innerErr
			return
		}
		key := datastoreutils.GetKeyFromID(datastoreutils.EntityUsers, userID)
		innerErr = client.Get(c, key, &u)
		if innerErr != nil {
			err = innerErr
		}
	}
	return
}