diff options
Diffstat (limited to 'server/models')
45 files changed, 258 insertions, 178 deletions
diff --git a/server/models/abuse/abuse-message.ts b/server/models/abuse/abuse-message.ts index 7e51b3e07..2c5987e96 100644 --- a/server/models/abuse/abuse-message.ts +++ b/server/models/abuse/abuse-message.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' | 2 | import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' |
3 | import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models' | 3 | import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { AbuseMessage } from '@shared/models' | 5 | import { AbuseMessage } from '@shared/models' |
5 | import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' | 6 | import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' |
6 | import { getSort, throwIfNotValid } from '../utils' | 7 | import { getSort, throwIfNotValid } from '../utils' |
@@ -17,7 +18,7 @@ import { AbuseModel } from './abuse' | |||
17 | } | 18 | } |
18 | ] | 19 | ] |
19 | }) | 20 | }) |
20 | export class AbuseMessageModel extends Model { | 21 | export class AbuseMessageModel extends Model<Partial<AttributesOnly<AbuseMessageModel>>> { |
21 | 22 | ||
22 | @AllowNull(false) | 23 | @AllowNull(false) |
23 | @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message')) | 24 | @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message')) |
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 262f364f1..3518f5c02 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -16,7 +16,7 @@ import { | |||
16 | UpdatedAt | 16 | UpdatedAt |
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' | 18 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' |
19 | import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' | 19 | import { abusePredefinedReasonsMap, AttributesOnly } from '@shared/core-utils' |
20 | import { | 20 | import { |
21 | AbuseFilter, | 21 | AbuseFilter, |
22 | AbuseObject, | 22 | AbuseObject, |
@@ -187,7 +187,7 @@ export enum ScopeNames { | |||
187 | } | 187 | } |
188 | ] | 188 | ] |
189 | }) | 189 | }) |
190 | export class AbuseModel extends Model { | 190 | export class AbuseModel extends Model<Partial<AttributesOnly<AbuseModel>>> { |
191 | 191 | ||
192 | @AllowNull(false) | 192 | @AllowNull(false) |
193 | @Default(null) | 193 | @Default(null) |
diff --git a/server/models/abuse/video-abuse.ts b/server/models/abuse/video-abuse.ts index 90aa0695e..95bff50d0 100644 --- a/server/models/abuse/video-abuse.ts +++ b/server/models/abuse/video-abuse.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoDetails } from '@shared/models' | 3 | import { VideoDetails } from '@shared/models' |
3 | import { VideoModel } from '../video/video' | 4 | import { VideoModel } from '../video/video' |
4 | import { AbuseModel } from './abuse' | 5 | import { AbuseModel } from './abuse' |
@@ -14,7 +15,7 @@ import { AbuseModel } from './abuse' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class VideoAbuseModel extends Model { | 18 | export class VideoAbuseModel extends Model<Partial<AttributesOnly<VideoAbuseModel>>> { |
18 | 19 | ||
19 | @CreatedAt | 20 | @CreatedAt |
20 | createdAt: Date | 21 | createdAt: Date |
diff --git a/server/models/abuse/video-comment-abuse.ts b/server/models/abuse/video-comment-abuse.ts index d3fce76a5..32cb2ca64 100644 --- a/server/models/abuse/video-comment-abuse.ts +++ b/server/models/abuse/video-comment-abuse.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoCommentModel } from '../video/video-comment' | 3 | import { VideoCommentModel } from '../video/video-comment' |
3 | import { AbuseModel } from './abuse' | 4 | import { AbuseModel } from './abuse' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { AbuseModel } from './abuse' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoCommentAbuseModel extends Model { | 17 | export class VideoCommentAbuseModel extends Model<Partial<AttributesOnly<VideoCommentAbuseModel>>> { |
17 | 18 | ||
18 | @CreatedAt | 19 | @CreatedAt |
19 | createdAt: Date | 20 | createdAt: Date |
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts index fe9168ab8..b2375b006 100644 --- a/server/models/account/account-blocklist.ts +++ b/server/models/account/account-blocklist.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { Op } from 'sequelize' | 1 | import { Op } from 'sequelize' |
2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' | 3 | import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { AccountBlock } from '../../../shared/models' | 5 | import { AccountBlock } from '../../../shared/models' |
5 | import { ActorModel } from '../activitypub/actor' | 6 | import { ActorModel } from '../actor/actor' |
6 | import { ServerModel } from '../server/server' | 7 | import { ServerModel } from '../server/server' |
7 | import { getSort, searchAttribute } from '../utils' | 8 | import { getSort, searchAttribute } from '../utils' |
8 | import { AccountModel } from './account' | 9 | import { AccountModel } from './account' |
@@ -40,7 +41,7 @@ enum ScopeNames { | |||
40 | } | 41 | } |
41 | ] | 42 | ] |
42 | }) | 43 | }) |
43 | export class AccountBlocklistModel extends Model { | 44 | export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountBlocklistModel>>> { |
44 | 45 | ||
45 | @CreatedAt | 46 | @CreatedAt |
46 | createdAt: Date | 47 | createdAt: Date |
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts index 801f76bba..ee6dbc6da 100644 --- a/server/models/account/account-video-rate.ts +++ b/server/models/account/account-video-rate.ts | |||
@@ -7,11 +7,12 @@ import { | |||
7 | MAccountVideoRateAccountVideo, | 7 | MAccountVideoRateAccountVideo, |
8 | MAccountVideoRateFormattable | 8 | MAccountVideoRateFormattable |
9 | } from '@server/types/models/video/video-rate' | 9 | } from '@server/types/models/video/video-rate' |
10 | import { AttributesOnly } from '@shared/core-utils' | ||
10 | import { AccountVideoRate } from '../../../shared' | 11 | import { AccountVideoRate } from '../../../shared' |
11 | import { VideoRateType } from '../../../shared/models/videos' | 12 | import { VideoRateType } from '../../../shared/models/videos' |
12 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 13 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
13 | import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants' | 14 | import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants' |
14 | import { ActorModel } from '../activitypub/actor' | 15 | import { ActorModel } from '../actor/actor' |
15 | import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils' | 16 | import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils' |
16 | import { VideoModel } from '../video/video' | 17 | import { VideoModel } from '../video/video' |
17 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' | 18 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' |
@@ -42,7 +43,7 @@ import { AccountModel } from './account' | |||
42 | } | 43 | } |
43 | ] | 44 | ] |
44 | }) | 45 | }) |
45 | export class AccountVideoRateModel extends Model { | 46 | export class AccountVideoRateModel extends Model<Partial<AttributesOnly<AccountVideoRateModel>>> { |
46 | 47 | ||
47 | @AllowNull(false) | 48 | @AllowNull(false) |
48 | @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES))) | 49 | @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES))) |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 312451abe..665ecd595 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -17,10 +17,11 @@ import { | |||
17 | UpdatedAt | 17 | UpdatedAt |
18 | } from 'sequelize-typescript' | 18 | } from 'sequelize-typescript' |
19 | import { ModelCache } from '@server/models/model-cache' | 19 | import { ModelCache } from '@server/models/model-cache' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { Account, AccountSummary } from '../../../shared/models/actors' | 21 | import { Account, AccountSummary } from '../../../shared/models/actors' |
21 | import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' | 22 | import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' |
22 | import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' | 23 | import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' |
23 | import { sendDeleteActor } from '../../lib/activitypub/send' | 24 | import { sendDeleteActor } from '../../lib/activitypub/send/send-delete' |
24 | import { | 25 | import { |
25 | MAccount, | 26 | MAccount, |
26 | MAccountActor, | 27 | MAccountActor, |
@@ -30,19 +31,19 @@ import { | |||
30 | MAccountSummaryFormattable, | 31 | MAccountSummaryFormattable, |
31 | MChannelActor | 32 | MChannelActor |
32 | } from '../../types/models' | 33 | } from '../../types/models' |
33 | import { ActorModel } from '../activitypub/actor' | 34 | import { ActorModel } from '../actor/actor' |
34 | import { ActorFollowModel } from '../activitypub/actor-follow' | 35 | import { ActorFollowModel } from '../actor/actor-follow' |
36 | import { ActorImageModel } from '../actor/actor-image' | ||
35 | import { ApplicationModel } from '../application/application' | 37 | import { ApplicationModel } from '../application/application' |
36 | import { ActorImageModel } from './actor-image' | ||
37 | import { ServerModel } from '../server/server' | 38 | import { ServerModel } from '../server/server' |
38 | import { ServerBlocklistModel } from '../server/server-blocklist' | 39 | import { ServerBlocklistModel } from '../server/server-blocklist' |
40 | import { UserModel } from '../user/user' | ||
39 | import { getSort, throwIfNotValid } from '../utils' | 41 | import { getSort, throwIfNotValid } from '../utils' |
40 | import { VideoModel } from '../video/video' | 42 | import { VideoModel } from '../video/video' |
41 | import { VideoChannelModel } from '../video/video-channel' | 43 | import { VideoChannelModel } from '../video/video-channel' |
42 | import { VideoCommentModel } from '../video/video-comment' | 44 | import { VideoCommentModel } from '../video/video-comment' |
43 | import { VideoPlaylistModel } from '../video/video-playlist' | 45 | import { VideoPlaylistModel } from '../video/video-playlist' |
44 | import { AccountBlocklistModel } from './account-blocklist' | 46 | import { AccountBlocklistModel } from './account-blocklist' |
45 | import { UserModel } from './user' | ||
46 | 47 | ||
47 | export enum ScopeNames { | 48 | export enum ScopeNames { |
48 | SUMMARY = 'SUMMARY' | 49 | SUMMARY = 'SUMMARY' |
@@ -141,7 +142,7 @@ export type SummaryOptions = { | |||
141 | } | 142 | } |
142 | ] | 143 | ] |
143 | }) | 144 | }) |
144 | export class AccountModel extends Model { | 145 | export class AccountModel extends Model<Partial<AttributesOnly<AccountModel>>> { |
145 | 146 | ||
146 | @AllowNull(false) | 147 | @AllowNull(false) |
147 | @Column | 148 | @Column |
@@ -411,7 +412,6 @@ export class AccountModel extends Model { | |||
411 | id: this.id, | 412 | id: this.id, |
412 | displayName: this.getDisplayName(), | 413 | displayName: this.getDisplayName(), |
413 | description: this.description, | 414 | description: this.description, |
414 | createdAt: this.createdAt, | ||
415 | updatedAt: this.updatedAt, | 415 | updatedAt: this.updatedAt, |
416 | userId: this.userId ? this.userId : undefined | 416 | userId: this.userId ? this.userId : undefined |
417 | } | 417 | } |
diff --git a/server/models/account/actor-custom-page.ts b/server/models/account/actor-custom-page.ts new file mode 100644 index 000000000..893023181 --- /dev/null +++ b/server/models/account/actor-custom-page.ts | |||
@@ -0,0 +1,69 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
2 | import { CustomPage } from '@shared/models' | ||
3 | import { ActorModel } from '../actor/actor' | ||
4 | import { getServerActor } from '../application/application' | ||
5 | |||
6 | @Table({ | ||
7 | tableName: 'actorCustomPage', | ||
8 | indexes: [ | ||
9 | { | ||
10 | fields: [ 'actorId', 'type' ], | ||
11 | unique: true | ||
12 | } | ||
13 | ] | ||
14 | }) | ||
15 | export class ActorCustomPageModel extends Model { | ||
16 | |||
17 | @AllowNull(true) | ||
18 | @Column(DataType.TEXT) | ||
19 | content: string | ||
20 | |||
21 | @AllowNull(false) | ||
22 | @Column | ||
23 | type: 'homepage' | ||
24 | |||
25 | @CreatedAt | ||
26 | createdAt: Date | ||
27 | |||
28 | @UpdatedAt | ||
29 | updatedAt: Date | ||
30 | |||
31 | @ForeignKey(() => ActorModel) | ||
32 | @Column | ||
33 | actorId: number | ||
34 | |||
35 | @BelongsTo(() => ActorModel, { | ||
36 | foreignKey: { | ||
37 | name: 'actorId', | ||
38 | allowNull: false | ||
39 | }, | ||
40 | onDelete: 'cascade' | ||
41 | }) | ||
42 | Actor: ActorModel | ||
43 | |||
44 | static async updateInstanceHomepage (content: string) { | ||
45 | const serverActor = await getServerActor() | ||
46 | |||
47 | return ActorCustomPageModel.upsert({ | ||
48 | content, | ||
49 | actorId: serverActor.id, | ||
50 | type: 'homepage' | ||
51 | }) | ||
52 | } | ||
53 | |||
54 | static async loadInstanceHomepage () { | ||
55 | const serverActor = await getServerActor() | ||
56 | |||
57 | return ActorCustomPageModel.findOne({ | ||
58 | where: { | ||
59 | actorId: serverActor.id | ||
60 | } | ||
61 | }) | ||
62 | } | ||
63 | |||
64 | toFormattedJSON (): CustomPage { | ||
65 | return { | ||
66 | content: this.content | ||
67 | } | ||
68 | } | ||
69 | } | ||
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/actor/actor-follow.ts index 4c5f37620..3a09e51d6 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/actor/actor-follow.ts | |||
@@ -28,6 +28,7 @@ import { | |||
28 | MActorFollowFormattable, | 28 | MActorFollowFormattable, |
29 | MActorFollowSubscriptions | 29 | MActorFollowSubscriptions |
30 | } from '@server/types/models' | 30 | } from '@server/types/models' |
31 | import { AttributesOnly } from '@shared/core-utils' | ||
31 | import { ActivityPubActorType } from '@shared/models' | 32 | import { ActivityPubActorType } from '@shared/models' |
32 | import { FollowState } from '../../../shared/models/actors' | 33 | import { FollowState } from '../../../shared/models/actors' |
33 | import { ActorFollow } from '../../../shared/models/actors/follow.model' | 34 | import { ActorFollow } from '../../../shared/models/actors/follow.model' |
@@ -61,7 +62,7 @@ import { ActorModel, unusedActorAttributesForAPI } from './actor' | |||
61 | } | 62 | } |
62 | ] | 63 | ] |
63 | }) | 64 | }) |
64 | export class ActorFollowModel extends Model { | 65 | export class ActorFollowModel extends Model<Partial<AttributesOnly<ActorFollowModel>>> { |
65 | 66 | ||
66 | @AllowNull(false) | 67 | @AllowNull(false) |
67 | @Column(DataType.ENUM(...values(FOLLOW_STATES))) | 68 | @Column(DataType.ENUM(...values(FOLLOW_STATES))) |
@@ -619,7 +620,7 @@ export class ActorFollowModel extends Model { | |||
619 | if (serverIds.length === 0) return | 620 | if (serverIds.length === 0) return |
620 | 621 | ||
621 | const me = await getServerActor() | 622 | const me = await getServerActor() |
622 | const serverIdsString = createSafeIn(ActorFollowModel, serverIds) | 623 | const serverIdsString = createSafeIn(ActorFollowModel.sequelize, serverIds) |
623 | 624 | ||
624 | const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` + | 625 | const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` + |
625 | 'WHERE id IN (' + | 626 | 'WHERE id IN (' + |
diff --git a/server/models/account/actor-image.ts b/server/models/actor/actor-image.ts index ae05b4969..a35f9edb0 100644 --- a/server/models/account/actor-image.ts +++ b/server/models/actor/actor-image.ts | |||
@@ -2,6 +2,7 @@ import { remove } from 'fs-extra' | |||
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
4 | import { MActorImageFormattable } from '@server/types/models' | 4 | import { MActorImageFormattable } from '@server/types/models' |
5 | import { AttributesOnly } from '@shared/core-utils' | ||
5 | import { ActorImageType } from '@shared/models' | 6 | import { ActorImageType } from '@shared/models' |
6 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 7 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
7 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 8 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
@@ -19,7 +20,7 @@ import { throwIfNotValid } from '../utils' | |||
19 | } | 20 | } |
20 | ] | 21 | ] |
21 | }) | 22 | }) |
22 | export class ActorImageModel extends Model { | 23 | export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageModel>>> { |
23 | 24 | ||
24 | @AllowNull(false) | 25 | @AllowNull(false) |
25 | @Column | 26 | @Column |
diff --git a/server/models/activitypub/actor.ts b/server/models/actor/actor.ts index 19f3f7e04..65c53f8f8 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/actor/actor.ts | |||
@@ -18,6 +18,7 @@ import { | |||
18 | UpdatedAt | 18 | UpdatedAt |
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { ModelCache } from '@server/models/model-cache' | 20 | import { ModelCache } from '@server/models/model-cache' |
21 | import { AttributesOnly } from '@shared/core-utils' | ||
21 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' | 22 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' |
22 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 23 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
23 | import { activityPubContextify } from '../../helpers/activitypub' | 24 | import { activityPubContextify } from '../../helpers/activitypub' |
@@ -51,12 +52,12 @@ import { | |||
51 | MActorWithInboxes | 52 | MActorWithInboxes |
52 | } from '../../types/models' | 53 | } from '../../types/models' |
53 | import { AccountModel } from '../account/account' | 54 | import { AccountModel } from '../account/account' |
54 | import { ActorImageModel } from '../account/actor-image' | ||
55 | import { ServerModel } from '../server/server' | 55 | import { ServerModel } from '../server/server' |
56 | import { isOutdated, throwIfNotValid } from '../utils' | 56 | import { isOutdated, throwIfNotValid } from '../utils' |
57 | import { VideoModel } from '../video/video' | 57 | import { VideoModel } from '../video/video' |
58 | import { VideoChannelModel } from '../video/video-channel' | 58 | import { VideoChannelModel } from '../video/video-channel' |
59 | import { ActorFollowModel } from './actor-follow' | 59 | import { ActorFollowModel } from './actor-follow' |
60 | import { ActorImageModel } from './actor-image' | ||
60 | 61 | ||
61 | enum ScopeNames { | 62 | enum ScopeNames { |
62 | FULL = 'FULL' | 63 | FULL = 'FULL' |
@@ -69,9 +70,7 @@ export const unusedActorAttributesForAPI = [ | |||
69 | 'outboxUrl', | 70 | 'outboxUrl', |
70 | 'sharedInboxUrl', | 71 | 'sharedInboxUrl', |
71 | 'followersUrl', | 72 | 'followersUrl', |
72 | 'followingUrl', | 73 | 'followingUrl' |
73 | 'createdAt', | ||
74 | 'updatedAt' | ||
75 | ] | 74 | ] |
76 | 75 | ||
77 | @DefaultScope(() => ({ | 76 | @DefaultScope(() => ({ |
@@ -161,7 +160,7 @@ export const unusedActorAttributesForAPI = [ | |||
161 | } | 160 | } |
162 | ] | 161 | ] |
163 | }) | 162 | }) |
164 | export class ActorModel extends Model { | 163 | export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> { |
165 | 164 | ||
166 | @AllowNull(false) | 165 | @AllowNull(false) |
167 | @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) | 166 | @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) |
@@ -222,6 +221,10 @@ export class ActorModel extends Model { | |||
222 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) | 221 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) |
223 | followingUrl: string | 222 | followingUrl: string |
224 | 223 | ||
224 | @AllowNull(true) | ||
225 | @Column | ||
226 | remoteCreatedAt: Date | ||
227 | |||
225 | @CreatedAt | 228 | @CreatedAt |
226 | createdAt: Date | 229 | createdAt: Date |
227 | 230 | ||
@@ -555,8 +558,7 @@ export class ActorModel extends Model { | |||
555 | followingCount: this.followingCount, | 558 | followingCount: this.followingCount, |
556 | followersCount: this.followersCount, | 559 | followersCount: this.followersCount, |
557 | banner, | 560 | banner, |
558 | createdAt: this.createdAt, | 561 | createdAt: this.getCreatedAt() |
559 | updatedAt: this.updatedAt | ||
560 | }) | 562 | }) |
561 | } | 563 | } |
562 | 564 | ||
@@ -608,6 +610,7 @@ export class ActorModel extends Model { | |||
608 | owner: this.url, | 610 | owner: this.url, |
609 | publicKeyPem: this.publicKey | 611 | publicKeyPem: this.publicKey |
610 | }, | 612 | }, |
613 | published: this.getCreatedAt().toISOString(), | ||
611 | icon, | 614 | icon, |
612 | image | 615 | image |
613 | } | 616 | } |
@@ -690,4 +693,8 @@ export class ActorModel extends Model { | |||
690 | 693 | ||
691 | return isOutdated(this, ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL) | 694 | return isOutdated(this, ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL) |
692 | } | 695 | } |
696 | |||
697 | getCreatedAt (this: MActorAPChannel | MActorAPAccount | MActorFormattable) { | ||
698 | return this.remoteCreatedAt || this.createdAt | ||
699 | } | ||
693 | } | 700 | } |
diff --git a/server/models/application/application.ts b/server/models/application/application.ts index 21f8b1cbc..5531d134a 100644 --- a/server/models/application/application.ts +++ b/server/models/application/application.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import * as memoizee from 'memoizee' | ||
1 | import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript' | 2 | import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { AccountModel } from '../account/account' | 4 | import { AccountModel } from '../account/account' |
3 | import * as memoizee from 'memoizee' | ||
4 | 5 | ||
5 | export const getServerActor = memoizee(async function () { | 6 | export const getServerActor = memoizee(async function () { |
6 | const application = await ApplicationModel.load() | 7 | const application = await ApplicationModel.load() |
@@ -24,7 +25,7 @@ export const getServerActor = memoizee(async function () { | |||
24 | tableName: 'application', | 25 | tableName: 'application', |
25 | timestamps: false | 26 | timestamps: false |
26 | }) | 27 | }) |
27 | export class ApplicationModel extends Model { | 28 | export class ApplicationModel extends Model<Partial<AttributesOnly<ApplicationModel>>> { |
28 | 29 | ||
29 | @AllowNull(false) | 30 | @AllowNull(false) |
30 | @Default(0) | 31 | @Default(0) |
diff --git a/server/models/oauth/oauth-client.ts b/server/models/oauth/oauth-client.ts index 8dbc1c2f5..890954bdb 100644 --- a/server/models/oauth/oauth-client.ts +++ b/server/models/oauth/oauth-client.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { OAuthTokenModel } from './oauth-token' | 3 | import { OAuthTokenModel } from './oauth-token' |
3 | 4 | ||
4 | @Table({ | 5 | @Table({ |
@@ -14,7 +15,7 @@ import { OAuthTokenModel } from './oauth-token' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class OAuthClientModel extends Model { | 18 | export class OAuthClientModel extends Model<Partial<AttributesOnly<OAuthClientModel>>> { |
18 | 19 | ||
19 | @AllowNull(false) | 20 | @AllowNull(false) |
20 | @Column | 21 | @Column |
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts index 27e643aa7..af4b0ec42 100644 --- a/server/models/oauth/oauth-token.ts +++ b/server/models/oauth/oauth-token.ts | |||
@@ -15,10 +15,11 @@ import { | |||
15 | import { TokensCache } from '@server/lib/auth/tokens-cache' | 15 | import { TokensCache } from '@server/lib/auth/tokens-cache' |
16 | import { MUserAccountId } from '@server/types/models' | 16 | import { MUserAccountId } from '@server/types/models' |
17 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' | 17 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' |
18 | import { AttributesOnly } from '@shared/core-utils' | ||
18 | import { logger } from '../../helpers/logger' | 19 | import { logger } from '../../helpers/logger' |
19 | import { AccountModel } from '../account/account' | 20 | import { AccountModel } from '../account/account' |
20 | import { UserModel } from '../account/user' | 21 | import { ActorModel } from '../actor/actor' |
21 | import { ActorModel } from '../activitypub/actor' | 22 | import { UserModel } from '../user/user' |
22 | import { OAuthClientModel } from './oauth-client' | 23 | import { OAuthClientModel } from './oauth-client' |
23 | 24 | ||
24 | export type OAuthTokenInfo = { | 25 | export type OAuthTokenInfo = { |
@@ -78,7 +79,7 @@ enum ScopeNames { | |||
78 | } | 79 | } |
79 | ] | 80 | ] |
80 | }) | 81 | }) |
81 | export class OAuthTokenModel extends Model { | 82 | export class OAuthTokenModel extends Model<Partial<AttributesOnly<OAuthTokenModel>>> { |
82 | 83 | ||
83 | @AllowNull(false) | 84 | @AllowNull(false) |
84 | @Column | 85 | @Column |
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts index 53ebadeaf..ca56a57dc 100644 --- a/server/models/redundancy/video-redundancy.ts +++ b/server/models/redundancy/video-redundancy.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { sample } from 'lodash' | 1 | import { sample } from 'lodash' |
2 | import { FindOptions, literal, Op, QueryTypes, Transaction, WhereOptions } from 'sequelize' | 2 | import { literal, Op, QueryTypes, Transaction, WhereOptions } from 'sequelize' |
3 | import { | 3 | import { |
4 | AllowNull, | 4 | AllowNull, |
5 | BeforeDestroy, | 5 | BeforeDestroy, |
@@ -16,6 +16,7 @@ import { | |||
16 | } from 'sequelize-typescript' | 16 | } from 'sequelize-typescript' |
17 | import { getServerActor } from '@server/models/application/application' | 17 | import { getServerActor } from '@server/models/application/application' |
18 | import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' | 18 | import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' |
19 | import { AttributesOnly } from '@shared/core-utils' | ||
19 | import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model' | 20 | import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model' |
20 | import { | 21 | import { |
21 | FileRedundancyInformation, | 22 | FileRedundancyInformation, |
@@ -29,7 +30,7 @@ import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validato | |||
29 | import { logger } from '../../helpers/logger' | 30 | import { logger } from '../../helpers/logger' |
30 | import { CONFIG } from '../../initializers/config' | 31 | import { CONFIG } from '../../initializers/config' |
31 | import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants' | 32 | import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants' |
32 | import { ActorModel } from '../activitypub/actor' | 33 | import { ActorModel } from '../actor/actor' |
33 | import { ServerModel } from '../server/server' | 34 | import { ServerModel } from '../server/server' |
34 | import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils' | 35 | import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils' |
35 | import { ScheduleVideoUpdateModel } from '../video/schedule-video-update' | 36 | import { ScheduleVideoUpdateModel } from '../video/schedule-video-update' |
@@ -84,7 +85,7 @@ export enum ScopeNames { | |||
84 | } | 85 | } |
85 | ] | 86 | ] |
86 | }) | 87 | }) |
87 | export class VideoRedundancyModel extends Model { | 88 | export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedundancyModel>>> { |
88 | 89 | ||
89 | @CreatedAt | 90 | @CreatedAt |
90 | createdAt: Date | 91 | createdAt: Date |
@@ -407,50 +408,6 @@ export class VideoRedundancyModel extends Model { | |||
407 | return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findOne(query) | 408 | return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findOne(query) |
408 | } | 409 | } |
409 | 410 | ||
410 | static async getTotalDuplicated (strategy: VideoRedundancyStrategy) { | ||
411 | const actor = await getServerActor() | ||
412 | const redundancyInclude = { | ||
413 | attributes: [], | ||
414 | model: VideoRedundancyModel, | ||
415 | required: true, | ||
416 | where: { | ||
417 | actorId: actor.id, | ||
418 | strategy | ||
419 | } | ||
420 | } | ||
421 | |||
422 | const queryFiles: FindOptions = { | ||
423 | include: [ redundancyInclude ] | ||
424 | } | ||
425 | |||
426 | const queryStreamingPlaylists: FindOptions = { | ||
427 | include: [ | ||
428 | { | ||
429 | attributes: [], | ||
430 | model: VideoModel.unscoped(), | ||
431 | required: true, | ||
432 | include: [ | ||
433 | { | ||
434 | required: true, | ||
435 | attributes: [], | ||
436 | model: VideoStreamingPlaylistModel.unscoped(), | ||
437 | include: [ | ||
438 | redundancyInclude | ||
439 | ] | ||
440 | } | ||
441 | ] | ||
442 | } | ||
443 | ] | ||
444 | } | ||
445 | |||
446 | return Promise.all([ | ||
447 | VideoFileModel.aggregate('size', 'SUM', queryFiles), | ||
448 | VideoFileModel.aggregate('size', 'SUM', queryStreamingPlaylists) | ||
449 | ]).then(([ r1, r2 ]) => { | ||
450 | return parseAggregateResult(r1) + parseAggregateResult(r2) | ||
451 | }) | ||
452 | } | ||
453 | |||
454 | static async listLocalExpired () { | 411 | static async listLocalExpired () { |
455 | const actor = await getServerActor() | 412 | const actor = await getServerActor() |
456 | 413 | ||
diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts index 82387af6a..a8de64dd4 100644 --- a/server/models/server/plugin.ts +++ b/server/models/server/plugin.ts | |||
@@ -1,9 +1,8 @@ | |||
1 | import { FindAndCountOptions, json, QueryTypes } from 'sequelize' | 1 | import { FindAndCountOptions, json, QueryTypes } from 'sequelize' |
2 | import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MPlugin, MPluginFormattable } from '@server/types/models' | 3 | import { MPlugin, MPluginFormattable } from '@server/types/models' |
4 | import { PeerTubePlugin } from '../../../shared/models/plugins/peertube-plugin.model' | 4 | import { AttributesOnly } from '@shared/core-utils' |
5 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | 5 | import { PeerTubePlugin, PluginType, RegisterServerSettingOptions } from '../../../shared/models' |
6 | import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' | ||
7 | import { | 6 | import { |
8 | isPluginDescriptionValid, | 7 | isPluginDescriptionValid, |
9 | isPluginHomepage, | 8 | isPluginHomepage, |
@@ -28,7 +27,7 @@ import { getSort, throwIfNotValid } from '../utils' | |||
28 | } | 27 | } |
29 | ] | 28 | ] |
30 | }) | 29 | }) |
31 | export class PluginModel extends Model { | 30 | export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> { |
32 | 31 | ||
33 | @AllowNull(false) | 32 | @AllowNull(false) |
34 | @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name')) | 33 | @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name')) |
@@ -284,7 +283,7 @@ export class PluginModel extends Model { | |||
284 | for (const r of registeredSettings) { | 283 | for (const r of registeredSettings) { |
285 | if (r.private !== false) continue | 284 | if (r.private !== false) continue |
286 | 285 | ||
287 | result[r.name] = settings[r.name] || r.default || null | 286 | result[r.name] = settings[r.name] ?? r.default ?? null |
288 | } | 287 | } |
289 | 288 | ||
290 | return result | 289 | return result |
diff --git a/server/models/server/server-blocklist.ts b/server/models/server/server-blocklist.ts index 4dc236537..b3579d589 100644 --- a/server/models/server/server-blocklist.ts +++ b/server/models/server/server-blocklist.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Op } from 'sequelize' | 1 | import { Op } from 'sequelize' |
2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' | 3 | import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { ServerBlock } from '@shared/models' | 5 | import { ServerBlock } from '@shared/models' |
5 | import { AccountModel } from '../account/account' | 6 | import { AccountModel } from '../account/account' |
6 | import { getSort, searchAttribute } from '../utils' | 7 | import { getSort, searchAttribute } from '../utils' |
@@ -42,7 +43,7 @@ enum ScopeNames { | |||
42 | } | 43 | } |
43 | ] | 44 | ] |
44 | }) | 45 | }) |
45 | export class ServerBlocklistModel extends Model { | 46 | export class ServerBlocklistModel extends Model<Partial<AttributesOnly<ServerBlocklistModel>>> { |
46 | 47 | ||
47 | @CreatedAt | 48 | @CreatedAt |
48 | createdAt: Date | 49 | createdAt: Date |
diff --git a/server/models/server/server.ts b/server/models/server/server.ts index 0e58beeaf..25d9924fb 100644 --- a/server/models/server/server.ts +++ b/server/models/server/server.ts | |||
@@ -1,7 +1,8 @@ | |||
1 | import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { MServer, MServerFormattable } from '@server/types/models/server' | 2 | import { MServer, MServerFormattable } from '@server/types/models/server' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { isHostValid } from '../../helpers/custom-validators/servers' | 4 | import { isHostValid } from '../../helpers/custom-validators/servers' |
4 | import { ActorModel } from '../activitypub/actor' | 5 | import { ActorModel } from '../actor/actor' |
5 | import { throwIfNotValid } from '../utils' | 6 | import { throwIfNotValid } from '../utils' |
6 | import { ServerBlocklistModel } from './server-blocklist' | 7 | import { ServerBlocklistModel } from './server-blocklist' |
7 | 8 | ||
@@ -14,7 +15,7 @@ import { ServerBlocklistModel } from './server-blocklist' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class ServerModel extends Model { | 18 | export class ServerModel extends Model<Partial<AttributesOnly<ServerModel>>> { |
18 | 19 | ||
19 | @AllowNull(false) | 20 | @AllowNull(false) |
20 | @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) | 21 | @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) |
diff --git a/server/models/server/tracker.ts b/server/models/server/tracker.ts index 97520f92d..c09fdd64b 100644 --- a/server/models/server/tracker.ts +++ b/server/models/server/tracker.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { Transaction } from 'sequelize/types' | 2 | import { Transaction } from 'sequelize/types' |
3 | import { MTracker } from '@server/types/models/server/tracker' | 3 | import { MTracker } from '@server/types/models/server/tracker' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoModel } from '../video/video' | 5 | import { VideoModel } from '../video/video' |
5 | import { VideoTrackerModel } from './video-tracker' | 6 | import { VideoTrackerModel } from './video-tracker' |
6 | 7 | ||
@@ -13,7 +14,7 @@ import { VideoTrackerModel } from './video-tracker' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class TrackerModel extends Model { | 17 | export class TrackerModel extends Model<Partial<AttributesOnly<TrackerModel>>> { |
17 | 18 | ||
18 | @AllowNull(false) | 19 | @AllowNull(false) |
19 | @Column | 20 | @Column |
diff --git a/server/models/server/video-tracker.ts b/server/models/server/video-tracker.ts index 367bf0117..c49fbd1c6 100644 --- a/server/models/server/video-tracker.ts +++ b/server/models/server/video-tracker.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from '../video/video' | 3 | import { VideoModel } from '../video/video' |
3 | import { TrackerModel } from './tracker' | 4 | import { TrackerModel } from './tracker' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { TrackerModel } from './tracker' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoTrackerModel extends Model { | 17 | export class VideoTrackerModel extends Model<Partial<AttributesOnly<VideoTrackerModel>>> { |
17 | @CreatedAt | 18 | @CreatedAt |
18 | createdAt: Date | 19 | createdAt: Date |
19 | 20 | ||
diff --git a/server/models/account/user-notification-setting.ts b/server/models/user/user-notification-setting.ts index 138051528..bee7d7851 100644 --- a/server/models/account/user-notification-setting.ts +++ b/server/models/user/user-notification-setting.ts | |||
@@ -14,6 +14,7 @@ import { | |||
14 | } from 'sequelize-typescript' | 14 | } from 'sequelize-typescript' |
15 | import { TokensCache } from '@server/lib/auth/tokens-cache' | 15 | import { TokensCache } from '@server/lib/auth/tokens-cache' |
16 | import { MNotificationSettingFormattable } from '@server/types/models' | 16 | import { MNotificationSettingFormattable } from '@server/types/models' |
17 | import { AttributesOnly } from '@shared/core-utils' | ||
17 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' | 18 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' |
18 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' | 19 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' |
19 | import { throwIfNotValid } from '../utils' | 20 | import { throwIfNotValid } from '../utils' |
@@ -28,7 +29,7 @@ import { UserModel } from './user' | |||
28 | } | 29 | } |
29 | ] | 30 | ] |
30 | }) | 31 | }) |
31 | export class UserNotificationSettingModel extends Model { | 32 | export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<UserNotificationSettingModel>>> { |
32 | 33 | ||
33 | @AllowNull(false) | 34 | @AllowNull(false) |
34 | @Default(null) | 35 | @Default(null) |
diff --git a/server/models/account/user-notification.ts b/server/models/user/user-notification.ts index 805095002..a7f84e9ca 100644 --- a/server/models/account/user-notification.ts +++ b/server/models/user/user-notification.ts | |||
@@ -1,14 +1,17 @@ | |||
1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' | 1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' | 3 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { UserNotification, UserNotificationType } from '../../../shared' | 5 | import { UserNotification, UserNotificationType } from '../../../shared' |
5 | import { isBooleanValid } from '../../helpers/custom-validators/misc' | 6 | import { isBooleanValid } from '../../helpers/custom-validators/misc' |
6 | import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' | 7 | import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' |
7 | import { AbuseModel } from '../abuse/abuse' | 8 | import { AbuseModel } from '../abuse/abuse' |
8 | import { VideoAbuseModel } from '../abuse/video-abuse' | 9 | import { VideoAbuseModel } from '../abuse/video-abuse' |
9 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' | 10 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' |
10 | import { ActorModel } from '../activitypub/actor' | 11 | import { AccountModel } from '../account/account' |
11 | import { ActorFollowModel } from '../activitypub/actor-follow' | 12 | import { ActorModel } from '../actor/actor' |
13 | import { ActorFollowModel } from '../actor/actor-follow' | ||
14 | import { ActorImageModel } from '../actor/actor-image' | ||
12 | import { ApplicationModel } from '../application/application' | 15 | import { ApplicationModel } from '../application/application' |
13 | import { PluginModel } from '../server/plugin' | 16 | import { PluginModel } from '../server/plugin' |
14 | import { ServerModel } from '../server/server' | 17 | import { ServerModel } from '../server/server' |
@@ -18,8 +21,6 @@ import { VideoBlacklistModel } from '../video/video-blacklist' | |||
18 | import { VideoChannelModel } from '../video/video-channel' | 21 | import { VideoChannelModel } from '../video/video-channel' |
19 | import { VideoCommentModel } from '../video/video-comment' | 22 | import { VideoCommentModel } from '../video/video-comment' |
20 | import { VideoImportModel } from '../video/video-import' | 23 | import { VideoImportModel } from '../video/video-import' |
21 | import { AccountModel } from './account' | ||
22 | import { ActorImageModel } from './actor-image' | ||
23 | import { UserModel } from './user' | 24 | import { UserModel } from './user' |
24 | 25 | ||
25 | enum ScopeNames { | 26 | enum ScopeNames { |
@@ -286,7 +287,7 @@ function buildAccountInclude (required: boolean, withActor = false) { | |||
286 | } | 287 | } |
287 | ] as (ModelIndexesOptions & { where?: WhereOptions })[] | 288 | ] as (ModelIndexesOptions & { where?: WhereOptions })[] |
288 | }) | 289 | }) |
289 | export class UserNotificationModel extends Model { | 290 | export class UserNotificationModel extends Model<Partial<AttributesOnly<UserNotificationModel>>> { |
290 | 291 | ||
291 | @AllowNull(false) | 292 | @AllowNull(false) |
292 | @Default(null) | 293 | @Default(null) |
diff --git a/server/models/account/user-video-history.ts b/server/models/user/user-video-history.ts index 6be1d65ea..e3dc4a062 100644 --- a/server/models/account/user-video-history.ts +++ b/server/models/user/user-video-history.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { DestroyOptions, Op, Transaction } from 'sequelize' | ||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
4 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from '../video/video' | 5 | import { VideoModel } from '../video/video' |
3 | import { UserModel } from './user' | 6 | import { UserModel } from './user' |
4 | import { DestroyOptions, Op, Transaction } from 'sequelize' | ||
5 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
6 | 7 | ||
7 | @Table({ | 8 | @Table({ |
8 | tableName: 'userVideoHistory', | 9 | tableName: 'userVideoHistory', |
@@ -19,7 +20,7 @@ import { MUserAccountId, MUserId } from '@server/types/models' | |||
19 | } | 20 | } |
20 | ] | 21 | ] |
21 | }) | 22 | }) |
22 | export class UserVideoHistoryModel extends Model { | 23 | export class UserVideoHistoryModel extends Model<Partial<AttributesOnly<UserVideoHistoryModel>>> { |
23 | @CreatedAt | 24 | @CreatedAt |
24 | createdAt: Date | 25 | createdAt: Date |
25 | 26 | ||
diff --git a/server/models/account/user.ts b/server/models/user/user.ts index 00c6d73aa..20696b1f4 100644 --- a/server/models/account/user.ts +++ b/server/models/user/user.ts | |||
@@ -31,6 +31,7 @@ import { | |||
31 | MUserWithNotificationSetting, | 31 | MUserWithNotificationSetting, |
32 | MVideoWithRights | 32 | MVideoWithRights |
33 | } from '@server/types/models' | 33 | } from '@server/types/models' |
34 | import { AttributesOnly } from '@shared/core-utils' | ||
34 | import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users' | 35 | import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users' |
35 | import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models' | 36 | import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models' |
36 | import { User, UserRole } from '../../../shared/models/users' | 37 | import { User, UserRole } from '../../../shared/models/users' |
@@ -60,8 +61,10 @@ import { | |||
60 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' | 61 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' |
61 | import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' | 62 | import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' |
62 | import { getThemeOrDefault } from '../../lib/plugins/theme-utils' | 63 | import { getThemeOrDefault } from '../../lib/plugins/theme-utils' |
63 | import { ActorModel } from '../activitypub/actor' | 64 | import { AccountModel } from '../account/account' |
64 | import { ActorFollowModel } from '../activitypub/actor-follow' | 65 | import { ActorModel } from '../actor/actor' |
66 | import { ActorFollowModel } from '../actor/actor-follow' | ||
67 | import { ActorImageModel } from '../actor/actor-image' | ||
65 | import { OAuthTokenModel } from '../oauth/oauth-token' | 68 | import { OAuthTokenModel } from '../oauth/oauth-token' |
66 | import { getSort, throwIfNotValid } from '../utils' | 69 | import { getSort, throwIfNotValid } from '../utils' |
67 | import { VideoModel } from '../video/video' | 70 | import { VideoModel } from '../video/video' |
@@ -69,9 +72,7 @@ import { VideoChannelModel } from '../video/video-channel' | |||
69 | import { VideoImportModel } from '../video/video-import' | 72 | import { VideoImportModel } from '../video/video-import' |
70 | import { VideoLiveModel } from '../video/video-live' | 73 | import { VideoLiveModel } from '../video/video-live' |
71 | import { VideoPlaylistModel } from '../video/video-playlist' | 74 | import { VideoPlaylistModel } from '../video/video-playlist' |
72 | import { AccountModel } from './account' | ||
73 | import { UserNotificationSettingModel } from './user-notification-setting' | 75 | import { UserNotificationSettingModel } from './user-notification-setting' |
74 | import { ActorImageModel } from './actor-image' | ||
75 | 76 | ||
76 | enum ScopeNames { | 77 | enum ScopeNames { |
77 | FOR_ME_API = 'FOR_ME_API', | 78 | FOR_ME_API = 'FOR_ME_API', |
@@ -233,7 +234,7 @@ enum ScopeNames { | |||
233 | } | 234 | } |
234 | ] | 235 | ] |
235 | }) | 236 | }) |
236 | export class UserModel extends Model { | 237 | export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> { |
237 | 238 | ||
238 | @AllowNull(true) | 239 | @AllowNull(true) |
239 | @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true)) | 240 | @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true)) |
@@ -565,6 +566,10 @@ export class UserModel extends Model { | |||
565 | return UserModel.unscoped().findByPk(id) | 566 | return UserModel.unscoped().findByPk(id) |
566 | } | 567 | } |
567 | 568 | ||
569 | static loadByIdFull (id: number): Promise<MUserDefault> { | ||
570 | return UserModel.findByPk(id) | ||
571 | } | ||
572 | |||
568 | static loadByIdWithChannels (id: number, withStats = false): Promise<MUserDefault> { | 573 | static loadByIdWithChannels (id: number, withStats = false): Promise<MUserDefault> { |
569 | const scopes = [ | 574 | const scopes = [ |
570 | ScopeNames.WITH_VIDEOCHANNELS | 575 | ScopeNames.WITH_VIDEOCHANNELS |
diff --git a/server/models/utils.ts b/server/models/utils.ts index ec51c66bf..e27625bc8 100644 --- a/server/models/utils.ts +++ b/server/models/utils.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import { literal, Op, OrderItem } from 'sequelize' | 1 | import { literal, Op, OrderItem, Sequelize } from 'sequelize' |
2 | import { Model, Sequelize } from 'sequelize-typescript' | ||
3 | import { Col } from 'sequelize/types/lib/utils' | 2 | import { Col } from 'sequelize/types/lib/utils' |
4 | import validator from 'validator' | 3 | import validator from 'validator' |
5 | 4 | ||
@@ -195,11 +194,11 @@ function parseAggregateResult (result: any) { | |||
195 | return total | 194 | return total |
196 | } | 195 | } |
197 | 196 | ||
198 | const createSafeIn = (model: typeof Model, stringArr: (string | number)[]) => { | 197 | function createSafeIn (sequelize: Sequelize, stringArr: (string | number)[]) { |
199 | return stringArr.map(t => { | 198 | return stringArr.map(t => { |
200 | return t === null | 199 | return t === null |
201 | ? null | 200 | ? null |
202 | : model.sequelize.escape('' + t) | 201 | : sequelize.escape('' + t) |
203 | }).join(', ') | 202 | }).join(', ') |
204 | } | 203 | } |
205 | 204 | ||
diff --git a/server/models/video/schedule-video-update.ts b/server/models/video/schedule-video-update.ts index 22b08e91a..b0952c431 100644 --- a/server/models/video/schedule-video-update.ts +++ b/server/models/video/schedule-video-update.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
2 | import { ScopeNames as VideoScopeNames, VideoModel } from './video' | ||
3 | import { VideoPrivacy } from '../../../shared/models/videos' | ||
4 | import { Op, Transaction } from 'sequelize' | 1 | import { Op, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
5 | import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models' | 3 | import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
5 | import { VideoPrivacy } from '../../../shared/models/videos' | ||
6 | import { ScopeNames as VideoScopeNames, VideoModel } from './video' | ||
6 | 7 | ||
7 | @Table({ | 8 | @Table({ |
8 | tableName: 'scheduleVideoUpdate', | 9 | tableName: 'scheduleVideoUpdate', |
@@ -16,7 +17,7 @@ import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@ | |||
16 | } | 17 | } |
17 | ] | 18 | ] |
18 | }) | 19 | }) |
19 | export class ScheduleVideoUpdateModel extends Model { | 20 | export class ScheduleVideoUpdateModel extends Model<Partial<AttributesOnly<ScheduleVideoUpdateModel>>> { |
20 | 21 | ||
21 | @AllowNull(false) | 22 | @AllowNull(false) |
22 | @Default(null) | 23 | @Default(null) |
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts index d04205703..c1eebe27f 100644 --- a/server/models/video/tag.ts +++ b/server/models/video/tag.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { col, fn, QueryTypes, Transaction } from 'sequelize' | 1 | import { col, fn, QueryTypes, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MTag } from '@server/types/models' | 3 | import { MTag } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoPrivacy, VideoState } from '../../../shared/models/videos' | 5 | import { VideoPrivacy, VideoState } from '../../../shared/models/videos' |
5 | import { isVideoTagValid } from '../../helpers/custom-validators/videos' | 6 | import { isVideoTagValid } from '../../helpers/custom-validators/videos' |
6 | import { throwIfNotValid } from '../utils' | 7 | import { throwIfNotValid } from '../utils' |
@@ -21,7 +22,7 @@ import { VideoTagModel } from './video-tag' | |||
21 | } | 22 | } |
22 | ] | 23 | ] |
23 | }) | 24 | }) |
24 | export class TagModel extends Model { | 25 | export class TagModel extends Model<Partial<AttributesOnly<TagModel>>> { |
25 | 26 | ||
26 | @AllowNull(false) | 27 | @AllowNull(false) |
27 | @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) | 28 | @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) |
diff --git a/server/models/video/thumbnail.ts b/server/models/video/thumbnail.ts index f1187c8d6..3388478d9 100644 --- a/server/models/video/thumbnail.ts +++ b/server/models/video/thumbnail.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | 18 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' |
19 | import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' | 19 | import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' | 21 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' |
21 | import { logger } from '../../helpers/logger' | 22 | import { logger } from '../../helpers/logger' |
22 | import { CONFIG } from '../../initializers/config' | 23 | import { CONFIG } from '../../initializers/config' |
@@ -40,7 +41,7 @@ import { VideoPlaylistModel } from './video-playlist' | |||
40 | } | 41 | } |
41 | ] | 42 | ] |
42 | }) | 43 | }) |
43 | export class ThumbnailModel extends Model { | 44 | export class ThumbnailModel extends Model<Partial<AttributesOnly<ThumbnailModel>>> { |
44 | 45 | ||
45 | @AllowNull(false) | 46 | @AllowNull(false) |
46 | @Column | 47 | @Column |
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index aa18896da..98f4ec9c5 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { FindOptions } from 'sequelize' | 1 | import { FindOptions } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' | 3 | import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' | 5 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' |
5 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' | 6 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' |
6 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 7 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
@@ -18,7 +19,7 @@ import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel | |||
18 | } | 19 | } |
19 | ] | 20 | ] |
20 | }) | 21 | }) |
21 | export class VideoBlacklistModel extends Model { | 22 | export class VideoBlacklistModel extends Model<Partial<AttributesOnly<VideoBlacklistModel>>> { |
22 | 23 | ||
23 | @AllowNull(true) | 24 | @AllowNull(true) |
24 | @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) | 25 | @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) |
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts index bfdec73e9..d2c742b66 100644 --- a/server/models/video/video-caption.ts +++ b/server/models/video/video-caption.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { v4 as uuidv4 } from 'uuid' | 18 | import { v4 as uuidv4 } from 'uuid' |
19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' | 19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' | 21 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' |
21 | import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' | 22 | import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' |
22 | import { logger } from '../../helpers/logger' | 23 | import { logger } from '../../helpers/logger' |
@@ -57,7 +58,7 @@ export enum ScopeNames { | |||
57 | } | 58 | } |
58 | ] | 59 | ] |
59 | }) | 60 | }) |
60 | export class VideoCaptionModel extends Model { | 61 | export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaptionModel>>> { |
61 | @CreatedAt | 62 | @CreatedAt |
62 | createdAt: Date | 63 | createdAt: Date |
63 | 64 | ||
diff --git a/server/models/video/video-change-ownership.ts b/server/models/video/video-change-ownership.ts index 298e8bfe2..7d20a954d 100644 --- a/server/models/video/video-change-ownership.ts +++ b/server/models/video/video-change-ownership.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' | 2 | import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' | 4 | import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' |
4 | import { AccountModel } from '../account/account' | 5 | import { AccountModel } from '../account/account' |
5 | import { getSort } from '../utils' | 6 | import { getSort } from '../utils' |
@@ -53,7 +54,7 @@ enum ScopeNames { | |||
53 | ] | 54 | ] |
54 | } | 55 | } |
55 | })) | 56 | })) |
56 | export class VideoChangeOwnershipModel extends Model { | 57 | export class VideoChangeOwnershipModel extends Model<Partial<AttributesOnly<VideoChangeOwnershipModel>>> { |
57 | @CreatedAt | 58 | @CreatedAt |
58 | createdAt: Date | 59 | createdAt: Date |
59 | 60 | ||
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index b7ffbd3b1..8c4357009 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { FindOptions, Includeable, literal, Op, QueryTypes, ScopeOptions } from 'sequelize' | 1 | import { FindOptions, Includeable, literal, Op, QueryTypes, ScopeOptions, Transaction } from 'sequelize' |
2 | import { | 2 | import { |
3 | AllowNull, | 3 | AllowNull, |
4 | BeforeDestroy, | 4 | BeforeDestroy, |
@@ -17,7 +17,9 @@ import { | |||
17 | Table, | 17 | Table, |
18 | UpdatedAt | 18 | UpdatedAt |
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { setAsUpdated } from '@server/helpers/database-utils' | ||
20 | import { MAccountActor } from '@server/types/models' | 21 | import { MAccountActor } from '@server/types/models' |
22 | import { AttributesOnly } from '@shared/core-utils' | ||
21 | import { ActivityPubActor } from '../../../shared/models/activitypub' | 23 | import { ActivityPubActor } from '../../../shared/models/activitypub' |
22 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' | 24 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' |
23 | import { | 25 | import { |
@@ -35,9 +37,9 @@ import { | |||
35 | MChannelSummaryFormattable | 37 | MChannelSummaryFormattable |
36 | } from '../../types/models/video' | 38 | } from '../../types/models/video' |
37 | import { AccountModel, ScopeNames as AccountModelScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' | 39 | import { AccountModel, ScopeNames as AccountModelScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' |
38 | import { ActorImageModel } from '../account/actor-image' | 40 | import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor' |
39 | import { ActorModel, unusedActorAttributesForAPI } from '../activitypub/actor' | 41 | import { ActorFollowModel } from '../actor/actor-follow' |
40 | import { ActorFollowModel } from '../activitypub/actor-follow' | 42 | import { ActorImageModel } from '../actor/actor-image' |
41 | import { ServerModel } from '../server/server' | 43 | import { ServerModel } from '../server/server' |
42 | import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils' | 44 | import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils' |
43 | import { VideoModel } from './video' | 45 | import { VideoModel } from './video' |
@@ -245,7 +247,7 @@ export type SummaryOptions = { | |||
245 | } | 247 | } |
246 | ] | 248 | ] |
247 | }) | 249 | }) |
248 | export class VideoChannelModel extends Model { | 250 | export class VideoChannelModel extends Model<Partial<AttributesOnly<VideoChannelModel>>> { |
249 | 251 | ||
250 | @AllowNull(false) | 252 | @AllowNull(false) |
251 | @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) | 253 | @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) |
@@ -653,7 +655,6 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` | |||
653 | description: this.description, | 655 | description: this.description, |
654 | support: this.support, | 656 | support: this.support, |
655 | isLocal: this.Actor.isOwned(), | 657 | isLocal: this.Actor.isOwned(), |
656 | createdAt: this.createdAt, | ||
657 | updatedAt: this.updatedAt, | 658 | updatedAt: this.updatedAt, |
658 | ownerAccount: undefined, | 659 | ownerAccount: undefined, |
659 | videosCount, | 660 | videosCount, |
@@ -691,4 +692,8 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` | |||
691 | isOutdated () { | 692 | isOutdated () { |
692 | return this.Actor.isOutdated() | 693 | return this.Actor.isOutdated() |
693 | } | 694 | } |
695 | |||
696 | setAsUpdated (transaction: Transaction) { | ||
697 | return setAsUpdated('videoChannel', this.id, transaction) | ||
698 | } | ||
694 | } | 699 | } |
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index 151c2bc81..bdf5d86bc 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts | |||
@@ -16,10 +16,11 @@ import { | |||
16 | } from 'sequelize-typescript' | 16 | } from 'sequelize-typescript' |
17 | import { getServerActor } from '@server/models/application/application' | 17 | import { getServerActor } from '@server/models/application/application' |
18 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' | 18 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' |
19 | import { AttributesOnly } from '@shared/core-utils' | ||
19 | import { VideoPrivacy } from '@shared/models' | 20 | import { VideoPrivacy } from '@shared/models' |
20 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' | 21 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' |
21 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' | 22 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' |
22 | import { VideoComment, VideoCommentAdmin } from '../../../shared/models/videos/video-comment.model' | 23 | import { VideoComment, VideoCommentAdmin } from '../../../shared/models/videos/comment/video-comment.model' |
23 | import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor' | 24 | import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor' |
24 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 25 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
25 | import { regexpCapture } from '../../helpers/regexp' | 26 | import { regexpCapture } from '../../helpers/regexp' |
@@ -39,7 +40,7 @@ import { | |||
39 | } from '../../types/models/video' | 40 | } from '../../types/models/video' |
40 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' | 41 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' |
41 | import { AccountModel } from '../account/account' | 42 | import { AccountModel } from '../account/account' |
42 | import { ActorModel, unusedActorAttributesForAPI } from '../activitypub/actor' | 43 | import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor' |
43 | import { | 44 | import { |
44 | buildBlockedAccountSQL, | 45 | buildBlockedAccountSQL, |
45 | buildBlockedAccountSQLOptimized, | 46 | buildBlockedAccountSQLOptimized, |
@@ -173,7 +174,7 @@ export enum ScopeNames { | |||
173 | } | 174 | } |
174 | ] | 175 | ] |
175 | }) | 176 | }) |
176 | export class VideoCommentModel extends Model { | 177 | export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoCommentModel>>> { |
177 | @CreatedAt | 178 | @CreatedAt |
178 | createdAt: Date | 179 | createdAt: Date |
179 | 180 | ||
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts index 1ad796104..22cf63804 100644 --- a/server/models/video/video-file.ts +++ b/server/models/video/video-file.ts | |||
@@ -25,6 +25,7 @@ import { logger } from '@server/helpers/logger' | |||
25 | import { extractVideo } from '@server/helpers/video' | 25 | import { extractVideo } from '@server/helpers/video' |
26 | import { getTorrentFilePath } from '@server/lib/video-paths' | 26 | import { getTorrentFilePath } from '@server/lib/video-paths' |
27 | import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' | 27 | import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' |
28 | import { AttributesOnly } from '@shared/core-utils' | ||
28 | import { | 29 | import { |
29 | isVideoFileExtnameValid, | 30 | isVideoFileExtnameValid, |
30 | isVideoFileInfoHashValid, | 31 | isVideoFileInfoHashValid, |
@@ -149,7 +150,7 @@ export enum ScopeNames { | |||
149 | } | 150 | } |
150 | ] | 151 | ] |
151 | }) | 152 | }) |
152 | export class VideoFileModel extends Model { | 153 | export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>>> { |
153 | @CreatedAt | 154 | @CreatedAt |
154 | createdAt: Date | 155 | createdAt: Date |
155 | 156 | ||
@@ -401,6 +402,10 @@ export class VideoFileModel extends Model { | |||
401 | return VideoFileModel.destroy(options) | 402 | return VideoFileModel.destroy(options) |
402 | } | 403 | } |
403 | 404 | ||
405 | hasTorrent () { | ||
406 | return this.infoHash && this.torrentFilename | ||
407 | } | ||
408 | |||
404 | getVideoOrStreamingPlaylist (this: MVideoFileVideo | MVideoFileStreamingPlaylistVideo): MVideo | MStreamingPlaylistVideo { | 409 | getVideoOrStreamingPlaylist (this: MVideoFileVideo | MVideoFileStreamingPlaylistVideo): MVideo | MStreamingPlaylistVideo { |
405 | if (this.videoId) return (this as MVideoFileVideo).Video | 410 | if (this.videoId) return (this as MVideoFileVideo).Video |
406 | 411 | ||
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts index bcba90093..551cb2842 100644 --- a/server/models/video/video-format-utils.ts +++ b/server/models/video/video-format-utils.ts | |||
@@ -205,7 +205,7 @@ function videoFilesModelToFormattedJSON ( | |||
205 | label: videoFile.resolution + 'p' | 205 | label: videoFile.resolution + 'p' |
206 | }, | 206 | }, |
207 | 207 | ||
208 | magnetUri: includeMagnet && videoFile.torrentFilename | 208 | magnetUri: includeMagnet && videoFile.hasTorrent() |
209 | ? generateMagnetUri(video, videoFile, trackerUrls) | 209 | ? generateMagnetUri(video, videoFile, trackerUrls) |
210 | : undefined, | 210 | : undefined, |
211 | 211 | ||
@@ -253,19 +253,21 @@ function addVideoFilesInAPAcc ( | |||
253 | fps: file.fps | 253 | fps: file.fps |
254 | }) | 254 | }) |
255 | 255 | ||
256 | acc.push({ | 256 | if (file.hasTorrent()) { |
257 | type: 'Link', | 257 | acc.push({ |
258 | mediaType: 'application/x-bittorrent' as 'application/x-bittorrent', | 258 | type: 'Link', |
259 | href: file.getTorrentUrl(), | 259 | mediaType: 'application/x-bittorrent' as 'application/x-bittorrent', |
260 | height: file.resolution | 260 | href: file.getTorrentUrl(), |
261 | }) | 261 | height: file.resolution |
262 | 262 | }) | |
263 | acc.push({ | 263 | |
264 | type: 'Link', | 264 | acc.push({ |
265 | mediaType: 'application/x-bittorrent;x-scheme-handler/magnet' as 'application/x-bittorrent;x-scheme-handler/magnet', | 265 | type: 'Link', |
266 | href: generateMagnetUri(video, file, trackerUrls), | 266 | mediaType: 'application/x-bittorrent;x-scheme-handler/magnet' as 'application/x-bittorrent;x-scheme-handler/magnet', |
267 | height: file.resolution | 267 | href: generateMagnetUri(video, file, trackerUrls), |
268 | }) | 268 | height: file.resolution |
269 | }) | ||
270 | } | ||
269 | } | 271 | } |
270 | } | 272 | } |
271 | 273 | ||
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts index 8324166cc..5c73fb07c 100644 --- a/server/models/video/video-import.ts +++ b/server/models/video/video-import.ts | |||
@@ -13,15 +13,16 @@ import { | |||
13 | Table, | 13 | Table, |
14 | UpdatedAt | 14 | UpdatedAt |
15 | } from 'sequelize-typescript' | 15 | } from 'sequelize-typescript' |
16 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | ||
16 | import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' | 17 | import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' |
18 | import { AttributesOnly } from '@shared/core-utils' | ||
17 | import { VideoImport, VideoImportState } from '../../../shared' | 19 | import { VideoImport, VideoImportState } from '../../../shared' |
18 | import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' | 20 | import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' |
19 | import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' | 21 | import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' |
20 | import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants' | 22 | import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants' |
21 | import { UserModel } from '../account/user' | 23 | import { UserModel } from '../user/user' |
22 | import { getSort, throwIfNotValid } from '../utils' | 24 | import { getSort, throwIfNotValid } from '../utils' |
23 | import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' | 25 | import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' |
24 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | ||
25 | 26 | ||
26 | @DefaultScope(() => ({ | 27 | @DefaultScope(() => ({ |
27 | include: [ | 28 | include: [ |
@@ -52,7 +53,7 @@ import { afterCommitIfTransaction } from '@server/helpers/database-utils' | |||
52 | } | 53 | } |
53 | ] | 54 | ] |
54 | }) | 55 | }) |
55 | export class VideoImportModel extends Model { | 56 | export class VideoImportModel extends Model<Partial<AttributesOnly<VideoImportModel>>> { |
56 | @CreatedAt | 57 | @CreatedAt |
57 | createdAt: Date | 58 | createdAt: Date |
58 | 59 | ||
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts index cb4a9b896..014491d50 100644 --- a/server/models/video/video-live.ts +++ b/server/models/video/video-live.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { WEBSERVER } from '@server/initializers/constants' | 2 | import { WEBSERVER } from '@server/initializers/constants' |
3 | import { MVideoLive, MVideoLiveVideo } from '@server/types/models' | 3 | import { MVideoLive, MVideoLiveVideo } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { LiveVideo, VideoState } from '@shared/models' | 5 | import { LiveVideo, VideoState } from '@shared/models' |
5 | import { VideoModel } from './video' | 6 | import { VideoModel } from './video' |
6 | import { VideoBlacklistModel } from './video-blacklist' | 7 | import { VideoBlacklistModel } from './video-blacklist' |
@@ -28,7 +29,7 @@ import { VideoBlacklistModel } from './video-blacklist' | |||
28 | } | 29 | } |
29 | ] | 30 | ] |
30 | }) | 31 | }) |
31 | export class VideoLiveModel extends Model { | 32 | export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel>>> { |
32 | 33 | ||
33 | @AllowNull(true) | 34 | @AllowNull(true) |
34 | @Column(DataType.STRING) | 35 | @Column(DataType.STRING) |
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts index d2d7e2740..e6906cb19 100644 --- a/server/models/video/video-playlist-element.ts +++ b/server/models/video/video-playlist-element.ts | |||
@@ -32,6 +32,7 @@ import { AccountModel } from '../account/account' | |||
32 | import { getSort, throwIfNotValid } from '../utils' | 32 | import { getSort, throwIfNotValid } from '../utils' |
33 | import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' | 33 | import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' |
34 | import { VideoPlaylistModel } from './video-playlist' | 34 | import { VideoPlaylistModel } from './video-playlist' |
35 | import { AttributesOnly } from '@shared/core-utils' | ||
35 | 36 | ||
36 | @Table({ | 37 | @Table({ |
37 | tableName: 'videoPlaylistElement', | 38 | tableName: 'videoPlaylistElement', |
@@ -48,7 +49,7 @@ import { VideoPlaylistModel } from './video-playlist' | |||
48 | } | 49 | } |
49 | ] | 50 | ] |
50 | }) | 51 | }) |
51 | export class VideoPlaylistElementModel extends Model { | 52 | export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<VideoPlaylistElementModel>>> { |
52 | @CreatedAt | 53 | @CreatedAt |
53 | createdAt: Date | 54 | createdAt: Date |
54 | 55 | ||
@@ -274,7 +275,8 @@ export class VideoPlaylistElementModel extends Model { | |||
274 | validate: false // We use a literal to update the position | 275 | validate: false // We use a literal to update the position |
275 | } | 276 | } |
276 | 277 | ||
277 | return VideoPlaylistElementModel.update({ position: Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) }, query) | 278 | const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) |
279 | return VideoPlaylistElementModel.update({ position: positionQuery as any }, query) | ||
278 | } | 280 | } |
279 | 281 | ||
280 | static increasePositionOf ( | 282 | static increasePositionOf ( |
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts index efe5be36d..c293287d3 100644 --- a/server/models/video/video-playlist.ts +++ b/server/models/video/video-playlist.ts | |||
@@ -19,6 +19,7 @@ import { | |||
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { v4 as uuidv4 } from 'uuid' | 20 | import { v4 as uuidv4 } from 'uuid' |
21 | import { MAccountId, MChannelId } from '@server/types/models' | 21 | import { MAccountId, MChannelId } from '@server/types/models' |
22 | import { AttributesOnly } from '@shared/core-utils' | ||
22 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' | 23 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' |
23 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' | 24 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' |
24 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' | 25 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' |
@@ -50,11 +51,11 @@ import { | |||
50 | MVideoPlaylistIdWithElements | 51 | MVideoPlaylistIdWithElements |
51 | } from '../../types/models/video/video-playlist' | 52 | } from '../../types/models/video/video-playlist' |
52 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' | 53 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' |
54 | import { ActorModel } from '../actor/actor' | ||
53 | import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils' | 55 | import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils' |
54 | import { ThumbnailModel } from './thumbnail' | 56 | import { ThumbnailModel } from './thumbnail' |
55 | import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' | 57 | import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' |
56 | import { VideoPlaylistElementModel } from './video-playlist-element' | 58 | import { VideoPlaylistElementModel } from './video-playlist-element' |
57 | import { ActorModel } from '../activitypub/actor' | ||
58 | 59 | ||
59 | enum ScopeNames { | 60 | enum ScopeNames { |
60 | AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST', | 61 | AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST', |
@@ -221,7 +222,7 @@ type AvailableForListOptions = { | |||
221 | } | 222 | } |
222 | ] | 223 | ] |
223 | }) | 224 | }) |
224 | export class VideoPlaylistModel extends Model { | 225 | export class VideoPlaylistModel extends Model<Partial<AttributesOnly<VideoPlaylistModel>>> { |
225 | @CreatedAt | 226 | @CreatedAt |
226 | createdAt: Date | 227 | createdAt: Date |
227 | 228 | ||
diff --git a/server/models/video/video-query-builder.ts b/server/models/video/video-query-builder.ts index 155afe64b..2aa5e65c8 100644 --- a/server/models/video/video-query-builder.ts +++ b/server/models/video/video-query-builder.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models' | 1 | import { Sequelize } from 'sequelize/types' |
2 | import { buildDirectionAndField, createSafeIn } from '@server/models/utils' | ||
3 | import { Model } from 'sequelize-typescript' | ||
4 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
5 | import validator from 'validator' | 2 | import validator from 'validator' |
6 | import { exists } from '@server/helpers/custom-validators/misc' | 3 | import { exists } from '@server/helpers/custom-validators/misc' |
4 | import { buildDirectionAndField, createSafeIn } from '@server/models/utils' | ||
5 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
6 | import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models' | ||
7 | 7 | ||
8 | export type BuildVideosQueryOptions = { | 8 | export type BuildVideosQueryOptions = { |
9 | attributes?: string[] | 9 | attributes?: string[] |
@@ -55,7 +55,7 @@ export type BuildVideosQueryOptions = { | |||
55 | having?: string | 55 | having?: string |
56 | } | 56 | } |
57 | 57 | ||
58 | function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) { | 58 | function buildListQuery (sequelize: Sequelize, options: BuildVideosQueryOptions) { |
59 | const and: string[] = [] | 59 | const and: string[] = [] |
60 | const joins: string[] = [] | 60 | const joins: string[] = [] |
61 | const replacements: any = {} | 61 | const replacements: any = {} |
@@ -77,7 +77,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
77 | const blockerIds = [ options.serverAccountId ] | 77 | const blockerIds = [ options.serverAccountId ] |
78 | if (options.user) blockerIds.push(options.user.Account.id) | 78 | if (options.user) blockerIds.push(options.user.Account.id) |
79 | 79 | ||
80 | const inClause = createSafeIn(model, blockerIds) | 80 | const inClause = createSafeIn(sequelize, blockerIds) |
81 | 81 | ||
82 | and.push( | 82 | and.push( |
83 | 'NOT EXISTS (' + | 83 | 'NOT EXISTS (' + |
@@ -179,7 +179,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
179 | 'EXISTS (' + | 179 | 'EXISTS (' + |
180 | ' SELECT 1 FROM "videoTag" ' + | 180 | ' SELECT 1 FROM "videoTag" ' + |
181 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 181 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
182 | ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsOneOfLower) + ') ' + | 182 | ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsOneOfLower) + ') ' + |
183 | ' AND "video"."id" = "videoTag"."videoId"' + | 183 | ' AND "video"."id" = "videoTag"."videoId"' + |
184 | ')' | 184 | ')' |
185 | ) | 185 | ) |
@@ -192,7 +192,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
192 | 'EXISTS (' + | 192 | 'EXISTS (' + |
193 | ' SELECT 1 FROM "videoTag" ' + | 193 | ' SELECT 1 FROM "videoTag" ' + |
194 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 194 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
195 | ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsAllOfLower) + ') ' + | 195 | ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsAllOfLower) + ') ' + |
196 | ' AND "video"."id" = "videoTag"."videoId" ' + | 196 | ' AND "video"."id" = "videoTag"."videoId" ' + |
197 | ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length + | 197 | ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length + |
198 | ')' | 198 | ')' |
@@ -232,7 +232,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
232 | languagesQueryParts.push( | 232 | languagesQueryParts.push( |
233 | 'EXISTS (' + | 233 | 'EXISTS (' + |
234 | ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' + | 234 | ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' + |
235 | ' IN (' + createSafeIn(model, languages) + ') AND ' + | 235 | ' IN (' + createSafeIn(sequelize, languages) + ') AND ' + |
236 | ' "videoCaption"."videoId" = "video"."id"' + | 236 | ' "videoCaption"."videoId" = "video"."id"' + |
237 | ')' | 237 | ')' |
238 | ) | 238 | ) |
@@ -345,8 +345,8 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
345 | } | 345 | } |
346 | 346 | ||
347 | if (options.search) { | 347 | if (options.search) { |
348 | const escapedSearch = model.sequelize.escape(options.search) | 348 | const escapedSearch = sequelize.escape(options.search) |
349 | const escapedLikeSearch = model.sequelize.escape('%' + options.search + '%') | 349 | const escapedLikeSearch = sequelize.escape('%' + options.search + '%') |
350 | 350 | ||
351 | cte.push( | 351 | cte.push( |
352 | '"trigramSearch" AS (' + | 352 | '"trigramSearch" AS (' + |
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts index 5059c1fa6..505c305e2 100644 --- a/server/models/video/video-share.ts +++ b/server/models/video/video-share.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' | 1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 4 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
4 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 5 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
5 | import { MActorDefault } from '../../types/models' | 6 | import { MActorDefault } from '../../types/models' |
6 | import { MVideoShareActor, MVideoShareFull } from '../../types/models/video' | 7 | import { MVideoShareActor, MVideoShareFull } from '../../types/models/video' |
7 | import { ActorModel } from '../activitypub/actor' | 8 | import { ActorModel } from '../actor/actor' |
8 | import { buildLocalActorIdsIn, throwIfNotValid } from '../utils' | 9 | import { buildLocalActorIdsIn, throwIfNotValid } from '../utils' |
9 | import { VideoModel } from './video' | 10 | import { VideoModel } from './video' |
10 | 11 | ||
@@ -50,7 +51,7 @@ enum ScopeNames { | |||
50 | } | 51 | } |
51 | ] | 52 | ] |
52 | }) | 53 | }) |
53 | export class VideoShareModel extends Model { | 54 | export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareModel>>> { |
54 | 55 | ||
55 | @AllowNull(false) | 56 | @AllowNull(false) |
56 | @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) | 57 | @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) |
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts index c9375b433..d627e8c9d 100644 --- a/server/models/video/video-streaming-playlist.ts +++ b/server/models/video/video-streaming-playlist.ts | |||
@@ -13,6 +13,7 @@ import { CONSTRAINTS_FIELDS, MEMOIZE_LENGTH, MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_ | |||
13 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' | 13 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' |
14 | import { throwIfNotValid } from '../utils' | 14 | import { throwIfNotValid } from '../utils' |
15 | import { VideoModel } from './video' | 15 | import { VideoModel } from './video' |
16 | import { AttributesOnly } from '@shared/core-utils' | ||
16 | 17 | ||
17 | @Table({ | 18 | @Table({ |
18 | tableName: 'videoStreamingPlaylist', | 19 | tableName: 'videoStreamingPlaylist', |
@@ -30,7 +31,7 @@ import { VideoModel } from './video' | |||
30 | } | 31 | } |
31 | ] | 32 | ] |
32 | }) | 33 | }) |
33 | export class VideoStreamingPlaylistModel extends Model { | 34 | export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<VideoStreamingPlaylistModel>>> { |
34 | @CreatedAt | 35 | @CreatedAt |
35 | createdAt: Date | 36 | createdAt: Date |
36 | 37 | ||
diff --git a/server/models/video/video-tag.ts b/server/models/video/video-tag.ts index 5052b8c4d..1285d375b 100644 --- a/server/models/video/video-tag.ts +++ b/server/models/video/video-tag.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { TagModel } from './tag' | 3 | import { TagModel } from './tag' |
3 | import { VideoModel } from './video' | 4 | import { VideoModel } from './video' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { VideoModel } from './video' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoTagModel extends Model { | 17 | export class VideoTagModel extends Model<Partial<AttributesOnly<VideoTagModel>>> { |
17 | @CreatedAt | 18 | @CreatedAt |
18 | createdAt: Date | 19 | createdAt: Date |
19 | 20 | ||
diff --git a/server/models/video/video-view.ts b/server/models/video/video-view.ts index 992cf258a..dfc6296ce 100644 --- a/server/models/video/video-view.ts +++ b/server/models/video/video-view.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from './video' | 4 | import { VideoModel } from './video' |
3 | import * as Sequelize from 'sequelize' | ||
4 | 5 | ||
5 | @Table({ | 6 | @Table({ |
6 | tableName: 'videoView', | 7 | tableName: 'videoView', |
@@ -14,7 +15,7 @@ import * as Sequelize from 'sequelize' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class VideoViewModel extends Model { | 18 | export class VideoViewModel extends Model<Partial<AttributesOnly<VideoViewModel>>> { |
18 | @CreatedAt | 19 | @CreatedAt |
19 | createdAt: Date | 20 | createdAt: Date |
20 | 21 | ||
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index e55a21a6b..d4a258187 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -24,12 +24,14 @@ import { | |||
24 | Table, | 24 | Table, |
25 | UpdatedAt | 25 | UpdatedAt |
26 | } from 'sequelize-typescript' | 26 | } from 'sequelize-typescript' |
27 | import { setAsUpdated } from '@server/helpers/database-utils' | ||
27 | import { buildNSFWFilter } from '@server/helpers/express-utils' | 28 | import { buildNSFWFilter } from '@server/helpers/express-utils' |
28 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' | 29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' |
29 | import { LiveManager } from '@server/lib/live-manager' | 30 | import { LiveManager } from '@server/lib/live-manager' |
30 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' | 31 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' |
31 | import { getServerActor } from '@server/models/application/application' | 32 | import { getServerActor } from '@server/models/application/application' |
32 | import { ModelCache } from '@server/models/model-cache' | 33 | import { ModelCache } from '@server/models/model-cache' |
34 | import { AttributesOnly } from '@shared/core-utils' | ||
33 | import { VideoFile } from '@shared/models/videos/video-file.model' | 35 | import { VideoFile } from '@shared/models/videos/video-file.model' |
34 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' | 36 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' |
35 | import { VideoObject } from '../../../shared/models/activitypub/objects' | 37 | import { VideoObject } from '../../../shared/models/activitypub/objects' |
@@ -99,14 +101,14 @@ import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models | |||
99 | import { VideoAbuseModel } from '../abuse/video-abuse' | 101 | import { VideoAbuseModel } from '../abuse/video-abuse' |
100 | import { AccountModel } from '../account/account' | 102 | import { AccountModel } from '../account/account' |
101 | import { AccountVideoRateModel } from '../account/account-video-rate' | 103 | import { AccountVideoRateModel } from '../account/account-video-rate' |
102 | import { ActorImageModel } from '../account/actor-image' | 104 | import { ActorModel } from '../actor/actor' |
103 | import { UserModel } from '../account/user' | 105 | import { ActorImageModel } from '../actor/actor-image' |
104 | import { UserVideoHistoryModel } from '../account/user-video-history' | ||
105 | import { ActorModel } from '../activitypub/actor' | ||
106 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' | 106 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' |
107 | import { ServerModel } from '../server/server' | 107 | import { ServerModel } from '../server/server' |
108 | import { TrackerModel } from '../server/tracker' | 108 | import { TrackerModel } from '../server/tracker' |
109 | import { VideoTrackerModel } from '../server/video-tracker' | 109 | import { VideoTrackerModel } from '../server/video-tracker' |
110 | import { UserModel } from '../user/user' | ||
111 | import { UserVideoHistoryModel } from '../user/user-video-history' | ||
110 | import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils' | 112 | import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils' |
111 | import { ScheduleVideoUpdateModel } from './schedule-video-update' | 113 | import { ScheduleVideoUpdateModel } from './schedule-video-update' |
112 | import { TagModel } from './tag' | 114 | import { TagModel } from './tag' |
@@ -488,7 +490,7 @@ export type AvailableForListIDsOptions = { | |||
488 | } | 490 | } |
489 | ] | 491 | ] |
490 | }) | 492 | }) |
491 | export class VideoModel extends Model { | 493 | export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { |
492 | 494 | ||
493 | @AllowNull(false) | 495 | @AllowNull(false) |
494 | @Default(DataType.UUIDV4) | 496 | @Default(DataType.UUIDV4) |
@@ -1007,6 +1009,7 @@ export class VideoModel extends Model { | |||
1007 | attributes: [ 'id' ], | 1009 | attributes: [ 'id' ], |
1008 | where: { | 1010 | where: { |
1009 | isLive: true, | 1011 | isLive: true, |
1012 | remote: false, | ||
1010 | state: VideoState.PUBLISHED | 1013 | state: VideoState.PUBLISHED |
1011 | } | 1014 | } |
1012 | } | 1015 | } |
@@ -1616,7 +1619,7 @@ export class VideoModel extends Model { | |||
1616 | includeLocalVideos: true | 1619 | includeLocalVideos: true |
1617 | } | 1620 | } |
1618 | 1621 | ||
1619 | const { query, replacements } = buildListQuery(VideoModel, queryOptions) | 1622 | const { query, replacements } = buildListQuery(VideoModel.sequelize, queryOptions) |
1620 | 1623 | ||
1621 | return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT }) | 1624 | return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT }) |
1622 | .then(rows => rows.map(r => r[field])) | 1625 | .then(rows => rows.map(r => r[field])) |
@@ -1644,7 +1647,7 @@ export class VideoModel extends Model { | |||
1644 | if (countVideos !== true) return Promise.resolve(undefined) | 1647 | if (countVideos !== true) return Promise.resolve(undefined) |
1645 | 1648 | ||
1646 | const countOptions = Object.assign({}, options, { isCount: true }) | 1649 | const countOptions = Object.assign({}, options, { isCount: true }) |
1647 | const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel, countOptions) | 1650 | const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel.sequelize, countOptions) |
1648 | 1651 | ||
1649 | return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT }) | 1652 | return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT }) |
1650 | .then(rows => rows.length !== 0 ? rows[0].total : 0) | 1653 | .then(rows => rows.length !== 0 ? rows[0].total : 0) |
@@ -1653,7 +1656,7 @@ export class VideoModel extends Model { | |||
1653 | function getModels () { | 1656 | function getModels () { |
1654 | if (options.count === 0) return Promise.resolve([]) | 1657 | if (options.count === 0) return Promise.resolve([]) |
1655 | 1658 | ||
1656 | const { query, replacements, order } = buildListQuery(VideoModel, options) | 1659 | const { query, replacements, order } = buildListQuery(VideoModel.sequelize, options) |
1657 | const queryModels = wrapForAPIResults(query, replacements, options, order) | 1660 | const queryModels = wrapForAPIResults(query, replacements, options, order) |
1658 | 1661 | ||
1659 | return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true }) | 1662 | return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true }) |
@@ -2053,11 +2056,7 @@ export class VideoModel extends Model { | |||
2053 | } | 2056 | } |
2054 | 2057 | ||
2055 | setAsRefreshed () { | 2058 | setAsRefreshed () { |
2056 | const options = { | 2059 | return setAsUpdated('video', this.id) |
2057 | where: { id: this.id } | ||
2058 | } | ||
2059 | |||
2060 | return VideoModel.update({ updatedAt: new Date() }, options) | ||
2061 | } | 2060 | } |
2062 | 2061 | ||
2063 | requiresAuth () { | 2062 | requiresAuth () { |