]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/activitypub/account.ts
Move models to typescript-sequelize
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / account.ts
CommitLineData
0f91ae62 1import * as Bluebird from 'bluebird'
0f91ae62 2import { Transaction } from 'sequelize'
3fd3ab2d
C
3import * as url from 'url'
4import { ActivityPubActor } from '../../../shared/models/activitypub'
5import { doRequest, logger, retryTransactionWrapper } from '../../helpers'
6import { isRemoteAccountValid } from '../../helpers/custom-validators/activitypub'
7import { ACTIVITY_PUB, sequelizeTypescript } from '../../initializers'
8import { AccountModel } from '../../models/account/account'
9import { ServerModel } from '../../models/server/server'
892211e8 10
0f91ae62 11async function getOrCreateAccountAndServer (accountUrl: string) {
3fd3ab2d 12 let account = await AccountModel.loadByUrl(accountUrl)
892211e8
C
13
14 // We don't have this account in our database, fetch it on remote
15 if (!account) {
0f91ae62
C
16 account = await fetchRemoteAccount(accountUrl)
17 if (account === undefined) throw new Error('Cannot fetch remote account.')
892211e8 18
0f91ae62
C
19 const options = {
20 arguments: [ account ],
21 errorMessage: 'Cannot save account and server with many retries.'
22 }
23 account = await retryTransactionWrapper(saveAccountAndServerIfNotExist, options)
892211e8
C
24 }
25
26 return account
27}
28
3fd3ab2d 29function saveAccountAndServerIfNotExist (account: AccountModel, t?: Transaction): Bluebird<AccountModel> | Promise<AccountModel> {
0f91ae62
C
30 if (t !== undefined) {
31 return save(t)
32 } else {
3fd3ab2d 33 return sequelizeTypescript.transaction(t => {
0f91ae62
C
34 return save(t)
35 })
36 }
37
38 async function save (t: Transaction) {
39 const accountHost = url.parse(account.url).host
40
41 const serverOptions = {
42 where: {
43 host: accountHost
44 },
45 defaults: {
46 host: accountHost
47 },
48 transaction: t
49 }
3fd3ab2d 50 const [ server ] = await ServerModel.findOrCreate(serverOptions)
0f91ae62
C
51
52 // Save our new account in database
53 account.set('serverId', server.id)
54 account = await account.save({ transaction: t })
55
56 return account
57 }
58}
59
60async function fetchRemoteAccount (accountUrl: string) {
892211e8
C
61 const options = {
62 uri: accountUrl,
63 method: 'GET',
64 headers: {
65 'Accept': ACTIVITY_PUB.ACCEPT_HEADER
66 }
67 }
68
69 logger.info('Fetching remote account %s.', accountUrl)
70
71 let requestResult
72 try {
73 requestResult = await doRequest(options)
74 } catch (err) {
75 logger.warn('Cannot fetch remote account %s.', accountUrl, err)
76 return undefined
77 }
78
79 const accountJSON: ActivityPubActor = JSON.parse(requestResult.body)
80 if (isRemoteAccountValid(accountJSON) === false) {
81 logger.debug('Remote account JSON is not valid.', { accountJSON })
82 return undefined
83 }
84
85 const followersCount = await fetchAccountCount(accountJSON.followers)
86 const followingCount = await fetchAccountCount(accountJSON.following)
87
3fd3ab2d 88 return new AccountModel({
892211e8
C
89 uuid: accountJSON.uuid,
90 name: accountJSON.preferredUsername,
91 url: accountJSON.url,
92 publicKey: accountJSON.publicKey.publicKeyPem,
93 privateKey: null,
94 followersCount: followersCount,
95 followingCount: followingCount,
96 inboxUrl: accountJSON.inbox,
97 outboxUrl: accountJSON.outbox,
98 sharedInboxUrl: accountJSON.endpoints.sharedInbox,
99 followersUrl: accountJSON.followers,
100 followingUrl: accountJSON.following
101 })
892211e8
C
102}
103
104export {
0f91ae62
C
105 getOrCreateAccountAndServer,
106 fetchRemoteAccount,
107 saveAccountAndServerIfNotExist
892211e8
C
108}
109
110// ---------------------------------------------------------------------------
111
112async function fetchAccountCount (url: string) {
113 const options = {
114 uri: url,
115 method: 'GET'
116 }
117
118 let requestResult
119 try {
120 requestResult = await doRequest(options)
121 } catch (err) {
122 logger.warn('Cannot fetch remote account count %s.', url, err)
123 return undefined
124 }
125
126 return requestResult.totalItems ? requestResult.totalItems : 0
127}