Skip to content

Commit d7932fc

Browse files
committed
fix examples auth and smoke paths
1 parent ab095e0 commit d7932fc

11 files changed

Lines changed: 154 additions & 30 deletions

File tree

examples/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,19 @@ is required by project-level compiler commands.
1818
| SSR and guards | `examples/auth-guard/` | `cd examples/auth-guard && make check && make routes && make build` |
1919
| One generated binary | `examples/embed/` | `go run ./cmd/gowdk build --out /tmp/gowdk-embed-build --app /tmp/gowdk-embed-app --bin /tmp/gowdk-embed-site examples/embed/site.page.gwdk` |
2020
| Contracts and realtime | `examples/contracts/` | `go run ./cmd/gowdk build --config examples/contracts/gowdk.config.go --out /tmp/gowdk-contracts-build --app /tmp/gowdk-contracts-app --bin /tmp/gowdk-contracts-site examples/contracts/patients.page.gwdk` |
21-
| CSS and Tailwind | `examples/css/`, `examples/tailwind/` | `go run ./cmd/gowdk build --config examples/css/gowdk.config.go --out /tmp/gowdk-css-build examples/css/styled.page.gwdk` |
21+
| CSS | `examples/css/` | `go run ./cmd/gowdk build --config examples/css/gowdk.config.go --out /tmp/gowdk-css-build examples/css/styled.page.gwdk` |
22+
| Tailwind | `examples/tailwind/` | `go run ./cmd/gowdk build --config examples/tailwind/gowdk.config.go --out /tmp/gowdk-tailwind-build examples/tailwind/site.page.gwdk` |
23+
| SEO | `examples/seo/` | `go run ./cmd/gowdk build --config examples/seo/gowdk.config.go --out /tmp/gowdk-seo-build examples/seo/*.gwdk` |
2224
| Component assets and WASM islands | `examples/components/` | `go run ./cmd/gowdk build --out /tmp/gowdk-wasm-island examples/components/wasm/*.gwdk` |
2325
| Full-stack vertical slice | `examples/flagship/` | `cd examples/flagship && make check && make routes && make build` |
2426

27+
The Tailwind build command requires the standalone `tailwindcss` executable on
28+
`PATH`. To validate the source without running the CSS processor:
29+
30+
```sh
31+
go run ./cmd/gowdk check --config examples/tailwind/gowdk.config.go examples/tailwind/site.page.gwdk
32+
```
33+
2534
## Full Example Check
2635

2736
Validate the broad source set with SSR enabled:

examples/flagship/Makefile

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
ROOT := ../..
2-
CONFIG := examples/flagship/gowdk.config.go
3-
APP_DIR := examples/flagship/.gowdk/app
1+
CONFIG := gowdk.config.go
2+
APP_DIR := .gowdk/app
43
HOOK_FILE := $(APP_DIR)/gowdkapp/flagship_hooks.go
54

65
.PHONY: check routes build serve clean
76

87
check:
9-
cd $(ROOT) && go run ./cmd/gowdk check --config $(CONFIG)
8+
go run ../../cmd/gowdk check --config $(CONFIG)
109

1110
routes:
12-
cd $(ROOT) && go run ./cmd/gowdk routes --config $(CONFIG)
11+
go run ../../cmd/gowdk routes --config $(CONFIG)
1312

1413
$(HOOK_FILE): apphooks/flagship_hooks.go.txt
15-
mkdir -p $(ROOT)/$(APP_DIR)/gowdkapp
16-
cp apphooks/flagship_hooks.go.txt $(ROOT)/$(HOOK_FILE)
14+
mkdir -p $(APP_DIR)/gowdkapp
15+
cp apphooks/flagship_hooks.go.txt $(HOOK_FILE)
1716

1817
build: $(HOOK_FILE)
19-
cd $(ROOT) && go run ./cmd/gowdk build --config $(CONFIG) --target flagship
18+
go run ../../cmd/gowdk build --config $(CONFIG) --target flagship
2019

2120
serve: build
22-
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_ADDR=127.0.0.1:8092 bin/flagship
21+
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_FLAGSHIP_SECRET=development-flagship-session-secret-32b GOWDK_FLAGSHIP_PASSWORD=demo-password GOWDK_ADDR=127.0.0.1:8092 bin/flagship
2322

2423
clean:
2524
rm -rf .gowdk bin dist

