Otto-AA / solid-filemanager

A file manager for solid pods.
https://otto-aa.github.io/solid-filemanager/
35 stars 18 forks source link

zip/unzip with acl #30

Open bourgeoa opened 4 years ago

bourgeoa commented 4 years ago

Can you add to your app zip with acl and unzip with validity control for acl.

I took inspiration from your work to implement zip/unzip in solid-ide. I improved the functions so as to zip with acl and unzip with validity control for acl

- `unzip with validity control`, uses fc.rdf.query() to make the following controls : 
-- acl is a valid rdf turtle
-- either webId or everybody has 'control'
-- `accessTo` links to parent file or parentFolder
// check for acl resource
    if (!itemName.endsWith('.acl')) {
      await self.updateFile(path, itemName, blob, contentType) // path+'/'
    } else {
    // read .acl content as text and check acl content for Webid or public (authorization, Control, accessTo)
    // groups are not checked for 'Control'
    blob.text().then(async content => {
      this.aclErr = ''

      // check if webId has control (use of aclAgent() or aclControl())
      const webId = Object.fromEntries(new Map([[app.webId, '']]))
      self.aclControl(destination, relativePath, content, null, null , webId)
      .then( async res => {
        if(res === 'incorrect rdf') return self.acl = self.acl.concat([relativePath + ': ' + self.err])
        if (res === 'acl') return await self.updateFile(path, itemName, content, contentType).catch(err => self.err = err)
    if (res === 'noAgent' || res === 'noControl') {
      this.aclErr = 'no "Control" for webId or everybody'

      // or check if everybody has control (use of aclAgent() or aclControl())
      self.aclControl(destination, relativePath, content, null, { acl: 'accessTo' }, null)
      .then( async res => {
      if (res === 'acl') return await self.updateFile(path, itemName, content, contentType).catch(err => self.err = err)                                
      else { self.acl = self.acl.concat([relativePath + ' : ' + this.aclErr]) }
      })
    }
      })
      .catch(err => self.err = err)     
The controls uses an aclControl() function

this.aclControl = async (path, itemName, content, s, p ,o) => { try { // find acl block for an agent const aclControl = await fc.rdf.queryTurtle(path+itemName,content, s, { acl: 'mode'}, { acl : 'Control' }) //s, p, o) if(!aclControl.length) { return self.err = 'noControl' }

await aclControl.map(async ({subject: item}) => {
// check if agent has 'Control' (check if 'write' could be enough with atomic delete)
const aclAgent = await fc.rdf.query(path+itemName, item, p, o) // { acl: 'mode'}, { acl : 'Control' })
if(!aclAgent.length) { return self.err = 'noAgent' }

// check if accessTo is correct
obj = Object.fromEntries(new Map([[(path+itemName).split('.acl')[0], '']]))
const aclAccessTo = await fc.rdf.query(path+itemName, item, { acl: 'accessTo' }, obj)
if(!aclAccessTo.length) { self.acl = self.acl.concat([itemName + ' wrong accessTo resource']); return self.err = 'noAccessTo' }
/* not used (not formally needed with NSS) : check for default and authorization
// check for default for folder.acl
if ((path+itemName).split('.acl')[0].endsWith('/')) {
const aclDefault = await fc.rdf.query(path+itemName, item, { acl: 'default' }, obj)
if(!aclDefault.length) { self.acl = self.acl.concat([itemName + ' folder should have acl:default'])} //; return self.err = 'noAuthorization' }
}

// check for authorization not a blocking error
const aclAuthorization = await fc.rdf.query(path+itemName, item, null, { acl: 'Authorization' })
if(!aclAuthorization.length) { self.acl = self.acl.concat([itemName + ' no acl:authorization'])} // ;       return self.err = 'noAuthorization' }
*/      

}) } catch( err) { self.err = err return 'incorrect rdf' } return 'acl' //self.updateFile(path, itemName, content, contentType).catch(err => self.err = err) }

Otto-AA commented 4 years ago

I'm currently not actively contributing to solid projects. I only try to keep them working and helping other people getting on, if they have some trouble. So I won't do this in the near future (and probably not at all).

Apart from that, I don't think that (un)zipping with acl files would be a top priority. In particular, a menu for handling permissions seems more useful. For the implementation this would also be useful, as one could display the user what permissions will be granted before unzipping it.

Regarding your suggested implementation I want to note, that the spec explicitly states that we shouldn't rely on the .acl for finding acl resources and I think this propagates to (un)zipping based on the .acl extension. So, while this works with NSS, I don't think it's Solid spec conform (which doesn't mean it's not useful).

And I think you can rewrite ...Object.entries(folderData.links).map(([type, item]) => item) to ...Object.values(folderData.links)