diff --git a/defaultPublicFiles/img/faq/script-1.jpg b/defaultPublicFiles/img/faq/script-1.jpg new file mode 100644 index 0000000..14723bc Binary files /dev/null and b/defaultPublicFiles/img/faq/script-1.jpg differ diff --git a/defaultPublicFiles/img/faq/script-2.jpg b/defaultPublicFiles/img/faq/script-2.jpg new file mode 100644 index 0000000..4a16a13 Binary files /dev/null and b/defaultPublicFiles/img/faq/script-2.jpg differ diff --git a/defaultPublicFiles/img/faq/script-3.jpg b/defaultPublicFiles/img/faq/script-3.jpg new file mode 100755 index 0000000..9d14caf Binary files /dev/null and b/defaultPublicFiles/img/faq/script-3.jpg differ diff --git a/defaultPublicFiles/img/faq/script-4.jpg b/defaultPublicFiles/img/faq/script-4.jpg new file mode 100755 index 0000000..42d5d2b Binary files /dev/null and b/defaultPublicFiles/img/faq/script-4.jpg differ diff --git a/defaultPublicFiles/img/faq/script-5.jpg b/defaultPublicFiles/img/faq/script-5.jpg new file mode 100644 index 0000000..b1765af Binary files /dev/null and b/defaultPublicFiles/img/faq/script-5.jpg differ diff --git a/defaultPublicFiles/img/faq/script-6.jpg b/defaultPublicFiles/img/faq/script-6.jpg new file mode 100644 index 0000000..b7eaf98 Binary files /dev/null and b/defaultPublicFiles/img/faq/script-6.jpg differ diff --git a/defaultPublicFiles/img/faq/siteadd-1.png b/defaultPublicFiles/img/faq/siteadd-1.png deleted file mode 100755 index 459398e..0000000 Binary files a/defaultPublicFiles/img/faq/siteadd-1.png and /dev/null differ diff --git a/defaultPublicFiles/img/faq/siteadd-2.png b/defaultPublicFiles/img/faq/siteadd-2.png deleted file mode 100755 index 518e5aa..0000000 Binary files a/defaultPublicFiles/img/faq/siteadd-2.png and /dev/null differ diff --git a/defaultPublicFiles/img/faq/siteadd-3.png b/defaultPublicFiles/img/faq/siteadd-3.png deleted file mode 100755 index 3310d61..0000000 Binary files a/defaultPublicFiles/img/faq/siteadd-3.png and /dev/null differ diff --git a/defaultPublicFiles/img/faq/siteadd-4.png b/defaultPublicFiles/img/faq/siteadd-4.png deleted file mode 100755 index 55536ed..0000000 Binary files a/defaultPublicFiles/img/faq/siteadd-4.png and /dev/null differ diff --git a/defaultPublicFiles/img/faq/sitesave-1.jpg b/defaultPublicFiles/img/faq/sitesave-1.jpg deleted file mode 100755 index bb58166..0000000 Binary files a/defaultPublicFiles/img/faq/sitesave-1.jpg and /dev/null differ diff --git a/defaultPublicFiles/img/faq/sitesave-2.jpg b/defaultPublicFiles/img/faq/sitesave-2.jpg deleted file mode 100755 index 235d6be..0000000 Binary files a/defaultPublicFiles/img/faq/sitesave-2.jpg and /dev/null differ diff --git a/defaultPublicFiles/img/scriptimg/script-1.jpg b/defaultPublicFiles/img/scriptimg/script-1.jpg index 240f397..14723bc 100644 Binary files a/defaultPublicFiles/img/scriptimg/script-1.jpg and b/defaultPublicFiles/img/scriptimg/script-1.jpg differ diff --git a/defaultPublicFiles/img/scriptimg/script-2.jpg b/defaultPublicFiles/img/scriptimg/script-2.jpg index e1eb096..4a16a13 100644 Binary files a/defaultPublicFiles/img/scriptimg/script-2.jpg and b/defaultPublicFiles/img/scriptimg/script-2.jpg differ diff --git a/defaultPublicFiles/img/scriptimg/script-5.jpg b/defaultPublicFiles/img/scriptimg/script-5.jpg new file mode 100644 index 0000000..b1765af Binary files /dev/null and b/defaultPublicFiles/img/scriptimg/script-5.jpg differ diff --git a/src/modules/api/submodules/p2p.ts b/src/modules/api/submodules/p2p.ts index 5a36939..7dc9ff3 100644 --- a/src/modules/api/submodules/p2p.ts +++ b/src/modules/api/submodules/p2p.ts @@ -324,14 +324,14 @@ async function authAndGetNewData({ peers, peer, selfInfo, - lastSyncWithPeer, }: { peers: PeerInfo[] peer: PeerInfo selfInfo: PeerInfo - lastSyncWithPeer: number }): Promise> { 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,34 +1007,41 @@ 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 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 usersOnly = !!req.query.usersOnly const result: SyncDataRes = { - questionDbs: questionDbsWithNewQuestions, - count: { + remoteInfo: getSelfInfo(), + } + + 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, 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,40 +1092,60 @@ function setup(data: SubmoduleData): Submodule { } } - const dateToLog = Number.isNaN(since) + const usersSinceDate = 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()} ` - ) - logger.logTable( - [ - ['Users', 'QDBs', 'Subjs', 'Questions'], + 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() + + 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, - questionDbsWithNewQuestions.length, - subjects, - questions, + ['Users', 'QDBs', 'Subjs', 'Questions'], + [ + sentUsers, + result.questionDbs.length, + result.count.subjects, + result.count.questions, + ], ], - ], - { rowPrefix: '\t' } - ) + { 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', diff --git a/src/types/basicTypes.ts b/src/types/basicTypes.ts index d82ddbe..22ba3d3 100644 --- a/src/types/basicTypes.ts +++ b/src/types/basicTypes.ts @@ -177,6 +177,7 @@ export interface PeerInfo { pw?: string sessionCookie?: string lastSync?: number + lastUsersSync?: number note?: string http?: boolean } diff --git a/src/types/typeSchemas.ts b/src/types/typeSchemas.ts index 191fa62..375167a 100644 --- a/src/types/typeSchemas.ts +++ b/src/types/typeSchemas.ts @@ -59,6 +59,7 @@ export const PeerInfoSchema: Schema = { ...PeerInfoSchemaBase, properties: { ...PeerInfoSchemaBase.properties, + lastUsersSync: { type: 'number' }, publicKey: { type: 'string' }, pw: { type: 'string' }, sessionCookie: { type: 'string' }, diff --git a/submodules/moodle-test-userscript b/submodules/moodle-test-userscript index aad2822..898326c 160000 --- a/submodules/moodle-test-userscript +++ b/submodules/moodle-test-userscript @@ -1 +1 @@ -Subproject commit aad2822226c6fc039ee190581b0eaa55f2859dc9 +Subproject commit 898326c3a061e786d9ff8cf437059db34da50504