Skip to content

Commit

Permalink
Added admin pages on menu, implemented teams server-side, #19.
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Schodde committed Sep 16, 2014
1 parent 133646c commit 3554c5a
Show file tree
Hide file tree
Showing 32 changed files with 1,537 additions and 25 deletions.
3 changes: 1 addition & 2 deletions client/app/login/login.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ angular.module('linesPerBeatApp')
password: $scope.password
};
Userservice.login(loginData).success(function (loginResp) {
$window.localStorage.setItem('user', $scope.username);
$materialToast({
controller: 'ToastCtrl',
templateUrl: 'components/toast/toast.html',
Expand All @@ -18,7 +17,7 @@ angular.module('linesPerBeatApp')
message: loginResp.message
}
});
$rootScope.$broadcast('loggedIn', {user: $scope.username});
$rootScope.$broadcast('loggedIn', {user: $scope.username, admin: loginResp.admin});
}).error(function (error) {
$materialToast({
controller: 'ToastCtrl',
Expand Down
31 changes: 29 additions & 2 deletions client/components/navbar/navbar.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ angular.module('linesPerBeatApp').controller('NavbarCtrl', ['$scope', '$location
active: false,
disabled: false,
show: false
},{
title: '',
link: '',
active: false,
disabled: true,
show: false
},{
title: 'Admin',
link: '/admin',
active: false,
disabled: false,
show: false
},{
title: 'Admin Register',
link: '/admin/register',
active: false,
disabled: false,
show: false
}];
$scope.onTabSelected = function (tab) {
$scope.selectedItem = this.$index;
Expand All @@ -60,23 +78,32 @@ angular.module('linesPerBeatApp').controller('NavbarCtrl', ['$scope', '$location
};
$scope.$on('loggedIn', function (event, reply) {
$window.localStorage.setItem('user', reply.user);
$scope.username = $window.localStorage.getItem('user');
$window.localStorage.setItem('admin', reply.admin);
$scope.username = reply.user;
$scope.menu[3].show = false;
$scope.menu[4].show = true;
$scope.menu[5].show = true;
$scope.menu[6].show = true;
if(reply.admin) {
$scope.menu[7].show = true;
$scope.menu[8].show = true;
$scope.menu[9].show = true;
}
$location.path('/');
});
$rootScope.$on('loggedOut', function () {
$scope.menu[3].show = true;
$scope.menu[4].show = false;
$scope.menu[5].show = false;
$scope.menu[6].show = false;
$scope.menu[7].show = false;
$scope.menu[8].show = false;
$scope.menu[9].show = false;
$location.path('/');
});
$scope.username = $window.localStorage.getItem('user');
if($scope.username !== null) {
$scope.$emit('loggedIn', {user: $scope.username});
$scope.$emit('loggedIn', {user: $scope.username, admin: $window.localStorage.getItem('admin')});
}
$scope.logout = function () {
Userservice.logout().success(function (logoutResp) {
Expand Down
27 changes: 19 additions & 8 deletions install.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ var settings = require('./server/config/environment');
var db = require('./server/components/database');
db.initialize('couchdb');

var userView = {views: {"all": {"map": "function(doc) {emit(null, doc)}","reduce": "_count"},"by_username": {"map": "function(doc) {emit(doc.username, doc)}","reduce": "_count"}, "by_admins": {"map": "function(doc) { if(doc.admin) {emit(doc.username, doc)}}","reduce": "_count"}}};
var userView = {views: {"all": {"map": "function(doc) {emit(null, doc)}","reduce": "_count"},"by_username": {"map": "function(doc) {emit(doc.username, doc)}","reduce": "_count"}, "by_id": {"map": "function(doc) {emit(doc._id, doc)}","reduce": "_count"}, "by_admins": {"map": "function(doc) { if(doc.admin) {emit(doc.username, doc)}}","reduce": "_count"}}};
var childListView = {views: {"all": {"map": "function(doc) {emit(null, doc)}","reduce": "_count"},"by_pid": {"map": "function(doc) {emit(doc.pid, doc)}","reduce": "_count"}}};
var teamView = {views: {"all": {"map": "function(doc) {emit(null, doc)}","reduce": "_count"},"by_name": {"map": "function(doc) {emit(doc.name, doc)}","reduce": "_count"},"by_id": {"map": "function(doc) {emit(doc._id, doc)}","reduce": "_count"}}};

db.createDB(settings.couchdb.users, function (err, body) {
if(err && err.status_code !== 412) {
Expand All @@ -15,9 +16,8 @@ db.createDB(settings.couchdb.users, function (err, body) {
db.insert(users, '_design/users', userView, function (err) {
// 409 is Document update conflict.
if(err && err.status_code !== 409) {
console.log('Error recreating database.'.red);
console.log(err);
return;
console.log('Error creating database.'.red);
return console.log(err);
}
db.createDB(settings.couchdb.childProcesses, function (err, body) {
if(err && err.status_code !== 412) {
Expand All @@ -27,11 +27,22 @@ db.createDB(settings.couchdb.users, function (err, body) {
// Insert view to make a lookup calls with.
db.insert(childProcesses, '_design/childProcesses', childListView, function (err, body) {
if(err && err.status_code !== 409) {
console.log('Error recreating database.'.red);
console.log(err);
return;
console.log('Error creating database.'.red);
return console.log(err);
}
console.log('DB Installation successful.'.green);
db.createDB(settings.couchdb.teams, function (err, body) {
if(err && err.status_code !== 412) {
return console.log(err);
}
var teams = db.getTeamsTable();
db.insert(teams, '_design/teams', teamView, function (err, body) {
if(err && err.status_code !== 409) {
console.log('Error creating database.'.red);
return console.log(err);
}
console.log('DB Installation successful.'.green);
});
});
});
});
});
Expand Down
1 change: 1 addition & 0 deletions server/api/admin/deleteAccount/deleteAccount.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exports.index = function(req, res) {
if(username === requestor) {
return res.json(400, {message: 'Can\'t delete your own account.'});
}
// Delete the user from their team before we delete them.
db.deleteUserByUsername(username, function (error, reply) {
if(error) {
console.log(error);
Expand Down
32 changes: 32 additions & 0 deletions server/api/admin/deleteMember/deleteMember.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

var validator = require('validator');
var db = require('../../../components/database');

db.initialize('couchdb');

// Delete a member from a team.
exports.index = function(req, res) {
if(!req.session.username || !req.session.isAdmin) {
return res.json(401, {message: 'Please sign in.'});
}
var teamName = req.body.teamname;
var username = req.body.username;
var requestor = req.session.username;
if(validator.isNull(username)) {
return res.json(400, {message: 'Missing username.'});
}
if(validator.isNull(teamName)) {
return res.json(400, {message: 'Missing username.'});
}
if(username === requestor) {
return res.json(400, {message: 'Can\'t remove yourself from a team.'});
}
db.deleteUserFromTeam(teamName, username, function (error) {
if(error) {
console.log(error);
return res.json(500, {message: 'Could not delete member, check logs.'});
}
return res.json({message: 'Member deleted.'});
});
};
164 changes: 164 additions & 0 deletions server/api/admin/deleteMember/deleteMember.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
'use strict';

var app = require('../../../app');
var request = require('supertest');
var assert = require('assert');
var uuid = require('node-uuid');
var db = require('../../../components/database');
var bcrypt = require('bcrypt');
var settings = require('../../../config/environment');
db.initialize('couchdb');
var users = db.getUsersTable();
var teams = db.getTeamsTable();
var cookie;

describe('POST /api/admin/deleteMember', function() {

beforeEach(function (done) {
var admin = {
username: 'mockAdmin',
password: bcrypt.hashSync('mockPassword', 10),
firstName: 'Foo',
lastName: 'Bar',
avatar: 'assets/images/default.png',
lastfm: {
username: '',
currentSong: {
artist: '',
song: '',
url: '',
lastUpdated: Date.now()
}
},
linesPerMinute: 0.0,
linesLastUpdated: Date.now(),
admin: true
};
var user = {
username: 'mockUser',
password: bcrypt.hashSync('mockPassword', 10),
firstName: 'Foo',
lastName: 'Bar',
avatar: 'images/default.png',
lastfm: {
username: '',
currentSong: {
artist: '',
song: '',
url: '',
lastUpdated: Date.now()
}
},
linesPerMinute: 0.0,
linesLastUpdated: Date.now(),
admin: false
};
var userId = uuid.v4();
var team = {
name: 'MockTeam',
logo: 'http://i.imgur.com/BS2iaX2.jpg',
users: [userId]
};
db.insert(users, uuid.v4(), admin, function (error) {
if (error) {
console.log('Error inserting new admin.'.red);
return done(error);
}
db.insert(users, userId, user, function (error) {
if (error) {
console.log('Error inserting new user.'.red);
return done(error);
}
db.insert(teams, uuid.v4(), team, function (error) {
if (error) {
console.log('Error inserting new team.'.red);
return done(error);
}
request(app).post('/api/user/login')
.send({username: 'mockAdmin', password: 'mockPassword'})
.expect(200)
.expect('Content-Type', /json/)
.end(function(error, res) {
if (error) {
return done(error);
}
cookie = res.headers['set-cookie'];
done();
});
});
});
});
});

afterEach(function (done) {
db.searchUserByAll(function (error, reply) {
if (error) {
console.log('Error retrieving admins.'.red);
return done(error);
}
var docs = [];
for (var i = 0; i < reply.rows.length; i++) {
var user = reply.rows[i].value;
user._deleted = true;
docs.push(user);
}
db.deleteAllUsers(docs, function(error, reply) {
if (error) {
console.log('Error deleting admins.'.red);
return done(error);
}
db.compactUserDB(function (error, reply) {
if (error) {
console.log('Error compacting user database.'.red);
return done(error);
}
db.searchTeamByAll(function (error, reply) {
if (error) {
console.log('Error retrieving teams.'.red);
return done(error);
}
var docs = [];
for (var i = 0; i < reply.rows.length; i++) {
var team = reply.rows[i].value;
team._deleted = true;
docs.push(team);
}
db.deleteAllTeams(docs, function(error, reply) {
if (error) {
console.log('Error deleting teams.'.red);
return done(error);
}
db.compactTeamDB(function (error, reply) {
if (error) {
console.log('Error compacting team database.'.red);
return done(error);
}
done();
});
});
});
});
});
});
});

it('should successfully delete a member from the team.', function(done) {
var memberReq = {
teamname: 'MockTeam',
username: 'mockUser'
};
request(app)
.post('/api/admin/deleteMember')
.expect(200)
.expect('Content-Type', /json/)
.set('cookie', cookie)
.send(memberReq)
.end(function(err, res) {
if (err) {
return done(err);
}
assert.equal(res.body.message, 'Member deleted.')
done();
});
});
});
10 changes: 10 additions & 0 deletions server/api/admin/deleteMember/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

var express = require('express');
var controller = require('./deleteMember.controller');

var router = express.Router();

router.post('/', controller.index);

module.exports = router;
28 changes: 28 additions & 0 deletions server/api/admin/deleteTeam/deleteTeam.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

var validator = require('validator');
var db = require('../../../components/database');

db.initialize('couchdb');

// Deletes a team based on team name.
exports.index = function(req, res) {
if(!req.session.username || !req.session.isAdmin) {
return res.json(401, {message: 'Please sign in.'});
}
var admin = req.session.username;
var teamName = req.body.name;
if(validator.isNull(teamName)) {
return res.json(400, {message: 'Missing team name.'});
}
if(teamName === 'Admins') {
return res.json(400, {message: 'Cannot delete the admin team.'});
}
db.deleteTeamByName(teamName, function (error, reply) {
if(error) {
console.log(error);
return res.json(500, {message: 'Could not delete team, check logs.'});
}
return res.json({message: 'Team deleted.'});
});
};
Loading

0 comments on commit 3554c5a

Please sign in to comment.