examples/flagship/README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ Run from this directory:
1111
make check
1212
make routes
1313
make build
14-
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_ADDR=127.0.0.1:8092 bin/flagship
14+
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b \
15+
GOWDK_FLAGSHIP_SECRET=development-flagship-session-secret-32b \
16+
GOWDK_FLAGSHIP_PASSWORD=demo-password \
17+
GOWDK_ADDR=127.0.0.1:8092 \
18+
bin/flagship
1519
```
1620

1721
Expected build outputs:
@@ -66,9 +70,10 @@ The main generated routes are:
6670

6771
## Demo Credentials
6872

69-
Use `demo@example.com` and `demo-password`. Override them with
70-
`GOWDK_FLAGSHIP_EMAIL`, `GOWDK_FLAGSHIP_PASSWORD`, and
71-
`GOWDK_FLAGSHIP_SECRET`.
73+
Use `demo@example.com` and set `GOWDK_FLAGSHIP_PASSWORD=demo-password` for the
74+
demo. `GOWDK_FLAGSHIP_EMAIL` can override the demo email.
75+
`GOWDK_FLAGSHIP_PASSWORD` is required; `GOWDK_FLAGSHIP_SECRET` is also required
76+
and signs the demo session cookie.
7277

7378
## Current Limitations
7479

examples/flagship/apphooks/flagship_hooks.go.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package gowdkapp
33
import (
44
"time"
55

6-
gowdkratelimit "github.com/cssbruno/gowdk/addons/ratelimit"
76
flagship "github.com/cssbruno/gowdk/examples/flagship/src/app"
87
gowdkguard "github.com/cssbruno/gowdk/runtime/guard"
8+
gowdkratelimit "github.com/cssbruno/gowdk/runtime/ratelimit"
99
)
1010

1111
func init() {

examples/flagship/gowdk.config.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ var Config = gowdk.Config{
1414
Include: []string{"src/**/*.gwdk"},
1515
},
1616
Build: gowdk.BuildConfig{
17-
Output: "examples/flagship/dist",
17+
Output: "dist",
1818
Targets: []gowdk.BuildTargetConfig{
1919
{
2020
Name: "flagship",
21-
Output: "examples/flagship/dist",
22-
App: "examples/flagship/.gowdk/app",
23-
Binary: "examples/flagship/bin/flagship",
21+
Output: "dist",
22+
App: ".gowdk/app",
23+
Binary: "bin/flagship",
2424
},
2525
},
2626
},
2727
CSS: gowdk.CSSConfig{
28-
Include: []string{"examples/flagship/styles/**/*.css"},
28+
Include: []string{"styles/*.css"},
2929
Output: gowdk.CSSOutputConfig{
3030
Dir: "assets/gowdk",
3131
HrefPrefix: "/assets/gowdk",

examples/flagship/src/app/app.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,17 @@ import (
2424
const sessionCookie = "gowdk_flagship_session"
2525

2626
func Login(_ context.Context, values form.Values) (response.Response, error) {
27+
if len(sessionSecret()) == 0 {
28+
return response.RedirectTo("/?login=failed"), nil
29+
}
30+
wantEmail, wantPassword, ok := configuredCredentials()
31+
if !ok {
32+
return response.RedirectTo("/?login=failed"), nil
33+
}
34+
2735
email := strings.TrimSpace(values.First("email"))
2836
password := values.First("password")
29-
if !constantEqual(email, env("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")) ||
30-
!constantEqual(password, env("GOWDK_FLAGSHIP_PASSWORD", "demo-password")) {
37+
if !constantEqual(email, wantEmail) || !constantEqual(password, wantPassword) {
3138
return response.RedirectTo("/?login=failed"), nil
3239
}
3340

@@ -127,6 +134,9 @@ var sessions = struct {
127134
}{Values: map[string]session{}}
128135

129136
func currentSession(request *http.Request) (session, bool) {
137+
if len(sessionSecret()) == 0 {
138+
return session{}, false
139+
}
130140
if request == nil {
131141
return session{}, false
132142
}
@@ -159,11 +169,21 @@ func sign(value string) string {
159169
}
160170

161171
func signature(value string) string {
162-
mac := hmac.New(sha256.New, []byte(env("GOWDK_FLAGSHIP_SECRET", "development-flagship-secret-change-me")))
172+
mac := hmac.New(sha256.New, sessionSecret())
163173
_, _ = mac.Write([]byte(value))
164174
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
165175
}
166176

177+
func sessionSecret() []byte {
178+
return []byte(strings.TrimSpace(os.Getenv("GOWDK_FLAGSHIP_SECRET")))
179+
}
180+
181+
func configuredCredentials() (email, password string, ok bool) {
182+
email = env("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")
183+
password = strings.TrimSpace(os.Getenv("GOWDK_FLAGSHIP_PASSWORD"))
184+
return email, password, password != ""
185+
}
186+
167187
func sessionDuration() time.Duration {
168188
return 12 * time.Hour
169189
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package flagship
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"strings"
7+
"testing"
8+
9+
"github.com/cssbruno/gowdk/runtime/form"
10+
"github.com/cssbruno/gowdk/runtime/response"
11+
)
12+
13+
func TestLoginRequiresExplicitSessionSecret(t *testing.T) {
14+
resetTestSessions(t)
15+
t.Setenv("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")
16+
t.Setenv("GOWDK_FLAGSHIP_SECRET", "")
17+
t.Setenv("GOWDK_FLAGSHIP_PASSWORD", "demo-password")
18+
19+
result := loginForTest(t, "demo@example.com", "demo-password")
20+
21+
assertLoginFailed(t, result)
22+
}
23+
24+
func TestLoginRequiresExplicitPassword(t *testing.T) {
25+
resetTestSessions(t)
26+
t.Setenv("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")
27+
t.Setenv("GOWDK_FLAGSHIP_SECRET", "development-flagship-session-secret-32b")
28+
t.Setenv("GOWDK_FLAGSHIP_PASSWORD", "")
29+
30+
result := loginForTest(t, "demo@example.com", "demo-password")
31+
32+
assertLoginFailed(t, result)
33+
}
34+
35+
func TestLoginCreatesSignedSessionWithExplicitCredentials(t *testing.T) {
36+
resetTestSessions(t)
37+
t.Setenv("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")
38+
t.Setenv("GOWDK_FLAGSHIP_SECRET", "development-flagship-session-secret-32b")
39+
t.Setenv("GOWDK_FLAGSHIP_PASSWORD", "demo-password")
40+
41+
result := loginForTest(t, "demo@example.com", "demo-password")
42+
43+
if result.Kind != response.Redirect || result.URL != "/dashboard" {
44+
t.Fatalf("login result = %#v, want redirect to dashboard", result)
45+
}
46+
if len(result.Cookies) != 1 {
47+
t.Fatalf("cookies = %#v, want one session cookie", result.Cookies)
48+
}
49+
cookie := result.Cookies[0]
50+
if cookie.Name != sessionCookie || !cookie.HttpOnly || cookie.Value == "" || !strings.Contains(cookie.Value, ".") {
51+
t.Fatalf("session cookie = %#v", cookie)
52+
}
53+
54+
request, err := http.NewRequest(http.MethodGet, "/dashboard", nil)
55+
if err != nil {
56+
t.Fatal(err)
57+
}
58+
request.AddCookie(&cookie)
59+
if current, ok := currentSession(request); !ok || current.Email != "demo@example.com" {
60+
t.Fatalf("current session = %#v ok=%v", current, ok)
61+
}
62+
}
63+
64+
func loginForTest(t *testing.T, email string, password string) response.Response {
65+
t.Helper()
66+
result, err := Login(context.Background(), form.Values{
67+
"email": {email},
68+
"password": {password},
69+
})
70+
if err != nil {
71+
t.Fatalf("Login returned error: %v", err)
72+
}
73+
return result
74+
}
75+
76+
func assertLoginFailed(t *testing.T, result response.Response) {
77+
t.Helper()
78+
if result.Kind != response.Redirect || result.URL != "/?login=failed" {
79+
t.Fatalf("login result = %#v, want failed redirect", result)
80+
}
81+
if len(result.Cookies) != 0 {
82+
t.Fatalf("failed login set cookies: %#v", result.Cookies)
83+
}
84+
}
85+
86+
func resetTestSessions(t *testing.T) {
87+
t.Helper()
88+
sessions.Lock()
89+
defer sessions.Unlock()
90+
sessions.Values = map[string]session{}
91+
}

examples/flagship/src/app/home.page.gwdk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ view {
5656
<h2>Session action</h2>
5757
<form class="stack-form" g:post={Login}>
5858
<label>Email <input name="email" type="email" required value="demo@example.com" /></label>
59-
<label>Password <input name="password" type="password" required minlength="8" value="demo-password" /></label>
59+
<label>Password <input name="password" type="password" required minlength="8" /></label>
6060
<button>Sign in</button>
6161
</form>
6262
</div>

examples/i18n/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ This example shows the first localization slice:
44

55
- `gowdk.config.go` declares `Config.I18N` locales.
66
- `messages.go` keeps typed message keys and catalogs in normal Go.
7-
- `messages_test.go` checks the typed message references against each locale
8-
catalog, which is the current CI-friendly extraction/completeness path.
7+
- `messages_test.go` checks the required typed message keys against each locale
8+
catalog without hand-maintained source line metadata.
99
- `home.page.gwdk` calls a Go build helper that reads
1010
`gowdk.BuildParams.LocaleCode()`.
1111

examples/i18n/messages.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ const (
1212
messageIntro messageKey = "intro"
1313
)
1414

15-
var homeMessageRefs = []gowdki18n.MessageReference[messageKey]{
16-
gowdki18n.Ref(messageTitle, "examples/i18n/home.page.gwdk", 14, 9),
17-
gowdki18n.Ref(messageIntro, "examples/i18n/home.page.gwdk", 15, 8),
15+
var homeRequiredMessages = []gowdki18n.MessageReference[messageKey]{
16+
gowdki18n.Key(messageTitle),
17+
gowdki18n.Key(messageIntro),
1818
}
1919

2020
type HomeCopy struct {

0 commit comments

Comments
 (0)