aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/account
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-04-06 11:35:56 +0200
committerChocobozzz <chocobozzz@cpy.re>2021-04-08 10:07:53 +0200
commitf479685678406a5df864d89615b33d29085ebfc6 (patch)
tree8de15e90cd8d97d8810715df8585c61f48d5282a /server/models/account
parent968aaed2066873fc1c39f95168284122d9d15e21 (diff)
downloadPeerTube-f479685678406a5df864d89615b33d29085ebfc6.tar.gz
PeerTube-f479685678406a5df864d89615b33d29085ebfc6.tar.zst
PeerTube-f479685678406a5df864d89615b33d29085ebfc6.zip
Agnostic actor image storage
Diffstat (limited to 'server/models/account')
-rw-r--r--server/models/account/account.ts5
-rw-r--r--server/models/account/actor-image.ts86
-rw-r--r--server/models/account/user-notification.ts8
3 files changed, 94 insertions, 5 deletions
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index c72f9c63d..312451abe 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -33,7 +33,7 @@ import {
33import { ActorModel } from '../activitypub/actor' 33import { ActorModel } from '../activitypub/actor'
34import { ActorFollowModel } from '../activitypub/actor-follow' 34import { ActorFollowModel } from '../activitypub/actor-follow'
35import { ApplicationModel } from '../application/application' 35import { ApplicationModel } from '../application/application'
36import { AvatarModel } from '../avatar/avatar' 36import { ActorImageModel } from './actor-image'
37import { ServerModel } from '../server/server' 37import { ServerModel } from '../server/server'
38import { ServerBlocklistModel } from '../server/server-blocklist' 38import { ServerBlocklistModel } from '../server/server-blocklist'
39import { getSort, throwIfNotValid } from '../utils' 39import { getSort, throwIfNotValid } from '../utils'
@@ -82,7 +82,8 @@ export type SummaryOptions = {
82 serverInclude, 82 serverInclude,
83 83
84 { 84 {
85 model: AvatarModel.unscoped(), 85 model: ActorImageModel.unscoped(),
86 as: 'Avatar',
86 required: false 87 required: false
87 } 88 }
88 ] 89 ]
diff --git a/server/models/account/actor-image.ts b/server/models/account/actor-image.ts
new file mode 100644
index 000000000..c532bd08d
--- /dev/null
+++ b/server/models/account/actor-image.ts
@@ -0,0 +1,86 @@
1import { remove } from 'fs-extra'
2import { join } from 'path'
3import { AfterDestroy, AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4import { MActorImageFormattable } from '@server/types/models'
5import { ActorImageType } from '@shared/models'
6import { ActorImage } from '../../../shared/models/actors/actor-image.model'
7import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
8import { logger } from '../../helpers/logger'
9import { CONFIG } from '../../initializers/config'
10import { LAZY_STATIC_PATHS } from '../../initializers/constants'
11import { throwIfNotValid } from '../utils'
12
13@Table({
14 tableName: 'actorImage',
15 indexes: [
16 {
17 fields: [ 'filename' ],
18 unique: true
19 }
20 ]
21})
22export class ActorImageModel extends Model {
23
24 @AllowNull(false)
25 @Column
26 filename: string
27
28 @AllowNull(true)
29 @Is('ActorImageFileUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'fileUrl', true))
30 @Column
31 fileUrl: string
32
33 @AllowNull(false)
34 @Column
35 onDisk: boolean
36
37 @AllowNull(false)
38 @Column
39 type: ActorImageType
40
41 @CreatedAt
42 createdAt: Date
43
44 @UpdatedAt
45 updatedAt: Date
46
47 @AfterDestroy
48 static removeFilesAndSendDelete (instance: ActorImageModel) {
49 logger.info('Removing actor image file %s.', instance.filename)
50
51 // Don't block the transaction
52 instance.removeImage()
53 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err))
54 }
55
56 static loadByName (filename: string) {
57 const query = {
58 where: {
59 filename
60 }
61 }
62
63 return ActorImageModel.findOne(query)
64 }
65
66 toFormattedJSON (this: MActorImageFormattable): ActorImage {
67 return {
68 path: this.getStaticPath(),
69 createdAt: this.createdAt,
70 updatedAt: this.updatedAt
71 }
72 }
73
74 getStaticPath () {
75 return join(LAZY_STATIC_PATHS.AVATARS, this.filename)
76 }
77
78 getPath () {
79 return join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
80 }
81
82 removeImage () {
83 const imagePath = join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
84 return remove(imagePath)
85 }
86}
diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts
index 25c523203..805095002 100644
--- a/server/models/account/user-notification.ts
+++ b/server/models/account/user-notification.ts
@@ -10,7 +10,6 @@ import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse'
10import { ActorModel } from '../activitypub/actor' 10import { ActorModel } from '../activitypub/actor'
11import { ActorFollowModel } from '../activitypub/actor-follow' 11import { ActorFollowModel } from '../activitypub/actor-follow'
12import { ApplicationModel } from '../application/application' 12import { ApplicationModel } from '../application/application'
13import { AvatarModel } from '../avatar/avatar'
14import { PluginModel } from '../server/plugin' 13import { PluginModel } from '../server/plugin'
15import { ServerModel } from '../server/server' 14import { ServerModel } from '../server/server'
16import { getSort, throwIfNotValid } from '../utils' 15import { getSort, throwIfNotValid } from '../utils'
@@ -20,6 +19,7 @@ import { VideoChannelModel } from '../video/video-channel'
20import { VideoCommentModel } from '../video/video-comment' 19import { VideoCommentModel } from '../video/video-comment'
21import { VideoImportModel } from '../video/video-import' 20import { VideoImportModel } from '../video/video-import'
22import { AccountModel } from './account' 21import { AccountModel } from './account'
22import { ActorImageModel } from './actor-image'
23import { UserModel } from './user' 23import { UserModel } from './user'
24 24
25enum ScopeNames { 25enum ScopeNames {
@@ -34,7 +34,8 @@ function buildActorWithAvatarInclude () {
34 include: [ 34 include: [
35 { 35 {
36 attributes: [ 'filename' ], 36 attributes: [ 'filename' ],
37 model: AvatarModel.unscoped(), 37 as: 'Avatar',
38 model: ActorImageModel.unscoped(),
38 required: false 39 required: false
39 }, 40 },
40 { 41 {
@@ -172,7 +173,8 @@ function buildAccountInclude (required: boolean, withActor = false) {
172 }, 173 },
173 { 174 {
174 attributes: [ 'filename' ], 175 attributes: [ 'filename' ],
175 model: AvatarModel.unscoped(), 176 as: 'Avatar',
177 model: ActorImageModel.unscoped(),
176 required: false 178 required: false
177 }, 179 },
178 { 180 {