mobbdev 0.0.83 → 0.0.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +195 -83
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -94,8 +94,8 @@ var errorMessages = {
94
94
  missingCxProjectName: `project name ${chalk.bold(
95
95
  "(--cx-project-name)"
96
96
  )} is needed if you're using checkmarx`,
97
- missingScmType: `SCM type ${chalk.bold(
98
- "(--scm-type)"
97
+ missingUrl: `url ${chalk.bold(
98
+ "(--url)"
99
99
  )} is needed if you're adding an SCM token`,
100
100
  invalidScmType: `SCM type ${chalk.bold(
101
101
  "(--scm-type)"
@@ -237,23 +237,33 @@ import { v4 as uuidv4 } from "uuid";
237
237
  import { gql } from "graphql-request";
238
238
  var UPDATE_SCM_TOKEN = gql`
239
239
  mutation updateScmToken(
240
- $type: ScmType!
240
+ $scmType: String!
241
+ $url: String!
241
242
  $token: String!
242
243
  $org: String
243
244
  $username: String
244
245
  $refreshToken: String
245
246
  ) {
246
247
  updateScmToken(
247
- type: $type
248
+ scmType: $scmType
249
+ url: $url
248
250
  token: $token
249
251
  org: $org
250
252
  username: $username
251
253
  refreshToken: $refreshToken
252
254
  ) {
253
- id
254
- adoAccessToken
255
- gitlabAccessToken
256
- gitHubAccessToken
255
+ __typename
256
+ ... on ScmAccessTokenUpdateSuccess {
257
+ token
258
+ }
259
+ ... on InvalidScmTypeError {
260
+ status
261
+ error
262
+ }
263
+ ... on BadScmCredentials {
264
+ status
265
+ error
266
+ }
257
267
  }
258
268
  }
259
269
  `;
@@ -368,10 +378,20 @@ var ME = gql2`
368
378
  me {
369
379
  id
370
380
  email
371
- githubToken
372
- gitlabToken
373
- adoToken
374
- adoOrg
381
+ scmConfigs {
382
+ id
383
+ isBroker
384
+ orgId
385
+ refreshToken
386
+ scmType
387
+ scmUrl
388
+ scmUsername
389
+ token
390
+ tokenLastUpdate
391
+ userId
392
+ scmOrg
393
+ isTokenAvailable
394
+ }
375
395
  }
376
396
  }
