Screened URLs list in admin

This commit is contained in:
Neil Lalonde 2013-08-15 10:48:30 -04:00
parent def134605d
commit 293361dcd3
16 changed files with 183 additions and 37 deletions

View File

@ -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);
});
}
});

View File

@ -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')
});

View File

@ -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);
});
});
}
});

View File

@ -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();
}
});

View File

@ -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'});

View File

@ -3,6 +3,7 @@
<ul class="nav nav-pills">
<li>{{#linkTo 'adminLogs.staffActionLogs'}}{{i18n admin.logs.staff_actions.title}}{{/linkTo}}</li>
<li>{{#linkTo 'adminLogs.screenedEmails'}}{{i18n admin.logs.screened_emails.title}}{{/linkTo}}</li>
<li>{{#linkTo 'adminLogs.screenedUrls'}}{{i18n admin.logs.screened_urls.title}}{{/linkTo}}</li>
</ul>
</div>
</div>

View File

@ -5,12 +5,12 @@
{{else}}
{{#if model.length}}
<div class='table blocked-emails'>
<div class='table screened-emails'>
<div class="heading-container">
<div class="col heading first email">{{i18n admin.logs.screened_emails.email}}</div>
<div class="col heading action">{{i18n admin.logs.action}}</div>
<div class="col heading match_count">{{i18n admin.logs.screened_emails.match_count}}</div>
<div class="col heading last_match_at">{{i18n admin.logs.screened_emails.last_match_at}}</div>
<div class="col heading match_count">{{i18n admin.logs.match_count}}</div>
<div class="col heading last_match_at">{{i18n admin.logs.last_match_at}}</div>
<div class="col heading created_at">{{i18n admin.logs.created_at}}</div>
<div class="clearfix"></div>
</div>

View File

@ -0,0 +1,24 @@
<p>{{i18n admin.logs.screened_urls.description}}</p>
{{#if loading}}
<div class='admin-loading'>{{i18n loading}}</div>
{{else}}
{{#if model.length}}
<div class='table screened-urls'>
<div class="heading-container">
<div class="col heading first url">{{i18n admin.logs.screened_urls.url}}</div>
<div class="col heading action">{{i18n admin.logs.action}}</div>
<div class="col heading match_count">{{i18n admin.logs.match_count}}</div>
<div class="col heading last_match_at">{{i18n admin.logs.last_match_at}}</div>
<div class="col heading created_at">{{i18n admin.logs.created_at}}</div>
<div class="clearfix"></div>
</div>
{{view Discourse.ScreenedUrlsListView contentBinding="controller"}}
</div>
{{else}}
{{i18n search.no_results}}
{{/if}}
{{/if}}

View File

@ -0,0 +1,6 @@
<div class="col first url">{{url}}</div>
<div class="col action">{{actionName}}</div>
<div class="col match_count">{{match_count}}</div>
<div class="col last_match_at">{{unboundAgeWithTooltip last_match_at}}</div>
<div class="col created_at">{{unboundAgeWithTooltip created_at}}</div>
<div class="clearfix"></div>

View File

@ -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"})
});

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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