I do not have more time to update the update to the company today, but i believe this is already a good amount of work for a commit. The company is going to be used for row level security, as users will only have access to the data from companies they are granted access, by virtue of being in the company_user relation. I did not know how add a row level security policy to the company_user because i needed the to select on the same relation and this is not allowed, because it would create an infinite loop. Had to add the vat, pg_libphonenumber, and uri extensions in order to validate VAT identification numbers, phone numbers, and URIs, repectively. These libraries are not in Debian, but i created packages for them all in https://dev.tandem.ws/tandem.
106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
package pkg
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
ContextCompanyKey = "numerus-company"
|
|
)
|
|
|
|
type Company struct {
|
|
Id int
|
|
Slug string
|
|
}
|
|
|
|
func CompanyHandler(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
slug := r.URL.Path
|
|
if idx := strings.IndexByte(slug, '/'); idx >= 0 {
|
|
slug = slug[:idx]
|
|
}
|
|
|
|
conn := getConn(r)
|
|
company := &Company{
|
|
Slug: slug,
|
|
}
|
|
err := conn.QueryRow(r.Context(), "select company_id from company where slug = $1", slug).Scan(&company.Id)
|
|
if err != nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
ctx := context.WithValue(r.Context(), ContextCompanyKey, company)
|
|
r = r.WithContext(ctx)
|
|
|
|
// Same as StripPrefix
|
|
p := strings.TrimPrefix(r.URL.Path, slug)
|
|
rp := strings.TrimPrefix(r.URL.RawPath, slug)
|
|
if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
|
|
r2 := new(http.Request)
|
|
*r2 = *r
|
|
r2.URL = new(url.URL)
|
|
*r2.URL = *r.URL
|
|
if p == "" {
|
|
r2.URL.Path = "/"
|
|
} else {
|
|
r2.URL.Path = p
|
|
}
|
|
r2.URL.RawPath = rp
|
|
next.ServeHTTP(w, r2)
|
|
} else {
|
|
http.NotFound(w, r)
|
|
}
|
|
})
|
|
}
|
|
|
|
func getCompany(r *http.Request) *Company {
|
|
company := r.Context().Value(ContextCompanyKey)
|
|
if company == nil {
|
|
return nil
|
|
}
|
|
return company.(*Company)
|
|
}
|
|
|
|
type TaxDetailsPage struct {
|
|
Title string
|
|
BusinessName string
|
|
VATIN string
|
|
TradeName string
|
|
Phone string
|
|
Email string
|
|
Web string
|
|
Address string
|
|
City string
|
|
Province string
|
|
PostalCode string
|
|
Country string
|
|
}
|
|
|
|
func CompanyTaxDetailsHandler() http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
locale := getLocale(r)
|
|
page := &TaxDetailsPage{
|
|
Title: pgettext("title", "Tax Details", locale),
|
|
}
|
|
company := mustGetCompany(r)
|
|
conn := getConn(r)
|
|
err := conn.QueryRow(r.Context(), "select business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country from company where company_id = $1", company.Id).Scan(&page.BusinessName, &page.VATIN, &page.TradeName, &page.Phone, &page.Email, &page.Web, &page.Address, &page.City, &page.Province, &page.PostalCode, &page.Country);
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
mustRenderAppTemplate(w, r, "tax-details.html", page)
|
|
});
|
|
}
|
|
|
|
func mustGetCompany(r *http.Request) *Company {
|
|
company := getCompany(r)
|
|
if company == nil {
|
|
panic(errors.New("company: required but not found"))
|
|
}
|
|
return company;
|
|
}
|