Skip to content

Commit cdcf900

Browse files
authored
Merge branch 'main' into 1237-schema-docs
2 parents b51e196 + 847983d commit cdcf900

File tree

14 files changed

+617
-502
lines changed

14 files changed

+617
-502
lines changed

eslint.config.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import js from '@eslint/js';
77
import ts from 'typescript-eslint';
88
import react from 'eslint-plugin-react';
99
import json from '@eslint/json';
10-
// @ts-expect-error
1110
import cypress from 'eslint-plugin-cypress';
1211
import prettierConfig from 'eslint-config-prettier/flat';
1312

package-lock.json

Lines changed: 314 additions & 284 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"version": "2.0.0-rc.3",
44
"description": "Deploy custom push protections and policies on top of Git.",
55
"scripts": {
6-
"cli": "node ./packages/git-proxy-cli/index.js",
6+
"cli": "tsx ./packages/git-proxy-cli/index.ts",
7+
"cli:js": "node ./packages/git-proxy-cli/dist/index.js",
78
"client": "vite --config vite.config.ts",
89
"clientinstall": "npm install --prefix client",
910
"server": "tsx index.ts",
@@ -44,7 +45,7 @@
4445
"dependencies": {
4546
"@material-ui/core": "^4.12.4",
4647
"@material-ui/icons": "4.11.3",
47-
"@primer/octicons-react": "^19.18.0",
48+
"@primer/octicons-react": "^19.19.0",
4849
"@seald-io/nedb": "^4.1.2",
4950
"axios": "^1.12.2",
5051
"bcryptjs": "^3.0.2",
@@ -59,7 +60,7 @@
5960
"express-rate-limit": "^8.1.0",
6061
"express-session": "^1.18.2",
6162
"history": "5.3.0",
62-
"isomorphic-git": "^1.33.1",
63+
"isomorphic-git": "^1.34.0",
6364
"jsonwebtoken": "^9.0.2",
6465
"jwk-to-pem": "^2.0.7",
6566
"load-plugin": "^6.0.3",
@@ -68,7 +69,7 @@
6869
"moment": "^2.30.1",
6970
"mongodb": "^5.9.2",
7071
"nodemailer": "^6.10.1",
71-
"openid-client": "^6.8.0",
72+
"openid-client": "^6.8.1",
7273
"parse-diff": "^0.11.1",
7374
"passport": "^0.7.0",
7475
"passport-activedirectory": "^1.4.0",
@@ -90,14 +91,14 @@
9091
"@commitlint/cli": "^19.8.1",
9192
"@commitlint/config-conventional": "^19.8.1",
9293
"@eslint/compat": "^1.4.0",
93-
"@eslint/js": "^9.36.0",
94+
"@eslint/js": "^9.37.0",
9495
"@eslint/json": "^0.13.2",
9596
"@types/domutils": "^1.7.8",
9697
"@types/express": "^5.0.3",
9798
"@types/express-http-proxy": "^1.6.7",
9899
"@types/lodash": "^4.17.20",
99100
"@types/mocha": "^10.0.10",
100-
"@types/node": "^22.18.6",
101+
"@types/node": "^22.18.8",
101102
"@types/react-dom": "^17.0.26",
102103
"@types/react-html-parser": "^2.0.7",
103104
"@types/validator": "^13.15.3",
@@ -106,15 +107,15 @@
106107
"@vitejs/plugin-react": "^4.7.0",
107108
"chai": "^4.5.0",
108109
"chai-http": "^4.4.0",
109-
"cypress": "^15.3.0",
110-
"eslint": "^9.36.0",
110+
"cypress": "^15.4.0",
111+
"eslint": "^9.37.0",
111112
"eslint-config-prettier": "^10.1.8",
112-
"eslint-plugin-cypress": "^5.1.1",
113+
"eslint-plugin-cypress": "^5.2.0",
113114
"eslint-plugin-react": "^7.37.5",
114115
"fast-check": "^4.3.0",
115116
"globals": "^16.4.0",
116117
"husky": "^9.1.7",
117-
"lint-staged": "^16.2.0",
118+
"lint-staged": "^16.2.3",
118119
"mocha": "^10.8.2",
119120
"nyc": "^17.1.0",
120121
"prettier": "^3.6.2",
@@ -124,9 +125,9 @@
124125
"sinon-chai": "^3.7.0",
125126
"ts-mocha": "^11.1.0",
126127
"ts-node": "^10.9.2",
127-
"tsx": "^4.20.5",
128-
"typescript": "^5.9.2",
129-
"typescript-eslint": "^8.44.1",
128+
"tsx": "^4.20.6",
129+
"typescript": "^5.9.3",
130+
"typescript-eslint": "^8.46.0",
130131
"vite": "^4.5.14",
131132
"vite-tsconfig-paths": "^5.1.4"
132133
},

packages/git-proxy-cli/index.js renamed to packages/git-proxy-cli/index.ts

Lines changed: 85 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#!/usr/bin/env node
2-
const axios = require('axios');
3-
const yargs = require('yargs/yargs');
4-
const { hideBin } = require('yargs/helpers');
5-
const fs = require('fs');
6-
const util = require('util');
2+
import axios from 'axios';
3+
import yargs from 'yargs/yargs';
4+
import { hideBin } from 'yargs/helpers';
5+
import fs from 'fs';
6+
import util from 'util';
7+
8+
import { CommitData, PushData } from '@finos/git-proxy/src/types/models';
9+
import { PushQuery } from '@finos/git-proxy/src/db/types';
710

811
const GIT_PROXY_COOKIE_FILE = 'git-proxy-cookie';
912
// GitProxy UI HOST and PORT (configurable via environment variable)
@@ -19,7 +22,7 @@ axios.defaults.timeout = 30000;
1922
* @param {string} username The user name to login with
2023
* @param {string} password The password to use for the login
2124
*/
22-
async function login(username, password) {
25+
async function login(username: string, password: string) {
2326
try {
2427
let response = await axios.post(
2528
`${baseUrl}/api/auth/login`,
@@ -44,7 +47,7 @@ async function login(username, password) {
4447
const user = `"${response.data.username}" <${response.data.email}>`;
4548
const isAdmin = response.data.admin ? ' (admin)' : '';
4649
console.log(`Login ${user}${isAdmin}: OK`);
47-
} catch (error) {
50+
} catch (error: any) {
4851
if (error.response) {
4952
console.error(`Error: Login '${username}': '${error.response.status}'`);
5053
process.exitCode = 1;
@@ -61,7 +64,7 @@ async function login(username, password) {
6164
* the push is allowed, authorised, blocked, canceled, encountered an error,
6265
* or was rejected.
6366
*
64-
* @param {Object} filters - An object containing filter criteria for Git
67+
* @param {Partial<PushQuery>} filters - An object containing filter criteria for Git
6568
* pushes.
6669
* @param {boolean} filters.allowPush - If not null, filters for pushes with
6770
* given attribute and status.
@@ -76,7 +79,7 @@ async function login(username, password) {
7679
* @param {boolean} filters.rejected - If not null, filters for pushes with
7780
* given attribute and status.
7881
*/
79-
async function getGitPushes(filters) {
82+
async function getGitPushes(filters: Partial<PushQuery>) {
8083
if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
8184
console.error('Error: List: Authentication required');
8285
process.exitCode = 1;
@@ -91,40 +94,64 @@ async function getGitPushes(filters) {
9194
params: filters,
9295
});
9396

94-
const records = [];
95-
response.data?.forEach((push) => {
96-
const record = {};
97-
record.id = push.id;
98-
record.timestamp = push.timestamp;
99-
record.url = push.url;
100-
record.allowPush = push.allowPush;
101-
record.authorised = push.authorised;
102-
record.blocked = push.blocked;
103-
record.canceled = push.canceled;
104-
record.error = push.error;
105-
record.rejected = push.rejected;
106-
107-
record.lastStep = {
108-
stepName: push.lastStep?.stepName,
109-
error: push.lastStep?.error,
110-
errorMessage: push.lastStep?.errorMessage,
111-
blocked: push.lastStep?.blocked,
112-
blockedMessage: push.lastStep?.blockedMessage,
97+
const records: PushData[] = [];
98+
response.data.forEach((push: PushData) => {
99+
const record: PushData = {
100+
id: push.id,
101+
repo: push.repo,
102+
branch: push.branch,
103+
commitFrom: push.commitFrom,
104+
commitTo: push.commitTo,
105+
commitData: push.commitData,
106+
diff: push.diff,
107+
error: push.error,
108+
canceled: push.canceled,
109+
rejected: push.rejected,
110+
blocked: push.blocked,
111+
authorised: push.authorised,
112+
attestation: push.attestation,
113+
autoApproved: push.autoApproved,
114+
timestamp: push.timestamp,
115+
url: push.url,
116+
allowPush: push.allowPush,
113117
};
114118

115-
record.commitData = [];
116-
push.commitData?.forEach((pushCommitDataRecord) => {
117-
record.commitData.push({
118-
message: pushCommitDataRecord.message,
119-
committer: pushCommitDataRecord.committer,
119+
if (push.lastStep) {
120+
record.lastStep = {
121+
id: push.lastStep?.id,
122+
content: push.lastStep?.content,
123+
logs: push.lastStep?.logs,
124+
stepName: push.lastStep?.stepName,
125+
error: push.lastStep?.error,
126+
errorMessage: push.lastStep?.errorMessage,
127+
blocked: push.lastStep?.blocked,
128+
blockedMessage: push.lastStep?.blockedMessage,
129+
};
130+
}
131+
132+
if (push.commitData) {
133+
const commitData: CommitData[] = [];
134+
push.commitData.forEach((pushCommitDataRecord: CommitData) => {
135+
commitData.push({
136+
message: pushCommitDataRecord.message,
137+
committer: pushCommitDataRecord.committer,
138+
committerEmail: pushCommitDataRecord.committerEmail,
139+
author: pushCommitDataRecord.author,
140+
authorEmail: pushCommitDataRecord.authorEmail,
141+
commitTimestamp: pushCommitDataRecord.commitTimestamp,
142+
tree: pushCommitDataRecord.tree,
143+
parent: pushCommitDataRecord.parent,
144+
commitTs: pushCommitDataRecord.commitTs,
145+
});
120146
});
121-
});
147+
record.commitData = commitData;
148+
}
122149

123150
records.push(record);
124151
});
125152

126153
console.log(`${util.inspect(records, false, null, false)}`);
127-
} catch (error) {
154+
} catch (error: any) {
128155
// default error
129156
const errorMessage = `Error: List: '${error.message}'`;
130157
process.exitCode = 2;
@@ -136,7 +163,7 @@ async function getGitPushes(filters) {
136163
* Authorise git push by ID
137164
* @param {string} id The ID of the git push to authorise
138165
*/
139-
async function authoriseGitPush(id) {
166+
async function authoriseGitPush(id: string) {
140167
if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
141168
console.error('Error: Authorise: Authentication required');
142169
process.exitCode = 1;
@@ -168,16 +195,15 @@ async function authoriseGitPush(id) {
168195
);
169196

170197
console.log(`Authorise: ID: '${id}': OK`);
171-
} catch (error) {
198+
} catch (error: any) {
172199
// default error
173200
let errorMessage = `Error: Authorise: '${error.message}'`;
174201
process.exitCode = 2;
175202

176203
if (error.response) {
177204
switch (error.response.status) {
178205
case 401:
179-
errorMessage =
180-
'Error: Authorise: Authentication required (401): ' + error?.response?.data?.message;
206+
errorMessage = 'Error: Authorise: Authentication required';
181207
process.exitCode = 3;
182208
break;
183209
case 404:
@@ -193,7 +219,7 @@ async function authoriseGitPush(id) {
193219
* Reject git push by ID
194220
* @param {string} id The ID of the git push to reject
195221
*/
196-
async function rejectGitPush(id) {
222+
async function rejectGitPush(id: string) {
197223
if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
198224
console.error('Error: Reject: Authentication required');
199225
process.exitCode = 1;
@@ -216,16 +242,15 @@ async function rejectGitPush(id) {
216242
);
217243

218244
console.log(`Reject: ID: '${id}': OK`);
219-
} catch (error) {
245+
} catch (error: any) {
220246
// default error
221247
let errorMessage = `Error: Reject: '${error.message}'`;
222248
process.exitCode = 2;
223249

224250
if (error.response) {
225251
switch (error.response.status) {
226252
case 401:
227-
errorMessage =
228-
'Error: Reject: Authentication required (401): ' + error?.response?.data?.message;
253+
errorMessage = 'Error: Reject: Authentication required';
229254
process.exitCode = 3;
230255
break;
231256
case 404:
@@ -241,7 +266,7 @@ async function rejectGitPush(id) {
241266
* Cancel git push by ID
242267
* @param {string} id The ID of the git push to cancel
243268
*/
244-
async function cancelGitPush(id) {
269+
async function cancelGitPush(id: string) {
245270
if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
246271
console.error('Error: Cancel: Authentication required');
247272
process.exitCode = 1;
@@ -264,16 +289,15 @@ async function cancelGitPush(id) {
264289
);
265290

266291
console.log(`Cancel: ID: '${id}': OK`);
267-
} catch (error) {
292+
} catch (error: any) {
268293
// default error
269294
let errorMessage = `Error: Cancel: '${error.message}'`;
270295
process.exitCode = 2;
271296

272297
if (error.response) {
273298
switch (error.response.status) {
274299
case 401:
275-
errorMessage =
276-
'Error: Cancel: Authentication required (401): ' + error?.response?.data?.message;
300+
errorMessage = 'Error: Cancel: Authentication required';
277301
process.exitCode = 3;
278302
break;
279303
case 404:
@@ -302,7 +326,7 @@ async function logout() {
302326
headers: { Cookie: cookies },
303327
},
304328
);
305-
} catch (error) {
329+
} catch (error: any) {
306330
console.log(`Warning: Logout: '${error.message}'`);
307331
}
308332
}
@@ -326,7 +350,7 @@ async function reloadConfig() {
326350
await axios.post(`${baseUrl}/api/v1/admin/reload-config`, {}, { headers: { Cookie: cookies } });
327351

328352
console.log('Configuration reloaded successfully');
329-
} catch (error) {
353+
} catch (error: any) {
330354
const errorMessage = `Error: Reload config: '${error.message}'`;
331355
process.exitCode = 2;
332356
console.error(errorMessage);
@@ -341,7 +365,13 @@ async function reloadConfig() {
341365
* @param {string} gitAccount The git account for the new user
342366
* @param {boolean} [admin=false] Whether the user should be an admin (optional)
343367
*/
344-
async function createUser(username, password, email, gitAccount, admin = false) {
368+
async function createUser(
369+
username: string,
370+
password: string,
371+
email: string,
372+
gitAccount: string,
373+
admin: boolean = false,
374+
) {
345375
if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
346376
console.error('Error: Create User: Authentication required');
347377
process.exitCode = 1;
@@ -366,7 +396,7 @@ async function createUser(username, password, email, gitAccount, admin = false)
366396
);
367397

368398
console.log(`User '${username}' created successfully`);
369-
} catch (error) {
399+
} catch (error: any) {
370400
let errorMessage = `Error: Create User: '${error.message}'`;
371401
process.exitCode = 2;
372402

@@ -518,8 +548,10 @@ yargs(hideBin(process.argv)) // eslint-disable-line @typescript-eslint/no-unused
518548
})
519549
.command({
520550
command: 'reload-config',
521-
description: 'Reload GitProxy configuration without restarting',
522-
action: reloadConfig,
551+
describe: 'Reload GitProxy configuration without restarting',
552+
handler() {
553+
reloadConfig();
554+
},
523555
})
524556
.command({
525557
command: 'create-user',

0 commit comments

Comments
 (0)