<commit_before>package multipass

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/mholt/caddy/caddyhttp/httpserver"

	jose "gopkg.in/square/go-jose.v1"
)

// Portable errors
var (
	ErrInvalidToken = errors.New("invalid token")
)

// Auth wraps a Multipass instance to be used by the caddy web server.
type Auth struct {
	*Multipass
	Next httpserver.Handler
}

// Rule holds the directive options parsed from a Caddyfile.
type Rule struct {
	Basepath  string
	Expires   time.Duration
	Resources []string
	Handles   []string

	SMTPAddr, SMTPUser, SMTPPass string
	MailFrom, MailTmpl           string
}

// Multipass implements the http.Handler interface which can handle
// authentication and authorization of users and resources using signed JWT.
type Multipass struct {
	Resources []string
	Basepath  string
	SiteAddr  string
	Expires   time.Duration

	Handler HandleService
	signer  jose.Signer
	key     *rsa.PrivateKey
	tmpl    *template.Template
	mux     *http.ServeMux
}

// NewMultipassFromRule return a new instance of Multipass from the given Rule.
// Returned error will most likely be parser errors.
func NewMultipassFromRule(r Rule) (*Multipass, error) {
	m, err := NewMultipass()
	if err != nil {
		return nil, err
	}
	if len(r.Resources) > 0 {
		m.Resources = r.Resources
	}
	if len(r.Basepath) > 0 {
		m.Basepath = path.Join("/", r.Basepath)
	}
	if r.Expires > 0 {
		m.Expires = r.Expires
	}

	// Set EmailHandler options
	opt := &EmailOptions{
		r.SMTPAddr,
		r.SMTPUser,
		r.SMTPPass,
		r.MailFrom,
	}
	handler, err := NewEmailHandler(opt)
	if err != nil {
		return nil, err
	}

	for _, handle := range r.Handles {
		handler.Register(handle)
	}
	m.Handler = handler

	mux := http.NewServeMux()
	mux.HandleFunc(path.Join(m.Basepath, "/"), m.rootHandler)
	mux.HandleFunc(path.Join(m.Basepath, "/login"), m.loginHandler)
	mux.HandleFunc(path.Join(m.Basepath, "/confirm"), m.confirmHandler)
	mux.HandleFunc(path.Join(m.Basepath, "/signout"), m.signoutHandler)
	mux.HandleFunc(path.Join(m.Basepath, "/pub.cer"), m.publickeyHandler)
	m.mux = mux

	tmpl, err := loadTemplates()
	if err != nil {
		return nil, err
	}
	m.tmpl = tmpl

	return m, nil
}

// NewMultipass returns a new instance of Multipass with reasonalble defaults
// like a 2048 bit RSA key pair, /multipass as basepath, 24 hours before a
// token will expire.
func NewMultipass() (*Multipass, error) {
	pk, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	signer, err := jose.NewSigner(jose.PS512, pk)
	if err != nil {
		return nil, err
	}
	return &Multipass{
		Resources: []string{"/"},
		Basepath:  "/multipass",
		Expires:   time.Hour * 24,
		key:       pk,
		signer:    signer,
	}, nil
}

// Claims are part of the JSON web token
type Claims struct {<commit_msg>Refactor NewMultipass() to include basic initialization<commit_after>package multipass

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/mholt/caddy/caddyhttp/httpserver"

	jose "gopkg.in/square/go-jose.v1"
)

// Portable errors
var (
	ErrInvalidToken = errors.New("invalid token")
)

// Auth wraps a Multipass instance to be used by the caddy web server.
type Auth struct {
	*Multipass
	Next httpserver.Handler
}

// Rule holds the directive options parsed from a Caddyfile.
type Rule struct {
	Basepath  string
	Expires   time.Duration
	Resources []string
	Handles   []string

	SMTPAddr, SMTPUser, SMTPPass string
	MailFrom, MailTmpl           string
}

// Multipass implements the http.Handler interface which can handle
// authentication and authorization of users and resources using signed JWT.
type Multipass struct {
	Resources []string
	Basepath  string
	SiteAddr  string
	Expires   time.Duration

	Handler HandleService
	signer  jose.Signer
	key     *rsa.PrivateKey
	tmpl    *template.Template
	mux     *http.ServeMux
}

// NewMultipassFromRule return a new instance of Multipass from the given Rule.
// Returned error will most likely be parser errors.
func NewMultipassFromRule(r Rule) (*Multipass, error) {
	m, err := NewMultipass(r.Basepath)
	if err != nil {
		return nil, err
	}

	if len(r.Resources) > 0 {
		m.Resources = r.Resources
	}
	if r.Expires > 0 {
		m.Expires = r.Expires
	}

	// Set EmailHandler options
	opt := &EmailOptions{
		r.SMTPAddr,
		r.SMTPUser,
		r.SMTPPass,
		r.MailFrom,
	}
	handler, err := NewEmailHandler(opt)
	if err != nil {
		return nil, err
	}
	for _, handle := range r.Handles {
		handler.Register(handle)
	}
	m.Handler = handler

	return m, nil
}

// NewMultipass returns a new instance of Multipass with reasonalble defaults
// like a 2048 bit RSA key pair, /multipass as basepath, 24 hours before a
// token will expire.
func NewMultipass(basepath string) (*Multipass, error) {
	// Absolute the given basepath or set a default
	if len(basepath) > 0 {
		basepath = path.Join("/", basepath)
	} else {
		basepath = "/multipass"
	}

	// Generate the RSA key pari
	pk, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	signer, err := jose.NewSigner(jose.PS512, pk)
	if err != nil {
		return nil, err
	}

	// Load HTML templates
	tmpl, err := loadTemplates()
	if err != nil {
		return nil, err
	}

	m := &Multipass{
		Resources: []string{"/"},
		Basepath:  basepath,
		Expires:   time.Hour * 24,
		key:       pk,
		signer:    signer,
		tmpl:      tmpl,
	}

	// Create the router
	mux := http.NewServeMux()
	mux.HandleFunc(path.Join(basepath, "/"), m.rootHandler)
	mux.HandleFunc(path.Join(basepath, "/login"), m.loginHandler)
	mux.HandleFunc(path.Join(basepath, "/confirm"), m.confirmHandler)
	mux.HandleFunc(path.Join(basepath, "/signout"), m.signoutHandler)
	mux.HandleFunc(path.Join(basepath, "/pub.cer"), m.publickeyHandler)
	m.mux = mux

	return m, nil
}

// Claims are part of the JSON web token
type Claims struct {
{'fraction_non_alphanumeric': 0.1183275491654272, 'fraction_numerical': 0.0072715253677078165, 'mean_word_length': 3.499628252788104, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3892390', 'n_tokens_mistral': 2301, 'n_tokens_neox': 2189, 'n_words': 616}