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, | ||||
|     peer, | ||||
|     selfInfo, | ||||
|     lastSyncWithPeer, | ||||
| }: { | ||||
|     peers: PeerInfo[] | ||||
|     peer: PeerInfo | ||||
|     selfInfo: PeerInfo | ||||
|     lastSyncWithPeer: number | ||||
| }): Promise<GetResult<SyncDataRes & { peer: PeerInfo }>> { | ||||
|     let sessionCookie = peer.sessionCookie | ||||
|     const lastSyncWithPeer = peer.lastSync || 0 | ||||
|     const lastUsersSyncWithPeer = peer.lastUsersSync || 0 | ||||
|  | ||||
|     if (!sessionCookie) { | ||||
|         const loginResult = await loginToPeer(peer) | ||||
| @@ -358,7 +358,11 @@ async function authAndGetNewData({ | ||||
|                 port: peer.port, | ||||
|                 path: `/api/getnewdatasince?host=${encodeURIComponent( | ||||
|                     peerToString(selfInfo) | ||||
|                 )}${lastSyncWithPeer ? `&since=${lastSyncWithPeer}` : ''}`, | ||||
|                 )}${lastSyncWithPeer ? `&since=${lastSyncWithPeer}` : ''}${ | ||||
|                     lastUsersSyncWithPeer | ||||
|                         ? `&usersSince=${lastUsersSyncWithPeer}` | ||||
|                         : '' | ||||
|                 }`, | ||||
|             }, | ||||
|             peer.http | ||||
|         ) | ||||
| @@ -591,7 +595,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async function syncData() { | ||||
|     async function syncData(usersOnly?: boolean) { | ||||
|         if (peers.length === 0) { | ||||
|             logger.Log( | ||||
|                 `There are no peers specified in ${paths.peersFile}, aborting sync`, | ||||
| @@ -607,6 +611,9 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                 peers.length | ||||
|             }${logger.C()} peers` | ||||
|         ) | ||||
|         if (usersOnly) { | ||||
|             logger.Log(`\tSyncing users only!`, 'yellowbg') | ||||
|         } | ||||
|  | ||||
|         const lastSync = selfInfo.lastSync | ||||
|         logger.Log( | ||||
| @@ -628,13 +635,10 @@ function setup(data: SubmoduleData): Submodule { | ||||
|         }) | ||||
|  | ||||
|         const requests = peers.map((peer) => { | ||||
|             const lastSyncWithPeer = peer.lastSync || 0 | ||||
|  | ||||
|             return authAndGetNewData({ | ||||
|                 peers: peers, | ||||
|                 peer: peer, | ||||
|                 selfInfo: selfInfo, | ||||
|                 lastSyncWithPeer: lastSyncWithPeer, | ||||
|             }) | ||||
|         }) | ||||
|  | ||||
| @@ -683,7 +687,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|  | ||||
|             if (questionCount > 0) { | ||||
|                 resultDataWithoutEmptyDbs.push(res) | ||||
|             } else { | ||||
|             } else if (!usersOnly) { | ||||
|                 updatePeersFile(peers, { | ||||
|                     ...res.peer, | ||||
|                     lastSync: syncStart, | ||||
| @@ -748,6 +752,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|         try { | ||||
|             resultData.forEach((res) => { | ||||
|                 if (res.encryptedUsers) { | ||||
|                     let addedUserCount = 0 | ||||
|                     const decryptedUsers: User[] = JSON.parse( | ||||
|                         decrypt(privateKey, res.encryptedUsers) | ||||
|                     ) | ||||
| @@ -758,6 +763,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                             pw: remoteUser.pw, | ||||
|                         }) | ||||
|                         if (localUser.length === 0) { | ||||
|                             addedUserCount += 1 | ||||
|                             // FIXME: users will not have consistend id across servers. This may be | ||||
|                             // harmless, will see | ||||
|                             dbtools.Insert(userDB, 'users', { | ||||
| @@ -767,8 +773,12 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                         } | ||||
|                     }) | ||||
|                     resultsCount[peerToString(res.peer)] = { | ||||
|                         newUsers: decryptedUsers.length, | ||||
|                         newUsers: addedUserCount, | ||||
|                     } | ||||
|                     updatePeersFile(peers, { | ||||
|                         ...res.peer, | ||||
|                         lastUsersSync: syncStart, | ||||
|                     }) | ||||
|                 } | ||||
|             }) | ||||
|         } 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 | ||||
|         // ------------------------------------------------------------------------------------------------------- | ||||
| @@ -930,6 +974,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                 oldQuestionCount: oldQuestionCount, | ||||
|             }, | ||||
|             added: { | ||||
|                 totalNewUers: newUsers, | ||||
|                 totalNewQdbs: totalNewQdbs, | ||||
|                 totalNewSubjects: totalNewSubjects, | ||||
|                 totalNewQuestions: totalNewQuestions, | ||||
| @@ -962,8 +1007,17 @@ function setup(data: SubmoduleData): Submodule { | ||||
|         // a getNewDataSince() call per question db | ||||
|         logger.LogReq(req) | ||||
|         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 usersOnly = !!req.query.usersOnly | ||||
|  | ||||
|         const result: SyncDataRes = { | ||||
|             remoteInfo: getSelfInfo(), | ||||
|         } | ||||
|  | ||||
|         if (!usersOnly) { | ||||
|             const questionDbsWithNewQuestions = Number.isNaN(since) | ||||
|                 ? getQuestionDbs() | ||||
|                 : getQuestionDbs() | ||||
| @@ -974,22 +1028,20 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                           } | ||||
|                       }) | ||||
|                       .filter((qdb) => { | ||||
|                       const { questionCount: questionCount } = countOfQdb(qdb) | ||||
|                           const { questionCount: questionCount } = | ||||
|                               countOfQdb(qdb) | ||||
|                           return questionCount > 0 | ||||
|                       }) | ||||
|  | ||||
|         const { subjCount: subjects, questionCount: questions } = countOfQdbs( | ||||
|             questionDbsWithNewQuestions | ||||
|         ) | ||||
|             const { subjCount: subjects, questionCount: questions } = | ||||
|                 countOfQdbs(questionDbsWithNewQuestions) | ||||
|  | ||||
|         const result: SyncDataRes = { | ||||
|             questionDbs: questionDbsWithNewQuestions, | ||||
|             count: { | ||||
|             result.questionDbs = questionDbsWithNewQuestions | ||||
|             result.count = { | ||||
|                 qdbs: questionDbsWithNewQuestions.length, | ||||
|                 subjects: subjects, | ||||
|                 questions: questions, | ||||
|             }, | ||||
|             remoteInfo: getSelfInfo(), | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let hostToLog = remoteHost || 'Unknown host' | ||||
| @@ -1003,7 +1055,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                 const remotePublicKey = remotePeerInfo?.publicKey | ||||
|                 if (remotePublicKey) { | ||||
|                     // FIXME: sign data? | ||||
|                     const newUsers = getNewUsersSince(since) | ||||
|                     const newUsers = getNewUsersSince(usersSince) | ||||
|                     sentUsers = newUsers.length | ||||
|                     result.encryptedUsers = encrypt( | ||||
|                         remotePublicKey, | ||||
| @@ -1040,6 +1092,22 @@ function setup(data: SubmoduleData): Submodule { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         const usersSinceDate = Number.isNaN(since) | ||||
|             ? 'all time' | ||||
|             : new Date(since).toLocaleString() | ||||
|  | ||||
|         if (usersOnly) { | ||||
|             logger.Log('Sending users only!', 'yellowbg') | ||||
|             logger.Log( | ||||
|                 `\tSending new users to ${logger.C( | ||||
|                     'blue' | ||||
|                 )}${hostToLog}${logger.C()} since  ${logger.C( | ||||
|                     'blue' | ||||
|                 )}${usersSinceDate}${logger.C()}. Sent users: ${logger.C( | ||||
|                     'blue' | ||||
|                 )}${sentUsers}${logger.C()}` | ||||
|             ) | ||||
|         } else { | ||||
|             const dateToLog = Number.isNaN(since) | ||||
|                 ? 'all time' | ||||
|                 : new Date(since).toLocaleString() | ||||
| @@ -1049,31 +1117,35 @@ function setup(data: SubmoduleData): Submodule { | ||||
|                     'blue' | ||||
|                 )}${hostToLog}${logger.C()} since ${logger.C( | ||||
|                     'blue' | ||||
|             )}${dateToLog}${logger.C()} ` | ||||
|                 )}${dateToLog}${logger.C()}, and new users since ${logger.C( | ||||
|                     'blue' | ||||
|                 )}${usersSinceDate}${logger.C()}` | ||||
|             ) | ||||
|             logger.logTable( | ||||
|                 [ | ||||
|                     ['Users', 'QDBs', 'Subjs', 'Questions'], | ||||
|                     [ | ||||
|                         sentUsers, | ||||
|                     questionDbsWithNewQuestions.length, | ||||
|                     subjects, | ||||
|                     questions, | ||||
|                         result.questionDbs.length, | ||||
|                         result.count.subjects, | ||||
|                         result.count.questions, | ||||
|                     ], | ||||
|                 ], | ||||
|                 { rowPrefix: '\t' } | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         res.json(result) | ||||
|     }) | ||||
|  | ||||
|     app.get('/syncp2pdata', (req: Request, res: Response) => { | ||||
|         logger.LogReq(req) | ||||
|         const usersOnly = !!req.query.usersOnly | ||||
|         const user = req.session.user | ||||
|         if (!user || user.id !== 1) { | ||||
|             res.json({ | ||||
|                 status: 'error', | ||||
|                 msg: 'only user 1 can call this EP', | ||||
|                 message: 'only user 1 can call this EP', | ||||
|             }) | ||||
|             return | ||||
|         } | ||||
| @@ -1088,7 +1160,7 @@ function setup(data: SubmoduleData): Submodule { | ||||
|  | ||||
|         syncInProgress = true | ||||
|         setPendingJobsAlertCount(5000) | ||||
|         syncData() | ||||
|         syncData(usersOnly) | ||||
|             .then((syncResult) => { | ||||
|                 res.json({ | ||||
|                     msg: 'sync successfull', | ||||
|   | ||||
| @@ -177,6 +177,7 @@ export interface PeerInfo { | ||||
|     pw?: string | ||||
|     sessionCookie?: string | ||||
|     lastSync?: number | ||||
|     lastUsersSync?: number | ||||
|     note?: string | ||||
|     http?: boolean | ||||
| } | ||||
|   | ||||
| @@ -59,6 +59,7 @@ export const PeerInfoSchema: Schema = { | ||||
|     ...PeerInfoSchemaBase, | ||||
|     properties: { | ||||
|         ...PeerInfoSchemaBase.properties, | ||||
|         lastUsersSync: { type: 'number' }, | ||||
|         publicKey: { type: 'string' }, | ||||
|         pw: { type: 'string' }, | ||||
|         sessionCookie: { type: 'string' }, | ||||
|   | ||||