]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/actor/actor-image.ts
Fix upload avatar button
[github/Chocobozzz/PeerTube.git] / server / models / actor / actor-image.ts
CommitLineData
f4796856 1import { remove } from 'fs-extra'
c5911fd3 2import { join } from 'path'
d0800f76 3import {
4 AfterDestroy,
5 AllowNull,
6 BelongsTo,
7 Column,
8 CreatedAt,
9 Default,
10 ForeignKey,
11 Is,
12 Model,
13 Table,
14 UpdatedAt
15} from 'sequelize-typescript'
16import { MActorImage, MActorImageFormattable } from '@server/types/models'
17import { getLowercaseExtension } from '@shared/core-utils'
18import { ActivityIconObject, ActorImageType } from '@shared/models'
6b5f72be 19import { AttributesOnly } from '@shared/typescript-utils'
f4796856
C
20import { ActorImage } from '../../../shared/models/actors/actor-image.model'
21import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
8e0fd45e 22import { logger } from '../../helpers/logger'
6dd9de95 23import { CONFIG } from '../../initializers/config'
d0800f76 24import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants'
557b13ae 25import { throwIfNotValid } from '../utils'
d0800f76 26import { ActorModel } from './actor'
2295ce6c 27
3fd3ab2d 28@Table({
f4796856 29 tableName: 'actorImage',
557b13ae
C
30 indexes: [
31 {
32 fields: [ 'filename' ],
33 unique: true
d0800f76 34 },
35 {
36 fields: [ 'actorId', 'type', 'width' ],
37 unique: true
557b13ae
C
38 }
39 ]
3fd3ab2d 40})
16c016e8 41export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageModel>>> {
2295ce6c 42
3fd3ab2d
C
43 @AllowNull(false)
44 @Column
45 filename: string
2295ce6c 46
84531547
C
47 @AllowNull(true)
48 @Default(null)
49 @Column
50 height: number
51
52 @AllowNull(true)
53 @Default(null)
54 @Column
55 width: number
56
557b13ae 57 @AllowNull(true)
f4796856 58 @Is('ActorImageFileUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'fileUrl', true))
557b13ae
C
59 @Column
60 fileUrl: string
61
62 @AllowNull(false)
63 @Column
64 onDisk: boolean
65
f4796856
C
66 @AllowNull(false)
67 @Column
68 type: ActorImageType
69
3fd3ab2d
C
70 @CreatedAt
71 createdAt: Date
2295ce6c 72
3fd3ab2d
C
73 @UpdatedAt
74 updatedAt: Date
c5911fd3 75
d0800f76 76 @ForeignKey(() => ActorModel)
77 @Column
78 actorId: number
79
80 @BelongsTo(() => ActorModel, {
81 foreignKey: {
82 allowNull: false
83 },
84 onDelete: 'CASCADE'
85 })
86 Actor: ActorModel
87
c5911fd3 88 @AfterDestroy
f4796856
C
89 static removeFilesAndSendDelete (instance: ActorImageModel) {
90 logger.info('Removing actor image file %s.', instance.filename)
ecf3f060
C
91
92 // Don't block the transaction
f4796856
C
93 instance.removeImage()
94 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, err))
c5911fd3
C
95 }
96
557b13ae
C
97 static loadByName (filename: string) {
98 const query = {
99 where: {
100 filename
101 }
102 }
103
f4796856 104 return ActorImageModel.findOne(query)
557b13ae
C
105 }
106
d0800f76 107 static getImageUrl (image: MActorImage) {
108 if (!image) return undefined
109
110 return WEBSERVER.URL + image.getStaticPath()
111 }
112
f4796856 113 toFormattedJSON (this: MActorImageFormattable): ActorImage {
c5911fd3 114 return {
d0800f76 115 width: this.width,
557b13ae 116 path: this.getStaticPath(),
c5911fd3
C
117 createdAt: this.createdAt,
118 updatedAt: this.updatedAt
119 }
120 }
121
d0800f76 122 toActivityPubObject (): ActivityIconObject {
123 const extension = getLowercaseExtension(this.filename)
124
125 return {
126 type: 'Image',
127 mediaType: MIMETYPES.IMAGE.EXT_MIMETYPE[extension],
128 height: this.height,
129 width: this.width,
130 url: ActorImageModel.getImageUrl(this)
cdeddff1 131 }
d0800f76 132 }
cdeddff1 133
d0800f76 134 getStaticPath () {
135 switch (this.type) {
136 case ActorImageType.AVATAR:
137 return join(LAZY_STATIC_PATHS.AVATARS, this.filename)
138
139 case ActorImageType.BANNER:
140 return join(LAZY_STATIC_PATHS.BANNERS, this.filename)
141 }
557b13ae
C
142 }
143
144 getPath () {
f4796856 145 return join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
c5911fd3
C
146 }
147
f4796856
C
148 removeImage () {
149 const imagePath = join(CONFIG.STORAGE.ACTOR_IMAGES, this.filename)
150 return remove(imagePath)
c5911fd3 151 }
79db409a
C
152
153 isOwned () {
154 return !this.fileUrl
155 }
2295ce6c 156}