user only sync and new images
BIN
defaultPublicFiles/img/faq/script-1.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
defaultPublicFiles/img/faq/script-2.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
defaultPublicFiles/img/faq/script-3.jpg
Executable file
After Width: | Height: | Size: 24 KiB |
BIN
defaultPublicFiles/img/faq/script-4.jpg
Executable file
After Width: | Height: | Size: 22 KiB |
BIN
defaultPublicFiles/img/faq/script-5.jpg
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
defaultPublicFiles/img/faq/script-6.jpg
Normal file
After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
BIN
defaultPublicFiles/img/scriptimg/script-5.jpg
Normal file
After Width: | Height: | Size: 9.7 KiB |
|
@ -324,14 +324,14 @@ async function authAndGetNewData({
|
||||||
peers,
|
peers,
|
||||||
peer,
|
peer,
|
||||||
selfInfo,
|
selfInfo,
|
||||||
lastSyncWithPeer,
|
|
||||||
}: {
|
}: {
|
||||||
peers: PeerInfo[]
|
peers: PeerInfo[]
|
||||||
peer: PeerInfo
|
peer: PeerInfo
|
||||||
selfInfo: PeerInfo
|
selfInfo: PeerInfo
|
||||||
lastSyncWithPeer: number
|
|
||||||
}): Promise<GetResult<SyncDataRes & { peer: PeerInfo }>> {
|
}): Promise<GetResult<SyncDataRes & { peer: PeerInfo }>> {
|
||||||
let sessionCookie = peer.sessionCookie
|
let sessionCookie = peer.sessionCookie
|
||||||
|
const lastSyncWithPeer = peer.lastSync || 0
|
||||||
|
const lastUsersSyncWithPeer = peer.lastUsersSync || 0
|
||||||
|
|
||||||
if (!sessionCookie) {
|
if (!sessionCookie) {
|
||||||
const loginResult = await loginToPeer(peer)
|
const loginResult = await loginToPeer(peer)
|
||||||
|
@ -358,7 +358,11 @@ async function authAndGetNewData({
|
||||||
port: peer.port,
|
port: peer.port,
|
||||||
path: `/api/getnewdatasince?host=${encodeURIComponent(
|
path: `/api/getnewdatasince?host=${encodeURIComponent(
|
||||||
peerToString(selfInfo)
|
peerToString(selfInfo)
|
||||||
)}${lastSyncWithPeer ? `&since=${lastSyncWithPeer}` : ''}`,
|
)}${lastSyncWithPeer ? `&since=${lastSyncWithPeer}` : ''}${
|
||||||
|
lastUsersSyncWithPeer
|
||||||
|
? `&usersSince=${lastUsersSyncWithPeer}`
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
},
|
},
|
||||||
peer.http
|
peer.http
|
||||||
)
|
)
|
||||||
|
@ -591,7 +595,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncData() {
|
async function syncData(usersOnly?: boolean) {
|
||||||
if (peers.length === 0) {
|
if (peers.length === 0) {
|
||||||
logger.Log(
|
logger.Log(
|
||||||
`There are no peers specified in ${paths.peersFile}, aborting sync`,
|
`There are no peers specified in ${paths.peersFile}, aborting sync`,
|
||||||
|
@ -607,6 +611,9 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
peers.length
|
peers.length
|
||||||
}${logger.C()} peers`
|
}${logger.C()} peers`
|
||||||
)
|
)
|
||||||
|
if (usersOnly) {
|
||||||
|
logger.Log(`\tSyncing users only!`, 'yellowbg')
|
||||||
|
}
|
||||||
|
|
||||||
const lastSync = selfInfo.lastSync
|
const lastSync = selfInfo.lastSync
|
||||||
logger.Log(
|
logger.Log(
|
||||||
|
@ -628,13 +635,10 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
})
|
})
|
||||||
|
|
||||||
const requests = peers.map((peer) => {
|
const requests = peers.map((peer) => {
|
||||||
const lastSyncWithPeer = peer.lastSync || 0
|
|
||||||
|
|
||||||
return authAndGetNewData({
|
return authAndGetNewData({
|
||||||
peers: peers,
|
peers: peers,
|
||||||
peer: peer,
|
peer: peer,
|
||||||
selfInfo: selfInfo,
|
selfInfo: selfInfo,
|
||||||
lastSyncWithPeer: lastSyncWithPeer,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -683,7 +687,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
|
|
||||||
if (questionCount > 0) {
|
if (questionCount > 0) {
|
||||||
resultDataWithoutEmptyDbs.push(res)
|
resultDataWithoutEmptyDbs.push(res)
|
||||||
} else {
|
} else if (!usersOnly) {
|
||||||
updatePeersFile(peers, {
|
updatePeersFile(peers, {
|
||||||
...res.peer,
|
...res.peer,
|
||||||
lastSync: syncStart,
|
lastSync: syncStart,
|
||||||
|
@ -748,6 +752,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
try {
|
try {
|
||||||
resultData.forEach((res) => {
|
resultData.forEach((res) => {
|
||||||
if (res.encryptedUsers) {
|
if (res.encryptedUsers) {
|
||||||
|
let addedUserCount = 0
|
||||||
const decryptedUsers: User[] = JSON.parse(
|
const decryptedUsers: User[] = JSON.parse(
|
||||||
decrypt(privateKey, res.encryptedUsers)
|
decrypt(privateKey, res.encryptedUsers)
|
||||||
)
|
)
|
||||||
|
@ -758,6 +763,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
pw: remoteUser.pw,
|
pw: remoteUser.pw,
|
||||||
})
|
})
|
||||||
if (localUser.length === 0) {
|
if (localUser.length === 0) {
|
||||||
|
addedUserCount += 1
|
||||||
// FIXME: users will not have consistend id across servers. This may be
|
// FIXME: users will not have consistend id across servers. This may be
|
||||||
// harmless, will see
|
// harmless, will see
|
||||||
dbtools.Insert(userDB, 'users', {
|
dbtools.Insert(userDB, 'users', {
|
||||||
|
@ -767,8 +773,12 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
resultsCount[peerToString(res.peer)] = {
|
resultsCount[peerToString(res.peer)] = {
|
||||||
newUsers: decryptedUsers.length,
|
newUsers: addedUserCount,
|
||||||
}
|
}
|
||||||
|
updatePeersFile(peers, {
|
||||||
|
...res.peer,
|
||||||
|
lastUsersSync: syncStart,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -794,6 +804,40 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usersOnly) {
|
||||||
|
if (Object.keys(resultsCount).length === 0) {
|
||||||
|
logger.Log('No new users received')
|
||||||
|
} else {
|
||||||
|
logger.logTable(
|
||||||
|
[
|
||||||
|
['', 'Users'],
|
||||||
|
['Old', oldUserCount],
|
||||||
|
...Object.entries(resultsCount).map(([key, result]) => {
|
||||||
|
return [key, result.newUsers]
|
||||||
|
}),
|
||||||
|
['Added total', newUserCount - oldUserCount],
|
||||||
|
['Final', newUserCount],
|
||||||
|
],
|
||||||
|
{ colWidth: [15], rowPrefix: '\t' }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
logger.Log(
|
||||||
|
`Sync successfully finished! Synced users only.`,
|
||||||
|
'green'
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
old: {
|
||||||
|
oldUserCount: oldUserCount,
|
||||||
|
},
|
||||||
|
added: {
|
||||||
|
totalNewUers: newUserCount - oldUserCount,
|
||||||
|
},
|
||||||
|
final: {
|
||||||
|
newUserCount: newUserCount,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------
|
||||||
// backup
|
// backup
|
||||||
// -------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------
|
||||||
|
@ -930,6 +974,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
oldQuestionCount: oldQuestionCount,
|
oldQuestionCount: oldQuestionCount,
|
||||||
},
|
},
|
||||||
added: {
|
added: {
|
||||||
|
totalNewUers: newUsers,
|
||||||
totalNewQdbs: totalNewQdbs,
|
totalNewQdbs: totalNewQdbs,
|
||||||
totalNewSubjects: totalNewSubjects,
|
totalNewSubjects: totalNewSubjects,
|
||||||
totalNewQuestions: totalNewQuestions,
|
totalNewQuestions: totalNewQuestions,
|
||||||
|
@ -962,34 +1007,41 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
// a getNewDataSince() call per question db
|
// a getNewDataSince() call per question db
|
||||||
logger.LogReq(req)
|
logger.LogReq(req)
|
||||||
const since = Number.isNaN(+req.query.since) ? 0 : +req.query.since
|
const since = Number.isNaN(+req.query.since) ? 0 : +req.query.since
|
||||||
|
const usersSince = Number.isNaN(+req.query.usersSince)
|
||||||
|
? 0
|
||||||
|
: +req.query.usersSince
|
||||||
const remoteHost = req.query.host
|
const remoteHost = req.query.host
|
||||||
|
const usersOnly = !!req.query.usersOnly
|
||||||
const questionDbsWithNewQuestions = Number.isNaN(since)
|
|
||||||
? getQuestionDbs()
|
|
||||||
: getQuestionDbs()
|
|
||||||
.map((qdb) => {
|
|
||||||
return {
|
|
||||||
...qdb,
|
|
||||||
data: getNewDataSince(qdb.data, since),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter((qdb) => {
|
|
||||||
const { questionCount: questionCount } = countOfQdb(qdb)
|
|
||||||
return questionCount > 0
|
|
||||||
})
|
|
||||||
|
|
||||||
const { subjCount: subjects, questionCount: questions } = countOfQdbs(
|
|
||||||
questionDbsWithNewQuestions
|
|
||||||
)
|
|
||||||
|
|
||||||
const result: SyncDataRes = {
|
const result: SyncDataRes = {
|
||||||
questionDbs: questionDbsWithNewQuestions,
|
remoteInfo: getSelfInfo(),
|
||||||
count: {
|
}
|
||||||
|
|
||||||
|
if (!usersOnly) {
|
||||||
|
const questionDbsWithNewQuestions = Number.isNaN(since)
|
||||||
|
? getQuestionDbs()
|
||||||
|
: getQuestionDbs()
|
||||||
|
.map((qdb) => {
|
||||||
|
return {
|
||||||
|
...qdb,
|
||||||
|
data: getNewDataSince(qdb.data, since),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter((qdb) => {
|
||||||
|
const { questionCount: questionCount } =
|
||||||
|
countOfQdb(qdb)
|
||||||
|
return questionCount > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const { subjCount: subjects, questionCount: questions } =
|
||||||
|
countOfQdbs(questionDbsWithNewQuestions)
|
||||||
|
|
||||||
|
result.questionDbs = questionDbsWithNewQuestions
|
||||||
|
result.count = {
|
||||||
qdbs: questionDbsWithNewQuestions.length,
|
qdbs: questionDbsWithNewQuestions.length,
|
||||||
subjects: subjects,
|
subjects: subjects,
|
||||||
questions: questions,
|
questions: questions,
|
||||||
},
|
}
|
||||||
remoteInfo: getSelfInfo(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let hostToLog = remoteHost || 'Unknown host'
|
let hostToLog = remoteHost || 'Unknown host'
|
||||||
|
@ -1003,7 +1055,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
const remotePublicKey = remotePeerInfo?.publicKey
|
const remotePublicKey = remotePeerInfo?.publicKey
|
||||||
if (remotePublicKey) {
|
if (remotePublicKey) {
|
||||||
// FIXME: sign data?
|
// FIXME: sign data?
|
||||||
const newUsers = getNewUsersSince(since)
|
const newUsers = getNewUsersSince(usersSince)
|
||||||
sentUsers = newUsers.length
|
sentUsers = newUsers.length
|
||||||
result.encryptedUsers = encrypt(
|
result.encryptedUsers = encrypt(
|
||||||
remotePublicKey,
|
remotePublicKey,
|
||||||
|
@ -1040,40 +1092,60 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateToLog = Number.isNaN(since)
|
const usersSinceDate = Number.isNaN(since)
|
||||||
? 'all time'
|
? 'all time'
|
||||||
: new Date(since).toLocaleString()
|
: new Date(since).toLocaleString()
|
||||||
|
|
||||||
logger.Log(
|
if (usersOnly) {
|
||||||
`\tSending new data to ${logger.C(
|
logger.Log('Sending users only!', 'yellowbg')
|
||||||
'blue'
|
logger.Log(
|
||||||
)}${hostToLog}${logger.C()} since ${logger.C(
|
`\tSending new users to ${logger.C(
|
||||||
'blue'
|
'blue'
|
||||||
)}${dateToLog}${logger.C()} `
|
)}${hostToLog}${logger.C()} since ${logger.C(
|
||||||
)
|
'blue'
|
||||||
logger.logTable(
|
)}${usersSinceDate}${logger.C()}. Sent users: ${logger.C(
|
||||||
[
|
'blue'
|
||||||
['Users', 'QDBs', 'Subjs', 'Questions'],
|
)}${sentUsers}${logger.C()}`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const dateToLog = Number.isNaN(since)
|
||||||
|
? 'all time'
|
||||||
|
: new Date(since).toLocaleString()
|
||||||
|
|
||||||
|
logger.Log(
|
||||||
|
`\tSending new data to ${logger.C(
|
||||||
|
'blue'
|
||||||
|
)}${hostToLog}${logger.C()} since ${logger.C(
|
||||||
|
'blue'
|
||||||
|
)}${dateToLog}${logger.C()}, and new users since ${logger.C(
|
||||||
|
'blue'
|
||||||
|
)}${usersSinceDate}${logger.C()}`
|
||||||
|
)
|
||||||
|
logger.logTable(
|
||||||
[
|
[
|
||||||
sentUsers,
|
['Users', 'QDBs', 'Subjs', 'Questions'],
|
||||||
questionDbsWithNewQuestions.length,
|
[
|
||||||
subjects,
|
sentUsers,
|
||||||
questions,
|
result.questionDbs.length,
|
||||||
|
result.count.subjects,
|
||||||
|
result.count.questions,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
{ rowPrefix: '\t' }
|
||||||
{ rowPrefix: '\t' }
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
res.json(result)
|
res.json(result)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/syncp2pdata', (req: Request, res: Response) => {
|
app.get('/syncp2pdata', (req: Request, res: Response) => {
|
||||||
logger.LogReq(req)
|
logger.LogReq(req)
|
||||||
|
const usersOnly = !!req.query.usersOnly
|
||||||
const user = req.session.user
|
const user = req.session.user
|
||||||
if (!user || user.id !== 1) {
|
if (!user || user.id !== 1) {
|
||||||
res.json({
|
res.json({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
msg: 'only user 1 can call this EP',
|
message: 'only user 1 can call this EP',
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1160,7 @@ function setup(data: SubmoduleData): Submodule {
|
||||||
|
|
||||||
syncInProgress = true
|
syncInProgress = true
|
||||||
setPendingJobsAlertCount(5000)
|
setPendingJobsAlertCount(5000)
|
||||||
syncData()
|
syncData(usersOnly)
|
||||||
.then((syncResult) => {
|
.then((syncResult) => {
|
||||||
res.json({
|
res.json({
|
||||||
msg: 'sync successfull',
|
msg: 'sync successfull',
|
||||||
|
|
|
@ -177,6 +177,7 @@ export interface PeerInfo {
|
||||||
pw?: string
|
pw?: string
|
||||||
sessionCookie?: string
|
sessionCookie?: string
|
||||||
lastSync?: number
|
lastSync?: number
|
||||||
|
lastUsersSync?: number
|
||||||
note?: string
|
note?: string
|
||||||
http?: boolean
|
http?: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ export const PeerInfoSchema: Schema = {
|
||||||
...PeerInfoSchemaBase,
|
...PeerInfoSchemaBase,
|
||||||
properties: {
|
properties: {
|
||||||
...PeerInfoSchemaBase.properties,
|
...PeerInfoSchemaBase.properties,
|
||||||
|
lastUsersSync: { type: 'number' },
|
||||||
publicKey: { type: 'string' },
|
publicKey: { type: 'string' },
|
||||||
pw: { type: 'string' },
|
pw: { type: 'string' },
|
||||||
sessionCookie: { type: 'string' },
|
sessionCookie: { type: 'string' },
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit aad2822226c6fc039ee190581b0eaa55f2859dc9
|
Subproject commit 898326c3a061e786d9ff8cf437059db34da50504
|