From df120bdea3a0e62733090806f4d429e1ce64571a Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Thu, 2 Apr 2015 11:44:18 -0700 Subject: [PATCH] Delete clan --- app/templates/clans/clan-details.jade | 6 +-- app/views/clans/ClanDetailsView.coffee | 60 ++++++++++++++----------- server/clans/clan_handler.coffee | 14 +++++- test/server/functional/clan.spec.coffee | 48 +++++++++++++++++++- 4 files changed, 95 insertions(+), 33 deletions(-) diff --git a/app/templates/clans/clan-details.jade b/app/templates/clans/clan-details.jade index 1c54c6e3d..22446e943 100644 --- a/app/templates/clans/clan-details.jade +++ b/app/templates/clans/clan-details.jade @@ -8,11 +8,11 @@ block content | ) div if isOwner - button.btn.btn-sm.btn-warning Delete Clan + button.btn.btn-sm.btn-warning.delete-clan-btn Delete Clan else if isMember - button.btn.btn-sm.btn-warning.leave-clan-btn(data-id="#{clan.id}") Leave Clan + button.btn.btn-sm.btn-warning.leave-clan-btn Leave Clan else - button.btn.btn-sm.btn-success.join-clan-btn(data-id="#{clan.id}") Join Clan + button.btn.btn-sm.btn-success.join-clan-btn Join Clan if clan.get('members') h3 Clan Members (#{clan.get('members').length}) diff --git a/app/views/clans/ClanDetailsView.coffee b/app/views/clans/ClanDetailsView.coffee index 41632430c..c8ccb3591 100644 --- a/app/views/clans/ClanDetailsView.coffee +++ b/app/views/clans/ClanDetailsView.coffee @@ -4,6 +4,7 @@ RootView = require 'views/core/RootView' template = require 'templates/clans/clan-details' Clan = require 'models/Clan' +# TODO: Message for clan not found # TODO: join/leave mostly duped from clans view module.exports = class ClanDetailsView extends RootView @@ -11,6 +12,7 @@ module.exports = class ClanDetailsView extends RootView template: template events: + 'click .delete-clan-btn': 'onDeleteClan' 'click .join-clan-btn': 'onJoinClan' 'click .leave-clan-btn': 'onLeaveClan' 'click .remove-member-btn': 'onRemoveMember' @@ -27,36 +29,42 @@ module.exports = class ClanDetailsView extends RootView context.isMember = _.find(@clan.get('members'), (m) -> m.id is me.id) ? false context + onDeleteClan: (e) -> + return @openModalView(new AuthModal()) if me.isAnonymous() + options = + url: "/db/clan/#{@clanID}" + method: 'DELETE' + error: (model, response, options) => + console.error 'Error joining clan', response + success: (model, response, options) => + app.router.navigate "/clans" + window.location.reload() + @supermodel.addRequestResource( 'delete_clan', options).load() + onJoinClan: (e) -> return @openModalView(new AuthModal()) if me.isAnonymous() - if clanID = $(e.target).data('id') - options = - url: "/db/clan/#{clanID}/join" - method: 'PUT' - error: (model, response, options) => - console.error 'Error joining clan', response - success: (model, response, options) => - @listenToOnce @clan, 'sync', => - @render?() - @clan.fetch cache: false - @supermodel.addRequestResource( 'join_clan', options).load() - else - console.error "No clan ID attached to join button." + options = + url: "/db/clan/#{@clanID}/join" + method: 'PUT' + error: (model, response, options) => + console.error 'Error joining clan', response + success: (model, response, options) => + @listenToOnce @clan, 'sync', => + @render?() + @clan.fetch cache: false + @supermodel.addRequestResource( 'join_clan', options).load() onLeaveClan: (e) -> - if clanID = $(e.target).data('id') - options = - url: "/db/clan/#{clanID}/leave" - method: 'PUT' - error: (model, response, options) => - console.error 'Error leaving clan', response - success: (model, response, options) => - @listenToOnce @clan, 'sync', => - @render?() - @clan.fetch cache: false - @supermodel.addRequestResource( 'leave_clan', options).load() - else - console.error "No clan ID attached to leave button." + options = + url: "/db/clan/#{@clanID}/leave" + method: 'PUT' + error: (model, response, options) => + console.error 'Error leaving clan', response + success: (model, response, options) => + @listenToOnce @clan, 'sync', => + @render?() + @clan.fetch cache: false + @supermodel.addRequestResource( 'leave_clan', options).load() onRemoveMember: (e) -> if memberID = $(e.target).data('id') diff --git a/server/clans/clan_handler.coffee b/server/clans/clan_handler.coffee index 3dc0f0b3b..dc9fb78ab 100644 --- a/server/clans/clan_handler.coffee +++ b/server/clans/clan_handler.coffee @@ -17,6 +17,7 @@ ClanHandler = class ClanHandler extends Handler method = (method or req.method).toLowerCase() return true if req.user?.isAdmin() return true if method is 'get' + return true if document.get('ownerID')?.equals req.user._id false makeNewInstance: (req) -> @@ -29,6 +30,15 @@ ClanHandler = class ClanHandler extends Handler ] instance + delete: (req, res, clanID) -> + @getDocumentForIdOrSlug clanID, (err, clan) => + return @sendDatabaseError res, err if err + return @sendNotFoundError res unless clan + return @sendForbiddenError res unless @hasAccessToDocument(req, clan) + Clan.remove {_id: clan.get('_id')}, (err) => + return @sendDatabaseError res, err if err + @sendNoContent(res) + getByRelationship: (req, res, args...) -> return @joinClan(req, res, args[0]) if args[1] is 'join' return @leaveClan(req, res, args[0]) if args[1] is 'leave' @@ -62,10 +72,10 @@ ClanHandler = class ClanHandler extends Handler clanID = mongoose.Types.ObjectId(clanID) memberID = mongoose.Types.ObjectId(memberID) catch err - return @sendBadInputError(res, err) + return @sendNotFoundError(res, err) Clan.findById clanID, (err, clan) => return @sendDatabaseError(res, err) if err - return @sendForbiddenError(res) unless clan.get('ownerID')?.equals req.user._id + return @sendForbiddenError res unless @hasAccessToDocument(req, clan) return @sendForbiddenError(res) if clan.get('ownerID').equals memberID Clan.update {_id: clanID}, {$pull: {members: {id: memberID}}}, (err) => return @sendDatabaseError(res, err) if err diff --git a/test/server/functional/clan.spec.coffee b/test/server/functional/clan.spec.coffee index 1b77f4e58..56b77cd80 100644 --- a/test/server/functional/clan.spec.coffee +++ b/test/server/functional/clan.spec.coffee @@ -194,12 +194,12 @@ describe 'Clans', -> expect(clan1.get('members')[0].id).toEqual(user1.get('_id')) done() - it 'Remove invalid memberID 422', (done) -> + it 'Remove invalid memberID 404', (done) -> loginNewUser (user1) -> createClan 'public', (clan1) -> request.put {uri: "#{clanURL}/#{clan1.id}/remove/123" }, (err, res, body) -> expect(err).toBeNull() - expect(res.statusCode).toBe(422) + expect(res.statusCode).toBe(404) done() it 'Remove member, not in clan 403', (done) -> @@ -238,3 +238,47 @@ describe 'Clans', -> expect(err).toBeNull() expect(res.statusCode).toBe(403) done() + + it 'Delete clan', (done) -> + loginNewUser (user1) -> + createClan 'public', (clan) -> + request.del {uri: "#{clanURL}/#{clan.id}" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(204) + done() + + it 'Delete clan anonymous 401', (done) -> + loginNewUser (user1) -> + createClan 'public', (clan) -> + logoutUser -> + request.del {uri: "#{clanURL}/#{clan.id}" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(401) + done() + + it 'Delete clan not owner 403', (done) -> + loginNewUser (user1) -> + createClan 'public', (clan) -> + loginNewUser (user2) -> + request.del {uri: "#{clanURL}/#{clan.id}" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(403) + done() + + it 'Delete clan no longer exists 404', (done) -> + loginNewUser (user1) -> + createClan 'public', (clan) -> + request.del {uri: "#{clanURL}/#{clan.id}" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(204) + request.del {uri: "#{clanURL}/#{clan.id}" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(404) + done() + + it 'Delete clan invalid ID 404', (done) -> + loginNewUser (user1) -> + request.del {uri: "#{clanURL}/1234" }, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe(404) + done()