diff options
Diffstat (limited to 'server/controllers/api/users/me.ts')
-rw-r--r-- | server/controllers/api/users/me.ts | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts new file mode 100644 index 000000000..1e096a35d --- /dev/null +++ b/server/controllers/api/users/me.ts | |||
@@ -0,0 +1,215 @@ | |||
1 | import * as express from 'express' | ||
2 | import 'multer' | ||
3 | import { UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared' | ||
4 | import { getFormattedObjects } from '../../../helpers/utils' | ||
5 | import { CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../../initializers' | ||
6 | import { sendUpdateActor } from '../../../lib/activitypub/send' | ||
7 | import { | ||
8 | asyncMiddleware, | ||
9 | authenticate, | ||
10 | paginationValidator, | ||
11 | setDefaultPagination, | ||
12 | setDefaultSort, | ||
13 | usersUpdateMeValidator, | ||
14 | usersVideoRatingValidator | ||
15 | } from '../../../middlewares' | ||
16 | import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' | ||
17 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | ||
18 | import { UserModel } from '../../../models/account/user' | ||
19 | import { VideoModel } from '../../../models/video/video' | ||
20 | import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' | ||
21 | import { createReqFiles } from '../../../helpers/express-utils' | ||
22 | import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' | ||
23 | import { updateAvatarValidator } from '../../../middlewares/validators/avatar' | ||
24 | import { updateActorAvatarFile } from '../../../lib/avatar' | ||
25 | import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' | ||
26 | import { VideoImportModel } from '../../../models/video/video-import' | ||
27 | |||
28 | const auditLogger = auditLoggerFactory('users-me') | ||
29 | |||
30 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) | ||
31 | |||
32 | const meRouter = express.Router() | ||
33 | |||
34 | meRouter.get('/me', | ||
35 | authenticate, | ||
36 | asyncMiddleware(getUserInformation) | ||
37 | ) | ||
38 | meRouter.delete('/me', | ||
39 | authenticate, | ||
40 | asyncMiddleware(deleteMeValidator), | ||
41 | asyncMiddleware(deleteMe) | ||
42 | ) | ||
43 | |||
44 | meRouter.get('/me/video-quota-used', | ||
45 | authenticate, | ||
46 | asyncMiddleware(getUserVideoQuotaUsed) | ||
47 | ) | ||
48 | |||
49 | meRouter.get('/me/videos/imports', | ||
50 | authenticate, | ||
51 | paginationValidator, | ||
52 | videoImportsSortValidator, | ||
53 | setDefaultSort, | ||
54 | setDefaultPagination, | ||
55 | asyncMiddleware(getUserVideoImports) | ||
56 | ) | ||
57 | |||
58 | meRouter.get('/me/videos', | ||
59 | authenticate, | ||
60 | paginationValidator, | ||
61 | videosSortValidator, | ||
62 | setDefaultSort, | ||
63 | setDefaultPagination, | ||
64 | asyncMiddleware(getUserVideos) | ||
65 | ) | ||
66 | |||
67 | meRouter.get('/me/videos/:videoId/rating', | ||
68 | authenticate, | ||
69 | asyncMiddleware(usersVideoRatingValidator), | ||
70 | asyncMiddleware(getUserVideoRating) | ||
71 | ) | ||
72 | |||
73 | meRouter.put('/me', | ||
74 | authenticate, | ||
75 | usersUpdateMeValidator, | ||
76 | asyncMiddleware(updateMe) | ||
77 | ) | ||
78 | |||
79 | meRouter.post('/me/avatar/pick', | ||
80 | authenticate, | ||
81 | reqAvatarFile, | ||
82 | updateAvatarValidator, | ||
83 | asyncMiddleware(updateMyAvatar) | ||
84 | ) | ||
85 | |||
86 | // --------------------------------------------------------------------------- | ||
87 | |||
88 | export { | ||
89 | meRouter | ||
90 | } | ||
91 | |||
92 | // --------------------------------------------------------------------------- | ||
93 | |||
94 | async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
95 | const user = res.locals.oauth.token.User as UserModel | ||
96 | const resultList = await VideoModel.listUserVideosForApi( | ||
97 | user.Account.id, | ||
98 | req.query.start as number, | ||
99 | req.query.count as number, | ||
100 | req.query.sort as VideoSortField | ||
101 | ) | ||
102 | |||
103 | const additionalAttributes = { | ||
104 | waitTranscoding: true, | ||
105 | state: true, | ||
106 | scheduledUpdate: true, | ||
107 | blacklistInfo: true | ||
108 | } | ||
109 | return res.json(getFormattedObjects(resultList.data, resultList.total, { additionalAttributes })) | ||
110 | } | ||
111 | |||
112 | async function getUserVideoImports (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
113 | const user = res.locals.oauth.token.User as UserModel | ||
114 | const resultList = await VideoImportModel.listUserVideoImportsForApi( | ||
115 | user.id, | ||
116 | req.query.start as number, | ||
117 | req.query.count as number, | ||
118 | req.query.sort | ||
119 | ) | ||
120 | |||
121 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
122 | } | ||
123 | |||
124 | async function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
125 | // We did not load channels in res.locals.user | ||
126 | const user = await UserModel.loadByUsernameAndPopulateChannels(res.locals.oauth.token.user.username) | ||
127 | |||
128 | return res.json(user.toFormattedJSON()) | ||
129 | } | ||
130 | |||
131 | async function getUserVideoQuotaUsed (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
132 | // We did not load channels in res.locals.user | ||
133 | const user = await UserModel.loadByUsernameAndPopulateChannels(res.locals.oauth.token.user.username) | ||
134 | const videoQuotaUsed = await UserModel.getOriginalVideoFileTotalFromUser(user) | ||
135 | |||
136 | const data: UserVideoQuota = { | ||
137 | videoQuotaUsed | ||
138 | } | ||
139 | return res.json(data) | ||
140 | } | ||
141 | |||
142 | async function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
143 | const videoId = +req.params.videoId | ||
144 | const accountId = +res.locals.oauth.token.User.Account.id | ||
145 | |||
146 | const ratingObj = await AccountVideoRateModel.load(accountId, videoId, null) | ||
147 | const rating = ratingObj ? ratingObj.type : 'none' | ||
148 | |||
149 | const json: FormattedUserVideoRate = { | ||
150 | videoId, | ||
151 | rating | ||
152 | } | ||
153 | res.json(json) | ||
154 | } | ||
155 | |||
156 | async function deleteMe (req: express.Request, res: express.Response) { | ||
157 | const user: UserModel = res.locals.oauth.token.User | ||
158 | |||
159 | await user.destroy() | ||
160 | |||
161 | auditLogger.delete(res.locals.oauth.token.User.Account.Actor.getIdentifier(), new UserAuditView(user.toFormattedJSON())) | ||
162 | |||
163 | return res.sendStatus(204) | ||
164 | } | ||
165 | |||
166 | async function updateMe (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
167 | const body: UserUpdateMe = req.body | ||
168 | |||
169 | const user: UserModel = res.locals.oauth.token.user | ||
170 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) | ||
171 | |||
172 | if (body.password !== undefined) user.password = body.password | ||
173 | if (body.email !== undefined) user.email = body.email | ||
174 | if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy | ||
175 | if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo | ||
176 | |||
177 | await sequelizeTypescript.transaction(async t => { | ||
178 | await user.save({ transaction: t }) | ||
179 | |||
180 | if (body.displayName !== undefined) user.Account.name = body.displayName | ||
181 | if (body.description !== undefined) user.Account.description = body.description | ||
182 | await user.Account.save({ transaction: t }) | ||
183 | |||
184 | await sendUpdateActor(user.Account, t) | ||
185 | |||
186 | auditLogger.update( | ||
187 | res.locals.oauth.token.User.Account.Actor.getIdentifier(), | ||
188 | new UserAuditView(user.toFormattedJSON()), | ||
189 | oldUserAuditView | ||
190 | ) | ||
191 | }) | ||
192 | |||
193 | return res.sendStatus(204) | ||
194 | } | ||
195 | |||
196 | async function updateMyAvatar (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
197 | const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] | ||
198 | const user: UserModel = res.locals.oauth.token.user | ||
199 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) | ||
200 | const account = user.Account | ||
201 | |||
202 | const avatar = await updateActorAvatarFile(avatarPhysicalFile, account.Actor, account) | ||
203 | |||
204 | auditLogger.update( | ||
205 | res.locals.oauth.token.User.Account.Actor.getIdentifier(), | ||
206 | new UserAuditView(user.toFormattedJSON()), | ||
207 | oldUserAuditView | ||
208 | ) | ||
209 | |||
210 | return res | ||
211 | .json({ | ||
212 | avatar: avatar.toFormattedJSON() | ||
213 | }) | ||
214 | .end() | ||
215 | } | ||