From 99830a40a1635200a67ed380ca0b2ebe922cabaa Mon Sep 17 00:00:00 2001
From: oliverpool <git@olivier.pfad.fr>
Date: Tue, 9 Apr 2024 11:06:36 +0200
Subject: [PATCH] webhook: matrix access_token helper text

---
 options/locale/locale_en-US.ini        |  2 ++
 services/webhook/matrix.go             |  6 ++----
 templates/webhook/new/matrix.tmpl      |  9 ++++++++-
 templates/webhook/shared-settings.tmpl | 10 ++++------
 tests/integration/repo_webhook_test.go | 12 ++++++------
 5 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index c1bca91e5a..79eb86a175 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2509,6 +2509,8 @@ settings.thread_id = Thread ID
 settings.matrix.homeserver_url = Homeserver URL
 settings.matrix.room_id = Room ID
 settings.matrix.message_type = Message type
+settings.matrix.access_token_helper = It is recommended to setup a dedicated Matrix account for this. The access token can be retrieved from the Element web client (in a private/incognito tab) > User menu (top left) > All settings > Help & About > Advanced > Access Token (right below the Homeserver URL). Close the private/incognito tab (logging out would invalidate the token).
+settings.matrix.room_id_helper = The Room ID can be retrieved from the Element web client > Room Settings > Advanced > Internal room ID. Example: %s.
 settings.archive.button = Archive repo
 settings.archive.header = Archive this repo
 settings.archive.text = Archiving the repo will make it entirely read-only. It will be hidden from the dashboard. Nobody (not even you!) will be able to make new commits, or open any issues or pull requests.
diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go
index 697e33e94c..2be7782616 100644
--- a/services/webhook/matrix.go
+++ b/services/webhook/matrix.go
@@ -42,12 +42,10 @@ func (matrixHandler) UnmarshalForm(bind func(any)) forms.WebhookForm {
 		HomeserverURL string `binding:"Required;ValidUrl"`
 		RoomID        string `binding:"Required"`
 		MessageType   int
-
-		// enforce requirement of authorization_header
-		// (value will still be set in the embedded WebhookCoreForm)
-		AuthorizationHeader string `binding:"Required"`
+		AccessToken   string `binding:"Required"`
 	}
 	bind(&form)
+	form.AuthorizationHeader = "Bearer " + strings.TrimSpace(form.AccessToken)
 
 	return forms.WebhookForm{
 		WebhookCoreForm: form.WebhookCoreForm,
diff --git a/templates/webhook/new/matrix.tmpl b/templates/webhook/new/matrix.tmpl
index 38c6309185..920180d4c8 100644
--- a/templates/webhook/new/matrix.tmpl
+++ b/templates/webhook/new/matrix.tmpl
@@ -5,9 +5,16 @@
 		<label for="homeserver_url">{{ctx.Locale.Tr "repo.settings.matrix.homeserver_url"}}</label>
 		<input id="homeserver_url" name="homeserver_url" type="url" value="{{.HookMetadata.HomeserverURL}}" autofocus required>
 	</div>
+	<!-- Access Token -->
+	<div class="field required {{if .Err_AccessToken}}error{{end}}">
+		<label for="access_token">{{ctx.Locale.Tr "form.AccessToken"}}</label>
+		<input id="access_token" name="access_token" type="password" value="{{.Webhook.HeaderAuthorizationTrimPrefix "Bearer "}}" required>
+		<span class="help">{{ctx.Locale.Tr "repo.settings.matrix.access_token_helper"}}</span>
+	</div>
 	<div class="required field {{if .Err_Room}}error{{end}}">
 		<label for="room_id">{{ctx.Locale.Tr "repo.settings.matrix.room_id"}}</label>
-		<input id="room_id" name="room_id" type="text" value="{{.HookMetadata.Room}}" required>
+		<input id="room_id" name="room_id" type="text" value="{{.HookMetadata.Room}}" placeholder="!opaque_id:domain" pattern="^!.+:.+$" maxlength="255" required>
+		<span class="help">{{ctx.Locale.Tr "repo.settings.matrix.room_id_helper" ("<code>!opaque_id:example.org</code>"|SafeHTML)}}</span>
 	</div>
 	<div class="field">
 		<label>{{ctx.Locale.Tr "repo.settings.matrix.message_type"}}</label>
diff --git a/templates/webhook/shared-settings.tmpl b/templates/webhook/shared-settings.tmpl
index f2724f25e2..80caad7279 100644
--- a/templates/webhook/shared-settings.tmpl
+++ b/templates/webhook/shared-settings.tmpl
@@ -258,15 +258,13 @@
 	<span class="help">{{ctx.Locale.Tr "repo.settings.branch_filter_desc"}}</span>
 </div>
 
-{{$skipAuthorizationHeader := (eq .HookType "sourcehut_builds")}}
+{{$skipAuthorizationHeader := or (eq .HookType "sourcehut_builds") (eq .HookType "matrix")}}
 {{if not $skipAuthorizationHeader}}
 	<!-- Authorization Header -->
-	<div class="field{{if eq .HookType "matrix"}} required{{end}} {{if .Err_AuthorizationHeader}}error{{end}}">
+	<div class="field {{if .Err_AuthorizationHeader}}error{{end}}">
 		<label for="authorization_header">{{ctx.Locale.Tr "repo.settings.authorization_header"}}</label>
-		<input id="authorization_header" name="authorization_header" type="text" value="{{.Webhook.HeaderAuthorization}}"{{if eq .HookType "matrix"}} placeholder="Bearer $access_token" required{{end}}>
-		{{if ne .HookType "matrix"}}{{/* Matrix doesn't make the authorization optional but it is implied by the help string, should be changed.*/}}
-			<span class="help">{{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("<code>Bearer token123456</code>, <code>Basic YWxhZGRpbjpvcGVuc2VzYW1l</code>" | SafeHTML)}}</span>
-		{{end}}
+		<input id="authorization_header" name="authorization_header" type="text" value="{{.Webhook.HeaderAuthorization}}">
+		<span class="help">{{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("<code>Bearer token123456</code>, <code>Basic YWxhZGRpbjpvcGVuc2VzYW1l</code>" | SafeHTML)}}</span>
 	</div>
 {{end}}
 
diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go
index fa717a4496..b98fce0f4a 100644
--- a/tests/integration/repo_webhook_test.go
+++ b/tests/integration/repo_webhook_test.go
@@ -227,19 +227,19 @@ func TestWebhookForms(t *testing.T) {
 	}))
 
 	t.Run("matrix/required", testWebhookForms("matrix", session, map[string]string{
-		"homeserver_url":       "https://matrix.example.com",
-		"room_id":              "123",
-		"authorization_header": "Bearer 123456",
+		"homeserver_url": "https://matrix.example.com",
+		"access_token":   "123456",
+		"room_id":        "123",
 	}, map[string]string{
-		"authorization_header": "",
+		"access_token": "",
 	}))
 	t.Run("matrix/optional", testWebhookForms("matrix", session, map[string]string{
 		"homeserver_url": "https://matrix.example.com",
+		"access_token":   "123456",
 		"room_id":        "123",
 		"message_type":   "1", // m.text
 
-		"branch_filter":        "matrix/*",
-		"authorization_header": "Bearer 123456",
+		"branch_filter": "matrix/*",
 	}))
 
 	t.Run("wechatwork/required", testWebhookForms("wechatwork", session, map[string]string{