diff --git a/arcgis.go b/arcgis.go index 2bc23470..9d3008c8 100644 --- a/arcgis.go +++ b/arcgis.go @@ -15,9 +15,9 @@ import ( "strings" "time" - "github.com/aarondl/opt/omit" "github.com/Gleipnir-Technology/arcgis-go" "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" @@ -65,8 +65,8 @@ func generateCodeVerifier() string { func getArcgisUserData(access_token string, expires time.Time, refresh_token string) { client := arcgis.NewArcGIS( arcgis.AuthenticatorOAuth{ - AccessToken: access_token, - Expires: expires, + AccessToken: access_token, + Expires: expires, RefreshToken: refresh_token, }, ) @@ -78,7 +78,7 @@ func getArcgisUserData(access_token string, expires time.Time, refresh_token str slog.Info("Got portals data", slog.String("Username", portal.User.Username), slog.String("ID", portal.ID)) -*/ + */ search, err := client.Search("Fieldseeker") if err != nil { 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 { slog.Info("Got result", slog.String("name", result.Name)) //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) setter := models.OauthTokenSetter{ - AccessToken: omit.From(tokenResponse.AccessToken), - Expires: omit.From(expires), + AccessToken: omit.From(tokenResponse.AccessToken), + Expires: omit.From(expires), RefreshToken: omit.From(tokenResponse.RefreshToken), - Username: omit.From(tokenResponse.Username), + Username: omit.From(tokenResponse.Username), } err = user.InsertUserOauthTokens(ctx, PGInstance.BobDB, &setter) if err != nil { diff --git a/auth.go b/auth.go index 26f8b46d..9adc9cbd 100644 --- a/auth.go +++ b/auth.go @@ -8,20 +8,23 @@ import ( "net/http" "strconv" - "github.com/aarondl/opt/omit" "github.com/Gleipnir-Technology/nidus-sync/enums" "github.com/Gleipnir-Technology/nidus-sync/models" "github.com/Gleipnir-Technology/nidus-sync/sql" + "github.com/aarondl/opt/omit" "golang.org/x/crypto/bcrypt" ) type NoCredentialsError struct{} + func (e NoCredentialsError) Error() string { return "No credentials were present in the request" } type InvalidCredentials struct{} + func (e InvalidCredentials) Error() string { return "No username with that password exists" } type InvalidUsername struct{} + func (e InvalidUsername) Error() string { return "That username doesn't exist" } 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) } setter := models.UserSetter{ - DisplayName: omit.From(name), - PasswordHash: omit.From(passwordHash), + DisplayName: omit.From(name), + PasswordHash: omit.From(passwordHash), PasswordHashType: omit.From(enums.HashtypeBcrypt14), - Username: omit.From(username), + Username: omit.From(username), } u, err := models.Users.Insert(&setter).One(context.TODO(), PGInstance.BobDB) 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) } switch len(result) { - case 0: + case 0: return nil, InvalidUsername{} case 1: row := result[0] @@ -128,16 +131,16 @@ func validateUser(ctx context.Context, username string, password string) (*model return nil, InvalidCredentials{} } user := models.User{ - ID: row.ID, - ArcgisAccessToken: row.ArcgisAccessToken, - ArcgisLicense: row.ArcgisLicense, - ArcgisRefreshToken: row.ArcgisRefreshToken, + ID: row.ID, + ArcgisAccessToken: row.ArcgisAccessToken, + ArcgisLicense: row.ArcgisLicense, + ArcgisRefreshToken: row.ArcgisRefreshToken, ArcgisRefreshTokenExpires: row.ArcgisRefreshTokenExpires, - ArcgisRole: row.ArcgisRole, - DisplayName: row.DisplayName, - Email: row.Email, - OrganizationID: row.OrganizationID, - Username: row.Username, + ArcgisRole: row.ArcgisRole, + DisplayName: row.DisplayName, + Email: row.Email, + OrganizationID: row.OrganizationID, + Username: row.Username, } return &user, nil default: diff --git a/database.go b/database.go index e707f4cc..ea454497 100644 --- a/database.go +++ b/database.go @@ -23,7 +23,7 @@ import ( var embedMigrations embed.FS type postgres struct { - BobDB bob.DB + BobDB bob.DB PGXPool *pgxpool.Pool } diff --git a/endpoint.go b/endpoint.go index 89d00975..852cfb1d 100644 --- a/endpoint.go +++ b/endpoint.go @@ -88,7 +88,7 @@ func getQRCodeReport(w http.ResponseWriter, r *http.Request) { // Set the appropriate content type w.Header().Set("Content-Type", "image/png") - + // Generate PNG and write directly to the response writer png, err := qr.PNG(size) if err != nil { @@ -190,14 +190,13 @@ func postSignin(w http.ResponseWriter, r *http.Request) { respondError(w, "Could not parse form", err, http.StatusBadRequest) return } - + username := r.FormValue("username") password := r.FormValue("password") - - slog.Info("Signin", + + slog.Info("Signin", slog.String("username", username), slog.String("password", strings.Repeat("*", len(password)))) - _, err := signinUser(r, username, password) if err != nil { @@ -217,17 +216,17 @@ func postSignup(w http.ResponseWriter, r *http.Request) { respondError(w, "Could not parse form", err, http.StatusBadRequest) return } - + username := r.FormValue("username") name := r.FormValue("name") password := r.FormValue("password") terms := r.FormValue("terms") - - slog.Info("Signup", + + slog.Info("Signup", slog.String("username", username), slog.String("name", name), slog.String("password", strings.Repeat("*", len(password)))) - + if terms != "on" { slog.Error("Terms not agreed", slog.String("terms", terms)) http.Error(w, "You must agree to the terms to register", http.StatusBadRequest) diff --git a/fileserver.go b/fileserver.go index 539bece4..a17d4955 100644 --- a/fileserver.go +++ b/fileserver.go @@ -1,4 +1,5 @@ package main + import ( "embed" "fmt" @@ -18,99 +19,100 @@ var embeddedStaticFS embed.FS // FileServer conveniently sets up a http.FileServer handler to serve // static files from a http.FileSystem. func FileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embed.FS, embeddedPath string) { - if strings.ContainsAny(path, "{}*") { - panic("FileServer does not permit any URL parameters.") - } + if strings.ContainsAny(path, "{}*") { + panic("FileServer does not permit any URL parameters.") + } - if path != "/" && path[len(path)-1] != '/' { - r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) - path += "/" - } - path += "*" + if path != "/" && path[len(path)-1] != '/' { + r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) + path += "/" + } + path += "*" - r.Get(path, func(w http.ResponseWriter, r *http.Request) { - rctx := chi.RouteContext(r.Context()) - pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*") + r.Get(path, func(w http.ResponseWriter, r *http.Request) { + rctx := chi.RouteContext(r.Context()) + pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*") - // Determine the actual file path - requestedPath := strings.TrimPrefix(r.URL.Path, pathPrefix) + // Determine the actual file path + requestedPath := strings.TrimPrefix(r.URL.Path, pathPrefix) - // Try to open from local filesystem first for development - localFile, localErr := root.Open(requestedPath) + // Try to open from local filesystem first for development + localFile, localErr := root.Open(requestedPath) - var fileToServe http.File + var fileToServe http.File - if localErr == nil { - // File found in local filesystem - fileToServe = localFile - } else { - // If not found locall, try embedded filesystem - embeddedFilePath := filepath.Join(embeddedPath, requestedPath) - embeddedFile, err := embeddedFS.Open(embeddedFilePath) + if localErr == nil { + // File found in local filesystem + fileToServe = localFile + } else { + // If not found locall, try embedded filesystem + embeddedFilePath := filepath.Join(embeddedPath, requestedPath) + embeddedFile, err := embeddedFS.Open(embeddedFilePath) - if err != nil { - http.NotFound(w, r) - return - } + if err != nil { + http.NotFound(w, r) + return + } - // Wrap the embedded file to implement http.File interface - fileToServe = &embeddedFileWrapper{embeddedFile} + // Wrap the embedded file to implement http.File interface + fileToServe = &embeddedFileWrapper{embeddedFile} - } + } - // Create a custom ResponseWriter that allows us to modify headers - crw := &customResponseWriter{ResponseWriter: w} + // Create a custom ResponseWriter that allows us to modify headers + crw := &customResponseWriter{ResponseWriter: w} - // Serve the file - http.ServeContent(crw, r, requestedPath, time.Time{}, fileToServe) + // Serve the file + http.ServeContent(crw, r, requestedPath, time.Time{}, fileToServe) - // Close the file - fileToServe.Close() - }) + // Close the file + fileToServe.Close() + }) } + type embeddedFileWrapper struct { - file fs.File + file fs.File } func (e *embeddedFileWrapper) Close() error { - return e.file.Close() + return e.file.Close() } func (e *embeddedFileWrapper) Read(p []byte) (n int, err error) { - return e.file.Read(p) + return e.file.Read(p) } 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) { - if seeker, ok := e.file.(Seeker); ok { - return seeker.Seek(offset, whence) - } - return 0, fmt.Errorf("Seek not supported") + if seeker, ok := e.file.(Seeker); ok { + return seeker.Seek(offset, whence) + } + return 0, fmt.Errorf("Seek not supported") } func (e *embeddedFileWrapper) Readdir(count int) ([]os.FileInfo, error) { - // This is a bit tricky with embedded files - if dirFile, ok := e.file.(fs.ReadDirFile); ok { - entries, err := dirFile.ReadDir(count) - if err != nil { - return nil, err - } + // This is a bit tricky with embedded files + if dirFile, ok := e.file.(fs.ReadDirFile); ok { + entries, err := dirFile.ReadDir(count) + if err != nil { + return nil, err + } - fileInfos := make([]os.FileInfo, len(entries)) - for i, entry := range entries { - fileInfos[i], err = entry.Info() - if err != nil { - return nil, err - } - } - return fileInfos, nil - } - return nil, fmt.Errorf("Readdir not supported") + fileInfos := make([]os.FileInfo, len(entries)) + for i, entry := range entries { + fileInfos[i], err = entry.Info() + if err != nil { + return nil, err + } + } + return fileInfos, nil + } + return nil, fmt.Errorf("Readdir not supported") } func (e *embeddedFileWrapper) Stat() (os.FileInfo, error) { - return e.file.Stat() + return e.file.Stat() } diff --git a/html.go b/html.go index d707055e..2833fcdf 100644 --- a/html.go +++ b/html.go @@ -9,23 +9,23 @@ import ( "os" "strings" - "github.com/riverqueue/river/rivershared/util/slogutil" "github.com/Gleipnir-Technology/nidus-sync/models" + "github.com/riverqueue/river/rivershared/util/slogutil" ) var ( - dashboard = newBuiltTemplate("dashboard", "authenticated") - report = newBuiltTemplate("report", "base") + dashboard = newBuiltTemplate("dashboard", "authenticated") + report = newBuiltTemplate("report", "base") reportConfirmation = newBuiltTemplate("report-confirmation", "base") - reportContribute = newBuiltTemplate("report-contribute", "base") - reportDetail = newBuiltTemplate("report-detail", "base") - reportEvidence = newBuiltTemplate("report-evidence", "base") - reportSchedule = newBuiltTemplate("report-schedule", "base") - reportUpdate = newBuiltTemplate("report-update", "base") - signin = newBuiltTemplate("signin", "base") - signup = newBuiltTemplate("signup", "base") + reportContribute = newBuiltTemplate("report-contribute", "base") + reportDetail = newBuiltTemplate("report-detail", "base") + reportEvidence = newBuiltTemplate("report-evidence", "base") + reportSchedule = newBuiltTemplate("report-schedule", "base") + reportUpdate = newBuiltTemplate("report-update", "base") + signin = newBuiltTemplate("signin", "base") + signup = newBuiltTemplate("signup", "base") ) -var components = [ ... ]string{"header"} +var components = [...]string{"header"} type BuiltTemplate struct { files []string @@ -37,7 +37,7 @@ type Link struct { Title string } type ContentReportDetail struct { - NextURL string + NextURL string UpdateURL string } type ContentReportDiagnostic struct { @@ -51,11 +51,11 @@ type ContentPlaceholder struct { type ContentSignin struct { InvalidCredentials bool } -type ContentSignup struct { } +type ContentSignup struct{} type User struct { DisplayName string - Initials string - Username string + Initials string + Username string } 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 { parts := strings.Fields(name) - var initials strings.Builder - - for _, part := range parts { - if len(part) > 0 { - initials.WriteString(strings.ToUpper(string(part[0]))) - } - } - - return initials.String() + var initials strings.Builder + + for _, part := range parts { + if len(part) > 0 { + initials.WriteString(strings.ToUpper(string(part[0]))) + } + } + + return initials.String() } func htmlDashboard(w io.Writer, user *models.User) error { data := ContentDashboard{ - User: User{ + User: User{ DisplayName: user.DisplayName, - Initials: extractInitials(user.DisplayName), - Username: user.Username, + Initials: extractInitials(user.DisplayName), + Username: user.Username, }, } 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 { nextURL := BaseURL + "/report/" + code + "/evidence" data := ContentReportDetail{ - NextURL: nextURL, + NextURL: nextURL, UpdateURL: BaseURL + "/report/" + code + "/update", } 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 { - data := ContentSignup{ - } + data := ContentSignup{} return signup.ExecuteTemplate(w, data) } diff --git a/response.go b/response.go index 3953df46..f9128c5a 100644 --- a/response.go +++ b/response.go @@ -1,31 +1,32 @@ package main + import ( "net/http" ) // Custom ResponseWriter to track Content-Type type customResponseWriter struct { - http.ResponseWriter - contentType string - wroteHeader bool + http.ResponseWriter + contentType string + wroteHeader bool } func (crw *customResponseWriter) WriteHeader(code int) { - crw.wroteHeader = true - crw.ResponseWriter.WriteHeader(code) + crw.wroteHeader = true + crw.ResponseWriter.WriteHeader(code) } func (crw *customResponseWriter) Header() http.Header { - return crw.ResponseWriter.Header() + return crw.ResponseWriter.Header() } func (crw *customResponseWriter) Write(b []byte) (int, error) { - if !crw.wroteHeader { - if crw.contentType == "" { - crw.contentType = http.DetectContentType(b) - crw.ResponseWriter.Header().Set("Content-Type", crw.contentType) - } - crw.WriteHeader(http.StatusOK) - } - return crw.ResponseWriter.Write(b) + if !crw.wroteHeader { + if crw.contentType == "" { + crw.contentType = http.DetectContentType(b) + crw.ResponseWriter.Header().Set("Content-Type", crw.contentType) + } + crw.WriteHeader(http.StatusOK) + } + return crw.ResponseWriter.Write(b) }