diff options
author | Wicklow <123956049+wickloww@users.noreply.github.com> | 2023-06-29 07:48:55 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-29 09:48:55 +0200 |
commit | 40346ead2b0b7afa475aef057d3673b6c7574b7a (patch) | |
tree | 24ffdc23c3a9d987334842e0d400b5bd44500cf7 /server/models/video/video-password.ts | |
parent | ae22c59f14d0d553f60b281948b6c232c2aca178 (diff) | |
download | PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.tar.gz PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.tar.zst PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.zip |
Feature/password protected videos (#5836)
* Add server endpoints
* Refactoring test suites
* Update server and add openapi documentation
* fix compliation and tests
* upload/import password protected video on client
* add server error code
* Add video password to update resolver
* add custom message when sharing pw protected video
* improve confirm component
* Add new alert in component
* Add ability to watch protected video on client
* Cannot have password protected replay privacy
* Add migration
* Add tests
* update after review
* Update check params tests
* Add live videos test
* Add more filter test
* Update static file privacy test
* Update object storage tests
* Add test on feeds
* Add missing word
* Fix tests
* Fix tests on live videos
* add embed support on password protected videos
* fix style
* Correcting data leaks
* Unable to add password protected privacy on replay
* Updated code based on review comments
* fix validator and command
* Updated code based on review comments
Diffstat (limited to 'server/models/video/video-password.ts')
-rw-r--r-- | server/models/video/video-password.ts | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/server/models/video/video-password.ts b/server/models/video/video-password.ts new file mode 100644 index 000000000..648366c3b --- /dev/null +++ b/server/models/video/video-password.ts | |||
@@ -0,0 +1,137 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
2 | import { VideoModel } from './video' | ||
3 | import { AttributesOnly } from '@shared/typescript-utils' | ||
4 | import { ResultList, VideoPassword } from '@shared/models' | ||
5 | import { getSort, throwIfNotValid } from '../shared' | ||
6 | import { FindOptions, Transaction } from 'sequelize' | ||
7 | import { MVideoPassword } from '@server/types/models' | ||
8 | import { isPasswordValid } from '@server/helpers/custom-validators/videos' | ||
9 | import { pick } from '@shared/core-utils' | ||
10 | |||
11 | @DefaultScope(() => ({ | ||
12 | include: [ | ||
13 | { | ||
14 | model: VideoModel.unscoped(), | ||
15 | required: true | ||
16 | } | ||
17 | ] | ||
18 | })) | ||
19 | @Table({ | ||
20 | tableName: 'videoPassword', | ||
21 | indexes: [ | ||
22 | { | ||
23 | fields: [ 'videoId', 'password' ], | ||
24 | unique: true | ||
25 | } | ||
26 | ] | ||
27 | }) | ||
28 | export class VideoPasswordModel extends Model<Partial<AttributesOnly<VideoPasswordModel>>> { | ||
29 | |||
30 | @AllowNull(false) | ||
31 | @Is('VideoPassword', value => throwIfNotValid(value, isPasswordValid, 'videoPassword')) | ||
32 | @Column | ||
33 | password: string | ||
34 | |||
35 | @CreatedAt | ||
36 | createdAt: Date | ||
37 | |||
38 | @UpdatedAt | ||
39 | updatedAt: Date | ||
40 | |||
41 | @ForeignKey(() => VideoModel) | ||
42 | @Column | ||
43 | videoId: number | ||
44 | |||
45 | @BelongsTo(() => VideoModel, { | ||
46 | foreignKey: { | ||
47 | allowNull: false | ||
48 | }, | ||
49 | onDelete: 'cascade' | ||
50 | }) | ||
51 | Video: VideoModel | ||
52 | |||
53 | static async countByVideoId (videoId: number, t?: Transaction) { | ||
54 | const query: FindOptions = { | ||
55 | where: { | ||
56 | videoId | ||
57 | }, | ||
58 | transaction: t | ||
59 | } | ||
60 | |||
61 | return VideoPasswordModel.count(query) | ||
62 | } | ||
63 | |||
64 | static async loadByIdAndVideo (options: { id: number, videoId: number, t?: Transaction }): Promise<MVideoPassword> { | ||
65 | const { id, videoId, t } = options | ||
66 | const query: FindOptions = { | ||
67 | where: { | ||
68 | id, | ||
69 | videoId | ||
70 | }, | ||
71 | transaction: t | ||
72 | } | ||
73 | |||
74 | return VideoPasswordModel.findOne(query) | ||
75 | } | ||
76 | |||
77 | static async listPasswords (options: { | ||
78 | start: number | ||
79 | count: number | ||
80 | sort: string | ||
81 | videoId: number | ||
82 | }): Promise<ResultList<MVideoPassword>> { | ||
83 | const { start, count, sort, videoId } = options | ||
84 | |||
85 | const { count: total, rows: data } = await VideoPasswordModel.findAndCountAll({ | ||
86 | where: { videoId }, | ||
87 | order: getSort(sort), | ||
88 | offset: start, | ||
89 | limit: count | ||
90 | }) | ||
91 | |||
92 | return { total, data } | ||
93 | } | ||
94 | |||
95 | static async addPasswords (passwords: string[], videoId: number, transaction?: Transaction): Promise<void> { | ||
96 | for (const password of passwords) { | ||
97 | await VideoPasswordModel.create({ | ||
98 | password, | ||
99 | videoId | ||
100 | }, { transaction }) | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static async deleteAllPasswords (videoId: number, transaction?: Transaction) { | ||
105 | await VideoPasswordModel.destroy({ | ||
106 | where: { videoId }, | ||
107 | transaction | ||
108 | }) | ||
109 | } | ||
110 | |||
111 | static async deletePassword (passwordId: number, transaction?: Transaction) { | ||
112 | await VideoPasswordModel.destroy({ | ||
113 | where: { id: passwordId }, | ||
114 | transaction | ||
115 | }) | ||
116 | } | ||
117 | |||
118 | static async isACorrectPassword (options: { | ||
119 | videoId: number | ||
120 | password: string | ||
121 | }) { | ||
122 | const query = { | ||
123 | where: pick(options, [ 'videoId', 'password' ]) | ||
124 | } | ||
125 | return VideoPasswordModel.findOne(query) | ||
126 | } | ||
127 | |||
128 | toFormattedJSON (): VideoPassword { | ||
129 | return { | ||
130 | id: this.id, | ||
131 | password: this.password, | ||
132 | videoId: this.videoId, | ||
133 | createdAt: this.createdAt, | ||
134 | updatedAt: this.updatedAt | ||
135 | } | ||
136 | } | ||
137 | } | ||