-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathparatii.core.users.js
170 lines (160 loc) · 5.61 KB
/
paratii.core.users.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
const joi = require('joi')
/**
* Utilities to create and manipulate information about the users on the blockchain.
* @param {ParatiiConfigSchema} config configuration object to initialize Paratii object
* @example let paratii = new Paratii()
* paratii.users // <- this is an instance of ParatiiUsers
*/
export class ParatiiUsers {
constructor (config) {
// const schema = joi.object({
// 'db.provider': joi.string().default(null)
// }).unknown()
//
// const result = joi.validate(config, schema)
// // const error = result.error
// if (error) throw error
this.config = config
}
/**
* @typedef {Array} userSchema
* @property {string} id the Ethereum address of the user
* @property {string=} name
* @property {string=} email
*/
/**
* Creates a user, fields id, name and email go to the smart contract Users, other fields are stored on IPFS.
* @param {userSchema} options information about the video ( id, name, email ... )
* @return {Promise} the id of the newly created user
* @example let userData = {
* id: '0x12456....',
* name: 'Humbert Humbert',
* email: 'humbert@humbert.ru',
* ipfsData: 'some-hash'
* }
* let result = await paratii.eth.users.create(userData)
* })
*/
async create (options) {
// FIXME: do some joi validation here
const paratii = this.config.paratii
let keysForBlockchain = ['id', 'name']
let optionsKeys = Object.keys(options)
let optionsBlockchain = {}
let optionsIpfs = {}
optionsKeys.forEach(function (key) {
if (keysForBlockchain.includes(key)) {
optionsBlockchain[key] = options[key]
} else {
optionsIpfs[key] = options[key]
}
})
let hash = await paratii.ipfs.local.addJSON(optionsIpfs)
optionsBlockchain['ipfsData'] = hash
// FIXME: add error handling if call to db fails.
if (options.email !== undefined) {
await paratii.db.users.setEmail(options.id, options.email)
}
return paratii.eth.users.create(optionsBlockchain)
}
/**
* Update the information of the user if the user already exists, otherwise it creates it
* @param {Object} options user informations
* @return {Promise} updated/new user informations
* @example let userData = {
* id: '0x12456....',
* name: 'Humbert Humbert',
* email: 'humbert@humbert.ru',
* ipfsData: 'some-hash'
* }
* let result = await paratii.eth.users.upsert(userData)
* })
*/
async upsert (options) {
let data = null
let userId = ''
if (options.id) {
userId = options.id
data = await this.get(userId)
}
if (!data) {
return this.create(options)
} else {
delete options.id
return this.update(userId, options, data)
}
}
/**
* retrieve data about the user
* @param {string} id user univocal id
* @return {Object} data about the user
* @example paratii.users.get('some-user-id')
*/
get (id) {
return this.config.paratii.db.users.get(id)
}
/**
* Updates a user's details. name and email are defined in the smart contract Users, other fields get written to IPFS.
* @param {string} userId user univocal id
* @param {UserSchema} options updated data i.e. { name: 'A new user name' }
* @return {Promise} updated data about the user
* @example let updatedData = await paratii.users.update('some-user-id', {name: 'A new user name'})
*/
async update (userId, options) {
const schema = joi.object({
name: joi.string().default(null).empty(''),
email: joi.string().default(null).empty('')
})
const result = joi.validate(options, schema)
const error = result.error
if (error) throw error
options = result.value
let data = await this.get(userId)
for (let key in options) {
if (options[key] !== null) {
data[key] = options[key]
}
}
data['id'] = userId
await this.create(data)
return data
}
/**
* migrate all contract data for paratii.config.account to a new account
* @param newAccount Address of new account
* @private
*/
async migrateAccount (newAccount) {
// migrate the videos
const paratii = this.config.paratii
const oldAccount = this.config.paratii.getAccount()
const search = await paratii.vids.search({owner: oldAccount})
const vids = search && search.results
const originalUserRecord = await paratii.eth.users.get(oldAccount)
const newUserRecord = originalUserRecord
newUserRecord.id = newAccount
await paratii.eth.users.create(newUserRecord)
if (vids) {
for (let i = 0; i < vids.length; i++) {
const vid = vids[i]
let videoId = vid.id || vid._id
await paratii.vids.update(videoId, {owner: newAccount})
let didVideoApply = await paratii.eth.tcr.appWasMade(videoId)
if (didVideoApply) {
// removing video from stake
let isWhitelisted = await paratii.eth.tcr.isWhitelisted(videoId)
if (isWhitelisted) {
await paratii.eth.tcr.exit(videoId)
} else {
// video applied but not yet whitelisted....
// TODO : figure out if it can be updated (listed or not)
}
}
}
}
// transfer all PTI to the new account
let ptiBalance = await paratii.eth.balanceOf(oldAccount, 'PTI')
await paratii.eth.transfer(newAccount, ptiBalance, 'PTI')
// FIXME: need to call tc.apply(vid.id) with newAccount as sender (how to do that?)
}
}