From 832d4bf771f9094a3e4769e99f5f004fdc8ebb21 Mon Sep 17 00:00:00 2001 From: Gabriel Viganotti Date: Tue, 22 Aug 2017 10:15:30 -0300 Subject: [PATCH] feat/Adapt to changes in safe_client_libs for containers permissions format (#131) --- package.json | 2 +- src/api/auth.js | 22 +++++++++++----- src/native/_auth.js | 63 ++++++++++++++++++++++----------------------- test/auth.js | 34 +++++++++++++++++------- test/mutable.js | 2 +- 5 files changed, 72 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index b716987..0b8b556 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ }, "safe_app": { "mirror": "https://s3.eu-west-2.amazonaws.com/safe-client-libs", - "version": "f576719", + "version": "96a73c3", "targetDir": "src/native", "filename": "safe_app", "filePattern": "^.*\\.(dll|so|dylib)$", diff --git a/src/api/auth.js b/src/api/auth.js index b4fb71f..296a0ab 100644 --- a/src/api/auth.js +++ b/src/api/auth.js @@ -205,17 +205,18 @@ class AuthInterface { } /** - * Get the names of all containers found. - * @return {Promise<[String]>} + * Get the names of all containers found and the app's granted + * permissions for each of them. + * @return {Promise<[ContainersPerms]>} */ - getContainersNames() { - return lib.access_container_get_names(this.app.connection); + getContainersPermissions() { + return lib.access_container_fetch(this.app.connection); } /** * Get the MutableData for the app's own container generated by Authenticator. * When run in tests, this falls back to the randomly generated version - * @return {Promise<[String]} + * @return {Promise} */ getOwnContainer() { const appInfo = this.app.appInfo; @@ -229,7 +230,8 @@ class AuthInterface { prms = prms.catch((err) => { // Error code -1002 corresponds to 'Container not found' case if (err.code !== -1002) return Promise.reject(err); - return this.getContainersNames().then((names) => { + return this.getContainersPermissions().then((contPerms) => { + const names = Object.keys(contPerms); const ctrnName = names.find((x) => x.match(/^apps\//)); if (!ctrnName) return Promise.reject(err); return this.getContainer(ctrnName); @@ -254,7 +256,13 @@ class AuthInterface { perms = permissions; } } - return lib.access_container_is_permitted(this.app.connection, name, perms); + + return this.getContainersPermissions() + .then((containersPerms) => { + const contPerms = containersPerms[name]; + const result = perms.every((perm) => contPerms[perm]); + return Promise.resolve(result); + }); } /** diff --git a/src/native/_auth.js b/src/native/_auth.js index 7699466..5684f6c 100644 --- a/src/native/_auth.js +++ b/src/native/_auth.js @@ -17,8 +17,6 @@ const AppExchangeInfo = Struct({ vendor: 'string' }); -const ContainerNames = new ArrayType('char *'); - const PermissionSet = Struct({ Read: t.bool, Insert: t.bool, @@ -192,24 +190,22 @@ module.exports = { encode_share_mdata_req: [t.Void, [ref.refType(ShareMDataReq), 'pointer', 'pointer'] ], encode_unregistered_req: [t.Void, ['pointer', 'pointer'] ], decode_ipc_msg: [t.Void, [ - "string", // (msg: *const c_char, + 'string', // (msg: *const c_char, t.VoidPtr, // user_data: *mut c_void, - "pointer", // o_auth: extern "C" fn(*mut c_void, u32, FfiAuthGranted), - "pointer", // o_unregistered: extern "C" fn(*mut c_void, u32, *const u8, usize), - "pointer", // o_containers: extern "C" fn(*mut c_void, u32), - "pointer", // o_share_mdata: extern "C" fn(*mut c_void, u32), - "pointer", // o_revoked: extern "C" fn(*mut c_void), - "pointer" // o_err: extern "C" fn(*mut c_void, i32, u32) + 'pointer', // o_auth: extern "C" fn(*mut c_void, u32, FfiAuthGranted), + 'pointer', // o_unregistered: extern "C" fn(*mut c_void, u32, *const u8, usize), + 'pointer', // o_containers: extern "C" fn(*mut c_void, u32), + 'pointer', // o_share_mdata: extern "C" fn(*mut c_void, u32), + 'pointer', // o_revoked: extern "C" fn(*mut c_void), + 'pointer' // o_err: extern "C" fn(*mut c_void, i32, u32) ] ], // access container: - // app: *const App, user_data: *mut c_void, o_cb: extern "C" fn(*mut c_void, i32, *const *const c_char, u32)) - access_container_get_names: [t.Void, [AppPtr, "pointer", "pointer"]], + // app: *const App, user_data: *mut c_void, o_cb: extern "C" fn(*mut c_void, i32, *const ContainerPermissions, usize)) + access_container_fetch: [t.Void, [AppPtr, 'pointer', 'pointer']], // app: *const App, user_data: *mut c_void, o_cb: extern "C" fn(*mut c_void, i32) - access_container_refresh_access_info: [t.Void, [AppPtr, "pointer", "pointer"]], + access_container_refresh_access_info: [t.Void, [AppPtr, 'pointer', 'pointer']], // app: *const App, name: FfiString, user_data: *mut c_void, o_cb: extern "C" fn(*mut c_void, i32, MDataInfoHandle) - access_container_get_container_mdata_info: [t.Void, [AppPtr, 'string', "pointer", "pointer"]], - // (app: *const App, name: FfiString, permission: Permission, user_data: *mut c_void, o_cb: extern "C" fn(*mut c_void, i32, bool)) { - access_container_is_permitted: [t.Void, [AppPtr, 'string', ContainerPermissionsArray, "pointer", "pointer"]], + access_container_get_container_mdata_info: [t.Void, [AppPtr, 'string', 'pointer', 'pointer']], }, helpers: { makeAppInfo, @@ -217,24 +213,27 @@ module.exports = { makeShareMDataPermissions, }, api: { - access_container_get_names: helpers.Promisified(null, ["pointer", 'uint32'], (args) => { + access_container_fetch: helpers.Promisified(null, [ref.refType(ContainerPermissions), t.usize], (args) => { const ptr = args[0]; const len = args[1]; - const names = []; - const PTR_SIZE = ptr.ref().length; - for (let i = 0; i < len; i++) { - let name = ref.readCString(ref.readPointer(ptr, i* PTR_SIZE , (i + 1) * PTR_SIZE)); - names.push(name); + let arrPtr = ref.reinterpret(ptr, ContainerPermissions.size * len); + let arr = ContainerPermissionsArray(arrPtr) + const contsPerms = {}; + for (let i = 0; i < len ; i++) { + let cont = arr[i]; + contsPerms[cont.cont_name] = { + Read: cont.access.Read, + Insert: cont.access.Insert, + Update: cont.access.Update, + Delete: cont.access.Delete, + ManagePermissions: cont.access.ManagePermissions + } } - return names; + return contsPerms; }), access_container_refresh_access_info: helpers.Promisified(), access_container_get_container_mdata_info: helpers.Promisified((app, str) => [app, str], 'pointer'), - access_container_is_permitted: helpers.Promisified((app, str, perms) => { - const permArray = makePermissionsSet(perms); - return [app, str, permArray] - }, t.bool), encode_containers_req: helpers.Promisified(null, ['uint32', 'char *'], remapEncodeValues), encode_auth_req: helpers.Promisified(null, ['uint32', 'char *'], remapEncodeValues), encode_share_mdata_req: helpers.Promisified(null, ['uint32', 'char *'], remapEncodeValues), @@ -244,22 +243,22 @@ module.exports = { return new Promise(function(resolve, reject) { fn.async(str, ref.NULL, - ffi.Callback("void", [t.VoidPtr, "uint32", ref.refType(AuthGranted)], function(user_data, req_id, authGranted) { + ffi.Callback('void', [t.VoidPtr, 'uint32', ref.refType(AuthGranted)], function(user_data, req_id, authGranted) { resolve(["granted", authGranted]) }), - ffi.Callback("void", [t.VoidPtr, "uint32", t.u8Pointer, t.usize], function(user_data, req_id, connUri, connUriLen) { + ffi.Callback('void', [t.VoidPtr, 'uint32', t.u8Pointer, t.usize], function(user_data, req_id, connUri, connUriLen) { resolve(["unregistered", new Buffer(ref.reinterpret(connUri, connUriLen, 0))]) }), - ffi.Callback("void", [t.VoidPtr, "uint32"], function(user_data, req_id) { + ffi.Callback('void', [t.VoidPtr, 'uint32'], function(user_data, req_id) { resolve(["containers", req_id]) }), - ffi.Callback("void", [t.VoidPtr, "uint32"], function(user_data, req_id) { + ffi.Callback('void', [t.VoidPtr, 'uint32'], function(user_data, req_id) { resolve(["share_mdata", req_id]) }), - ffi.Callback("void", [t.VoidPtr], function(user_data) { + ffi.Callback('void', [t.VoidPtr], function(user_data) { resolve(["revoked"]) }), - ffi.Callback("void", [t.VoidPtr, t.FfiResult, "uint32"], function(user_data, result, req_id) { + ffi.Callback('void', [t.VoidPtr, t.FfiResult, 'uint32'], function(user_data, result, req_id) { reject(makeFfiError(result.error_code, result.error_description)) }), function () {} diff --git a/test/auth.js b/test/auth.js index a7e9274..ba9ea64 100644 --- a/test/auth.js +++ b/test/auth.js @@ -4,7 +4,8 @@ const h = require('./helpers'); const createAuthenticatedTestApp = h.createAuthenticatedTestApp; describe('Access Container', () => { - const app = createAuthenticatedTestApp('_test_scope', { _public: ['Read'], _publicNames: ['Read', 'Insert'] }); + const containersPermissions = { _public: ['Read'], _publicNames: ['Read', 'Insert', 'ManagePermissions'] }; + const app = createAuthenticatedTestApp('_test_scope', containersPermissions); it('should have a connection object after completing app authentication', () => { should.exist(app.connection); @@ -14,11 +15,25 @@ describe('Access Container', () => { should(app.auth.registered).be.true(); }); + /* eslint-disable dot-notation */ it('get container names', () => app.auth.refreshContainersPermissions().then(() => - app.auth.getContainersNames().then((names) => { - // we always get a our own sandboxed container in tests") - should(names.length).be.equal(3); - should(names).containEql('_public'); + app.auth.getContainersPermissions().then((contsPerms) => { + // we always get a our own sandboxed container in tests + should(Object.keys(contsPerms).length).be.equal(3); + should(contsPerms['_public']).be.eql({ + Read: true, + Insert: false, + Delete: false, + Update: false, + ManagePermissions: false + }); + should(contsPerms['_publicNames']).be.eql({ + Read: true, + Insert: true, + Delete: false, + Update: false, + ManagePermissions: true + }); }))); it('get own container', () => app.auth.refreshContainersPermissions().then(() => @@ -31,14 +46,13 @@ describe('Access Container', () => { should(hasAccess).be.true(); }))); - // This is blocked by issue MAID-2265 - it.skip('has read access to `_public` for `Read` and Insert`', () => app.auth.refreshContainersPermissions().then(() => + it('has read access to `_public` for `Read` and Insert`', () => app.auth.refreshContainersPermissions().then(() => app.auth.canAccessContainer('_public', ['Read', 'Insert']).then((hasAccess) => { should(hasAccess).be.false(); }))); - it('has read access to `_publicNames` for `Read` and Insert`', () => app.auth.refreshContainersPermissions().then(() => - app.auth.canAccessContainer('_publicNames', ['Read', 'Insert']).then((hasAccess) => { + it('has read access to `_publicNames` for `Read` and ManagePermissions`', () => app.auth.refreshContainersPermissions().then(() => + app.auth.canAccessContainer('_publicNames', ['Read', 'ManagePermissions']).then((hasAccess) => { should(hasAccess).be.true(); }))); @@ -52,7 +66,7 @@ describe('Access Container', () => { should(resp.tag).equal(15000); }))); - it('mutate info of `_public` container', () => app.auth.refreshContainersPermissions().then(() => + it('mutate info of `_publicNames` container', () => app.auth.refreshContainersPermissions().then(() => app.auth.getContainer('_publicNames') .then((md) => md.getEntries() .then((entries) => entries.mutate() diff --git a/test/mutable.js b/test/mutable.js index 3173634..b5efe74 100644 --- a/test/mutable.js +++ b/test/mutable.js @@ -860,7 +860,7 @@ describe('Mutable Data', () => { ) ); - it.skip('nfs creation and modification date for read', () => { + it('nfs creation and modification date for read', () => { let creationDate; return app.mutableData.newRandomPrivate(TAG_TYPE) .then((m) => m.quickSetup({}).then(() => m.emulateAs('NFS')))