377
397
  `;
@@ -565,10 +585,7 @@ function subscribe(query, variables, callback, wsClientOptions) {
565
585
  import { z as z2 } from "zod";
566
586
  var UpdateScmTokenZ = z2.object({
567
587
  updateScmToken: z2.object({
568
- id: z2.string(),
569
- gitHubAccessToken: z2.string().nullable(),
570
- gitlabAccessToken: z2.string().nullable(),
571
- adoAccessToken: z2.string().nullable()
588
+ token: z2.string()
572
589
  })
573
590
  });
574
591
  var UploadFieldsZ = z2.object({
@@ -803,9 +820,10 @@ var GQLClient = class {
803
820
  }
804
821
  }
805
822
  async updateScmToken(args) {
806
- const { type: type2, token, org, username, refreshToken } = args;
823
+ const { scmType, url, token, org, username, refreshToken } = args;
807
824
  const updateScmTokenResult = await this._client.request(UPDATE_SCM_TOKEN, {
808
- type: type2,
825
+ scmType,
826
+ url,
809
827
  token,
810
828
  org,
811
829
  username,
@@ -1402,9 +1420,9 @@ async function getGithubBlameRanges({ ref, gitHubUrl, path: path9 }, options) {
1402
1420
  return res.repository.object.blame.ranges.map((range) => ({
1403
1421
  startingLine: range.startingLine,
1404
1422
  endingLine: range.endingLine,
1405
- email: range.commit.author.user.email,
1406
- name: range.commit.author.user.name,
1407
- login: range.commit.author.user.login
1423
+ email: range.commit.author.user?.email || "",
1424
+ name: range.commit.author.user?.name || "",
1425
+ login: range.commit.author.user?.login || ""
1408
1426
  }));
1409
1427
  }
1410
1428
  async function createPr({
@@ -1881,7 +1899,7 @@ var isValidBranchName = async (branchName) => {
1881
1899
  var FixesZ = z6.array(z6.object({ fixId: z6.string(), diff: z6.string() })).nonempty();
1882
1900
 
1883
1901
  // src/features/analysis/scm/scm.ts
1884
- function getScmLibTypeFromUrl(url) {
1902
+ function getCloudScmLibTypeFromUrl(url) {
1885
1903
  if (!url) {
1886
1904
  return void 0;
1887
1905
  }
@@ -1898,19 +1916,92 @@ function getScmLibTypeFromUrl(url) {
1898
1916
  }
1899
1917
  return void 0;
1900
1918
  }
1919
+ function getScmTypeFromScmLibType(scmLibType) {
1920
+ if (scmLibType === "GITLAB" /* GITLAB */) {
1921
+ return "GitLab" /* GitLab */;
1922
+ }
1923
+ if (scmLibType === "GITHUB" /* GITHUB */) {
1924
+ return "GitHub" /* GitHub */;
1925
+ }
1926
+ if (scmLibType === "ADO" /* ADO */) {
1927
+ return "Ado" /* Ado */;
1928
+ }
1929
+ throw new Error(`unknown scm lib type: ${scmLibType}`);
1930
+ }
1931
+ function getScmLibTypeFromScmType(scmType) {
1932
+ if (scmType === "GitLab" /* GitLab */) {
1933
+ return "GITLAB" /* GITLAB */;
1934
+ }
1935
+ if (scmType === "GitHub" /* GitHub */) {
1936
+ return "GITHUB" /* GITHUB */;
1937
+ }
1938
+ if (scmType === "Ado" /* Ado */) {
1939
+ return "ADO" /* ADO */;
1940
+ }
1941
+ throw new Error(`unknown scm type: ${scmType}`);
1942
+ }
1943
+ function getScmConfig({
1944
+ url,
1945
+ scmConfigs,
1946
+ includeOrgTokens = true
1947
+ }) {
1948
+ const filteredScmConfigs = scmConfigs.filter((scm) => {
1949
+ const urlObject = new URL(url);
1950
+ const configUrl = new URL(scm.scmUrl);
1951
+ return (
1952
+ //if we the user does an ADO oauth flow then the token is saved for dev.azure.com but
1953
+ //sometimes the user uses the url dev.azure.com and sometimes the url visualstudio.com
1954
+ //so we need to check both
1955
+ (urlObject.hostname === configUrl.hostname || urlObject.hostname.endsWith(".visualstudio.com") && configUrl.hostname === "dev.azure.com") && urlObject.protocol === configUrl.protocol && urlObject.port === configUrl.port
1956
+ );
1957
+ });
1958
+ const scmOrgConfig = filteredScmConfigs.find((scm) => scm.orgId && scm.token);
1959
+ if (scmOrgConfig && includeOrgTokens) {
1960
+ return {
1961
+ id: scmOrgConfig.id,
1962
+ accessToken: scmOrgConfig.token || void 0,
1963
+ scmLibType: getScmLibTypeFromScmType(scmOrgConfig.scmType),
1964
+ scmOrg: scmOrgConfig.scmOrg || void 0
1965
+ };
1966
+ }
1967
+ const scmUserConfig = filteredScmConfigs.find(
1968
+ (scm) => scm.userId && scm.token
1969
+ );
1970
+ if (scmUserConfig) {
1971
+ return {
1972
+ id: scmUserConfig.id,
1973
+ accessToken: scmUserConfig.token || void 0,
1974
+ scmLibType: getScmLibTypeFromScmType(scmUserConfig.scmType),
1975
+ scmOrg: scmUserConfig.scmOrg || void 0
1976
+ };
1977
+ }
1978
+ const type2 = getCloudScmLibTypeFromUrl(url);
1979
+ if (type2) {
1980
+ return {
1981
+ id: void 0,
1982
+ accessToken: void 0,
1983
+ scmLibType: type2,
1984
+ scmOrg: void 0
1985
+ };
1986
+ }
1987
+ return {
1988
+ id: void 0,
1989
+ accessToken: void 0,
1990
+ scmLibType: void 0,
1991
+ scmOrg: void 0
1992
+ };
1993
+ }
1901
1994
  async function scmCanReachRepo({
1902
1995
  repoUrl,
1903
- githubToken,
1904
- gitlabToken,
1905
- adoToken,
1996
+ scmType,
1997
+ accessToken,
1906
1998
  scmOrg
1907
1999
  }) {
1908
2000
  try {
1909
- const scmLibType = getScmLibTypeFromUrl(repoUrl);
1910
2001
  await SCMLib.init({
1911
2002
  url: repoUrl,
1912
- accessToken: scmLibType === "GITHUB" /* GITHUB */ ? githubToken : scmLibType === "GITLAB" /* GITLAB */ ? gitlabToken : scmLibType === "ADO" /* ADO */ ? adoToken : "",
1913
- scmType: scmLibType,
2003
+ accessToken,
2004
+ scmType: getScmLibTypeFromScmType(scmType),
1914
2005
  scmOrg
1915
2006
  });
1916
2007
  return true;
@@ -1961,7 +2052,7 @@ var SCMLib = class {
1961
2052
  if (!this.accessToken) {
1962
2053
  return trimmedUrl;
1963
2054
  }
1964
- const scmLibType = getScmLibTypeFromUrl(trimmedUrl);
2055
+ const scmLibType = this.getScmLibType();
1965
2056
  if (scmLibType === "ADO" /* ADO */) {
1966
2057
  return `https://${this.accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
