From eaa7cc8547c0bdc92d8b7cad837d2fdad98904df Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Mon, 8 Apr 2024 17:04:19 -0600 Subject: [PATCH 1/5] get something up there --- Dockerfile | 2 +- .../cloudflare/cloudflare.go | 0 adapters/{ => external_dns}/external_dns.go | 0 adapters/files/files_adapter.go | 8 ++ adapters/files/filesystem/filesystem.go | 37 ++++++++ api/auth/auth.go | 14 ++- api/dns/dns.go | 6 +- api/dns/dns_test.go | 4 +- api/profiles/profiles.go | 83 ++++++++++++++++++ api/serve.go | 32 +++++-- args/args.go | 9 ++ database/migrate.go | 34 +++++++ database/users.go | 46 +++++++++- docker-compose.yml | 1 + templates/base.html | 4 +- templates/home.html | 6 +- templates/profile.html | 29 ++++++ .../f54386d9-f310-4c5a-a3f9-e950320479f7 | Bin 0 -> 29171 bytes utils/{RandomId.go => random_id.go} | 0 19 files changed, 297 insertions(+), 18 deletions(-) rename adapters/{ => external_dns}/cloudflare/cloudflare.go (100%) rename adapters/{ => external_dns}/external_dns.go (100%) create mode 100644 adapters/files/files_adapter.go create mode 100644 adapters/files/filesystem/filesystem.go create mode 100644 api/profiles/profiles.go create mode 100644 templates/profile.html create mode 100644 uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 rename utils/{RandomId.go => random_id.go} (100%) diff --git a/Dockerfile b/Dockerfile index 790c580..a95f9b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,4 +11,4 @@ RUN go build -o /app/hatecomputers EXPOSE 8080 -CMD ["/app/hatecomputers", "--server", "--migrate", "--port", "8080", "--template-path", "/app/templates", "--database-path", "/app/db/hatecomputers.db", "--static-path", "/app/static", "--scheduler", "--dns", "--dns-port", "8053", "--dns-resolvers", "1.1.1.1:53,1.0.0.1:53"] +CMD ["/app/hatecomputers", "--server", "--migrate", "--port", "8080", "--template-path", "/app/templates", "--database-path", "/app/db/hatecomputers.db", "--static-path", "/app/static", "--scheduler", "--dns", "--dns-port", "8053", "--dns-resolvers", "1.1.1.1:53,1.0.0.1:53", "--uploads", "/app/uploads"] diff --git a/adapters/cloudflare/cloudflare.go b/adapters/external_dns/cloudflare/cloudflare.go similarity index 100% rename from adapters/cloudflare/cloudflare.go rename to adapters/external_dns/cloudflare/cloudflare.go diff --git a/adapters/external_dns.go b/adapters/external_dns/external_dns.go similarity index 100% rename from adapters/external_dns.go rename to adapters/external_dns/external_dns.go diff --git a/adapters/files/files_adapter.go b/adapters/files/files_adapter.go new file mode 100644 index 0000000..bf3ea5f --- /dev/null +++ b/adapters/files/files_adapter.go @@ -0,0 +1,8 @@ +package files + +import "io" + +type FilesAdapter interface { + CreateFile(path string, content io.Reader) (string, error) + DeleteFile(path string) error +} diff --git a/adapters/files/filesystem/filesystem.go b/adapters/files/filesystem/filesystem.go new file mode 100644 index 0000000..726a588 --- /dev/null +++ b/adapters/files/filesystem/filesystem.go @@ -0,0 +1,37 @@ +package filesystem + +import ( + "io" + "os" + "path/filepath" +) + +type FilesystemAdapter struct { + BasePath string + Permissions os.FileMode +} + +func (f *FilesystemAdapter) CreateFile(path string, content io.Reader) (string, error) { + fullPath := f.BasePath + path + dir := filepath.Dir(fullPath) + if _, err := os.Stat(dir); os.IsNotExist(err) { + os.MkdirAll(dir, f.Permissions) + } + + file, err := os.Create(f.BasePath + path) + if err != nil { + return "", err + } + defer file.Close() + + _, err = io.Copy(file, content) + if err != nil { + return "", err + } + + return path, nil +} + +func (f *FilesystemAdapter) DeleteFile(path string) error { + return os.Remove(f.BasePath + path) +} diff --git a/api/auth/auth.go b/api/auth/auth.go index 0ffbf9c..c54aad6 100644 --- a/api/auth/auth.go +++ b/api/auth/auth.go @@ -18,6 +18,18 @@ import ( "golang.org/x/oauth2" ) +func ListUsersContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + users, err := database.ListUsers(context.DBConn) + if err != nil { + return failure(context, req, resp) + } + + (*context.TemplateData)["Users"] = users + return success(context, req, resp) + } +} + func StartSessionContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { verifier := utils.RandomId() + utils.RandomId() @@ -216,7 +228,7 @@ func getOauthUser(dbConn *sql.DB, client *http.Client, uri string) (*database.Us return nil, err } - user, err := database.FindOrSaveUser(dbConn, userStruct) + user, err := database.FindOrSaveBaseUser(dbConn, userStruct) if err != nil { return nil, err } diff --git a/api/dns/dns.go b/api/dns/dns.go index aa2f356..bf91994 100644 --- a/api/dns/dns.go +++ b/api/dns/dns.go @@ -8,12 +8,16 @@ import ( "strconv" "strings" - "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/external_dns" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" "git.hatecomputers.club/hatecomputers/hatecomputers.club/database" "git.hatecomputers.club/hatecomputers/hatecomputers.club/utils" ) +const MaxUserRecords = 100 + +var UserOwnedInternalFmtDomains = []string{"%s", "%s.endpoints"} + func userCanFuckWithDNSRecord(dbConn *sql.DB, user *database.User, record *database.DNSRecord, ownedInternalDomainFormats []string) bool { ownedByUser := (user.ID == record.UserID) if !ownedByUser { diff --git a/api/dns/dns_test.go b/api/dns/dns_test.go index 43dc680..30baedf 100644 --- a/api/dns/dns_test.go +++ b/api/dns/dns_test.go @@ -39,7 +39,7 @@ func setup() (*sql.DB, *types.RequestContext, func()) { Mail: "test@test.com", DisplayName: "test", } - database.FindOrSaveUser(testDb, user) + database.FindOrSaveBaseUser(testDb, user) context := &types.RequestContext{ DBConn: testDb, @@ -246,7 +246,7 @@ func TestThatUserMustOwnRecordToRemove(t *testing.T) { defer testServer.Close() nonOwnerUser := &database.User{ID: "n/a", Username: "testuser"} - _, err := database.FindOrSaveUser(db, nonOwnerUser) + _, err := database.FindOrSaveBaseUser(db, nonOwnerUser) if err != nil { t.Error(err) } diff --git a/api/profiles/profiles.go b/api/profiles/profiles.go new file mode 100644 index 0000000..905b437 --- /dev/null +++ b/api/profiles/profiles.go @@ -0,0 +1,83 @@ +package profiles + +import ( + "log" + "net/http" + + "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/files" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/database" +) + +const MaxAvatarSize = 1024 * 1024 * 2 // 2MB +const AvatarPath = "avatars/" + +func GetProfileContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + if context.User == nil { + return failure(context, req, resp) + } + + (*context.TemplateData)["Profile"] = context.User + return success(context, req, resp) + } +} + +func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int, avatarPath string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + formErrors := types.FormError{ + Errors: []string{}, + } + + err := req.ParseMultipartForm(int64(maxAvatarSize)) + if err != nil { + log.Println(err) + + formErrors.Errors = append(formErrors.Errors, "avatar file too large") + } + + if len(formErrors.Errors) == 0 { + file, _, err := req.FormFile("avatar") + if err != nil { + formErrors.Errors = append(formErrors.Errors, "error uploading avatar") + } else { + defer file.Close() + + _, err = fileAdapter.CreateFile(avatarPath+context.User.ID, file) + if err != nil { + log.Println(err) + formErrors.Errors = append(formErrors.Errors, "error saving avatar") + } + } + } + + if len(formErrors.Errors) == 0 { + bio := req.FormValue("bio") + location := req.FormValue("location") + website := req.FormValue("website") + + context.User.Bio = bio + context.User.Location = location + context.User.Website = website + + _, err = database.SaveUser(context.DBConn, context.User) + if err != nil { + formErrors.Errors = append(formErrors.Errors, "error saving profile") + } + } + + (*context.TemplateData)["Profile"] = context.User + (*context.TemplateData)["FormError"] = formErrors + + if len(formErrors.Errors) > 0 { + log.Println(formErrors.Errors) + + resp.WriteHeader(http.StatusBadRequest) + return failure(context, req, resp) + } + + return success(context, req, resp) + } + } +} diff --git a/api/serve.go b/api/serve.go index c8775d8..6218d1b 100644 --- a/api/serve.go +++ b/api/serve.go @@ -7,12 +7,14 @@ import ( "net/http" "time" - "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/cloudflare" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/external_dns/cloudflare" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/files/filesystem" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/auth" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/dns" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/guestbook" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/hcaptcha" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/keys" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/profiles" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/template" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" "git.hatecomputers.club/hatecomputers/hatecomputers.club/args" @@ -32,7 +34,6 @@ func LogRequestContinuation(context *types.RequestContext, req *http.Request, re func LogExecutionTimeContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain { end := time.Now() - log.Println(context.Id, "took", end.Sub(context.Start)) return success(context, req, resp) @@ -70,14 +71,21 @@ func CacheControlMiddleware(next http.Handler, maxAge int) http.Handler { func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { mux := http.NewServeMux() - fileServer := http.FileServer(http.Dir(argv.StaticPath)) - mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(fileServer, 3600))) + staticFileServer := http.FileServer(http.Dir(argv.StaticPath)) + uploadFileServer := http.FileServer(http.Dir(argv.UploadPath)) + mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600))) + mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 3600))) cloudflareAdapter := &cloudflare.CloudflareExternalDNSAdapter{ APIToken: argv.CloudflareToken, ZoneId: argv.CloudflareZone, } + uploadAdapter := &filesystem.FilesystemAdapter{ + BasePath: argv.UploadPath, + Permissions: 0777, + } + makeRequestContext := func() *types.RequestContext { return &types.RequestContext{ DBConn: dbConn, @@ -88,7 +96,7 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() - LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(template.TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(auth.ListUsersContinuation, auth.ListUsersContinuation)(template.TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) { @@ -111,16 +119,24 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { LogRequestContinuation(requestContext, r, w)(auth.LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) + mux.HandleFunc("GET /profile", func(w http.ResponseWriter, r *http.Request) { + requestContext := makeRequestContext() + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.GetProfileContinuation, auth.GoLoginContinuation)(template.TemplateContinuation("profile.html", true), template.TemplateContinuation("profile.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + }) + + mux.HandleFunc("POST /profile", func(w http.ResponseWriter, r *http.Request) { + requestContext := makeRequestContext() + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath), auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + }) + mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, auth.GoLoginContinuation)(template.TemplateContinuation("dns.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) - const MAX_USER_RECORDS = 100 - var USER_OWNED_INTERNAL_FMT_DOMAINS = []string{"%s", "%s.endpoints"} mux.HandleFunc("POST /dns", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() - LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, auth.GoLoginContinuation)(dns.CreateDNSRecordContinuation(cloudflareAdapter, MAX_USER_RECORDS, USER_OWNED_INTERNAL_FMT_DOMAINS), FailurePassingContinuation)(dns.ListDNSRecordsContinuation, dns.ListDNSRecordsContinuation)(template.TemplateContinuation("dns.html", true), template.TemplateContinuation("dns.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, auth.GoLoginContinuation)(dns.CreateDNSRecordContinuation(cloudflareAdapter, dns.MaxUserRecords, dns.UserOwnedInternalFmtDomains), FailurePassingContinuation)(dns.ListDNSRecordsContinuation, dns.ListDNSRecordsContinuation)(template.TemplateContinuation("dns.html", true), template.TemplateContinuation("dns.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) mux.HandleFunc("POST /dns/delete", func(w http.ResponseWriter, r *http.Request) { diff --git a/args/args.go b/args/args.go index 09c96be..59eb441 100644 --- a/args/args.go +++ b/args/args.go @@ -13,6 +13,7 @@ type Arguments struct { DatabasePath string TemplatePath string StaticPath string + UploadPath string Migrate bool Scheduler bool @@ -35,6 +36,13 @@ type Arguments struct { func GetArgs() (*Arguments, error) { databasePath := flag.String("database-path", "./hatecomputers.db", "Path to the SQLite database") + + uploadPath := flag.String("upload-path", "./uploads", "Path to the uploads directory") + uploadPathValue := *uploadPath + if uploadPathValue[len(uploadPathValue)-1] != '/' { + uploadPathValue += "/" + } + templatePath := flag.String("template-path", "./templates", "Path to the template directory") staticPath := flag.String("static-path", "./static", "Path to the static directory") dnsResolvers := flag.String("dns-resolvers", "1.1.1.1:53,1.0.0.1:53", "Comma-separated list of DNS resolvers") @@ -96,6 +104,7 @@ func GetArgs() (*Arguments, error) { arguments := &Arguments{ DatabasePath: *databasePath, TemplatePath: *templatePath, + UploadPath: uploadPathValue, StaticPath: *staticPath, CloudflareToken: cloudflareToken, CloudflareZone: cloudflareZone, diff --git a/database/migrate.go b/database/migrate.go index a117480..04eae72 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -127,6 +127,39 @@ func MigrateGuestBook(dbConn *sql.DB) (*sql.DB, error) { return dbConn, nil } +func MigrateProfiles(dbConn *sql.DB) (*sql.DB, error) { + log.Println("migrating profiles columns") + + userColumns := map[string]bool{} + row, err := dbConn.Query(`PRAGMA table_info(users);`) + if err != nil { + return dbConn, err + } + defer row.Close() + + for row.Next() { + var columnName string + row.Scan(nil, &columnName, nil, nil, nil, nil) + userColumns[columnName] = true + } + + columns := map[string]string{} + columns["bio"] = "a computer hater" + columns["location"] = "earth" + columns["website"] = "https://hatecomputers.club" + columns["avatar"] = "/files/avatars/default.png" + + for column, defaultValue := range columns { + if userColumns[column] { + continue + } + log.Println("migrating column", column) + _, err = dbConn.Exec(`ALTER TABLE users ADD COLUMN ` + column + ` TEXT NOT NULL DEFAULT '` + defaultValue + `';`) + } + + return dbConn, nil +} + func Migrate(dbConn *sql.DB) (*sql.DB, error) { log.Println("migrating database") @@ -137,6 +170,7 @@ func Migrate(dbConn *sql.DB) (*sql.DB, error) { MigrateDomainOwners, MigrateDNSRecords, MigrateGuestBook, + MigrateProfiles, } for _, migration := range migrations { diff --git a/database/users.go b/database/users.go index 6f9456e..cb1b3d2 100644 --- a/database/users.go +++ b/database/users.go @@ -24,6 +24,10 @@ type User struct { Mail string `json:"email"` Username string `json:"preferred_username"` DisplayName string `json:"name"` + Bio string `json:"bio"` + Location string `json:"location"` + Website string `json:"website"` + Avatar string `json:"avatar"` CreatedAt time.Time `json:"created_at"` } @@ -36,10 +40,10 @@ type UserSession struct { func GetUser(dbConn *sql.DB, id string) (*User, error) { log.Println("getting user", id) - row := dbConn.QueryRow(`SELECT id, mail, username, display_name, created_at FROM users WHERE id = ?;`, id) + row := dbConn.QueryRow(`SELECT id, mail, username, display_name, bio, location, website, avatar, created_at FROM users WHERE id = ?;`, id) var user User - err := row.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.CreatedAt) + err := row.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.CreatedAt) if err != nil { log.Println(err) return nil, err @@ -48,7 +52,32 @@ func GetUser(dbConn *sql.DB, id string) (*User, error) { return &user, nil } -func FindOrSaveUser(dbConn *sql.DB, user *User) (*User, error) { +func ListUsers(dbConn *sql.DB) ([]*User, error) { + log.Println("listing users") + + rows, err := dbConn.Query(`SELECT id, mail, username, display_name, bio, location, website, avatar, created_at FROM users;`) + if err != nil { + log.Println(err) + return nil, err + } + defer rows.Close() + + var users []*User + for rows.Next() { + var user User + err := rows.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.CreatedAt) + if err != nil { + log.Println(err) + return nil, err + } + + users = append(users, &user) + } + + return users, nil +} + +func FindOrSaveBaseUser(dbConn *sql.DB, user *User) (*User, error) { log.Println("finding or saving user", user.ID) _, err := dbConn.Exec(`INSERT INTO users (id, mail, username, display_name) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET mail = excluded.mail, username = excluded.username, display_name = excluded.display_name;`, user.ID, user.Mail, user.Username, user.DisplayName) @@ -59,6 +88,17 @@ func FindOrSaveUser(dbConn *sql.DB, user *User) (*User, error) { return user, nil } +func SaveUser(dbConn *sql.DB, user *User) (*User, error) { + log.Println("saving user", user.ID) + + _, err := dbConn.Exec(`INSERT OR REPLACE INTO users (id, mail, username, display_name, bio, location, website, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?);`, user.ID, user.Mail, user.Username, user.DisplayName, user.Bio, user.Location, user.Website, user.Avatar) + if err != nil { + return nil, err + } + + return user, nil +} + func MakeUserSessionFor(dbConn *sql.DB, user *User) (*UserSession, error) { log.Println("making session for user", user.ID) diff --git a/docker-compose.yml b/docker-compose.yml index b568e87..957683f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,5 +15,6 @@ services: - ./db:/app/db - ./templates:/app/templates - ./static:/app/static + - ./uploads:/app/uploads ports: - "127.0.0.1:4455:8080" diff --git a/templates/base.html b/templates/base.html index 9f5a903..285b0dc 100644 --- a/templates/base.html +++ b/templates/base.html @@ -37,7 +37,9 @@ | api keys. | - logout, {{ .User.DisplayName }}. + {{ .User.DisplayName }}. + | + logout. {{ else }} login. diff --git a/templates/home.html b/templates/home.html index 1c03377..944216d 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,3 +1,7 @@ {{ define "content" }} -

under construction!

+

hello there!

+

current peeps:

+ {{ range $user := .Users }} +

{{ $user.Username }}

+ {{ end }} {{ end }} diff --git a/templates/profile.html b/templates/profile.html new file mode 100644 index 0000000..eb2091c --- /dev/null +++ b/templates/profile.html @@ -0,0 +1,29 @@ +{{ define "content" }} + +

hey {{ .Profile.DisplayName }}

+
+
+ + + + + + + + + + + + + + + {{ if .FormError }} + {{ if (len .FormError.Errors) }} + {{ range $error := .FormError.Errors }} +
{{ $error }}
+ {{ end }} + {{ end }} + {{ end }} +
+ +{{ end }} diff --git a/uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 b/uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 new file mode 100644 index 0000000000000000000000000000000000000000..60b7a106183eaaf7e94fdc27ddaa6df251babe36 GIT binary patch literal 29171 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 literal 0 HcmV?d00001 diff --git a/utils/RandomId.go b/utils/random_id.go similarity index 100% rename from utils/RandomId.go rename to utils/random_id.go -- 2.40.1 From 3d7bb77eab51ad369f6c7050ff37fdfb488b1467 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Mon, 8 Apr 2024 17:15:31 -0600 Subject: [PATCH 2/5] a little further --- api/profiles/profiles.go | 24 +++++++++++++++++++----- api/serve.go | 2 +- database/migrate.go | 2 +- static/img/default-avatar.png | Bin 0 -> 105755 bytes templates/home.html | 1 + templates/profile.html | 2 +- 6 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 static/img/default-avatar.png diff --git a/api/profiles/profiles.go b/api/profiles/profiles.go index 905b437..c46d2a2 100644 --- a/api/profiles/profiles.go +++ b/api/profiles/profiles.go @@ -11,6 +11,7 @@ import ( const MaxAvatarSize = 1024 * 1024 * 2 // 2MB const AvatarPath = "avatars/" +const AvatarPrefix = "/uploads/avatars/" func GetProfileContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { @@ -23,7 +24,7 @@ func GetProfileContinuation(context *types.RequestContext, req *http.Request, re } } -func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int, avatarPath string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { +func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int, avatarPath string, avatarPrefix string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { formErrors := types.FormError{ @@ -39,6 +40,9 @@ func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int if len(formErrors.Errors) == 0 { file, _, err := req.FormFile("avatar") + if file == nil { + formErrors.Errors = append(formErrors.Errors, "avatar required") + } if err != nil { formErrors.Errors = append(formErrors.Errors, "error uploading avatar") } else { @@ -52,14 +56,24 @@ func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int } } - if len(formErrors.Errors) == 0 { - bio := req.FormValue("bio") - location := req.FormValue("location") - website := req.FormValue("website") + bio := req.FormValue("bio") + location := req.FormValue("location") + website := req.FormValue("website") + if len(bio) > 128 { + formErrors.Errors = append(formErrors.Errors, "bio too long, keep it to 128") + } + if len(location) > 32 { + formErrors.Errors = append(formErrors.Errors, "location too long, keep it to 32") + } + if len(website) > 64 { + formErrors.Errors = append(formErrors.Errors, "website too long, keep it to 64") + } + if len(formErrors.Errors) == 0 { context.User.Bio = bio context.User.Location = location context.User.Website = website + context.User.Avatar = avatarPrefix + context.User.ID _, err = database.SaveUser(context.DBConn, context.User) if err != nil { diff --git a/api/serve.go b/api/serve.go index 6218d1b..5721cdf 100644 --- a/api/serve.go +++ b/api/serve.go @@ -126,7 +126,7 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { mux.HandleFunc("POST /profile", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() - LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath), auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath, profiles.AvatarPrefix), auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) { diff --git a/database/migrate.go b/database/migrate.go index 04eae72..fbba6ff 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -147,7 +147,7 @@ func MigrateProfiles(dbConn *sql.DB) (*sql.DB, error) { columns["bio"] = "a computer hater" columns["location"] = "earth" columns["website"] = "https://hatecomputers.club" - columns["avatar"] = "/files/avatars/default.png" + columns["avatar"] = "/static/img/default-avatar.png" for column, defaultValue := range columns { if userColumns[column] { diff --git a/static/img/default-avatar.png b/static/img/default-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..66a38c2605d7e743f94e409fd7ec2c05cfee625f GIT binary patch literal 105755 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�-1=l9{+b?iLYrHJ;l)&OFQ!i{Sd6^yF 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≶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%0Ad;&*@J8UkhcVFX&b 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 H@AH2Ew*HO} literal 0 HcmV?d00001 diff --git a/templates/home.html b/templates/home.html index 944216d..09edc20 100644 --- a/templates/home.html +++ b/templates/home.html @@ -3,5 +3,6 @@

current peeps:

{{ range $user := .Users }}

{{ $user.Username }}

+ {{ $user.Username }} {{ end }} {{ end }} diff --git a/templates/profile.html b/templates/profile.html index eb2091c..52f7127 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -4,7 +4,7 @@
- + -- 2.40.1 From fb85836649bb58245e29cd9e0f69f4e0ae07aaf4 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Tue, 9 Apr 2024 11:56:00 -0600 Subject: [PATCH 3/5] move stuff around for clarity --- api/serve.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/serve.go b/api/serve.go index 5721cdf..c129098 100644 --- a/api/serve.go +++ b/api/serve.go @@ -71,16 +71,11 @@ func CacheControlMiddleware(next http.Handler, maxAge int) http.Handler { func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { mux := http.NewServeMux() - staticFileServer := http.FileServer(http.Dir(argv.StaticPath)) - uploadFileServer := http.FileServer(http.Dir(argv.UploadPath)) - mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600))) - mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 3600))) - + // "dependency injection" cloudflareAdapter := &cloudflare.CloudflareExternalDNSAdapter{ APIToken: argv.CloudflareToken, ZoneId: argv.CloudflareZone, } - uploadAdapter := &filesystem.FilesystemAdapter{ BasePath: argv.UploadPath, Permissions: 0777, @@ -94,6 +89,11 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { } } + staticFileServer := http.FileServer(http.Dir(argv.StaticPath)) + uploadFileServer := http.FileServer(http.Dir(argv.UploadPath)) + mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600))) + mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 3600))) + mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(auth.ListUsersContinuation, auth.ListUsersContinuation)(template.TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) -- 2.40.1 From a32026d0133b868840d97b6b573310143c897269 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Tue, 9 Apr 2024 16:29:52 -0600 Subject: [PATCH 4/5] add error and success messages, finish profile validation --- .gitignore | 1 + api/auth/auth.go | 1 + api/dns/dns.go | 86 ++++++++------- api/guestbook/guestbook.go | 104 +++++++++--------- api/hcaptcha/hcaptcha.go | 4 +- api/keys/keys.go | 20 +++- api/profiles/profiles.go | 93 ++++++++++------ api/serve.go | 6 +- api/types/types.go | 4 +- database/migrate.go | 2 + database/users.go | 37 ++++--- static/css/club.css | 48 ++++++++ static/css/colors.css | 11 +- static/css/form.css | 3 + static/css/guestbook.css | 1 + static/css/styles.css | 36 +++++- static/js/components/infoBanners.js | 6 + static/js/script.js | 1 + templates/api_keys.html | 7 -- templates/base.html | 11 ++ templates/dns.html | 14 +-- templates/guestbook.html | 9 -- templates/home.html | 19 +++- templates/profile.html | 21 ++-- .../f54386d9-f310-4c5a-a3f9-e950320479f7 | Bin 29171 -> 0 bytes 25 files changed, 338 insertions(+), 207 deletions(-) create mode 100644 static/css/club.css create mode 100644 static/js/components/infoBanners.js delete mode 100644 uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 diff --git a/.gitignore b/.gitignore index c7bbdba..12a6077 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .env hatecomputers.club *.db +uploads diff --git a/api/auth/auth.go b/api/auth/auth.go index c54aad6..04d6c12 100644 --- a/api/auth/auth.go +++ b/api/auth/auth.go @@ -170,6 +170,7 @@ func VerifySessionContinuation(context *types.RequestContext, req *http.Request, func GoLoginContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + log.Println("GoLoginContinuation") http.SetCookie(resp, &http.Cookie{ Name: "redirect", Value: req.URL.Path, diff --git a/api/dns/dns.go b/api/dns/dns.go index bf91994..6357dfc 100644 --- a/api/dns/dns.go +++ b/api/dns/dns.go @@ -18,34 +18,6 @@ const MaxUserRecords = 100 var UserOwnedInternalFmtDomains = []string{"%s", "%s.endpoints"} -func userCanFuckWithDNSRecord(dbConn *sql.DB, user *database.User, record *database.DNSRecord, ownedInternalDomainFormats []string) bool { - ownedByUser := (user.ID == record.UserID) - if !ownedByUser { - return false - } - - if !record.Internal { - for _, format := range ownedInternalDomainFormats { - domain := fmt.Sprintf(format, user.Username) - - isInSubDomain := strings.HasSuffix(record.Name, "."+domain) - if domain == record.Name || isInSubDomain { - return true - } - } - return false - } - - owner, err := database.FindFirstDomainOwnerId(dbConn, record.Name) - if err != nil { - log.Println(err) - return false - } - - userIsOwnerOfDomain := owner == user.ID - return ownedByUser && userIsOwnerOfDomain -} - func ListDNSRecordsContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { dnsRecords, err := database.GetUserDNSRecords(context.DBConn, context.User.ID) @@ -63,8 +35,8 @@ func ListDNSRecordsContinuation(context *types.RequestContext, req *http.Request func CreateDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter, maxUserRecords int, allowedUserDomainFormats []string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { - formErrors := types.FormError{ - Errors: []string{}, + formErrors := types.BannerMessages{ + Messages: []string{}, } internal := req.FormValue("internal") == "on" || req.FormValue("internal") == "true" @@ -81,7 +53,7 @@ func CreateDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter, max ttlNum, err := strconv.Atoi(ttl) if err != nil { resp.WriteHeader(http.StatusBadRequest) - formErrors.Errors = append(formErrors.Errors, "invalid ttl") + formErrors.Messages = append(formErrors.Messages, "invalid ttl") } dnsRecordCount, err := database.CountUserDNSRecords(context.DBConn, context.User.ID) @@ -92,7 +64,7 @@ func CreateDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter, max } if dnsRecordCount >= maxUserRecords { resp.WriteHeader(http.StatusTooManyRequests) - formErrors.Errors = append(formErrors.Errors, "max records reached") + formErrors.Messages = append(formErrors.Messages, "max records reached") } dnsRecord := &database.DNSRecord{ @@ -106,10 +78,10 @@ func CreateDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter, max if !userCanFuckWithDNSRecord(context.DBConn, context.User, dnsRecord, allowedUserDomainFormats) { resp.WriteHeader(http.StatusUnauthorized) - formErrors.Errors = append(formErrors.Errors, "'name' must end with "+context.User.Username+" or you must be a domain owner for internal domains") + formErrors.Messages = append(formErrors.Messages, "'name' must end with "+context.User.Username+" or you must be a domain owner for internal domains") } - if len(formErrors.Errors) == 0 { + if len(formErrors.Messages) == 0 { if dnsRecord.Internal { dnsRecord.ID = utils.RandomId() } else { @@ -117,24 +89,28 @@ func CreateDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter, max if err != nil { log.Println(err) resp.WriteHeader(http.StatusInternalServerError) - formErrors.Errors = append(formErrors.Errors, err.Error()) + formErrors.Messages = append(formErrors.Messages, err.Error()) } } } - if len(formErrors.Errors) == 0 { + if len(formErrors.Messages) == 0 { _, err := database.SaveDNSRecord(context.DBConn, dnsRecord) if err != nil { log.Println(err) - formErrors.Errors = append(formErrors.Errors, "error saving record") + formErrors.Messages = append(formErrors.Messages, "error saving record") } } - if len(formErrors.Errors) == 0 { + if len(formErrors.Messages) == 0 { + formSuccess := types.BannerMessages{ + Messages: []string{"record added."}, + } + (*context.TemplateData)["Success"] = formSuccess return success(context, req, resp) } - (*context.TemplateData)["FormError"] = &formErrors + (*context.TemplateData)[""] = &formErrors (*context.TemplateData)["RecordForm"] = dnsRecord return failure(context, req, resp) } @@ -172,7 +148,39 @@ func DeleteDNSRecordContinuation(dnsAdapter external_dns.ExternalDNSAdapter) fun return failure(context, req, resp) } + formSuccess := types.BannerMessages{ + Messages: []string{"record deleted."}, + } + (*context.TemplateData)["Success"] = formSuccess return success(context, req, resp) } } } + +func userCanFuckWithDNSRecord(dbConn *sql.DB, user *database.User, record *database.DNSRecord, ownedInternalDomainFormats []string) bool { + ownedByUser := (user.ID == record.UserID) + if !ownedByUser { + return false + } + + if !record.Internal { + for _, format := range ownedInternalDomainFormats { + domain := fmt.Sprintf(format, user.Username) + + isInSubDomain := strings.HasSuffix(record.Name, "."+domain) + if domain == record.Name || isInSubDomain { + return true + } + } + return false + } + + owner, err := database.FindFirstDomainOwnerId(dbConn, record.Name) + if err != nil { + log.Println(err) + return false + } + + userIsOwnerOfDomain := owner == user.ID + return ownedByUser && userIsOwnerOfDomain +} diff --git a/api/guestbook/guestbook.go b/api/guestbook/guestbook.go index 60a7b4b..c0c7892 100644 --- a/api/guestbook/guestbook.go +++ b/api/guestbook/guestbook.go @@ -10,6 +10,60 @@ import ( "git.hatecomputers.club/hatecomputers/hatecomputers.club/utils" ) +func SignGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + name := req.FormValue("name") + message := req.FormValue("message") + + formErrors := types.BannerMessages{ + Messages: []string{}, + } + + entry := &database.GuestbookEntry{ + ID: utils.RandomId(), + Name: name, + Message: message, + } + formErrors.Messages = append(formErrors.Messages, validateGuestbookEntry(entry)...) + + if len(formErrors.Messages) == 0 { + _, err := database.SaveGuestbookEntry(context.DBConn, entry) + if err != nil { + log.Println(err) + formErrors.Messages = append(formErrors.Messages, "failed to save entry") + } + } + + if len(formErrors.Messages) > 0 { + (*context.TemplateData)["Error"] = formErrors + (*context.TemplateData)["EntryForm"] = entry + resp.WriteHeader(http.StatusBadRequest) + + return failure(context, req, resp) + } + + formSuccess := types.BannerMessages{ + Messages: []string{"entry added."}, + } + (*context.TemplateData)["Success"] = formSuccess + return success(context, req, resp) + } +} + +func ListGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + entries, err := database.GetGuestbookEntries(context.DBConn) + if err != nil { + log.Println(err) + resp.WriteHeader(http.StatusInternalServerError) + return failure(context, req, resp) + } + + (*context.TemplateData)["GuestbookEntries"] = entries + return success(context, req, resp) + } +} + func validateGuestbookEntry(entry *database.GuestbookEntry) []string { errors := []string{} @@ -33,53 +87,3 @@ func validateGuestbookEntry(entry *database.GuestbookEntry) []string { return errors } - -func SignGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { - return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { - name := req.FormValue("name") - message := req.FormValue("message") - - formErrors := types.FormError{ - Errors: []string{}, - } - - entry := &database.GuestbookEntry{ - ID: utils.RandomId(), - Name: name, - Message: message, - } - formErrors.Errors = append(formErrors.Errors, validateGuestbookEntry(entry)...) - - if len(formErrors.Errors) == 0 { - _, err := database.SaveGuestbookEntry(context.DBConn, entry) - if err != nil { - log.Println(err) - formErrors.Errors = append(formErrors.Errors, "failed to save entry") - } - } - - if len(formErrors.Errors) > 0 { - (*context.TemplateData)["FormError"] = formErrors - (*context.TemplateData)["EntryForm"] = entry - resp.WriteHeader(http.StatusBadRequest) - - return failure(context, req, resp) - } - - return success(context, req, resp) - } -} - -func ListGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { - return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { - entries, err := database.GetGuestbookEntries(context.DBConn) - if err != nil { - log.Println(err) - resp.WriteHeader(http.StatusInternalServerError) - return failure(context, req, resp) - } - - (*context.TemplateData)["GuestbookEntries"] = entries - return success(context, req, resp) - } -} diff --git a/api/hcaptcha/hcaptcha.go b/api/hcaptcha/hcaptcha.go index 007190d..e8ea238 100644 --- a/api/hcaptcha/hcaptcha.go +++ b/api/hcaptcha/hcaptcha.go @@ -62,8 +62,8 @@ func CaptchaVerificationContinuation(context *types.RequestContext, req *http.Re err := verifyCaptcha(secretKey, hCaptchaResponse) if err != nil { - (*context.TemplateData)["FormError"] = types.FormError{ - Errors: []string{"hCaptcha verification failed"}, + (*context.TemplateData)["Error"] = types.BannerMessages{ + Messages: []string{"hCaptcha verification failed"}, } resp.WriteHeader(http.StatusBadRequest) diff --git a/api/keys/keys.go b/api/keys/keys.go index cef3f3c..7702f3d 100644 --- a/api/keys/keys.go +++ b/api/keys/keys.go @@ -27,8 +27,8 @@ func ListAPIKeysContinuation(context *types.RequestContext, req *http.Request, r func CreateAPIKeyContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { - formErrors := types.FormError{ - Errors: []string{}, + formErrors := types.BannerMessages{ + Messages: []string{}, } numKeys, err := database.CountUserAPIKeys(context.DBConn, context.User.ID) @@ -39,11 +39,11 @@ func CreateAPIKeyContinuation(context *types.RequestContext, req *http.Request, } if numKeys >= MAX_USER_API_KEYS { - formErrors.Errors = append(formErrors.Errors, "max types keys reached") + formErrors.Messages = append(formErrors.Messages, "max types keys reached") } - if len(formErrors.Errors) > 0 { - (*context.TemplateData)["FormError"] = formErrors + if len(formErrors.Messages) > 0 { + (*context.TemplateData)["Error"] = formErrors return failure(context, req, resp) } @@ -56,6 +56,11 @@ func CreateAPIKeyContinuation(context *types.RequestContext, req *http.Request, resp.WriteHeader(http.StatusInternalServerError) return failure(context, req, resp) } + + formSuccess := types.BannerMessages{ + Messages: []string{"key created."}, + } + (*context.TemplateData)["Success"] = formSuccess return success(context, req, resp) } } @@ -82,6 +87,11 @@ func DeleteAPIKeyContinuation(context *types.RequestContext, req *http.Request, return failure(context, req, resp) } + formSuccess := types.BannerMessages{ + Messages: []string{"key deleted."}, + } + (*context.TemplateData)["Success"] = formSuccess + return success(context, req, resp) } } diff --git a/api/profiles/profiles.go b/api/profiles/profiles.go index c46d2a2..8e10e5f 100644 --- a/api/profiles/profiles.go +++ b/api/profiles/profiles.go @@ -3,6 +3,7 @@ package profiles import ( "log" "net/http" + "strings" "git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/files" "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" @@ -27,71 +28,91 @@ func GetProfileContinuation(context *types.RequestContext, req *http.Request, re func UpdateProfileContinuation(fileAdapter files.FilesAdapter, maxAvatarSize int, avatarPath string, avatarPrefix string) func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { - formErrors := types.FormError{ - Errors: []string{}, + formErrors := types.BannerMessages{ + Messages: []string{}, } err := req.ParseMultipartForm(int64(maxAvatarSize)) if err != nil { - log.Println(err) - - formErrors.Errors = append(formErrors.Errors, "avatar file too large") + formErrors.Messages = append(formErrors.Messages, "avatar file too large") } - if len(formErrors.Errors) == 0 { + if len(formErrors.Messages) == 0 { file, _, err := req.FormFile("avatar") - if file == nil { - formErrors.Errors = append(formErrors.Errors, "avatar required") - } - if err != nil { - formErrors.Errors = append(formErrors.Errors, "error uploading avatar") - } else { + if file != nil && err != nil { + formErrors.Messages = append(formErrors.Messages, "error uploading avatar") + } else if file != nil { defer file.Close() + reader := http.MaxBytesReader(resp, file, int64(maxAvatarSize)) + defer reader.Close() - _, err = fileAdapter.CreateFile(avatarPath+context.User.ID, file) + _, err = fileAdapter.CreateFile(avatarPath+context.User.ID, reader) if err != nil { log.Println(err) - formErrors.Errors = append(formErrors.Errors, "error saving avatar") + formErrors.Messages = append(formErrors.Messages, "error saving avatar (is it too big?)") } } } - bio := req.FormValue("bio") - location := req.FormValue("location") - website := req.FormValue("website") - if len(bio) > 128 { - formErrors.Errors = append(formErrors.Errors, "bio too long, keep it to 128") - } - if len(location) > 32 { - formErrors.Errors = append(formErrors.Errors, "location too long, keep it to 32") - } - if len(website) > 64 { - formErrors.Errors = append(formErrors.Errors, "website too long, keep it to 64") - } - - if len(formErrors.Errors) == 0 { - context.User.Bio = bio - context.User.Location = location - context.User.Website = website - context.User.Avatar = avatarPrefix + context.User.ID + context.User.Bio = strings.Trim(req.FormValue("bio"), "\n") + context.User.Pronouns = req.FormValue("pronouns") + context.User.Location = req.FormValue("location") + context.User.Website = req.FormValue("website") + context.User.Avatar = avatarPrefix + context.User.ID + formErrors.Messages = append(formErrors.Messages, validateProfileUpdate(context.User)...) + if len(formErrors.Messages) == 0 { _, err = database.SaveUser(context.DBConn, context.User) if err != nil { - formErrors.Errors = append(formErrors.Errors, "error saving profile") + formErrors.Messages = append(formErrors.Messages, "error saving profile") } } (*context.TemplateData)["Profile"] = context.User - (*context.TemplateData)["FormError"] = formErrors + (*context.TemplateData)["Error"] = formErrors - if len(formErrors.Errors) > 0 { - log.Println(formErrors.Errors) + if len(formErrors.Messages) > 0 { + log.Println(formErrors.Messages) resp.WriteHeader(http.StatusBadRequest) return failure(context, req, resp) } + formSuccess := types.BannerMessages{ + Messages: []string{"profile updated"}, + } + (*context.TemplateData)["Success"] = formSuccess return success(context, req, resp) } } } + +func validateProfileUpdate(user *database.User) []string { + errors := []string{} + + if (!strings.HasPrefix(user.Website, "https://") && !strings.HasPrefix(user.Website, "http://")) || len(user.Website) < 8 { + errors = append(errors, "website must be a valid URL") + } + if len(user.Website) > 64 { + errors = append(errors, "website cannot be longer than 64 characters") + } + + if len(user.Pronouns) > 64 { + errors = append(errors, "pronouns cannot be longer than 64 characters") + } + + if len(user.Bio) > 128 { + errors = append(errors, "bio cannot be longer than 128 characters") + } + + newLines := strings.Count(user.Bio, "\n") + if newLines > 8 { + errors = append(errors, "message cannot contain more than 8 new lines") + } + + if len(user.Location) > 32 { + errors = append(errors, "location cannot be longer than 64 characters") + } + + return errors +} diff --git a/api/serve.go b/api/serve.go index c129098..a688445 100644 --- a/api/serve.go +++ b/api/serve.go @@ -92,7 +92,7 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { staticFileServer := http.FileServer(http.Dir(argv.StaticPath)) uploadFileServer := http.FileServer(http.Dir(argv.UploadPath)) mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600))) - mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 3600))) + mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 60))) mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() @@ -126,7 +126,9 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server { mux.HandleFunc("POST /profile", func(w http.ResponseWriter, r *http.Request) { requestContext := makeRequestContext() - LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath, profiles.AvatarPrefix), auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) + updateProfileContinuation := profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath, profiles.AvatarPrefix) + + LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(updateProfileContinuation, auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), template.TemplateContinuation("profile.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation) }) mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) { diff --git a/api/types/types.go b/api/types/types.go index bbc25ea..84ed93c 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -20,8 +20,8 @@ type RequestContext struct { User *database.User } -type FormError struct { - Errors []string +type BannerMessages struct { + Messages []string } type Continuation func(*RequestContext, *http.Request, http.ResponseWriter) ContinuationChain diff --git a/database/migrate.go b/database/migrate.go index fbba6ff..e9e21b7 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -4,6 +4,7 @@ import ( "log" "database/sql" + _ "github.com/mattn/go-sqlite3" ) @@ -144,6 +145,7 @@ func MigrateProfiles(dbConn *sql.DB) (*sql.DB, error) { } columns := map[string]string{} + columns["pronouns"] = "unspecified" columns["bio"] = "a computer hater" columns["location"] = "earth" columns["website"] = "https://hatecomputers.club" diff --git a/database/users.go b/database/users.go index cb1b3d2..804b723 100644 --- a/database/users.go +++ b/database/users.go @@ -27,6 +27,7 @@ type User struct { Bio string `json:"bio"` Location string `json:"location"` Website string `json:"website"` + Pronouns string `json:"pronouns"` // liberals!! :O Avatar string `json:"avatar"` CreatedAt time.Time `json:"created_at"` } @@ -37,25 +38,10 @@ type UserSession struct { ExpireAt time.Time `json:"expire_at"` } -func GetUser(dbConn *sql.DB, id string) (*User, error) { - log.Println("getting user", id) - - row := dbConn.QueryRow(`SELECT id, mail, username, display_name, bio, location, website, avatar, created_at FROM users WHERE id = ?;`, id) - - var user User - err := row.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.CreatedAt) - if err != nil { - log.Println(err) - return nil, err - } - - return &user, nil -} - func ListUsers(dbConn *sql.DB) ([]*User, error) { log.Println("listing users") - rows, err := dbConn.Query(`SELECT id, mail, username, display_name, bio, location, website, avatar, created_at FROM users;`) + rows, err := dbConn.Query(`SELECT id, mail, username, display_name, bio, location, website, avatar, pronouns, created_at FROM users;`) if err != nil { log.Println(err) return nil, err @@ -65,7 +51,7 @@ func ListUsers(dbConn *sql.DB) ([]*User, error) { var users []*User for rows.Next() { var user User - err := rows.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.CreatedAt) + err := rows.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.Pronouns, &user.CreatedAt) if err != nil { log.Println(err) return nil, err @@ -77,6 +63,21 @@ func ListUsers(dbConn *sql.DB) ([]*User, error) { return users, nil } +func GetUser(dbConn *sql.DB, id string) (*User, error) { + log.Println("getting user", id) + + row := dbConn.QueryRow(`SELECT id, mail, username, display_name, bio, location, website, avatar, pronouns, created_at FROM users WHERE id = ?;`, id) + + var user User + err := row.Scan(&user.ID, &user.Mail, &user.Username, &user.DisplayName, &user.Bio, &user.Location, &user.Website, &user.Avatar, &user.Pronouns, &user.CreatedAt) + if err != nil { + log.Println(err) + return nil, err + } + + return &user, nil +} + func FindOrSaveBaseUser(dbConn *sql.DB, user *User) (*User, error) { log.Println("finding or saving user", user.ID) @@ -91,7 +92,7 @@ func FindOrSaveBaseUser(dbConn *sql.DB, user *User) (*User, error) { func SaveUser(dbConn *sql.DB, user *User) (*User, error) { log.Println("saving user", user.ID) - _, err := dbConn.Exec(`INSERT OR REPLACE INTO users (id, mail, username, display_name, bio, location, website, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?);`, user.ID, user.Mail, user.Username, user.DisplayName, user.Bio, user.Location, user.Website, user.Avatar) + _, err := dbConn.Exec(`INSERT INTO users (id, mail, username, display_name, bio, location, website, pronouns, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET mail = excluded.mail, username = excluded.username, display_name = excluded.display_name, bio = excluded.bio, location = excluded.location, website = excluded.website, pronouns = excluded.pronouns, avatar = excluded.avatar;`, user.ID, user.Mail, user.Username, user.DisplayName, user.Bio, user.Location, user.Website, user.Pronouns, user.Avatar) if err != nil { return nil, err } diff --git a/static/css/club.css b/static/css/club.css new file mode 100644 index 0000000..747f2d0 --- /dev/null +++ b/static/css/club.css @@ -0,0 +1,48 @@ +.club-members { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: left; + gap: 20px; + padding: 20px; +} + +.club-member { + flex: 1; + background-color: var(--background-color-2); + border: 1px solid var(--border-color); + padding: 10px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + gap: 10px; + max-width: 600px; + min-width: 400px; + line-break: anywhere; +} + +.club-bio { + white-space: pre-wrap; + border-top: 1px solid var(--border-color); +} + +.avatar { + flex: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.avatar div { + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + width: 120px; + height: 120px; + border-radius: 25%; +} + +.about { + flex: 2; +} diff --git a/static/css/colors.css b/static/css/colors.css index c68bf8e..46357d9 100644 --- a/static/css/colors.css +++ b/static/css/colors.css @@ -1,7 +1,8 @@ :root { --background-color-light: #f4e8e9; - --background-color-light-2: #f7f7f7; + --background-color-light-2: #f5e6f3; --text-color-light: #333; + --confirm-color-light: #91d9bb; --link-color-light: #d291bc; --container-bg-light: #fff7f87a; --border-color-light: #692fcc; @@ -10,6 +11,7 @@ --background-color-dark: #333; --background-color-dark-2: #2c2c2c; --text-color-dark: #f4e8e9; + --confirm-color-dark: #4d8f73; --link-color-dark: #b86b77; --container-bg-dark: #424242ea; --border-color-dark: #956ade; @@ -24,6 +26,7 @@ --container-bg: var(--container-bg-dark); --border-color: var(--border-color-dark); --error-color: var(--error-color-dark); + --confirm-color: var(--confirm-color-dark); } [data-theme="LIGHT"] { @@ -34,9 +37,15 @@ --container-bg: var(--container-bg-light); --border-color: var(--border-color-light); --error-color: var(--error-color-light); + --confirm-color: var(--confirm-color-light); } .error { background-color: var(--error-color); padding: 1rem; } + +.success { + background-color: var(--confirm-color); + padding: 1rem; +} diff --git a/static/css/form.css b/static/css/form.css index a5dc358..7ccd8db 100644 --- a/static/css/form.css +++ b/static/css/form.css @@ -36,4 +36,7 @@ textarea { margin: 0 0 1em; border: 1px solid var(--border-color); background: var(--container-bg); + + resize: vertical; + min-height: 100px; } diff --git a/static/css/guestbook.css b/static/css/guestbook.css index 0fb7a16..6241717 100644 --- a/static/css/guestbook.css +++ b/static/css/guestbook.css @@ -3,6 +3,7 @@ border: 1px solid var(--border-color); padding: 10px; + max-width: 700px; } .entry-name { diff --git a/static/css/styles.css b/static/css/styles.css index ba58018..886052e 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -3,6 +3,7 @@ @import "/static/css/table.css"; @import "/static/css/form.css"; @import "/static/css/guestbook.css"; +@import "/static/css/club.css"; @font-face { font-family: "ComicSans"; @@ -22,15 +23,27 @@ } @-webkit-keyframes cursor { - 0% {cursor: url("/static/img/cursor-2.png"), auto;} - 50% {cursor: url("/static/img/cursor-1.png"), auto;} - 100% {cursor: url("/static/img/cursor-2.png"), auto;} + 0% { + cursor: url("/static/img/cursor-2.png"), auto; + } + 50% { + cursor: url("/static/img/cursor-1.png"), auto; + } + 100% { + cursor: url("/static/img/cursor-2.png"), auto; + } } @keyframes cursor { - 0% {cursor: url("/static/img/cursor-2.png"), auto;} - 50% {cursor: url("/static/img/cursor-1.png"), auto;} - 100% {cursor: url("/static/img/cursor-2.png"), auto;} + 0% { + cursor: url("/static/img/cursor-2.png"), auto; + } + 50% { + cursor: url("/static/img/cursor-1.png"), auto; + } + 100% { + cursor: url("/static/img/cursor-2.png"), auto; + } } body { @@ -70,3 +83,14 @@ hr { max-width: 900px; gap: 10px 10px; } + +.info { + margin-bottom: 1rem; + max-width: 600px; + + transition: opacity 0.3s; +} + +.info:hover { + opacity: 0.8; +} diff --git a/static/js/components/infoBanners.js b/static/js/components/infoBanners.js new file mode 100644 index 0000000..6a19864 --- /dev/null +++ b/static/js/components/infoBanners.js @@ -0,0 +1,6 @@ +const infoBanners = document.querySelectorAll(".info"); +Array.from(infoBanners).forEach((infoBanner) => { + infoBanner.addEventListener("click", () => { + infoBanner.remove(); + }); +}); diff --git a/static/js/script.js b/static/js/script.js index 56233e3..b5e6249 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -1,5 +1,6 @@ const scripts = [ "/static/js/components/themeSwitcher.js", "/static/js/components/formatDate.js", + "/static/js/components/infoBanners.js", ]; requirejs(scripts); diff --git a/templates/api_keys.html b/templates/api_keys.html index cd4d274..018fda3 100644 --- a/templates/api_keys.html +++ b/templates/api_keys.html @@ -28,12 +28,5 @@

