wotex2.ts 12 KB
Newer Older
Cédric Moreau's avatar
Cédric Moreau committed
1
import {DataFinder} from "../lib/DataFinder";
2
import {MonitConstants} from "../lib/constants2";
Cédric Moreau's avatar
Cédric Moreau committed
3

4
5
6
7
8
const _ = require('underscore')
const getLang = require(__dirname + '/../lib/getLang')

const MAX_STEP_LOOK = 7

Cédric Moreau's avatar
Cédric Moreau committed
9
module.exports = async (req:any, res:any, next:any) => {
10
  
Éloïs's avatar
Éloïs committed
11
  var { duniterServer  } = req.app.locals
12

Cédric Moreau's avatar
Cédric Moreau committed
13
14
  const dataFinder = new DataFinder(duniterServer)

15
16
17
    try {
      // get GET parameters
      var format = req.query.format || 'HTML';
Éloïs's avatar
Éloïs committed
18
      var help = req.query.help || 'yes';
19
20
      
      // get lg file
21
      const LANG = getLang(`${__dirname}/../lg/wotex_${req.query.lg||MonitConstants.DEFAULT_LANGUAGE}.txt`);
22
23
24
25
      
      // Trouve les points de contrôle efficacement grâce au module C (nommé "wotb")
      const wotb = duniterServer.dal.wotb.memCopy();
      wotb.setMaxCert(100);
Cédric Moreau's avatar
Cédric Moreau committed
26
      const head = await duniterServer.dal.getCurrentBlockOrNull();
27
28
      const membersCount = head ? head.membersCount : 0;
      let dSen = Math.ceil(Math.pow(membersCount, 1 / duniterServer.conf.stepMax));
Cédric Moreau's avatar
Cédric Moreau committed
29
      const dicoIdentites: any = {};
30
      const pointsDeControle = wotb.getSentries(dSen);
Cédric Moreau's avatar
Cédric Moreau committed
31
32
      const sentries = await Promise.all(pointsDeControle.map(async (wotb_id: number) => {
        const identite = await dataFinder.getIdentityByWotbid(wotb_id);
33
34
35
36
37
38
        identite.statusClass = 'isSentry';
        dicoIdentites[identite.wotb_id] = identite;
        return identite;
      }));

      let searchResult = '';
Cédric Moreau's avatar
Cédric Moreau committed
39
			let lignes:any = [];
40
41
42
43
44
45
46
47
      if (req.query.to) {
        let idty;
        let pos = 0, search = req.query.to;
        if (req.query.to.match(/(\[|\])/)) {
          const match = req.query.to.match(/^(.+)(\[\d+\])!?$/);
          search = match[1];
          pos = parseInt(match[2].replace(/(\[|\])/g, ''));
        }
Cédric Moreau's avatar
Cédric Moreau committed
48
        let idties = await dataFinder.searchIdentities(search);
49
50
51
52
53
54
55
56
57
58
59
        idty = idties[pos];
        if (!idty) {
          searchResult = `
                  <p>UID or public key « ${req.query.to} » is not known in the WoT nor in the sandboxes.</p>
                `;
        } else if (!req.query.pending && idty.wotb_id === null) {
          searchResult = `
                  <p>UID or public key « ${req.query.to} » requires the "Include sandbox's data" option to be enabled.</p>
                `;
        } else {

Cédric Moreau's avatar
Cédric Moreau committed
60
          let membres = await prepareMembresInitiaux(dataFinder, wotb, dSen, sentries, dicoIdentites, duniterServer);
61

Cédric Moreau's avatar
Cédric Moreau committed
62
          const res = await prepareMembres(req, wotb, duniterServer, membres, idty, dicoIdentites);
63
64
65
66
67
68
69
70
71
72
73
          membres = res.membres;
          idty = res.idty;
          const mapPendingCerts = res.mapPendingCerts;

          for (const membre of membres) {
            if (req.query.mode == "u2w") {
              alimenteLignes(wotb, idty, membre, lignes, dicoIdentites, mapPendingCerts);
            } else {
              alimenteLignes(wotb, membre, idty, lignes, dicoIdentites, mapPendingCerts);
            }
          }
Éloïs's avatar
Éloïs committed
74
          searchResult = genereHTMLdeRecherche(lignes, LANG, help);
75
76
77
78
79
80
        }
      }

      // Si le client demande la réponse au format JSON, le faire
      if (format == 'JSON')
      {
81
82
				// Send JSON reponse
				res.status(200).jsonp( lignes )
83
84
85
86
      }
      // Sinon, printer la page html
      else
      {
87
88
				// write sentriesHTML
				let sentriesHTML = sentries
Cédric Moreau's avatar
Cédric Moreau committed
89
						.map((sentry:any) => `
90
91
92
93
94
95
96
97
98
99
100
					<div class="sentry isSentry"><a href="wotex?lg=${LANG['LG']}&to=${sentry.uid}">${sentry.uid}</a></div>
							`)
						.join('');
				
				res.locals = {
					// Les varibles à passer au template
					host: req.headers.host.toString(),
					searchResult,
					sentriesHTML
				}
				next()
101
102
103
104
105
106
      }
    } catch (e) {
      // En cas d'exception, afficher le message
      res.status(500).send('<pre>' + (e.stack || e.message) + '</pre>');
    }

Cédric Moreau's avatar
Cédric Moreau committed
107
  };
