mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Merge pull request #2359 from laituan245/master
Added ability to delete account
This commit is contained in:
commit
4cbbcdad6d
7 changed files with 97 additions and 5 deletions
|
@ -50,7 +50,12 @@ module.exports.loginUser = (userObject, failure=genericFailure, nextURL=null) ->
|
|||
|
||||
module.exports.logoutUser = ->
|
||||
FB?.logout?()
|
||||
res = $.post('/auth/logout', {}, -> window.location.reload())
|
||||
callback = ->
|
||||
if (window.location.href.indexOf("/account/settings") > -1)
|
||||
window.location = '/'
|
||||
else
|
||||
window.location.reload()
|
||||
res = $.post('/auth/logout', {}, callback)
|
||||
res.fail(genericFailure)
|
||||
|
||||
onSetVolume = (e) ->
|
||||
|
|
|
@ -604,13 +604,17 @@
|
|||
autosave: "Changes Save Automatically"
|
||||
me_tab: "Me"
|
||||
picture_tab: "Picture"
|
||||
delete_account_tab: "Delete Your Account"
|
||||
wrong_email: "Wrong Email"
|
||||
upload_picture: "Upload a picture"
|
||||
delete_this_account: "Delete this account permanently"
|
||||
god_mode: "God Mode"
|
||||
password_tab: "Password"
|
||||
emails_tab: "Emails"
|
||||
admin: "Admin"
|
||||
new_password: "New Password"
|
||||
new_password_verify: "Verify"
|
||||
type_in_email: "Type in your email to confirm the deletion"
|
||||
email_subscriptions: "Email Subscriptions"
|
||||
email_subscriptions_none: "No Email Subscriptions."
|
||||
email_announcements: "Announcements"
|
||||
|
|
|
@ -276,6 +276,7 @@ _.extend UserSchema.properties,
|
|||
|
||||
earned: c.RewardSchema 'earned by achievements'
|
||||
purchased: c.RewardSchema 'purchased with gems or money'
|
||||
deleted: {type: 'boolean'}
|
||||
spent: {type: 'number'}
|
||||
stripeCustomerID: { type: 'string' } # TODO: Migrate away from this property
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
.panel-title
|
||||
font-size: 20px
|
||||
|
||||
#delete-account-panel-title
|
||||
color: #F00
|
||||
|
||||
//- Panel specific stuff
|
||||
|
||||
.profile-photo
|
||||
|
|
|
@ -48,6 +48,16 @@ else
|
|||
label.control-label(for="password2", data-i18n="account_settings.new_password_verify") Verify
|
||||
input#password2.form-control(name="password2", type="password")
|
||||
|
||||
.panel.panel-default
|
||||
.panel-heading
|
||||
.panel-title#delete-account-panel-title(data-i18n="account_settings.delete_account_tab")
|
||||
.panel-body
|
||||
.form
|
||||
.form-group
|
||||
label.control-label(for="email1", data-i18n="account_settings.type_in_email") Type in your email to confirm the deletion
|
||||
input#email1.form-control(name="email1", type="text")
|
||||
button#delete-account-button.btn.form-control.btn-primary(data-i18n="account_settings.delete_this_account")
|
||||
|
||||
.col-md-6
|
||||
|
||||
#email-panel.panel.panel-default
|
||||
|
|
|
@ -4,6 +4,8 @@ template = require 'templates/account/account-settings-view'
|
|||
forms = require 'core/forms'
|
||||
User = require 'models/User'
|
||||
AuthModal = require 'views/core/AuthModal'
|
||||
ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
||||
{logoutUser, me} = require('core/auth')
|
||||
|
||||
module.exports = class AccountSettingsView extends CocoView
|
||||
id: 'account-settings-view'
|
||||
|
@ -16,6 +18,7 @@ module.exports = class AccountSettingsView extends CocoView
|
|||
'click #toggle-all-button': 'toggleEmailSubscriptions'
|
||||
'click .profile-photo': 'onEditProfilePhoto'
|
||||
'click #upload-photo-button': 'onEditProfilePhoto'
|
||||
'click #delete-account-button': 'confirmAccountDeletion'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
@ -35,10 +38,12 @@ module.exports = class AccountSettingsView extends CocoView
|
|||
|
||||
|
||||
#- Form input callbacks
|
||||
|
||||
onInputChanged: (e) ->
|
||||
$(e.target).addClass 'changed'
|
||||
@trigger 'input-changed'
|
||||
if (JSON.stringify(document.getElementById('email1').className)).indexOf("changed") > -1
|
||||
$(e.target).removeClass 'changed'
|
||||
else
|
||||
@trigger 'input-changed'
|
||||
|
||||
toggleEmailSubscriptions: =>
|
||||
subs = @getSubscriptions()
|
||||
|
@ -62,7 +67,49 @@ module.exports = class AccountSettingsView extends CocoView
|
|||
|
||||
|
||||
#- Just copied from OptionsView, TODO refactor
|
||||
|
||||
|
||||
confirmAccountDeletion: ->
|
||||
forms.clearFormAlerts(@$el)
|
||||
myEmail = me.get 'email'
|
||||
email1 = document.getElementById('email1').value
|
||||
if Boolean(email1) and email1 is myEmail
|
||||
renderData =
|
||||
'confirmTitle': 'Are you really sure?'
|
||||
'confirmBody': 'This will completely delete your account. This action CANNOT be undone. Are you entirely sure?'
|
||||
'confirmDecline': 'Not really'
|
||||
'confirmConfirm': 'Definitely'
|
||||
confirmModal = new ConfirmModal renderData
|
||||
confirmModal.on 'confirm', @deleteAccount
|
||||
@openModalView confirmModal
|
||||
else
|
||||
message = $.i18n.t('account_settings.wrong_email', defaultValue: 'Wrong Email.')
|
||||
err = [message: message, property: 'email1', formatted: true]
|
||||
forms.applyErrorsToForm(@$el, err)
|
||||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
|
||||
deleteAccount: ->
|
||||
myID = me.id
|
||||
$.ajax
|
||||
type: 'DELETE'
|
||||
success: ->
|
||||
noty
|
||||
timeout: 5000
|
||||
text: 'Your account is gone.'
|
||||
type: 'success'
|
||||
layout: 'topCenter'
|
||||
_.delay ->
|
||||
Backbone.Mediator.publish("auth:logging-out", {})
|
||||
window.tracker?.trackEvent 'Log Out', category:'Homepage', ['Google Analytics'] if @id is 'home-view'
|
||||
logoutUser($('#login-email').val())
|
||||
, 500
|
||||
error: (jqXHR, status, error) ->
|
||||
console.error jqXHR
|
||||
timeout: 5000
|
||||
text: "Deleting account failed with error code #{jqXHR.status}"
|
||||
type: 'error'
|
||||
layout: 'topCenter'
|
||||
url: "/db/user/#{myID}"
|
||||
|
||||
onEditProfilePhoto: (e) ->
|
||||
return if window.application.isIPadApp # TODO: have an iPad-native way of uploading a photo, since we don't want to load FilePicker on iPad (memory)
|
||||
photoContainer = @$el.find('.profile-photo')
|
||||
|
|
|
@ -28,6 +28,8 @@ candidateProperties = [
|
|||
UserHandler = class UserHandler extends Handler
|
||||
modelClass: User
|
||||
|
||||
allowedMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
|
||||
getEditableProperties: (req, document) ->
|
||||
props = super req, document
|
||||
props.push 'permissions' unless config.isProduction
|
||||
|
@ -211,11 +213,31 @@ UserHandler = class UserHandler extends Handler
|
|||
@put(req, res)
|
||||
|
||||
hasAccessToDocument: (req, document) ->
|
||||
if req.route.method in ['put', 'post', 'patch']
|
||||
if req.route.method in ['put', 'post', 'patch', 'delete']
|
||||
return true if req.user?.isAdmin()
|
||||
return req.user?._id.equals(document._id)
|
||||
return true
|
||||
|
||||
delete: (req, res, userID) ->
|
||||
# Instead of just deleting the User object, we should remove all the properties except for _id
|
||||
# And add a `deleted: true` property
|
||||
@getDocumentForIdOrSlug userID, (err, user) => # Check first
|
||||
return @sendDatabaseError res, err if err
|
||||
return @sendNotFoundError res unless user
|
||||
return @sendForbiddenError res unless @hasAccessToDocument(req, user)
|
||||
obj = user.toObject()
|
||||
for prop, val of obj
|
||||
user.set(prop, undefined) unless prop is '_id'
|
||||
user.set('deleted', true)
|
||||
|
||||
# Hack to get saving of Users to work. Probably should replace these props with strings
|
||||
# so that validation doesn't get hung up on Date objects in the documents.
|
||||
delete obj.dateCreated
|
||||
|
||||
user.save (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendNoContent res
|
||||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
return @agreeToCLA(req, res) if args[1] is 'agreeToCLA'
|
||||
return @agreeToEmployerAgreement(req, res) if args[1] is 'agreeToEmployerAgreement'
|
||||
|
|
Loading…
Reference in a new issue