Skip to content

Commit

Permalink
Merge pull request #71 from mediumroast/alpha_2_delete_objects
Browse files Browse the repository at this point in the history
Alpha 2 delete objects
  • Loading branch information
miha42-github authored Jan 7, 2024
2 parents 479c4e8 + b3c50df commit 3affcfa
Show file tree
Hide file tree
Showing 8 changed files with 404 additions and 168 deletions.
49 changes: 36 additions & 13 deletions cli/mrcli-company.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import CLIOutput from '../src/cli/output.js'
import FilesystemOperators from '../src/cli/filesystem.js'
import ArchivePackage from '../src/cli/archive.js'
import ora from 'ora'
import WizardUtils from '../src/cli/commonWizard.js'

// Related object type
const objectType = 'Companies'
Expand All @@ -33,8 +34,16 @@ const environment = new Environmentals(
// Filesystem object
const fileSystem = new FilesystemOperators()

// Create the environmental settings
const myArgs = environment.parseCLIArgs()
// Process the command line options
let myProgram = environment.parseCLIArgs(true)
myProgram
.option('-o, --allow_orphans', 'Allow orphaned interactions to remain in the system', false)

// Parse the command line arguments into myArgs and obtain the options
let myArgs = myProgram.parse(process.argv)
myArgs = myArgs.opts()

// Read the environmental settings
const myConfig = environment.readConfig(myArgs.conf_file)
let myEnv = environment.getEnv(myArgs, myConfig)
const accessToken = await environment.verifyAccessToken()
Expand All @@ -43,6 +52,9 @@ const processName = 'mrcli-company'
// Output object
const output = new CLIOutput(myEnv, objectType)

// CLI Wizard object
const wutils = new WizardUtils()

// Construct the controller objects
const companyCtl = new Companies(accessToken, myEnv.gitHubOrg, processName)
// const studyCtl = new Studies(accessToken, myEnv.gitHubOrg, processName)
Expand Down Expand Up @@ -213,17 +225,28 @@ if (myArgs.report) {
}
// TODO: Need to reimplement the below to account for GitHub
} else if (myArgs.delete) {
console.error('ERROR (%d): Delete not implemented.', -1)
process.exit(-1)
// Delete an object
const [success, stat, resp] = await companyCtl.deleteObj(myArgs.delete)
if(success) {
console.log(`SUCCESS: deleted company object.`)
process.exit(0)
} else {
console.error('ERROR (%d): Unable to delete company object.', -1)
process.exit(-1)
}
// Use operationOrNot to confirm the delete
const deleteOrNot = await wutils.operationOrNot(`Preparing to delete the company [${myArgs.delete}], are you sure?`)
if(!deleteOrNot) {
console.log(`INFO: Delete of [${myArgs.delete}] cancelled.`)
process.exit(0)
}
// If allow_orphans is set log a warning to the user that they are allowing orphaned interactions
if(myArgs.allow_orphans) {
console.log(chalk.bold.yellow(`WARNING: Allowing orphaned interactions to remain in the system.`))
}
// Delete the object
const mySpinner = new ora(`Deleting company [${myArgs.delete}] ...`)
mySpinner.start()
const [success, stat, resp] = await companyCtl.deleteObj(myArgs.delete, myArgs.allow_orphans)
mySpinner.stop()
if(success) {
console.log(`SUCCESS: ${stat.status_msg}`)
process.exit(0)
} else {
console.log(`ERROR: ${stat.status_msg}`)
process.exit(-1)
}
} else if (myArgs.add_wizard) {
myEnv.DEFAULT = {company: 'Unknown'}
const newCompany = new AddCompany(myEnv, companyCtl)
Expand Down
24 changes: 16 additions & 8 deletions cli/mrcli-interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ import CLIOutput from '../src/cli/output.js'
import FilesystemOperators from '../src/cli/filesystem.js'
import ArchivePackage from '../src/cli/archive.js'
import ora from 'ora'

// External modules
import chalk from 'chalk'
import WizardUtils from "../src/cli/commonWizard.js"

// Reset the status of objects for caffiene reprocessing
async function resetStatuses(interactionType, interactionCtl, objStatus=0) {
Expand Down Expand Up @@ -78,6 +76,9 @@ const processName = 'mrcli-interaction'
// Output object
const output = new CLIOutput(myEnv, objectType)

// Common wizard utilities
const wutils = new WizardUtils(objectType)

// Construct the controller objects
const companyCtl = new Companies(accessToken, myEnv.gitHubOrg, processName)
const interactionCtl = new Interactions(accessToken, myEnv.gitHubOrg, processName)
Expand Down Expand Up @@ -196,15 +197,22 @@ if (myArgs.report) {
process.exit(-1)
}
} else if (myArgs.delete) {
console.error('ERROR (%d): Delete not implemented.', -1)
process.exit(-1)
// Delete an object
// Use operationOrNot to confirm the delete
const deleteOrNot = await wutils.operationOrNot(`Preparing to delete the interaction [${myArgs.delete}], are you sure?`)
if(!deleteOrNot) {
console.log(`INFO: Delete of [${myArgs.delete}] cancelled.`)
process.exit(0)
}
// Delete the object
const mySpinner = new ora(`Deleting interaction [${myArgs.delete}] ...`)
mySpinner.start()
const [success, stat, resp] = await interactionCtl.deleteObj(myArgs.delete)
mySpinner.stop()
if(success) {
console.log(`SUCCESS: deleted interaction object.`)
console.log(`SUCCESS: ${stat.status_msg}`)
process.exit(0)
} else {
console.error('ERROR (%d): Unable to delete interaction object.', -1)
console.log(`ERROR: ${stat.status_msg}`)
process.exit(-1)
}
} else if (myArgs.add_wizard) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mediumroast_js",
"version": "0.4.19",
"version": "0.4.25",
"description": "A Command Line Interface (CLI) and Javascript SDK to interact with mediumroast.io.",
"main": "cli/mrcli.js",
"scripts": {
Expand Down
42 changes: 10 additions & 32 deletions src/api/authorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import crypto from "node:crypto"
import open from "open"
import * as octoDevAuth from '@octokit/auth-oauth-device'
import chalk from "chalk"
import Table from 'cli-table'


class Auth0Auth {
Expand Down Expand Up @@ -226,17 +227,17 @@ class GitHubAuth {
clientId: env.clientId,
onVerification(verifier) {
deviceCode = verifier.device_code
// Print the verification artifact to the console
console.log(
chalk.blue.bold(
`
If your platform supports this, opening your browser. Otherwise, navigate to the URL below in your browser.
\n\tAuthorization URL: ${verifier.verification_uri}
Type or paste the code below into your browser and follow the prompts to authorize this client.
\n\tDevice authorization code: ${verifier.user_code}
`

)
chalk.blue.bold(`If your OS supports it, opening your browser, otherwise, navigate to the website below.\n`)
)
const table = new Table({
rows: [
[chalk.blue.bold(`Authorization website:`), chalk.bold.red(verifier.verification_uri)],
[chalk.blue.bold(`Authorization code:`), chalk.bold.red(verifier.user_code)]
]
})
console.log(table.toString())
open(verifier.verification_uri)
}
})
Expand All @@ -253,29 +254,6 @@ class GitHubAuth {
return accessToken
}


/**
* @function refreshAccessToken
* @description Assuming device flow authorization, generate a new access token from a valid refresh token
* @param {String} clientId - The clientId for the device
* @param {String} refreshToken - A valid unexpired refresh token
* @param {String} accessTokenUrl - Url needed to obtain the access token using a refresh token
* @param {String} contentType - Accepted content type defaults to 'application/json'
* @param {String} grantType - Targeted grant type defaults to 'refresh_token'
* @returns {Array} An array with position 0 being boolean to signify sucess/failure and position 1 being token data/err string
*/
async refreshAccessToken(clientId, refreshToken, accessTokenUrl, contentType='application/json', grantType='refresh_token'){

try {
const resp = await axios.post(accessTokenUrl, null, {
params: {grant_type: grantType, refresh_token: refreshToken,client_id: clientId},
headers: {Accept: contentType},
})
return [true, resp.data]
} catch (err) {
return [false, err.message]
}
}
}

export {Auth0Auth, GitHubAuth}
101 changes: 94 additions & 7 deletions src/api/gitHubServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// Import required modules
import GitHubFunctions from './github.js'
import { createHash } from 'crypto'
import ora from 'ora'


class baseObjects {
Expand Down Expand Up @@ -73,12 +74,20 @@ class baseObjects {
* @param {String} value - the value for the defined attribute
* @returns {Array} the results from the called function mrRest class
*/
async findByX(attribute, value) {
async findByX(attribute, value, allObjects=null) {
if(attribute === 'name') {
value = value.toLowerCase()
}
// console.log(`Searching for ${this.objType} where ${attribute} = ${value}`)
let myObjects = []
const allObjectsResp = await this.serverCtl.readObjects(this.objType)
const allObjects = allObjectsResp[2].mrJson
if(allObjects === null) {
const allObjectsResp = await this.serverCtl.readObjects(this.objType)
allObjects = allObjectsResp[2].mrJson
}
for(const obj in allObjects) {
if(allObjects[obj][attribute] === value) {
let currentObject
attribute == 'name' ? currentObject = allObjects[obj][attribute].toLowerCase() : null
if(currentObject === value) {
myObjects.push(allObjects[obj])
}
}
Expand Down Expand Up @@ -117,9 +126,8 @@ class baseObjects {
* @returns {Array} the results from the called function mrRest class
* @todo implment when available in the backend
*/
async deleteObj(id, endpoint='delete') {
const fullEndpoint = '/' + this.apiVersion + '/' + this.objType + '/' + endpoint
return this.rest.deleteObj(fullEndpoint, {"id": id})
async deleteObj(objName, source, repoMetadata=null, catchIt=true) {
return await this.serverCtl.deleteObject(objName, source, repoMetadata, catchIt)
}

/**
Expand Down Expand Up @@ -223,6 +231,77 @@ class Companies extends baseObjects {
]
return await super.updateObj(name, key, value, dontWrite, system, whiteList)
}

async deleteObj(objName, allowOrphans=false) {
let source = {
from: 'Companies',
to: ['Interactions']
}

// If allowOrphans is true then use the baseObjects deleteObj
if(allowOrphans){
return await super.deleteObj(objName, source)
}

// Catch the Companies and Interaction containers
// Assign repoMetadata to capture Companies nad Studies
let repoMetadata = {
containers: {
Companies: {},
Interactions: {}
},
branch: {}
}
const caught = await this.serverCtl.catchContainer(repoMetadata)

// Use findByX to get all linkedInteractions
// NOTE: This has to be done here because the company has been deleted in the next step
const getCompanyObject = await this.findByX('name', objName, caught[2].containers.Companies.objects)
if(!getCompanyObject[0]) {
return getCompanyObject
}
const linkedInteractions = getCompanyObject[2][0].linked_interactions

// Delete the company
// Use deleteObj to delete the company
const deleteCompanyObjResp = await this.serverCtl.deleteObject(
objName,
source,
caught[2],
false
)
if(!deleteCompanyObjResp[0]) {
return deleteCompanyObjResp
}

// Delete all linkedInteractions
// Update source to be from the perspective of the Interactions
source = {
from: 'Interactions',
to: ['Companies']
}
// Use deleteObect to delete all linkedInteractions
for(const interaction in linkedInteractions) {
const deleteInteractionObjResp = await this.serverCtl.deleteObject(
interaction,
source,
caught[2],
false
)
if(!deleteInteractionObjResp[0]) {
return deleteInteractionObjResp
}
}

// Release the container
const relased = await this.serverCtl.releaseContainer(caught[2])
if(!relased[0]) {
return relased
}

// Return the response
return [true, {status_code: 200, status_msg: `deleted company [${objName}] and all linked interactions`}, null]
}
}


Expand Down Expand Up @@ -251,6 +330,14 @@ class Interactions extends baseObjects {
]
return await super.updateObj(name, key, value, dontWrite, system, whiteList)
}

async deleteObj(objName) {
const source = {
from: 'Interactions',
to: ['Companies']
}
return await super.deleteObj(objName, source)
}
}

// Export classes for consumers
Expand Down
Loading

0 comments on commit 3affcfa

Please sign in to comment.