1
0
Fork 0

Remove one pod (#76)

* Client: Fix typo

* Client: Add removeFriend feature

* Server: Add removeFriend feature

* Server: Update method name

* Fix rebase onto develop issues

* Server: Fix error message

* Server: Remove useless methods in removeFriend method

* Server: Finish remove on pod feature after rebase

* Server: Type pod parameter

* Fix Travis build

* Add friend-basic test for the remove one pod feature

* Add check-params tests for the remove one pod feature

* Fix typos

* Add friend-advanced test for the remove one pod feature

* Client: Trailing new line

* Move to promises

* Add undefined id test

* Use find method instead of a for loop to find the friend to remove

* Remove setTimeout method

* Server: Remove requestScheduler operations

* Server: Fix logging messages

* Server: Remove sign request parameter
This commit is contained in:
Green-Star 2017-08-02 21:50:42 +02:00 committed by Bigard Florian
parent 291e8d3eed
commit d5f5a670fc
10 changed files with 324 additions and 13 deletions

View File

@ -2,7 +2,7 @@
<div class="content-padding">
<h3>Friends list</h3>
<ng2-smart-table [settings]="tableSettings" [source]="friendsSource"></ng2-smart-table>
<ng2-smart-table [settings]="tableSettings" [source]="friendsSource" (delete)="removeFriend($event)"></ng2-smart-table>
<a *ngIf="hasFriends()" class="btn btn-danger pull-left" (click)="quitFriends()">
Quit friends

View File

@ -6,6 +6,7 @@ import { ServerDataSource } from 'ng2-smart-table'
import { ConfirmService } from '../../../core'
import { Utils } from '../../../shared'
import { FriendService } from '../shared'
import { Pod } from '../../../../../../shared'
@Component({
selector: 'my-friend-list',
@ -15,6 +16,7 @@ import { FriendService } from '../shared'
export class FriendListComponent {
friendsSource = null
tableSettings = {
mode: 'external',
attr: {
class: 'table-hover'
},
@ -23,7 +25,10 @@ export class FriendListComponent {
position: 'right',
add: false,
edit: false,
delete: false
delete: true
},
delete: {
deleteButtonContent: Utils.getRowDeleteButton()
},
columns: {
id: {
@ -71,8 +76,7 @@ export class FriendListComponent {
this.friendService.quitFriends().subscribe(
status => {
this.notificationsService.success('Sucess', 'Friends left!')
this.notificationsService.success('Success', 'Friends left!')
this.friendsSource.refresh()
},
@ -81,4 +85,24 @@ export class FriendListComponent {
}
)
}
removeFriend ({ data }) {
const confirmMessage = 'Do you really want to remove this friend ? All its videos will be deleted.'
const friend: Pod = data
this.confirmService.confirm(confirmMessage, 'Remove').subscribe(
res => {
if (res === false) return
this.friendService.removeFriend(friend).subscribe(
status => {
this.notificationsService.success('Success', 'Friend removed')
this.friendsSource.refresh()
},
err => this.notificationsService.error('Error', err.text)
)
}
)
}
}

View File

@ -6,6 +6,7 @@ import 'rxjs/add/operator/map'
import { ServerDataSource } from 'ng2-smart-table'
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared'
import { Pod } from '../../../../../../shared'
@Injectable()
export class FriendService {
@ -20,7 +21,7 @@ export class FriendService {
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL)
}
makeFriends (notEmptyHosts) {
makeFriends (notEmptyHosts: String[]) {
const body = {
hosts: notEmptyHosts
}
@ -35,4 +36,10 @@ export class FriendService {
.map(res => res.status)
.catch((res) => this.restExtractor.handleError(res))
}
removeFriend (friend: Pod) {
return this.authHttp.delete(FriendService.BASE_FRIEND_URL + friend.id)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res))
}
}

View File

@ -10,7 +10,8 @@ import {
import {
sendOwnedVideosToPod,
makeFriends,
quitFriends
quitFriends,
removeFriend
} from '../../lib'
import {
podsAddValidator,
@ -18,7 +19,8 @@ import {
ensureIsAdmin,
makeFriendsValidator,
setBodyHostPort,
setBodyHostsPort
setBodyHostsPort,
podRemoveValidator
} from '../../middlewares'
import {
PodInstance
@ -45,6 +47,12 @@ podsRouter.get('/quitfriends',
ensureIsAdmin,
quitFriendsController
)
podsRouter.delete('/:id',
authenticate,
ensureIsAdmin,
podRemoveValidator,
removeFriendController
)
// ---------------------------------------------------------------------------
@ -93,3 +101,11 @@ function quitFriendsController (req: express.Request, res: express.Response, nex
.then(() => res.type('json').status(204).end())
.catch(err => next(err))
}
function removeFriendController (req: express.Request, res: express.Response, next: express.NextFunction) {
const pod = res.locals.pod as PodInstance
removeFriend(pod)
.then(() => (res.type('json').status(204).end()))
.catch(err => next(err))
}

View File

@ -242,6 +242,23 @@ function fetchRemotePreview (pod: PodInstance, video: VideoInstance) {
return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
}
function removeFriend (pod: PodInstance) {
const requestParams = {
method: 'POST' as 'POST',
path: '/api/' + API_VERSION + '/remote/pods/remove',
toPod: pod
}
return makeSecureRequest(requestParams)
.then(() => pod.destroy())
.then(() => {
logger.info('Removed friend.')
})
.catch(err => {
logger.error('Some errors while quitting friend %s (id: %d).', pod.host, pod.id, err)
})
}
function getRequestScheduler () {
return requestScheduler
}
@ -268,6 +285,7 @@ export {
hasFriends,
makeFriends,
quitFriends,
removeFriend,
removeVideoToFriends,
sendOwnedVideosToPod,
getRequestScheduler,

View File

@ -58,9 +58,33 @@ function podsAddValidator (req: express.Request, res: express.Response, next: ex
})
}
function podRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
req.checkParams('id', 'Should have a valid id').notEmpty().isNumeric()
logger.debug('Checking podRemoveValidator parameters', { parameters: req.params })
checkErrors(req, res, function () {
db.Pod.load(req.params.id)
.then(pod => {
if (!pod) {
logger.error('Cannot find pod %d.', req.params.id)
return res.sendStatus(404)
}
res.locals.pod = pod
return next()
})
.catch(err => {
logger.error('Cannot load pod %d.', req.params.id, err)
res.sendStatus(500)
})
})
}
// ---------------------------------------------------------------------------
export {
makeFriendsValidator,
podsAddValidator
podsAddValidator,
podRemoveValidator
}

View File

@ -17,7 +17,7 @@ describe('Test pods API validators', function () {
// ---------------------------------------------------------------
before(function (done) {
this.timeout(20000)
this.timeout(45000)
series([
function (next) {
@ -110,7 +110,7 @@ describe('Test pods API validators', function () {
.expect(400, done)
})
it('Should fail with a invalid token', function (done) {
it('Should fail with an invalid token', function (done) {
request(server.url)
.post(path + '/makefriends')
.send(body)
@ -130,7 +130,7 @@ describe('Test pods API validators', function () {
})
describe('When quitting friends', function () {
it('Should fail with a invalid token', function (done) {
it('Should fail with an invalid token', function (done) {
request(server.url)
.get(path + '/quitfriends')
.query({ start: 'hello' })
@ -148,6 +148,50 @@ describe('Test pods API validators', function () {
.expect(403, done)
})
})
describe('When removing one friend', function () {
it('Should fail with an invalid token', function (done) {
request(server.url)
.delete(path + '/1')
.set('Authorization', 'Bearer faketoken')
.set('Accept', 'application/json')
.expect(401, done)
})
it('Should fail if the user is not an administrator', function (done) {
request(server.url)
.delete(path + '/1')
.set('Authorization', 'Bearer ' + userAccessToken)
.set('Accept', 'application/json')
.expect(403, done)
})
it('Should fail with an undefined id', function (done) {
request(server.url)
.delete(path + '/' + undefined)
.set('Authorization', 'Bearer ' + server.accessToken)
.set('Accept', 'application/json')
.expect(400, done)
})
it('Should fail with an invalid id', function (done) {
request(server.url)
.delete(path + '/foobar')
.set('Authorization', 'Bearer ' + server.accessToken)
.set('Accept', 'application/json')
.expect(400, done)
})
it('Should fail if the pod is not a friend', function (done) {
request(server.url)
.delete(path + '/-1')
.set('Authorization', 'Bearer ' + server.accessToken)
.set('Accept', 'application/json')
.expect(404, done)
})
it('Should succeed with the correct parameters')
})
})
describe('When adding a pod', function () {
@ -181,7 +225,7 @@ describe('Test pods API validators', function () {
requestsUtils.makePostBodyRequest(server.url, path, null, data, done)
})
it('Should fail without an host', function (done) {
it('Should fail without a host', function (done) {
const data = {
email: 'testexample.com',
publicKey: 'mysuperpublickey'

View File

@ -25,6 +25,20 @@ describe('Test advanced friends', function () {
return podsUtils.quitFriends(server.url, server.accessToken, callback)
}
function removeFriend (podNumber, podNumberToRemove, callback) {
const server = servers[podNumber - 1]
const serverToRemove = servers[podNumberToRemove - 1]
getFriendsList(podNumber, function (err, res) {
if (err) throw err
let friendsList = res.body.data
let podToRemove = friendsList.find((friend) => (friend.host === serverToRemove.host))
return podsUtils.quitOneFriend(server.url, server.accessToken, podToRemove.id, callback)
})
}
function getFriendsList (podNumber, end) {
const server = servers[podNumber - 1]
return podsUtils.getFriendsList(server.url, end)
@ -288,6 +302,84 @@ describe('Test advanced friends', function () {
})
})
it('Should allow pod 6 to quit pod 1 & 2 and be friend with pod 3', function (done) {
this.timeout(30000)
series([
// Pod 3 should have 4 friends
function (next) {
getFriendsList(3, function (err, res) {
if (err) throw err
const friendsList = res.body.data
expect(friendsList).to.be.an('array')
expect(friendsList.length).to.equal(4)
next()
})
},
// Pod 1, 2, 6 should have 3 friends each
function (next) {
each([ 1, 2, 6 ], function (i, callback) {
getFriendsList(i, function (err, res) {
if (err) throw err
const friendsList = res.body.data
expect(friendsList).to.be.an('array')
expect(friendsList.length).to.equal(3)
callback()
})
}, next)
},
function (next) {
removeFriend(6, 1, next)
},
function (next) {
removeFriend(6, 2, next)
},
// Pod 6 should now have only 1 friend (and it should be Pod 3)
function (next) {
getFriendsList(6, function (err, res) {
if (err) throw err
const friendsList = res.body.data
expect(friendsList).to.be.an('array')
expect(friendsList.length).to.equal(1)
expect(friendsList[0].host).to.equal(servers[2].host)
next()
})
},
// Pod 1 & 2 should not know friend 6 anymore
function (next) {
each([ 1, 2 ], function (i, callback) {
getFriendsList(i, function (err, res) {
if (err) throw err
const friendsList = res.body.data
expect(friendsList).to.be.an('array')
expect(friendsList.length).to.equal(2)
callback()
})
}, next)
},
// Pod 3 should know every pod
function (next) {
getFriendsList(3, function (err, res) {
if (err) throw err
const friendsList = res.body.data
expect(friendsList).to.be.an('array')
expect(friendsList.length).to.equal(4)
next()
})
}
], done)
})
after(function (done) {
servers.forEach(function (server) {
process.kill(-server.app.pid)

View File

@ -198,6 +198,71 @@ describe('Test basic friends', function () {
})
})
it('Should allow pod 1 to quit only pod 2', function (done) {
series([
// Pod 1 quits pod 2
function (next) {
const server = servers[0]
// Get pod 2 id so we can query it
podsUtils.getFriendsList(server.url, function (err, res) {
if (err) throw err
const result = res.body.data
let pod = result.find((friend) => (friend.host === servers[1].host))
// Remove it from the friends list
podsUtils.quitOneFriend(server.url, server.accessToken, pod.id, next)
})
},
// Pod 1 should have only pod 3 in its friends list
function (next) {
podsUtils.getFriendsList(servers[0].url, function (err, res) {
if (err) throw err
const result = res.body.data
expect(result).to.be.an('array')
expect(result.length).to.equal(1)
const pod = result[0]
expect(pod.host).to.equal(servers[2].host)
next()
})
},
// Pod 2 should have only pod 3 in its friends list
function (next) {
podsUtils.getFriendsList(servers[1].url, function (err, res) {
if (err) throw err
const result = res.body.data
expect(result).to.be.an('array')
expect(result.length).to.equal(1)
const pod = result[0]
expect(pod.host).to.equal(servers[2].host)
next()
})
},
// Pod 3 should have both pods in its friends list
function (next) {
podsUtils.getFriendsList(servers[2].url, function (err, res) {
if (err) throw err
const result = res.body.data
expect(result).to.be.an('array')
expect(result.length).to.equal(2)
next()
})
}
], done)
})
after(function (done) {
servers.forEach(function (server) {
process.kill(-server.app.pid)

View File

@ -5,7 +5,8 @@ const request = require('supertest')
const podsUtils = {
getFriendsList,
makeFriends,
quitFriends
quitFriends,
quitOneFriend
}
// ---------------------- Export functions --------------------
@ -90,6 +91,26 @@ function quitFriends (url, accessToken, expectedStatus, end) {
})
}
function quitOneFriend (url, accessToken, friendId, expectedStatus, end) {
if (!end) {
end = expectedStatus
expectedStatus = 204
}
const path = '/api/v1/pods/' + friendId
request(url)
.delete(path)
.set('Accept', 'application/json')
.set('Authorization', 'Bearer ' + accessToken)
.expect(expectedStatus)
.end(function (err, res) {
if (err) throw err
end()
})
}
// ---------------------------------------------------------------------------
module.exports = podsUtils