Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user script setting #2836

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions internal/database/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -942,4 +942,9 @@ var migrations = []func(tx *sql.Tx) error{
_, err = tx.Exec(sql)
return err
},
func(tx *sql.Tx) (err error) {
sql := `ALTER TABLE users ADD COLUMN custom_js text not null default '';`
_, err = tx.Exec(sql)
return err
},
}
1 change: 1 addition & 0 deletions internal/locale/translations/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Geste zum Navigieren zwischen Einträgen",
"form.prefs.label.show_reading_time": "Geschätzte Lesezeit für Artikel anzeigen",
"form.prefs.label.custom_css": "Benutzerdefiniertes CSS",
"form.prefs.label.custom_js": "Benutzerdefiniertes JS",
"form.prefs.label.entry_order": "Artikel-Sortierspalte",
"form.prefs.label.default_home_page": "Standard-Startseite",
"form.prefs.label.categories_sorting_order": "Kategorie-Sortierung",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/el_EL.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Χειρονομία για πλοήγηση μεταξύ των καταχωρήσεων",
"form.prefs.label.show_reading_time": "Εμφάνιση εκτιμώμενου χρόνου ανάγνωσης για άρθρα",
"form.prefs.label.custom_css": "Προσαρμοσμένο CSS",
"form.prefs.label.custom_js": "Προσαρμοσμένο JS",
"form.prefs.label.entry_order": "Στήλη ταξινόμησης εισόδου",
"form.prefs.label.default_home_page": "Προεπιλεγμένη αρχική σελίδα",
"form.prefs.label.categories_sorting_order": "Ταξινόμηση κατηγοριών",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Gesture to navigate between entries",
"form.prefs.label.show_reading_time": "Show estimated reading time for entries",
"form.prefs.label.custom_css": "Custom CSS",
"form.prefs.label.custom_js": "Custom JS",
"form.prefs.label.entry_order": "Entry sorting column",
"form.prefs.label.default_home_page": "Default home page",
"form.prefs.label.categories_sorting_order": "Categories sorting",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/es_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Gesto para navegar entre entradas",
"form.prefs.label.show_reading_time": "Mostrar el tiempo estimado de lectura de los artículos",
"form.prefs.label.custom_css": "CSS personalizado",
"form.prefs.label.custom_js": "JS personalizado",
"form.prefs.label.entry_order": "Columna de clasificación de artículos",
"form.prefs.label.default_home_page": "Página de inicio por defecto",
"form.prefs.label.categories_sorting_order": "Clasificación por categorías",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/fi_FI.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Ele siirtyäksesi merkintöjen välillä",
"form.prefs.label.show_reading_time": "Näytä artikkeleiden arvioitu lukuaika",
"form.prefs.label.custom_css": "Mukautettu CSS",
"form.prefs.label.custom_js": "Mukautettu JS",
"form.prefs.label.entry_order": "Lajittele sarakkeen mukaan",
"form.prefs.label.default_home_page": "Oletusarvoinen etusivu",
"form.prefs.label.categories_sorting_order": "Kategorioiden lajittelu",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/fr_FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Geste pour naviguer entre les entrées",
"form.prefs.label.show_reading_time": "Afficher le temps de lecture estimé des articles",
"form.prefs.label.custom_css": "Feuille de style personnalisée",
"form.prefs.label.custom_js": "Script personnalisée",
"form.prefs.label.entry_order": "Colonne de tri des entrées",
"form.prefs.label.default_home_page": "Page d'accueil par défaut",
"form.prefs.label.categories_sorting_order": "Colonne de tri des catégories",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/hi_IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "प्रविष्टियों के बीच नेविगेट करने के लिए इशारा",
"form.prefs.label.show_reading_time": "विषय के लिए अनुमानित पढ़ने का समय दिखाएं",
"form.prefs.label.custom_css": "कस्टम सीएसएस",
"form.prefs.label.custom_js": "कस्टम जेएस",
"form.prefs.label.entry_order": "प्रवेश छँटाई कॉलम",
"form.prefs.label.default_home_page": "डिफ़ॉल्ट होमपेज़",
"form.prefs.label.categories_sorting_order": "श्रेणियाँ छँटाई",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/id_ID.json
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
"form.prefs.label.gesture_nav": "Isyarat untuk menavigasi antar entri",
"form.prefs.label.show_reading_time": "Tampilkan perkiraan waktu baca untuk artikel",
"form.prefs.label.custom_css": "Modifikasi CSS",
"form.prefs.label.custom_js": "Modifikasi JS",
"form.prefs.label.entry_order": "Pengurutan Kolom Entri",
"form.prefs.label.default_home_page": "Beranda Baku",
"form.prefs.label.categories_sorting_order": "Pengurutan Kategori",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/it_IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Gesto per navigare tra le voci",
"form.prefs.label.show_reading_time": "Mostra il tempo di lettura stimato per gli articoli",
"form.prefs.label.custom_css": "CSS personalizzati",
"form.prefs.label.custom_js": "JS personalizzati",
"form.prefs.label.entry_order": "Colonna di ordinamento delle voci",
"form.prefs.label.default_home_page": "Pagina iniziale predefinita",
"form.prefs.label.categories_sorting_order": "Ordinamento delle categorie",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/ja_JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
"form.prefs.label.gesture_nav": "エントリ間を移動するジェスチャー",
"form.prefs.label.show_reading_time": "記事の推定読書時間を表示する",
"form.prefs.label.custom_css": "カスタム CSS",
"form.prefs.label.custom_js": "カスタム JS",
"form.prefs.label.entry_order": "記事の表示順の基準",
"form.prefs.label.default_home_page": "デフォルトのトップページ",
"form.prefs.label.categories_sorting_order": "カテゴリの表示順",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/nl_NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Gebaar om tussen artikelen te navigeren",
"form.prefs.label.show_reading_time": "Toon geschatte leestijd van artikelen",
"form.prefs.label.custom_css": "Aangepaste CSS",
"form.prefs.label.custom_js": "Aangepaste JS",
"form.prefs.label.entry_order": "Artikelen sorteren",
"form.prefs.label.default_home_page": "Startpagina",
"form.prefs.label.categories_sorting_order": "Volgorde categorieën",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/pl_PL.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@
"form.prefs.select.tap": "Podwójne wciśnięcie",
"form.prefs.select.swipe": "Trzepnąć",
"form.prefs.label.custom_css": "Niestandardowy CSS",
"form.prefs.label.custom_js": "Niestandardowy JS",
"form.prefs.label.entry_order": "Kolumna sortowania wpisów",
"form.prefs.label.default_home_page": "Domyślna strona główna",
"form.prefs.label.categories_sorting_order": "Sortowanie kategorii",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@
"form.prefs.label.gesture_nav": "Gesto para navegar entre as entradas",
"form.prefs.label.show_reading_time": "Mostrar tempo estimado de leitura de artigos",
"form.prefs.label.custom_css": "CSS customizado",
"form.prefs.label.custom_js": "JS customizado",
"form.prefs.label.entry_order": "Coluna de Ordenação de Entrada",
"form.prefs.label.default_home_page": "Página inicial predefinida",
"form.prefs.label.categories_sorting_order": "Classificação das categorias",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/ru_RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@
"form.prefs.label.gesture_nav": "Жест для перехода между статьями",
"form.prefs.label.show_reading_time": "Показать примерное время чтения статей",
"form.prefs.label.custom_css": "Пользовательский CSS",
"form.prefs.label.custom_js": "Пользовательский JS",
"form.prefs.label.entry_order": "Столбец сортировки статей",
"form.prefs.label.default_home_page": "Домашняя страница по умолчанию",
"form.prefs.label.categories_sorting_order": "Сортировка категорий",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/tr_TR.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
"form.prefs.label.categories_sorting_order": "Kategori sıralaması",
"form.prefs.label.cjk_reading_speed": "Çince, Korece ve Japonca için okuma hızı (dakika başına karakter)",
"form.prefs.label.custom_css": "Özel CSS",
"form.prefs.label.custom_js": "Özel JS",
"form.prefs.label.default_home_page": "Varsayılan ana sayfa",
"form.prefs.label.default_reading_speed": "Diğer diller için okuma hızı (dakika başına kelime)",
"form.prefs.label.display_mode": "Progressive Web App (PWA) görüntüleme modu",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/uk_UA.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@
"form.prefs.label.gesture_nav": "Жест для переходу між записами",
"form.prefs.label.show_reading_time": "Показувати приблизний час читання для записів",
"form.prefs.label.custom_css": "Спеціальний CSS",
"form.prefs.label.custom_js": "Спеціальний JS",
"form.prefs.label.entry_order": "Стовпець сортування записів",
"form.prefs.label.default_home_page": "Домашня сторінка за умовчанням",
"form.prefs.label.categories_sorting_order": "Сортування за категоріями",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
"form.prefs.label.gesture_nav": "在条目之间导航的手势",
"form.prefs.label.show_reading_time": "显示文章的预计阅读时间",
"form.prefs.label.custom_css": "自定义 CSS",
"form.prefs.label.custom_js": "自定义 JS",
"form.prefs.label.entry_order": "文章排序依据",
"form.prefs.label.default_home_page": "默认主页",
"form.prefs.label.categories_sorting_order": "分类排序",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
"form.prefs.label.gesture_nav": "在條目之間導航的手勢",
"form.prefs.label.show_reading_time": "顯示文章的預計閱讀時間",
"form.prefs.label.custom_css": "自定義 CSS",
"form.prefs.label.custom_js": "自定義 JS",
"form.prefs.label.entry_order": "文章排序依據",
"form.prefs.label.default_home_page": "預設主頁",
"form.prefs.label.categories_sorting_order": "分類排序",
Expand Down
6 changes: 6 additions & 0 deletions internal/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type User struct {
EntryDirection string `json:"entry_sorting_direction"`
EntryOrder string `json:"entry_sorting_order"`
Stylesheet string `json:"stylesheet"`
CustomJS string `json:"script"`
GoogleID string `json:"google_id"`
OpenIDConnectID string `json:"openid_connect_id"`
EntriesPerPage int `json:"entries_per_page"`
Expand Down Expand Up @@ -60,6 +61,7 @@ type UserModificationRequest struct {
EntryDirection *string `json:"entry_sorting_direction"`
EntryOrder *string `json:"entry_sorting_order"`
Stylesheet *string `json:"stylesheet"`
CustomJS *string `json:"script"`
GoogleID *string `json:"google_id"`
OpenIDConnectID *string `json:"openid_connect_id"`
EntriesPerPage *int `json:"entries_per_page"`
Expand Down Expand Up @@ -118,6 +120,10 @@ func (u *UserModificationRequest) Patch(user *User) {
user.Stylesheet = *u.Stylesheet
}

if u.CustomJS != nil {
user.CustomJS = *u.CustomJS
}

if u.GoogleID != nil {
user.GoogleID = *u.GoogleID
}
Expand Down
69 changes: 41 additions & 28 deletions internal/storage/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func (s *Storage) CreateUser(userCreationRequest *model.UserCreationRequest) (*m
entry_swipe,
gesture_nav,
stylesheet,
custom_js,
google_id,
openid_connect_id,
display_mode,
Expand Down Expand Up @@ -124,6 +125,7 @@ func (s *Storage) CreateUser(userCreationRequest *model.UserCreationRequest) (*m
&user.EntrySwipe,
&user.GestureNav,
&user.Stylesheet,
&user.CustomJS,
&user.GoogleID,
&user.OpenIDConnectID,
&user.DisplayMode,
Expand Down Expand Up @@ -184,21 +186,22 @@ func (s *Storage) UpdateUser(user *model.User) error {
entry_swipe=$11,
gesture_nav=$12,
stylesheet=$13,
google_id=$14,
openid_connect_id=$15,
display_mode=$16,
entry_order=$17,
default_reading_speed=$18,
cjk_reading_speed=$19,
default_home_page=$20,
categories_sorting_order=$21,
mark_read_on_view=$22,
mark_read_on_media_player_completion=$23,
media_playback_rate=$24,
block_filter_entry_rules=$25,
keep_filter_entry_rules=$26
custom_js=$14,
google_id=$15,
openid_connect_id=$16,
display_mode=$17,
entry_order=$18,
default_reading_speed=$19,
cjk_reading_speed=$20,
default_home_page=$21,
categories_sorting_order=$22,
mark_read_on_view=$23,
mark_read_on_media_player_completion=$24,
media_playback_rate=$25,
block_filter_entry_rules=$26,
keep_filter_entry_rules=$27
WHERE
id=$27
id=$28
`

_, err = s.db.Exec(
Expand All @@ -216,6 +219,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
user.EntrySwipe,
user.GestureNav,
user.Stylesheet,
user.CustomJS,
user.GoogleID,
user.OpenIDConnectID,
user.DisplayMode,
Expand Down Expand Up @@ -249,21 +253,22 @@ func (s *Storage) UpdateUser(user *model.User) error {
entry_swipe=$10,
gesture_nav=$11,
stylesheet=$12,
google_id=$13,
openid_connect_id=$14,
display_mode=$15,
entry_order=$16,
default_reading_speed=$17,
cjk_reading_speed=$18,
default_home_page=$19,
categories_sorting_order=$20,
mark_read_on_view=$21,
mark_read_on_media_player_completion=$22,
media_playback_rate=$23,
block_filter_entry_rules=$24,
keep_filter_entry_rules=$25
custom_js=$13,
google_id=$14,
openid_connect_id=$15,
display_mode=$16,
entry_order=$17,
default_reading_speed=$18,
cjk_reading_speed=$19,
default_home_page=$20,
categories_sorting_order=$21,
mark_read_on_view=$22,
mark_read_on_media_player_completion=$23,
media_playback_rate=$24,
block_filter_entry_rules=$25,
keep_filter_entry_rules=$26
WHERE
id=$26
id=$27
`

_, err := s.db.Exec(
Expand All @@ -280,6 +285,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
user.EntrySwipe,
user.GestureNav,
user.Stylesheet,
user.CustomJS,
user.GoogleID,
user.OpenIDConnectID,
user.DisplayMode,
Expand Down Expand Up @@ -332,6 +338,7 @@ func (s *Storage) UserByID(userID int64) (*model.User, error) {
gesture_nav,
last_login_at,
stylesheet,
custom_js,
google_id,
openid_connect_id,
display_mode,
Expand Down Expand Up @@ -371,6 +378,7 @@ func (s *Storage) UserByUsername(username string) (*model.User, error) {
gesture_nav,
last_login_at,
stylesheet,
custom_js,
google_id,
openid_connect_id,
display_mode,
Expand Down Expand Up @@ -410,6 +418,7 @@ func (s *Storage) UserByField(field, value string) (*model.User, error) {
gesture_nav,
last_login_at,
stylesheet,
custom_js,
google_id,
openid_connect_id,
display_mode,
Expand Down Expand Up @@ -456,6 +465,7 @@ func (s *Storage) UserByAPIKey(token string) (*model.User, error) {
u.gesture_nav,
u.last_login_at,
u.stylesheet,
u.custom_js,
u.google_id,
u.openid_connect_id,
u.display_mode,
Expand Down Expand Up @@ -496,6 +506,7 @@ func (s *Storage) fetchUser(query string, args ...interface{}) (*model.User, err
&user.GestureNav,
&user.LastLoginAt,
&user.Stylesheet,
&user.CustomJS,
&user.GoogleID,
&user.OpenIDConnectID,
&user.DisplayMode,
Expand Down Expand Up @@ -608,6 +619,7 @@ func (s *Storage) Users() (model.Users, error) {
gesture_nav,
last_login_at,
stylesheet,
custom_js,
google_id,
openid_connect_id,
display_mode,
Expand Down Expand Up @@ -649,6 +661,7 @@ func (s *Storage) Users() (model.Users, error) {
&user.GestureNav,
&user.LastLoginAt,
&user.Stylesheet,
&user.CustomJS,
&user.GoogleID,
&user.OpenIDConnectID,
&user.DisplayMode,
Expand Down
3 changes: 3 additions & 0 deletions internal/template/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ func (f *funcMap) Map() template.FuncMap {
"safeCSS": func(str string) template.CSS {
return template.CSS(str)
},
"safeJS": func(str string) template.JS {
return template.JS(str)
},
"noescape": func(str string) template.HTML {
return template.HTML(str)
},
Expand Down
13 changes: 9 additions & 4 deletions internal/template/templates/common/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@

<link rel="stylesheet" type="text/css" href="{{ route "stylesheet" "name" .theme "checksum" .theme_checksum }}">

{{ if and .user .user.Stylesheet }}
{{ $stylesheetNonce := nonce }}
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; style-src 'self' 'nonce-{{ $stylesheetNonce }}'; require-trusted-types-for 'script'; trusted-types ttpolicy;">
<style nonce="{{ $stylesheetNonce }}">{{ .user.Stylesheet | safeCSS }}</style>
{{ if .user }}
{{ $cspNonce := nonce }}
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; style-src 'self'{{ if .user.Stylesheet }} 'nonce-{{ $cspNonce }}'{{ end }}{{ if .user.Script }}; script-src 'self' 'nonce-{{ $cspNonce }}'{{ end }}; require-trusted-types-for 'script'; trusted-types ttpolicy;">
{{ if .user.Stylesheet }}
<style nonce="{{ $cspNonce }}">{{ .user.Stylesheet | safeCSS }}</style>
{{ end }}
{{ if .user.Script }}
<script type="module" nonce="{{ $cspNonce }}">{{ .user.Script | safeJS }}</script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@milhnl You forgot to rename .user.Script to .user.CustomJS in the template.

{{ end }}
{{ else }}
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; require-trusted-types-for 'script'; trusted-types ttpolicy;">
{{ end }}
Expand Down
3 changes: 3 additions & 0 deletions internal/template/templates/views/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ <h1 id="page-header-title">{{ t "page.settings.title" }}</h1>
<label for="form-custom-css">{{t "form.prefs.label.custom_css" }}</label>
<textarea id="form-custom-css" name="custom_css" cols="40" rows="10" spellcheck="false">{{ .form.CustomCSS }}</textarea>

<label for="form-custom-js">{{t "form.prefs.label.custom_js" }}</label>
<textarea id="form-custom-js" name="custom_js" cols="40" rows="10" spellcheck="false">{{ .form.CustomJS }}</textarea>

<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
Expand Down
Loading
Loading