108

Cédric Moreau's avatar
Cédric Moreau committed
109
110
function traduitCheminEnIdentites(chemins:any, dicoIdentites:any): any[] {
  const cheminsTries = chemins.sort((cheminA:any, cheminB:any) => {
111
112
113
114
115
116
117
118
119
    if (cheminA.length < cheminB.length) {
      return -1;
    }
    if (cheminA.length > cheminB.length) {
      return 1;
    }
    return 0;
  });
  if (cheminsTries[0]) {
Cédric Moreau's avatar
Cédric Moreau committed
120
    return cheminsTries[0].slice().map((wotb_id: number) => {
121
122
123
124
125
126
127
128
129
130
131
132
      return {
        uid: dicoIdentites[wotb_id].uid,
        pub: dicoIdentites[wotb_id].pub,
        wotb_id: wotb_id,
        statusClass: dicoIdentites[wotb_id].statusClass
      };
    });
  } else {
    return [];
  }
}

Cédric Moreau's avatar
Cédric Moreau committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
async function prepareMembresInitiaux(dataFinder: DataFinder, wotb:any, dSen:any, sentries:any, dicoIdentites:any, duniterServer:any) {
  // Ajout des membres non-sentries
  const pointsNormaux = wotb.getNonSentries(dSen);
  const nonSentries = await Promise.all(pointsNormaux.map(async (wotb_id:number) => {
    const identite = await dataFinder.getIdentityByWotbid(wotb_id);
    identite.statusClass = 'isMember';
    dicoIdentites[identite.wotb_id] = identite;
    return identite;
  }));
  const nonMembres = wotb.getDisabled();
  const disabled = await Promise.all(nonMembres.map(async (wotb_id:number) => {
    const identite = await dataFinder.getIdentityByWotbid(wotb_id);
    identite.statusClass = 'isNonMember';
    dicoIdentites[identite.wotb_id] = identite;
    return identite;
  }));

  return sentries.concat(nonSentries).concat(disabled);
151
152
}

Cédric Moreau's avatar
Cédric Moreau committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
async function prepareMembres(req:any, wotb:any, duniterServer:any, membres:any, idty:any, dicoIdentites:any) {
  const mapPendingCerts:any = {};
  const mapPendingIdties:any = {};
  const mapSiblings:any = {};
  if (req.query.pending) {
    // Recherche les identités en attente
    const pendingIdties = await duniterServer.dal.idtyDAL.sqlListAll();
    for (const theIdty of pendingIdties) {
      // Add it to the temp wot
      theIdty.wotb_id = wotb.addNode();
      theIdty.statusClass = 'isPending';
      theIdty.pub = theIdty.pubkey;
      const siblings = _.where(pendingIdties, { uid: theIdty.uid });
      if (siblings.length > 1 || mapSiblings[theIdty.uid] !== undefined) {
        const initialUID = theIdty.uid;
        mapSiblings[initialUID] = (mapSiblings[initialUID] || 0);
        theIdty.uid += "[" + mapSiblings[initialUID] + "]";
        if (theIdty.uid == req.query.to) {
          idty = theIdty;
        }
        mapSiblings[initialUID]++;
      } else {
        if (theIdty.uid == req.query.to) {
          idty = theIdty;
177
178
        }
      }
Cédric Moreau's avatar
Cédric Moreau committed
179
180
181
      dicoIdentites[theIdty.wotb_id] = theIdty;
      mapPendingIdties[theIdty.wotb_id] = theIdty;
    }
182

Cédric Moreau's avatar
Cédric Moreau committed
183
    membres = membres.concat(Object.values(mapPendingIdties));
184

Cédric Moreau's avatar
Cédric Moreau committed
185
186
187
188
189
190
191
192
    // Recherche les certifications en attente
    const pendingCerts = await duniterServer.dal.certDAL.sqlListAll();
    for (const cert of pendingCerts) {
      const from = _.findWhere(membres, { pub: cert.from });
      const target = _.findWhere(membres, { hash: cert.target });
      if (target && from) {
        wotb.addLink(from.wotb_id, target.wotb_id);
        mapPendingCerts[[from.wotb_id, target.wotb_id].join('-')] = true;
193
194
      }
    }
Cédric Moreau's avatar
Cédric Moreau committed
195
196
  }
  return { idty, membres, mapPendingCerts };
197
198
}

