Format all source files.
This commit is contained in:
parent
f7ad8b9c5f
commit
fa89e0719f
7 changed files with 142 additions and 138 deletions
16
arcgis.go
16
arcgis.go
|
|
@ -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
31
auth.go
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
17
endpoint.go
17
endpoint.go
|
|
@ -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)
|
||||||
|
|
|
||||||
126
fileserver.go
126
fileserver.go
|
|
@ -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
59
html.go
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
29
response.go
29
response.go
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue