207f75fae3d503444f93610c835579dae86933d1
Gitcub / server.js
'use strict';

const express = require('express');
const next = require('next');
const fs = require('fs');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
const nodeGit = require('nodegit');

const repositoryDirectory = './user-content-access/';
const dbFile = './gitcub.db';

const dev = process.env.NODE_ENV !== 'production';
const port = 3000;
const app = next({ dev });
const handle = app.getRequestHandler();

const directoryExists = (path) => fs.existsSync(path) ? fs.statSync(path).isDirectory() : false;

const repositoryExists = (name, rows) => (
  directoryExists(repositoryDirectory + name + '.git') && rows.some((x) => x.name === name)
);

const sendResult = (res, resultType, resultPath, resultContent = '') => {
  const result = {
    resultType: resultType,
    resultPath: resultPath,
    resultContent: resultContent,
  };

  res.json(result);
};

const sendError = (res, message) => {
  sendResult(res, 'error', [], message);
};

const sendRepositoryResult = (res, pathArray, depth, tree) => {
  const recursion = (depth, tree) => {
    if (pathArray.length > depth) {
      const entries = tree.entries();
      const isMatchingTree = (x) => x.name() === pathArray[depth] && x.isTree();
      const isMatchingBlob = (x) => x.name() === pathArray[depth] && x.isBlob();

      if (entries.some(isMatchingTree)) {
        entries.find(isMatchingTree).getTree().then((tree) => {
          const newDepth = depth + 1;
          recursion(newDepth, tree);
        });
      } else if (pathArray.length === depth + 1) {
        if (entries.some(isMatchingBlob)) {
          entries.find(isMatchingBlob).getBlob().then((blob) => {
            if (blob.isBinary()) {
              sendResult(res, 'binaryBlob', pathArray);
            } else {
              const text = blob.toString();
              sendResult(res, 'textBlob', pathArray, text);
            }
          });
        } else {
          sendError(res, 'File or directory does not exist.');
        }
      } else {
        sendError(res, 'File or directory does not exist.');
      }
    } else {
      const entryNamesSorted = {
        trees: tree.entries().filter((entry) => entry.isTree()).map((entry) => entry.name()),
        blobs: tree.entries().filter((entry) => entry.isBlob()).map((entry) => entry.name()),
      };

      sendResult(res, 'treeContents', pathArray, entryNamesSorted);
    }
  };

  recursion(depth, tree);
};

const sendAPIResult = (req, res, rows) => {
  if (req.originalUrl.indexOf('\0') === -1) {
    const pathNormalized = path.normalize(req.path);
    const pathArray = pathNormalized.split('/').filter((x) => x.length > 0);
    
    // remove 'api'
    pathArray.shift();
    
    if (pathArray.length > 0) {
      if (repositoryExists(pathArray[0], rows)) {
        const pathToRepo = repositoryDirectory + pathArray[0] + '.git';
        nodeGit.Repository.openBare(pathToRepo)
          .then((repo) => repo.getMasterCommit())
          .then((commit) => commit.getTree())
          .then((tree) => {
            sendRepositoryResult(res, pathArray, 1, tree);
          });
      } else {
        sendError(res, 'Repository does not exist.');
      }
    } else {
      sendError(res, 'Repository not specified.');
    }
  } else {
    sendError(res, 'Null byte found in url. Nice try :)');
  }
};

app.prepare()
.then(() => {
  const server = express();
  const db = new sqlite3.Database(dbFile, sqlite3.OPEN_READWRITE);

  server.get('/api/*', (req, res) => {
    db.all('select name from repositories', (err, rows) => {
      sendAPIResult(req, res, rows);
    });
  });

  server.get('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
  });
})
.catch((ex) => {
  console.error(ex.stack);
  process.exit(1);
});
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