generate key.


- {{ if .FormError }} - {{ if (len .FormError.Errors) }} - {{ range $error := .FormError.Errors }} -
{{ $error }}
- {{ end }} - {{ end }} - {{ end }} {{ end }} diff --git a/templates/base.html b/templates/base.html index 285b0dc..89d6dd2 100644 --- a/templates/base.html +++ b/templates/base.html @@ -48,6 +48,17 @@
+ {{ if and .Success (gt (len .Success.Messages) 0) }} + {{ range $message := .Success.Messages }} +
{{ $message }}
+ {{ end }} + {{ end }} + {{ if and .Error (gt (len .Error.Messages) 0) }} + {{ range $error := .Error.Messages }} +
{{ $error }}
+ {{ end }} + {{ end }} + {{ template "content" . }}
diff --git a/templates/dns.html b/templates/dns.html index d16ed89..2f3f0a7 100644 --- a/templates/dns.html +++ b/templates/dns.html @@ -76,18 +76,6 @@ {{ end }} /> - - - - - {{ if .FormError }} - {{ if (len .FormError.Errors) }} - {{ range $error := .FormError.Errors }} -
{{ $error }}
- {{ end }} - {{ end }} - {{ end }} + - - {{ end }} diff --git a/templates/guestbook.html b/templates/guestbook.html index 85727c7..d1f4417 100644 --- a/templates/guestbook.html +++ b/templates/guestbook.html @@ -21,18 +21,9 @@

