Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
- Integrate encryptr tests in the new test structure.
- remove ordering requirement from tests as encryptr exports are
  non-deterministic
- standardize how we read keys in encryptr importer
- update readme/manpage with encryptr support information
- fix up codacy issues
- add in encryptr support. establish arbitrary card fields. add in tests
  for card types
- Ensure the python prefix is always the one from the distribution #67
- CI: Also test the install.
- Add coverage website link.
- Publish code coverage report with GitLab Pages.
  • Loading branch information
roddhjav committed May 19, 2019
2 parents 0624288 + f269cba commit a0db5d3
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 6 deletions.
22 changes: 22 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
stages:
- lint
- test
- deploy

bash:
stage: lint
Expand Down Expand Up @@ -40,7 +41,11 @@ sast:
stage: test
script:
- pip3 install green coverage defusedxml pyaml
- make
- make tests
- make install
- cd ~
- pass import --help

.only: &only
only:
Expand All @@ -51,6 +56,10 @@ archlinux:
image: archlinux/base
before_script:
- pacman -Syu --noconfirm --noprogressbar make python-pip which grep pass
artifacts:
expire_in: 2 days
paths:
- htmlcov/
<<: *script

ubuntu:
Expand All @@ -76,3 +85,16 @@ fedora:
- dnf -y install make gpg pass python3-pip grep which --setopt=install_weak_deps=False
<<: *script
<<: *only

pages:
stage: deploy
dependencies:
- archlinux
script:
- mv htmlcov/ public/
artifacts:
expire_in: 2 days
paths:
- public
only:
- master
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ install:
@install -v -m 0755 "$(PROG).bash" "$(DESTDIR)$(SYSTEM_EXTENSION_DIR)/$(PROG).bash"
@install -v -m 0644 "pass-$(PROG).1" "$(DESTDIR)$(MANDIR)/man1/pass-$(PROG).1"
@install -v -m 0644 "completion/pass-$(PROG).bash" "$(DESTDIR)$(BASHCOMPDIR)/pass-$(PROG)"
@python3 setup.py install --root="$(DESTDIR)" --prefix="$(PREFIX)" --optimize=1 --skip-build
@python3 setup.py install --root="$(DESTDIR)" --optimize=1 --skip-build
@echo
@echo "pass-$(PROG) is installed succesfully"
@echo
Expand All @@ -49,6 +49,7 @@ T = $(sort $(wildcard tests/test_*.sh))

tests:
@python3 setup.py green -vvv --run-coverage --termcolor --processes $(shell nproc)
@coverage html
@make tests_bash

tests_bash: $(T)
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<a href="https://gitlab.com/roddhjav/pass-import/pipelines">
<img src="https://gitlab.com/roddhjav/pass-import/badges/master/pipeline.svg?style=flat-square"
alt="Pipeline Status" /></a>
<a href="https://www.codacy.com/app/roddhjav/pass-import">
<a href="https://roddhjav.gitlab.io/pass-import/">
<img src="https://img.shields.io/codacy/coverage/783d8cf291434d2b8f1c063b51cfebbb/master.svg?style=flat-square"
alt="Code Coverage" /></a>
<a href="https://www.codacy.com/app/roddhjav/pass-import">
Expand Down Expand Up @@ -48,6 +48,7 @@ Pass import handles duplicates and is compatible with [browserpass][bp].
| [buttercup][buttercup] | *File > Export > Export File to CSV* | `pass import buttercup file.csv` |
| [chrome][chrome] | *See this [guide][export-chrome]* | `pass import chrome file.csv` |
| [chromesqlite][chrome] | *See this [guide][export-chrome]* | `pass import chrome file.csv` |
| [encryptr][encryptr] | *See this [encryptr issue](/~https://github.com/SpiderOak/Encryptr/issues/295#issuecomment-322449705)* | `pass import encryptr file.csv` |
| [enpass][enpass] | *File > Export > As CSV* | `pass import enpass file.csv` |
| [enpass6][enpass] | *Menu > File > Export > As JSON* | `pass import enpass6 file.json` |
| [dashlane][dashlane] | *File > Export > Unsecured Archive in CSV* | `pass import dashlane file.csv` |
Expand Down Expand Up @@ -274,6 +275,7 @@ Feedback, contributors, pull requests are all very welcome. Please read the
[buttercup]: https://buttercup.pw/
[chrome]: https://support.google.com/chrome
[dashlane]: https://www.dashlane.com/
[encryptr]: https://spideroak.com/encryptr/
[enpass]: https://www.enpass.io/
[fpm]: http://fpm.sourceforge.net/
[gorilla]: /~https://github.com/zdia/gorilla/wiki
Expand Down
10 changes: 10 additions & 0 deletions pass-import.1
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,16 @@ Export: File > Export > Unsecured Archive in CSV

Command: pass import dashlane file.csv

.TP
\fBencryptr\fP
Website: \fIhttps://spideroak.com/encryptr/\fP

Export: Compile from source and follow instructions here:

\fI/~https://github.com/SpiderOak/Encryptr/issues/295#issuecomment-322449705\fP

Command: pass import encryptr file.csv

.TP
\fBenpass\fP
Website: \fIhttps://www-enpass.io/\fP
Expand Down
41 changes: 41 additions & 0 deletions pass_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
'chrome': ['Chrome', 'https://support.google.com/chrome'],
'chromesqlite': ['ChromeSQLite', 'https://support.google.com/chrome'],
'dashlane': ['Dashlane', 'https://www.dashlane.com/'],
'encryptr': ['Encryptr', 'https://spideroak.com/encryptr/'],
'enpass': ['Enpass', 'https://www.enpass.io/'],
'enpass6': ['Enpass6', 'https://www.enpass.io/'],
'fpm': ['FigaroPM', 'http://fpm.sourceforge.net/'],
Expand Down Expand Up @@ -592,6 +593,46 @@ class Dashlane(PasswordManagerCSV):
'url': 'url', 'comments': 'comments'}


class Encryptr(PasswordManagerCSV):
# Looking at how Encryptr processes exports here (method getCsvFields):
# /~https://github.com/SpiderOak/Encryptr/blob/master/src/views/MainView.js#L163
# and entry types contained here:
# /~https://github.com/SpiderOak/Encryptr/tree/master/src/models/types
# we conclude:
# Every record has metadata: "Entry Type","Label"
# Every record happens to have, independently: "Notes"
# Password type has: "Username","Password", "Site URL"
# General type has: "Text"
# Credit card type has: "Type", "Name on card", "Card Number", "CVV", "Expiry"
# encryptr dynamically generates CSVs based on available entry types,
# and supports credit cards.
# all told, we have, in no particular order as it's dynamic:
# "Entry Type","Label", "Notes", "Username", "Password", "Site URL",
# "Text", "Type", "Name on card", "Card Number", "CVV", "Expiry"

# and now let's map it all. Ignoring Entry Type.
keys = {
'title': 'Label',
'password': 'Password',
'login': 'Username',
'url': 'Site URL',
'comments': 'Notes',
'text': 'Text', # do we want to consider this
# a password since it was the
# "secret" for general type?
'group': 'Entry Type',
}

# since it's dynamically generated, there is no guarantee
# that all keys are there (e.g, no credit cards, no keys related to it.)
# so we only check for those that are there with at least one entry.
@classmethod
def _checkformat(cls, fieldnames):
for csvkey in ("Entry Type", "Label", "Notes"):
if csvkey not in fieldnames:
raise FormatError()


