diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.html b/client/src/app/+admin/follows/followers-list/followers-list.component.html
index 24d75d2b3..549aacdf0 100644
--- a/client/src/app/+admin/follows/followers-list/followers-list.component.html
+++ b/client/src/app/+admin/follows/followers-list/followers-list.component.html
@@ -7,9 +7,9 @@
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
-
+
-
+
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.html b/client/src/app/+admin/follows/following-list/following-list.component.html
index fbcebfaa7..dcc03f4a5 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.html
+++ b/client/src/app/+admin/follows/following-list/following-list.component.html
@@ -7,10 +7,15 @@
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
-
+
-
+
+
+
+
+
+
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.ts b/client/src/app/+admin/follows/following-list/following-list.component.ts
index a1dff1db3..411b8f640 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.ts
+++ b/client/src/app/+admin/follows/following-list/following-list.component.ts
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications'
import { SortMeta } from 'primeng/primeng'
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
+import { ConfirmService } from '../../../core/confirm/confirm.service'
import { RestPagination, RestTable } from '../../../shared'
import { FollowService } from '../shared'
@@ -18,11 +19,29 @@ export class FollowingListComponent extends RestTable {
constructor (
private notificationsService: NotificationsService,
+ private confirmService: ConfirmService,
private followService: FollowService
) {
super()
}
+ removeFollowing (follow: AccountFollow) {
+ this.confirmService.confirm(`Do you really want to unfollow ${follow.following.host}?`, 'Unfollow').subscribe(
+ res => {
+ if (res === false) return
+
+ this.followService.unfollow(follow).subscribe(
+ () => {
+ this.notificationsService.success('Success', `You are not following ${follow.following.host} anymore.`)
+ this.loadData()
+ },
+
+ err => this.notificationsService.error('Error', err.message)
+ )
+ }
+ )
+ }
+
protected loadData () {
this.followService.getFollowing(this.pagination, this.sort)
.subscribe(
diff --git a/client/src/app/+admin/follows/shared/follow.service.ts b/client/src/app/+admin/follows/shared/follow.service.ts
index f66ed477d..0bfbe8eb6 100644
--- a/client/src/app/+admin/follows/shared/follow.service.ts
+++ b/client/src/app/+admin/follows/shared/follow.service.ts
@@ -37,7 +37,7 @@ export class FollowService {
.catch(res => this.restExtractor.handleError(res))
}
- follow (notEmptyHosts: String[]) {
+ follow (notEmptyHosts: string[]) {
const body = {
hosts: notEmptyHosts
}
@@ -46,4 +46,10 @@ export class FollowService {
.map(this.restExtractor.extractDataBool)
.catch(res => this.restExtractor.handleError(res))
}
+
+ unfollow (follow: AccountFollow) {
+ return this.authHttp.delete(FollowService.BASE_APPLICATION_URL + '/following/' + follow.following.id)
+ .map(this.restExtractor.extractDataBool)
+ .catch(res => this.restExtractor.handleError(res))
+ }
}
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts
index 6debf89be..1e8e1af49 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/users/user-list/user-list.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core'
+import { Component } from '@angular/core'
import { SortMeta } from 'primeng/components/common/sortmeta'
import { NotificationsService } from 'angular2-notifications'
@@ -12,7 +12,7 @@ import { UserService } from '../shared'
templateUrl: './user-list.component.html',
styleUrls: [ './user-list.component.scss' ]
})
-export class UserListComponent extends RestTable implements OnInit {
+export class UserListComponent extends RestTable {
users: User[] = []
totalRecords = 0
rowsPerPage = 10
@@ -27,10 +27,6 @@ export class UserListComponent extends RestTable implements OnInit {
super()
}
- ngOnInit () {
- this.loadData()
- }
-
removeUser (user: User) {
if (user.username === 'root') {
this.notificationsService.error('Error', 'You cannot delete root.')
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 9c7c31a61..c46043931 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -134,7 +134,7 @@ const CONSTRAINTS_FIELDS = {
VIEWS: { min: 0 },
LIKES: { min: 0 },
DISLIKES: { min: 0 },
- FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 3 /* 3Go */ },
+ FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 10 /* 10Go */ },
URL: { min: 3, max: 2000 } // Length
},
ACCOUNTS: {
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts
index 5d09423e1..610b800fb 100644
--- a/server/lib/activitypub/process/process-undo.ts
+++ b/server/lib/activitypub/process/process-undo.ts
@@ -10,7 +10,7 @@ async function processUndoActivity (activity: ActivityUndo) {
const following = await db.Account.loadByUrl(activityToUndo.object)
const accountFollow = await db.AccountFollow.loadByAccountAndTarget(follower.id, following.id)
- if (!accountFollow) throw new Error(`'Unknown account follow (${follower.id} -> ${following.id}.`)
+ if (!accountFollow) throw new Error(`'Unknown account follow ${follower.id} -> ${following.id}.`)
await accountFollow.destroy()
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts
index e22349726..dfd6e7f03 100644
--- a/server/middlewares/validators/follows.ts
+++ b/server/middlewares/validators/follows.ts
@@ -1,12 +1,12 @@
import * as express from 'express'
-import { body } from 'express-validator/check'
+import { body, param } from 'express-validator/check'
import { isTestInstance } from '../../helpers/core-utils'
-import { isAccountIdValid } from '../../helpers/custom-validators/activitypub/account'
import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers'
import { logger } from '../../helpers/logger'
import { CONFIG, database as db } from '../../initializers'
import { checkErrors } from './utils'
import { getServerAccount } from '../../helpers/utils'
+import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
const followValidator = [
body('hosts').custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
@@ -28,7 +28,7 @@ const followValidator = [
]
const removeFollowingValidator = [
- body('accountId').custom(isAccountIdValid).withMessage('Should have a valid account id'),
+ param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking follow parameters', { parameters: req.body })
diff --git a/server/models/account/account-follow-interface.ts b/server/models/account/account-follow-interface.ts
index 21fda98ce..6f228c790 100644
--- a/server/models/account/account-follow-interface.ts
+++ b/server/models/account/account-follow-interface.ts
@@ -1,18 +1,19 @@
-import * as Sequelize from 'sequelize'
import * as Bluebird from 'bluebird'
-import { FollowState } from '../../../shared/models/accounts/follow.model'
+import * as Sequelize from 'sequelize'
+import { AccountFollow, FollowState } from '../../../shared/models/accounts/follow.model'
import { ResultList } from '../../../shared/models/result-list.model'
import { AccountInstance } from './account-interface'
export namespace AccountFollowMethods {
export type LoadByAccountAndTarget = (accountId: number, targetAccountId: number) => Bluebird
- export type ListFollowingForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList >
- export type ListFollowersForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList >
+ export type ListFollowingForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList>
+ export type ListFollowersForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList>
export type ListAcceptedFollowerUrlsForApi = (accountId: number[], start?: number, count?: number) => Promise< ResultList >
export type ListAcceptedFollowingUrlsForApi = (accountId: number[], start?: number, count?: number) => Promise< ResultList >
export type ListAcceptedFollowerSharedInboxUrls = (accountId: number[]) => Promise< ResultList >
+ export type ToFormattedJSON = (this: AccountFollowInstance) => AccountFollow
}
export interface AccountFollowClass {
@@ -38,6 +39,8 @@ export interface AccountFollowInstance extends AccountFollowClass, AccountFollow
AccountFollower?: AccountInstance
AccountFollowing?: AccountInstance
+
+ toFormattedJSON: AccountFollowMethods.ToFormattedJSON
}
export interface AccountFollowModel extends AccountFollowClass, Sequelize.Model {}
diff --git a/server/models/account/account-follow.ts b/server/models/account/account-follow.ts
index f00c7dcd9..34ba3f8db 100644
--- a/server/models/account/account-follow.ts
+++ b/server/models/account/account-follow.ts
@@ -12,6 +12,7 @@ let listFollowersForApi: AccountFollowMethods.ListFollowersForApi
let listAcceptedFollowerUrlsForApi: AccountFollowMethods.ListAcceptedFollowerUrlsForApi
let listAcceptedFollowingUrlsForApi: AccountFollowMethods.ListAcceptedFollowingUrlsForApi
let listAcceptedFollowerSharedInboxUrls: AccountFollowMethods.ListAcceptedFollowerSharedInboxUrls
+let toFormattedJSON: AccountFollowMethods.ToFormattedJSON
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
AccountFollow = sequelize.define('AccountFollow',
@@ -46,7 +47,10 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
listAcceptedFollowingUrlsForApi,
listAcceptedFollowerSharedInboxUrls
]
- addMethodsToModel(AccountFollow, classMethods)
+ const instanceMethods = [
+ toFormattedJSON
+ ]
+ addMethodsToModel(AccountFollow, classMethods, instanceMethods)
return AccountFollow
}
@@ -73,6 +77,22 @@ function associate (models) {
})
}
+toFormattedJSON = function (this: AccountFollowInstance) {
+ const follower = this.AccountFollower.toFormattedJSON()
+ const following = this.AccountFollowing.toFormattedJSON()
+
+ const json = {
+ id: this.id,
+ follower,
+ following,
+ state: this.state,
+ createdAt: this.createdAt,
+ updatedAt: this.updatedAt
+ }
+
+ return json
+}
+
loadByAccountAndTarget = function (accountId: number, targetAccountId: number) {
const query = {
where: {
@@ -122,7 +142,7 @@ listFollowingForApi = function (id: number, start: number, count: number, sort:
return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
return {
- data: rows.map(r => r.AccountFollowing),
+ data: rows,
total: count
}
})
@@ -154,7 +174,7 @@ listFollowersForApi = function (id: number, start: number, count: number, sort:
return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
return {
- data: rows.map(r => r.AccountFollower),
+ data: rows,
total: count
}
})
diff --git a/shared/models/accounts/follow.model.ts b/shared/models/accounts/follow.model.ts
index 8094634c1..cdc3da560 100644
--- a/shared/models/accounts/follow.model.ts
+++ b/shared/models/accounts/follow.model.ts
@@ -1,8 +1,12 @@
+import { Account } from './account.model'
+
export type FollowState = 'pending' | 'accepted'
export interface AccountFollow {
id: number
- name: string
- score?: number // Used for followers
- host: string
+ follower: Account
+ following: Account
+ state: FollowState
+ createdAt: Date
+ updatedAt: Date
}
diff --git a/support/nginx/peertube b/support/nginx/peertube
index f7db3eea3..8120738f6 100644
--- a/support/nginx/peertube
+++ b/support/nginx/peertube
@@ -10,6 +10,9 @@ server {
# For the video upload
client_max_body_size 2G;
+ proxy_connect_timeout 600;
+ proxy_send_timeout 600;
+ proxy_read_timeout 600;
}
# Bypass PeerTube webseed route for better performances
diff --git a/support/nginx/peertube-https b/support/nginx/peertube-https
index 1b9c40e7f..f46442835 100644
--- a/support/nginx/peertube-https
+++ b/support/nginx/peertube-https
@@ -23,6 +23,9 @@ server {
# For the video upload
client_max_body_size 2G;
+ proxy_connect_timeout 600;
+ proxy_send_timeout 600;
+ proxy_read_timeout 600;
}
# Bypass PeerTube webseed route for better performances