- commit
- c0517ee
- parent
- c0208b3
- author
- Eric Bower
- date
- 2026-03-28 23:12:36 -0400 EDT
docs: rm auto form
5 files changed,
+6,
-135
+0,
-124
1@@ -1,124 +0,0 @@
2-# Auto-Form Feature for pgs.sh
3-
4-## Overview
5-
6-The auto-form feature allows users to create HTML forms on their pgs.sh sites that automatically submit data to the pgs database. Form submissions can then be retrieved via the pgs CLI in JSON format.
7-
8-## How It Works
9-
10-1. Form submissions are automatically captured and stored in PostgreSQL
11-2. Users can retrieve form data via the pgs CLI
12-
13-## Database Schema
14-
15-```sql
16-CREATE TABLE form_entries (
17- id uuid NOT NULL DEFAULT uuid_generate_v4(),
18- user_id uuid NOT NULL,
19- name VARCHAR(255) NOT NULL,
20- data jsonb NOT NULL,
21- created_at timestamp without time zone NOT NULL DEFAULT NOW(),
22- CONSTRAINT form_entries_pkey PRIMARY KEY (id),
23- CONSTRAINT fk_form_entries_users
24- FOREIGN KEY(user_id)
25- REFERENCES app_users(id)
26- ON DELETE CASCADE
27-);
28-
29-CREATE INDEX IF NOT EXISTS idx_form_entries_user ON form_entries(user_id);
30-CREATE INDEX IF NOT EXISTS idx_form_entries_name ON form_entries(name);
31-```
32-
33-### Migration
34-
35-Run the migration:
36-```bash
37-make latest
38-```
39-
40-Or run all migrations:
41-```bash
42-make migrate
43-```
44-
45-## HTML Form Example
46-
47-```html
48-<form method="POST" action="/forms/example" data-pgs="true">
49- <p>
50- <label>Your Name: <input type="text" name="name" /></label>
51- </p>
52- <p>
53- <label>Your Email: <input type="email" name="email" /></label>
54- </p>
55- <p>
56- <label>Your Role: <select name="role[]" multiple>
57- <option value="leader">Leader</option>
58- <option value="follower">Follower</option>
59- </select></label>
60- </p>
61- <p>
62- <label>Message: <textarea name="message"></textarea></label>
63- </p>
64- <p>
65- <button type="submit">Send</button>
66- </p>
67-</form>
68-```
69-
70-## CLI Commands
71-
72-### List all form names for a user
73-```bash
74-ssh pgs.sh forms ls
75-```
76-
77-### Get form submissions for a specific form
78-```bash
79-ssh pgs.sh forms show example
80-```
81-
82-Output (JSON):
83-```json
84-[
85- {
86- "id": "uuid",
87- "name": "contact",
88- "data": {
89- "name": "John Doe",
90- "email": "john@example.com",
91- "role": ["leader", "follower"],
92- "message": "Hello!"
93- },
94- "created_at": "2026-03-05T12:00:00Z"
95- }
96-]
97-```
98-
99-### Delete all submissions for a form
100-```bash
101-ssh pgs.sh forms rm example --write
102-```
103-
104-## Data Storage
105-
106-- Form data is stored in PostgreSQL `form_entries` table
107-- Each submission is a JSON object with form field names as keys
108-- Data is associated with the user, not the project
109-- Form data is deleted when the user account is deleted (CASCADE)
110-
111-## Implementation Details
112-
113-### Database Methods
114-
115-```go
116-InsertFormEntry(userID, name string, data map[string]interface{}) error
117-FindFormEntriesByUserAndName(userID, name string) ([]*db.FormEntry, error)
118-FindFormNamesByUser(userID string) ([]string, error)
119-RemoveFormEntriesByUserAndName(userID, name string) error
120-```
121-
122-## More features
123-
124-- Form validation and confirmation pages
125-- CSRF token in form and validated in post handler
+1,
-3
1@@ -144,9 +144,7 @@ func (h *UploadAssetHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils
2 fileInfo.FSize = info.Size
3 fileInfo.FModTime = info.LastModified
4
5- reader := storage.NewAllReaderAt(contents)
6-
7- return fileInfo, reader, nil
8+ return fileInfo, contents, nil
9 }
10
11 func (h *UploadAssetHandler) List(s *pssh.SSHServerConnSession, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {
+1,
-2
1@@ -123,7 +123,6 @@ func (h *UploadImgHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils.F
2 if err != nil {
3 return nil, nil, err
4 }
5- reader := storage.NewAllReaderAt(contents)
6
7 fileInfo := &sendutils.VirtualFile{
8 FName: cleanFilename,
9@@ -132,7 +131,7 @@ func (h *UploadImgHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils.F
10 FModTime: info.LastModified,
11 }
12
13- return fileInfo, reader, nil
14+ return fileInfo, contents, nil
15 }
16
17 func (h *UploadImgHandler) Write(s *pssh.SSHServerConnSession, entry *sendutils.FileEntry) (string, error) {
+3,
-3
1@@ -10,9 +10,8 @@ type ReadAndReaderAt interface {
2 }
3
4 type ReadAndReaderAtCloser interface {
5- io.Reader
6 io.ReaderAt
7- io.ReadCloser
8+ io.ReadSeekCloser
9 }
10
11 func NopReadAndReaderAtCloser(r ReadAndReaderAt) ReadAndReaderAtCloser {
12@@ -23,4 +22,5 @@ type nopReadAndReaderAt struct {
13 ReadAndReaderAt
14 }
15
16-func (nopReadAndReaderAt) Close() error { return nil }
17+func (nopReadAndReaderAt) Close() error { return nil }
18+func (nopReadAndReaderAt) Seek(int64, int) (int64, error) { return 0, nil }
+1,
-3
1@@ -109,9 +109,7 @@ func (h *UploadAssetHandler) Read(s *pssh.SSHServerConnSession, entry *utils.Fil
2 fileInfo.FSize = info.Size
3 fileInfo.FModTime = info.LastModified
4
5- reader := NewAllReaderAt(contents)
6-
7- return fileInfo, reader, nil
8+ return fileInfo, contents, nil
9 }
10
11 func (h *UploadAssetHandler) List(s *pssh.SSHServerConnSession, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {