diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/helpers/custom-validators/activitypub/account.ts | 7 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/misc.ts | 10 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/videos.ts | 7 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-channels.ts | 8 | ||||
-rw-r--r-- | server/helpers/custom-validators/videos.ts | 6 | ||||
-rw-r--r-- | server/initializers/constants.ts | 11 | ||||
-rw-r--r-- | server/initializers/installer.ts | 20 | ||||
-rw-r--r-- | server/lib/user.ts | 3 | ||||
-rw-r--r-- | server/lib/video-channel.ts | 3 | ||||
-rw-r--r-- | server/models/account/account.ts | 36 | ||||
-rw-r--r-- | server/models/account/user.ts | 21 | ||||
-rw-r--r-- | server/models/pod/pod.ts | 10 | ||||
-rw-r--r-- | server/models/video/video-channel.ts | 9 | ||||
-rw-r--r-- | server/models/video/video.ts | 8 |
14 files changed, 95 insertions, 64 deletions
diff --git a/server/helpers/custom-validators/activitypub/account.ts b/server/helpers/custom-validators/activitypub/account.ts index 8a7d1b7fe..acd2b8058 100644 --- a/server/helpers/custom-validators/activitypub/account.ts +++ b/server/helpers/custom-validators/activitypub/account.ts | |||
@@ -3,6 +3,7 @@ import * as validator from 'validator' | |||
3 | import { exists, isUUIDValid } from '../misc' | 3 | import { exists, isUUIDValid } from '../misc' |
4 | import { isActivityPubUrlValid } from './misc' | 4 | import { isActivityPubUrlValid } from './misc' |
5 | import { isUserUsernameValid } from '../users' | 5 | import { isUserUsernameValid } from '../users' |
6 | import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' | ||
6 | 7 | ||
7 | function isAccountEndpointsObjectValid (endpointObject: any) { | 8 | function isAccountEndpointsObjectValid (endpointObject: any) { |
8 | return isAccountSharedInboxValid(endpointObject.sharedInbox) | 9 | return isAccountSharedInboxValid(endpointObject.sharedInbox) |
@@ -34,7 +35,8 @@ function isAccountPublicKeyValid (publicKey: string) { | |||
34 | return exists(publicKey) && | 35 | return exists(publicKey) && |
35 | typeof publicKey === 'string' && | 36 | typeof publicKey === 'string' && |
36 | publicKey.startsWith('-----BEGIN PUBLIC KEY-----') && | 37 | publicKey.startsWith('-----BEGIN PUBLIC KEY-----') && |
37 | publicKey.endsWith('-----END PUBLIC KEY-----') | 38 | publicKey.endsWith('-----END PUBLIC KEY-----') && |
39 | validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACCOUNTS.PUBLIC_KEY) | ||
38 | } | 40 | } |
39 | 41 | ||
40 | function isAccountIdValid (id: string) { | 42 | function isAccountIdValid (id: string) { |
@@ -73,7 +75,8 @@ function isAccountPrivateKeyValid (privateKey: string) { | |||
73 | return exists(privateKey) && | 75 | return exists(privateKey) && |
74 | typeof privateKey === 'string' && | 76 | typeof privateKey === 'string' && |
75 | privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') && | 77 | privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') && |
76 | privateKey.endsWith('-----END RSA PRIVATE KEY-----') | 78 | privateKey.endsWith('-----END RSA PRIVATE KEY-----') && |
79 | validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACCOUNTS.PRIVATE_KEY) | ||
77 | } | 80 | } |
78 | 81 | ||
79 | function isRemoteAccountValid (remoteAccount: any) { | 82 | function isRemoteAccountValid (remoteAccount: any) { |
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts index f049f5a8c..a94c36b51 100644 --- a/server/helpers/custom-validators/activitypub/misc.ts +++ b/server/helpers/custom-validators/activitypub/misc.ts | |||
@@ -1,4 +1,7 @@ | |||
1 | import * as validator from 'validator' | ||
1 | import { exists } from '../misc' | 2 | import { exists } from '../misc' |
3 | import { isTestInstance } from '../../core-utils' | ||
4 | import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' | ||
2 | 5 | ||
3 | function isActivityPubUrlValid (url: string) { | 6 | function isActivityPubUrlValid (url: string) { |
4 | const isURLOptions = { | 7 | const isURLOptions = { |
@@ -9,7 +12,12 @@ function isActivityPubUrlValid (url: string) { | |||
9 | protocols: [ 'http', 'https' ] | 12 | protocols: [ 'http', 'https' ] |
10 | } | 13 | } |
11 | 14 | ||
12 | return exists(url) && validator.isURL(url, isURLOptions) | 15 | // We validate 'localhost', so we don't have the top level domain |
16 | if (isTestInstance()) { | ||
17 | isURLOptions.require_tld = false | ||
18 | } | ||
19 | |||
20 | return exists(url) && validator.isURL(url, isURLOptions) && validator.isLength(url, CONSTRAINTS_FIELDS.ACCOUNTS.URL) | ||
13 | } | 21 | } |
14 | 22 | ||
15 | function isBaseActivityValid (activity: any, type: string) { | 23 | function isBaseActivityValid (activity: any, type: string) { |
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index 9233a1359..8f6d50f50 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -10,7 +10,8 @@ import { | |||
10 | isVideoTruncatedDescriptionValid, | 10 | isVideoTruncatedDescriptionValid, |
11 | isVideoDurationValid, | 11 | isVideoDurationValid, |
12 | isVideoNameValid, | 12 | isVideoNameValid, |
13 | isVideoTagValid | 13 | isVideoTagValid, |
14 | isVideoUrlValid | ||
14 | } from '../videos' | 15 | } from '../videos' |
15 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' | 16 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' |
16 | import { isBaseActivityValid } from './misc' | 17 | import { isBaseActivityValid } from './misc' |
@@ -93,7 +94,7 @@ function isRemoteVideoContentValid (mediaType: string, content: string) { | |||
93 | 94 | ||
94 | function isRemoteVideoIconValid (icon: any) { | 95 | function isRemoteVideoIconValid (icon: any) { |
95 | return icon.type === 'Image' && | 96 | return icon.type === 'Image' && |
96 | validator.isURL(icon.url) && | 97 | isVideoUrlValid(icon.url) && |
97 | icon.mediaType === 'image/jpeg' && | 98 | icon.mediaType === 'image/jpeg' && |
98 | validator.isInt(icon.width, { min: 0 }) && | 99 | validator.isInt(icon.width, { min: 0 }) && |
99 | validator.isInt(icon.height, { min: 0 }) | 100 | validator.isInt(icon.height, { min: 0 }) |
@@ -111,7 +112,7 @@ function setValidRemoteVideoUrls (video: any) { | |||
111 | function isRemoteVideoUrlValid (url: any) { | 112 | function isRemoteVideoUrlValid (url: any) { |
112 | return url.type === 'Link' && | 113 | return url.type === 'Link' && |
113 | ACTIVITY_PUB.VIDEO_URL_MIME_TYPES.indexOf(url.mimeType) !== -1 && | 114 | ACTIVITY_PUB.VIDEO_URL_MIME_TYPES.indexOf(url.mimeType) !== -1 && |
114 | validator.isURL(url.url) && | 115 | isVideoUrlValid(url.url) && |
115 | validator.isInt(url.width, { min: 0 }) && | 116 | validator.isInt(url.width, { min: 0 }) && |
116 | validator.isInt(url.size, { min: 0 }) | 117 | validator.isInt(url.size, { min: 0 }) |
117 | } | 118 | } |
diff --git a/server/helpers/custom-validators/video-channels.ts b/server/helpers/custom-validators/video-channels.ts index acc42f4a4..5787c3850 100644 --- a/server/helpers/custom-validators/video-channels.ts +++ b/server/helpers/custom-validators/video-channels.ts | |||
@@ -8,9 +8,14 @@ import { database as db, CONSTRAINTS_FIELDS } from '../../initializers' | |||
8 | import { VideoChannelInstance } from '../../models' | 8 | import { VideoChannelInstance } from '../../models' |
9 | import { logger } from '../logger' | 9 | import { logger } from '../logger' |
10 | import { exists } from './misc' | 10 | import { exists } from './misc' |
11 | import { isActivityPubUrlValid } from './index' | ||
11 | 12 | ||
12 | const VIDEO_CHANNELS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_CHANNELS | 13 | const VIDEO_CHANNELS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_CHANNELS |
13 | 14 | ||
15 | function isVideoChannelUrlValid (value: string) { | ||
16 | return isActivityPubUrlValid(value) | ||
17 | } | ||
18 | |||
14 | function isVideoChannelDescriptionValid (value: string) { | 19 | function isVideoChannelDescriptionValid (value: string) { |
15 | return value === null || validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.DESCRIPTION) | 20 | return value === null || validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.DESCRIPTION) |
16 | } | 21 | } |
@@ -53,5 +58,6 @@ export { | |||
53 | isVideoChannelDescriptionValid, | 58 | isVideoChannelDescriptionValid, |
54 | isVideoChannelNameValid, | 59 | isVideoChannelNameValid, |
55 | isVideoChannelUUIDValid, | 60 | isVideoChannelUUIDValid, |
56 | checkVideoChannelExists | 61 | checkVideoChannelExists, |
62 | isVideoChannelUrlValid | ||
57 | } | 63 | } |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index 487b3d646..715119cf6 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -19,6 +19,7 @@ import { isArray, exists } from './misc' | |||
19 | import { VideoInstance } from '../../models' | 19 | import { VideoInstance } from '../../models' |
20 | import { logger } from '../../helpers' | 20 | import { logger } from '../../helpers' |
21 | import { VideoRateType } from '../../../shared' | 21 | import { VideoRateType } from '../../../shared' |
22 | import { isActivityPubUrlValid } from './activitypub/misc' | ||
22 | 23 | ||
23 | const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS | 24 | const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS |
24 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES | 25 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES |
@@ -33,6 +34,10 @@ function isRemoteVideoCategoryValid (value: string) { | |||
33 | return validator.isInt('' + value) | 34 | return validator.isInt('' + value) |
34 | } | 35 | } |
35 | 36 | ||
37 | function isVideoUrlValid (value: string) { | ||
38 | return isActivityPubUrlValid(value) | ||
39 | } | ||
40 | |||
36 | function isVideoLicenceValid (value: number) { | 41 | function isVideoLicenceValid (value: number) { |
37 | return VIDEO_LICENCES[value] !== undefined | 42 | return VIDEO_LICENCES[value] !== undefined |
38 | } | 43 | } |
@@ -219,5 +224,6 @@ export { | |||
219 | isVideoTagValid, | 224 | isVideoTagValid, |
220 | isRemoteVideoCategoryValid, | 225 | isRemoteVideoCategoryValid, |
221 | isRemoteVideoLicenceValid, | 226 | isRemoteVideoLicenceValid, |
227 | isVideoUrlValid, | ||
222 | isRemoteVideoLanguageValid | 228 | isRemoteVideoLanguageValid |
223 | } | 229 | } |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 5d0d39395..e27d011fa 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -121,7 +121,8 @@ const CONSTRAINTS_FIELDS = { | |||
121 | }, | 121 | }, |
122 | VIDEO_CHANNELS: { | 122 | VIDEO_CHANNELS: { |
123 | NAME: { min: 3, max: 120 }, // Length | 123 | NAME: { min: 3, max: 120 }, // Length |
124 | DESCRIPTION: { min: 3, max: 250 } // Length | 124 | DESCRIPTION: { min: 3, max: 250 }, // Length |
125 | URL: { min: 3, max: 2000 } // Length | ||
125 | }, | 126 | }, |
126 | VIDEOS: { | 127 | VIDEOS: { |
127 | NAME: { min: 3, max: 120 }, // Length | 128 | NAME: { min: 3, max: 120 }, // Length |
@@ -137,7 +138,13 @@ const CONSTRAINTS_FIELDS = { | |||
137 | VIEWS: { min: 0 }, | 138 | VIEWS: { min: 0 }, |
138 | LIKES: { min: 0 }, | 139 | LIKES: { min: 0 }, |
139 | DISLIKES: { min: 0 }, | 140 | DISLIKES: { min: 0 }, |
140 | FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 3 /* 3Go */ } | 141 | FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 3 /* 3Go */ }, |
142 | URL: { min: 3, max: 2000 } // Length | ||
143 | }, | ||
144 | ACCOUNTS: { | ||
145 | PUBLIC_KEY: { min: 10, max: 5000 }, // Length | ||
146 | PRIVATE_KEY: { min: 10, max: 5000 }, // Length | ||
147 | URL: { min: 3, max: 2000 } // Length | ||
141 | }, | 148 | }, |
142 | VIDEO_EVENTS: { | 149 | VIDEO_EVENTS: { |
143 | COUNT: { min: 0 } | 150 | COUNT: { min: 0 } |
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index c617b16c9..5221b81a5 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts | |||
@@ -1,21 +1,25 @@ | |||
1 | import * as passwordGenerator from 'password-generator' | 1 | import * as passwordGenerator from 'password-generator' |
2 | import { UserRole } from '../../shared' | 2 | import { UserRole } from '../../shared' |
3 | import { logger, mkdirpPromise, rimrafPromise } from '../helpers' | 3 | import { logger, mkdirpPromise, rimrafPromise } from '../helpers' |
4 | import { createPrivateAndPublicKeys } from '../helpers/peertube-crypto' | ||
5 | import { createUserAccountAndChannel } from '../lib' | 4 | import { createUserAccountAndChannel } from '../lib' |
5 | import { createLocalAccount } from '../lib/user' | ||
6 | import { clientsExist, usersExist } from './checker' | 6 | import { clientsExist, usersExist } from './checker' |
7 | import { CACHE, CONFIG, LAST_MIGRATION_VERSION } from './constants' | 7 | import { CACHE, CONFIG, LAST_MIGRATION_VERSION } from './constants' |
8 | 8 | ||
9 | import { database as db } from './database' | 9 | import { database as db } from './database' |
10 | import { createLocalAccount } from '../lib/user' | ||
11 | 10 | ||
12 | async function installApplication () { | 11 | async function installApplication () { |
13 | await db.sequelize.sync() | 12 | try { |
14 | await removeCacheDirectories() | 13 | await db.sequelize.sync() |
15 | await createDirectoriesIfNotExist() | 14 | await removeCacheDirectories() |
16 | await createOAuthClientIfNotExist() | 15 | await createDirectoriesIfNotExist() |
17 | await createOAuthAdminIfNotExist() | 16 | await createOAuthClientIfNotExist() |
18 | await createApplicationIfNotExist() | 17 | await createOAuthAdminIfNotExist() |
18 | await createApplicationIfNotExist() | ||
19 | } catch (err) { | ||
20 | logger.error('Cannot install application.', err) | ||
21 | throw err | ||
22 | } | ||
19 | } | 23 | } |
20 | 24 | ||
21 | // --------------------------------------------------------------------------- | 25 | // --------------------------------------------------------------------------- |
diff --git a/server/lib/user.ts b/server/lib/user.ts index 1094c2401..d2d599dfd 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -16,8 +16,9 @@ async function createUserAccountAndChannel (user: UserInstance, validateUser = t | |||
16 | const userCreated = await user.save(userOptions) | 16 | const userCreated = await user.save(userOptions) |
17 | const accountCreated = await createLocalAccount(user.username, user.id, null, t) | 17 | const accountCreated = await createLocalAccount(user.username, user.id, null, t) |
18 | 18 | ||
19 | const videoChannelName = `Default ${userCreated.username} channel` | ||
19 | const videoChannelInfo = { | 20 | const videoChannelInfo = { |
20 | name: `Default ${userCreated.username} channel` | 21 | name: videoChannelName |
21 | } | 22 | } |
22 | const videoChannel = await createVideoChannel(videoChannelInfo, accountCreated, t) | 23 | const videoChannel = await createVideoChannel(videoChannelInfo, accountCreated, t) |
23 | 24 | ||
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 459d9d4a8..13841ea33 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -5,6 +5,7 @@ import { logger } from '../helpers' | |||
5 | import { AccountInstance } from '../models' | 5 | import { AccountInstance } from '../models' |
6 | import { VideoChannelCreate } from '../../shared/models' | 6 | import { VideoChannelCreate } from '../../shared/models' |
7 | import { sendCreateVideoChannel } from './activitypub/send-request' | 7 | import { sendCreateVideoChannel } from './activitypub/send-request' |
8 | import { getActivityPubUrl } from '../helpers/activitypub' | ||
8 | 9 | ||
9 | async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountInstance, t: Sequelize.Transaction) { | 10 | async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountInstance, t: Sequelize.Transaction) { |
10 | const videoChannelData = { | 11 | const videoChannelData = { |
@@ -15,6 +16,8 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account | |||
15 | } | 16 | } |
16 | 17 | ||
17 | const videoChannel = db.VideoChannel.build(videoChannelData) | 18 | const videoChannel = db.VideoChannel.build(videoChannelData) |
19 | videoChannel.set('url', getActivityPubUrl('videoChannel', videoChannel.uuid)) | ||
20 | |||
18 | const options = { transaction: t } | 21 | const options = { transaction: t } |
19 | 22 | ||
20 | const videoChannelCreated = await videoChannel.save(options) | 23 | const videoChannelCreated = await videoChannel.save(options) |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 6ef29c8b7..cd6c822f1 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -22,8 +22,8 @@ import { | |||
22 | 22 | ||
23 | AccountMethods | 23 | AccountMethods |
24 | } from './account-interface' | 24 | } from './account-interface' |
25 | import LoadApplication = AccountMethods.LoadApplication | ||
26 | import { sendDeleteAccount } from '../../lib/activitypub/send-request' | 25 | import { sendDeleteAccount } from '../../lib/activitypub/send-request' |
26 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | ||
27 | 27 | ||
28 | let Account: Sequelize.Model<AccountInstance, AccountAttributes> | 28 | let Account: Sequelize.Model<AccountInstance, AccountAttributes> |
29 | let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID | 29 | let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID |
@@ -60,14 +60,14 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
60 | type: DataTypes.STRING, | 60 | type: DataTypes.STRING, |
61 | allowNull: false, | 61 | allowNull: false, |
62 | validate: { | 62 | validate: { |
63 | usernameValid: value => { | 63 | nameValid: value => { |
64 | const res = isUserUsernameValid(value) | 64 | const res = isUserUsernameValid(value) |
65 | if (res === false) throw new Error('Username is not valid.') | 65 | if (res === false) throw new Error('Name is not valid.') |
66 | } | 66 | } |
67 | } | 67 | } |
68 | }, | 68 | }, |
69 | url: { | 69 | url: { |
70 | type: DataTypes.STRING, | 70 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
71 | allowNull: false, | 71 | allowNull: false, |
72 | validate: { | 72 | validate: { |
73 | urlValid: value => { | 73 | urlValid: value => { |
@@ -77,7 +77,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
77 | } | 77 | } |
78 | }, | 78 | }, |
79 | publicKey: { | 79 | publicKey: { |
80 | type: DataTypes.STRING, | 80 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.PUBLIC_KEY.max), |
81 | allowNull: false, | 81 | allowNull: false, |
82 | validate: { | 82 | validate: { |
83 | publicKeyValid: value => { | 83 | publicKeyValid: value => { |
@@ -87,7 +87,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
87 | } | 87 | } |
88 | }, | 88 | }, |
89 | privateKey: { | 89 | privateKey: { |
90 | type: DataTypes.STRING, | 90 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.PRIVATE_KEY.max), |
91 | allowNull: false, | 91 | allowNull: false, |
92 | validate: { | 92 | validate: { |
93 | privateKeyValid: value => { | 93 | privateKeyValid: value => { |
@@ -110,14 +110,14 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
110 | type: DataTypes.INTEGER, | 110 | type: DataTypes.INTEGER, |
111 | allowNull: false, | 111 | allowNull: false, |
112 | validate: { | 112 | validate: { |
113 | followersCountValid: value => { | 113 | followingCountValid: value => { |
114 | const res = isAccountFollowingCountValid(value) | 114 | const res = isAccountFollowingCountValid(value) |
115 | if (res === false) throw new Error('Following count is not valid.') | 115 | if (res === false) throw new Error('Following count is not valid.') |
116 | } | 116 | } |
117 | } | 117 | } |
118 | }, | 118 | }, |
119 | inboxUrl: { | 119 | inboxUrl: { |
120 | type: DataTypes.STRING, | 120 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
121 | allowNull: false, | 121 | allowNull: false, |
122 | validate: { | 122 | validate: { |
123 | inboxUrlValid: value => { | 123 | inboxUrlValid: value => { |
@@ -127,7 +127,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
127 | } | 127 | } |
128 | }, | 128 | }, |
129 | outboxUrl: { | 129 | outboxUrl: { |
130 | type: DataTypes.STRING, | 130 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
131 | allowNull: false, | 131 | allowNull: false, |
132 | validate: { | 132 | validate: { |
133 | outboxUrlValid: value => { | 133 | outboxUrlValid: value => { |
@@ -137,7 +137,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
137 | } | 137 | } |
138 | }, | 138 | }, |
139 | sharedInboxUrl: { | 139 | sharedInboxUrl: { |
140 | type: DataTypes.STRING, | 140 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
141 | allowNull: false, | 141 | allowNull: false, |
142 | validate: { | 142 | validate: { |
143 | sharedInboxUrlValid: value => { | 143 | sharedInboxUrlValid: value => { |
@@ -147,7 +147,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
147 | } | 147 | } |
148 | }, | 148 | }, |
149 | followersUrl: { | 149 | followersUrl: { |
150 | type: DataTypes.STRING, | 150 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
151 | allowNull: false, | 151 | allowNull: false, |
152 | validate: { | 152 | validate: { |
153 | followersUrlValid: value => { | 153 | followersUrlValid: value => { |
@@ -157,7 +157,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes | |||
157 | } | 157 | } |
158 | }, | 158 | }, |
159 | followingUrl: { | 159 | followingUrl: { |
160 | type: DataTypes.STRING, | 160 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.URL.max), |
161 | allowNull: false, | 161 | allowNull: false, |
162 | validate: { | 162 | validate: { |
163 | followingUrlValid: value => { | 163 | followingUrlValid: value => { |
@@ -241,7 +241,7 @@ function associate (models) { | |||
241 | 241 | ||
242 | Account.belongsTo(models.Application, { | 242 | Account.belongsTo(models.Application, { |
243 | foreignKey: { | 243 | foreignKey: { |
244 | name: 'userId', | 244 | name: 'applicationId', |
245 | allowNull: true | 245 | allowNull: true |
246 | }, | 246 | }, |
247 | onDelete: 'cascade' | 247 | onDelete: 'cascade' |
@@ -256,7 +256,7 @@ function associate (models) { | |||
256 | hooks: true | 256 | hooks: true |
257 | }) | 257 | }) |
258 | 258 | ||
259 | Account.hasMany(models.AccountFollower, { | 259 | Account.hasMany(models.AccountFollow, { |
260 | foreignKey: { | 260 | foreignKey: { |
261 | name: 'accountId', | 261 | name: 'accountId', |
262 | allowNull: false | 262 | allowNull: false |
@@ -265,7 +265,7 @@ function associate (models) { | |||
265 | onDelete: 'cascade' | 265 | onDelete: 'cascade' |
266 | }) | 266 | }) |
267 | 267 | ||
268 | Account.hasMany(models.AccountFollower, { | 268 | Account.hasMany(models.AccountFollow, { |
269 | foreignKey: { | 269 | foreignKey: { |
270 | name: 'targetAccountId', | 270 | name: 'targetAccountId', |
271 | allowNull: false | 271 | allowNull: false |
@@ -329,7 +329,7 @@ getFollowerSharedInboxUrls = function (this: AccountInstance) { | |||
329 | attributes: [ 'sharedInboxUrl' ], | 329 | attributes: [ 'sharedInboxUrl' ], |
330 | include: [ | 330 | include: [ |
331 | { | 331 | { |
332 | model: Account['sequelize'].models.AccountFollower, | 332 | model: Account['sequelize'].models.AccountFollow, |
333 | where: { | 333 | where: { |
334 | targetAccountId: this.id | 334 | targetAccountId: this.id |
335 | } | 335 | } |
@@ -523,9 +523,9 @@ async function createListAcceptedFollowForApiQuery (type: 'followers' | 'followi | |||
523 | 523 | ||
524 | for (const selection of selections) { | 524 | for (const selection of selections) { |
525 | let query = 'SELECT ' + selection + ' FROM "Account" ' + | 525 | let query = 'SELECT ' + selection + ' FROM "Account" ' + |
526 | 'INNER JOIN "AccountFollower" ON "AccountFollower"."' + firstJoin + '" = "Account"."id" ' + | 526 | 'INNER JOIN "AccountFollow" ON "AccountFollow"."' + firstJoin + '" = "Account"."id" ' + |
527 | 'INNER JOIN "Account" AS "Follows" ON "Followers"."id" = "Follows"."' + secondJoin + '" ' + | 527 | 'INNER JOIN "Account" AS "Follows" ON "Followers"."id" = "Follows"."' + secondJoin + '" ' + |
528 | 'WHERE "Account"."id" = $id AND "AccountFollower"."state" = \'accepted\' ' + | 528 | 'WHERE "Account"."id" = $id AND "AccountFollow"."state" = \'accepted\' ' + |
529 | 'LIMIT ' + start | 529 | 'LIMIT ' + start |
530 | 530 | ||
531 | if (count !== undefined) query += ', ' + count | 531 | if (count !== undefined) query += ', ' + count |
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 7390baf91..8f7c9b013 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -1,23 +1,16 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | 2 | import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' | |
3 | import { getSort, addMethodsToModel } from '../utils' | ||
4 | import { | 3 | import { |
5 | cryptPassword, | ||
6 | comparePassword, | 4 | comparePassword, |
5 | cryptPassword, | ||
6 | isUserDisplayNSFWValid, | ||
7 | isUserPasswordValid, | 7 | isUserPasswordValid, |
8 | isUserRoleValid, | ||
8 | isUserUsernameValid, | 9 | isUserUsernameValid, |
9 | isUserDisplayNSFWValid, | 10 | isUserVideoQuotaValid |
10 | isUserVideoQuotaValid, | ||
11 | isUserRoleValid | ||
12 | } from '../../helpers' | 11 | } from '../../helpers' |
13 | import { UserRight, USER_ROLE_LABELS, hasUserRight } from '../../../shared' | 12 | import { addMethodsToModel, getSort } from '../utils' |
14 | 13 | import { UserAttributes, UserInstance, UserMethods } from './user-interface' | |
15 | import { | ||
16 | UserInstance, | ||
17 | UserAttributes, | ||
18 | |||
19 | UserMethods | ||
20 | } from './user-interface' | ||
21 | 14 | ||
22 | let User: Sequelize.Model<UserInstance, UserAttributes> | 15 | let User: Sequelize.Model<UserInstance, UserAttributes> |
23 | let isPasswordMatch: UserMethods.IsPasswordMatch | 16 | let isPasswordMatch: UserMethods.IsPasswordMatch |
diff --git a/server/models/pod/pod.ts b/server/models/pod/pod.ts index 7c8b49bf8..6d270ad7f 100644 --- a/server/models/pod/pod.ts +++ b/server/models/pod/pod.ts | |||
@@ -63,8 +63,6 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
63 | ) | 63 | ) |
64 | 64 | ||
65 | const classMethods = [ | 65 | const classMethods = [ |
66 | associate, | ||
67 | |||
68 | countAll, | 66 | countAll, |
69 | incrementScores, | 67 | incrementScores, |
70 | list, | 68 | list, |
@@ -98,14 +96,6 @@ toFormattedJSON = function (this: PodInstance) { | |||
98 | 96 | ||
99 | // ------------------------------ Statics ------------------------------ | 97 | // ------------------------------ Statics ------------------------------ |
100 | 98 | ||
101 | function associate (models) { | ||
102 | Pod.belongsToMany(models.Request, { | ||
103 | foreignKey: 'podId', | ||
104 | through: models.RequestToPod, | ||
105 | onDelete: 'cascade' | ||
106 | }) | ||
107 | } | ||
108 | |||
109 | countAll = function () { | 99 | countAll = function () { |
110 | return Pod.count() | 100 | return Pod.count() |
111 | } | 101 | } |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 919ec916d..6d70f2aa2 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -10,6 +10,8 @@ import { | |||
10 | VideoChannelMethods | 10 | VideoChannelMethods |
11 | } from './video-channel-interface' | 11 | } from './video-channel-interface' |
12 | import { sendDeleteVideoChannel } from '../../lib/activitypub/send-request' | 12 | import { sendDeleteVideoChannel } from '../../lib/activitypub/send-request' |
13 | import { isVideoChannelUrlValid } from '../../helpers/custom-validators/video-channels' | ||
14 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | ||
13 | 15 | ||
14 | let VideoChannel: Sequelize.Model<VideoChannelInstance, VideoChannelAttributes> | 16 | let VideoChannel: Sequelize.Model<VideoChannelInstance, VideoChannelAttributes> |
15 | let toFormattedJSON: VideoChannelMethods.ToFormattedJSON | 17 | let toFormattedJSON: VideoChannelMethods.ToFormattedJSON |
@@ -65,10 +67,13 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
65 | defaultValue: false | 67 | defaultValue: false |
66 | }, | 68 | }, |
67 | url: { | 69 | url: { |
68 | type: DataTypes.STRING, | 70 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.URL.max), |
69 | allowNull: false, | 71 | allowNull: false, |
70 | validate: { | 72 | validate: { |
71 | isUrl: true | 73 | urlValid: value => { |
74 | const res = isVideoChannelUrlValid(value) | ||
75 | if (res === false) throw new Error('Video channel URL is not valid.') | ||
76 | } | ||
72 | } | 77 | } |
73 | } | 78 | } |
74 | }, | 79 | }, |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index ca71da375..dd73dd7ca 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -46,6 +46,7 @@ import { TagInstance } from './tag-interface' | |||
46 | import { VideoFileInstance, VideoFileModel } from './video-file-interface' | 46 | import { VideoFileInstance, VideoFileModel } from './video-file-interface' |
47 | import { VideoAttributes, VideoInstance, VideoMethods } from './video-interface' | 47 | import { VideoAttributes, VideoInstance, VideoMethods } from './video-interface' |
48 | import { sendDeleteVideo } from '../../lib/activitypub/send-request' | 48 | import { sendDeleteVideo } from '../../lib/activitypub/send-request' |
49 | import { isVideoUrlValid } from '../../helpers/custom-validators/videos' | ||
49 | 50 | ||
50 | const Buffer = safeBuffer.Buffer | 51 | const Buffer = safeBuffer.Buffer |
51 | 52 | ||
@@ -220,10 +221,13 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da | |||
220 | defaultValue: false | 221 | defaultValue: false |
221 | }, | 222 | }, |
222 | url: { | 223 | url: { |
223 | type: DataTypes.STRING, | 224 | type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max), |
224 | allowNull: false, | 225 | allowNull: false, |
225 | validate: { | 226 | validate: { |
226 | isUrl: true | 227 | urlValid: value => { |
228 | const res = isVideoUrlValid(value) | ||
229 | if (res === false) throw new Error('Video URL is not valid.') | ||
230 | } | ||
227 | } | 231 | } |
228 | } | 232 | } |
229 | }, | 233 | }, |