diff --git a/app/assets/javascripts/admin/controllers/admin_logs_screened_urls_controller.js b/app/assets/javascripts/admin/controllers/admin_logs_screened_urls_controller.js new file mode 100644 index 00000000000..c14d95c2337 --- /dev/null +++ b/app/assets/javascripts/admin/controllers/admin_logs_screened_urls_controller.js @@ -0,0 +1,21 @@ +/** + This controller supports the interface for listing screened URLs in the admin section. + + @class AdminLogsScreenedUrlsController + @extends Ember.ArrayController + @namespace Discourse + @module Discourse +**/ +Discourse.AdminLogsScreenedUrlsController = Ember.ArrayController.extend(Discourse.Presence, { + loading: false, + content: [], + + show: function() { + var self = this; + this.set('loading', true); + Discourse.ScreenedUrl.findAll().then(function(result) { + self.set('content', result); + self.set('loading', false); + }); + } +}); diff --git a/app/assets/javascripts/admin/models/screened_email.js b/app/assets/javascripts/admin/models/screened_email.js index 21209ad436f..d2f524414c1 100644 --- a/app/assets/javascripts/admin/models/screened_email.js +++ b/app/assets/javascripts/admin/models/screened_email.js @@ -9,7 +9,7 @@ **/ Discourse.ScreenedEmail = Discourse.Model.extend({ actionName: function() { - return I18n.t("admin.logs.screened_emails.actions." + this.get('action')); + return I18n.t("admin.logs.screened_actions." + this.get('action')); }.property('action') }); diff --git a/app/assets/javascripts/admin/models/screened_url.js b/app/assets/javascripts/admin/models/screened_url.js new file mode 100644 index 00000000000..592726f4840 --- /dev/null +++ b/app/assets/javascripts/admin/models/screened_url.js @@ -0,0 +1,23 @@ +/** + Represents a URL that is watched for, and an action may be taken. + + @class ScreenedUrl + @extends Discourse.Model + @namespace Discourse + @module Discourse +**/ +Discourse.ScreenedUrl = Discourse.Model.extend({ + actionName: function() { + return I18n.t("admin.logs.screened_actions." + this.get('action')); + }.property('action') +}); + +Discourse.ScreenedUrl.reopenClass({ + findAll: function(filter) { + return Discourse.ajax("/admin/logs/screened_urls.json").then(function(screened_urls) { + return screened_urls.map(function(b) { + return Discourse.ScreenedUrl.create(b); + }); + }); + } +}); diff --git a/app/assets/javascripts/admin/routes/admin_logs_routes.js b/app/assets/javascripts/admin/routes/admin_logs_routes.js index da006a9861f..c14010109ed 100644 --- a/app/assets/javascripts/admin/routes/admin_logs_routes.js +++ b/app/assets/javascripts/admin/routes/admin_logs_routes.js @@ -12,24 +12,6 @@ Discourse.AdminLogsIndexRoute = Discourse.Route.extend({ } }); -/** - The route that lists blocked email addresses. - - @class AdminLogsScreenedEmailsRoute - @extends Discourse.Route - @namespace Discourse - @module Discourse -**/ -Discourse.AdminLogsScreenedEmailsRoute = Discourse.Route.extend({ - renderTemplate: function() { - this.render('admin/templates/logs/screened_emails', {into: 'adminLogs'}); - }, - - setupController: function() { - return this.controllerFor('adminLogsScreenedEmails').show(); - } -}); - /** The route that lists staff actions that were logged. @@ -57,4 +39,40 @@ Discourse.AdminLogsStaffActionLogsRoute = Discourse.Route.extend({ // Clear any filters when we leave the route Discourse.URL.set('queryParams', null); } +}); + +/** + The route that lists blocked email addresses. + + @class AdminLogsScreenedEmailsRoute + @extends Discourse.Route + @namespace Discourse + @module Discourse +**/ +Discourse.AdminLogsScreenedEmailsRoute = Discourse.Route.extend({ + renderTemplate: function() { + this.render('admin/templates/logs/screened_emails', {into: 'adminLogs'}); + }, + + setupController: function() { + return this.controllerFor('adminLogsScreenedEmails').show(); + } +}); + +/** + The route that lists screened URLs. + + @class AdminLogsScreenedUrlsRoute + @extends Discourse.Route + @namespace Discourse + @module Discourse +**/ +Discourse.AdminLogsScreenedUrlsRoute = Discourse.Route.extend({ + renderTemplate: function() { + this.render('admin/templates/logs/screened_urls', {into: 'adminLogs'}); + }, + + setupController: function() { + return this.controllerFor('adminLogsScreenedUrls').show(); + } }); \ No newline at end of file diff --git a/app/assets/javascripts/admin/routes/admin_routes.js b/app/assets/javascripts/admin/routes/admin_routes.js index 4622f60954f..835b851dc4b 100644 --- a/app/assets/javascripts/admin/routes/admin_routes.js +++ b/app/assets/javascripts/admin/routes/admin_routes.js @@ -30,8 +30,9 @@ Discourse.Route.buildRoutes(function() { }); this.resource('adminLogs', { path: '/logs' }, function() { - this.route('screenedEmails', { path: '/screened_emails' }); this.route('staffActionLogs', { path: '/staff_action_logs' }); + this.route('screenedEmails', { path: '/screened_emails' }); + this.route('screenedUrls', { path: '/screened_urls' }); }); this.route('groups', {path: '/groups'}); diff --git a/app/assets/javascripts/admin/templates/logs.js.handlebars b/app/assets/javascripts/admin/templates/logs.js.handlebars index f18bf8cc5de..f1faac2b6f3 100644 --- a/app/assets/javascripts/admin/templates/logs.js.handlebars +++ b/app/assets/javascripts/admin/templates/logs.js.handlebars @@ -3,6 +3,7 @@ diff --git a/app/assets/javascripts/admin/templates/logs/screened_emails.js.handlebars b/app/assets/javascripts/admin/templates/logs/screened_emails.js.handlebars index 915eaf92f87..ec5c2d339a5 100644 --- a/app/assets/javascripts/admin/templates/logs/screened_emails.js.handlebars +++ b/app/assets/javascripts/admin/templates/logs/screened_emails.js.handlebars @@ -5,12 +5,12 @@ {{else}} {{#if model.length}} -
+
{{i18n admin.logs.action}}
-
{{i18n admin.logs.screened_emails.match_count}}
-
{{i18n admin.logs.screened_emails.last_match_at}}
+
{{i18n admin.logs.match_count}}
+
{{i18n admin.logs.last_match_at}}
{{i18n admin.logs.created_at}}
diff --git a/app/assets/javascripts/admin/templates/logs/screened_urls.js.handlebars b/app/assets/javascripts/admin/templates/logs/screened_urls.js.handlebars new file mode 100644 index 00000000000..9ac85c0a0f3 --- /dev/null +++ b/app/assets/javascripts/admin/templates/logs/screened_urls.js.handlebars @@ -0,0 +1,24 @@ +

{{i18n admin.logs.screened_urls.description}}

+ +{{#if loading}} +
{{i18n loading}}
+{{else}} + {{#if model.length}} + +
+
+
{{i18n admin.logs.screened_urls.url}}
+
{{i18n admin.logs.action}}
+
{{i18n admin.logs.match_count}}
+
{{i18n admin.logs.last_match_at}}
+
{{i18n admin.logs.created_at}}
+
+
+ + {{view Discourse.ScreenedUrlsListView contentBinding="controller"}} +
+ + {{else}} + {{i18n search.no_results}} + {{/if}} +{{/if}} \ No newline at end of file diff --git a/app/assets/javascripts/admin/templates/logs/screened_urls_list_item.js.handlebars b/app/assets/javascripts/admin/templates/logs/screened_urls_list_item.js.handlebars new file mode 100644 index 00000000000..babb5e4b43a --- /dev/null +++ b/app/assets/javascripts/admin/templates/logs/screened_urls_list_item.js.handlebars @@ -0,0 +1,6 @@ +
{{url}}
+
{{actionName}}
+
{{match_count}}
+
{{unboundAgeWithTooltip last_match_at}}
+
{{unboundAgeWithTooltip created_at}}
+
\ No newline at end of file diff --git a/app/assets/javascripts/admin/views/logs/screened_urls_list_view.js b/app/assets/javascripts/admin/views/logs/screened_urls_list_view.js new file mode 100644 index 00000000000..98f65049cb8 --- /dev/null +++ b/app/assets/javascripts/admin/views/logs/screened_urls_list_view.js @@ -0,0 +1,5 @@ +Discourse.ScreenedUrlsListView = Ember.ListView.extend({ + height: 700, + rowHeight: 32, + itemViewClass: Ember.ListItemView.extend({templateName: "admin/templates/logs/screened_urls_list_item"}) +}); diff --git a/app/assets/stylesheets/admin/admin_base.scss b/app/assets/stylesheets/admin/admin_base.scss index 1d17eaada0f..41e6738de1a 100644 --- a/app/assets/stylesheets/admin/admin_base.scss +++ b/app/assets/stylesheets/admin/admin_base.scss @@ -700,9 +700,9 @@ table { // Logs -.blocked-emails { +.screened-emails, .screened-urls { width: 900px; - .email { + .email, .url { width: 400px; } .action, .match_count, .last_match_at, .created_at { @@ -775,7 +775,7 @@ table { position: absolute; } -.blocked-emails, .staff-actions { +.staff-actions, .screened-emails, .screened-urls { margin-left: 5px; border-bottom: dotted 1px #ddd; diff --git a/app/controllers/admin/screened_urls_controller.rb b/app/controllers/admin/screened_urls_controller.rb new file mode 100644 index 00000000000..cc605e97aa9 --- /dev/null +++ b/app/controllers/admin/screened_urls_controller.rb @@ -0,0 +1,8 @@ +class Admin::ScreenedUrlsController < Admin::AdminController + + def index + screened_urls = ScreenedUrl.limit(200).order('last_match_at desc').to_a + render_serialized(screened_urls, ScreenedUrlSerializer) + end + +end diff --git a/app/serializers/screened_url_serializer.rb b/app/serializers/screened_url_serializer.rb new file mode 100644 index 00000000000..6d109e1ddcb --- /dev/null +++ b/app/serializers/screened_url_serializer.rb @@ -0,0 +1,12 @@ +class ScreenedUrlSerializer < ApplicationSerializer + attributes :url, + :domain, + :action, + :match_count, + :last_match_at, + :created_at + + def action + ScreenedUrl.actions.key(object.action_type).to_s + end +end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 0110b69e77f..ce9e289f19f 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1181,15 +1181,11 @@ en: title: "Logs" action: "Action" created_at: "Created" - screened_emails: - title: "Screened Emails" - description: "When someone tries to create a new account, the following email addresses will be checked and the registration will be blocked, or some other action performed." - email: "Email Address" - last_match_at: "Last Matched" - match_count: "Matches" - actions: - block: "block" - do_nothing: "do nothing" + last_match_at: "Last Matched" + match_count: "Matches" + screened_actions: + block: "block" + do_nothing: "do nothing" staff_actions: title: "Staff Actions" instructions: "Click usernames and actions to filter the list. Click avatars to go to user pages." @@ -1202,6 +1198,14 @@ en: actions: delete_user: "delete user" change_trust_level: "change trust level" + screened_emails: + title: "Screened Emails" + description: "When someone tries to create a new account, the following email addresses will be checked and the registration will be blocked, or some other action performed." + email: "Email Address" + screened_urls: + title: "Screened URLs" + description: "The URLs listed here were used in posts by users who have been identified as spammers." + url: "URL" impersonate: title: "Impersonate User" diff --git a/config/routes.rb b/config/routes.rb index d52c7a8e316..6f1863bf84d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -64,8 +64,9 @@ Discourse::Application.routes.draw do end scope '/logs' do - resources :screened_emails, only: [:index, :create, :update, :destroy] - resources :staff_action_logs, only: [:index, :create, :update, :destroy] + resources :staff_action_logs, only: [:index] + resources :screened_emails, only: [:index] + resources :screened_urls, only: [:index] end get 'customize' => 'site_customizations#index', constraints: AdminConstraint.new diff --git a/spec/controllers/admin/screened_urls_controller_spec.rb b/spec/controllers/admin/screened_urls_controller_spec.rb new file mode 100644 index 00000000000..979da4674e2 --- /dev/null +++ b/spec/controllers/admin/screened_urls_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Admin::ScreenedUrlsController do + it "is a subclass of AdminController" do + (Admin::ScreenedUrlsController < Admin::AdminController).should be_true + end + + let!(:user) { log_in(:admin) } + + context '.index' do + before do + xhr :get, :index + end + + subject { response } + it { should be_success } + + it 'returns JSON' do + ::JSON.parse(subject.body).should be_a(Array) + end + end +end