<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
import { ConfirmService } from '../../../core'
import { Utils } from '../../../shared'
import { FriendService } from '../shared'
+import { Pod } from '../../../../../../shared'
@Component({
selector: 'my-friend-list',
export class FriendListComponent {
friendsSource = null
tableSettings = {
+ mode: 'external',
attr: {
class: 'table-hover'
},
position: 'right',
add: false,
edit: false,
- delete: false
+ delete: true
+ },
+ delete: {
+ deleteButtonContent: Utils.getRowDeleteButton()
},
columns: {
id: {
this.friendService.quitFriends().subscribe(
status => {
- this.notificationsService.success('Sucess', 'Friends left!')
-
+ this.notificationsService.success('Success', 'Friends left!')
this.friendsSource.refresh()
},
}
)
}
+
+ 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)
+ )
+ }
+ )
+ }
}
import { ServerDataSource } from 'ng2-smart-table'
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared'
+import { Pod } from '../../../../../../shared'
@Injectable()
export class FriendService {
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL)
}
- makeFriends (notEmptyHosts) {
+ makeFriends (notEmptyHosts: String[]) {
const body = {
hosts: notEmptyHosts
}
.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))
+ }
}
import {
sendOwnedVideosToPod,
makeFriends,
- quitFriends
+ quitFriends,
+ removeFriend
} from '../../lib'
import {
podsAddValidator,
ensureIsAdmin,
makeFriendsValidator,
setBodyHostPort,
- setBodyHostsPort
+ setBodyHostsPort,
+ podRemoveValidator
} from '../../middlewares'
import {
PodInstance
ensureIsAdmin,
quitFriendsController
)
+podsRouter.delete('/:id',
+ authenticate,
+ ensureIsAdmin,
+ podRemoveValidator,
+ removeFriendController
+)
// ---------------------------------------------------------------------------
.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))
+}
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
}
hasFriends,
makeFriends,
quitFriends,
+ removeFriend,
removeVideoToFriends,
sendOwnedVideosToPod,
getRequestScheduler,
})
}
+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
}
// ---------------------------------------------------------------
before(function (done) {
- this.timeout(20000)
+ this.timeout(45000)
series([
function (next) {
.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)
})
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' })
.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 () {
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'
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)
})
})
+ 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)
})
})
+ 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)
const podsUtils = {
getFriendsList,
makeFriends,
- quitFriends
+ quitFriends,
+ quitOneFriend
}
// ---------------------- Export functions --------------------
})
}
+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