Format all source files.

This commit is contained in:
Eli Ribble 2025-11-06 22:31:51 +00:00
parent f7ad8b9c5f
commit fa89e0719f
No known key found for this signature in database
7 changed files with 142 additions and 138 deletions

View file

@ -15,9 +15,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/aarondl/opt/omit"
"github.com/Gleipnir-Technology/arcgis-go" "github.com/Gleipnir-Technology/arcgis-go"
"github.com/Gleipnir-Technology/nidus-sync/models" "github.com/Gleipnir-Technology/nidus-sync/models"
"github.com/aarondl/opt/omit"
) )
var CodeVerifier string = "random_secure_string_min_43_chars_long_should_be_stored_in_session" var CodeVerifier string = "random_secure_string_min_43_chars_long_should_be_stored_in_session"
@ -65,8 +65,8 @@ func generateCodeVerifier() string {
func getArcgisUserData(access_token string, expires time.Time, refresh_token string) { func getArcgisUserData(access_token string, expires time.Time, refresh_token string) {
client := arcgis.NewArcGIS( client := arcgis.NewArcGIS(
arcgis.AuthenticatorOAuth{ arcgis.AuthenticatorOAuth{
AccessToken: access_token, AccessToken: access_token,
Expires: expires, Expires: expires,
RefreshToken: refresh_token, RefreshToken: refresh_token,
}, },
) )
@ -78,7 +78,7 @@ func getArcgisUserData(access_token string, expires time.Time, refresh_token str
slog.Info("Got portals data", slog.Info("Got portals data",
slog.String("Username", portal.User.Username), slog.String("Username", portal.User.Username),
slog.String("ID", portal.ID)) slog.String("ID", portal.ID))
*/ */
search, err := client.Search("Fieldseeker") search, err := client.Search("Fieldseeker")
if err != nil { if err != nil {
slog.Error("Failed to get search FieldseekerGIS data", slog.String("err", err.Error())) slog.Error("Failed to get search FieldseekerGIS data", slog.String("err", err.Error()))
@ -87,7 +87,7 @@ func getArcgisUserData(access_token string, expires time.Time, refresh_token str
for _, result := range search.Results { for _, result := range search.Results {
slog.Info("Got result", slog.String("name", result.Name)) slog.Info("Got result", slog.String("name", result.Name))
//if result.Name == "FieldseekerGIS" { //if result.Name == "FieldseekerGIS" {
//slog.Info("Found Fieldseeker", slog.String("url", result.URL)) //slog.Info("Found Fieldseeker", slog.String("url", result.URL))
//} //}
} }
} }
@ -142,10 +142,10 @@ func handleOauthAccessCode(ctx context.Context, user *models.User, code string)
expires := futureUTCTimestamp(tokenResponse.ExpiresIn) expires := futureUTCTimestamp(tokenResponse.ExpiresIn)
setter := models.OauthTokenSetter{ setter := models.OauthTokenSetter{
AccessToken: omit.From(tokenResponse.AccessToken), AccessToken: omit.From(tokenResponse.AccessToken),
Expires: omit.From(expires), Expires: omit.From(expires),
RefreshToken: omit.From(tokenResponse.RefreshToken), RefreshToken: omit.From(tokenResponse.RefreshToken),
Username: omit.From(tokenResponse.Username), Username: omit.From(tokenResponse.Username),
} }
err = user.InsertUserOauthTokens(ctx, PGInstance.BobDB, &setter) err = user.InsertUserOauthTokens(ctx, PGInstance.BobDB, &setter)
if err != nil { if err != nil {

31
auth.go
View file

@ -8,20 +8,23 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"github.com/aarondl/opt/omit"
"github.com/Gleipnir-Technology/nidus-sync/enums" "github.com/Gleipnir-Technology/nidus-sync/enums"
"github.com/Gleipnir-Technology/nidus-sync/models" "github.com/Gleipnir-Technology/nidus-sync/models"
"github.com/Gleipnir-Technology/nidus-sync/sql" "github.com/Gleipnir-Technology/nidus-sync/sql"
"github.com/aarondl/opt/omit"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
type NoCredentialsError struct{} type NoCredentialsError struct{}
func (e NoCredentialsError) Error() string { return "No credentials were present in the request" } func (e NoCredentialsError) Error() string { return "No credentials were present in the request" }
type InvalidCredentials struct{} type InvalidCredentials struct{}
func (e InvalidCredentials) Error() string { return "No username with that password exists" } func (e InvalidCredentials) Error() string { return "No username with that password exists" }
type InvalidUsername struct{} type InvalidUsername struct{}
func (e InvalidUsername) Error() string { return "That username doesn't exist" } func (e InvalidUsername) Error() string { return "That username doesn't exist" }
func addUserSession(r *http.Request, user *models.User) { func addUserSession(r *http.Request, user *models.User) {
@ -85,10 +88,10 @@ func signupUser(username string, name string, password string) (*models.User, er
return nil, fmt.Errorf("Cannot signup user: %v", err) return nil, fmt.Errorf("Cannot signup user: %v", err)
} }
setter := models.UserSetter{ setter := models.UserSetter{
DisplayName: omit.From(name), DisplayName: omit.From(name),
PasswordHash: omit.From(passwordHash), PasswordHash: omit.From(passwordHash),
PasswordHashType: omit.From(enums.HashtypeBcrypt14), PasswordHashType: omit.From(enums.HashtypeBcrypt14),
Username: omit.From(username), Username: omit.From(username),
} }
u, err := models.Users.Insert(&setter).One(context.TODO(), PGInstance.BobDB) u, err := models.Users.Insert(&setter).One(context.TODO(), PGInstance.BobDB)
if err != nil { if err != nil {
@ -120,7 +123,7 @@ func validateUser(ctx context.Context, username string, password string) (*model
return nil, fmt.Errorf("Failed to query for user: %v", err) return nil, fmt.Errorf("Failed to query for user: %v", err)
} }
switch len(result) { switch len(result) {
case 0: case 0:
return nil, InvalidUsername{} return nil, InvalidUsername{}
case 1: case 1:
row := result[0] row := result[0]
@ -128,16 +131,16 @@ func validateUser(ctx context.Context, username string, password string) (*model
return nil, InvalidCredentials{} return nil, InvalidCredentials{}
} }
user := models.User{ user := models.User{
ID: row.ID, ID: row.ID,
ArcgisAccessToken: row.ArcgisAccessToken, ArcgisAccessToken: row.ArcgisAccessToken,
ArcgisLicense: row.ArcgisLicense, ArcgisLicense: row.ArcgisLicense,
ArcgisRefreshToken: row.ArcgisRefreshToken, ArcgisRefreshToken: row.ArcgisRefreshToken,
ArcgisRefreshTokenExpires: row.ArcgisRefreshTokenExpires, ArcgisRefreshTokenExpires: row.ArcgisRefreshTokenExpires,
ArcgisRole: row.ArcgisRole, ArcgisRole: row.ArcgisRole,
DisplayName: row.DisplayName, DisplayName: row.DisplayName,
Email: row.Email, Email: row.Email,
OrganizationID: row.OrganizationID, OrganizationID: row.OrganizationID,
Username: row.Username, Username: row.Username,
} }
return &user, nil return &user, nil
default: default:

View file

@ -23,7 +23,7 @@ import (
var embedMigrations embed.FS var embedMigrations embed.FS
type postgres struct { type postgres struct {
BobDB bob.DB BobDB bob.DB
PGXPool *pgxpool.Pool PGXPool *pgxpool.Pool
} }

View file

@ -88,7 +88,7 @@ func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
// Set the appropriate content type // Set the appropriate content type
w.Header().Set("Content-Type", "image/png") w.Header().Set("Content-Type", "image/png")
// Generate PNG and write directly to the response writer // Generate PNG and write directly to the response writer
png, err := qr.PNG(size) png, err := qr.PNG(size)
if err != nil { if err != nil {
@ -190,14 +190,13 @@ func postSignin(w http.ResponseWriter, r *http.Request) {
respondError(w, "Could not parse form", err, http.StatusBadRequest) respondError(w, "Could not parse form", err, http.StatusBadRequest)
return return
} }
username := r.FormValue("username") username := r.FormValue("username")
password := r.FormValue("password") password := r.FormValue("password")
slog.Info("Signin", slog.Info("Signin",
slog.String("username", username), slog.String("username", username),
slog.String("password", strings.Repeat("*", len(password)))) slog.String("password", strings.Repeat("*", len(password))))
_, err := signinUser(r, username, password) _, err := signinUser(r, username, password)
if err != nil { if err != nil {
@ -217,17 +216,17 @@ func postSignup(w http.ResponseWriter, r *http.Request) {
respondError(w, "Could not parse form", err, http.StatusBadRequest) respondError(w, "Could not parse form", err, http.StatusBadRequest)
return return
} }
username := r.FormValue("username") username := r.FormValue("username")
name := r.FormValue("name") name := r.FormValue("name")
password := r.FormValue("password") password := r.FormValue("password")
terms := r.FormValue("terms") terms := r.FormValue("terms")
slog.Info("Signup", slog.Info("Signup",
slog.String("username", username), slog.String("username", username),
slog.String("name", name), slog.String("name", name),
slog.String("password", strings.Repeat("*", len(password)))) slog.String("password", strings.Repeat("*", len(password))))
if terms != "on" { if terms != "on" {
slog.Error("Terms not agreed", slog.String("terms", terms)) slog.Error("Terms not agreed", slog.String("terms", terms))
http.Error(w, "You must agree to the terms to register", http.StatusBadRequest) http.Error(w, "You must agree to the terms to register", http.StatusBadRequest)

View file

@ -1,4 +1,5 @@
package main package main
import ( import (
"embed" "embed"
"fmt" "fmt"
@ -18,99 +19,100 @@ var embeddedStaticFS embed.FS
// FileServer conveniently sets up a http.FileServer handler to serve // FileServer conveniently sets up a http.FileServer handler to serve
// static files from a http.FileSystem. // static files from a http.FileSystem.
func FileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embed.FS, embeddedPath string) { func FileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embed.FS, embeddedPath string) {
if strings.ContainsAny(path, "{}*") { if strings.ContainsAny(path, "{}*") {
panic("FileServer does not permit any URL parameters.") panic("FileServer does not permit any URL parameters.")
} }
if path != "/" && path[len(path)-1] != '/' { if path != "/" && path[len(path)-1] != '/' {
r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP)
path += "/" path += "/"
} }
path += "*" path += "*"
r.Get(path, func(w http.ResponseWriter, r *http.Request) { r.Get(path, func(w http.ResponseWriter, r *http.Request) {
rctx := chi.RouteContext(r.Context()) rctx := chi.RouteContext(r.Context())
pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*") pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
// Determine the actual file path // Determine the actual file path
requestedPath := strings.TrimPrefix(r.URL.Path, pathPrefix) requestedPath := strings.TrimPrefix(r.URL.Path, pathPrefix)
// Try to open from local filesystem first for development // Try to open from local filesystem first for development
localFile, localErr := root.Open(requestedPath) localFile, localErr := root.Open(requestedPath)
var fileToServe http.File var fileToServe http.File
if localErr == nil { if localErr == nil {
// File found in local filesystem // File found in local filesystem
fileToServe = localFile fileToServe = localFile
} else { } else {
// If not found locall, try embedded filesystem // If not found locall, try embedded filesystem
embeddedFilePath := filepath.Join(embeddedPath, requestedPath) embeddedFilePath := filepath.Join(embeddedPath, requestedPath)
embeddedFile, err := embeddedFS.Open(embeddedFilePath) embeddedFile, err := embeddedFS.Open(embeddedFilePath)
if err != nil { if err != nil {
http.NotFound(w, r) http.NotFound(w, r)
return return
} }
// Wrap the embedded file to implement http.File interface // Wrap the embedded file to implement http.File interface
fileToServe = &embeddedFileWrapper{embeddedFile} fileToServe = &embeddedFileWrapper{embeddedFile}
} }
// Create a custom ResponseWriter that allows us to modify headers // Create a custom ResponseWriter that allows us to modify headers
crw := &customResponseWriter{ResponseWriter: w} crw := &customResponseWriter{ResponseWriter: w}
// Serve the file // Serve the file
http.ServeContent(crw, r, requestedPath, time.Time{}, fileToServe) http.ServeContent(crw, r, requestedPath, time.Time{}, fileToServe)
// Close the file // Close the file
fileToServe.Close() fileToServe.Close()
}) })
} }
type embeddedFileWrapper struct { type embeddedFileWrapper struct {
file fs.File file fs.File
} }
func (e *embeddedFileWrapper) Close() error { func (e *embeddedFileWrapper) Close() error {
return e.file.Close() return e.file.Close()
} }
func (e *embeddedFileWrapper) Read(p []byte) (n int, err error) { func (e *embeddedFileWrapper) Read(p []byte) (n int, err error) {
return e.file.Read(p) return e.file.Read(p)
} }
type Seeker interface { type Seeker interface {
Seek(offset int64, whence int) (int64, error) Seek(offset int64, whence int) (int64, error)
} }
func (e *embeddedFileWrapper) Seek(offset int64, whence int) (int64, error) { func (e *embeddedFileWrapper) Seek(offset int64, whence int) (int64, error) {
if seeker, ok := e.file.(Seeker); ok { if seeker, ok := e.file.(Seeker); ok {
return seeker.Seek(offset, whence) return seeker.Seek(offset, whence)
} }
return 0, fmt.Errorf("Seek not supported") return 0, fmt.Errorf("Seek not supported")
} }
func (e *embeddedFileWrapper) Readdir(count int) ([]os.FileInfo, error) { func (e *embeddedFileWrapper) Readdir(count int) ([]os.FileInfo, error) {
// This is a bit tricky with embedded files // This is a bit tricky with embedded files
if dirFile, ok := e.file.(fs.ReadDirFile); ok { if dirFile, ok := e.file.(fs.ReadDirFile); ok {
entries, err := dirFile.ReadDir(count) entries, err := dirFile.ReadDir(count)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fileInfos := make([]os.FileInfo, len(entries)) fileInfos := make([]os.FileInfo, len(entries))
for i, entry := range entries { for i, entry := range entries {
fileInfos[i], err = entry.Info() fileInfos[i], err = entry.Info()
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
return fileInfos, nil return fileInfos, nil
} }
return nil, fmt.Errorf("Readdir not supported") return nil, fmt.Errorf("Readdir not supported")
} }
func (e *embeddedFileWrapper) Stat() (os.FileInfo, error) { func (e *embeddedFileWrapper) Stat() (os.FileInfo, error) {
return e.file.Stat() return e.file.Stat()
} }

59
html.go
View file

@ -9,23 +9,23 @@ import (
"os" "os"
"strings" "strings"
"github.com/riverqueue/river/rivershared/util/slogutil"
"github.com/Gleipnir-Technology/nidus-sync/models" "github.com/Gleipnir-Technology/nidus-sync/models"
"github.com/riverqueue/river/rivershared/util/slogutil"
) )
var ( var (
dashboard = newBuiltTemplate("dashboard", "authenticated") dashboard = newBuiltTemplate("dashboard", "authenticated")
report = newBuiltTemplate("report", "base") report = newBuiltTemplate("report", "base")
reportConfirmation = newBuiltTemplate("report-confirmation", "base") reportConfirmation = newBuiltTemplate("report-confirmation", "base")
reportContribute = newBuiltTemplate("report-contribute", "base") reportContribute = newBuiltTemplate("report-contribute", "base")
reportDetail = newBuiltTemplate("report-detail", "base") reportDetail = newBuiltTemplate("report-detail", "base")
reportEvidence = newBuiltTemplate("report-evidence", "base") reportEvidence = newBuiltTemplate("report-evidence", "base")
reportSchedule = newBuiltTemplate("report-schedule", "base") reportSchedule = newBuiltTemplate("report-schedule", "base")
reportUpdate = newBuiltTemplate("report-update", "base") reportUpdate = newBuiltTemplate("report-update", "base")
signin = newBuiltTemplate("signin", "base") signin = newBuiltTemplate("signin", "base")
signup = newBuiltTemplate("signup", "base") signup = newBuiltTemplate("signup", "base")
) )
var components = [ ... ]string{"header"} var components = [...]string{"header"}
type BuiltTemplate struct { type BuiltTemplate struct {
files []string files []string
@ -37,7 +37,7 @@ type Link struct {
Title string Title string
} }
type ContentReportDetail struct { type ContentReportDetail struct {
NextURL string NextURL string
UpdateURL string UpdateURL string
} }
type ContentReportDiagnostic struct { type ContentReportDiagnostic struct {
@ -51,11 +51,11 @@ type ContentPlaceholder struct {
type ContentSignin struct { type ContentSignin struct {
InvalidCredentials bool InvalidCredentials bool
} }
type ContentSignup struct { } type ContentSignup struct{}
type User struct { type User struct {
DisplayName string DisplayName string
Initials string Initials string
Username string Username string
} }
func (bt *BuiltTemplate) ExecuteTemplate(w io.Writer, data any) error { func (bt *BuiltTemplate) ExecuteTemplate(w io.Writer, data any) error {
@ -77,23 +77,23 @@ func (bt *BuiltTemplate) ExecuteTemplate(w io.Writer, data any) error {
func extractInitials(name string) string { func extractInitials(name string) string {
parts := strings.Fields(name) parts := strings.Fields(name)
var initials strings.Builder var initials strings.Builder
for _, part := range parts { for _, part := range parts {
if len(part) > 0 { if len(part) > 0 {
initials.WriteString(strings.ToUpper(string(part[0]))) initials.WriteString(strings.ToUpper(string(part[0])))
} }
} }
return initials.String() return initials.String()
} }
func htmlDashboard(w io.Writer, user *models.User) error { func htmlDashboard(w io.Writer, user *models.User) error {
data := ContentDashboard{ data := ContentDashboard{
User: User{ User: User{
DisplayName: user.DisplayName, DisplayName: user.DisplayName,
Initials: extractInitials(user.DisplayName), Initials: extractInitials(user.DisplayName),
Username: user.Username, Username: user.Username,
}, },
} }
return dashboard.ExecuteTemplate(w, data) return dashboard.ExecuteTemplate(w, data)
@ -126,7 +126,7 @@ func htmlReportContribute(w io.Writer, code string) error {
func htmlReportDetail(w io.Writer, code string) error { func htmlReportDetail(w io.Writer, code string) error {
nextURL := BaseURL + "/report/" + code + "/evidence" nextURL := BaseURL + "/report/" + code + "/evidence"
data := ContentReportDetail{ data := ContentReportDetail{
NextURL: nextURL, NextURL: nextURL,
UpdateURL: BaseURL + "/report/" + code + "/update", UpdateURL: BaseURL + "/report/" + code + "/update",
} }
return reportDetail.ExecuteTemplate(w, data) return reportDetail.ExecuteTemplate(w, data)
@ -164,8 +164,7 @@ func htmlSignin(w io.Writer, errorCode string) error {
} }
func htmlSignup(w io.Writer, path string) error { func htmlSignup(w io.Writer, path string) error {
data := ContentSignup{ data := ContentSignup{}
}
return signup.ExecuteTemplate(w, data) return signup.ExecuteTemplate(w, data)
} }

View file

@ -1,31 +1,32 @@
package main package main
import ( import (
"net/http" "net/http"
) )
// Custom ResponseWriter to track Content-Type // Custom ResponseWriter to track Content-Type
type customResponseWriter struct { type customResponseWriter struct {
http.ResponseWriter http.ResponseWriter
contentType string contentType string
wroteHeader bool wroteHeader bool
} }
func (crw *customResponseWriter) WriteHeader(code int) { func (crw *customResponseWriter) WriteHeader(code int) {
crw.wroteHeader = true crw.wroteHeader = true
crw.ResponseWriter.WriteHeader(code) crw.ResponseWriter.WriteHeader(code)
} }
func (crw *customResponseWriter) Header() http.Header { func (crw *customResponseWriter) Header() http.Header {
return crw.ResponseWriter.Header() return crw.ResponseWriter.Header()
} }
func (crw *customResponseWriter) Write(b []byte) (int, error) { func (crw *customResponseWriter) Write(b []byte) (int, error) {
if !crw.wroteHeader { if !crw.wroteHeader {
if crw.contentType == "" { if crw.contentType == "" {
crw.contentType = http.DetectContentType(b) crw.contentType = http.DetectContentType(b)
crw.ResponseWriter.Header().Set("Content-Type", crw.contentType) crw.ResponseWriter.Header().Set("Content-Type", crw.contentType)
} }
crw.WriteHeader(http.StatusOK) crw.WriteHeader(http.StatusOK)
} }
return crw.ResponseWriter.Write(b) return crw.ResponseWriter.Write(b)
} }