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:
parent
291e8d3eed
commit
d5f5a670fc
10 changed files with 324 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue