diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 211ac3342..d97d23180 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -117,7 +117,16 @@ export class ClientHtml {
const schemaType = 'VideoObject'
customHtml = ClientHtml.addTags(customHtml, {
- url, originUrl, siteName, title, description, image, embed, ogType, twitterCard, schemaType
+ url,
+ originUrl,
+ siteName,
+ title,
+ description,
+ image,
+ embed,
+ ogType,
+ twitterCard,
+ schemaType
})
return customHtml
@@ -168,7 +177,17 @@ export class ClientHtml {
const schemaType = 'ItemList'
customHtml = ClientHtml.addTags(customHtml, {
- url, originUrl, siteName, embed, title, description, image, list, ogType, twitterCard, schemaType
+ url,
+ originUrl,
+ siteName,
+ embed,
+ title,
+ description,
+ image,
+ list,
+ ogType,
+ twitterCard,
+ schemaType
})
return customHtml
@@ -216,7 +235,7 @@ export class ClientHtml {
let customHtml = ClientHtml.addTitleTag(html, escapeHTML(entity.getDisplayName()))
customHtml = ClientHtml.addDescriptionTag(customHtml, escapeHTML(entity.description))
- const url = entity.Actor.url
+ const url = entity.getLocalUrl()
const originUrl = entity.Actor.url
const siteName = escapeHTML(CONFIG.INSTANCE.NAME)
const title = escapeHTML(entity.getDisplayName())
@@ -232,7 +251,17 @@ export class ClientHtml {
const twitterCard = 'summary'
const schemaType = 'ProfilePage'
- customHtml = ClientHtml.addTags(customHtml, { url, originUrl, title, siteName, description, image, ogType, twitterCard, schemaType })
+ customHtml = ClientHtml.addTags(customHtml, {
+ url,
+ originUrl,
+ title,
+ siteName,
+ description,
+ image,
+ ogType,
+ twitterCard,
+ schemaType
+ })
return customHtml
}
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index 1162643be..8c244d432 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -1,3 +1,5 @@
+import * as Bluebird from 'bluebird'
+import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
import {
AllowNull,
BeforeDestroy,
@@ -15,27 +17,33 @@ import {
Table,
UpdatedAt
} from 'sequelize-typescript'
+import { ModelCache } from '@server/models/model-cache'
import { Account, AccountSummary } from '../../../shared/models/actors'
import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts'
+import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
import { sendDeleteActor } from '../../lib/activitypub/send'
+import {
+ MAccount,
+ MAccountActor,
+ MAccountAP,
+ MAccountDefault,
+ MAccountFormattable,
+ MAccountSummaryFormattable,
+ MChannelActor
+} from '../../types/models'
import { ActorModel } from '../activitypub/actor'
+import { ActorFollowModel } from '../activitypub/actor-follow'
import { ApplicationModel } from '../application/application'
+import { AvatarModel } from '../avatar/avatar'
import { ServerModel } from '../server/server'
+import { ServerBlocklistModel } from '../server/server-blocklist'
import { getSort, throwIfNotValid } from '../utils'
+import { VideoModel } from '../video/video'
import { VideoChannelModel } from '../video/video-channel'
import { VideoCommentModel } from '../video/video-comment'
-import { UserModel } from './user'
-import { AvatarModel } from '../avatar/avatar'
import { VideoPlaylistModel } from '../video/video-playlist'
-import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
-import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
import { AccountBlocklistModel } from './account-blocklist'
-import { ServerBlocklistModel } from '../server/server-blocklist'
-import { ActorFollowModel } from '../activitypub/actor-follow'
-import { MAccountActor, MAccountAP, MAccountDefault, MAccountFormattable, MAccountSummaryFormattable, MAccount } from '../../types/models'
-import * as Bluebird from 'bluebird'
-import { ModelCache } from '@server/models/model-cache'
-import { VideoModel } from '../video/video'
+import { UserModel } from './user'
export enum ScopeNames {
SUMMARY = 'SUMMARY'
@@ -441,6 +449,10 @@ export class AccountModel extends Model {
return this.name
}
+ getLocalUrl (this: MAccountActor | MChannelActor) {
+ return WEBSERVER.URL + `/accounts/` + this.Actor.preferredUsername
+ }
+
isBlocked () {
return this.BlockedAccounts && this.BlockedAccounts.length !== 0
}
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 202dc513f..0c8aef18f 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -18,6 +18,7 @@ import {
Table,
UpdatedAt
} from 'sequelize-typescript'
+import { MAccountActor } from '@server/types/models'
import { ActivityPubActor } from '../../../shared/models/activitypub'
import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos'
import {
@@ -628,6 +629,10 @@ export class VideoChannelModel extends Model {
})
}
+ getLocalUrl (this: MAccountActor | MChannelActor) {
+ return WEBSERVER.URL + `/video-channels/` + this.Actor.preferredUsername
+ }
+
getDisplayName () {
return this.name
}
diff --git a/server/tests/client.ts b/server/tests/client.ts
index 7bcb999ea..7572fd34a 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -8,20 +8,21 @@ import {
addVideoInPlaylist,
cleanupTests,
createVideoPlaylist,
+ doubleFollow,
+ flushAndRunMultipleServers,
getAccount,
getCustomConfig,
getVideosList,
makeHTMLRequest,
ServerInfo,
+ setAccessTokensToServers,
setDefaultVideoChannel,
updateCustomConfig,
updateCustomSubConfig,
- uploadVideo,
updateMyUser,
updateVideoChannel,
- doubleFollow,
- flushAndRunMultipleServers,
- setAccessTokensToServers
+ uploadVideo,
+ waitJobs
} from '../../shared/extra-utils'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
@@ -35,10 +36,7 @@ function checkIndexTags (html: string, title: string, description: string, css:
describe('Test a client controllers', function () {
let servers: ServerInfo[] = []
- let server: ServerInfo
let account: Account
- let videoUUID: string
- let videoOriginalUrl: string
const videoName = 'my super name for server 1'
const videoDescription = 'my super description for server 1'
@@ -53,32 +51,25 @@ describe('Test a client controllers', function () {
this.timeout(120000)
servers = await flushAndRunMultipleServers(2)
- const server = servers[0]
await setAccessTokensToServers(servers)
- {
- const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
- videoUUID = res.body.video.uuid
- videoOriginalUrl = res.body.video.url
- }
-
await doubleFollow(servers[0], servers[1])
- await setDefaultVideoChannel([ server ])
+ await setDefaultVideoChannel(servers)
- await updateVideoChannel(server.url, server.accessToken, server.videoChannel.name, { description: channelDescription })
+ await updateVideoChannel(servers[0].url, servers[0].accessToken, servers[0].videoChannel.name, { description: channelDescription })
// Video
const videoAttributes = { name: videoName, description: videoDescription }
- await uploadVideo(server.url, server.accessToken, videoAttributes)
+ await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
- const resVideosRequest = await getVideosList(server.url)
+ const resVideosRequest = await getVideosList(servers[0].url)
const videos = resVideosRequest.body.data
expect(videos.length).to.equal(1)
- server.video = videos[0]
+ servers[0].video = videos[0]
// Playlist
@@ -86,54 +77,56 @@ describe('Test a client controllers', function () {
displayName: playlistName,
description: playlistDescription,
privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.videoChannel.id
+ videoChannelId: servers[0].videoChannel.id
}
- const resVideoPlaylistRequest = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs })
+ const resVideoPlaylistRequest = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs })
const playlist = resVideoPlaylistRequest.body.videoPlaylist
const playlistId = playlist.id
playlistUUID = playlist.uuid
await addVideoInPlaylist({
- url: server.url,
- token: server.accessToken,
+ url: servers[0].url,
+ token: servers[0].accessToken,
playlistId,
- elementAttrs: { videoId: server.video.id }
+ elementAttrs: { videoId: servers[0].video.id }
})
// Account
- await updateMyUser({ url: server.url, accessToken: server.accessToken, description: 'my account description' })
+ await updateMyUser({ url: servers[0].url, accessToken: servers[0].accessToken, description: 'my account description' })
- const resAccountRequest = await getAccount(server.url, `${server.user.username}@${server.host}`)
+ const resAccountRequest = await getAccount(servers[0].url, `${servers[0].user.username}@${servers[0].host}`)
account = resAccountRequest.body
+
+ await waitJobs(servers)
})
describe('oEmbed', function () {
it('Should have valid oEmbed discovery tags for videos', async function () {
- const path = '/videos/watch/' + server.video.uuid
- const res = await request(server.url)
+ const path = '/videos/watch/' + servers[0].video.uuid
+ const res = await request(servers[0].url)
.get(path)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
- const port = server.port
+ const port = servers[0].port
const expectedLink = '`
+ `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2F${servers[0].video.uuid}" ` +
+ `title="${servers[0].video.name}" />`
expect(res.text).to.contain(expectedLink)
})
it('Should have valid oEmbed discovery tags for a playlist', async function () {
- const res = await request(server.url)
+ const res = await request(servers[0].url)
.get('/videos/watch/playlist/' + playlistUUID)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
- const port = server.port
+ const port = servers[0].port
const expectedLink = '`)
expect(res.text).to.contain(``)
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
})
it('Should have valid Open Graph tags on the channel page', async function () {
- const res = await request(server.url)
- .get('/video-channels/' + server.videoChannel.name)
+ const res = await request(servers[0].url)
+ .get('/video-channels/' + servers[0].videoChannel.name)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
expect(res.text).to.contain(``)
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
})
it('Should have valid Open Graph tags on the watch page with video id', async function () {
- const res = await request(server.url)
- .get('/videos/watch/' + server.video.id)
+ const res = await request(servers[0].url)
+ .get('/videos/watch/' + servers[0].video.id)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
expect(res.text).to.contain(``)
expect(res.text).to.contain(``)
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
})
it('Should have valid Open Graph tags on the watch page with video uuid', async function () {
- const res = await request(server.url)
- .get('/videos/watch/' + server.video.uuid)
+ const res = await request(servers[0].url)
+ .get('/videos/watch/' + servers[0].video.uuid)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
expect(res.text).to.contain(``)
expect(res.text).to.contain(``)
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
})
it('Should have valid Open Graph tags on the watch playlist page', async function () {
- const res = await request(server.url)
+ const res = await request(servers[0].url)
.get('/videos/watch/playlist/' + playlistUUID)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -202,15 +195,15 @@ describe('Test a client controllers', function () {
expect(res.text).to.contain(``)
expect(res.text).to.contain(``)
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
})
})
describe('Twitter card', async function () {
it('Should have valid twitter card on the watch video page', async function () {
- const res = await request(server.url)
- .get('/videos/watch/' + server.video.uuid)
+ const res = await request(servers[0].url)
+ .get('/videos/watch/' + servers[0].video.uuid)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -221,7 +214,7 @@ describe('Test a client controllers', function () {
})
it('Should have valid twitter card on the watch playlist page', async function () {
- const res = await request(server.url)
+ const res = await request(servers[0].url)
.get('/videos/watch/playlist/' + playlistUUID)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -233,7 +226,7 @@ describe('Test a client controllers', function () {
})
it('Should have valid twitter card on the account page', async function () {
- const res = await request(server.url)
+ const res = await request(servers[0].url)
.get('/accounts/' + account.name)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -245,35 +238,35 @@ describe('Test a client controllers', function () {
})
it('Should have valid twitter card on the channel page', async function () {
- const res = await request(server.url)
- .get('/video-channels/' + server.videoChannel.name)
+ const res = await request(servers[0].url)
+ .get('/video-channels/' + servers[0].videoChannel.name)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
expect(res.text).to.contain('')
expect(res.text).to.contain('')
- expect(res.text).to.contain(``)
+ expect(res.text).to.contain(``)
expect(res.text).to.contain(``)
})
it('Should have valid twitter card if Twitter is whitelisted', async function () {
- const res1 = await getCustomConfig(server.url, server.accessToken)
+ const res1 = await getCustomConfig(servers[0].url, servers[0].accessToken)
const config = res1.body
config.services.twitter = {
username: '@Kuja',
whitelisted: true
}
- await updateCustomConfig(server.url, server.accessToken, config)
+ await updateCustomConfig(servers[0].url, servers[0].accessToken, config)
- const resVideoRequest = await request(server.url)
- .get('/videos/watch/' + server.video.uuid)
+ const resVideoRequest = await request(servers[0].url)
+ .get('/videos/watch/' + servers[0].video.uuid)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
expect(resVideoRequest.text).to.contain('')
expect(resVideoRequest.text).to.contain('')
- const resVideoPlaylistRequest = await request(server.url)
+ const resVideoPlaylistRequest = await request(servers[0].url)
.get('/videos/watch/playlist/' + playlistUUID)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -281,7 +274,7 @@ describe('Test a client controllers', function () {
expect(resVideoPlaylistRequest.text).to.contain('')
expect(resVideoPlaylistRequest.text).to.contain('')
- const resAccountRequest = await request(server.url)
+ const resAccountRequest = await request(servers[0].url)
.get('/accounts/' + account.name)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -289,8 +282,8 @@ describe('Test a client controllers', function () {
expect(resAccountRequest.text).to.contain('')
expect(resAccountRequest.text).to.contain('')
- const resChannelRequest = await request(server.url)
- .get('/video-channels/' + server.videoChannel.name)
+ const resChannelRequest = await request(servers[0].url)
+ .get('/video-channels/' + servers[0].videoChannel.name)
.set('Accept', 'text/html')
.expect(HttpStatusCode.OK_200)
@@ -302,14 +295,14 @@ describe('Test a client controllers', function () {
describe('Index HTML', function () {
it('Should have valid index html tags (title, description...)', async function () {
- const res = await makeHTMLRequest(server.url, '/videos/trending')
+ const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
checkIndexTags(res.text, 'PeerTube', description, '')
})
it('Should update the customized configuration and have the correct index html tags', async function () {
- await updateCustomSubConfig(server.url, server.accessToken, {
+ await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
instance: {
name: 'PeerTube updated',
shortDescription: 'my short description',
@@ -324,24 +317,39 @@ describe('Test a client controllers', function () {
}
})
- const res = await makeHTMLRequest(server.url, '/videos/trending')
+ const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
})
it('Should have valid index html updated tags (title, description...)', async function () {
- const res = await makeHTMLRequest(server.url, '/videos/trending')
+ const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
})
it('Should use the original video URL for the canonical tag', async function () {
- const res = await makeHTMLRequest(servers[1].url, '/videos/watch/' + videoUUID)
- expect(res.text).to.contain(``)
+ const res = await makeHTMLRequest(servers[1].url, '/videos/watch/' + servers[0].video.uuid)
+ expect(res.text).to.contain(``)
+ })
+
+ it('Should use the original account URL for the canonical tag', async function () {
+ const res = await makeHTMLRequest(servers[1].url, '/accounts/root@' + servers[0].host)
+ expect(res.text).to.contain(``)
+ })
+
+ it('Should use the original channel URL for the canonical tag', async function () {
+ const res = await makeHTMLRequest(servers[1].url, '/video-channels/root_channel@' + servers[0].host)
+ expect(res.text).to.contain(``)
+ })
+
+ it('Should use the original playlist URL for the canonical tag', async function () {
+ const res = await makeHTMLRequest(servers[1].url, '/videos/watch/playlist/' + playlistUUID)
+ expect(res.text).to.contain(``)
})
})
after(async function () {
- await cleanupTests([ server ])
+ await cleanupTests(servers)
})
})
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index 4ad3eb14a..e88482e49 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -42,6 +42,7 @@ interface ServerInfo {
id: number
uuid: string
name?: string
+ url?: string
account?: {
name: string
}