From 7b6d6b76eb3b7dbf1982c382a1f0e981e7ff8eee Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 9 Jun 2015 12:19:41 -0400 Subject: [PATCH] FEATURE: Multiple embeddable hosts - Also refactors two site settings components into one, with tests --- .../admin/components/site-setting.js.es6 | 2 +- .../admin/components/url-list.js.es6 | 32 ----------------- .../admin/components/value-list.js.es6 | 34 +++++++++++++++++++ .../admin/templates/components/url-list.hbs | 18 ---------- .../admin/templates/components/value-list.hbs | 18 ++++++++++ .../templates/site-settings/host_list.hbs | 3 ++ .../templates/site-settings/url_list.hbs | 2 +- .../stylesheets/common/admin/admin_base.scss | 6 ++-- app/controllers/embed_controller.rb | 4 +-- app/models/site_setting.rb | 13 +++++-- app/models/topic.rb | 2 +- config/locales/client.en.yml | 1 + config/locales/server.bs_BA.yml | 2 +- config/locales/server.de.yml | 2 +- config/locales/server.en.yml | 2 +- config/locales/server.es.yml | 2 +- config/locales/server.fa_IR.yml | 2 +- config/locales/server.fi.yml | 2 +- config/locales/server.fr.yml | 2 +- config/locales/server.he.yml | 2 +- config/locales/server.ja.yml | 2 +- config/locales/server.pt.yml | 2 +- config/locales/server.pt_BR.yml | 2 +- config/locales/server.ru.yml | 2 +- config/locales/server.sq.yml | 2 +- config/locales/server.tr_TR.yml | 2 +- config/locales/server.zh_CN.yml | 2 +- config/site_settings.yml | 6 ++-- .../20150609163211_migrate_embeddable_host.rb | 5 +++ lib/site_setting_extension.rb | 2 +- lib/topic_retriever.rb | 5 +-- spec/controllers/embed_controller_spec.rb | 30 +++++++++++++--- spec/models/site_setting_spec.rb | 33 ++++++++++++------ spec/models/topic_spec.rb | 8 ++--- .../components/value-list-test.js.es6 | 31 +++++++++++++++++ 35 files changed, 183 insertions(+), 102 deletions(-) delete mode 100644 app/assets/javascripts/admin/components/url-list.js.es6 create mode 100644 app/assets/javascripts/admin/components/value-list.js.es6 delete mode 100644 app/assets/javascripts/admin/templates/components/url-list.hbs create mode 100644 app/assets/javascripts/admin/templates/components/value-list.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings/host_list.hbs create mode 100644 db/migrate/20150609163211_migrate_embeddable_host.rb create mode 100644 test/javascripts/components/value-list-test.js.es6 diff --git a/app/assets/javascripts/admin/components/site-setting.js.es6 b/app/assets/javascripts/admin/components/site-setting.js.es6 index f8e3cc6b2c..c7375af4fc 100644 --- a/app/assets/javascripts/admin/components/site-setting.js.es6 +++ b/app/assets/javascripts/admin/components/site-setting.js.es6 @@ -2,7 +2,7 @@ import BufferedContent from 'discourse/mixins/buffered-content'; import ScrollTop from 'discourse/mixins/scroll-top'; import SiteSetting from 'admin/models/site-setting'; -const CustomTypes = ['bool', 'enum', 'list', 'url_list']; +const CustomTypes = ['bool', 'enum', 'list', 'url_list', 'host_list']; export default Ember.Component.extend(BufferedContent, ScrollTop, { classNameBindings: [':row', ':setting', 'setting.overridden', 'typeClass'], diff --git a/app/assets/javascripts/admin/components/url-list.js.es6 b/app/assets/javascripts/admin/components/url-list.js.es6 deleted file mode 100644 index 4562c4b20e..0000000000 --- a/app/assets/javascripts/admin/components/url-list.js.es6 +++ /dev/null @@ -1,32 +0,0 @@ -export default Ember.Component.extend({ - _setupUrls: function() { - const value = this.get('value'); - this.set('urls', (value && value.length) ? value.split("\n") : []); - }.on('init').observes('value'), - - _urlsChanged: function() { - this.set('value', this.get('urls').join("\n")); - }.observes('urls.@each'), - - urlInvalid: Ember.computed.empty('newUrl'), - - keyDown(e) { - if (e.keyCode === 13) { - this.send('addUrl'); - } - }, - - actions: { - addUrl() { - if (this.get('urlInvalid')) { return; } - - this.get('urls').addObject(this.get('newUrl')); - this.set('newUrl', ''); - }, - - removeUrl(url) { - const urls = this.get('urls'); - urls.removeObject(url); - } - } -}); diff --git a/app/assets/javascripts/admin/components/value-list.js.es6 b/app/assets/javascripts/admin/components/value-list.js.es6 new file mode 100644 index 0000000000..c995097a9d --- /dev/null +++ b/app/assets/javascripts/admin/components/value-list.js.es6 @@ -0,0 +1,34 @@ +export default Ember.Component.extend({ + classNameBindings: [':value-list'], + + _setupCollection: function() { + const values = this.get('values'); + this.set('collection', (values && values.length) ? values.split("\n") : []); + }.on('init').observes('values'), + + _collectionChanged: function() { + this.set('values', this.get('collection').join("\n")); + }.observes('collection.@each'), + + inputInvalid: Ember.computed.empty('newValue'), + + keyDown(e) { + if (e.keyCode === 13) { + this.send('addValue'); + } + }, + + actions: { + addValue() { + if (this.get('inputInvalid')) { return; } + + this.get('collection').addObject(this.get('newValue')); + this.set('newValue', ''); + }, + + removeValue(value) { + const collection = this.get('collection'); + collection.removeObject(value); + } + } +}); diff --git a/app/assets/javascripts/admin/templates/components/url-list.hbs b/app/assets/javascripts/admin/templates/components/url-list.hbs deleted file mode 100644 index d313c5b30a..0000000000 --- a/app/assets/javascripts/admin/templates/components/url-list.hbs +++ /dev/null @@ -1,18 +0,0 @@ -{{#if urls}} -
- {{#each url in urls}} -
- {{d-button action="removeUrl" - actionParam=url - icon="times" - class="btn-small no-text"}} - {{url}} -
- {{/each}} -
-{{/if}} - -
- {{text-field value=newUrl placeholderKey="admin.site_settings.add_url"}} - {{d-button action="addUrl" icon="plus" class="btn-primary btn-small no-text" disabled=urlInvalid}} -
diff --git a/app/assets/javascripts/admin/templates/components/value-list.hbs b/app/assets/javascripts/admin/templates/components/value-list.hbs new file mode 100644 index 0000000000..74904f92e8 --- /dev/null +++ b/app/assets/javascripts/admin/templates/components/value-list.hbs @@ -0,0 +1,18 @@ +{{#if collection}} +
+ {{#each collection as |value|}} +
+ {{d-button action="removeValue" + actionParam=value + icon="times" + class="btn-small no-text"}} + {{value}} +
+ {{/each}} +
+{{/if}} + +
+ {{text-field value=newValue placeholderKey=addKey}} + {{d-button action="addValue" icon="plus" class="btn-primary btn-small no-text" disabled=inputInvalid}} +
diff --git a/app/assets/javascripts/admin/templates/site-settings/host_list.hbs b/app/assets/javascripts/admin/templates/site-settings/host_list.hbs new file mode 100644 index 0000000000..5f0c301d0d --- /dev/null +++ b/app/assets/javascripts/admin/templates/site-settings/host_list.hbs @@ -0,0 +1,3 @@ +{{value-list values=buffered.value addKey="admin.site_settings.add_host"}} +{{setting-validation-message message=validationMessage}} +
{{{unbound setting.description}}}
diff --git a/app/assets/javascripts/admin/templates/site-settings/url_list.hbs b/app/assets/javascripts/admin/templates/site-settings/url_list.hbs index bd22e1b033..12e640c2c3 100644 --- a/app/assets/javascripts/admin/templates/site-settings/url_list.hbs +++ b/app/assets/javascripts/admin/templates/site-settings/url_list.hbs @@ -1,3 +1,3 @@ -{{url-list value=buffered.value}} +{{value-list value=buffered.value addKey="admin.site_settings.add_url"}} {{setting-validation-message message=validationMessage}}
{{{unbound setting.description}}}
diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index 6659f61a7f..580ff074e5 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -1449,8 +1449,8 @@ table#user-badges { } } -.url-list { - .url { +.value-list { + .value { border-bottom: 1px solid #ddd; padding: 3px; margin-right: 10px; @@ -1460,7 +1460,7 @@ table#user-badges { text-overflow: ellipsis; } - .urls { + .values { margin-bottom: 10px; } diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb index 249a18f7a7..198288297a 100644 --- a/app/controllers/embed_controller.rb +++ b/app/controllers/embed_controller.rb @@ -53,8 +53,8 @@ class EmbedController < ApplicationController def ensure_embeddable if !(Rails.env.development? && current_user.try(:admin?)) - raise Discourse::InvalidAccess.new('embeddable host not set') if SiteSetting.normalized_embeddable_host.blank? - raise Discourse::InvalidAccess.new('invalid referer host') if URI(request.referer || '').host != SiteSetting.normalized_embeddable_host + raise Discourse::InvalidAccess.new('embeddable hosts not set') if SiteSetting.embeddable_hosts.blank? + raise Discourse::InvalidAccess.new('invalid referer host') unless SiteSetting.allows_embeddable_host?(request.referer) end response.headers['X-Frame-Options'] = "ALLOWALL" diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index 5b272c0d91..02dad62554 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -68,9 +68,16 @@ class SiteSetting < ActiveRecord::Base @anonymous_menu_items ||= Set.new Discourse.anonymous_filters.map(&:to_s) end - def self.normalized_embeddable_host - return embeddable_host if embeddable_host.blank? - embeddable_host.sub(/^https?\:\/\//, '') + def self.allows_embeddable_host?(host) + return false if embeddable_hosts.blank? + uri = URI(host) rescue nil + + return false unless uri.present? + + host = uri.host + return false unless host.present? + + !!embeddable_hosts.split("\n").detect {|h| h.sub(/^https?\:\/\//, '') == host } end def self.anonymous_homepage diff --git a/app/models/topic.rb b/app/models/topic.rb index 1d0f6e4573..d9ebbd3af1 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -842,7 +842,7 @@ class Topic < ActiveRecord::Base end def expandable_first_post? - SiteSetting.embeddable_host.present? && SiteSetting.embed_truncate? && has_topic_embed? + SiteSetting.embeddable_hosts.present? && SiteSetting.embed_truncate? && has_topic_embed? end private diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 4034dd8b64..f4a746ba60 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2292,6 +2292,7 @@ en: no_results: "No results found." clear_filter: "Clear" add_url: "add URL" + add_host: "add host" categories: all_results: 'All' required: 'Required' diff --git a/config/locales/server.bs_BA.yml b/config/locales/server.bs_BA.yml index e492bd653c..930e3ae556 100644 --- a/config/locales/server.bs_BA.yml +++ b/config/locales/server.bs_BA.yml @@ -738,7 +738,7 @@ bs_BA: default_code_lang: "Default programming language syntax highlighting applied to GitHub code blocks (lang-auto, ruby, python etc.)" warn_reviving_old_topic_age: "When someone starts replying to a topic where the last reply is older than this many days, a warning will be displayed. Disable by setting to 0." autohighlight_all_code: "Force apply code highlighting to all preformatted code blocks even when they didn't explicitly specify the language." - embeddable_host: "Host that can embed the comments from this Discourse forum." + embeddable_hosts: "Host that can embed the comments from this Discourse forum." feed_polling_enabled: "EMBEDDING ONLY: Whether to embed a RSS/ATOM feed as posts." feed_polling_url: "EMBEDDING ONLY: URL of RSS/ATOM feed to embed." embed_by_username: "Discourse username of the user who creates the embedded topics." diff --git a/config/locales/server.de.yml b/config/locales/server.de.yml index cf2a6222b4..9630552949 100644 --- a/config/locales/server.de.yml +++ b/config/locales/server.de.yml @@ -937,7 +937,7 @@ de: warn_reviving_old_topic_age: "Wenn jemand beginnt auf ein Thema zu antworten, dessen letzte Antwort älter als diese Anzahl an Tagen ist, wird eine Warnung angezeigt. Deaktiviere dies durch setzen auf 0." autohighlight_all_code: "Erzwinge Syntaxhervorhebung für alle Quellcode-Blöcke, auch dann wenn keine Sprache angeben wurde." highlighted_languages: "Es wurden Syntaxregeln zur Hervorhebung von Textstellen hinzugefügt. (Achtung: Werden zu viele Sprachen hinzugefügt, kann das die Performance beeinflussen) siehe: https://highlightjs.org/static/demo/ für eine Demo." - embeddable_host: "Host, der Kommentare aus diesem Discourse Forum einbetten darf. Nur Hostname ohne http://" + embeddable_hosts: "Host, der Kommentare aus diesem Discourse Forum einbetten darf. Nur Hostname ohne http://" feed_polling_enabled: "NUR WENN EINGEBETTET: Bestimmt, ob Inhalte eines RSS-/ATOM-Feeds als zusätzliche Beiträge dargestellt werden." feed_polling_url: "NUR WENN EINGEBETTET: URL des einzubettenden RSS-/ATOM-Feeds." embed_by_username: "Discourse-Benutzername des Benutzers, der die eingebetteten Themen erstellt." diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index fc8525206f..bb6ce41067 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1126,7 +1126,7 @@ en: autohighlight_all_code: "Force apply code highlighting to all preformatted code blocks even when they didn't explicitly specify the language." highlighted_languages: "Included syntax highlighting rules. (Warning: including too many langauges may impact performance) see: https://highlightjs.org/static/demo/ for a demo" - embeddable_host: "Host that can embed the comments from this Discourse forum. Hostname only, do not begin with http://" + embeddable_hosts: "Host(s) that can embed the comments from this Discourse forum. Hostname only, do not begin with http://" feed_polling_enabled: "EMBEDDING ONLY: Whether to embed a RSS/ATOM feed as posts." feed_polling_url: "EMBEDDING ONLY: URL of RSS/ATOM feed to embed." embed_by_username: "Discourse username of the user who creates the embedded topics." diff --git a/config/locales/server.es.yml b/config/locales/server.es.yml index 707c6b407b..d9808f08f7 100644 --- a/config/locales/server.es.yml +++ b/config/locales/server.es.yml @@ -959,7 +959,7 @@ es: warn_reviving_old_topic_age: "Cuando alguien publica en un tema cuya última respuesta fue hace este número de días o más, se le mostrará un aviso para desalentar el hecho de resucitar una antigua discusión. Deshabilita esta opción introduciendo el valor 0." autohighlight_all_code: "Forzar el resaltado de código a los bloques de código preformateado cuando no se especifique el lenguaje del código." highlighted_languages: "Incluye reglas resaltadas de sintaxis. (Advertencia: incluyendo demasiadas lenguages puede afectar al rendimiento) ver: https://highlightjs.org/static/demo/ para una demostración" - embeddable_host: "Host que puede incrustar los comentarios de este foro Discourse. Nombre de host solamente, no comienzan con http://" + embeddable_hosts: "Host que puede incrustar los comentarios de este foro Discourse. Nombre de host solamente, no comienzan con http://" feed_polling_enabled: "SOLO PARA EMBEBER: embeber feeds RSS/ATOM como posts." feed_polling_url: "SOLO PARA EMBEBER: URL de los feeds RSS/ATOM a embeber." embed_by_username: "Nombre de usuario en Discourse del que crea los temas embebidos." diff --git a/config/locales/server.fa_IR.yml b/config/locales/server.fa_IR.yml index 7b80c9f829..f1b1be2b99 100644 --- a/config/locales/server.fa_IR.yml +++ b/config/locales/server.fa_IR.yml @@ -916,7 +916,7 @@ fa_IR: warn_reviving_old_topic_age: "وقتی کسی شروع می کند با پاسخ دادن به جستاری که آخرین پاسخ برمی گردد به خیلی قبل یک هشدار نمایش داده می شود. نمایش با تنظیمات تا 0. " autohighlight_all_code: "اعمال زور برای برجسته کردن کد به تمام بلاک های کد تنظیم نشده حتی وقتی به صراحت زبان را مشخص نمی کنند. " highlighted_languages: "شامل نحوه قوانین برجسته شده. ( اخطار: شامل زبان های متفاوت ممکن است در نحوه اجرا تاثیر گذار باشد) ببین: https://highlightjs.org/static/demo/ برای دمو" - embeddable_host: "سروری که می تونه در نوشته ها جا سازی بشه از انجمن دیسکورس. فقط نام سروری که با http:// شروع می شود" + embeddable_hosts: "سروری که می تونه در نوشته ها جا سازی بشه از انجمن دیسکورس. فقط نام سروری که با http:// شروع می شود" feed_polling_enabled: "فقط جاسازی: چه جاسازی RSS/ATOM feed به عنوان نوشته" feed_polling_url: "فقط جاسازی: URL of RSS/ATOM feed to embed." embed_by_username: "نام کاربری دیسکورس کاربری که نوشته های جاسازی شده را ساخته." diff --git a/config/locales/server.fi.yml b/config/locales/server.fi.yml index 2d73da7ff6..be1af1cbc8 100644 --- a/config/locales/server.fi.yml +++ b/config/locales/server.fi.yml @@ -962,7 +962,7 @@ fi: warn_reviving_old_topic_age: "Kun käyttäjä alkaa kirjoittamaan vastausta ketjuun, jonka uusin viesti on tätä vanhempi päivissä, näytetään varoitus. Poista käytöstä asettamalla arvoksi 0." autohighlight_all_code: "Pakota koodin korostus kaikkiin esimuotoiltuihin tekstiblokkeihin, vaikka käyttäjä ei määrittelisi kieltä." highlighted_languages: "Syntaksin korostamisen säännöt. (Varoitus: liian monen kielen sisällyttäminen voi vaikuttaa suorituskykyyn) katso demo: https://highlightjs.org/static/demo/" - embeddable_host: "Isäntä, joka voi upottaa kommentteja tältä palstalta. Pelkkä isäntänimi, älä aloita http://" + embeddable_hosts: "Isäntä, joka voi upottaa kommentteja tältä palstalta. Pelkkä isäntänimi, älä aloita http://" feed_polling_enabled: "VAIN UPOTUS: Upotetaanko RSS/ATOM syöte viesteinä." feed_polling_url: "VAIN UPOTUS: RSS/ATOM syötteen URL." embed_by_username: "Sen käyttäjän Discourse käyttäjänimi, joka luo upotetut ketjut." diff --git a/config/locales/server.fr.yml b/config/locales/server.fr.yml index 6eba5d754d..380ff34846 100644 --- a/config/locales/server.fr.yml +++ b/config/locales/server.fr.yml @@ -963,7 +963,7 @@ fr: warn_reviving_old_topic_age: "Lorsque quelqu'un commence à répondre à un sujet dont la dernière réponse est vielle de plusieurs jours, un avertissement sera affiché. Désactiver la fonctionnalité en indiquant: 0." autohighlight_all_code: "Forcer la mise en évidence de tout les textes dans les balises code, même si ils ne correspondent à aucun langage de programmation." highlighted_languages: "Include les règles de mise en surbrillance de syntaxe. (Avertissement: l'ajout de trop de langages peut impacter les performances) voir l'exemple https://highlightjs.org/static/demo/" - embeddable_host: "Hôte qui peut incorporer des messages de ce forum Discourse. Nom d'hôte seulement, sans http://" + embeddable_hosts: "Hôte qui peut incorporer des messages de ce forum Discourse. Nom d'hôte seulement, sans http://" feed_polling_enabled: "EMBARQUER UNIQUEMENT: Embarqué le flux RSS/ATOM en tant que messages." feed_polling_url: "EMBARQUER UNIQUEMENT: Url du flux RSS/ATOM à embarqué." embed_by_username: "Pseudo de l'utilisateur Discourse qui crée les sujets embarqués." diff --git a/config/locales/server.he.yml b/config/locales/server.he.yml index 4b89ec7e52..b16af98532 100644 --- a/config/locales/server.he.yml +++ b/config/locales/server.he.yml @@ -925,7 +925,7 @@ he: warn_reviving_old_topic_age: "כאשר מישהו/מישהי מתחילים להגיב לנושא שבו התגובה האחרונה היא בת יותר מכמה ימים, אזהרה תוצג. בטלו אפשרות זו באמצעות הזנה של 0." autohighlight_all_code: "לחייב שימוש בקוד הדגשה לכל קוד מעוצב מראש (preformatted code blocks) אפילו אם הם אינם מציינים את השפה." highlighted_languages: "הכללת הדגשת שגיאות תחביר. (אזהרה: הכללת שפות רבות מידי עשוי להשפיע על הביצוע) ראו: https://highlightjs.org/static/demo/ להדגמה" - embeddable_host: "מארח (Host) אשר יכול להטמיע את התגובות מפורום Discourse זה. שם מארח בלבד, ללא http:// בהתחלה" + embeddable_hosts: "מארח (Host) אשר יכול להטמיע את התגובות מפורום Discourse זה. שם מארח בלבד, ללא http:// בהתחלה" feed_polling_enabled: "הטמעה בלבד: האם לעמבד פידים של RSS/ATOM כפרסומים." feed_polling_url: "הטמעה בלבד: URL של פיד RSS/ATOM להטמעה." embed_by_username: "שם המשתמש של המשתמש/ת שיוצר את הנושאים המוטמעים." diff --git a/config/locales/server.ja.yml b/config/locales/server.ja.yml index 2a20f5ba6d..3544584d66 100644 --- a/config/locales/server.ja.yml +++ b/config/locales/server.ja.yml @@ -837,7 +837,7 @@ ja: warn_reviving_old_topic_age: "最後の返信がこの設定よりも古いトピックに返信すると、警告を表示します。0を設定すると無効になります" autohighlight_all_code: "明示的に言語を指定しなくても、全てのコードブロックにコードハイライトを強制的に適用する" highlighted_languages: "適用するシンタックスハイライトルール(警告: あまりに多くの言語を含むとパフォーマンスに影響を与えます) デモ: https://highlightjs.org/static/demo/ " - embeddable_host: "このDiscourseフォーラムのコメントを埋め込む事が出来るHost。Host名のみ、http:// で始めない" + embeddable_hosts: "このDiscourseフォーラムのコメントを埋め込む事が出来るHost。Host名のみ、http:// で始めない" feed_polling_enabled: "EMBEDDING ONLY: ポストとしてRSS/Atomフィードを埋め込むかどうか" feed_polling_url: "EMBEDDING ONLY: RSS/ATOMフィードのURLを埋め込む事が出来ます" embed_by_username: "embedされたトピックの作成者として表示されるDiscourseユーザー名" diff --git a/config/locales/server.pt.yml b/config/locales/server.pt.yml index 2dc6087fb2..1bb604cc61 100644 --- a/config/locales/server.pt.yml +++ b/config/locales/server.pt.yml @@ -950,7 +950,7 @@ pt: warn_reviving_old_topic_age: "Quando alguém começa a responder a um tópico em que a última resposta é mais antiga que estes dias, um aviso será exibido. Desativar ao configurar para 0." autohighlight_all_code: "Forçar o destaque do código a todos os blocos de código pré-formatados mesmo quando não se especifica a linguagem." highlighted_languages: "Incluídas regras de destaque da sintaxe (Aviso: incluir demasiadas linguagens pode impactar o desempenho) ver: https://highlightjs.org/static/demo/ para uma demonstração" - embeddable_host: "Servidor que pode incorporar os comentários deste fórum Discourse. Apenas o nome do servidor, não começar com http://" + embeddable_hosts: "Servidor que pode incorporar os comentários deste fórum Discourse. Apenas o nome do servidor, não começar com http://" feed_polling_enabled: "INCORPORAR APENAS: incorporar feeds RSS/ATOM como mensagens." feed_polling_url: "INCORPORAR APENAS: URL dos feeds de RSS/ATOM para embutir." embed_by_username: "Nome de utilizador Discourse do utilizador que cria tópicos embebidos." diff --git a/config/locales/server.pt_BR.yml b/config/locales/server.pt_BR.yml index 9e6ed66873..07e62e329d 100644 --- a/config/locales/server.pt_BR.yml +++ b/config/locales/server.pt_BR.yml @@ -950,7 +950,7 @@ pt_BR: warn_reviving_old_topic_age: "Quando alguém começa a responder a um tópico mais velho do que este número de dias, um aviso será exibido para desencorajar o usuário de reviver uma velha discussão. Desabilite definindo para 0." autohighlight_all_code: "Aplicar código destacando todos os blocos de código pré-formatados, mesmo quando não for específica o idioma" highlighted_languages: "Incluir regras de destaque de sintaxe. (AVISO: incluir muitas linguagens podem afetar a performance) veja: https://highlightjs.org/static/demo/ para uma demonstração" - embeddable_host: "Servidor que pode incorporar os comentários deste forum Discourse. Apenas o Nome do Servidor, não começar com http://" + embeddable_hosts: "Servidor que pode incorporar os comentários deste forum Discourse. Apenas o Nome do Servidor, não começar com http://" feed_polling_enabled: "Se um feed RSS / ATOM são importados como mensagens" feed_polling_url: "URL do feed RSS / ATOM para importar" embed_by_username: "Nome de usuário Discourse para o usuário que cria os tópicos" diff --git a/config/locales/server.ru.yml b/config/locales/server.ru.yml index 2f988dea9e..f0a862aa69 100644 --- a/config/locales/server.ru.yml +++ b/config/locales/server.ru.yml @@ -1005,7 +1005,7 @@ ru: warn_reviving_old_topic_age: "Показывать предупреждение, когда кто-то пытается ответить в очень старую тему. Указывается в днях. Чтобы отключить 0." autohighlight_all_code: "Принудительно использовать подсветку кода для всех отформатированных блоков кода, даже когда они явно не указан язык." highlighted_languages: "Включить правила подсветки синтаксиса. (ВНИМАНИЕ: включение для многих языков может вызвать проблемы с производительностью) пример можно посмотреть на: https://highlightjs.org/static/demo/ " - embeddable_host: "Имя хоста которому разрешено использовать комменты с данного форума. Не указывайте http://" + embeddable_hosts: "Имя хоста которому разрешено использовать комменты с данного форума. Не указывайте http://" feed_polling_enabled: "ТОЛЬКО ДЛЯ ВЛОЖЕННЫХ: Встраивать ли вложенные сообщения в RSS/ATOM ленту" feed_polling_url: "URL адрес импорта RSS/ATOM ленты" embed_by_username: "Имя пользователя который созал вложенную тему" diff --git a/config/locales/server.sq.yml b/config/locales/server.sq.yml index ed59ff9198..c692d86810 100644 --- a/config/locales/server.sq.yml +++ b/config/locales/server.sq.yml @@ -938,7 +938,7 @@ sq: warn_reviving_old_topic_age: "When someone starts replying to a topic where the last reply is older than this many days, a warning will be displayed. Disable by setting to 0." autohighlight_all_code: "Force apply code highlighting to all preformatted code blocks even when they didn't explicitly specify the language." highlighted_languages: "Included syntax highlighting rules. (Warning: including too many langauges may impact performance) see: https://highlightjs.org/static/demo/ for a demo" - embeddable_host: "Host that can embed the comments from this Discourse forum. Hostname only, do not begin with http://" + embeddable_hosts: "Host that can embed the comments from this Discourse forum. Hostname only, do not begin with http://" feed_polling_enabled: "EMBEDDING ONLY: Whether to embed a RSS/ATOM feed as posts." feed_polling_url: "EMBEDDING ONLY: URL of RSS/ATOM feed to embed." embed_by_username: "Discourse username of the user who creates the embedded topics." diff --git a/config/locales/server.tr_TR.yml b/config/locales/server.tr_TR.yml index eea2bfc804..ee726c2a3d 100644 --- a/config/locales/server.tr_TR.yml +++ b/config/locales/server.tr_TR.yml @@ -903,7 +903,7 @@ tr_TR: warn_reviving_old_topic_age: "Herhangi bir kullanıcı, son cevabın burada belirtilen gün sayısından daha önce yazıldığı bir konuya cevap yazmaya başladığında, bir uyarı mesajı çıkacak. Bu özelliği devre dışı bırakmak için 0 girin. " autohighlight_all_code: "Tüm önceden formatlanan kod bloklarına, açıkça dil seçimi yapılmamış olsa da, zorla kod vurgulaması uygula." highlighted_languages: "Dahil edilen sözdizimi vurgulama kuralları. (Dikkat: çok fazla dili dahil etmek performansı etkileyebilir) Demo için https://highlightjs.org/static/demo/ adresine bakınız" - embeddable_host: "Bu Discourse forumundan yorumların yerleştirilebileceği sunucu. Sadece sunucu, http:// ile başlamayın" + embeddable_hosts: "Bu Discourse forumundan yorumların yerleştirilebileceği sunucu. Sadece sunucu, http:// ile başlamayın" feed_polling_enabled: "SADECE YERLEŞTİRME İÇİN: RSS/ATOM beslemesinin gönderi olarak yerleştirilip yerleştirilemeyeceği." feed_polling_url: "SADECE YERLEŞTİRME İÇİN: Yerleştirilecek RSS/ATOM beslemesinin URL'i." embed_by_username: "Yerleştirilmiş konuları oluşturan kullanıcıya ait Discourse kullanıcı adı. " diff --git a/config/locales/server.zh_CN.yml b/config/locales/server.zh_CN.yml index 0af033048a..6bb6b7ded3 100644 --- a/config/locales/server.zh_CN.yml +++ b/config/locales/server.zh_CN.yml @@ -934,7 +934,7 @@ zh_CN: warn_reviving_old_topic_age: "当有人开始回复最后一贴超过一定天数前的主题时,将有一个警告显示,不鼓励他们复活一个老的讨论。将其设置为 0 以禁用。" autohighlight_all_code: "即使未显式设定语言,仍为所有预编排代码块应用语法高亮。" highlighted_languages: "包含语法高亮规则。(警告:包含太多的语言可能会印象性能)见:https://highlightjs.org/static/demo/ 查看演示" - embeddable_host: "能从这个 Discourse 论坛嵌入评论的主机。\n仅主机名,不要以 http:// 开头" + embeddable_hosts: "能从这个 Discourse 论坛嵌入评论的主机。\n仅主机名,不要以 http:// 开头" feed_polling_enabled: "仅用于嵌入:是否将 RSS/ATOM 订阅为帖子。" feed_polling_url: "仅用于嵌入:RSS/ATOM 订阅的 URL。" embed_by_username: "创建嵌入主题的 Discourse 的用户名。" diff --git a/config/site_settings.yml b/config/site_settings.yml index c514c80297..8f2d141fef 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -729,9 +729,9 @@ developer: client: true embedding: - embeddable_host: - default: '' - regex: "^(?!http).+" # don't allow this to start with http:// or https:// + embeddable_hosts: + default: '' + type: host_list feed_polling_enabled: false feed_polling_url: '' embed_by_username: diff --git a/db/migrate/20150609163211_migrate_embeddable_host.rb b/db/migrate/20150609163211_migrate_embeddable_host.rb new file mode 100644 index 0000000000..d3d351a32b --- /dev/null +++ b/db/migrate/20150609163211_migrate_embeddable_host.rb @@ -0,0 +1,5 @@ +class MigrateEmbeddableHost < ActiveRecord::Migration + def change + execute "UPDATE site_settings SET name = 'embeddable_hosts', data_type = 9 WHERE name = 'embeddable_host'" + end +end diff --git a/lib/site_setting_extension.rb b/lib/site_setting_extension.rb index 456f94d336..facb22bb4b 100644 --- a/lib/site_setting_extension.rb +++ b/lib/site_setting_extension.rb @@ -14,7 +14,7 @@ module SiteSettingExtension end def types - @types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list, :url_list) + @types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list, :url_list, :host_list) end def mutex diff --git a/lib/topic_retriever.rb b/lib/topic_retriever.rb index 161f362be4..1682377309 100644 --- a/lib/topic_retriever.rb +++ b/lib/topic_retriever.rb @@ -13,10 +13,7 @@ class TopicRetriever private def invalid_host? - SiteSetting.normalized_embeddable_host != URI(@embed_url).host - rescue URI::InvalidURIError - # An invalid URI is an invalid host - true + SiteSetting.allows_embeddable_host?(@embed_url) end def retrieved_recently? diff --git a/spec/controllers/embed_controller_spec.rb b/spec/controllers/embed_controller_spec.rb index e68965d9bd..514d84f57c 100644 --- a/spec/controllers/embed_controller_spec.rb +++ b/spec/controllers/embed_controller_spec.rb @@ -11,14 +11,14 @@ describe EmbedController do end it "raises an error with a missing host" do - SiteSetting.stubs(:embeddable_host).returns(nil) + SiteSetting.embeddable_hosts = nil get :comments, embed_url: embed_url expect(response).not_to be_success end context "with a host" do before do - SiteSetting.stubs(:embeddable_host).returns(host) + SiteSetting.embeddable_hosts = host end it "raises an error with no referer" do @@ -27,7 +27,6 @@ describe EmbedController do end context "success" do - before do controller.request.stubs(:referer).returns(embed_url) end @@ -51,8 +50,31 @@ describe EmbedController do get :comments, embed_url: embed_url end end - end + context "with multiple hosts" do + before do + SiteSetting.embeddable_hosts = "#{host}\nhttp://discourse.org" + end + context "success" do + it "works with the first host" do + controller.request.stubs(:referer).returns("http://eviltrout.com/wat/1-2-3.html") + get :comments, embed_url: embed_url + expect(response).to be_success + end + + it "works with the second host" do + controller.request.stubs(:referer).returns("https://discourse.org/blog-entry-1") + get :comments, embed_url: embed_url + expect(response).to be_success + end + + it "doesn't work with a made up host" do + controller.request.stubs(:referer).returns("http://codinghorror.com/invalid-url") + get :comments, embed_url: embed_url + expect(response).to_not be_success + end + end + end end diff --git a/spec/models/site_setting_spec.rb b/spec/models/site_setting_spec.rb index 0cd8691a66..a4ca870d5d 100644 --- a/spec/models/site_setting_spec.rb +++ b/spec/models/site_setting_spec.rb @@ -4,21 +4,34 @@ require_dependency 'site_setting_extension' describe SiteSetting do - describe "normalized_embeddable_host" do - it 'returns the `embeddable_host` value' do - SiteSetting.stubs(:embeddable_host).returns("eviltrout.com") - expect(SiteSetting.normalized_embeddable_host).to eq("eviltrout.com") + describe "allows_embeddable_host" do + it 'works as expected' do + SiteSetting.embeddable_hosts = 'eviltrout.com' + expect(SiteSetting.allows_embeddable_host?('http://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://not-eviltrout.com')).to eq(false) end - it 'strip http from `embeddable_host` value' do - SiteSetting.stubs(:embeddable_host).returns("http://eviltrout.com") - expect(SiteSetting.normalized_embeddable_host).to eq("eviltrout.com") + it 'works with a http host' do + SiteSetting.embeddable_hosts = 'http://eviltrout.com' + expect(SiteSetting.allows_embeddable_host?('http://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://not-eviltrout.com')).to eq(false) end - it 'strip https from `embeddable_host` value' do - SiteSetting.stubs(:embeddable_host).returns("https://eviltrout.com") - expect(SiteSetting.normalized_embeddable_host).to eq("eviltrout.com") + it 'works with a https host' do + SiteSetting.embeddable_hosts = 'https://eviltrout.com' + expect(SiteSetting.allows_embeddable_host?('http://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('https://not-eviltrout.com')).to eq(false) end + + it 'works with multiple hosts' do + SiteSetting.embeddable_hosts = "https://eviltrout.com\nhttps://discourse.org" + expect(SiteSetting.allows_embeddable_host?('http://eviltrout.com')).to eq(true) + expect(SiteSetting.allows_embeddable_host?('http://discourse.org')).to eq(true) + end + end describe 'topic_title_length' do diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index 673c7e9b69..ff971fa737 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -1400,8 +1400,8 @@ describe Topic do let(:topic) { Fabricate.build(:topic) } before do - SiteSetting.stubs(:embeddable_host).returns("http://eviltrout.com") - SiteSetting.stubs(:embed_truncate?).returns(true) + SiteSetting.embeddable_hosts = "http://eviltrout.com" + SiteSetting.embed_truncate = true topic.stubs(:has_topic_embed?).returns(true) end @@ -1410,12 +1410,12 @@ describe Topic do end it "is false if embeddable_host is blank" do - SiteSetting.stubs(:embeddable_host).returns(nil) + SiteSetting.embeddable_hosts = nil expect(topic.expandable_first_post?).to eq(false) end it "is false if embed_truncate? is false" do - SiteSetting.stubs(:embed_truncate?).returns(false) + SiteSetting.embed_truncate = false expect(topic.expandable_first_post?).to eq(false) end diff --git a/test/javascripts/components/value-list-test.js.es6 b/test/javascripts/components/value-list-test.js.es6 new file mode 100644 index 0000000000..db8767471b --- /dev/null +++ b/test/javascripts/components/value-list-test.js.es6 @@ -0,0 +1,31 @@ +moduleForComponent('value-list', {integration: true}); + +test('functionality', function(assert) { + andThen(() => { + this.render('{{value-list value=values}}'); + }); + + andThen(() => { + assert.ok(this.$('.values .value').length === 0, 'it has no values'); + assert.ok(this.$('input').length, 'it renders the input'); + assert.ok(this.$('.btn-primary[disabled]').length, 'it is disabled with no value'); + }); + + fillIn('input', 'eviltrout'); + andThen(() => { + assert.ok(!this.$('.btn-primary[disabled]').length, "it isn't disabled anymore"); + }); + + click('.btn-primary'); + andThen(() => { + assert.ok(this.$('.values .value').length === 1, 'it adds the value'); + assert.ok(this.$('input').val() === '', 'it clears the input'); + assert.ok(this.$('.btn-primary[disabled]').length, "it is disabled again"); + }); + + click('.value .btn-small'); + andThen(() => { + assert.ok(this.$('.values .value').length === 0, 'it removes the value'); + }); + +});