Cédric Moreau's avatar
Cédric Moreau committed
199
function alimenteLignes(wotb:any, source:any, cible:any, lignes:any, dicoIdentites:any, mapPendingCerts:any) {
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  const plusCourtsCheminsPossibles = wotb.getPaths(source.wotb_id, cible.wotb_id, MAX_STEP_LOOK);
  if (plusCourtsCheminsPossibles.length) {
    const ligne = traduitCheminEnIdentites(plusCourtsCheminsPossibles, dicoIdentites);
    for (let i = 0; i < ligne.length - 1; i++) {
      const from_wid = ligne[i].wotb_id;
      const to_wid = ligne[i + 1].wotb_id;
      const lien = [from_wid, to_wid].join('-');
      if (mapPendingCerts[lien]) {
        ligne[i + 1].pendingCert = true;
      }
    }
    lignes.push(ligne);
  } else {
    const identiteObservee = dicoIdentites[source.wotb_id];
    if (identiteObservee.uid != cible.uid) {
      lignes.push([identiteObservee,
        { uid: '?', statusClass: 'isPending', pendingCert: true },
        { uid: '?', statusClass: 'isPending', pendingCert: true },
        { uid: '?', statusClass: 'isPending', pendingCert: true },
        { uid: '?', statusClass: 'isPending', pendingCert: true },
        { uid: '?', statusClass: 'isPending', pendingCert: true },
        cible]);
    }
  }
}

Cédric Moreau's avatar
Cédric Moreau committed
226
227
function genereHTMLdeRecherche(lignes: any, LANG: any, help: any) {
  lignes.sort((ligneA:any, ligneB:any) => {
228
229
230
231
232
233
234
235
236
237
238
    if (ligneA.length > ligneB.length) return -1;
    if (ligneB.length > ligneA.length) return 1;
    if ((ligneA[1] && ligneA[1] == '?') && (!ligneB[1] || ligneB[1] != '?')) {
      return 1;
    }
    if ((ligneB[1] && ligneB[1] == '?') && (!ligneA[1] || ligneA[1] != '?')) {
      return -1;
    }
    return 0;
  });
  lignes.reverse();
Cédric Moreau's avatar
Cédric Moreau committed
239
  const chemins = lignes.map((colonnes: any) => {
240
241
    return `
    <tr>
Éloïs's avatar
Éloïs committed
242
      <td class="${ colonnes[0] && colonnes[0].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[0] && colonnes[0].uid) || ''}">${ (colonnes[0] && colonnes[0].uid) || ''}</td>
243
      <td class="${ colonnes[1] && colonnes[1].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[1] && colonnes[1].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
244
      <td class="${ colonnes[1] && colonnes[1].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[1] && colonnes[1].uid) || ''}">${ (colonnes[1] && colonnes[1].uid) || ''}</td>
245
      <td class="${ colonnes[2] && colonnes[2].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[2] && colonnes[2].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
246
      <td class="${ colonnes[2] && colonnes[2].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[2] && colonnes[2].uid) || ''}">${ (colonnes[2] && colonnes[2].uid) || ''}</td>
247
      <td class="${ colonnes[3] && colonnes[3].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[3] && colonnes[3].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
248
      <td class="${ colonnes[3] && colonnes[3].statusClass }"><a href="wotex?lg=$&help=${help}&to=${ (colonnes[3] && colonnes[3].uid) || ''}">${ (colonnes[3] && colonnes[3].uid) || ''}</td>
249
      <td class="${ colonnes[4] && colonnes[4].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[4] && colonnes[4].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
250
      <td class="${ colonnes[4] && colonnes[4].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[4] && colonnes[4].uid) || ''}">${ (colonnes[4] && colonnes[4].uid) || ''}</td>
251
      <td class="${ colonnes[5] && colonnes[5].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[5] && colonnes[5].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
252
      <td class="isMax ${ colonnes[5] && colonnes[5].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[5] && colonnes[5].uid) || ''}">${ (colonnes[5] && colonnes[5].uid) || ''}</td>
253
      <td class="${ colonnes[6] && colonnes[6].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[6] && colonnes[6].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
254
      <td class="${ colonnes[6] && colonnes[6].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[6] && colonnes[6].uid) || ''}">${ (colonnes[6] && colonnes[6].uid) || ''}</td>
255
      <td class="${ colonnes[7] && colonnes[7].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[7] && colonnes[7].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
256
      <td class="${ colonnes[7] && colonnes[7].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[7] && colonnes[7].uid) || ''}">${ (colonnes[7] && colonnes[7].uid) || ''}</td>
257
      <td class="${ colonnes[8] && colonnes[8].pendingCert ? 'isPendingCert' : '' }">${ (colonnes[8] && colonnes[8].uid) ? '->' : ''}</td>
Éloïs's avatar
Éloïs committed
258
      <td class="${ colonnes[8] && colonnes[8].statusClass }"><a href="wotex?lg=${LANG['LG']}&help=${help}&to=${ (colonnes[8] && colonnes[8].uid) || ''}">${ (colonnes[8] && colonnes[8].uid) || ''}</td>
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
    </tr>
  `;
  }).join('');

  return `
    <table>
      <tr>
        <th>${LANG['STEP']} 0</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 1</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 2</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 3</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 4</th>
        <th class="arrow">-></th>
        <th class="isMax">${LANG['STEP']} 5 (${LANG['MAX']})</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 6</th>
        <th class="arrow">-></th>
        <th>${LANG['STEP']} 7</th>
        <th class="arrow">-></th>
        <th>${LANG['INFINITY']}</th>
      </tr>
      ${chemins}
    </table>
  `;
}