diff options
-rw-r--r-- | server.ts | 4 | ||||
-rw-r--r-- | server/controllers/index.ts | 2 | ||||
-rw-r--r-- | server/controllers/misc.ts | 206 | ||||
-rw-r--r-- | server/controllers/static.ts | 271 | ||||
-rw-r--r-- | server/controllers/well-known.ts | 76 |
5 files changed, 291 insertions, 268 deletions
@@ -95,9 +95,11 @@ import { VideosPreviewCache, VideosCaptionCache } from './server/lib/files-cache | |||
95 | import { | 95 | import { |
96 | activityPubRouter, | 96 | activityPubRouter, |
97 | apiRouter, | 97 | apiRouter, |
98 | miscRouter, | ||
98 | clientsRouter, | 99 | clientsRouter, |
99 | feedsRouter, | 100 | feedsRouter, |
100 | staticRouter, | 101 | staticRouter, |
102 | wellKnownRouter, | ||
101 | lazyStaticRouter, | 103 | lazyStaticRouter, |
102 | servicesRouter, | 104 | servicesRouter, |
103 | liveRouter, | 105 | liveRouter, |
@@ -231,6 +233,8 @@ app.use('/', botsRouter) | |||
231 | 233 | ||
232 | // Static files | 234 | // Static files |
233 | app.use('/', staticRouter) | 235 | app.use('/', staticRouter) |
236 | app.use('/', wellKnownRouter) | ||
237 | app.use('/', miscRouter) | ||
234 | app.use('/', downloadRouter) | 238 | app.use('/', downloadRouter) |
235 | app.use('/', lazyStaticRouter) | 239 | app.use('/', lazyStaticRouter) |
236 | 240 | ||
diff --git a/server/controllers/index.ts b/server/controllers/index.ts index fa27ecec2..e8833d58c 100644 --- a/server/controllers/index.ts +++ b/server/controllers/index.ts | |||
@@ -7,7 +7,9 @@ export * from './services' | |||
7 | export * from './static' | 7 | export * from './static' |
8 | export * from './lazy-static' | 8 | export * from './lazy-static' |
9 | export * from './live' | 9 | export * from './live' |
10 | export * from './misc' | ||
10 | export * from './webfinger' | 11 | export * from './webfinger' |
11 | export * from './tracker' | 12 | export * from './tracker' |
12 | export * from './bots' | 13 | export * from './bots' |
13 | export * from './plugins' | 14 | export * from './plugins' |
15 | export * from './well-known' | ||
diff --git a/server/controllers/misc.ts b/server/controllers/misc.ts new file mode 100644 index 000000000..4c8af2adc --- /dev/null +++ b/server/controllers/misc.ts | |||
@@ -0,0 +1,206 @@ | |||
1 | import cors from 'cors' | ||
2 | import express from 'express' | ||
3 | import { CONFIG, isEmailEnabled } from '@server/initializers/config' | ||
4 | import { serveIndexHTML } from '@server/lib/client-html' | ||
5 | import { ServerConfigManager } from '@server/lib/server-config-manager' | ||
6 | import { HttpStatusCode } from '@shared/models' | ||
7 | import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' | ||
8 | import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION, ROUTE_CACHE_LIFETIME } from '../initializers/constants' | ||
9 | import { getThemeOrDefault } from '../lib/plugins/theme-utils' | ||
10 | import { asyncMiddleware } from '../middlewares' | ||
11 | import { cacheRoute } from '../middlewares/cache/cache' | ||
12 | import { UserModel } from '../models/user/user' | ||
13 | import { VideoModel } from '../models/video/video' | ||
14 | import { VideoCommentModel } from '../models/video/video-comment' | ||
15 | |||
16 | const miscRouter = express.Router() | ||
17 | |||
18 | miscRouter.use(cors()) | ||
19 | |||
20 | miscRouter.use('/nodeinfo/:version.json', | ||
21 | cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO), | ||
22 | asyncMiddleware(generateNodeinfo) | ||
23 | ) | ||
24 | |||
25 | // robots.txt service | ||
26 | miscRouter.get('/robots.txt', | ||
27 | cacheRoute(ROUTE_CACHE_LIFETIME.ROBOTS), | ||
28 | (_, res: express.Response) => { | ||
29 | res.type('text/plain') | ||
30 | |||
31 | return res.send(CONFIG.INSTANCE.ROBOTS) | ||
32 | } | ||
33 | ) | ||
34 | |||
35 | miscRouter.all('/teapot', | ||
36 | getCup, | ||
37 | asyncMiddleware(serveIndexHTML) | ||
38 | ) | ||
39 | |||
40 | // security.txt service | ||
41 | miscRouter.get('/security.txt', | ||
42 | (_, res: express.Response) => { | ||
43 | return res.redirect(HttpStatusCode.MOVED_PERMANENTLY_301, '/.well-known/security.txt') | ||
44 | } | ||
45 | ) | ||
46 | |||
47 | // --------------------------------------------------------------------------- | ||
48 | |||
49 | export { | ||
50 | miscRouter | ||
51 | } | ||
52 | |||
53 | // --------------------------------------------------------------------------- | ||
54 | |||
55 | async function generateNodeinfo (req: express.Request, res: express.Response) { | ||
56 | const { totalVideos } = await VideoModel.getStats() | ||
57 | const { totalLocalVideoComments } = await VideoCommentModel.getStats() | ||
58 | const { totalUsers, totalMonthlyActiveUsers, totalHalfYearActiveUsers } = await UserModel.getStats() | ||
59 | |||
60 | if (!req.params.version || req.params.version !== '2.0') { | ||
61 | return res.fail({ | ||
62 | status: HttpStatusCode.NOT_FOUND_404, | ||
63 | message: 'Nodeinfo schema version not handled' | ||
64 | }) | ||
65 | } | ||
66 | |||
67 | const json = { | ||
68 | version: '2.0', | ||
69 | software: { | ||
70 | name: 'peertube', | ||
71 | version: PEERTUBE_VERSION | ||
72 | }, | ||
73 | protocols: [ | ||
74 | 'activitypub' | ||
75 | ], | ||
76 | services: { | ||
77 | inbound: [], | ||
78 | outbound: [ | ||
79 | 'atom1.0', | ||
80 | 'rss2.0' | ||
81 | ] | ||
82 | }, | ||
83 | openRegistrations: CONFIG.SIGNUP.ENABLED, | ||
84 | usage: { | ||
85 | users: { | ||
86 | total: totalUsers, | ||
87 | activeMonth: totalMonthlyActiveUsers, | ||
88 | activeHalfyear: totalHalfYearActiveUsers | ||
89 | }, | ||
90 | localPosts: totalVideos, | ||
91 | localComments: totalLocalVideoComments | ||
92 | }, | ||
93 | metadata: { | ||
94 | taxonomy: { | ||
95 | postsName: 'Videos' | ||
96 | }, | ||
97 | nodeName: CONFIG.INSTANCE.NAME, | ||
98 | nodeDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
99 | nodeConfig: { | ||
100 | search: { | ||
101 | remoteUri: { | ||
102 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
103 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
104 | } | ||
105 | }, | ||
106 | plugin: { | ||
107 | registered: ServerConfigManager.Instance.getRegisteredPlugins() | ||
108 | }, | ||
109 | theme: { | ||
110 | registered: ServerConfigManager.Instance.getRegisteredThemes(), | ||
111 | default: getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
112 | }, | ||
113 | email: { | ||
114 | enabled: isEmailEnabled() | ||
115 | }, | ||
116 | contactForm: { | ||
117 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
118 | }, | ||
119 | transcoding: { | ||
120 | hls: { | ||
121 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
122 | }, | ||
123 | webtorrent: { | ||
124 | enabled: CONFIG.TRANSCODING.WEBTORRENT.ENABLED | ||
125 | }, | ||
126 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('vod') | ||
127 | }, | ||
128 | live: { | ||
129 | enabled: CONFIG.LIVE.ENABLED, | ||
130 | transcoding: { | ||
131 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
132 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('live') | ||
133 | } | ||
134 | }, | ||
135 | import: { | ||
136 | videos: { | ||
137 | http: { | ||
138 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
139 | }, | ||
140 | torrent: { | ||
141 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
142 | } | ||
143 | } | ||
144 | }, | ||
145 | autoBlacklist: { | ||
146 | videos: { | ||
147 | ofUsers: { | ||
148 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
149 | } | ||
150 | } | ||
151 | }, | ||
152 | avatar: { | ||
153 | file: { | ||
154 | size: { | ||
155 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
156 | }, | ||
157 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
158 | } | ||
159 | }, | ||
160 | video: { | ||
161 | image: { | ||
162 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
163 | size: { | ||
164 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
165 | } | ||
166 | }, | ||
167 | file: { | ||
168 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
169 | } | ||
170 | }, | ||
171 | videoCaption: { | ||
172 | file: { | ||
173 | size: { | ||
174 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
175 | }, | ||
176 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
177 | } | ||
178 | }, | ||
179 | user: { | ||
180 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
181 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
182 | }, | ||
183 | trending: { | ||
184 | videos: { | ||
185 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS | ||
186 | } | ||
187 | }, | ||
188 | tracker: { | ||
189 | enabled: CONFIG.TRACKER.ENABLED | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | } as HttpNodeinfoDiasporaSoftwareNsSchema20 | ||
194 | |||
195 | res.contentType('application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"') | ||
196 | .send(json) | ||
197 | .end() | ||
198 | } | ||
199 | |||
200 | function getCup (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
201 | res.status(HttpStatusCode.I_AM_A_TEAPOT_418) | ||
202 | res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1') | ||
203 | res.setHeader('Safe', 'if-sepia-awake') | ||
204 | |||
205 | return next() | ||
206 | } | ||
diff --git a/server/controllers/static.ts b/server/controllers/static.ts index 87bceba7a..7668ceb82 100644 --- a/server/controllers/static.ts +++ b/server/controllers/static.ts | |||
@@ -1,37 +1,13 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { join } from 'path' | 3 | import { CONFIG } from '../initializers/config' |
4 | import { serveIndexHTML } from '@server/lib/client-html' | 4 | import { HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers/constants' |
5 | import { ServerConfigManager } from '@server/lib/server-config-manager' | ||
6 | import { HttpStatusCode } from '@shared/models' | ||
7 | import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' | ||
8 | import { root } from '@shared/core-utils' | ||
9 | import { CONFIG, isEmailEnabled } from '../initializers/config' | ||
10 | import { | ||
11 | CONSTRAINTS_FIELDS, | ||
12 | DEFAULT_THEME_NAME, | ||
13 | HLS_STREAMING_PLAYLIST_DIRECTORY, | ||
14 | PEERTUBE_VERSION, | ||
15 | ROUTE_CACHE_LIFETIME, | ||
16 | STATIC_MAX_AGE, | ||
17 | STATIC_PATHS, | ||
18 | WEBSERVER | ||
19 | } from '../initializers/constants' | ||
20 | import { getThemeOrDefault } from '../lib/plugins/theme-utils' | ||
21 | import { asyncMiddleware } from '../middlewares' | ||
22 | import { cacheRoute } from '../middlewares/cache/cache' | ||
23 | import { UserModel } from '../models/user/user' | ||
24 | import { VideoModel } from '../models/video/video' | ||
25 | import { VideoCommentModel } from '../models/video/video-comment' | ||
26 | 5 | ||
27 | const staticRouter = express.Router() | 6 | const staticRouter = express.Router() |
28 | 7 | ||
8 | // Cors is very important to let other servers access torrent and video files | ||
29 | staticRouter.use(cors()) | 9 | staticRouter.use(cors()) |
30 | 10 | ||
31 | /* | ||
32 | Cors is very important to let other servers access torrent and video files | ||
33 | */ | ||
34 | |||
35 | // Videos path for webseed | 11 | // Videos path for webseed |
36 | staticRouter.use( | 12 | staticRouter.use( |
37 | STATIC_PATHS.WEBSEED, | 13 | STATIC_PATHS.WEBSEED, |
@@ -45,7 +21,6 @@ staticRouter.use( | |||
45 | // HLS | 21 | // HLS |
46 | staticRouter.use( | 22 | staticRouter.use( |
47 | STATIC_PATHS.STREAMING_PLAYLISTS.HLS, | 23 | STATIC_PATHS.STREAMING_PLAYLISTS.HLS, |
48 | cors(), | ||
49 | express.static(HLS_STREAMING_PLAYLIST_DIRECTORY, { fallthrough: false }) // 404 if the file does not exist | 24 | express.static(HLS_STREAMING_PLAYLIST_DIRECTORY, { fallthrough: false }) // 404 if the file does not exist |
50 | ) | 25 | ) |
51 | 26 | ||
@@ -56,248 +31,8 @@ staticRouter.use( | |||
56 | express.static(thumbnailsPhysicalPath, { maxAge: STATIC_MAX_AGE.SERVER, fallthrough: false }) // 404 if the file does not exist | 31 | express.static(thumbnailsPhysicalPath, { maxAge: STATIC_MAX_AGE.SERVER, fallthrough: false }) // 404 if the file does not exist |
57 | ) | 32 | ) |
58 | 33 | ||
59 | // robots.txt service | ||
60 | staticRouter.get('/robots.txt', | ||
61 | cacheRoute(ROUTE_CACHE_LIFETIME.ROBOTS), | ||
62 | (_, res: express.Response) => { | ||
63 | res.type('text/plain') | ||
64 | |||
65 | return res.send(CONFIG.INSTANCE.ROBOTS) | ||
66 | } | ||
67 | ) | ||
68 | |||
69 | staticRouter.all('/teapot', | ||
70 | getCup, | ||
71 | asyncMiddleware(serveIndexHTML) | ||
72 | ) | ||
73 | |||
74 | // security.txt service | ||
75 | staticRouter.get('/security.txt', | ||
76 | (_, res: express.Response) => { | ||
77 | return res.redirect(HttpStatusCode.MOVED_PERMANENTLY_301, '/.well-known/security.txt') | ||
78 | } | ||
79 | ) | ||
80 | |||
81 | staticRouter.get('/.well-known/security.txt', | ||
82 | cacheRoute(ROUTE_CACHE_LIFETIME.SECURITYTXT), | ||
83 | (_, res: express.Response) => { | ||
84 | res.type('text/plain') | ||
85 | return res.send(CONFIG.INSTANCE.SECURITYTXT + CONFIG.INSTANCE.SECURITYTXT_CONTACT) | ||
86 | } | ||
87 | ) | ||
88 | |||
89 | // nodeinfo service | ||
90 | staticRouter.use('/.well-known/nodeinfo', | ||
91 | cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO), | ||
92 | (_, res: express.Response) => { | ||
93 | return res.json({ | ||
94 | links: [ | ||
95 | { | ||
96 | rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0', | ||
97 | href: WEBSERVER.URL + '/nodeinfo/2.0.json' | ||
98 | } | ||
99 | ] | ||
100 | }) | ||
101 | } | ||
102 | ) | ||
103 | staticRouter.use('/nodeinfo/:version.json', | ||
104 | cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO), | ||
105 | asyncMiddleware(generateNodeinfo) | ||
106 | ) | ||
107 | |||
108 | // dnt-policy.txt service (see https://www.eff.org/dnt-policy) | ||
109 | staticRouter.use('/.well-known/dnt-policy.txt', | ||
110 | cacheRoute(ROUTE_CACHE_LIFETIME.DNT_POLICY), | ||
111 | (_, res: express.Response) => { | ||
112 | res.type('text/plain') | ||
113 | |||
114 | return res.sendFile(join(root(), 'dist/server/static/dnt-policy/dnt-policy-1.0.txt')) | ||
115 | } | ||
116 | ) | ||
117 | |||
118 | // dnt service (see https://www.w3.org/TR/tracking-dnt/#status-resource) | ||
119 | staticRouter.use('/.well-known/dnt/', | ||
120 | (_, res: express.Response) => { | ||
121 | res.json({ tracking: 'N' }) | ||
122 | } | ||
123 | ) | ||
124 | |||
125 | staticRouter.use('/.well-known/change-password', | ||
126 | (_, res: express.Response) => { | ||
127 | res.redirect('/my-account/settings') | ||
128 | } | ||
129 | ) | ||
130 | |||
131 | staticRouter.use('/.well-known/host-meta', | ||
132 | (_, res: express.Response) => { | ||
133 | res.type('application/xml') | ||
134 | |||
135 | const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
136 | '<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">\n' + | ||
137 | ` <Link rel="lrdd" type="application/xrd+xml" template="${WEBSERVER.URL}/.well-known/webfinger?resource={uri}"/>\n` + | ||
138 | '</XRD>' | ||
139 | |||
140 | res.send(xml).end() | ||
141 | } | ||
142 | ) | ||
143 | |||
144 | // --------------------------------------------------------------------------- | 34 | // --------------------------------------------------------------------------- |
145 | 35 | ||
146 | export { | 36 | export { |
147 | staticRouter | 37 | staticRouter |
148 | } | 38 | } |
149 | |||
150 | // --------------------------------------------------------------------------- | ||
151 | |||
152 | async function generateNodeinfo (req: express.Request, res: express.Response) { | ||
153 | const { totalVideos } = await VideoModel.getStats() | ||
154 | const { totalLocalVideoComments } = await VideoCommentModel.getStats() | ||
155 | const { totalUsers, totalMonthlyActiveUsers, totalHalfYearActiveUsers } = await UserModel.getStats() | ||
156 | |||
157 | if (!req.params.version || req.params.version !== '2.0') { | ||
158 | return res.fail({ | ||
159 | status: HttpStatusCode.NOT_FOUND_404, | ||
160 | message: 'Nodeinfo schema version not handled' | ||
161 | }) | ||
162 | } | ||
163 | |||
164 | const json = { | ||
165 | version: '2.0', | ||
166 | software: { | ||
167 | name: 'peertube', | ||
168 | version: PEERTUBE_VERSION | ||
169 | }, | ||
170 | protocols: [ | ||
171 | 'activitypub' | ||
172 | ], | ||
173 | services: { | ||
174 | inbound: [], | ||
175 | outbound: [ | ||
176 | 'atom1.0', | ||
177 | 'rss2.0' | ||
178 | ] | ||
179 | }, | ||
180 | openRegistrations: CONFIG.SIGNUP.ENABLED, | ||
181 | usage: { | ||
182 | users: { | ||
183 | total: totalUsers, | ||
184 | activeMonth: totalMonthlyActiveUsers, | ||
185 | activeHalfyear: totalHalfYearActiveUsers | ||
186 | }, | ||
187 | localPosts: totalVideos, | ||
188 | localComments: totalLocalVideoComments | ||
189 | }, | ||
190 | metadata: { | ||
191 | taxonomy: { | ||
192 | postsName: 'Videos' | ||
193 | }, | ||
194 | nodeName: CONFIG.INSTANCE.NAME, | ||
195 | nodeDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
196 | nodeConfig: { | ||
197 | search: { | ||
198 | remoteUri: { | ||
199 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
200 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
201 | } | ||
202 | }, | ||
203 | plugin: { | ||
204 | registered: ServerConfigManager.Instance.getRegisteredPlugins() | ||
205 | }, | ||
206 | theme: { | ||
207 | registered: ServerConfigManager.Instance.getRegisteredThemes(), | ||
208 | default: getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
209 | }, | ||
210 | email: { | ||
211 | enabled: isEmailEnabled() | ||
212 | }, | ||
213 | contactForm: { | ||
214 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
215 | }, | ||
216 | transcoding: { | ||
217 | hls: { | ||
218 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
219 | }, | ||
220 | webtorrent: { | ||
221 | enabled: CONFIG.TRANSCODING.WEBTORRENT.ENABLED | ||
222 | }, | ||
223 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('vod') | ||
224 | }, | ||
225 | live: { | ||
226 | enabled: CONFIG.LIVE.ENABLED, | ||
227 | transcoding: { | ||
228 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
229 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('live') | ||
230 | } | ||
231 | }, | ||
232 | import: { | ||
233 | videos: { | ||
234 | http: { | ||
235 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
236 | }, | ||
237 | torrent: { | ||
238 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
239 | } | ||
240 | } | ||
241 | }, | ||
242 | autoBlacklist: { | ||
243 | videos: { | ||
244 | ofUsers: { | ||
245 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
246 | } | ||
247 | } | ||
248 | }, | ||
249 | avatar: { | ||
250 | file: { | ||
251 | size: { | ||
252 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
253 | }, | ||
254 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
255 | } | ||
256 | }, | ||
257 | video: { | ||
258 | image: { | ||
259 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
260 | size: { | ||
261 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
262 | } | ||
263 | }, | ||
264 | file: { | ||
265 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
266 | } | ||
267 | }, | ||
268 | videoCaption: { | ||
269 | file: { | ||
270 | size: { | ||
271 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
272 | }, | ||
273 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
274 | } | ||
275 | }, | ||
276 | user: { | ||
277 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
278 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
279 | }, | ||
280 | trending: { | ||
281 | videos: { | ||
282 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS | ||
283 | } | ||
284 | }, | ||
285 | tracker: { | ||
286 | enabled: CONFIG.TRACKER.ENABLED | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | } as HttpNodeinfoDiasporaSoftwareNsSchema20 | ||
291 | |||
292 | res.contentType('application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"') | ||
293 | .send(json) | ||
294 | .end() | ||
295 | } | ||
296 | |||
297 | function getCup (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
298 | res.status(HttpStatusCode.I_AM_A_TEAPOT_418) | ||
299 | res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1') | ||
300 | res.setHeader('Safe', 'if-sepia-awake') | ||
301 | |||
302 | return next() | ||
303 | } | ||
diff --git a/server/controllers/well-known.ts b/server/controllers/well-known.ts new file mode 100644 index 000000000..f467bd629 --- /dev/null +++ b/server/controllers/well-known.ts | |||
@@ -0,0 +1,76 @@ | |||
1 | import cors from 'cors' | ||
2 | import express from 'express' | ||
3 | import { join } from 'path' | ||
4 | import { root } from '@shared/core-utils' | ||
5 | import { CONFIG } from '../initializers/config' | ||
6 | import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants' | ||
7 | import { cacheRoute } from '../middlewares/cache/cache' | ||
8 | |||
9 | const wellKnownRouter = express.Router() | ||
10 | |||
11 | wellKnownRouter.use(cors()) | ||
12 | |||
13 | wellKnownRouter.get('/.well-known/security.txt', | ||
14 | cacheRoute(ROUTE_CACHE_LIFETIME.SECURITYTXT), | ||
15 | (_, res: express.Response) => { | ||
16 | res.type('text/plain') | ||
17 | return res.send(CONFIG.INSTANCE.SECURITYTXT + CONFIG.INSTANCE.SECURITYTXT_CONTACT) | ||
18 | } | ||
19 | ) | ||
20 | |||
21 | // nodeinfo service | ||
22 | wellKnownRouter.use('/.well-known/nodeinfo', | ||
23 | cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO), | ||
24 | (_, res: express.Response) => { | ||
25 | return res.json({ | ||
26 | links: [ | ||
27 | { | ||
28 | rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0', | ||
29 | href: WEBSERVER.URL + '/nodeinfo/2.0.json' | ||
30 | } | ||
31 | ] | ||
32 | }) | ||
33 | } | ||
34 | ) | ||
35 | |||
36 | // dnt-policy.txt service (see https://www.eff.org/dnt-policy) | ||
37 | wellKnownRouter.use('/.well-known/dnt-policy.txt', | ||
38 | cacheRoute(ROUTE_CACHE_LIFETIME.DNT_POLICY), | ||
39 | (_, res: express.Response) => { | ||
40 | res.type('text/plain') | ||
41 | |||
42 | return res.sendFile(join(root(), 'dist/server/static/dnt-policy/dnt-policy-1.0.txt')) | ||
43 | } | ||
44 | ) | ||
45 | |||
46 | // dnt service (see https://www.w3.org/TR/tracking-dnt/#status-resource) | ||
47 | wellKnownRouter.use('/.well-known/dnt/', | ||
48 | (_, res: express.Response) => { | ||
49 | res.json({ tracking: 'N' }) | ||
50 | } | ||
51 | ) | ||
52 | |||
53 | wellKnownRouter.use('/.well-known/change-password', | ||
54 | (_, res: express.Response) => { | ||
55 | res.redirect('/my-account/settings') | ||
56 | } | ||
57 | ) | ||
58 | |||
59 | wellKnownRouter.use('/.well-known/host-meta', | ||
60 | (_, res: express.Response) => { | ||
61 | res.type('application/xml') | ||
62 | |||
63 | const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + | ||
64 | '<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">\n' + | ||
65 | ` <Link rel="lrdd" type="application/xrd+xml" template="${WEBSERVER.URL}/.well-known/webfinger?resource={uri}"/>\n` + | ||
66 | '</XRD>' | ||
67 | |||
68 | res.send(xml).end() | ||
69 | } | ||
70 | ) | ||
71 | |||
72 | // --------------------------------------------------------------------------- | ||
73 | |||
74 | export { | ||
75 | wellKnownRouter | ||
76 | } | ||