-
- {{ if .FormError }} - {{ if (len .FormError.Errors) }} - {{ range $error := .FormError.Errors }} -
{{ $error }}
- {{ end }} - {{ end }} - {{ end }}
diff --git a/templates/home.html b/templates/home.html index 09edc20..76bbc6a 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,8 +1,19 @@ {{ define "content" }} -

hello there!

-

current peeps:

+

hello there!

+

current peeps in the club :D

+
{{ end }} diff --git a/templates/profile.html b/templates/profile.html index 52f7127..a6e1b68 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -3,27 +3,22 @@

hey {{ .Profile.DisplayName }}


- - + + - + - + - + + + + - - {{ if .FormError }} - {{ if (len .FormError.Errors) }} - {{ range $error := .FormError.Errors }} -
{{ $error }}
- {{ end }} - {{ end }} - {{ end }}
{{ end }} diff --git a/uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 b/uploads/avatars/f54386d9-f310-4c5a-a3f9-e950320479f7 deleted file mode 100644 index 60b7a106183eaaf7e94fdc27ddaa6df251babe36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29171 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 -- 2.40.1 From ae1ab91deff4f8f33c89df63c0268e3bad1bdfc5 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Tue, 9 Apr 2024 16:33:30 -0600 Subject: [PATCH 5/5] fix old call in hcdns_test --- hcdns/server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hcdns/server_test.go b/hcdns/server_test.go index f1b283f..4fdf03d 100644 --- a/hcdns/server_test.go +++ b/hcdns/server_test.go @@ -27,7 +27,7 @@ func setup(arguments *args.Arguments) (*sql.DB, *dns.Server, string, func()) { testUser := &database.User{ ID: "test", } - database.FindOrSaveUser(testDb, testUser) + database.FindOrSaveBaseUser(testDb, testUser) dnsArguments := arguments if dnsArguments == nil { -- 2.40.1