Blocked Emails list in admin

This commit is contained in:
Neil Lalonde 2013-08-01 21:30:13 -04:00
parent c091b44028
commit d2fb6ec53f
14 changed files with 194 additions and 0 deletions

View file

@ -0,0 +1,21 @@
/**
This controller supports the interface for listing blocked email addresses in the admin section.
@class AdminLogsBlockedEmailsController
@extends Ember.ArrayController
@namespace Discourse
@module Discourse
**/
Discourse.AdminLogsBlockedEmailsController = Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
show: function() {
var self = this;
this.set('loading', true);
Discourse.BlockedEmail.findAll().then(function(result) {
console.log('findAll done');
self.set('content', result);
self.set('loading', false);
});
}
});

View file

@ -0,0 +1,26 @@
/**
Represents an email address that is watched for during account registration,
and an action is taken.
@class BlockedEmail
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.BlockedEmail = Discourse.Model.extend({
actionName: function() {
return I18n.t("admin.logs.actions." + this.get('action'));
}.property('action')
});
Discourse.BlockedEmail.reopenClass({
findAll: function(filter) {
return Discourse.ajax("/admin/logs/blocked_emails.json").then(function(blocked_emails) {
return blocked_emails.map(function(b) {
return Discourse.BlockedEmail.create(b);
})
});
}
});

View file

@ -0,0 +1,35 @@
/**
Index redirects to a default logs index.
@class AdminLogsIndexRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.AdminLogsIndexRoute = Discourse.Route.extend({
redirect: function() {
this.transitionTo('adminLogs.blockedEmails');
}
});
/**
The route that lists blocked email addresses.
@class AdminLogsBlockedEmailsRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.AdminLogsBlockedEmailsRoute = Discourse.Route.extend({
// model: function() {
// return Discourse.BlockedEmail.findAll();
// },
renderTemplate: function() {
this.render('admin/templates/logs/blocked_emails', {into: 'adminLogs'});
},
setupController: function() {
return this.controllerFor('adminLogsBlockedEmails').show();
}
});

View file

@ -29,6 +29,10 @@ Discourse.Route.buildRoutes(function() {
this.route('old', { path: '/old' });
});
this.resource('adminLogs', { path: '/logs' }, function() {
this.route('blockedEmails', { path: '/blocked_emails' });
});
this.route('groups', {path: '/groups'});
this.resource('adminUsers', { path: '/users' }, function() {

View file

@ -14,6 +14,7 @@
{{/if}}
<li>{{#linkTo 'adminEmail'}}{{i18n admin.email.title}}{{/linkTo}}</li>
<li>{{#linkTo 'adminFlags'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
<li>{{#linkTo 'adminLogs'}}{{i18n admin.logs.title}}{{/linkTo}}</li>
{{#if currentUser.admin}}
<li>{{#linkTo 'admin.customize'}}{{i18n admin.customize.title}}{{/linkTo}}</li>
<li>{{#linkTo 'admin.api'}}{{i18n admin.api.title}}{{/linkTo}}</li>

View file

@ -0,0 +1,9 @@
<div class='admin-controls'>
<div class='span15'>
<ul class="nav nav-pills">
<li>{{#linkTo 'adminLogs.blockedEmails'}}{{i18n admin.logs.blocked_emails}}{{/linkTo}}</li>
</ul>
</div>
</div>
{{outlet}}

View file

@ -0,0 +1,29 @@
{{#if loading}}
<div class='admin-loading'>{{i18n loading}}</div>
{{else}}
{{#if model.length}}
<table class='table blocked-emails'>
<thead>
<th class="email">{{i18n admin.logs.email}}</th>
<th class="action">{{i18n admin.logs.action}}</th>
<th class="match_count">{{i18n admin.logs.match_count}}</th>
<th class="last_match_at">{{i18n admin.logs.last_match_at}}</th>
<th class="created_at">{{i18n admin.logs.created_at}}</th>
</thead>
<tbody>
{{#each model}}
<tr>
<td class="email">{{email}}</td>
<td class="action">{{actionName}}</td>
<td class="match_count">{{match_count}}</td>
<td class="last_match_at">{{unboundAgeWithTooltip last_match_at}}</td>
<td class="created_at">{{unboundAgeWithTooltip created_at}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
No results.
{{/if}}
{{/if}}

View file

@ -693,3 +693,11 @@ table {
width: 600px;
}
}
/* Logs */
.blocked-emails {
.match_count, .last_match_at, .created_at {
text-align: center;
}
}

View file

@ -0,0 +1,8 @@
class Admin::BlockedEmailsController < Admin::AdminController
def index
blocked_emails = BlockedEmail.limit(50).order('created_at desc').to_a
render_serialized(blocked_emails, BlockedEmailSerializer)
end
end

View file

@ -1,3 +1,7 @@
# A BlockedEmail record represents an email address that is being watched,
# typically when creating a new User account. If the email of the signup form
# (or some other form) matches a BlockedEmail record, an action can be
# performed based on the action_type.
class BlockedEmail < ActiveRecord::Base
before_validation :set_defaults

View file

@ -0,0 +1,11 @@
class BlockedEmailSerializer < ApplicationSerializer
attributes :email,
:action,
:match_count,
:last_match_at,
:created_at
def action
BlockedEmail.actions.key(object.action_type).to_s
end
end

View file

@ -1160,6 +1160,18 @@ en:
last_seen_user: "Last Seen User:"
reply_key: "Reply Key"
logs:
title: "Logs"
blocked_emails: "Blocked Emails"
email: "Email Address"
action: "Action"
last_match_at: "Last Matched"
match_count: "Matches"
created_at: "Created"
actions:
block: "block"
do_nothing: "do nothing"
impersonate:
title: "Impersonate User"
username_or_email: "Username or Email of User"

View file

@ -62,6 +62,10 @@ Discourse::Application.routes.draw do
end
end
scope '/logs' do
resources :blocked_emails, only: [:index, :create, :update, :destroy]
end
get 'customize' => 'site_customizations#index', constraints: AdminConstraint.new
get 'flags' => 'flags#index'
get 'flags/:filter' => 'flags#index'

View file

@ -0,0 +1,22 @@
require 'spec_helper'
describe Admin::BlockedEmailsController do
it "is a subclass of AdminController" do
(Admin::BlockedEmailsController < 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