mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-27 14:33:59 -04:00
Made espionage mode simpler, and added an admin user lookup.
This commit is contained in:
parent
4d24233b0d
commit
24d3d189df
4 changed files with 79 additions and 37 deletions
app
server
|
@ -2,17 +2,23 @@ extends /templates/base
|
|||
|
||||
block content
|
||||
|
||||
h3 Espionage mode
|
||||
h5 Please enter the email/username of the person you want to spy on
|
||||
.form
|
||||
.form-group
|
||||
label.control-label Email
|
||||
input#user-email
|
||||
.form-group
|
||||
label.control-label Username
|
||||
input#user-username
|
||||
|
||||
button.btn.btn-primary.btn-large#enter-espionage-mode 007
|
||||
.form-horizontal
|
||||
.form-group
|
||||
label.control-label.col-sm-2(for="espionage-name-or-email") Espionage
|
||||
.col-sm-4
|
||||
input.form-control#espionage-name-or-email(placeholder="Email or username", type="text")
|
||||
.col-sm-1
|
||||
button.btn.btn-primary.btn-large#enter-espionage-mode 007
|
||||
label.control-label.col-sm-5(for="espionage-name-or-email")
|
||||
em you are currently #{me.get('name')} at #{me.get('email')}
|
||||
.form-group
|
||||
label.control-label.col-sm-2(for="user-search") User Search
|
||||
.col-sm-4
|
||||
input.form-control#user-search(placeholder="Email, username, name, whatever", type="text")
|
||||
.col-sm-1
|
||||
button.btn.btn-primary.btn-large#user-search-button Search
|
||||
#user-search-result
|
||||
|
||||
|
||||
h3(data-i18n="admin.av_title") Admin Views
|
||||
|
||||
|
|
|
@ -5,32 +5,56 @@ template = require 'templates/admin'
|
|||
module.exports = class MainAdminView extends RootView
|
||||
id: 'admin-view'
|
||||
template: template
|
||||
lastUserSearchValue: ''
|
||||
|
||||
events:
|
||||
'keyup': 'checkForFormSubmissionEnterPress'
|
||||
'click #enter-espionage-mode': 'enterEspionageMode'
|
||||
'click #user-search-button': 'searchForUser'
|
||||
'click #increment-button': 'incrementUserAttribute'
|
||||
|
||||
checkForFormSubmissionEnterPress: (e) ->
|
||||
if e.which is 13 and @$el.find('#espionage-name-or-email').val() isnt ''
|
||||
@enterEspionageMode()
|
||||
return
|
||||
if @$el.find('#user-search').val() isnt @lastUserSearchValue
|
||||
@searchForUser()
|
||||
|
||||
enterEspionageMode: ->
|
||||
userEmail = $('#user-email').val().toLowerCase()
|
||||
username = $('#user-username').val().toLowerCase()
|
||||
|
||||
postData =
|
||||
usernameLower: username
|
||||
emailLower: userEmail
|
||||
|
||||
userNameOrEmail = @$el.find('#espionage-name-or-email').val().toLowerCase()
|
||||
$.ajax
|
||||
type: 'POST',
|
||||
url: '/auth/spy'
|
||||
data: postData
|
||||
data: {nameOrEmailLower: userNameOrEmail}
|
||||
success: @espionageSuccess
|
||||
error: @espionageFailure
|
||||
|
||||
espionageSuccess: (model) ->
|
||||
window.location.reload()
|
||||
|
||||
espionageFailure: (jqxhr, status,error)->
|
||||
espionageFailure: (jqxhr, status, error)->
|
||||
console.log "There was an error entering espionage mode: #{error}"
|
||||
|
||||
searchForUser: ->
|
||||
return @onSearchRequestSuccess [] unless @lastUserSearchValue = @$el.find('#user-search').val().toLowerCase()
|
||||
$.ajax
|
||||
type: 'POST',
|
||||
url: '/db/user/-/admin_search'
|
||||
data: {search: @lastUserSearchValue}
|
||||
success: @onSearchRequestSuccess
|
||||
error: @onSearchRequestFailure
|
||||
|
||||
onSearchRequestSuccess: (users) =>
|
||||
result = ''
|
||||
if users.length
|
||||
result = ("<tr><td><code>#{user._id}</code></td><td>#{_.escape(user.name or 'Anoner')}</td><td>#{_.escape(user.email)}</td></tr>" for user in users)
|
||||
result = "<table class=\"table\">#{result.join('\n')}</table>"
|
||||
@$el.find('#user-search-result').html(result)
|
||||
|
||||
onSearchRequestFailure: (jqxhr, status, error) =>
|
||||
return if @destroyed
|
||||
console.warn "There was an error looking up #{@lastUserSearchValue}:", error
|
||||
|
||||
incrementUserAttribute: (e) ->
|
||||
val = $('#increment-field').val()
|
||||
me.set(val, me.get(val) + 1)
|
||||
|
|
|
@ -32,23 +32,14 @@ module.exports.setup = (app) ->
|
|||
|
||||
app.post '/auth/spy', (req, res, next) ->
|
||||
if req?.user?.isAdmin()
|
||||
|
||||
username = req.body.usernameLower
|
||||
emailLower = req.body.emailLower
|
||||
if emailLower
|
||||
query = {'emailLower': emailLower}
|
||||
else if username
|
||||
query = {'nameLower': username}
|
||||
else
|
||||
return errors.badInput res, 'You need to supply one of emailLower or username'
|
||||
|
||||
target = req.body.nameOrEmailLower
|
||||
return errors.badInput res, 'Specify a username or email to espionage.' unless target
|
||||
query = $or: [{nameLower: target}, {emailLower: target}]
|
||||
User.findOne query, (err, user) ->
|
||||
if err? then return errors.serverError res, 'There was an error finding the specified user'
|
||||
|
||||
unless user then return errors.badInput res, 'The specified user couldn\'t be found'
|
||||
|
||||
req.logIn user, (err) ->
|
||||
if err? then return errors.serverError res, 'There was an error logging in with the specified'
|
||||
if err? then return errors.serverError res, 'There was an error logging in with the specified user'
|
||||
res.send(UserHandler.formatEntity(req, user))
|
||||
return res.end()
|
||||
else
|
||||
|
@ -117,7 +108,7 @@ module.exports.setup = (app) ->
|
|||
)
|
||||
)
|
||||
|
||||
app.get '/auth/unsubscribe', (req, res) ->
|
||||
app.get '/auth/unsubscribe', (req, res) ->
|
||||
req.query.email = decodeURIComponent(req.query.email)
|
||||
email = req.query.email
|
||||
unless req.query.email
|
||||
|
@ -132,7 +123,7 @@ module.exports.setup = (app) ->
|
|||
return errors.serverError res, 'Database failure.' if err
|
||||
res.send "Unsubscribed #{req.query.email} from CodeCombat emails for #{session.levelName} #{session.team} ladder updates. Sorry to see you go! <p><a href='/play/ladder/#{session.levelID}#my-matches'>Ladder preferences</a></p>"
|
||||
res.end()
|
||||
|
||||
|
||||
User.findOne({emailLower: req.query.email.toLowerCase()}).exec (err, user) ->
|
||||
if not user
|
||||
return errors.notFound res, "No user found with email '#{req.query.email}'"
|
||||
|
@ -147,7 +138,7 @@ module.exports.setup = (app) ->
|
|||
else if req.query.employerNotes
|
||||
emails.employerNotes ?= {}
|
||||
emails.employerNotes.enabled = false
|
||||
|
||||
|
||||
msg = "Unsubscribed #{req.query.email} from employer emails."
|
||||
else
|
||||
msg = "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go!"
|
||||
|
|
|
@ -13,6 +13,7 @@ LevelSession = require '../levels/sessions/LevelSession'
|
|||
LevelSessionHandler = require '../levels/sessions/level_session_handler'
|
||||
EarnedAchievement = require '../achievements/EarnedAchievement'
|
||||
UserRemark = require './remarks/UserRemark'
|
||||
{isID} = require '../lib/utils'
|
||||
|
||||
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset']
|
||||
candidateProperties = [
|
||||
|
@ -187,6 +188,7 @@ UserHandler = class UserHandler extends Handler
|
|||
return @getRecentlyPlayed(req, res, args[0]) if args[1] is 'recently_played'
|
||||
return @trackActivity(req, res, args[0], args[2], args[3]) if args[1] is 'track' and args[2]
|
||||
return @getRemark(req, res, args[0]) if args[1] is 'remark'
|
||||
return @searchForUser(req, res) if args[1] is 'admin_search'
|
||||
return @sendNotFoundError(res)
|
||||
super(arguments...)
|
||||
|
||||
|
@ -388,6 +390,25 @@ UserHandler = class UserHandler extends Handler
|
|||
return @sendNotFoundError res unless remark?
|
||||
@sendSuccess res, remark
|
||||
|
||||
searchForUser: (req, res) ->
|
||||
# TODO: also somehow search the CLAs to find a match amongst those fields and to find GitHub ids
|
||||
return @sendUnauthorizedError(res) unless req.user.isAdmin()
|
||||
search = req.body.search
|
||||
query = email: {$exists: true}, $or: [
|
||||
{emailLower: search}
|
||||
{nameLower: search}
|
||||
]
|
||||
query.$or.push {_id: mongoose.Types.ObjectId(search) if isID search}
|
||||
if search.length > 5
|
||||
searchParts = search.split(/[.+@]/)
|
||||
if searchParts.length > 1
|
||||
query.$or.push {emailLower: {$regex: '^' + searchParts[0]}}
|
||||
projection = name: 1, email: 1, dateCreated: 1
|
||||
User.find(query).select(projection).lean().exec (err, users) =>
|
||||
return @sendDatabaseError res, err if err
|
||||
@sendSuccess res, users
|
||||
|
||||
|
||||
countEdits = (model, done) ->
|
||||
statKey = User.statsMapping.edits[model.modelName]
|
||||
return done(new Error 'Could not resolve statKey for model') unless statKey?
|
||||
|
@ -578,7 +599,7 @@ UserHandler = class UserHandler extends Handler
|
|||
thangTypeTranslationPatches: (done) ->
|
||||
countPatchesByUsersInMemory {'target.collection': 'thang_type'}, isTranslationPatch, User.statsMapping.translations['thang.type'], done
|
||||
|
||||
|
||||
|
||||
recalculateStats: (statName, done) =>
|
||||
done new Error 'Recalculation handler not found' unless statName of @statRecalculators
|
||||
@statRecalculators[statName] done
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue