Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: atom/node-keytar
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v5.0.0-beta.0
Choose a base ref
...
head repository: atom/node-keytar
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Aug 19, 2019

  1. Bump node-abi from 2.10.0 to 2.11.0 (#218)

    Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.10.0 to 2.11.0.
    - [Release notes](https://github.com/lgeiger/node-abi/releases)
    - [Commits](electron/node-abi@v2.10.0...v2.11.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Aug 19, 2019
    Copy the full SHA
    62143df View commit details
  2. Bump prebuild from 9.0.1 to 9.1.0 (#217)

    Bumps [prebuild](https://github.com/prebuild/prebuild) from 9.0.1 to 9.1.0.
    - [Release notes](https://github.com/prebuild/prebuild/releases)
    - [Commits](prebuild/prebuild@v9.0.1...v9.1.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Aug 19, 2019
    Copy the full SHA
    f624c5d View commit details

Commits on Sep 10, 2019

  1. Bump prebuild-install from 5.3.0 to 5.3.1 (#220)

    Bumps [prebuild-install](https://github.com/prebuild/prebuild-install) from 5.3.0 to 5.3.1.
    - [Release notes](https://github.com/prebuild/prebuild-install/releases)
    - [Commits](prebuild/prebuild-install@v5.3.0...v5.3.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Sep 10, 2019
    Copy the full SHA
    9b60163 View commit details
  2. Add electron v75 (7.0.0) to prebuild (#219)

    * Add electron v75 (7.0.0) to prebuild
    
    * Update package.json
    Benjamin Kniffler authored and shiftkey committed Sep 10, 2019
    Copy the full SHA
    fd871ce View commit details
  3. 5.0.0-beta.1

    shiftkey committed Sep 10, 2019
    Copy the full SHA
    3704289 View commit details
  4. Copy the full SHA
    0650476 View commit details
  5. 5.0.0-beta.2

    shiftkey committed Sep 10, 2019
    Copy the full SHA
    1392990 View commit details

Commits on Sep 16, 2019

  1. Bump prebuild-install from 5.3.1 to 5.3.2 (#222)

    Bumps [prebuild-install](https://github.com/prebuild/prebuild-install) from 5.3.1 to 5.3.2.
    - [Release notes](https://github.com/prebuild/prebuild-install/releases)
    - [Commits](prebuild/prebuild-install@v5.3.1...v5.3.2)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Sep 16, 2019
    Copy the full SHA
    cd03761 View commit details

Commits on Oct 1, 2019

  1. Bump mocha from 6.2.0 to 6.2.1 (#226)

    Bumps [mocha](https://github.com/mochajs/mocha) from 6.2.0 to 6.2.1.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/v6.2.1/CHANGELOG.md)
    - [Commits](mochajs/mocha@v6.2.0...v6.2.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 1, 2019
    Copy the full SHA
    38405cb View commit details
  2. Bump node-gyp from 5.0.3 to 5.0.4 (#225)

    Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 5.0.3 to 5.0.4.
    - [Release notes](https://github.com/nodejs/node-gyp/releases)
    - [Changelog](https://github.com/nodejs/node-gyp/blob/v5.0.4/CHANGELOG.md)
    - [Commits](nodejs/node-gyp@v5.0.3...v5.0.4)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 1, 2019
    Copy the full SHA
    464487c View commit details
  3. 5.0.0-beta.3

    shiftkey committed Oct 1, 2019
    Copy the full SHA
    c8f7670 View commit details

Commits on Oct 8, 2019

  1. Bump prebuild from 9.1.0 to 9.1.1 (#227)

    Bumps [prebuild](https://github.com/prebuild/prebuild) from 9.1.0 to 9.1.1.
    - [Release notes](https://github.com/prebuild/prebuild/releases)
    - [Commits](prebuild/prebuild@v9.1.0...v9.1.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 8, 2019
    Copy the full SHA
    8beb1a8 View commit details
  2. Bump node-gyp from 5.0.4 to 6.0.0 (#228)

    Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 5.0.4 to 6.0.0.
    - [Release notes](https://github.com/nodejs/node-gyp/releases)
    - [Changelog](https://github.com/nodejs/node-gyp/blob/master/CHANGELOG.md)
    - [Commits](nodejs/node-gyp@v5.0.4...v6.0.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 8, 2019
    Copy the full SHA
    a95b149 View commit details

Commits on Oct 21, 2019

  1. Bump mocha from 6.2.1 to 6.2.2 (#229)

    Bumps [mocha](https://github.com/mochajs/mocha) from 6.2.1 to 6.2.2.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
    - [Commits](mochajs/mocha@v6.2.1...v6.2.2)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 21, 2019
    Copy the full SHA
    90e995c View commit details

Commits on Oct 28, 2019

  1. Bump node-abi from 2.11.0 to 2.12.0 (#232)

    Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.11.0 to 2.12.0.
    - [Release notes](https://github.com/lgeiger/node-abi/releases)
    - [Commits](electron/node-abi@v2.11.0...v2.12.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Oct 28, 2019
    Copy the full SHA
    a38fce5 View commit details
  2. Copy the full SHA
    f991307 View commit details
  3. 5.0.0-beta.4

    shiftkey committed Oct 28, 2019
    Copy the full SHA
    4bd04ba View commit details

Commits on Nov 13, 2019

  1. Bump prebuild-install from 5.3.2 to 5.3.3 (#236)

    Bumps [prebuild-install](https://github.com/prebuild/prebuild-install) from 5.3.2 to 5.3.3.
    - [Release notes](https://github.com/prebuild/prebuild-install/releases)
    - [Commits](prebuild/prebuild-install@v5.3.2...v5.3.3)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Nov 13, 2019
    Copy the full SHA
    4d733a5 View commit details
  2. Bump node-gyp from 6.0.0 to 6.0.1 (#237)

    Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 6.0.0 to 6.0.1.
    - [Release notes](https://github.com/nodejs/node-gyp/releases)
    - [Changelog](https://github.com/nodejs/node-gyp/blob/master/CHANGELOG.md)
    - [Commits](nodejs/node-gyp@v6.0.0...v6.0.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Nov 13, 2019
    Copy the full SHA
    d98b4c6 View commit details
  3. 5.0.0-beta.5

    shiftkey committed Nov 13, 2019
    Copy the full SHA
    1413ee3 View commit details
  4. Copy the full SHA
    1cef076 View commit details
  5. 5.0.0

    shiftkey committed Nov 13, 2019
    Copy the full SHA
    1f6e680 View commit details

Commits on Dec 4, 2019

  1. Bump node-abi from 2.12.0 to 2.13.0 (#240)

    Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.12.0 to 2.13.0.
    - [Release notes](https://github.com/lgeiger/node-abi/releases)
    - [Commits](electron/node-abi@v2.12.0...v2.13.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Dec 4, 2019
    Copy the full SHA
    26782fd View commit details

Commits on Jan 6, 2020

  1. Bump mocha from 6.2.2 to 7.0.0 (#242)

    Bumps [mocha](https://github.com/mochajs/mocha) from 6.2.2 to 7.0.0.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
    - [Commits](mochajs/mocha@v6.2.2...v7.0.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Jan 6, 2020
    Copy the full SHA
    ec0c51b View commit details

Commits on Jan 20, 2020

  1. Bump node-gyp from 6.0.1 to 6.1.0 (#244)

    Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 6.0.1 to 6.1.0.
    - [Release notes](https://github.com/nodejs/node-gyp/releases)
    - [Changelog](https://github.com/nodejs/node-gyp/blob/master/CHANGELOG.md)
    - [Commits](nodejs/node-gyp@v6.0.1...v6.1.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Jan 20, 2020
    Copy the full SHA
    a0a0fbd View commit details
  2. Bump prebuild from 9.1.1 to 10.0.0 (#243)

    Bumps [prebuild](https://github.com/prebuild/prebuild) from 9.1.1 to 10.0.0.
    - [Release notes](https://github.com/prebuild/prebuild/releases)
    - [Commits](prebuild/prebuild@v9.1.1...v10.0.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Jan 20, 2020
    Copy the full SHA
    a404d46 View commit details

Commits on Jan 27, 2020

  1. Bump mocha from 7.0.0 to 7.0.1 (#246)

    Bumps [mocha](https://github.com/mochajs/mocha) from 7.0.0 to 7.0.1.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
    - [Commits](mochajs/mocha@v7.0.0...v7.0.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and shiftkey committed Jan 27, 2020
    Copy the full SHA
    042f70d View commit details
  2. add prebuild support for Node 13 (#238)

    * add prebuild support for Node 13 too
    
    * bump node-abi to support prebuilding for node 13
    shiftkey authored Jan 27, 2020
    Copy the full SHA
    66c11b5 View commit details
  3. 5.1.0

    shiftkey committed Jan 27, 2020
    Copy the full SHA
    3bbdbe7 View commit details

Commits on Feb 10, 2020

  1. Bump node-abi from 2.13.0 to 2.14.0 (#247)

    Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.13.0 to 2.14.0.
    - [Release notes](https://github.com/lgeiger/node-abi/releases)
    - [Commits](electron/node-abi@v2.13.0...v2.14.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Feb 10, 2020
    Copy the full SHA
    ef21fce View commit details
  2. Add support for electron 8 (#248)

    * bump node-abi to detect Electron 8
    
    * add prebuild targets for Electron 8
    romansp authored Feb 10, 2020
    Copy the full SHA
    a875b5e View commit details
  3. 5.2.0

    shiftkey committed Feb 10, 2020
    Copy the full SHA
    667ac2a View commit details

Commits on Feb 24, 2020

  1. Bump node-abi from 2.14.0 to 2.15.0 (#251)

    Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.14.0 to 2.15.0.
    - [Release notes](https://github.com/lgeiger/node-abi/releases)
    - [Commits](electron/node-abi@v2.14.0...v2.15.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Feb 24, 2020
    Copy the full SHA
    f918df4 View commit details
  2. Copy the full SHA
    e7415ab View commit details
  3. 5.3.0

    shiftkey committed Feb 24, 2020
    Copy the full SHA
    edbc3a4 View commit details

Commits on Feb 25, 2020

  1. Copy the full SHA
    a720791 View commit details
  2. 5.4.0

    shiftkey committed Feb 25, 2020
    Copy the full SHA
    8739710 View commit details

Commits on Mar 2, 2020

  1. Bump mocha from 7.0.1 to 7.1.0 (#254)

    Bumps [mocha](https://github.com/mochajs/mocha) from 7.0.1 to 7.1.0.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
    - [Commits](mochajs/mocha@v7.0.1...v7.1.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Mar 2, 2020
    Copy the full SHA
    f2216bf View commit details

Commits on Mar 23, 2020

  1. Bump mocha from 7.1.0 to 7.1.1 (#257)

    Bumps [mocha](https://github.com/mochajs/mocha) from 7.1.0 to 7.1.1.
    - [Release notes](https://github.com/mochajs/mocha/releases)
    - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
    - [Commits](mochajs/mocha@v7.1.0...v7.1.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    
    Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
    dependabot-preview[bot] authored Mar 23, 2020
    Copy the full SHA
    3c232b5 View commit details

Commits on Apr 15, 2020

  1. On mac, use SecKeyChainItemModifyAttributesAndData instead of delete …

    …and add (#260)
    Rachel Macfarlane authored Apr 15, 2020
    Copy the full SHA
    ef46bb2 View commit details
  2. 5.5.0

    shiftkey committed Apr 15, 2020
    Copy the full SHA
    d863665 View commit details

Commits on Apr 26, 2020

  1. Copy the full SHA
    d27b7ad View commit details
  2. fix checking user_name (#241)

    After converting utf8 to wchar, the wrong variable was checked, probably
    by copy-paste.
    hrantzsch authored Apr 26, 2020
    Copy the full SHA
    95d958b View commit details
  3. Copy the full SHA
    ae43983 View commit details
  4. 5.6.0

    shiftkey committed Apr 26, 2020
    Copy the full SHA
    6effd6b View commit details

Commits on Apr 29, 2020

  1. Copy the full SHA
    1945238 View commit details
  2. Copy the full SHA
    c5d5c7a View commit details

Commits on May 2, 2020

  1. Copy the full SHA
    2b1a9fa View commit details

Commits on May 10, 2020

  1. migrate keytar to napi (#268)

    John Kleinschmidt authored May 10, 2020
    Copy the full SHA
    3682c56 View commit details
  2. 6.0.0-beta.0

    shiftkey committed May 10, 2020
    Copy the full SHA
    7170f09 View commit details
Showing with 2,462 additions and 1,542 deletions.
  1. +8 −0 .github/dependabot.yml
  2. +162 −0 .github/workflows/ci.yml
  3. +40 −0 .github/workflows/codeql.yml
  4. +1 −2 .gitignore
  5. +1 −0 .node-version
  6. +0 −53 .travis.yml
  7. +4 −0 README.md
  8. +0 −32 appveyor.yml
  9. +24 −1 binding.gyp
  10. +29 −0 docker/arm64-cross-compile/Dockerfile
  11. +29 −0 docker/armv7l-cross-compile/Dockerfile
  12. +5 −21 lib/keytar.js
  13. +1,838 −1,223 package-lock.json
  14. +23 −15 package.json
  15. +36 −0 script/download-node-lib-win-arm64.ps1
  16. +2 −0 spec/keytar-spec.js
  17. +101 −83 src/async.cc
  18. +33 −15 src/async.h
  19. +40 −23 src/keytar_mac.cc
  20. +5 −1 src/keytar_win.cc
  21. +81 −73 src/main.cc
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
time: "11:00"
open-pull-requests-limit: 10
162 changes: 162 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
name: CI

on:
push:
branches: [ master ]
tags:
- v*.*.*
pull_request:
branches: [ master ]

jobs:
build:
name: ${{ matrix.friendlyName }}
env:
CC: "clang"
CXX: "clang++"
npm_config_clang: "1"

strategy:
matrix:
node-version: [15.x]
os: [ubuntu-20.04, windows-2019, macos-latest]
include:
- os: ubuntu-20.04
friendlyName: Ubuntu
- os: windows-2019
friendlyName: Windows
- os: macos-latest
friendlyName: macOS

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: |
sudo apt-get install gnome-keyring \
libsecret-1-dev \
dbus-x11 \
python3-dev
if: ${{ matrix.os == 'ubuntu-20.04' }}
name: Install additional dependencies
# This step can be removed as soon as official Windows arm64 builds are published:
# https://github.com/nodejs/build/issues/2450#issuecomment-705853342
- run: |
$NodeVersion = (node --version) -replace '^.'
$NodeFallbackVersion = "15.8.0"
& .\script\download-node-lib-win-arm64.ps1 $NodeVersion $NodeFallbackVersion
if: ${{ matrix.os == 'windows-2019' }}
name: Install Windows arm64 node.lib
- run: npm install
name: Setup environment

- run: npm run build
name: Build native module from source

- run: |
echo "Install keyring..."
pip3 install --upgrade pip
pip3 install keyring
echo "Prepare D-Bus session..."
eval $(dbus-launch --sh-syntax);
eval $(echo 'somecredstorepass' | gnome-keyring-daemon --unlock)
echo "Create a test key using script..."
python -c "import keyring;keyring.set_password('system', 'login', 'pwd');"
npm test
if: ${{ matrix.os == 'ubuntu-20.04' }}
name: Run tests (Linux)
- run: npm test
if: ${{ matrix.os != 'ubuntu-20.04' }}
name: Run tests (Windows/macOS)

- run: npm run prebuild-napi-x64
name: Prebuild (x64)

- run: npm run prebuild-napi-arm64
name: Prebuild (arm64)
if: ${{ matrix.os != 'ubuntu-20.04' }}

- run: npm run prebuild-napi-ia32
if: ${{ matrix.os == 'windows-2019' }}
name: Prebuild (Windows x86)

- run: |
mkdir -p prebuilds && chmod 777 prebuilds
docker build -t node-keytar/i386 docker/i386
docker run --rm -v ${PWD}:/project node-keytar/i386 /bin/bash -c "cd /project && npm run prebuild-napi-ia32 && rm -rf build"
docker build -t node-keytar/arm64-cross-compile docker/arm64-cross-compile
docker run --rm -v ${PWD}:/project node-keytar/arm64-cross-compile /bin/bash -c "cd /project && npm run prebuild-napi-arm64 && rm -rf build"
docker build -t node-keytar/armv7l-cross-compile docker/armv7l-cross-compile
docker run --rm -v ${PWD}:/project node-keytar/armv7l-cross-compile /bin/bash -c "cd /project && npm run prebuild-napi-armv7l"
if: ${{ matrix.os == 'ubuntu-20.04' }}
name: Prebuild (Linux x86 + ARM64 + ARMV7L)
- run: |
ls prebuilds/
name: List prebuilds
- name: Upload prebuilds to GitHub
run: npm run upload
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

alpine-build:
runs-on: ubuntu-latest
container: node:15-alpine3.12
steps:
- uses: actions/checkout@v2
- name: install additional dependencies
run: |
apk add g++ make python2 libsecret-dev
- run: npm install
name: Setup environment

- run: |
npm run prebuild-napi-x64
npm run prebuild-napi-arm64
name: Prebuild
- run: |
ls prebuilds/
name: List prebuilds
- name: Upload prebuilds to GitHub
run: npm run upload
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Separate step for publishing to NPM so we're sure that generating + uploading prebuilds worked on all platforms
npm-publish:
needs: [build, alpine-build]
name: Publish to NPM
runs-on: ubuntu-20.04
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')

steps:
- uses: actions/checkout@v2
- name: Use Node.js 15
uses: actions/setup-node@v1
with:
node-version: 15.x
registry-url: 'https://registry.npmjs.org'

- run: sudo apt-get install libsecret-1-dev
name: Install additional dependencies

- run: npm install
name: Setup environment

- run: npm publish --access public
name: Upload to NPM
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
40 changes: 40 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: "Code Scanning"

on: pull_request

jobs:
CodeQL:

name: ${{ matrix.friendlyName }}

runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-2019, macos-latest]
include:
- os: ubuntu-latest
friendlyName: Ubuntu
- os: windows-2019
friendlyName: Windows
- os: macos-latest
friendlyName: macOS
steps:
- name: Checkout repository
uses: actions/checkout@v2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: javascript, cpp

# Setup dependencies (and build native modules from source)
- name: Install dependencies
run: |
npm install
npm run build
# Run code analysis
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -3,9 +3,8 @@
/build
*.log
*~
.node-version
.tags
iojs-*/
8.*/
6.*/
.idea/
.idea/
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.15.1
53 changes: 0 additions & 53 deletions .travis.yml

This file was deleted.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -32,6 +32,10 @@ Depending on your distribution, you will need to run the following command:

Each release of `keytar` includes prebuilt binaries for the versions of Node and Electron that are actively supported by these projects. Please refer to the release documentation for [Node](https://github.com/nodejs/Release) and [Electron](https://electronjs.org/docs/tutorial/support) to see what is supported currently.

## Bindings from other languages

- [Rust](https://crates.io/crates/keytar)

## Docs

```javascript
32 changes: 0 additions & 32 deletions appveyor.yml

This file was deleted.

25 changes: 24 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
@@ -2,7 +2,30 @@
'targets': [
{
'target_name': 'keytar',
'include_dirs': [ '<!(node -e "require(\'nan\')")' ],
'defines': [
"NAPI_VERSION=<(napi_build_version)",
],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LIBRARY': 'libc++',
'MACOSX_DEPLOYMENT_TARGET': '10.7',
},
'msvs_settings': {
'VCCLCompilerTool': {
'ExceptionHandling': 1,
'AdditionalOptions': [
'/Qspectre',
'/guard:cf'
]
},
'VCLinkerTool': {
'AdditionalOptions': [
'/guard:cf'
]
}
},
'include_dirs': ["<!(node -p \"require('node-addon-api').include_dir\")"],
'sources': [
'src/async.cc',
'src/main.cc',
29 changes: 29 additions & 0 deletions docker/arm64-cross-compile/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM debian:buster

RUN dpkg --add-architecture arm64
RUN apt-get update && apt-get install -y --no-install-recommends \
crossbuild-essential-arm64 \
python \
git \
pkg-config \
fakeroot \
rpm \
ca-certificates \
libx11-dev:arm64 \
libx11-xcb-dev:arm64 \
libxkbfile-dev:arm64 \
libsecret-1-dev:arm64 \
curl

ENV AS=/usr/bin/aarch64-linux-gnu-as \
STRIP=/usr/bin/aarch64-linux-gnu-strip \
AR=/usr/bin/aarch64-linux-gnu-ar \
CC=/usr/bin/aarch64-linux-gnu-gcc \
CPP=/usr/bin/aarch64-linux-gnu-cpp \
CXX=/usr/bin/aarch64-linux-gnu-g++ \
LD=/usr/bin/aarch64-linux-gnu-ld \
FC=/usr/bin/aarch64-linux-gnu-gfortran \
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig

RUN curl -sL https://deb.nodesource.com/setup_15.x | bash -
RUN apt-get install -y nodejs
29 changes: 29 additions & 0 deletions docker/armv7l-cross-compile/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM debian:buster

RUN dpkg --add-architecture armhf
RUN apt-get update && apt-get install -y --no-install-recommends \
crossbuild-essential-armhf \
python \
git \
pkg-config \
fakeroot \
rpm \
ca-certificates \
libx11-dev:armhf \
libx11-xcb-dev:armhf \
libxkbfile-dev:armhf \
libsecret-1-dev:armhf \
curl

ENV AS=/usr/bin/arm-linux-gnueabihf-as \
STRIP=/usr/bin/arm-linux-gnueabihf-strip \
AR=/usr/bin/arm-linux-gnueabihf-ar \
CC=/usr/bin/arm-linux-gnueabihf-gcc \
CPP=/usr/bin/arm-linux-gnueabihf-cpp \
CXX=/usr/bin/arm-linux-gnueabihf-g++ \
LD=/usr/bin/arm-linux-gnueabihf-ld \
FC=/usr/bin/arm-linux-gnueabihf-gfortran \
PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig

RUN curl -sL https://deb.nodesource.com/setup_15.x | bash -
RUN apt-get install -y nodejs
26 changes: 5 additions & 21 deletions lib/keytar.js
Original file line number Diff line number Diff line change
@@ -6,54 +6,38 @@ function checkRequired(val, name) {
}
}

function callbackPromise(callback) {
if (typeof callback === 'function') {
return new Promise(function(resolve, reject) {
callback((err, val) => {
if (err) {
reject(err)
} else {
resolve(val)
}
})
})
} else {
throw new Error('Callback required')
}
}

module.exports = {
getPassword: function (service, account) {
checkRequired(service, 'Service')
checkRequired(account, 'Account')

return callbackPromise(callback => keytar.getPassword(service, account, callback))
return keytar.getPassword(service, account)
},

setPassword: function (service, account, password) {
checkRequired(service, 'Service')
checkRequired(account, 'Account')
checkRequired(password, 'Password')

return callbackPromise(callback => keytar.setPassword(service, account, password, callback))
return keytar.setPassword(service, account, password)
},

deletePassword: function (service, account) {
checkRequired(service, 'Service')
checkRequired(account, 'Account')

return callbackPromise(callback => keytar.deletePassword(service, account, callback))
return keytar.deletePassword(service, account)
},

findPassword: function (service) {
checkRequired(service, 'Service')

return callbackPromise(callback => keytar.findPassword(service, callback))
return keytar.findPassword(service)
},

findCredentials: function (service) {
checkRequired(service, 'Service')

return callbackPromise(callback => keytar.findCredentials(service, callback))
return keytar.findCredentials(service)
}
}
3,061 changes: 1,838 additions & 1,223 deletions package-lock.json

Large diffs are not rendered by default.

38 changes: 23 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
"typings": "keytar.d.ts",
"name": "keytar",
"description": "Bindings to native Mac/Linux/Windows password APIs",
"version": "5.0.0-beta.0",
"version": "7.9.0",
"license": "MIT",
"repository": {
"type": "git",
@@ -30,29 +30,37 @@
],
"types": "./keytar.d.ts",
"scripts": {
"install": "prebuild-install || node-gyp rebuild",
"install": "prebuild-install || npm run build",
"build": "node-gyp rebuild",
"lint": "npm run cpplint",
"cpplint": "node-cpplint --filters legal-copyright,build-include,build-namespaces src/*.cc",
"test": "npm run lint && npm build . && mocha --require babel-core/register spec/",
"prebuild-node": "prebuild -t 8.9.0 -t 9.4.0 -t 10.11.0 -t 11.9.0 -t 12.0.0 --strip",
"prebuild-node-ia32": "prebuild -t 8.9.0 -t 9.4.0 -a ia32 --strip",
"prebuild-electron": "prebuild -t 4.0.4 -t 5.0.0 -t 6.0.0 -r electron --strip",
"prebuild-electron-ia32": "prebuild -t 4.0.4 -t 5.0.0 -t 6.0.0 -r electron -a ia32 --strip",
"upload": "node ./script/upload.js",
"postpublish": "git push --follow-tags"
"test": "npm run lint && npm rebuild && mocha --require babel-core/register spec/",
"prebuild-napi-x64": "prebuild -t 3 -r napi -a x64 --strip",
"prebuild-napi-ia32": "prebuild -t 3 -r napi -a ia32 --strip",
"prebuild-napi-arm64": "prebuild -t 3 -r napi -a arm64 --strip",
"prebuild-napi-armv7l": "prebuild -t 3 -r napi -a armv7l --strip",
"upload": "node ./script/upload.js"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"chai": "^4.2.0",
"mocha": "^6.1.4",
"node-abi": "^2.10.0",
"mocha": "^9.2.0",
"node-cpplint": "~0.4.0",
"node-gyp": "^5.0.0",
"prebuild": "^9.0.0"
"node-gyp": "^8.4.1",
"prebuild": "^11.0.2"
},
"dependencies": {
"nan": "2.14.0",
"prebuild-install": "5.3.0"
"node-addon-api": "^4.3.0",
"prebuild-install": "^7.0.1"
},
"binary": {
"napi_versions": [
3
]
},
"config": {
"runtime": "napi",
"target": 3
}
}
36 changes: 36 additions & 0 deletions script/download-node-lib-win-arm64.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This script can be removed as soon as official Windows arm64 builds are published:
# https://github.com/nodejs/build/issues/2450#issuecomment-705853342

$nodeVersion = $args[0]
$fallbackVersion = $args[1]

If ($null -eq $nodeVersion -Or $null -eq $fallbackVersion) {
Write-Error "No NodeJS version given as argument to this file. Run it like download-nodejs-win-arm64.ps1 NODE_VERSION NODE_FALLBACK_VERSION"
exit 1
}

$url = "https://unofficial-builds.nodejs.org/download/release/v$nodeVersion/win-arm64/node.lib"
$fallbackUrl = "https://unofficial-builds.nodejs.org/download/release/v$fallbackVersion/win-arm64/node.lib"

# Always write to the $nodeVersion cache folder, even if we're using the fallbackVersion
$cacheFolder = "$env:TEMP\prebuild\napi\$nodeVersion\arm64"

If (!(Test-Path $cacheFolder)) {
New-Item -ItemType Directory -Force -Path $cacheFolder
}

$output = "$cacheFolder\node.lib"
$start_time = Get-Date

Try {
Invoke-WebRequest -Uri $url -OutFile $output
$downloadedNodeVersion = $nodeVersion
} Catch {
If ($_.Exception.Response -And $_.Exception.Response.StatusCode -eq "NotFound") {
Write-Output "No arm64 node.lib found for Node Windows $nodeVersion, trying fallback version $fallbackVersion..."
Invoke-WebRequest -Uri $fallbackUrl -OutFile $output
$downloadedNodeVersion = $fallbackVersion
}
}

Write-Output "Downloaded arm64 NodeJS lib v$downloadedNodeVersion to $output in $((Get-Date).Subtract($start_time).Seconds) second(s)"
2 changes: 2 additions & 0 deletions spec/keytar-spec.js
Original file line number Diff line number Diff line change
@@ -131,6 +131,8 @@ describe("keytar", function() {
})

describe("findPassword(service)", function() {
this.timeout(5000);

it("yields a password for the service", async function() {
await keytar.setPassword(service, account, password),
await keytar.setPassword(service, account2, password2)
184 changes: 101 additions & 83 deletions src/async.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <string>
#include <vector>

#include "nan.h"
#include "napi.h"
#include "keytar.h"
#include "async.h"

@@ -11,214 +11,232 @@ SetPasswordWorker::SetPasswordWorker(
const std::string& service,
const std::string& account,
const std::string& password,
Nan::Callback* callback
) : AsyncWorker(callback),
const Napi::Env &env
) : AsyncWorker(env),
service(service),
account(account),
password(password) {}
password(password),
deferred(Napi::Promise::Deferred::New(env)) {}

SetPasswordWorker::~SetPasswordWorker() {}

Napi::Promise SetPasswordWorker::Promise() {
return deferred.Promise();
}

void SetPasswordWorker::Execute() {
std::string error;
KEYTAR_OP_RESULT result = keytar::SetPassword(service,
account,
password,
&error);
if (result == keytar::FAIL_ERROR) {
SetErrorMessage(error.c_str());
SetError(error.c_str());
}
}

void SetPasswordWorker::OnOK() {
Napi::HandleScope scope(Env());
deferred.Resolve(Env().Undefined());
}

void SetPasswordWorker::OnError(Napi::Error const &error) {
Napi::HandleScope scope(Env());
deferred.Reject(error.Value());
}


GetPasswordWorker::GetPasswordWorker(
const std::string& service,
const std::string& account,
Nan::Callback* callback
) : AsyncWorker(callback),
const Napi::Env &env
) : AsyncWorker(env),
service(service),
account(account) {}
account(account),
deferred(Napi::Promise::Deferred::New(env)) {}

GetPasswordWorker::~GetPasswordWorker() {}

Napi::Promise GetPasswordWorker::Promise() {
return deferred.Promise();
}

void GetPasswordWorker::Execute() {
std::string error;
KEYTAR_OP_RESULT result = keytar::GetPassword(service,
account,
&password,
&error);
if (result == keytar::FAIL_ERROR) {
SetErrorMessage(error.c_str());
SetError(error.c_str());
} else if (result == keytar::FAIL_NONFATAL) {
success = false;
} else {
success = true;
}
}

void GetPasswordWorker::HandleOKCallback() {
Nan::HandleScope scope;
v8::Local<v8::Value> val = Nan::Null();
void GetPasswordWorker::OnOK() {
Napi::HandleScope scope(Env());
Napi::Value val = Env().Null();
if (success) {
val = Nan::New<v8::String>(password.data(),
password.length()).ToLocalChecked();
val = Napi::String::New(Env(), password.data(),
password.length());
}
v8::Local<v8::Value> argv[] = {
Nan::Null(),
val
};

callback->Call(2, argv, async_resource);
deferred.Resolve(val);
}


void GetPasswordWorker::OnError(Napi::Error const &error) {
Napi::HandleScope scope(Env());
deferred.Reject(error.Value());
}

DeletePasswordWorker::DeletePasswordWorker(
const std::string& service,
const std::string& account,
Nan::Callback* callback
) : AsyncWorker(callback),
const Napi::Env &env
) : AsyncWorker(env),
service(service),
account(account) {}
account(account),
deferred(Napi::Promise::Deferred::New(env)) {}

DeletePasswordWorker::~DeletePasswordWorker() {}

Napi::Promise DeletePasswordWorker::Promise() {
return deferred.Promise();
}

void DeletePasswordWorker::Execute() {
std::string error;
KEYTAR_OP_RESULT result = keytar::DeletePassword(service, account, &error);
if (result == keytar::FAIL_ERROR) {
SetErrorMessage(error.c_str());
SetError(error.c_str());
} else if (result == keytar::FAIL_NONFATAL) {
success = false;
} else {
success = true;
}
}

void DeletePasswordWorker::HandleOKCallback() {
Nan::HandleScope scope;
v8::Local<v8::Boolean> val =
Nan::New<v8::Boolean>(success);
v8::Local<v8::Value> argv[] = {
Nan::Null(),
val
};

callback->Call(2, argv, async_resource);
void DeletePasswordWorker::OnOK() {
Napi::HandleScope scope(Env());
deferred.Resolve(Napi::Boolean::New(Env(), success));
}


void DeletePasswordWorker::OnError(Napi::Error const &error) {
Napi::HandleScope scope(Env());
deferred.Reject(error.Value());
}

FindPasswordWorker::FindPasswordWorker(
const std::string& service,
Nan::Callback* callback
) : AsyncWorker(callback),
service(service) {}
const Napi::Env &env
) : AsyncWorker(env),
service(service),
deferred(Napi::Promise::Deferred::New(env)) {}

FindPasswordWorker::~FindPasswordWorker() {}

Napi::Promise FindPasswordWorker::Promise() {
return deferred.Promise();
}

void FindPasswordWorker::Execute() {
std::string error;
KEYTAR_OP_RESULT result = keytar::FindPassword(service,
&password,
&error);
if (result == keytar::FAIL_ERROR) {
SetErrorMessage(error.c_str());
SetError(error.c_str());
} else if (result == keytar::FAIL_NONFATAL) {
success = false;
} else {
success = true;
}
}

void FindPasswordWorker::HandleOKCallback() {
Nan::HandleScope scope;
v8::Local<v8::Value> val = Nan::Null();
void FindPasswordWorker::OnOK() {
Napi::HandleScope scope(Env());
Napi::Value val = Env().Null();
if (success) {
val = Nan::New<v8::String>(password.data(),
password.length()).ToLocalChecked();
val = Napi::String::New(Env(), password.data(),
password.length());
}
v8::Local<v8::Value> argv[] = {
Nan::Null(),
val
};

callback->Call(2, argv, async_resource);
deferred.Resolve(val);
}


void FindPasswordWorker::OnError(Napi::Error const &error) {
Napi::HandleScope scope(Env());
deferred.Reject(error.Value());
}

FindCredentialsWorker::FindCredentialsWorker(
const std::string& service,
Nan::Callback* callback
) : AsyncWorker(callback),
service(service) {}
const Napi::Env &env
) : AsyncWorker(env),
service(service),
deferred(Napi::Promise::Deferred::New(env)) {}

FindCredentialsWorker::~FindCredentialsWorker() {}

Napi::Promise FindCredentialsWorker::Promise() {
return deferred.Promise();
}

void FindCredentialsWorker::Execute() {
std::string error;
KEYTAR_OP_RESULT result = keytar::FindCredentials(service,
&credentials,
&error);
if (result == keytar::FAIL_ERROR) {
SetErrorMessage(error.c_str());
SetError(error.c_str());
} else if (result == keytar::FAIL_NONFATAL) {
success = false;
} else {
success = true;
}
}

void FindCredentialsWorker::HandleOKCallback() {
Nan::HandleScope scope;
void FindCredentialsWorker::OnOK() {
Napi::HandleScope scope(Env());
Napi::Env env = Env();

if (success) {
v8::Local<v8::Array> val = Nan::New<v8::Array>(credentials.size());
Napi::Array val = Napi::Array::New(env, credentials.size());
unsigned int idx = 0;
std::vector<keytar::Credentials>::iterator it;
for (it = credentials.begin(); it != credentials.end(); it++) {
keytar::Credentials cred = *it;
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
Napi::Object obj = Napi::Object::New(env);

v8::Local<v8::String> account = Nan::New<v8::String>(
Napi::String account = Napi::String::New(env,
cred.first.data(),
cred.first.length()).ToLocalChecked();
cred.first.length());

v8::Local<v8::String> password = Nan::New<v8::String>(
Napi::String password = Napi::String::New(env,
cred.second.data(),
cred.second.length()).ToLocalChecked();
cred.second.length());

#ifndef _WIN32
#pragma GCC diagnostic ignored "-Wunused-result"
#endif
obj->Set(
Nan::GetCurrentContext(),
Nan::New("account").ToLocalChecked(),
account);
obj.Set("account", account);
#ifndef _WIN32
#pragma GCC diagnostic ignored "-Wunused-result"
#endif
obj->Set(
Nan::GetCurrentContext(),
Nan::New("password").ToLocalChecked(),
password);
obj.Set("password", password);

Nan::Set(val, idx, obj);
(val).Set(idx, obj);
++idx;
}

v8::Local<v8::Value> argv[] = {
Nan::Null(),
val
};
callback->Call(2, argv, async_resource);
deferred.Resolve(val);
} else {
v8::Local<v8::Value> argv[] = {
Nan::Null(),
Nan::New<v8::Array>(0)
};
callback->Call(2, argv, async_resource);
deferred.Resolve(Napi::Array::New(env, 0));
}
}

void FindCredentialsWorker::OnError(Napi::Error const &error) {
Napi::HandleScope scope(Env());
deferred.Reject(error.Value());
}
48 changes: 33 additions & 15 deletions src/async.h
Original file line number Diff line number Diff line change
@@ -2,84 +2,102 @@
#define SRC_ASYNC_H_

#include <string>
#include "nan.h"
#include "napi.h"

#include "credentials.h"

class SetPasswordWorker : public Nan::AsyncWorker {
class SetPasswordWorker : public Napi::AsyncWorker {
public:
SetPasswordWorker(const std::string& service, const std::string& account, const std::string& password,
Nan::Callback* callback);
const Napi::Env &env);

~SetPasswordWorker();

void Execute();
void OnOK();
void OnError(Napi::Error const &error);
Napi::Promise Promise();

private:
const std::string service;
const std::string account;
const std::string password;
Napi::Promise::Deferred deferred;
};

class GetPasswordWorker : public Nan::AsyncWorker {
class GetPasswordWorker : public Napi::AsyncWorker {
public:
GetPasswordWorker(const std::string& service, const std::string& account, Nan::Callback* callback);
GetPasswordWorker(const std::string& service, const std::string& account,
const Napi::Env &env);

~GetPasswordWorker();

void Execute();
void HandleOKCallback();
void OnOK();
void OnError(Napi::Error const &error);
Napi::Promise Promise();

private:
const std::string service;
const std::string account;
std::string password;
bool success;
const Napi::Promise::Deferred deferred;
};

class DeletePasswordWorker : public Nan::AsyncWorker {
class DeletePasswordWorker : public Napi::AsyncWorker {
public:
DeletePasswordWorker(const std::string& service, const std::string& account, Nan::Callback* callback);
DeletePasswordWorker(const std::string& service, const std::string& account,
const Napi::Env &env);

~DeletePasswordWorker();

void Execute();
void HandleOKCallback();
void OnOK();
void OnError(Napi::Error const &error);
Napi::Promise Promise();

private:
const std::string service;
const std::string account;
bool success;
Napi::Promise::Deferred deferred;
};

class FindPasswordWorker : public Nan::AsyncWorker {
class FindPasswordWorker : public Napi::AsyncWorker {
public:
FindPasswordWorker(const std::string& service, Nan::Callback* callback);
FindPasswordWorker(const std::string& service, const Napi::Env &env);

~FindPasswordWorker();

void Execute();
void HandleOKCallback();
void OnOK();
void OnError(Napi::Error const &error);
Napi::Promise Promise();

private:
const std::string service;
std::string password;
bool success;
const Napi::Promise::Deferred deferred;
};

class FindCredentialsWorker : public Nan::AsyncWorker {
class FindCredentialsWorker : public Napi::AsyncWorker {
public:
FindCredentialsWorker(const std::string& service, Nan::Callback* callback);
FindCredentialsWorker(const std::string& service, const Napi::Env &env);

~FindCredentialsWorker();

void Execute();
void HandleOKCallback();
void OnOK();
void OnError(Napi::Error const &error);
Napi::Promise Promise();

private:
const std::string service;
std::vector<keytar::Credentials> credentials;
bool success;
const Napi::Promise::Deferred deferred;
};

#endif // SRC_ASYNC_H_
63 changes: 40 additions & 23 deletions src/keytar_mac.cc
Original file line number Diff line number Diff line change
@@ -57,8 +57,7 @@ const std::string errorStatusToString(OSStatus status) {
KEYTAR_OP_RESULT AddPassword(const std::string& service,
const std::string& account,
const std::string& password,
std::string* error,
bool returnNonfatalOnDuplicate) {
std::string* error) {
OSStatus status = SecKeychainAddGenericPassword(NULL,
service.length(),
service.data(),
@@ -68,9 +67,7 @@ KEYTAR_OP_RESULT AddPassword(const std::string& service,
password.data(),
NULL);

if (status == errSecDuplicateItem && returnNonfatalOnDuplicate) {
return FAIL_NONFATAL;
} else if (status != errSecSuccess) {
if (status != errSecSuccess) {
*error = errorStatusToString(status);
return FAIL_ERROR;
}
@@ -82,16 +79,30 @@ KEYTAR_OP_RESULT SetPassword(const std::string& service,
const std::string& account,
const std::string& password,
std::string* error) {
KEYTAR_OP_RESULT result = AddPassword(service, account, password,
error, true);
if (result == FAIL_NONFATAL) {
// This password already exists, delete it and try again.
KEYTAR_OP_RESULT delResult = DeletePassword(service, account, error);
if (delResult == FAIL_ERROR)
return FAIL_ERROR;
else
return AddPassword(service, account, password, error, false);
} else if (result == FAIL_ERROR) {
SecKeychainItemRef item;
OSStatus result = SecKeychainFindGenericPassword(NULL,
service.length(),
service.data(),
account.length(),
account.data(),
NULL,
NULL,
&item);

if (result == errSecItemNotFound) {
return AddPassword(service, account, password, error);
} else if (result != errSecSuccess) {
*error = errorStatusToString(result);
return FAIL_ERROR;
}

result = SecKeychainItemModifyAttributesAndData(item,
NULL,
password.length(),
password.data());
CFRelease(item);
if (result != errSecSuccess) {
*error = errorStatusToString(result);
return FAIL_ERROR;
}

@@ -202,9 +213,12 @@ Credentials getCredentialsForItem(CFDictionaryRef item) {
CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
CFDictionaryAddValue(query, kSecAttrAccount, account);

CFTypeRef result;
Credentials cred;
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, &result);

CFRelease(query);

if (status == errSecSuccess) {
CFDataRef passwordData = (CFDataRef) CFDictionaryGetValue(
(CFDictionaryRef) result,
@@ -214,15 +228,18 @@ Credentials getCredentialsForItem(CFDictionaryRef item) {
passwordData,
kCFStringEncodingUTF8);

Credentials cred = Credentials(
cred = Credentials(
CFStringToStdString(account),
CFStringToStdString(password));

CFRelease(password);
}

return cred;
if (result != NULL) {
CFRelease(result);
}

return Credentials();
return cred;
}

KEYTAR_OP_RESULT FindCredentials(const std::string& service,
@@ -244,9 +261,12 @@ KEYTAR_OP_RESULT FindCredentials(const std::string& service,
CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);

CFTypeRef result;
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, &result);

CFRelease(serviceStr);
CFRelease(query);

if (status == errSecSuccess) {
CFArrayRef resultArray = (CFArrayRef) result;
int resultCount = CFArrayGetCount(resultArray);
@@ -266,13 +286,10 @@ KEYTAR_OP_RESULT FindCredentials(const std::string& service,
return FAIL_ERROR;
}


if (result != NULL) {
CFRelease(result);
}

CFRelease(query);

return SUCCESS;
}

6 changes: 5 additions & 1 deletion src/keytar_win.cc
Original file line number Diff line number Diff line change
@@ -123,7 +123,7 @@ KEYTAR_OP_RESULT SetPassword(const std::string& service,
}

LPWSTR user_name = utf8ToWideChar(account);
if (target_name == NULL) {
if (user_name == NULL) {
return FAIL_ERROR;
}

@@ -228,6 +228,10 @@ KEYTAR_OP_RESULT FindCredentials(const std::string& service,
std::vector<Credentials>* credentials,
std::string* errStr) {
LPWSTR filter = utf8ToWideChar(service + "*");
if (filter == NULL) {
*errStr = "Error generating credential filter";
return FAIL_ERROR;
}

DWORD count;
CREDENTIAL **creds;
154 changes: 81 additions & 73 deletions src/main.cc
Original file line number Diff line number Diff line change
@@ -1,131 +1,139 @@
#include "nan.h"
#include "napi.h"
#include "async.h"

namespace {

NAN_METHOD(SetPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
Napi::Value SetPassword(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

if (!info[0].IsString()) {
Napi::TypeError::New(env, "Parameter 'service' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());
std::string service = info[0].As<Napi::String>();

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
if (!info[1].IsString()) {
Napi::TypeError::New(env, "Parameter 'username' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());
std::string username = info[1].As<Napi::String>();

if (!info[2]->IsString()) {
Nan::ThrowTypeError("Parameter 'password' must be a string");
return;
if (!info[2].IsString()) {
Napi::TypeError::New(env, "Parameter 'password' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String passwordNan(info[2]);
std::string password(*passwordNan, passwordNan.length());
std::string password = info[2].As<Napi::String>();

SetPasswordWorker* worker = new SetPasswordWorker(
service,
username,
password,
new Nan::Callback(info[3].As<v8::Function>()));
Nan::AsyncQueueWorker(worker);
env);
worker->Queue();
return worker->Promise();
}

NAN_METHOD(GetPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
Napi::Value GetPassword(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (!info[0].IsString()) {
Napi::TypeError::New(env, "Parameter 'service' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());
std::string service = info[0].As<Napi::String>();

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
if (!info[1].IsString()) {
Napi::TypeError::New(env, "Parameter 'username' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());
std::string username = info[1].As<Napi::String>();

GetPasswordWorker* worker = new GetPasswordWorker(
service,
username,
new Nan::Callback(info[2].As<v8::Function>()));
Nan::AsyncQueueWorker(worker);
env);
worker->Queue();
return worker->Promise();
}

NAN_METHOD(DeletePassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
Napi::Value DeletePassword(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (!info[0].IsString()) {
Napi::TypeError::New(env, "Parameter 'service' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());
std::string service = info[0].As<Napi::String>();

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
if (!info[1].IsString()) {
Napi::TypeError::New(env, "Parameter 'username' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());
std::string username = info[1].As<Napi::String>();

DeletePasswordWorker* worker = new DeletePasswordWorker(
DeletePasswordWorker *worker = new DeletePasswordWorker(
service,
username,
new Nan::Callback(info[2].As<v8::Function>()));
Nan::AsyncQueueWorker(worker);
env);
worker->Queue();
return worker->Promise();
}

NAN_METHOD(FindPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
Napi::Value FindPassword(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (!info[0].IsString()) {
Napi::TypeError::New(env, "Parameter 'service' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());
std::string service = info[0].As<Napi::String>();

FindPasswordWorker* worker = new FindPasswordWorker(
service,
new Nan::Callback(info[1].As<v8::Function>()));
Nan::AsyncQueueWorker(worker);
env);
worker->Queue();
return worker->Promise();
}

NAN_METHOD(FindCredentials) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
Napi::Value FindCredentials(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (!info[0].IsString()) {
Napi::TypeError::New(env, "Parameter 'service' must be a string").
ThrowAsJavaScriptException();
return env.Null();
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());
std::string service = info[0].As<Napi::String>();

FindCredentialsWorker* worker = new FindCredentialsWorker(
service,
new Nan::Callback(info[1].As<v8::Function>()));
Nan::AsyncQueueWorker(worker);
env);
worker->Queue();
return worker->Promise();
}

NAN_MODULE_INIT(Init) {
Nan::SetMethod(target, "getPassword", GetPassword);
Nan::SetMethod(target, "setPassword", SetPassword);
Nan::SetMethod(target, "deletePassword", DeletePassword);
Nan::SetMethod(target, "findPassword", FindPassword);
Nan::SetMethod(target, "findCredentials", FindCredentials);
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("getPassword", Napi::Function::New(env, GetPassword));
exports.Set("setPassword", Napi::Function::New(env, SetPassword));
exports.Set("deletePassword", Napi::Function::New(env, DeletePassword));
exports.Set("findPassword", Napi::Function::New(env, FindPassword));
exports.Set("findCredentials", Napi::Function::New(env, FindCredentials));
return exports;
}

} // namespace

#if NODE_MAJOR_VERSION >= 10
NAN_MODULE_WORKER_ENABLED(keytar, Init)
#else
NODE_MODULE(keytar, Init)
#endif
NODE_API_MODULE(keytar, Init)