class Enpass(PasswordManagerCSV):
format = '"Title","Field","Value","Field","Value",.........,"Note"'
keys = {'title': 'Title', 'password': 'Password', 'login': 'Username',
Expand Down
2 changes: 2 additions & 0 deletions tests/db/encryptr-card.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Entry Type,Label,Password,Username,Site URL,Notes,Text,Type,Name on card,Card Number,CVV,Expiry
Credit Card,Goliath National Bank,,,,note here,,Visatron,J Smith,5012345678900000,123,22/01
16 changes: 16 additions & 0 deletions tests/db/encryptr.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Entry Type,Label,Password,Username,Site URL,Notes,Text,Type,Name on card,Card Number,CVV,Expiry
Password,mastodon.social,D<INNeT?#?Bf4%`zA/4i!/'$T,ostqxi,mastodon.social/,,,,,,,
Password,twitter.com,"SoNEwvU,kJ%-cIKJ9[c#S;]jB",ostqxi,twitter.com/,,,,,,,
Password,news.ycombinator.com,"1)Btf2EI~Tfb7g2A!Sy',*Sj#",ostqxi,news.ycombinator.com,,,,,,,
Password,ovh.com,^Vr/|o>_H8X%T]7>f}7|:U!Zs,jsdkyvbwjn,www.ovh.com/manager/web/,,,,,,,
Password,ovh.com,"3Z-VW!i,j(&!zRGPu(hFe]s'(",bynbyjhqjz,www.ovh.com/manager/web/,,,,,,,
Password,aib,"ws5T@;_UB[Q|P!8'`~z%XC'JHFUbf#IX _E0}:HF,[{ei0hBg14",dpbx@fner.ws,onlinebanking.aib.ie,462916,,,,,,
Password,dpbx@afoqwdr.tx,9KVHnx:.S_S;cF`=CE@e\p{v6,dpbx,afoqwdr.tx,,,,,,,
Password,dpbx@klivak.xb,"2cUqe}e9}>IVZf)Ye>3C8ZN,r",dpbx,,This is a garbage address,,,,,,
Password,dpbx@mnyfymt.ws,rPCkmNkhIa>{izt3C3F823!Go,dpbx,mail.mnyfymt.ws,,,,,,,
Password,dpbx@fner.ws,mt}h'hSUCY;SU;;A!l[8y3O:8,dpbx,,For financial purpose only!,,,,,,
Password,space title,]stDKo{%pk,vkeelpbu,nhysdo.wg,,,,,,,
Password,empty entry,,,,,,,,,,
Password,empty password,,vkeelpbu,nhysdo.wg,,,,,,,
General,note,,,,,"This is a multiline note entry. Cube shank petroleum guacamole dart mower
acutely slashing upper cringing lunchbox tapioca wrongful unbeaten sift.",,,,,
32 changes: 28 additions & 4 deletions tests/test_importers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,27 @@
REFERENCE_NOTE = yaml.safe_load(open('tests/references/applekeychain-note.yml', 'r'))
REFERENCE_OTHER = yaml.safe_load(open('tests/references/keepass-other.yml', 'r'))

REF_CARD = [
{
'title': "Goliath National Bank",
'Type': "Visatron",
'Name on card': "J Smith",
'Card Number': "5012345678900000",
'CVV': "123",
'Expiry': "22/01",
'group': 'Credit Card'
}
]


class TestBaseImporters(TestBase):
importers = yaml.safe_load(open('tests/importers.yml', 'r'))

@staticmethod
def _clear(data):
def _clear(data, keep=None):
"""Only keep the keys present in the template and reference file."""
keep = ['title', 'password', 'login', 'url', 'comments', 'group']
if not keep:
keep = ['title', 'password', 'login', 'url', 'comments', 'group']
for entry in data:
delete = [k for k in entry.keys() if k not in keep]
empty = [k for k, v in entry.items() if not v]
Expand Down Expand Up @@ -73,9 +86,9 @@ def _reference(self, manager):
entry['group'] = self.importers[manager]['root'] + entry['group']
return reference

def assertImport(self, data, refdata):
def assertImport(self, data, refdata, keep=None):
"""Compare imported data with the reference data."""
self._clear(data)
self._clear(data, keep)
for entry in data:
self.assertIn(entry, refdata)

Expand Down Expand Up @@ -126,6 +139,17 @@ def test_importers_keepassxother(self):
importer.parse(file)
self.assertImport(importer.data, REFERENCE_OTHER)

def test_importers_encryptr(self):
"""Testing: parse method for Encryptr with credit card."""
keep = ['title', 'Type', 'Name on card', 'Card Number', 'CVV',
'Expiry', 'group']
importer = self._class('encryptr')
testpath = os.path.join(self.db, 'encryptr-card.csv')
with open(testpath, 'r') as file:
importer.parse(file)
print(importer.data)
self.assertImport(importer.data, REF_CARD, keep)


class TestImportersFormat(TestBaseImporters):
formaterror = (pass_import.FormatError, AttributeError, ValueError,
Expand Down

0 comments on commit a0db5d3

Please sign in to comment.