services/solidService.js

const fs = require('fs')
const rimraf = require('rimraf')
const { v4: uuidv4 } = require('uuid')
const N3 = require('n3')

const profilePathName = 'profile.n3'

/**
 * This class provided an access point to a users solid pod
 * Everything that has solid interaction will go through this class
 * The api assumes a statelessness so for each request a new Object is required
 */
class SolidService {
  /**
   * Initialize the user webID and the location of the temporal storage
   */
  constructor () {
    this.storageLocation = 'data/temp/'
    this.validated = null
    this.tempDir = this.createUniqueName()
    this.createStoragePlace()
  }

  /**
    * Generate a unique temporal name for this solid service
    */
  createUniqueName () {
    return uuidv4()
  }

  /**
   * Create asynchronous the storage place
   */
  async createStoragePlace () {
    await fs.promises.mkdir(this.storageLocation + this.tempDir, { recursive: true })
  }

  /**
   * Whipe the data of the user, the service itself will be cleaned up by the garbage collector
   * rimraf is the equivalent of UNIX rm -rf, if you want to store certain parts change this
   * Need to call this manually
   */
  removeUserData () {
    rimraf(this.storageLocation + this.tempDir, (err) => {
      if (err) return err // handle this error
    })
  }

  /**
   * Insert user storage in predefined list of files so the reasoner can execute specific for this person
   *
   * @param {object} inference current inference used by the eye reasoner
   */
  injectUserStorageLocation (inference) {
    if (!('data' in inference)) {
      inference.data = []
    }
    inference.data = inference.data.filter(e => !e.match(this.storageLocation))
    inference.data.push('./' + this.storageLocation + this.tempDir + '/*')
  }

  /**
   * Upload the data to storage place so the EYE reasoner can use it
   *
   * @param {string} data file provided by post of the user
   */
  uploadProfileToPersonalStorage (data) {
    try {
      const parser = new N3.Parser({ format: 'text/turtle' })
      parser.parse(data)
      fs.writeFile(this.storageLocation + this.tempDir + '/' + profilePathName, data,
        (err) => {
          if (err) {
            return err
          }
        })
    } catch (e) {
      this.validated = e
    }
  }

  /**
   * DEPRECATED: NO DOUBLE AUTHENTICATION
   * Log in user for the current session
   * TODO check if multiple diff pods can connect
   * TODO change current auth login, a hardcode test login, localhost wont't work
   */
  /* async login () {
    const auth = require('solid-auth-cli')
    let session = await auth.currentSession()
    if (!session) {
      session = await auth.login()
    }
    this.webID = session.webID
    return session
  }
  */
}

module.exports = SolidService