1967
2058
  }
@@ -2088,6 +2179,9 @@ var AdoSCMLib = class extends SCMLib {
2088
2179
  repoUrl: this.url
2089
2180
  });
2090
2181
  }
2182
+ getScmLibType() {
2183
+ return "ADO" /* ADO */;
2184
+ }
2091
2185
  getAuthHeaders() {
2092
2186
  if (this.accessToken) {
2093
2187
  if (getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
@@ -2249,6 +2343,9 @@ var GitlabSCMLib = class extends SCMLib {
2249
2343
  repoUrl: this.url
2250
2344
  });
2251
2345
  }
2346
+ getScmLibType() {
2347
+ return "GITLAB" /* GITLAB */;
2348
+ }
2252
2349
  getAuthHeaders() {
2253
2350
  if (this?.accessToken?.startsWith("glpat-")) {
2254
2351
  return {
@@ -2512,6 +2609,9 @@ var GithubSCMLib = class extends SCMLib {
2512
2609
  }
2513
2610
  return getGithubBranchList(this.accessToken, this.url);
2514
2611
  }
2612
+ getScmLibType() {
2613
+ return "GITHUB" /* GITHUB */;
2614
+ }
2515
2615
  getAuthHeaders() {
2516
2616
  if (this.accessToken) {
2517
2617
  return { authorization: `Bearer ${this.accessToken}` };
@@ -2633,6 +2733,10 @@ var StubSCMLib = class extends SCMLib {
2633
2733
  console.error("createSubmitRequest() not implemented");
2634
2734
  throw new Error("createSubmitRequest() not implemented");
2635
2735
  }
2736
+ getScmLibType() {
2737
+ console.error("getScmLibType() not implemented");
2738
+ throw new Error("getScmLibType() not implemented");
2739
+ }
2636
2740
  getAuthHeaders() {
2637
2741
  console.error("getAuthHeaders() not implemented");
2638
2742
  throw new Error("getAuthHeaders() not implemented");
@@ -3913,11 +4017,8 @@ async function runAnalysis(params, options) {
3913
4017
  tmpObj.removeCallback();
3914
4018
  }
3915
4019
  }
3916
- function _getTokenAndUrlForScmType({
3917
- scmLibType,
3918
- githubToken,
3919
- gitlabToken,
3920
- adoToken
4020
+ function _getUrlForScmType({
4021
+ scmLibType
3921
4022
  }) {
3922
4023
  const githubAuthUrl = `${WEB_APP_URL}/github-auth`;
3923
4024
  const gitlabAuthUrl = `${WEB_APP_URL}/gitlab-auth`;
@@ -3925,22 +4026,18 @@ function _getTokenAndUrlForScmType({
3925
4026
  switch (scmLibType) {
3926
4027
  case "GITHUB" /* GITHUB */:
3927
4028
  return {
3928
- token: githubToken,
3929
4029
  authUrl: githubAuthUrl
3930
4030
  };
3931
4031
  case "GITLAB" /* GITLAB */:
3932
4032
  return {
3933
- token: gitlabToken,
3934
4033
  authUrl: gitlabAuthUrl
3935
4034
  };
3936
4035
  case "ADO" /* ADO */:
3937
4036
  return {
3938
- token: adoToken,
3939
4037
  authUrl: adoAuthUrl
3940
4038
  };
3941
4039
  default:
3942
4040
  return {
3943
- token: void 0,
3944
4041
  authUrl: void 0
3945
4042
  };
3946
4043
  }
@@ -3983,35 +4080,34 @@ async function _scan(params, { skipPrompts = false } = {}) {
3983
4080
  throw new Error("repo is required in case srcPath is not provided");
3984
4081
  }
3985
4082
  const userInfo = await gqlClient.getUserInfo();
3986
- const { githubToken, gitlabToken, adoToken, adoOrg } = userInfo;
4083
+ const tokenInfo = getScmConfig({
4084
+ url: repo,
4085
+ scmConfigs: userInfo.scmConfigs,
4086
+ includeOrgTokens: false
4087
+ });
3987
4088
  const isRepoAvailable = await scmCanReachRepo({
3988
4089
  repoUrl: repo,
3989
- githubToken,
3990
- gitlabToken,
3991
- adoToken,
3992
- scmOrg: adoOrg
4090
+ accessToken: tokenInfo.accessToken,
4091
+ scmOrg: tokenInfo.scmOrg,
4092
+ scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
3993
4093
  });
3994
- const scmLibType = getScmLibTypeFromUrl(repo);
3995
- const { authUrl: scmAuthUrl, token } = _getTokenAndUrlForScmType({
3996
- scmLibType,
3997
- githubToken,
3998
- gitlabToken,
3999
- adoToken
4094
+ const cloudScmLibType = getCloudScmLibTypeFromUrl(repo);
4095
+ const { authUrl: scmAuthUrl } = _getUrlForScmType({
4096
+ scmLibType: cloudScmLibType
4000
4097
  });
4001
- let myToken = token;
4098
+ let myToken = tokenInfo.accessToken;
4002
4099
  if (!isRepoAvailable) {
4003
- if (ci || !scmLibType || !scmAuthUrl) {
4100
+ if (ci || !cloudScmLibType || !scmAuthUrl) {
4004
4101
  const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
4005
4102
  throw new Error(errorMessage);
4006
4103
  }
4007
- if (scmLibType && scmAuthUrl) {
4008
- myToken = await handleScmIntegration(token, scmLibType, scmAuthUrl) || "";
4104
+ if (cloudScmLibType && scmAuthUrl) {
4105
+ myToken = await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo) || "";
4009
4106
  const isRepoAvailable2 = await scmCanReachRepo({
4010
4107
  repoUrl: repo,
4011
- githubToken: myToken,
4012
- gitlabToken: myToken,
4013
- adoToken: myToken,
4014
- scmOrg: adoOrg
4108
+ accessToken: myToken,
4109
+ scmOrg: tokenInfo.scmOrg,
4110
+ scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
4015
4111
  });
4016
4112
  if (!isRepoAvailable2) {
4017
4113
  throw new Error(
@@ -4022,9 +4118,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
4022
4118
  }
4023
4119
  const scm = await SCMLib.init({
4024
4120
  url: repo,
4025
- accessToken: token,
4026
- scmType: scmLibType,
4027
- scmOrg: adoOrg
4121
+ accessToken: myToken,
4122
+ scmOrg: tokenInfo.scmOrg,
4123
+ scmType: tokenInfo.scmLibType
4028
4124
  });
4029
4125
  const reference = ref ?? await scm.getRepoDefaultBranch();
4030
4126
  const { sha } = await scm.getReferenceData(reference);
@@ -4196,8 +4292,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
4196
4292
  throw new CliError2();
4197
4293
  }
4198
4294
  }
4199
- async function handleScmIntegration(oldToken, scmLibType2, scmAuthUrl2) {
4200
- const scmName = scmLibType2 === "GITHUB" /* GITHUB */ ? "Github" : scmLibType2 === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType2 === "ADO" /* ADO */ ? "Azure DevOps" : "";
4295
+ async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
4296
+ const scmLibType = getCloudScmLibTypeFromUrl(repoUrl);
4297
+ const scmName = scmLibType === "GITHUB" /* GITHUB */ ? "Github" : scmLibType === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType === "ADO" /* ADO */ ? "Azure DevOps" : "";
4201
4298
  const addScmIntegration = skipPrompts ? true : await scmIntegrationPrompt(scmName);
4202
4299
  const scmSpinner = createSpinner4(
4203
4300
  `\u{1F517} Waiting for ${scmName} integration...`
@@ -4211,14 +4308,15 @@ async function _scan(params, { skipPrompts = false } = {}) {
4211
4308
  );
4212
4309
  await open2(scmAuthUrl2);
4213
4310
  for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
4214
- const { githubToken: githubToken2, gitlabToken: gitlabToken2 } = await gqlClient.getUserInfo();
4215
- if (scmLibType2 === "GITHUB" /* GITHUB */ && githubToken2 !== oldToken) {
4216
- scmSpinner.success({ text: "\u{1F517} Github integration successful!" });
4217
- return githubToken2;
4218
- }
4219
- if (scmLibType2 === "GITLAB" /* GITLAB */ && gitlabToken2 !== oldToken) {
4220
- scmSpinner.success({ text: "\u{1F517} Gitlab integration successful!" });
4221
- return gitlabToken2;
4311
+ const userInfo2 = await gqlClient.getUserInfo();
4312
+ const tokenInfo2 = getScmConfig({
4313
+ url: repoUrl,
4314
+ scmConfigs: userInfo2.scmConfigs,
4315
+ includeOrgTokens: false
4316
+ });
4317
+ if (tokenInfo2.accessToken && tokenInfo2.accessToken !== oldToken) {
4318
+ scmSpinner.success({ text: `\u{1F517} ${scmName} integration successful!` });
4319
+ return tokenInfo2.accessToken;
4222
4320
  }
4223
4321
  scmSpinner.spin();
4224
4322
  await sleep(LOGIN_CHECK_DELAY);
@@ -4373,12 +4471,16 @@ var packageJson2 = JSON.parse(
4373
4471
  );
4374
4472
  var config3 = new Configstore2(packageJson2.name, { apiToken: "" });
4375
4473
  async function addScmToken(addScmTokenOptions) {
4376
- const { apiKey, token, organization, scm, username, refreshToken } = addScmTokenOptions;
4474
+ const { apiKey, token, organization, scmType, url, username, refreshToken } = addScmTokenOptions;
4377
4475
  const gqlClient = new GQLClient({
4378
4476
  apiKey: apiKey || config3.get("apiToken")
4379
4477
  });
4478
+ if (!scmType) {
4479
+ throw new CliError(errorMessages.invalidScmType);
4480
+ }
4380
4481
  await gqlClient.updateScmToken({
4381
- type: scm,
4482
+ scmType,
4483
+ url,
4382
4484
  token,
4383
4485
  org: organization,
4384
4486
  username,
@@ -4462,9 +4564,16 @@ var commitHashOption = {
4462
4564
  type: "string"
4463
4565
  };
4464
4566
  var scmTypeOption = {
4567
+ demandOption: true,
4465
4568
  describe: chalk5.bold("SCM type (GitHub, GitLab, Ado)"),
4466
4569
  type: "string"
4467
4570
  };
4571
+ var urlOption = {
4572
+ describe: chalk5.bold(
4573
+ "URL of the repository (used in GitHub, GitLab, Azure DevOps)"
4574
+ ),
4575
+ type: "string"
4576
+ };
4468
4577
  var scmOrgOption = {
4469
4578
  describe: chalk5.bold("Organization name in SCM (used in Azure DevOps)"),
4470
4579
  type: "string"
@@ -4651,29 +4760,32 @@ async function scanHandler(args) {
4651
4760
 
4652
4761
  // src/args/commands/token.ts
4653
4762
  function addScmTokenBuilder(args) {
4654
- return args.option("scm", scmTypeOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
4655
- "$0 add-scm-token --scm ado --token abcdef0123456 --organization myOrg",
4763
+ return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
4764
+ "$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
4656
4765
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
4657
- ).help().demandOption(["scm", "token"]);
4766
+ ).help().demandOption(["url", "token"]);
4658
4767
  }
4659
4768
  function validateAddScmTokenOptions(argv) {
4660
- if (!argv.scm) {
4661
- throw new CliError(errorMessages.missingScmType);
4662
- }
4663
- if (!Object.values(ScmTypes).includes(argv.scm)) {
4664
- throw new CliError(errorMessages.invalidScmType);
4769
+ if (!argv.url) {
4770
+ throw new CliError(errorMessages.missingUrl);
4665
4771
  }
4666
4772
  if (!argv.token) {
4667
4773
  throw new CliError(errorMessages.missingToken);
4668
4774
  }
4669
- if (argv.scm === ScmTypes.AzureDevOps && !argv.organization) {
4775
+ if ("GitHub" /* GitHub */ !== argv.scmType && "Ado" /* Ado */ !== argv.scmType && "GitLab" /* GitLab */ !== argv.scmType) {
4670
4776
  throw new CliError(
4671
- "\nError: --organization flag is required for Azure DevOps"
4777
+ "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado)"
4672
4778
  );
4673
4779
  }
4674
- if (argv.scm === ScmTypes.Github && !argv.username) {
4780
+ const urlObj = new URL(argv.url);
4781
+ if (urlObj.hostname === "github.com" && !argv.username) {
4675
4782
  throw new CliError("\nError: --username flag is required for GitHub");
4676
4783
  }
4784
+ if ((urlObj.hostname === "dev.azure.com" || urlObj.hostname.endsWith(".visualstudio.com")) && !argv.organization) {
4785
+ throw new CliError(
4786
+ "\nError: --organization flag is required for Azure DevOps"
4787
+ );
4788
+ }
4677
4789
  }
4678
4790
  async function addScmTokenHandler(args) {
4679
4791
  validateAddScmTokenOptions(args);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "0.0.83",
3
+ "version": "0.0.84",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "https://github.com/mobb-dev/bugsy",
6
6
  "main": "dist/index.js",