pax_global_header00006660000000000000000000000064152370371130014514gustar00rootroot0000000000000052 comment=d71ce8174df9f7710898fe6c246c39b7e41eef18 peshay-tpm-d71ce81/000077500000000000000000000000001523703711300142215ustar00rootroot00000000000000peshay-tpm-d71ce81/.github/000077500000000000000000000000001523703711300155615ustar00rootroot00000000000000peshay-tpm-d71ce81/.github/release.yml000066400000000000000000000015241523703711300177260ustar00rootroot00000000000000# Configuration for GitHub's automatically generated release notes. # Applied when using "Generate release notes" while drafting a release, # so future releases get a clean, categorised changelog from PR titles. # See: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes changelog: exclude: labels: - ignore-for-release categories: - title: 🚨 Breaking Changes labels: - breaking - breaking-change - title: ✨ Features & Enhancements labels: - enhancement - feature - title: 🐛 Bug Fixes labels: - bug - fix - title: 🏗️ Tooling, CI & Dependencies labels: - ci - build - dependencies - testing - title: 📝 Other Changes labels: - "*" peshay-tpm-d71ce81/.github/workflows/000077500000000000000000000000001523703711300176165ustar00rootroot00000000000000peshay-tpm-d71ce81/.github/workflows/ci.yml000066400000000000000000000040741523703711300207410ustar00rootroot00000000000000name: CI on: push: branches: [master] pull_request: branches: [master] permissions: contents: read id-token: write jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: # 3.15 is a release candidate (final: 2026-10-01). It runs as an early # warning only, so a broken rc can't block a PR. python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.15'] continue-on-error: ${{ matrix.python-version == '3.15' }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} # Needed while 3.15 has no final release; no effect on stable versions. allow-prereleases: true cache: pip - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e ".[dev]" - name: Public artifact guard run: pre-commit run --all-files - name: Ruff run: ruff check tpm.py tests tools - name: Tests with coverage run: pytest --cov=tpm --cov=tools --cov-report=xml tests/ - name: Upload coverage if: github.event_name == 'push' uses: codecov/codecov-action@v4 with: use_oidc: true files: ./coverage.xml sonarcloud: name: SonarQube Cloud runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: # Full history lets SonarQube Cloud attribute new code accurately. fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: '3.12' cache: pip - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e ".[dev]" - name: Tests with coverage run: pytest --cov=tpm --cov=tools --cov-report=xml tests/ - name: SonarQube Cloud scan uses: SonarSource/sonarqube-scan-action@v6 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: https://sonarcloud.io peshay-tpm-d71ce81/.github/workflows/release.yml000066400000000000000000000014631523703711300217650ustar00rootroot00000000000000name: Release on: push: tags: # Match both the bare-number convention (5.0, 5.0.0) and a v-prefix. - '[0-9]*' - 'v[0-9]*' # Allow manual runs (e.g. to (re)publish the current version on master). workflow_dispatch: permissions: contents: read jobs: pypi-publish: name: Build and publish to PyPI runs-on: ubuntu-latest permissions: # Required for PyPI Trusted Publishing (OIDC) — no API token needed. id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - name: Build distributions run: | python -m pip install --upgrade pip build python -m build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 peshay-tpm-d71ce81/.gitignore000066400000000000000000000003231523703711300162070ustar00rootroot00000000000000# Byte-compiled / cache __pycache__/ *.py[cod] *.egg-info/ .pytest_cache/ .ruff_cache/ # Build / distribution build/ dist/ *.egg # Coverage .coverage coverage.xml htmlcov/ # Virtual environments .venv/ venv/ peshay-tpm-d71ce81/.pre-commit-config.yaml000066400000000000000000000003651523703711300205060ustar00rootroot00000000000000repos: - repo: local hooks: - id: public-artifact-hygiene name: Public artifact hygiene guard entry: python3 tools/check_public_artifacts.py language: system pass_filenames: true types: [text] peshay-tpm-d71ce81/AGENTS.md000066400000000000000000000012501523703711300155220ustar00rootroot00000000000000# AGENTS This repository accepts AI-assisted contributions. ## Guardrails - Keep changes small and reviewable. - Treat all credential and password-handling paths as sensitive; do not change their behavior without explicit intent. - Do not commit secrets, API keys, or password data. - Run the public artifact hygiene guard (pre-commit) before publishing PR text, commits, or docs. ## Required Human Checks - Review every AI-generated change before merge. - Validate authentication (password and key-based) and request handling. - Ensure docs match implemented methods. ## Attribution A concise note such as "AI-assisted" in the PR description is recommended for transparency. peshay-tpm-d71ce81/CONTRIBUTING.md000066400000000000000000000017111523703711300164520ustar00rootroot00000000000000# Contributing Thanks for contributing to tpm.py. ## Requirements - Python 3.x - `pip` ## Development Setup ```bash pip install -e . pip install -r tests/requirements.txt pre-commit install --install-hooks pytest ``` ## Branch and Commit Guidelines - Create a feature branch from `master`. - Use Conventional Commits, e.g.: - `feat: add file upload endpoint` - `fix: handle locked password unlock reason` - `docs: document v5 endpoints` ## Pull Request Checklist - Keep changes focused and minimal. - Add or update tests for behavior changes. - Update docs when behavior changes. - Run `pre-commit run --all-files` before opening a PR. - Ensure CI is green. ## Security and Secrets - Never commit real TeamPasswordManager credentials, keys, or password data. - For vulnerabilities, follow `SECURITY.md`. ## Review Policy - All PRs require human review before merge. - AI-assisted changes are welcome, but maintainers are responsible for final correctness. peshay-tpm-d71ce81/LICENSE000066400000000000000000000020621523703711300152260ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 peshay Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. peshay-tpm-d71ce81/README.md000066400000000000000000000352301523703711300155030ustar00rootroot00000000000000# tpm.py > Modern Python SDK groundwork for TeamPasswordManager with safer API boundaries and maintainable packaging. [![CI](https://github.com/peshay/tpm/actions/workflows/ci.yml/badge.svg)](https://github.com/peshay/tpm/actions/workflows/ci.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=peshay_tpm&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=peshay_tpm) [![PyPI version](https://img.shields.io/pypi/v/tpm)](https://pypi.org/project/tpm/) [![Python version](https://img.shields.io/pypi/pyversions/tpm)](https://pypi.org/project/tpm/) [![License](https://img.shields.io/github/license/peshay/tpm)](LICENSE) [![Support via bunq](https://img.shields.io/badge/Support-bunq-00A1E0?style=flat-square&logo=bunq&logoColor=white)](https://bunq.me/ahuservices?description=tpm-maintenance-support) A Python Module for the [TeamPasswordManager API](http://teampasswordmanager.com/docs/api/) Requires: requests ## Install tpm.py You can install the tpm module via pip pip install tpm ## How to Use This is an example how you can use it in a python script ```python #! /usr/bin/env python import tpm # create a object for the connection settings URL = "https://mypasswordmanager.example.com" USER = 'example-user' PASS = 'EXAMPLE_PASSWORD' tpmconn = tpm.TpmApiv5(URL, username=USER, password=PASS) # get a dictionary for all password entries data = tpmconn.list_passwords() # show all names from the password entries for item in data: print (item.get('name')) ``` You can also use Private/Public Key authentication ```python #! /usr/bin/env python import tpm # create a object for the connection settings URL = "https://mypasswordmanager.example.com" pubkey = 'EXAMPLE_PUBLIC_KEY' privkey = 'EXAMPLE_PRIVATE_KEY' tpmconn = tpm.TpmApiv5(URL, private_key=privkey, public_key=pubkey) # get a dictionary for all password entries data = tpmconn.list_passwords() # show all names from the password entries for item in data: print (item.get('name')) ``` If you always want to unlock entries that are locked, you can specify an unlock reason ```python tpmconn = tpm.TpmApiv5(URL, username=USER, password=PASS, unlock_reason="Because I can!") ``` ### TLS certificate verification TLS certificates are verified by default (`verify=True`). To connect to a server with a self-signed certificate you can disable verification or point to a custom CA bundle: ```python # disable verification (not recommended) tpmconn = tpm.TpmApiv5(URL, username=USER, password=PASS, verify=False) # or verify against a custom CA bundle tpmconn = tpm.TpmApiv5(URL, username=USER, password=PASS, verify="/path/to/ca-bundle.pem") ``` ## API v6 Use `tpm.TpmApiv6` to talk to the v6 API. It inherits every function from the previous versions and adds the endpoints introduced in v6 (see the [Functions explained](#functions-explained) section, marked `(since v6)`): ```python tpmconn = tpm.TpmApiv6(URL, username=USER, password=PASS) ``` ### Page size Since v6 you can set the page size for paginated requests via the `X-Page-Size` header. Pass `page_size` (an integer between 5 and 1000) when creating the client: ```python tpmconn = tpm.TpmApiv6(URL, username=USER, password=PASS, page_size=100) ``` ## Development artifact guard This repository uses pre-commit to keep public artifacts safe to publish. Install the hook once after cloning: ```sh python3 -m pip install pre-commit pre-commit install --install-hooks ``` Before opening a PR, run: ```sh pre-commit run --all-files ``` The guard blocks accidental literal backslash-n text where real line breaks belong, local machine paths, internal workflow details, and obvious secret or auth-token values. Replace real values with placeholders or environment-variable references before publishing. ## Logging Every function call leads to a at least a logging message. If you want to log all your script does, you can do it like this: ```python import logging # set log file and log level logfile = 'MyLogFile.log' loglevel = logging.INFO logformat = '%(asctime)s - %(levelname)s - %(message)s' logging.basicConfig(filename=logfile, level=loglevel, format=logformat) # If you don't want the requests and urllib3 module to log too much logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) ``` ## Functions explained ### All Functions are also explained at the API documentation --- ### [API Projects](http://teampasswordmanager.com/docs/api-projects) #### [List Projects](http://teampasswordmanager.com/docs/api-projects/#list_projects) list_projects() list_projects_archived() list_projects_favorite() list_projects_search(searchstring) #### (since v4) [List Subprojects](http://teampasswordmanager.com/docs/api-projects/#list_subprojects) list_subprojects(ID) list_subprojects_action(ID, action) #### [Show Project](http://teampasswordmanager.com/docs/api-projects/#show_project) show_project(ID) #### [List Passwords of Project](http://teampasswordmanager.com/docs/api-projects/#list_pwds_prj) list_passwords_of_project(ID) #### [List User Access on Project](http://teampasswordmanager.com/docs/api-projects/#list_users_prj) list_user_access_on_project(ID) #### [Create Project](http://teampasswordmanager.com/docs/api-projects/#create_project) create_project(data) #### [Update Project](http://teampasswordmanager.com/docs/api-projects/#update_project) update_project(ID, data) #### [Change Parent of Project](http://teampasswordmanager.com/docs/api-projects/#change_parent) change_parent_of_project(ID, NewParentID) #### [Update Security of Project](http://teampasswordmanager.com/docs/api-projects/#update_project_security) update_security_of_project(ID, data) #### [Archive Project](http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project) archive_project(ID) #### [Unarchive Project](http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project) unarchive_project(ID) #### [Delete Project](http://teampasswordmanager.com/docs/api-projects/#delete_project) delete_project(ID) ### [API Passwords](http://teampasswordmanager.com/docs/api-passwords) #### [List Passwords](http://teampasswordmanager.com/docs/api-passwords/#list_passwords) list_passwords() list_passwords_archived() list_passwords_favorite() list_passwords_search(searchstring) #### [Show Password](http://teampasswordmanager.com/docs/api-passwords/#show_password) show_password(ID) #### [List User Access on Password](http://teampasswordmanager.com/docs/api-passwords/#list_users_pwd) list_user_access_on_password(ID) #### [Create Password](http://teampasswordmanager.com/docs/api-passwords/#create_password) create_password(data) #### [Update Password](http://teampasswordmanager.com/docs/api-passwords/#update_password) update_password(ID, data) #### [Update Security of Password](http://teampasswordmanager.com/docs/api-passwords/#update_security_password) update_security_of_password(ID, data) #### [Update Custom Fields of Password](http://teampasswordmanager.com/docs/api-passwords/#update_cf_password) update_custom_fields_of_password(ID, data) #### [Delete Password](http://teampasswordmanager.com/docs/api-passwords/#delete_password) delete_password(ID) #### [Lock Password](http://teampasswordmanager.com/docs/api-passwords/#lock_password) lock_password(ID) #### [Unlock Password](http://teampasswordmanager.com/docs/api-passwords/#unlock_password) unlock_password(ID) #### (since v5) [Archive Password](http://teampasswordmanager.com/docs/api-passwords/#arch_unarch_password) archive_password(ID) #### (since v5) [Unarchive Password](http://teampasswordmanager.com/docs/api-passwords/#arch_unarch_password) unarchive_password(ID) #### (since v5) [Move Password](http://teampasswordmanager.com/docs/api-passwords/#move_password) move_password(ID, PROJECT_ID) ### [API MyPasswords](http://teampasswordmanager.com/docs/api-my-passwords) #### (since v6) [List Archived MyPasswords](http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords) list_mypasswords_archived() #### (since v6) [List Favorite MyPasswords](http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords) list_mypasswords_favorite() #### [List MyPasswords](http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords) list_mypasswords() list_mypasswords_search(searchstring) #### [Show MyPassword](http://teampasswordmanager.com/docs/api-my-passwords/#show_password) show_mypassword(ID) #### [Create MyPassword](http://teampasswordmanager.com/docs/api-my-passwords/#create_password) create_mypassword(data) #### [Update MyPassword](http://teampasswordmanager.com/docs/api-my-passwords/#update_password) update_mypassword(ID, data) #### [Delete MyPassword](http://teampasswordmanager.com/docs/api-my-passwords/#delete_password) delete_mypassword(ID) ### [API Favorites](http://teampasswordmanager.com/docs/api-favorites) #### [Set Favorite Password](http://teampasswordmanager.com/docs/api-favorites/#set_fav) set_favorite_password(ID) #### [Unset Favorite Password](http://teampasswordmanager.com/docs/api-favorites/#del_fav) unset_favorite_password(ID) #### [Set Favorite Project](http://teampasswordmanager.com/docs/api-favorites/#set_fav) set_favorite_project(ID) #### [Unset Favorite Project](http://teampasswordmanager.com/docs/api-favorites/#del_fav) unset_favorite_project(ID) > Note: `TpmApiv6` overrides these two to use the v6 endpoint `favorite_projects/{ID}.json` (plural); earlier versions use `favorite_project/{ID}.json`. #### (since v6) [Set Favorite MyPassword](http://teampasswordmanager.com/docs/api-favorites/#set_fav) set_favorite_mypassword(ID) #### (since v6) [Unset Favorite MyPassword](http://teampasswordmanager.com/docs/api-favorites/#del_fav) unset_favorite_mypassword(ID) #### [Move MyPassword to a Project](https://teampasswordmanager.com/docs/api-my-passwords/#move_password) move_mypassword(ID, PROJECT_ID) ### [API Users](http://teampasswordmanager.com/docs/api-users) #### [List Users](http://teampasswordmanager.com/docs/api-users/#list_users) list_users() #### [Show User](http://teampasswordmanager.com/docs/api-users/#show_user) show_user(ID) #### (since v6) [List Passwords a User can access](http://teampasswordmanager.com/docs/api-users/) list_user_passwords(ID) #### (since v6) [List Projects a User can access](http://teampasswordmanager.com/docs/api-users/) list_user_projects(ID) #### [Show Me/Who am I?](http://teampasswordmanager.com/docs/api-users/#show_me) show_me() who_am_i() #### [Create User](http://teampasswordmanager.com/docs/api-users/#create_user) create_user(data) #### (since v5) [Create LDAP User](http://teampasswordmanager.com/docs/api-users/#create_user_ldap) create_user_ldap(data) #### (since v5) [Create SAML User](http://teampasswordmanager.com/docs/api-users/#create_user_saml) create_user_saml(data) #### [Update User](http://teampasswordmanager.com/docs/api-users/#update_user) update_user(ID, data) #### [Change User Password](http://teampasswordmanager.com/docs/api-users/#change_password) change_user_password(ID, data) #### [Activate User](http://teampasswordmanager.com/docs/api-users/#activate_deactivate) activate_user(ID) #### [Deactivate User](http://teampasswordmanager.com/docs/api-users/#activate_deactivate) deactivate_user(ID) #### [Convert User to LDAP](http://teampasswordmanager.com/docs/api-users/#convert_to_ldap) convert_user_to_ldap(ID, DN) convert_ldap_user_to_normal(ID) #### (since v5) [Convert User to LDAP](http://teampasswordmanager.com/docs/api-users/#convert_to_ldap) convert_user_to_ldap(ID, DN, SERVER_ID) #### (since v5) [Convert User to SAML](http://teampasswordmanager.com/docs/api-users/#convert_to_saml) convert_user_to_saml(ID) #### [Delete User](http://teampasswordmanager.com/docs/api-users/#delete_user) delete_user(ID) ### [API Groups](http://teampasswordmanager.com/docs/api-groups) #### [List groups](http://teampasswordmanager.com/docs/api-groups/#list_groups) list_groups() #### [Show Group](http://teampasswordmanager.com/docs/api-groups/#show_group) show_group(ID) #### [Create Group](http://teampasswordmanager.com/docs/api-groups/#create_group) create_group(data) #### [Update Group](http://teampasswordmanager.com/docs/api-groups/#update_group) update_group(ID, data): #### [Add User to Group](http://teampasswordmanager.com/docs/api-groups/#add_user) add_user_to_group(GroupID, UserID) #### [Delete User from Group](http://teampasswordmanager.com/docs/api-groups/#del_user) delete_user_from_group(GroupID, UserID) #### [Delete Group](http://teampasswordmanager.com/docs/api-groups/#delete_group) delete_group(ID) ### [Files](https://teampasswordmanager.com/docs/api-files/) #### (since v5) [List Files of Project](https://teampasswordmanager.com/docs/api-projects/#list_files) list_project_files(ID) #### (since v5) [List Files of Password](http://teampasswordmanager.com/docs/api-passwords/#list_files) list_password_files(ID) #### (since v5) [Upload a file to a project](https://teampasswordmanager.com/docs/api-projects/#upload) upload_project_file(ID, file, notes="optional notes") #### (since v5) [Upload a file to a password](http://teampasswordmanager.com/docs/api-passwords/#upload) upload_password_file(ID, file, notes="optional notes") #### (since v5) [Show info of a file](https://teampasswordmanager.com/docs/api-files/#show_file) show_file_info(ID) #### (since v5) [Updates notes of a file](https://teampasswordmanager.com/docs/api-files/#update_file) update_file_notes(ID, NOTES) #### (since v5) [Show max upload file size](https://teampasswordmanager.com/docs/api-files/#max_upload_file_size) max_upload_file_size() #### (since v5) [Download a file](https://teampasswordmanager.com/docs/api-files/#download_file) download_file(ID) #### (since v5) [Delete a file](https://teampasswordmanager.com/docs/api-files/#delete_file) delete_file(ID) ### [API Password Generator](http://teampasswordmanager.com/docs/api-passwords-generator/) generate_password() ### [API Version](http://teampasswordmanager.com/docs/api-version/) get_version() get_latest_version() up_to_date() ### (since v6) [API Log](http://teampasswordmanager.com/docs/api-log/) #### (since v6) [List Log](http://teampasswordmanager.com/docs/api-log/) list_log() #### (since v6) [Search Log](http://teampasswordmanager.com/docs/api-log/) list_log_search(searchstring) ## Governance - Contribution guide: [CONTRIBUTING.md](CONTRIBUTING.md) - Security policy: [SECURITY.md](SECURITY.md) - AI-agent guide: [AGENTS.md](AGENTS.md) - License: [LICENSE](LICENSE) ## Support If this Python SDK is useful to you, you can [support its ongoing maintenance via bunq](https://bunq.me/ahuservices?description=tpm-maintenance-support). Support is voluntary and appreciated, but does not create any entitlement to support, features, consulting, an SLA, or invoice-based work. peshay-tpm-d71ce81/SECURITY.md000066400000000000000000000015141523703711300160130ustar00rootroot00000000000000# Security Policy ## Supported Versions The `master` branch and the latest release on PyPI are the actively supported lines. ## Reporting a Vulnerability Please do not open public issues for security vulnerabilities. Report privately by email to security@ahu.services and include: - affected component or function - impact and attack scenario - reproduction steps - suggested mitigation if available You will receive an acknowledgement as soon as possible, and we will coordinate remediation and disclosure timing. ## Hardening Notes - This module talks to a password manager; treat all credentials, keys, and password payloads as highly sensitive. - Never commit credentials or paste them into issues, logs, or test fixtures. - Use private/public key authentication where possible. - Keep dependencies (`requests`, `urllib3`) up to date. peshay-tpm-d71ce81/docs/000077500000000000000000000000001523703711300151515ustar00rootroot00000000000000peshay-tpm-d71ce81/docs/audits/000077500000000000000000000000001523703711300164425ustar00rootroot00000000000000peshay-tpm-d71ce81/docs/audits/repository-structure-packaging-tests-ci.md000066400000000000000000000025171523703711300267210ustar00rootroot00000000000000# Repository structure, packaging, tests, CI audit Scope: `peshay/tpm` ## Findings - Repo is a single-module package: `tpm.py`, `setup.py`, `requirements.txt`, `tests/`. - No `pyproject.toml` yet; packaging still uses `distutils.core.setup` in `setup.py`. - Runtime dependencies are legacy-pinned (`requests<=2.26.0`, `future`, `urllib3`). - CI is Travis-based, targets Python 3.6-3.9 plus nightly, installs with `python setup.py -q install`, and runs `nose2 -v --with-coverage`. - Tests are fixture-driven under `tests/resources/` and cover API v4/v5 behavior. - Resolved: the request layer now verifies TLS certificates by default (`verify=True`), configurable per client via the `verify` keyword. ## Risks / gaps - ~~Packaging path is outdated for current Python tooling.~~ Resolved: migrated to `pyproject.toml`. - ~~CI/runtime support matrix is stale and likely misses current supported versions.~~ Resolved: matrix now targets Python 3.10-3.14 (all non-EOL versions). - ~~TLS verification default is unsafe for production use.~~ Resolved: `verify` defaults to `True` and is configurable. ## Follow-up - ~~Modernize packaging to `pyproject.toml`.~~ Done. - ~~Refresh the test/CI matrix.~~ Done. - ~~Revisit transport security defaults in a separate hardening card.~~ Done: TLS verification is on by default and configurable via the `verify` keyword. peshay-tpm-d71ce81/pyproject.toml000066400000000000000000000025331523703711300171400ustar00rootroot00000000000000[build-system] requires = ["setuptools>=64"] build-backend = "setuptools.build_meta" [project] name = "tpm" description = "Provides functions to work with TeamPasswordManager API." readme = "README.md" requires-python = ">=3.10" license = "MIT" license-files = ["LICENSE"] authors = [{ name = "Andreas Hubert", email = "anhubert@gmail.com" }] keywords = ["TeamPasswordManager", "json", "api"] dynamic = ["version"] dependencies = [ "requests>=2.33.0", "urllib3>=2.7.0", ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Application Frameworks", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", ] [project.urls] Homepage = "https://github.com/peshay/tpm" Repository = "https://github.com/peshay/tpm" [project.optional-dependencies] test = [ "pytest>=9.0.3", "pytest-cov", "requests-mock", ] dev = [ "tpm[test]", "ruff", "pre-commit", ] [tool.setuptools] py-modules = ["tpm"] [tool.setuptools.dynamic] version = { attr = "tpm.__version__" } [tool.ruff] target-version = "py310" line-length = 100 [tool.pytest.ini_options] testpaths = ["tests"] peshay-tpm-d71ce81/requirements.txt000066400000000000000000000000401523703711300174770ustar00rootroot00000000000000requests>=2.33.0 urllib3>=2.7.0 peshay-tpm-d71ce81/sonar-project.properties000066400000000000000000000023201523703711300211220ustar00rootroot00000000000000# SonarQube Cloud (SonarCloud) configuration. # Project key and organization are the defaults SonarCloud assigns when # importing a GitHub repo (_ / ); adjust if your SonarCloud # organization differs. sonar.projectKey=peshay_tpm sonar.organization=peshay sonar.projectName=tpm # Source vs. test layout. sonar.sources=tpm.py,tools sonar.tests=tests # Test fixtures are data, not code to analyze. sonar.exclusions=tests/resources/** # Duplication in test scaffolding (e.g. the shared fake_data helper that is # copied per test module) is acceptable; don't measure duplication on tests. sonar.cpd.exclusions=tests/** # Hard-coded "credentials" in the test suite are fixtures, not real secrets, # so ignore the hard-coded-credentials rule within tests only. sonar.issue.ignore.multicriteria=e1 sonar.issue.ignore.multicriteria.e1.ruleKey=python:S6437 sonar.issue.ignore.multicriteria.e1.resourceKey=tests/** # Supported runtimes (matches requires-python in pyproject.toml). sonar.python.version=3.10,3.11,3.12,3.13,3.14 # Coverage import requires CI-based analysis (the scanner uploading # coverage.xml); SonarCloud's no-CI "Automatic Analysis" does not import it. sonar.python.coverage.reportPaths=coverage.xml peshay-tpm-d71ce81/tests/000077500000000000000000000000001523703711300153635ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/docker-compose.yml000066400000000000000000000022311523703711300210160ustar00rootroot00000000000000# Team Password Manager v.7.118.217 Docker Compose file # More information: https://teampasswordmanager.com/docs/docker/ version: '3' services: teampasswordmanager: image: teampasswordmanager/teampasswordmanager:latest depends_on: - mysql restart: always ports: - "8080:80" - "8443:443" volumes: - tpm_volume:/var/www/html networks: - tpm_network environment: - TPM_SERVER_TIMEZONE=Etc/UTC - TPM_PHP_TIMEZONE=Etc/UTC - TPM_ENCRYPT_DB_CONFIG=0 - TPM_CONFIG_HOSTNAME=mysql - TPM_CONFIG_PORT=3306 - TPM_CONFIG_USERNAME=tpm_user - TPM_CONFIG_PASSWORD=tpm_password - TPM_CONFIG_DATABASE=tpm_database - TPM_UPGRADE=0 mysql: image: mysql:5.7 restart: always ports: - "13306:3306" volumes: - tpm_mysqldata:/var/lib/mysql networks: - tpm_network environment: - MYSQL_USER=tpm_user - MYSQL_PASSWORD=tpm_password - MYSQL_DATABASE=tpm_database - MYSQL_ROOT_PASSWORD=password5.7 networks: tpm_network: driver: "bridge" volumes: tpm_mysqldata: driver: "local" tpm_volume: driver: "local"peshay-tpm-d71ce81/tests/get_sampledata.py000077500000000000000000000173561523703711300207260ustar00rootroot00000000000000#! /usr/bin/env python import errno import json import os import tpm # Taken from https://stackoverflow.com/a/600612/119527 def mkdir_p(path): try: os.makedirs(path) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise def safe_open_w(path): ''' Open "path" for writing, creating any parent directories as needed. ''' path = f'resources/{path}' dirpath = os.path.dirname(path) if dirpath != '': mkdir_p(dirpath) return open(path, 'w') # create a object for the connection settings URL = "http://localhost:8080" USER = 'john' PASS = 'demopassword' tpmconn = tpm.TpmApiv4(URL, username=USER, password=PASS) # Query values passsearches = ['test', 'reddit', 'facebook', 'dns', 'backup', 'firewall'] mypassearches =['john', 'jonny', 'facebook', 'amazon', 'backup'] projsearches = ['internal', 'company', 'website'] usersearches = ['Alan', 'Frank', 'Brown', 'Black', 'externalorg', 'teampasswordmanager', 'boss'] groupsearches = ['test', 'web', 'work', 'users'] # All projects AllProjects = tpmconn.list_projects() AllProjectIDs = [] for project in AllProjects: AllProjectIDs.append(project.get('id')) # All passwords AllPasswords = tpmconn.list_passwords() AllPasswordIDs = [] for password in AllPasswords: AllPasswordIDs.append(password.get('id')) # All MyPasswords AllMyPasswords = tpmconn.list_mypasswords() AllMyPasswordIDs = [] for mypassword in AllMyPasswords: AllMyPasswordIDs.append(mypassword.get('id')) # All users AllUsers = tpmconn.list_users() AllUserIDs = [] for user in AllUsers: AllUserIDs.append(user.get('id')) # All Groups AllGroups = tpmconn.list_groups() AllGroupIDs = [] for group in AllGroups: AllGroupIDs.append(group.get('id')) # List projects data = tpmconn.list_projects() with safe_open_w('projects.json') as outfile: json.dump(data, outfile) data = tpmconn.list_projects_archived() with safe_open_w('projects/archived.json') as outfile: json.dump(data, outfile) data = tpmconn.list_projects_favorite() with safe_open_w('projects/favorite.json') as outfile: json.dump(data, outfile) for search in projsearches: data = tpmconn.list_projects_search(search) with safe_open_w(f'projects/search/{search}.json') as outfile: json.dump(data, outfile) # subprojects for project_id in AllProjectIDs: data = tpmconn.list_subprojects(project_id) with safe_open_w(f'projects/{project_id}/subprojects.json') as outfile: json.dump(data, outfile) for project_id in AllProjectIDs: data = tpmconn.list_subprojects_action(project_id, 'new_pwd') with safe_open_w(f'projects/{project_id}/subprojects/new_pwd.json') as outfile: json.dump(data, outfile) # show project for project_id in AllProjectIDs: data = tpmconn.show_project(project_id) with safe_open_w(f'projects/{project_id}.json') as outfile: json.dump(data, outfile) for project_id in AllProjectIDs: data = tpmconn.list_passwords_of_project(project_id) with safe_open_w(f'projects/{project_id}/passwords.json') as outfile: json.dump(data, outfile) for project_id in AllProjectIDs: data = tpmconn.list_user_access_on_project(project_id) with safe_open_w(f'projects/{project_id}/security.json') as outfile: json.dump(data, outfile) ## special cases ## create_project(data) == return code 201 Created && created "id": 42 ### update_project == return code 204 No content ### change_parent_of_project == return code 204 No content ### update_security_of_project == 204 No content ### archive_project == 204 No content ### unarchive_project == 204 No content ### delete_project == 204 No content # List passwords data = tpmconn.list_passwords() with safe_open_w('passwords.json') as outfile: json.dump(data, outfile) data = tpmconn.list_passwords_archived() with safe_open_w('passwords/archived.json') as outfile: json.dump(data, outfile) data = tpmconn.list_passwords_favorite() with safe_open_w('passwords/favorite.json') as outfile: json.dump(data, outfile) for search in passsearches: data = tpmconn.list_passwords_search(search) with safe_open_w(f'passwords/search/{search}.json') as outfile: json.dump(data, outfile) for password_id in AllPasswordIDs: data = tpmconn.show_password(password_id) with safe_open_w(f'passwords/{password_id}.json') as outfile: json.dump(data, outfile) for password_id in AllPasswordIDs: data = tpmconn.list_user_access_on_password(password_id) with safe_open_w(f'passwords/{password_id}/security.json') as outfile: json.dump(data, outfile) ## special cases ## create_password(data) == return code 201 Created && created "id": 42 ### update_password == return code 204 No content ### update_security_of_password == 204 No content ### update_custom_fields_of_password == 204 No content ### delete_password == 204 No content ### delete_password == 204 No content ### unlock_password == 204 No content # List MyPasswords data = tpmconn.list_mypasswords() with safe_open_w('my_passwords.json') as outfile: json.dump(data, outfile) for search in mypassearches: data = tpmconn.list_mypasswords_search(search) with safe_open_w(f'my_passwords/search/{search}.json') as outfile: json.dump(data, outfile) for mypassword_id in AllMyPasswordIDs: data = tpmconn.show_mypassword(mypassword_id) with safe_open_w(f'my_passwords/{mypassword_id}.json') as outfile: json.dump(data, outfile) ## special cases ## create_mypassword(data) == return code 201 Created && created "id": 42 ### update_mypassword == return code 204 No content ### delete_mypassword == 204 No content # List Favorites ## special cases ## set_favorite_password(ID) == return 204 No content ### unset_favorite_password(ID) == return code 204 No content ## set_favorite_project(ID) == return 204 No content ### unset_favorite_project(ID) == return code 204 No content # List Users data = tpmconn.list_users() with safe_open_w('users.json') as outfile: json.dump(data, outfile) for user_id in AllUserIDs: data = tpmconn.show_user(user_id) with safe_open_w(f'users/{user_id}.json') as outfile: json.dump(data, outfile) data = tpmconn.show_me() with safe_open_w('users/me.json') as outfile: json.dump(data, outfile) ## special cases ## create_user(data) == return code 201 Created && created "id": 42 ### update_user(ID, data) == return code 204 No content ### change_user_password == 204 No content ### activate_user == 204 No content ### deactivate_user == 204 No content ### convert_user_to_ldap == 204 No content ### convert_ldap_user_to_normal == 204 No content ### delete_user == 204 No content # List Groups data = tpmconn.list_groups() with safe_open_w('groups.json') as outfile: json.dump(data, outfile) for group_id in AllGroupIDs: data = tpmconn.show_group(group_id) with safe_open_w(f'groups/{group_id}.json') as outfile: json.dump(data, outfile) data = tpmconn.show_me() with safe_open_w('users/me.json') as outfile: json.dump(data, outfile) ## special cases ## create_group(data) == return code 201 Created && created "id": 42 ### update_group(ID, data) == return code 204 No content ### add_user_to_group == 204 No content ### delete_user_from_group == 204 No content ### delete_group == 204 No content # others ### generate_password == 204 No content ### get_version == 204 No content data = tpmconn.generate_password() with safe_open_w('generate_password.json'.format()) as outfile: json.dump(data, outfile) data = tpmconn.get_version() with safe_open_w('version.json'.format()) as outfile: json.dump(data, outfile) data = tpmconn.get_latest_version() with safe_open_w('version/check_latest.json'.format()) as outfile: json.dump(data, outfile) ## special cases ## up_to_date = True or False peshay-tpm-d71ce81/tests/requirements.txt000066400000000000000000000000471523703711300206500ustar00rootroot00000000000000pytest>=9.0.3 pytest-cov requests-mock peshay-tpm-d71ce81/tests/resources/000077500000000000000000000000001523703711300173755ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/files/000077500000000000000000000000001523703711300204775ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/files/4.json000066400000000000000000000013151523703711300215350ustar00rootroot00000000000000{ "id": 309, "name": "server specs.pdf", "container": { "type": "password", "id": 9972, "is_linked": false, "source_id": 0 }, "notes": "Given by the vendor", "size_bytes": 62393, "size_txt": "60.93 kb", "uploaded_on": "2021-09-16 12:32:42", "uploaded_by": { "id": 1570, "username": "johnboss", "email_address": "johnboss@teampasswordmanager.com", "name": "John Boss", "role": "Admin" }, "notes_updated_on": "2021-09-16 12:32:42", "notes_updated_by": { "id": 1570, "username": "johnboss", "email_address": "johnboss@teampasswordmanager.com", "name": "John Boss", "role": "Admin" } }peshay-tpm-d71ce81/tests/resources/files/download/000077500000000000000000000000001523703711300223065ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/files/download/4.json000066400000000000000000000013151523703711300233440ustar00rootroot00000000000000{ "id": 309, "name": "server specs.pdf", "container": { "type": "password", "id": 9972, "is_linked": false, "source_id": 0 }, "notes": "Given by the vendor", "size_bytes": 62393, "size_txt": "60.93 kb", "uploaded_on": "2021-09-16 12:32:42", "uploaded_by": { "id": 1570, "username": "johnboss", "email_address": "johnboss@teampasswordmanager.com", "name": "John Boss", "role": "Admin" }, "notes_updated_on": "2021-09-16 12:32:42", "notes_updated_by": { "id": 1570, "username": "johnboss", "email_address": "johnboss@teampasswordmanager.com", "name": "John Boss", "role": "Admin" } }peshay-tpm-d71ce81/tests/resources/files/max_upload_file_size.json000066400000000000000000000001311523703711300255470ustar00rootroot00000000000000{ "max_upload_file_size_bytes": 335544320, "max_upload_file_size_text": "320Mb" }peshay-tpm-d71ce81/tests/resources/files/uploads_folder_info.json000066400000000000000000000000741523703711300254100ustar00rootroot00000000000000{ "uploads_folder": "./uploads/", "writable": true }peshay-tpm-d71ce81/tests/resources/generate_password.json000066400000000000000000000000321523703711300237770ustar00rootroot00000000000000{"password": "Pt8)Zc7& peshay-tpm-d71ce81/tests/resources/plain.txt000066400000000000000000000000341523703711300212360ustar00rootroot00000000000000this is not a json response peshay-tpm-d71ce81/tests/resources/projects.json000066400000000000000000000104041523703711300221200ustar00rootroot00000000000000[{"archived": false, "name": "www.fictionalgadgetsite.com", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 18}, {"archived": false, "name": "Internal systems", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 17}, {"archived": false, "name": "Company internet services", "tags": "internal", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 16}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "inventedsitename.com", "tags": "project,test", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 14}, {"archived": false, "name": "Job search site campaign", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 13}, {"archived": false, "name": "Client Anoname", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 12}, {"archived": false, "name": "Client Banother", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 11}, {"archived": false, "name": "New company app", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 10}, {"archived": false, "name": "Internal", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 6}, {"archived": false, "name": "Company projects", "tags": "project", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 5}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "SEO", "tags": "client,seo", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 3}, {"archived": false, "name": "General consulting", "tags": "client,consulting", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 2}, {"archived": false, "name": "Clients", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 1}]peshay-tpm-d71ce81/tests/resources/projects/000077500000000000000000000000001523703711300212265ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/1.json000066400000000000000000000020621523703711300222610ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "Clients", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 0, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": null, "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}], "id": 1, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/1/000077500000000000000000000000001523703711300213665ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/1/passwords.json000066400000000000000000000000021523703711300242760ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/1/security.json000066400000000000000000000034711523703711300241350ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}]peshay-tpm-d71ce81/tests/resources/projects/1/subprojects.json000066400000000000000000000007121523703711300246240ustar00rootroot00000000000000[{"archived": false, "name": "General consulting", "has_children": true, "favorite": false, "num_pwds_branch": 15, "disabled": false, "num_pwds": 0, "id": 2}, {"archived": false, "name": "SEO", "has_children": true, "favorite": false, "num_pwds_branch": 2, "disabled": false, "num_pwds": 0, "id": 3}, {"archived": false, "name": "Website development", "has_children": true, "favorite": true, "num_pwds_branch": 12, "disabled": false, "num_pwds": 0, "id": 4}]peshay-tpm-d71ce81/tests/resources/projects/1/subprojects/000077500000000000000000000000001523703711300237315ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/1/subprojects/new_pwd.json000066400000000000000000000007121523703711300262670ustar00rootroot00000000000000[{"archived": false, "name": "General consulting", "has_children": true, "favorite": false, "num_pwds_branch": 15, "disabled": false, "num_pwds": 0, "id": 2}, {"archived": false, "name": "SEO", "has_children": true, "favorite": false, "num_pwds_branch": 2, "disabled": false, "num_pwds": 0, "id": 3}, {"archived": false, "name": "Website development", "has_children": true, "favorite": true, "num_pwds_branch": 12, "disabled": false, "num_pwds": 0, "id": 4}]peshay-tpm-d71ce81/tests/resources/projects/10.json000066400000000000000000000020741523703711300223440ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "New company app", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "internal", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": [{"user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}], "parent_id": 5, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "parents": [5], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": null, "id": 10, "num_passwords": 4, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/10/000077500000000000000000000000001523703711300214465ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/10/passwords.json000066400000000000000000000026111523703711300243660ustar00rootroot00000000000000[{"username": "root", "archived": false, "locked": false, "name": "VPS root", "tags": "server,vps", "access_info": "7.8.9.10", "favorite": false, "email": "", "project": {"name": "New company app"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 17}, {"username": "newcpapp", "archived": false, "locked": false, "name": "Github account", "tags": "github", "access_info": "https://github.com/login", "favorite": false, "email": "", "project": {"name": "New company app"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 16}, {"username": "", "archived": false, "locked": false, "name": "Maps API KEY", "tags": "api,maps", "access_info": "", "favorite": false, "email": "", "project": {"name": "New company app"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 15}, {"username": "myuser2", "archived": false, "locked": false, "name": "VPS db", "tags": "server,vps", "access_info": "7.8.9.10", "favorite": false, "email": "", "project": {"name": "New company app"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 14}]peshay-tpm-d71ce81/tests/resources/projects/10/security.json000066400000000000000000000012331523703711300242070ustar00rootroot00000000000000[{"granted_via": "Project manager", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "User direct", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}]peshay-tpm-d71ce81/tests/resources/projects/10/subprojects.json000066400000000000000000000000021523703711300246740ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/10/subprojects/000077500000000000000000000000001523703711300240115ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/10/subprojects/new_pwd.json000066400000000000000000000000021523703711300263370ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/11.json000066400000000000000000000015751523703711300223520ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Client Banother", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client", "grant_all_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 2, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "parents": [1, 2], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": null, "id": 11, "num_passwords": 4, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/11/000077500000000000000000000000001523703711300214475ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/11/passwords.json000066400000000000000000000026171523703711300243750ustar00rootroot00000000000000[{"username": "admin", "archived": false, "locked": false, "name": "Internal app user", "tags": "app", "access_info": "internalapp.exe (from any pc on the network)", "favorite": false, "email": "", "project": {"name": "Client Banother"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 28}, {"username": "wmtcu", "archived": false, "locked": false, "name": "TC wmtc", "tags": "hardware", "access_info": "192.168.1.9", "favorite": false, "email": "", "project": {"name": "Client Banother"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 25}, {"username": "", "archived": false, "locked": false, "name": "TC bk1", "tags": "hardware", "access_info": "", "favorite": false, "email": "", "project": {"name": "Client Banother"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 21}, {"username": "", "archived": false, "locked": false, "name": "Wifi password", "tags": "hardware,wifi", "access_info": "", "favorite": true, "email": "", "project": {"name": "Client Banother"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 20}]peshay-tpm-d71ce81/tests/resources/projects/11/security.json000066400000000000000000000037361523703711300242220ustar00rootroot00000000000000[{"granted_via": "Grant all users", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Project manager", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "jake", "role": "Read only", "email_address": "jake@externalorg.com", "id": 9, "name": "Jake Brown"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Grant all users", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}]peshay-tpm-d71ce81/tests/resources/projects/11/subprojects.json000066400000000000000000000000021523703711300246750ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/11/subprojects/000077500000000000000000000000001523703711300240125ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/11/subprojects/new_pwd.json000066400000000000000000000000021523703711300263400ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/12.json000066400000000000000000000024131523703711300223430ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Client Anoname", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": [{"user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}], "parent_id": 2, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "parents": [1, 2], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": null, "id": 12, "num_passwords": 5, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/12/000077500000000000000000000000001523703711300214505ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/12/passwords.json000066400000000000000000000035561523703711300244010ustar00rootroot00000000000000[{"username": "", "archived": false, "locked": false, "name": "Mail info for main site", "tags": "email", "access_info": "Outlook in Lisa's computer", "favorite": false, "email": "info@anonamesite.com", "project": {"name": "Client Anoname"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 27}, {"username": "", "archived": false, "locked": false, "name": "Twitterfeed", "tags": "rss,twitter", "access_info": "http://twitterfeed.com/session/new", "favorite": false, "email": "anonane@gmail.com", "project": {"name": "Client Anoname"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 26}, {"username": "test", "archived": false, "locked": false, "name": ".htaccess new site (no tags)", "tags": "", "access_info": "http://test.anoname.com", "favorite": false, "email": "", "project": {"name": "Client Anoname"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 24}, {"username": "admin", "archived": false, "locked": false, "name": "Forum admin", "tags": "forum,social", "access_info": "http://anonamesite.com/phpbb", "favorite": false, "email": "", "project": {"name": "Client Anoname"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 19}, {"username": "", "archived": false, "locked": false, "name": "Blog", "tags": "blog,seo", "access_info": "http://anonameblog.wordpress.com", "favorite": false, "email": "", "project": {"name": "Client Anoname"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 18}]peshay-tpm-d71ce81/tests/resources/projects/12/security.json000066400000000000000000000016101523703711300242100ustar00rootroot00000000000000[{"granted_via": "Project manager", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "User direct", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "User direct", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/12/subprojects.json000066400000000000000000000000021523703711300246760ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/12/subprojects/000077500000000000000000000000001523703711300240135ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/12/subprojects/new_pwd.json000066400000000000000000000000021523703711300263410ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/13.json000066400000000000000000000021271523703711300223460ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Job search site campaign", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 4, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "parents": [1, 4], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}], "id": 13, "num_passwords": 8, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/13/000077500000000000000000000000001523703711300214515ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/13/passwords.json000066400000000000000000000061141523703711300243730ustar00rootroot00000000000000[{"username": "admin", "archived": false, "locked": false, "name": "WP admin", "tags": "wordpress", "access_info": "http://localhost/testsite/wp-admin", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 36}, {"username": "user facebook's account", "archived": false, "locked": false, "name": "Stumbleupon", "tags": "social,stumbleupon", "access_info": "https://www.stumbleupon.com/login", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 35}, {"username": "jssitered", "archived": false, "locked": false, "name": "Reddit", "tags": "reddit,social", "access_info": "http://www.reddit.com", "favorite": true, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 34}, {"username": "login with facebook", "archived": false, "locked": false, "name": "Pinterest", "tags": "pinterest,social", "access_info": "https://pinterest.com/login/", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 31}, {"username": "", "archived": false, "locked": false, "name": "Facebook", "tags": "facebook,social", "access_info": "https://www.facebook.com", "favorite": false, "email": "infojssc@gmail.com", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 30}, {"username": "infojssc", "archived": false, "locked": false, "name": "Email+ account", "tags": "g+,seo,social", "access_info": "https://plug.google.com", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 29}, {"username": "", "archived": false, "locked": false, "name": "WP helper website", "tags": "blog,seo", "access_info": "http://hiringformoney.wordpress.com", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 23}, {"username": "", "archived": false, "locked": false, "name": "Blogger helper website", "tags": "blog,seo", "access_info": "http://jobsearchtipos.blogspot.com", "favorite": false, "email": "", "project": {"name": "Job search site campaign"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 22}]peshay-tpm-d71ce81/tests/resources/projects/13/security.json000066400000000000000000000034671523703711300242250ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Project manager", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/13/subprojects.json000066400000000000000000000000021523703711300246770ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/13/subprojects/000077500000000000000000000000001523703711300240145ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/13/subprojects/new_pwd.json000066400000000000000000000000021523703711300263420ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/14.json000066400000000000000000000021321523703711300223430ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "inventedsitename.com", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "project,test", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 5, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "parents": [5], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}], "id": 14, "num_passwords": 7, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/14/000077500000000000000000000000001523703711300214525ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/14/passwords.json000066400000000000000000000051331523703711300243740ustar00rootroot00000000000000[{"username": "admin_inv", "archived": false, "locked": false, "name": "WP admin user", "tags": "wordpress", "access_info": "http://inventedsitename.com/wp-admin", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 43}, {"username": "ftpu88", "archived": false, "locked": false, "name": "FTP", "tags": "ftp", "access_info": "ftp://78.33.44.22", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 41}, {"username": "admin", "archived": false, "locked": false, "name": "phpBB3 admin", "tags": "forum", "access_info": "http://inventedsitename.com/forum", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 40}, {"username": "", "archived": false, "locked": false, "name": "Directadmin (server panel)", "tags": "server", "access_info": "http://inventedsitename.com:555", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 38}, {"username": "root", "archived": false, "locked": false, "name": "Svr root", "tags": "server", "access_info": "78.33.44.22", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 37}, {"username": "editor2", "archived": false, "locked": false, "name": "WP editor 1", "tags": "wordpress", "access_info": "http://inventedsitename.com/wp-admin", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 33}, {"username": "editor1", "archived": false, "locked": false, "name": "WP editor 1", "tags": "wordpress", "access_info": "http://inventedsitename.com/wp-admin", "favorite": false, "email": "", "project": {"name": "inventedsitename.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 32}]peshay-tpm-d71ce81/tests/resources/projects/14/security.json000066400000000000000000000035031523703711300242150ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/14/subprojects.json000066400000000000000000000000021523703711300247000ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/14/subprojects/000077500000000000000000000000001523703711300240155ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/14/subprojects/new_pwd.json000066400000000000000000000000021523703711300263430ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/15.json000066400000000000000000000021061523703711300223450ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Sempry website", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client,web", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": [{"user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}], "parent_id": 4, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "parents": [1, 4], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": null, "id": 15, "num_passwords": 4, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/15/000077500000000000000000000000001523703711300214535ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/15/passwords.json000066400000000000000000000027021523703711300243740ustar00rootroot00000000000000[{"username": "myuser", "archived": false, "locked": false, "name": "External db server", "tags": "db,mysql,server", "access_info": "http://www.semprysiteinvented.com/phpMyAdmin", "favorite": false, "email": "", "project": {"name": "Sempry website"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 45}, {"username": "root", "archived": false, "locked": false, "name": "Internal db server", "tags": "server", "access_info": "192.168.1.3", "favorite": false, "email": "", "project": {"name": "Sempry website"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 44}, {"username": "sempuser", "archived": false, "locked": false, "name": "AnotherHP CPanel", "tags": "server", "access_info": "http://4.3.2.1:2222", "favorite": false, "email": "", "project": {"name": "Sempry website"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 42}, {"username": "", "archived": false, "locked": false, "name": "Linode VPS", "tags": "server", "access_info": "1.2.4.4", "favorite": false, "email": "", "project": {"name": "Sempry website"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 39}]peshay-tpm-d71ce81/tests/resources/projects/15/security.json000066400000000000000000000012411523703711300242130ustar00rootroot00000000000000[{"granted_via": "Project manager", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "User direct", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}]peshay-tpm-d71ce81/tests/resources/projects/15/subprojects.json000066400000000000000000000000021523703711300247010ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/15/subprojects/000077500000000000000000000000001523703711300240165ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/15/subprojects/new_pwd.json000066400000000000000000000000021523703711300263440ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/16.json000066400000000000000000000016011523703711300223450ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Company internet services", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "internal", "grant_all_permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}, "notes": "", "favorite": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 6, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": [6], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": null, "id": 16, "num_passwords": 11, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/16/000077500000000000000000000000001523703711300214545ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/16/passwords.json000066400000000000000000000102731523703711300243770ustar00rootroot00000000000000[{"username": "", "archived": false, "locked": false, "name": "Delicious bookmarks", "tags": "delicious,social", "access_info": "https://delicious.com/ourcompany", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 66}, {"username": "", "archived": false, "locked": false, "name": "iMybackup account", "tags": "backup", "access_info": "http://ourcompany.imybkacctinvented.com", "favorite": true, "email": "ourcemail@ourcdomain.com", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 65}, {"username": "", "archived": false, "locked": false, "name": "Pingdom", "tags": "monitoring", "access_info": "https://www.pingdom.com/", "favorite": false, "email": "ourcemail@ourcdomain.com", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 61}, {"username": "", "archived": false, "locked": false, "name": "DNS server account", "tags": "hosting", "access_info": "http://ourcompany.mydnsacct.com", "favorite": true, "email": "ourcemail@ourcdomain.com", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 60}, {"username": "1234567", "archived": false, "locked": false, "name": "Hosting provider", "tags": "hosting", "access_info": "http://www.godaddy.com/", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 59}, {"username": "ourcompany", "archived": false, "locked": false, "name": "Linkedin", "tags": "linkedin,social", "access_info": "http://www.linkedin.com/", "favorite": true, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 55}, {"username": "ourcompany", "archived": false, "locked": false, "name": "Facebook", "tags": "facebook,social", "access_info": "https://www.facebook.com/", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 54}, {"username": "ourcompany", "archived": false, "locked": false, "name": "Twitter", "tags": "social,twitter", "access_info": "https://twitter.com", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 53}, {"username": "", "archived": false, "locked": false, "name": "Email Account", "tags": "consulting,email", "access_info": "https://accounts.google.com/", "favorite": false, "email": "info@ourcompany.com", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 52}, {"username": "root", "archived": false, "locked": false, "name": "VPS2", "tags": "server", "access_info": "16.17.18.19", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 47}, {"username": "", "archived": false, "locked": false, "name": "VPS1", "tags": "server", "access_info": "http://12.13.14.15", "favorite": false, "email": "", "project": {"name": "Company internet services"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 46}]peshay-tpm-d71ce81/tests/resources/projects/16/security.json000066400000000000000000000040561523703711300242230ustar00rootroot00000000000000[{"granted_via": "Grant all users", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Grant all users", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Grant all users", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Grant all users", "user": {"username": "jake", "role": "Read only", "email_address": "jake@externalorg.com", "id": 9, "name": "Jake Brown"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Grant all users", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Grant all users", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Grant all users", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Grant all users", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/16/subprojects.json000066400000000000000000000000021523703711300247020ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/16/subprojects/000077500000000000000000000000001523703711300240175ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/16/subprojects/new_pwd.json000066400000000000000000000000021523703711300263450ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/17.json000066400000000000000000000022361523703711300223530ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "Internal systems", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "internal", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": [{"user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}], "parent_id": 6, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "parents": [6], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 3, "name": "External users"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}], "id": 17, "num_passwords": 5, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/17/000077500000000000000000000000001523703711300214555ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/17/passwords.json000066400000000000000000000034151523703711300244000ustar00rootroot00000000000000[{"username": "sa", "archived": false, "locked": false, "name": "SQL Server", "tags": "db,server,sqlserver", "access_info": "192.168.0.23", "favorite": false, "email": "", "project": {"name": "Internal systems"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 62}, {"username": "admin", "archived": false, "locked": false, "name": "Intranet administrator", "tags": "server", "access_info": "192.168.0.23", "favorite": false, "email": "", "project": {"name": "Internal systems"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 56}, {"username": "dkdddrd", "archived": false, "locked": false, "name": "Main Router", "tags": "hardware", "access_info": "192.168.0.1", "favorite": false, "email": "", "project": {"name": "Internal systems"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 51}, {"username": "root", "archived": false, "locked": false, "name": "Firewall root", "tags": "server", "access_info": "192.168.0.2", "favorite": true, "email": "", "project": {"name": "Internal systems"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 49}, {"username": "root", "archived": false, "locked": false, "name": "Fileserver root", "tags": "server", "access_info": "192.168.0.34", "favorite": false, "email": "", "project": {"name": "Internal systems"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 48}]peshay-tpm-d71ce81/tests/resources/projects/17/security.json000066400000000000000000000015651523703711300242260ustar00rootroot00000000000000[{"granted_via": "Project manager", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: External users", "user": {"username": "jake", "role": "Read only", "email_address": "jake@externalorg.com", "id": 9, "name": "Jake Brown"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "User direct", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}]peshay-tpm-d71ce81/tests/resources/projects/17/subprojects.json000066400000000000000000000000021523703711300247030ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/17/subprojects/000077500000000000000000000000001523703711300240205ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/17/subprojects/new_pwd.json000066400000000000000000000000021523703711300263460ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/18.json000066400000000000000000000021171523703711300223520ustar00rootroot00000000000000{"is_leaf": true, "archived": false, "name": "www.fictionalgadgetsite.com", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 5, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "parents": [5], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}], "id": 18, "num_passwords": 7, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/18/000077500000000000000000000000001523703711300214565ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/18/passwords.json000066400000000000000000000053131523703711300244000ustar00rootroot00000000000000[{"username": "admin_sg", "archived": false, "locked": false, "name": "Wordpress admin", "tags": "wordpress", "access_info": "http://www.fictionalgadgetsite.com/wp-admin", "favorite": true, "email": "", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 68}, {"username": "spftpu", "archived": false, "locked": false, "name": "Ftp", "tags": "ftp", "access_info": "sftp://www.fictionalgadgetsite.com", "favorite": false, "email": "", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 67}, {"username": "", "archived": false, "locked": false, "name": "Amazon", "tags": "amazon", "access_info": "http://www.amazon.com", "favorite": false, "email": "info@fictionalgadgetsite.com", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 64}, {"username": "", "archived": false, "locked": false, "name": "Email account", "tags": "client,email", "access_info": "https://accounts.google.com/", "favorite": false, "email": "info@fictionalgadgetsite.com", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:45", "expiry_status": 0, "external_sharing": false, "id": 63}, {"username": "fictionalgadgetsite", "archived": false, "locked": false, "name": "Facebook", "tags": "facebook,social", "access_info": "https://www.facebook.com/", "favorite": false, "email": "", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 58}, {"username": "fictionalgadgetsite", "archived": false, "locked": false, "name": "Twitter", "tags": "social,twitter", "access_info": "https://twitter.com", "favorite": false, "email": "", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 57}, {"username": "sgsiteroot", "archived": false, "locked": false, "name": "MySQL user", "tags": "db,mysql,server", "access_info": "localhost", "favorite": false, "email": "", "project": {"name": "www.fictionalgadgetsite.com"}, "num_files": 0, "expiry_date": null, "notes_snippet": "", "updated_on": "2016-09-07 04:41:44", "expiry_status": 0, "external_sharing": false, "id": 50}]peshay-tpm-d71ce81/tests/resources/projects/18/security.json000066400000000000000000000034371523703711300242270ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Project manager", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Admin rights", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 20, "label": "PRJ_PERM_ACCESS_READ"}}]peshay-tpm-d71ce81/tests/resources/projects/18/subprojects.json000066400000000000000000000000021523703711300247040ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/18/subprojects/000077500000000000000000000000001523703711300240215ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/18/subprojects/new_pwd.json000066400000000000000000000000021523703711300263470ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/2.json000066400000000000000000000021131523703711300222570ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "General consulting", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client,consulting", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 1, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": [1], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}], "id": 2, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/2/000077500000000000000000000000001523703711300213675ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/2/passwords.json000066400000000000000000000000021523703711300242770ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/2/security.json000066400000000000000000000035111523703711300241310ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/2/subprojects.json000066400000000000000000000007371523703711300246340ustar00rootroot00000000000000[{"archived": false, "name": "Client Anoname", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": false, "num_pwds": 5, "id": 12}, {"archived": false, "name": "Client Banother", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 11}, {"archived": true, "name": "HW maintenance for Notanymore", "has_children": false, "favorite": false, "num_pwds_branch": 6, "disabled": false, "num_pwds": 6, "id": 8}]peshay-tpm-d71ce81/tests/resources/projects/2/subprojects/000077500000000000000000000000001523703711300237325ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/2/subprojects/new_pwd.json000066400000000000000000000007361523703711300262760ustar00rootroot00000000000000[{"archived": false, "name": "Client Anoname", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": false, "num_pwds": 5, "id": 12}, {"archived": false, "name": "Client Banother", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 11}, {"archived": true, "name": "HW maintenance for Notanymore", "has_children": false, "favorite": false, "num_pwds_branch": 6, "disabled": true, "num_pwds": 6, "id": 8}]peshay-tpm-d71ce81/tests/resources/projects/3.json000066400000000000000000000020561523703711300222660ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "SEO", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client,seo", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 1, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": [1], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}], "id": 3, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/3/000077500000000000000000000000001523703711300213705ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/3/passwords.json000066400000000000000000000000021523703711300243000ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/3/security.json000066400000000000000000000034551523703711300241410ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 50, "label": "PRJ_PERM_ACCESS_MANAGE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}]peshay-tpm-d71ce81/tests/resources/projects/3/subprojects.json000066400000000000000000000002321523703711300246230ustar00rootroot00000000000000[{"archived": true, "name": "Old SEO project", "has_children": false, "favorite": false, "num_pwds_branch": 2, "disabled": false, "num_pwds": 2, "id": 9}]peshay-tpm-d71ce81/tests/resources/projects/3/subprojects/000077500000000000000000000000001523703711300237335ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/3/subprojects/new_pwd.json000066400000000000000000000002311523703711300262650ustar00rootroot00000000000000[{"archived": true, "name": "Old SEO project", "has_children": false, "favorite": false, "num_pwds_branch": 2, "disabled": true, "num_pwds": 2, "id": 9}]peshay-tpm-d71ce81/tests/resources/projects/4.json000066400000000000000000000020731523703711300222660ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "Website development", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "client,web", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 1, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": [1], "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}], "id": 4, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/4/000077500000000000000000000000001523703711300213715ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/4/files.json000066400000000000000000000006141523703711300233670ustar00rootroot00000000000000[ { "id": 65, "filename": "mouse.jpg", "size_bytes": 82935, "size_txt": "80.99 kb", "notes_snippet": "A little ...", "updated_on": "2021-07-15 13:00:48" }, { "id": 58, "filename": "server_room_map.pdf", "size_bytes": 92655, "size_txt": "90.48 kb", "notes_snippet": "", "updated_on": "2019-04-25 13:37:00" } ]peshay-tpm-d71ce81/tests/resources/projects/4/passwords.json000066400000000000000000000000021523703711300243010ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/4/security.json000066400000000000000000000034561523703711300241430ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 40, "label": "PRJ_PERM_ACCESS_EDIT_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/4/subprojects.json000066400000000000000000000005001523703711300246220ustar00rootroot00000000000000[{"archived": false, "name": "Job search site campaign", "has_children": false, "favorite": false, "num_pwds_branch": 8, "disabled": false, "num_pwds": 8, "id": 13}, {"archived": false, "name": "Sempry website", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 15}]peshay-tpm-d71ce81/tests/resources/projects/4/subprojects/000077500000000000000000000000001523703711300237345ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/4/subprojects/new_pwd.json000066400000000000000000000005001523703711300262650ustar00rootroot00000000000000[{"archived": false, "name": "Job search site campaign", "has_children": false, "favorite": false, "num_pwds_branch": 8, "disabled": false, "num_pwds": 8, "id": 13}, {"archived": false, "name": "Sempry website", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 15}]peshay-tpm-d71ce81/tests/resources/projects/4/upload.json000066400000000000000000000000211523703711300235410ustar00rootroot00000000000000{ "id": 373 }peshay-tpm-d71ce81/tests/resources/projects/5.json000066400000000000000000000020671523703711300222720ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "Company projects", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "project", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 0, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": null, "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}], "id": 5, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/5/000077500000000000000000000000001523703711300213725ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/5/passwords.json000066400000000000000000000000021523703711300243020ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/5/security.json000066400000000000000000000034471523703711300241440ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 10, "label": "PRJ_PERM_ACCESS_TRAVERSE"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 0, "label": "PRJ_PERM_NO_ACCESS"}}]peshay-tpm-d71ce81/tests/resources/projects/5/subprojects.json000066400000000000000000000007451523703711300246360ustar00rootroot00000000000000[{"archived": false, "name": "inventedsitename.com", "has_children": false, "favorite": false, "num_pwds_branch": 7, "disabled": false, "num_pwds": 7, "id": 14}, {"archived": false, "name": "New company app", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 10}, {"archived": false, "name": "www.fictionalgadgetsite.com", "has_children": false, "favorite": false, "num_pwds_branch": 7, "disabled": false, "num_pwds": 7, "id": 18}]peshay-tpm-d71ce81/tests/resources/projects/5/subprojects/000077500000000000000000000000001523703711300237355ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/5/subprojects/new_pwd.json000066400000000000000000000007451523703711300263010ustar00rootroot00000000000000[{"archived": false, "name": "inventedsitename.com", "has_children": false, "favorite": false, "num_pwds_branch": 7, "disabled": false, "num_pwds": 7, "id": 14}, {"archived": false, "name": "New company app", "has_children": false, "favorite": false, "num_pwds_branch": 4, "disabled": false, "num_pwds": 4, "id": 10}, {"archived": false, "name": "www.fictionalgadgetsite.com", "has_children": false, "favorite": false, "num_pwds_branch": 7, "disabled": false, "num_pwds": 7, "id": 18}]peshay-tpm-d71ce81/tests/resources/projects/6.json000066400000000000000000000020731523703711300222700ustar00rootroot00000000000000{"is_leaf": false, "archived": false, "name": "Internal", "user_permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}, "tags": "internal", "grant_all_permission": {"id": -1, "label": "PRJ_PERM_DO_NOT_SET"}, "notes": "", "favorite": false, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "users_permissions": null, "parent_id": 0, "created_on": "2016-09-07 04:41:44", "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "parents": null, "user_can_create_passwords": true, "num_files": 0, "updated_on": "2016-09-07 04:41:44", "groups_permissions": [{"group": {"id": 1, "name": "Web work"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"group": {"id": 2, "name": "IT work"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}], "id": 6, "num_passwords": 0, "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/projects/6/000077500000000000000000000000001523703711300213735ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/6/passwords.json000066400000000000000000000000021523703711300243030ustar00rootroot00000000000000[]peshay-tpm-d71ce81/tests/resources/projects/6/security.json000066400000000000000000000035211523703711300241360ustar00rootroot00000000000000[{"granted_via": "Group: IT work", "user": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "frank", "role": "Normal user", "email_address": "frank@teampasswordmanager.com", "id": 2, "name": "Frank Steel"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "janine", "role": "Normal user", "email_address": "janine@teampasswordmanager.com", "id": 7, "name": "Janine Black"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Project manager", "user": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "permission": {"id": 60, "label": "PRJ_PERM_MANAGE"}}, {"granted_via": "Group: Web work", "user": {"username": "lucas", "role": "Normal user", "email_address": "lucas@teampasswordmanager.com", "id": 5, "name": "Lucas Cross"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: IT work", "user": {"username": "tom", "role": "Normal user", "email_address": "tom@teampasswordmanager.com", "id": 8, "name": "Tom Landy"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}, {"granted_via": "Group: Web work", "user": {"username": "zoe", "role": "Normal user", "email_address": "zoe@teampasswordmanager.com", "id": 4, "name": "Zoe Timpelton"}, "permission": {"id": 30, "label": "PRJ_PERM_ACCESS_CREATE_PWD"}}]peshay-tpm-d71ce81/tests/resources/projects/6/subprojects.json000066400000000000000000000007421523703711300246340ustar00rootroot00000000000000[{"archived": false, "name": "Company internet services", "has_children": false, "favorite": true, "num_pwds_branch": 11, "disabled": false, "num_pwds": 11, "id": 16}, {"archived": false, "name": "Internal systems", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": false, "num_pwds": 5, "id": 17}, {"archived": true, "name": "TPM social campaign", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": false, "num_pwds": 5, "id": 7}]peshay-tpm-d71ce81/tests/resources/projects/6/subprojects/000077500000000000000000000000001523703711300237365ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/6/subprojects/new_pwd.json000066400000000000000000000007411523703711300262760ustar00rootroot00000000000000[{"archived": false, "name": "Company internet services", "has_children": false, "favorite": true, "num_pwds_branch": 11, "disabled": false, "num_pwds": 11, "id": 16}, {"archived": false, "name": "Internal systems", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": false, "num_pwds": 5, "id": 17}, {"archived": true, "name": "TPM social campaign", "has_children": false, "favorite": false, "num_pwds_branch": 5, "disabled": true, "num_pwds": 5, "id": 7}]peshay-tpm-d71ce81/tests/resources/projects/archived.json000066400000000000000000000015721523703711300237130ustar00rootroot00000000000000[{"archived": true, "name": "Old SEO project", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 9}, {"archived": true, "name": "HW maintenance for Notanymore", "tags": "client", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 8}, {"archived": true, "name": "TPM social campaign", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 7}]peshay-tpm-d71ce81/tests/resources/projects/favorite.json000066400000000000000000000011011523703711300237310ustar00rootroot00000000000000[{"archived": false, "name": "Company internet services", "tags": "internal", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 16}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}]peshay-tpm-d71ce81/tests/resources/projects/search/000077500000000000000000000000001523703711300224735ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/projects/search/company.json000066400000000000000000000015401523703711300250340ustar00rootroot00000000000000[{"archived": false, "name": "Company internet services", "tags": "internal", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 16}, {"archived": false, "name": "New company app", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 10}, {"archived": false, "name": "Company projects", "tags": "project", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 5}]peshay-tpm-d71ce81/tests/resources/projects/search/internal.json000066400000000000000000000026521523703711300252070ustar00rootroot00000000000000[{"archived": false, "name": "Internal systems", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 17}, {"archived": false, "name": "Company internet services", "tags": "internal", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 16}, {"archived": false, "name": "New company app", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 10}, {"archived": true, "name": "TPM social campaign", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "claire", "role": "Project manager", "email_address": "claire@teampasswordmanager.com", "id": 3, "name": "Claire Wood"}, "updated_on": "2016-09-07 04:41:44", "id": 7}, {"archived": false, "name": "Internal", "tags": "internal", "favorite": false, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 6}]peshay-tpm-d71ce81/tests/resources/projects/search/search with spaces.json000066400000000000000000000516601523703711300270360ustar00rootroot00000000000000[{"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}, {"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}] peshay-tpm-d71ce81/tests/resources/projects/search/website.json000066400000000000000000000011031523703711300250230ustar00rootroot00000000000000[{"archived": false, "name": "Sempry website", "tags": "client,web", "favorite": false, "num_files": 0, "managed_by": {"username": "alan", "role": "Project manager", "email_address": "alan@teampasswordmanager.com", "id": 6, "name": "Alan Hall"}, "updated_on": "2016-09-07 04:41:44", "id": 15}, {"archived": false, "name": "Website development", "tags": "client,web", "favorite": true, "num_files": 0, "managed_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "id": 4}]peshay-tpm-d71ce81/tests/resources/users.json000066400000000000000000000037671523703711300214460ustar00rootroot00000000000000[{"username": "alan", "name": "Alan Hall", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "alan@teampasswordmanager.com", "id": "6"}, {"username": "claire", "name": "Claire Wood", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "claire@teampasswordmanager.com", "id": "3"}, {"username": "frank", "name": "Frank Steel", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "frank@teampasswordmanager.com", "id": "2"}, {"username": "jake", "name": "Jake Brown", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Read only", "valid_hash": true, "is_2fa_enabled": false, "email_address": "jake@externalorg.com", "id": "9"}, {"username": "janine", "name": "Janine Black", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "janine@teampasswordmanager.com", "id": "7"}, {"username": "john", "name": "John Boss", "is_active": true, "num_groups": 0, "is_ldap": false, "role": "Admin", "valid_hash": true, "is_2fa_enabled": false, "email_address": "john@teampasswordmanager.com", "id": "1"}, {"username": "lucas", "name": "Lucas Cross", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "lucas@teampasswordmanager.com", "id": "5"}, {"username": "tom", "name": "Tom Landy", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "tom@teampasswordmanager.com", "id": "8"}, {"username": "zoe", "name": "Zoe Timpelton", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "zoe@teampasswordmanager.com", "id": "4"}]peshay-tpm-d71ce81/tests/resources/users/000077500000000000000000000000001523703711300205365ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/users/1.json000066400000000000000000000012121523703711300215650ustar00rootroot00000000000000{"username": "john", "login_dn": "", "last_login": "2017-06-02 07:20:00", "name": "John Boss", "last_api_request": "2017-06-02 13:20:28", "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:42", "created_on": "2016-09-07 04:41:42", "is_ldap": false, "role": "Admin", "groups": null, "valid_hash": true, "is_2fa_enabled": false, "email_address": "john@teampasswordmanager.com", "id": "1", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/2.json000066400000000000000000000012151523703711300215710ustar00rootroot00000000000000{"username": "frank", "login_dn": "", "last_login": null, "name": "Frank Steel", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:43", "created_on": "2016-09-07 04:41:43", "is_ldap": false, "role": "Normal user", "groups": [{"id": 1, "name": "Web work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "frank@teampasswordmanager.com", "id": "2", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/3.json000066400000000000000000000012231523703711300215710ustar00rootroot00000000000000{"username": "claire", "login_dn": "", "last_login": null, "name": "Claire Wood", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:43", "created_on": "2016-09-07 04:41:43", "is_ldap": false, "role": "Project manager", "groups": [{"id": 1, "name": "Web work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "claire@teampasswordmanager.com", "id": "3", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/4.json000066400000000000000000000012131523703711300215710ustar00rootroot00000000000000{"username": "zoe", "login_dn": "", "last_login": null, "name": "Zoe Timpelton", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:43", "created_on": "2016-09-07 04:41:43", "is_ldap": false, "role": "Normal user", "groups": [{"id": 1, "name": "Web work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "zoe@teampasswordmanager.com", "id": "4", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/4/000077500000000000000000000000001523703711300207015ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/users/4/passwords.json000066400000000000000000000005271523703711300236250ustar00rootroot00000000000000[{"id": 4, "name": "facebook", "project": {"id": 2, "name": "Internal"}, "access_info": "https://www.facebook.com/", "username": "johnny", "updated_on": "2017-06-02 07:35:26"}, {"id": 5, "name": "firewall", "project": {"id": 3, "name": "Network"}, "access_info": "https://10.0.0.1/", "username": "admin", "updated_on": "2017-06-02 07:36:00"}] peshay-tpm-d71ce81/tests/resources/users/4/projects.json000066400000000000000000000003321523703711300234230ustar00rootroot00000000000000[{"id": 2, "name": "Internal", "parent_id": 0, "tags": "", "notes": "", "updated_on": "2016-09-07 04:41:43"}, {"id": 3, "name": "Network", "parent_id": 0, "tags": "", "notes": "", "updated_on": "2016-09-07 04:42:10"}] peshay-tpm-d71ce81/tests/resources/users/5.json000066400000000000000000000012151523703711300215740ustar00rootroot00000000000000{"username": "lucas", "login_dn": "", "last_login": null, "name": "Lucas Cross", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:43", "created_on": "2016-09-07 04:41:43", "is_ldap": false, "role": "Normal user", "groups": [{"id": 1, "name": "Web work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "lucas@teampasswordmanager.com", "id": "5", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/6.json000066400000000000000000000012141523703711300215740ustar00rootroot00000000000000{"username": "alan", "login_dn": "", "last_login": null, "name": "Alan Hall", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:43", "created_on": "2016-09-07 04:41:43", "is_ldap": false, "role": "Project manager", "groups": [{"id": 2, "name": "IT work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "alan@teampasswordmanager.com", "id": "6", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/7.json000066400000000000000000000012171523703711300216000ustar00rootroot00000000000000{"username": "janine", "login_dn": "", "last_login": null, "name": "Janine Black", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "created_on": "2016-09-07 04:41:44", "is_ldap": false, "role": "Normal user", "groups": [{"id": 2, "name": "IT work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "janine@teampasswordmanager.com", "id": "7", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/8.json000066400000000000000000000012061523703711300215770ustar00rootroot00000000000000{"username": "tom", "login_dn": "", "last_login": null, "name": "Tom Landy", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "created_on": "2016-09-07 04:41:44", "is_ldap": false, "role": "Normal user", "groups": [{"id": 2, "name": "IT work"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "tom@teampasswordmanager.com", "id": "8", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/9.json000066400000000000000000000012061523703711300216000ustar00rootroot00000000000000{"username": "jake", "login_dn": "", "last_login": null, "name": "Jake Brown", "last_api_request": null, "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:44", "created_on": "2016-09-07 04:41:44", "is_ldap": false, "role": "Read only", "groups": [{"id": 3, "name": "External users"}], "valid_hash": true, "is_2fa_enabled": false, "email_address": "jake@externalorg.com", "id": "9", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users/me.json000066400000000000000000000012121523703711300220260ustar00rootroot00000000000000{"username": "john", "login_dn": "", "last_login": "2017-06-02 07:20:00", "name": "John Boss", "last_api_request": "2017-06-02 13:20:30", "is_active": true, "created_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}, "updated_on": "2016-09-07 04:41:42", "created_on": "2016-09-07 04:41:42", "is_ldap": false, "role": "Admin", "groups": null, "valid_hash": true, "is_2fa_enabled": false, "email_address": "john@teampasswordmanager.com", "id": "1", "updated_by": {"username": "john", "role": "Admin", "email_address": "john@teampasswordmanager.com", "id": 1, "name": "John Boss"}}peshay-tpm-d71ce81/tests/resources/users_ldap.json000066400000000000000000000037671523703711300224460ustar00rootroot00000000000000[{"username": "alan", "name": "Alan Hall", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "alan@teampasswordmanager.com", "id": "6"}, {"username": "claire", "name": "Claire Wood", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "claire@teampasswordmanager.com", "id": "3"}, {"username": "frank", "name": "Frank Steel", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "frank@teampasswordmanager.com", "id": "2"}, {"username": "jake", "name": "Jake Brown", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Read only", "valid_hash": true, "is_2fa_enabled": false, "email_address": "jake@externalorg.com", "id": "9"}, {"username": "janine", "name": "Janine Black", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "janine@teampasswordmanager.com", "id": "7"}, {"username": "john", "name": "John Boss", "is_active": true, "num_groups": 0, "is_ldap": false, "role": "Admin", "valid_hash": true, "is_2fa_enabled": false, "email_address": "john@teampasswordmanager.com", "id": "1"}, {"username": "lucas", "name": "Lucas Cross", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "lucas@teampasswordmanager.com", "id": "5"}, {"username": "tom", "name": "Tom Landy", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "tom@teampasswordmanager.com", "id": "8"}, {"username": "zoe", "name": "Zoe Timpelton", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "zoe@teampasswordmanager.com", "id": "4"}]peshay-tpm-d71ce81/tests/resources/users_saml.json000066400000000000000000000037671523703711300224620ustar00rootroot00000000000000[{"username": "alan", "name": "Alan Hall", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "alan@teampasswordmanager.com", "id": "6"}, {"username": "claire", "name": "Claire Wood", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Project manager", "valid_hash": true, "is_2fa_enabled": false, "email_address": "claire@teampasswordmanager.com", "id": "3"}, {"username": "frank", "name": "Frank Steel", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "frank@teampasswordmanager.com", "id": "2"}, {"username": "jake", "name": "Jake Brown", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Read only", "valid_hash": true, "is_2fa_enabled": false, "email_address": "jake@externalorg.com", "id": "9"}, {"username": "janine", "name": "Janine Black", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "janine@teampasswordmanager.com", "id": "7"}, {"username": "john", "name": "John Boss", "is_active": true, "num_groups": 0, "is_ldap": false, "role": "Admin", "valid_hash": true, "is_2fa_enabled": false, "email_address": "john@teampasswordmanager.com", "id": "1"}, {"username": "lucas", "name": "Lucas Cross", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "lucas@teampasswordmanager.com", "id": "5"}, {"username": "tom", "name": "Tom Landy", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "tom@teampasswordmanager.com", "id": "8"}, {"username": "zoe", "name": "Zoe Timpelton", "is_active": true, "num_groups": 1, "is_ldap": false, "role": "Normal user", "valid_hash": true, "is_2fa_enabled": false, "email_address": "zoe@teampasswordmanager.com", "id": "4"}]peshay-tpm-d71ce81/tests/resources/version.json000066400000000000000000000001111523703711300217460ustar00rootroot00000000000000{"version": "7.73.146", "version_date": "2017-01-20", "api_version": "4"}peshay-tpm-d71ce81/tests/resources/version/000077500000000000000000000000001523703711300210625ustar00rootroot00000000000000peshay-tpm-d71ce81/tests/resources/version/check_latest.json000066400000000000000000000001471523703711300244100ustar00rootroot00000000000000{"latest_version": "7.73.146", "version": "7.73.146", "version_date": "2017-01-20", "api_version": "4"}peshay-tpm-d71ce81/tests/resources/version/check_outdated.json000066400000000000000000000001501523703711300247170ustar00rootroot00000000000000{"latest_version": "7.73.146", "version": "6.68.138", "version_date": "2017-01-20", "api_version": "4"} peshay-tpm-d71ce81/tests/test_public_artifacts.py000066400000000000000000000041571523703711300223210ustar00rootroot00000000000000"""Tests for the public artifact hygiene guard.""" import subprocess import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from tools.check_public_artifacts import check_text, git_files def assert_clean(text): assert check_text("artifact.md", text, ".md") == [] def assert_blocks(text, expected): findings = check_text("artifact.md", text, ".md") assert findings assert any(expected in finding for finding in findings) def test_clean_public_artifact_passes(): assert_clean("Use EXAMPLE_PASSWORD and environment variables in docs.\n") def test_literal_escaped_newline_is_blocked(): assert_blocks("first" + "\\\\n" + "second\n", "literal escaped newline") def test_local_path_is_blocked(): assert_blocks("trace: " + "/home/" + "alice/project/file.txt\n", "local home path") def test_internal_workflow_terms_are_blocked(): assert_blocks("Generated by " + "Open" + "Claw" + " automation.\n", "internal automation marker") def test_secret_assignment_is_blocked(): value = "a" * 32 assert_blocks("private_key = '" + value + "'\n", "secret-looking assignment") def test_placeholder_secret_assignment_passes(): assert_clean("private_key = 'EXAMPLE_PRIVATE_KEY'\n") def test_git_files_lists_tracked_files_and_drops_blank_lines(monkeypatch): def fake_run(cmd, **kwargs): assert cmd == ["git", "ls-files"] assert kwargs["capture_output"] is True assert kwargs["text"] is True return subprocess.CompletedProcess(cmd, 0, stdout="tpm.py\n\nREADME.md\n", stderr="") monkeypatch.setattr(subprocess, "run", fake_run) assert git_files() == ["tpm.py", "README.md"] def test_git_files_is_empty_when_git_exits_nonzero(monkeypatch): def fake_run(cmd, **kwargs): raise subprocess.CalledProcessError(128, cmd) monkeypatch.setattr(subprocess, "run", fake_run) assert git_files() == [] def test_git_files_is_empty_when_git_is_unavailable(monkeypatch): def fake_run(cmd, **kwargs): raise OSError("git not found") monkeypatch.setattr(subprocess, "run", fake_run) assert git_files() == [] peshay-tpm-d71ce81/tests/test_tpm_v4.py000066400000000000000000001364371523703711300202230ustar00rootroot00000000000000import hashlib import hmac import json import logging import os.path import time import unittest import requests_mock import tpm log = logging.getLogger(__name__) api_url = 'https://tpm.example.com/index.php/api/v4/' local_path = 'tests/resources/' item_limit = 20 def fake_data(url, m, altpath=False): """ A stub urlopen() implementation that load json responses from the filesystem. """ # Map path from url to a file path_parts = url.split('/')[6:] if not altpath: path = '/'.join(path_parts) else: path = altpath resource_file = os.path.normpath(f'tests/resources/{path}') with open(resource_file, 'r') as data_file: data_txt = data_file.read() try: data = json.loads(data_txt) except ValueError: # Issue #14: serve non-JSON content as-is so tpm raises the error # through its own request handling, instead of the test helper # choking on json.loads. clean_url = url.replace(" ", "+") m.get(clean_url, text=data_txt) m.post(clean_url, text=data_txt) m.put(clean_url, text=data_txt) return data_len = len(data) log.debug(f'Data length: {data_len}') # Must return a json-like object header = {} count = 0 while True: count += 1 if data_len > item_limit and isinstance(data,list): returndata = data[:item_limit] returndata_txt = json.dumps(returndata) data = data[item_limit:] data_txt = json.dumps(data) pageingurl = url.replace('.json', f'/page/{count}.json') log.debug(f"Registering URL: {pageingurl}") log.debug(f"Registering data: {returndata_txt}") log.debug(f"Data length: {len(returndata)}") log.debug(f"Registering header: {header}") m.get(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) header = { 'link': f'{pageingurl}; rel="next"'} data_len = len(data) else: log.debug(f"Registering URL: {url}") log.debug(f"Registering data: {data_txt}") log.debug(f"Registering header: {header}") m.get(url.replace(" ", "+"), text=data_txt, headers=header.copy()) header.clear() break class ClientProjectTestCase(unittest.TestCase): """Test cases for all project related queries.""" client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') # get all retrievable sample data path_to_mock = 'projects.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Projects Projects = client.list_projects() def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_function_list_projects(self): """Test function list_projects.""" path_to_mock = 'projects.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_archived(self): """Test function list_projects_archived.""" path_to_mock = 'projects/archived.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_archived() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_favorite(self): """Test function list_projects_favorite.""" path_to_mock = 'projects/favorite.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_favorite() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_search(self): """Test function list_projects_search.""" searches = ['company', 'internal', 'website', 'search with spaces'] for search in searches: path_to_mock = f'projects/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_project(self): """Test function show_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_passwords_of_project(self): """Test function list_passwords_of_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords_of_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_user_access_on_project(self): """Test function list_user_access_on_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/security.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_access_on_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_project(self): """Test function create_project.""" path_to_mock = 'projects.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_project(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_project(self): """Test function update_project.""" path_to_mock = 'projects/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_project('4', update_data) self.assertEqual(response, None) def test_function_change_parent_of_project(self): """Test function change_parent_of_project.""" path_to_mock = 'projects/4/change_parent.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.change_parent_of_project('4', '5') self.assertEqual(response, None) def test_function_update_security_of_project(self): """Test function update_security_of_project.""" path_to_mock = 'projects/4/security.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_security_of_project('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_archive_project(self): """Test function archive_project.""" path_to_mock = 'projects/4/archive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.archive_project('4') self.assertEqual(response, None) def test_function_delete_project(self): """Test function delete_project.""" path_to_mock = 'projects/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_project('4') self.assertEqual(response, None) def test_function_unarchive_project(self): """Test function unarchive_project.""" path_to_mock = 'projects/4/unarchive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.unarchive_project('4') self.assertEqual(response, None) def test_function_list_subprojects(self): """Test function list_subprojects.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/subprojects.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_subprojects(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_subprojects_action_new_pwd(self): """Test function list_subprojects_action_new_pwd.""" action = 'new_pwd' for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/subprojects/{action}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_subprojects_action(project_id, action) # number of passwords as from original json file. self.assertEqual(data, response) class ClientPasswordTestCase(unittest.TestCase): """Test cases for all password related queries.""" client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'passwords.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Passwords Passwords = client.list_passwords() def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_function_list_passwords(self): """Test function list_passwords.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_archived(self): """Test function list_passwords_archived.""" path_to_mock = 'passwords/archived.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords_archived(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_favorite(self): """Test function list_passwords_favorite.""" path_to_mock = 'passwords/favorite.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords_favorite(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_search(self): """Test function list_passwords_search.""" searches = ['backup', 'dns', 'facebook', 'firewall', 'reddit', 'test', 'search with spaces'] for search in searches: path_to_mock = f'passwords/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_password(self): """Test function show_password.""" for password in Passwords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'passwords/{password_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_password(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_user_access_on_password(self): """Test function list_user_access_on_password.""" for password in Passwords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'passwords/{password_id}/security.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_access_on_password(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_password(self): """Test function create_password.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_password(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_password(self): """Test function update_password.""" path_to_mock = 'passwords/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_password('4', update_data) self.assertEqual(response, None) def test_function_update_security_of_password(self): """Test function update_security_of_password.""" path_to_mock = 'passwords/4/security.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_security_of_password('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_update_custom_fields_of_password(self): """Test function update_custom_fields_of_password.""" path_to_mock = 'passwords/4/custom_fields.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_custom_fields_of_password('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_delete_password(self): """Test function delete_password.""" path_to_mock = 'passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_password('4') self.assertEqual(response, None) def test_function_lock_password(self): """Test function lock_password.""" path_to_mock = 'passwords/4/lock.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.lock_password('4') self.assertEqual(response, None) def test_function_unlock_password(self): """Test function unlock_password.""" path_to_mock = 'passwords/4/unlock.json' request_url = api_url + path_to_mock unlock_reason = 'because I can' with requests_mock.Mocker() as m: m.put(request_url, status_code=204, request_headers={'X-Unlock-Reason': unlock_reason}) response = self.client.unlock_password('4', unlock_reason) self.assertEqual(response, None) class ClientMyPasswordTestCase(unittest.TestCase): """Test cases for all mypassword related queries.""" client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global MyPasswords MyPasswords = client.list_mypasswords() def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_function_list_mypasswords(self): """Test function list_mypasswords.""" path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_mypasswords_search(self): """Test function list_mypasswords_search.""" searches = ['amazon', 'backup', 'facebook', 'john', 'jonny'] for search in searches: path_to_mock = f'my_passwords/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_mypassword(self): """Test function show_mypassword.""" for password in MyPasswords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'my_passwords/{password_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_mypassword(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_mypassword(self): """Test function create_mypassword.""" path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_mypassword(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_mypassword(self): """Test function update_mypassword.""" path_to_mock = 'my_passwords/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_mypassword('4', update_data) self.assertEqual(response, None) def test_function_delete_mypassword(self): """Test function delete_mypassword.""" path_to_mock = 'my_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_mypassword('4') self.assertEqual(response, None) def test_function_set_favorite_password(self): """Test function set_favorite_password.""" path_to_mock = 'favorite_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_password('4') self.assertEqual(response, None) def test_function_unset_favorite_password(self): """Test function unset_favorite_password.""" path_to_mock = 'favorite_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_password('4') self.assertEqual(response, None) def test_function_set_favorite_project(self): """Test function set_favorite_project.""" path_to_mock = 'favorite_project/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_project('4') self.assertEqual(response, None) def test_function_unset_favorite_project(self): """Test function unset_favorite_project.""" path_to_mock = 'favorite_project/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_project('4') self.assertEqual(response, None) class ClientUsersTestCase(unittest.TestCase): """Test cases for all user related queries.""" client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'users.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Users Users = client.list_users() def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_function_list_users(self): """Test function list_users.""" path_to_mock = 'users.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_users() self.assertEqual(data, response) def test_function_show_user(self): """Test function show_user.""" for user in Users: user_id = user.get('id') log.debug(f"Testing with Project ID: {user_id}") path_to_mock = f'users/{user_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_user(user_id) self.assertEqual(data, response) def test_function_show_me(self): """Test function show_me.""" path_to_mock = 'users/me.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_me() response2 = self.client.who_am_i() self.assertEqual(data, response) self.assertEqual(response2, response) def test_function_create_user(self): """Test function create_user.""" path_to_mock = 'users.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_user(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_user(self): """Test function update_user.""" path_to_mock = 'users/4.json' request_url = api_url + path_to_mock update_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_user('4', update_data) self.assertEqual(response, None) def test_function_change_user_password(self): """Test function change_user_password.""" path_to_mock = 'users/4/change_password.json' request_url = api_url + path_to_mock update_data = { "password": "NewSecret"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.change_user_password('4', update_data) self.assertEqual(response, None) def test_function_activate_user(self): """Test function activate_user.""" path_to_mock = 'users/4/activate.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.activate_user('4') self.assertEqual(response, None) def test_function_deactivate_user(self): """Test function deactivate_user.""" path_to_mock = 'users/4/deactivate.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.deactivate_user('4') self.assertEqual(response, None) def test_function_convert_user_to_ldap(self): """Test function convert_user_to_ldap.""" path_to_mock = 'users/4/convert_to_ldap.json' request_url = api_url + path_to_mock login_dn = 'CN=Jane,CN=Users,DC=tpm,DC=local' def match_request_text(request): return {"login_dn": login_dn} with requests_mock.Mocker() as m: m.put(request_url, status_code=204, additional_matcher=match_request_text) response = self.client.convert_user_to_ldap('4', login_dn) self.assertEqual(response, None) def test_function_convert_ldap_user_to_normal(self): """Test function convert_ldap_user_to_normal.""" path_to_mock = 'users/4/convert_to_normal.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.convert_ldap_user_to_normal('4') self.assertEqual(response, None) def test_function_delete_user(self): """Test function delete_user.""" path_to_mock = 'users/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_user('4') self.assertEqual(response, None) class ClientGroupsTestCase(unittest.TestCase): """Test cases for all group related queries.""" client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'groups.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Groups Groups = client.list_groups() def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_function_list_groups(self): """Test function list_groups.""" path_to_mock = 'groups.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_groups() self.assertEqual(data, response) def test_function_show_group(self): """Test function show_group.""" for group in Groups: group_id = group.get('id') log.debug(f"Testing with Project ID: {group_id}") path_to_mock = f'groups/{group_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_group(group_id) self.assertEqual(data, response) def test_function_create_group(self): """Test function create_group.""" path_to_mock = 'groups.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "somegroup"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_group(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_group(self): """Test function update_group.""" path_to_mock = 'groups/4.json' request_url = api_url + path_to_mock update_data = { "name": "somegroup"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_group('4', update_data) self.assertEqual(response, None) def test_function_add_user_to_group(self): """Test function add_user_to_group.""" group_id = '3' user_id = '4' path_to_mock = f'groups/{group_id}/add_user/{user_id}.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.add_user_to_group(group_id, user_id) self.assertEqual(response, None) def test_function_delete_user_from_group(self): """Test function delete_user_from_group.""" group_id = '3' user_id = '4' path_to_mock = f'groups/{group_id}/delete_user/{user_id}.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.delete_user_from_group(group_id, user_id) self.assertEqual(response, None) def test_function_delete_group(self): """Test function delete_group.""" path_to_mock = 'groups/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_group('4') self.assertEqual(response, None) class GeneralClientTestCases(unittest.TestCase): """general test cases for client queries.""" def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_paging(self): """Test paging, if number of items is same as from original data source.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords() # number of passwords as from original json file. source_items = len(data) paging_count = round((source_items / 20) + 0.5) response_items = len(response) log.debug(f"Paging should be {paging_count}") log.debug(f"Paged {m.call_count} times") log.debug(f"Source Items: {source_items}; Response Items: {response_items}") self.assertEqual(paging_count, m.call_count) self.assertEqual(source_items, response_items) def test_provide_unlock_reason(self): """Test providing an unlock reason.""" path_to_mock = 'passwords/14.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: json.load(data_file) unlock_reason = 'because I can' client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS', unlock_reason=unlock_reason) with requests_mock.Mocker() as m: m.get(request_url, request_headers={'X-Unlock-Reason': unlock_reason}) client.show_password('14') history = m.request_history request_unlock_reason = history[0].headers.get('X-Unlock-Reason') self.assertEqual(request_unlock_reason, unlock_reason) def test_key_authentciation(self): """Test Key authentication header.""" private_key='private_secret' public_key='public_secret' client = tpm.TpmApiv4('https://tpm.example.com', private_key=private_key, public_key=public_key) path_to_mock = 'version.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) client.get_version() history = m.request_history request_hash = history[0].headers.get('X-Request-Hash') history[0].headers.get('X-Public-Key') request_timestamp = history[0].headers.get('X-Request-Timestamp') str(int(time.time())) unhashed = 'api/v4/' + path_to_mock + request_timestamp hashed = hmac.new(str.encode(private_key), msg=unhashed.encode('utf-8'), digestmod=hashlib.sha256).hexdigest() self.assertEqual(request_hash, hashed) def test_function_generate_password(self): """Test function generate_password.""" path_to_mock = 'generate_password.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.generate_password() self.assertEqual(data, response) def test_get_version(self): """Test function get_version.""" path_to_mock = 'version.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.get_version() self.assertEqual(data, response) def test_a_call_with_v3(self): """Test function get_version with v3 API.""" path_to_mock = 'version.json' request_url = 'https://tpm.example.com/index.php/api/v3/' + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) client = tpm.TpmApiv3('https://tpm.example.com', username='USER', password='PASS') with requests_mock.Mocker() as m: fake_data(request_url, m) response = client.get_version() self.assertEqual(data, response) def test_function_check_latest(self): """Test function generate_password.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.get_latest_version() self.assertEqual(data, response) def test_function_up_to_date_true(self): """Test function up_to_date is true.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response_up_to_date_true = self.client.up_to_date() self.assertTrue(response_up_to_date_true) def test_function_up_to_date_false(self): """Test function up_to_date is false.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m, 'version/check_outdated.json') response_up_to_date_false = self.client.up_to_date() self.assertFalse(response_up_to_date_false) class ExceptionTestCases(unittest.TestCase): """Test case for Config Exceptions.""" def test_wrong_auth_exception1(self): """Exception if wrong authentication mehtod with username but private_key.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv4('https://tpm.example.com', username='USER', private_key='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception2(self): """Exception if wrong authentication mehtod with public key but password.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv4('https://tpm.example.com', public_key='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception3(self): """Exception if wrong authentication mehtod with username but public_key.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv4('https://tpm.example.com', username='USER', public_key='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception4(self): """Exception if wrong authentication mehtod with private key but password.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv4('https://tpm.example.com', private_key='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_url_exception(self): """Exception if URL does not match REGEXurl.""" wrong_url = 'ftp://tpm.example.com' with self.assertRaises(tpm.TpmApiv4.ConfigError) as context: tpm.TpmApiv4(wrong_url, username='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual(f"'Invalid URL: {wrong_url}'", str(context.exception)) class ExceptionOnRequestsTestCases(unittest.TestCase): """Test case for Request based Exceptions.""" def setUp(self): self.client = tpm.TpmApiv4('https://tpm.example.com', username='USER', password='PASS') def test_connection_exception(self): """Exception if connection fails.""" exception_error = "Connection error for " with self.assertRaises(tpm.TPMException) as context: self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_value_error_exception(self): """Exception if value is not json format.""" path_to_mock = 'passwords/value_error.json' request_url = api_url + path_to_mock exception_error = "No JSON object could be decoded: " exception_error3 = "Expecting value: line 1 column 1 (char 0): " resource_file = os.path.normpath(f'tests/resources/{path_to_mock}') # str() of the open handle is deliberately not valid JSON, which is # what makes the response body fail to decode at position 0. with open(resource_file) as data, \ self.assertRaises(ValueError) as context, \ requests_mock.Mocker() as m: m.get(request_url, text=str(data)) self.client.show_password('value_error') log.debug(f"context exception: {context.exception}") self.assertTrue(str(context.exception).startswith(exception_error) or str(context.exception).startswith(exception_error3)) def test_exception_on_error_in_result(self): """Exception if "error" found in result.""" exception_error = 'something bad happened' error_json={'error': 'not good', 'message': exception_error} path_to_mock = 'passwords/json_error.json' request_url = api_url + path_to_mock with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, json=error_json) self.client.show_password('json_error') log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_403(self): """Exception if 403 forbidden.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} forbidden" with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, text='forbidden', status_code=403) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_404(self): """Exception if 404 not found.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} not found" with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, text='not found', status_code=404) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_405(self): """Exception if 405 Method Not Allowed.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} Method Not Allowed" with self.assertRaises(ValueError) as context, requests_mock.Mocker() as m: m.get(request_url, text='Method Not Allowed', status_code=405) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(str(context.exception).endswith(exception_error)) peshay-tpm-d71ce81/tests/test_tpm_v5.py000066400000000000000000001605711523703711300202200ustar00rootroot00000000000000import hashlib import hmac import json import logging import os.path import time import unittest import requests_mock import tpm log = logging.getLogger(__name__) api_url = 'https://tpm.example.com/index.php/api/v5/' local_path = 'tests/resources/' item_limit = 20 def fake_data(url, m, altpath=False): """ A stub urlopen() implementation that load json responses from the filesystem. """ # Map path from url to a file path_parts = url.split('/')[6:] if not altpath: path = '/'.join(path_parts) else: path = altpath resource_file = os.path.normpath(f'tests/resources/{path}') with open(resource_file, 'r') as data_file: data_txt = data_file.read() try: data = json.loads(data_txt) except ValueError: # Issue #14: serve non-JSON content as-is so tpm raises the error # through its own request handling, instead of the test helper # choking on json.loads. clean_url = url.replace(" ", "+") m.get(clean_url, text=data_txt) m.post(clean_url, text=data_txt) m.put(clean_url, text=data_txt) return data_len = len(data) log.debug(f'Data length: {data_len}') # Must return a json-like object header = {} count = 0 while True: count += 1 if data_len > item_limit and isinstance(data,list): returndata = data[:item_limit] returndata_txt = json.dumps(returndata) data = data[item_limit:] data_txt = json.dumps(data) pageingurl = url.replace('.json', f'/page/{count}.json') log.debug(f"Registering URL: {pageingurl}") log.debug(f"Registering data: {returndata_txt}") log.debug(f"Data length: {len(returndata)}") log.debug(f"Registering header: {header}") m.get(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) m.post(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) m.put(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) header = { 'link': f'{pageingurl}; rel="next"'} data_len = len(data) else: log.debug(f"Registering URL: {url}") log.debug(f"Registering data: {data_txt}") log.debug(f"Registering header: {header}") m.get(url.replace(" ", "+"), text=data_txt, headers=header.copy()) m.post(url.replace(" ", "+"), text=data_txt, headers=header.copy()) m.put(url.replace(" ", "+"), text=data_txt, headers=header.copy()) header.clear() break class ClientProjectTestCase(unittest.TestCase): """Test cases for all project related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') # get all retrievable sample data path_to_mock = 'projects.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Projects Projects = client.list_projects() def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_projects(self): """Test function list_projects.""" path_to_mock = 'projects.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_archived(self): """Test function list_projects_archived.""" path_to_mock = 'projects/archived.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_archived() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_favorite(self): """Test function list_projects_favorite.""" path_to_mock = 'projects/favorite.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_favorite() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_projects_search(self): """Test function list_projects_search.""" searches = ['company', 'internal', 'website', 'search with spaces'] for search in searches: path_to_mock = f'projects/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_projects_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_project(self): """Test function show_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_passwords_of_project(self): """Test function list_passwords_of_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords_of_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_user_access_on_project(self): """Test function list_user_access_on_project.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/security.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_access_on_project(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_project(self): """Test function create_project.""" path_to_mock = 'projects.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_project(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_project(self): """Test function update_project.""" path_to_mock = 'projects/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_project('4', update_data) self.assertEqual(response, None) def test_function_change_parent_of_project(self): """Test function change_parent_of_project.""" path_to_mock = 'projects/4/change_parent.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.change_parent_of_project('4', '5') self.assertEqual(response, None) def test_function_update_security_of_project(self): """Test function update_security_of_project.""" path_to_mock = 'projects/4/security.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_security_of_project('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_archive_project(self): """Test function archive_project.""" path_to_mock = 'projects/4/archive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.archive_project('4') self.assertEqual(response, None) def test_function_delete_project(self): """Test function delete_project.""" path_to_mock = 'projects/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_project('4') self.assertEqual(response, None) def test_function_unarchive_project(self): """Test function unarchive_project.""" path_to_mock = 'projects/4/unarchive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.unarchive_project('4') self.assertEqual(response, None) def test_function_list_subprojects(self): """Test function list_subprojects.""" for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/subprojects.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_subprojects(project_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_subprojects_action_new_pwd(self): """Test function list_subprojects_action_new_pwd.""" action = 'new_pwd' for project in Projects: project_id = project.get('id') log.debug(f"Testing with Project ID: {project_id}") path_to_mock = f'projects/{project_id}/subprojects/{action}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_subprojects_action(project_id, action) # number of passwords as from original json file. self.assertEqual(data, response) class ClientPasswordTestCase(unittest.TestCase): """Test cases for all password related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'passwords.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Passwords Passwords = client.list_passwords() def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_passwords(self): """Test function list_passwords.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_archived(self): """Test function list_passwords_archived.""" path_to_mock = 'passwords/archived.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords_archived(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_favorite(self): """Test function list_passwords_favorite.""" path_to_mock = 'passwords/favorite.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = sorted(json.load(data_file), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(self.client.list_passwords_favorite(), key=lambda k: k['id']) self.assertEqual(data, response) def test_function_list_passwords_search(self): """Test function list_passwords_search.""" searches = ['backup', 'dns', 'facebook', 'firewall', 'reddit', 'test', 'search with spaces'] for search in searches: path_to_mock = f'passwords/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_password(self): """Test function show_password.""" for password in Passwords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'passwords/{password_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_password(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_user_access_on_password(self): """Test function list_user_access_on_password.""" for password in Passwords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'passwords/{password_id}/security.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_access_on_password(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_password(self): """Test function create_password.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_password(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_password(self): """Test function update_password.""" path_to_mock = 'passwords/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_password('4', update_data) self.assertEqual(response, None) def test_function_update_security_of_password(self): """Test function update_security_of_password.""" path_to_mock = 'passwords/4/security.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_security_of_password('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_update_custom_fields_of_password(self): """Test function update_custom_fields_of_password.""" path_to_mock = 'passwords/4/custom_fields.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_custom_fields_of_password('4', {'name': 'setdata'}) self.assertEqual(response, None) def test_function_delete_password(self): """Test function delete_password.""" path_to_mock = 'passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_password('4') self.assertEqual(response, None) def test_function_lock_password(self): """Test function lock_password.""" path_to_mock = 'passwords/4/lock.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.lock_password('4') self.assertEqual(response, None) def test_function_unlock_password(self): """Test function unlock_password.""" path_to_mock = 'passwords/4/unlock.json' request_url = api_url + path_to_mock unlock_reason = 'because I can' with requests_mock.Mocker() as m: m.put(request_url, status_code=204, request_headers={'X-Unlock-Reason': unlock_reason}) response = self.client.unlock_password('4', unlock_reason) self.assertEqual(response, None) def test_function_archive_password(self): """Test function archive_password.""" path_to_mock = 'passwords/4/archive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.archive_password('4') self.assertEqual(response, None) def test_function_unarchive_password(self): """Test function unarchive_password.""" path_to_mock = 'passwords/4/unarchive.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.unarchive_password('4') self.assertEqual(response, None) def test_function_move_password(self): """Test function move_password.""" path_to_mock = 'passwords/4/move.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.move_password('4', '5') self.assertEqual(response, None) class ClientMyPasswordTestCase(unittest.TestCase): """Test cases for all mypassword related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global MyPasswords MyPasswords = client.list_mypasswords() def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_mypasswords(self): """Test function list_mypasswords.""" path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords() # number of passwords as from original json file. self.assertEqual(data, response) def test_function_list_mypasswords_search(self): """Test function list_mypasswords_search.""" searches = ['amazon', 'backup', 'facebook', 'john', 'jonny'] for search in searches: path_to_mock = f'my_passwords/search/{search}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords_search(search) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_show_mypassword(self): """Test function show_mypassword.""" for password in MyPasswords: password_id = password.get('id') log.debug(f"Testing with Password ID: {password_id}") path_to_mock = f'my_passwords/{password_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_mypassword(password_id) # number of passwords as from original json file. self.assertEqual(data, response) def test_function_create_mypassword(self): """Test function create_mypassword.""" path_to_mock = 'my_passwords.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_mypassword(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_mypassword(self): """Test function update_mypassword.""" path_to_mock = 'my_passwords/4.json' request_url = api_url + path_to_mock update_data = { "name": "someproject"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_mypassword('4', update_data) self.assertEqual(response, None) def test_function_delete_mypassword(self): """Test function delete_mypassword.""" path_to_mock = 'my_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_mypassword('4') self.assertEqual(response, None) def test_function_set_favorite_password(self): """Test function set_favorite_password.""" path_to_mock = 'favorite_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_password('4') self.assertEqual(response, None) def test_function_unset_favorite_password(self): """Test function unset_favorite_password.""" path_to_mock = 'favorite_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_password('4') self.assertEqual(response, None) def test_function_set_favorite_project(self): """Test function set_favorite_project.""" path_to_mock = 'favorite_project/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_project('4') self.assertEqual(response, None) def test_function_unset_favorite_project(self): """Test function unset_favorite_project.""" path_to_mock = 'favorite_project/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_project('4') self.assertEqual(response, None) def test_function_move_mypassword(self): """Test function move_mypassword.""" path_to_mock = 'my_passwords/4/move.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.move_mypassword('4', '5') self.assertEqual(response, data.get('id')) class ClientUsersTestCase(unittest.TestCase): """Test cases for all user related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'users.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Users Users = client.list_users() def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_users(self): """Test function list_users.""" path_to_mock = 'users.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_users() self.assertEqual(data, response) def test_function_show_user(self): """Test function show_user.""" for user in Users: user_id = user.get('id') log.debug(f"Testing with Project ID: {user_id}") path_to_mock = f'users/{user_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_user(user_id) self.assertEqual(data, response) def test_function_show_me(self): """Test function show_me.""" path_to_mock = 'users/me.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_me() response2 = self.client.who_am_i() self.assertEqual(data, response) self.assertEqual(response2, response) def test_function_create_user(self): """Test function create_user.""" path_to_mock = 'users.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_user(create_data) self.assertEqual(response, return_data.get('id')) def test_function_create_user_ldap(self): """Test function create_user_ldap.""" path_to_mock = 'users_ldap.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_user_ldap(create_data) self.assertEqual(response, return_data.get('id')) def test_function_create_user_saml(self): """Test function create_user_saml.""" path_to_mock = 'users_saml.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_user_saml(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_user(self): """Test function update_user.""" path_to_mock = 'users/4.json' request_url = api_url + path_to_mock update_data = { "name": "someuser"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_user('4', update_data) self.assertEqual(response, None) def test_function_change_user_password(self): """Test function change_user_password.""" path_to_mock = 'users/4/change_password.json' request_url = api_url + path_to_mock update_data = { "password": "NewSecret"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.change_user_password('4', update_data) self.assertEqual(response, None) def test_function_activate_user(self): """Test function activate_user.""" path_to_mock = 'users/4/activate.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.activate_user('4') self.assertEqual(response, None) def test_function_deactivate_user(self): """Test function deactivate_user.""" path_to_mock = 'users/4/deactivate.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.deactivate_user('4') self.assertEqual(response, None) def test_function_convert_user_to_ldap(self): """Test function convert_user_to_ldap.""" path_to_mock = 'users/4/convert_to_ldap.json' request_url = api_url + path_to_mock login_dn = 'CN=Jane,CN=Users,DC=tpm,DC=local' server_id = "1" def match_request_text(request): return {"login_dn": login_dn, "ldap_server_id": server_id} with requests_mock.Mocker() as m: m.put(request_url, status_code=204, additional_matcher=match_request_text) response = self.client.convert_user_to_ldap('4', login_dn, server_id) self.assertEqual(response, None) def test_function_convert_user_to_saml(self): """Test function convert_user_to_saml.""" path_to_mock = 'users/4/convert_to_saml.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.convert_user_to_saml('4') self.assertEqual(response, None) def test_function_convert_ldap_user_to_normal(self): """Test function convert_ldap_user_to_normal.""" path_to_mock = 'users/4/convert_to_normal.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.convert_ldap_user_to_normal('4') self.assertEqual(response, None) def test_function_delete_user(self): """Test function delete_user.""" path_to_mock = 'users/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_user('4') self.assertEqual(response, None) class ClientGroupsTestCase(unittest.TestCase): """Test cases for all group related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'groups.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) global Groups Groups = client.list_groups() def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_groups(self): """Test function list_groups.""" path_to_mock = 'groups.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_groups() self.assertEqual(data, response) def test_function_show_group(self): """Test function show_group.""" for group in Groups: group_id = group.get('id') log.debug(f"Testing with Project ID: {group_id}") path_to_mock = f'groups/{group_id}.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_group(group_id) self.assertEqual(data, response) def test_function_create_group(self): """Test function create_group.""" path_to_mock = 'groups.json' request_url = api_url + path_to_mock return_data = { "id": 4 } create_data = { "name": "somegroup"} with requests_mock.Mocker() as m: m.post(request_url, json=return_data, status_code=200) response = self.client.create_group(create_data) self.assertEqual(response, return_data.get('id')) def test_function_update_group(self): """Test function update_group.""" path_to_mock = 'groups/4.json' request_url = api_url + path_to_mock update_data = { "name": "somegroup"} with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_group('4', update_data) self.assertEqual(response, None) def test_function_add_user_to_group(self): """Test function add_user_to_group.""" group_id = '3' user_id = '4' path_to_mock = f'groups/{group_id}/add_user/{user_id}.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.add_user_to_group(group_id, user_id) self.assertEqual(response, None) def test_function_delete_user_from_group(self): """Test function delete_user_from_group.""" group_id = '3' user_id = '4' path_to_mock = f'groups/{group_id}/delete_user/{user_id}.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.delete_user_from_group(group_id, user_id) self.assertEqual(response, None) def test_function_delete_group(self): """Test function delete_group.""" path_to_mock = 'groups/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_group('4') self.assertEqual(response, None) class GeneralClientTestCases(unittest.TestCase): """general test cases for client queries.""" def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_paging(self): """Test paging, if number of items is same as from original data source.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_passwords() # number of passwords as from original json file. source_items = len(data) paging_count = round((source_items / 20) + 0.5) response_items = len(response) log.debug(f"Paging should be {paging_count}") log.debug(f"Paged {m.call_count} times") log.debug(f"Source Items: {source_items}; Response Items: {response_items}") self.assertEqual(paging_count, m.call_count) self.assertEqual(source_items, response_items) def test_provide_unlock_reason(self): """Test providing an unlock reason.""" path_to_mock = 'passwords/14.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: json.load(data_file) unlock_reason = 'because I can' client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS', unlock_reason=unlock_reason) with requests_mock.Mocker() as m: m.get(request_url, request_headers={'X-Unlock-Reason': unlock_reason}) client.show_password('14') history = m.request_history request_unlock_reason = history[0].headers.get('X-Unlock-Reason') self.assertEqual(request_unlock_reason, unlock_reason) def test_key_authentciation(self): """Test Key authentication header.""" private_key='private_secret' public_key='public_secret' client = tpm.TpmApiv5('https://tpm.example.com', private_key=private_key, public_key=public_key) path_to_mock = 'version.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m) client.get_version() history = m.request_history request_hash = history[0].headers.get('X-Request-Hash') history[0].headers.get('X-Public-Key') request_timestamp = history[0].headers.get('X-Request-Timestamp') str(int(time.time())) unhashed = 'api/v5/' + path_to_mock + request_timestamp hashed = hmac.new(str.encode(private_key), msg=unhashed.encode('utf-8'), digestmod=hashlib.sha256).hexdigest() self.assertEqual(request_hash, hashed) def test_function_generate_password(self): """Test function generate_password.""" path_to_mock = 'generate_password.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.generate_password() self.assertEqual(data, response) def test_get_version(self): """Test function get_version.""" path_to_mock = 'version.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.get_version() self.assertEqual(data, response) def test_a_call_with_v3(self): """Test function get_version with v3 API.""" path_to_mock = 'version.json' request_url = 'https://tpm.example.com/index.php/api/v3/' + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) client = tpm.TpmApiv3('https://tpm.example.com', username='USER', password='PASS') with requests_mock.Mocker() as m: fake_data(request_url, m) response = client.get_version() self.assertEqual(data, response) def test_function_check_latest(self): """Test function generate_password.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.get_latest_version() self.assertEqual(data, response) def test_function_up_to_date_true(self): """Test function up_to_date is true.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response_up_to_date_true = self.client.up_to_date() self.assertTrue(response_up_to_date_true) def test_function_up_to_date_false(self): """Test function up_to_date is false.""" path_to_mock = 'version/check_latest.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: fake_data(request_url, m, 'version/check_outdated.json') response_up_to_date_false = self.client.up_to_date() self.assertFalse(response_up_to_date_false) class ExceptionTestCases(unittest.TestCase): """Test case for Config Exceptions.""" def test_wrong_auth_exception1(self): """Exception if wrong authentication mehtod with username but private_key.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv5('https://tpm.example.com', username='USER', private_key='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception2(self): """Exception if wrong authentication mehtod with public key but password.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv5('https://tpm.example.com', public_key='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception3(self): """Exception if wrong authentication mehtod with username but public_key.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv5('https://tpm.example.com', username='USER', public_key='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_auth_exception4(self): """Exception if wrong authentication mehtod with private key but password.""" with self.assertRaises(tpm.TpmApi.ConfigError) as context: tpm.TpmApiv5('https://tpm.example.com', private_key='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual("'No authentication specified (user/password or private/public key)'", str(context.exception)) def test_wrong_url_exception(self): """Exception if URL does not match REGEXurl.""" wrong_url = 'ftp://tpm.example.com' with self.assertRaises(tpm.TpmApiv5.ConfigError) as context: tpm.TpmApiv5(wrong_url, username='USER', password='PASS') log.debug(f"context exception: {context.exception}") self.assertEqual(f"'Invalid URL: {wrong_url}'", str(context.exception)) class ExceptionOnRequestsTestCases(unittest.TestCase): """Test case for Request based Exceptions.""" def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_connection_exception(self): """Exception if connection fails.""" exception_error = "Connection error for " with self.assertRaises(tpm.TPMException) as context: self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_value_error_exception(self): """Exception if value is not json format.""" path_to_mock = 'passwords/value_error.json' request_url = api_url + path_to_mock exception_error = "No JSON object could be decoded: " exception_error3 = "Expecting value: line 1 column 1 (char 0): " resource_file = os.path.normpath(f'tests/resources/{path_to_mock}') # str() of the open handle is deliberately not valid JSON, which is # what makes the response body fail to decode at position 0. with open(resource_file) as data, \ self.assertRaises(ValueError) as context, \ requests_mock.Mocker() as m: m.get(request_url, text=str(data)) self.client.show_password('value_error') log.debug(f"context exception: {context.exception}") self.assertTrue(str(context.exception).startswith(exception_error) or str(context.exception).startswith(exception_error3)) def test_exception_on_error_in_result(self): """Exception if "error" found in result.""" exception_error = 'something bad happened' error_json={'error': 'not good', 'message': exception_error} path_to_mock = 'passwords/json_error.json' request_url = api_url + path_to_mock with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, json=error_json) self.client.show_password('json_error') log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_403(self): """Exception if 403 forbidden.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} forbidden" with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, text='forbidden', status_code=403) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_404(self): """Exception if 404 not found.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} not found" with self.assertRaises(tpm.TPMException) as context, requests_mock.Mocker() as m: m.get(request_url, text='not found', status_code=404) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(exception_error in str(context.exception)) def test_exception_on_405(self): """Exception if 405 Method Not Allowed.""" path_to_mock = 'passwords.json' request_url = api_url + path_to_mock exception_error = f"{request_url} Method Not Allowed" with self.assertRaises(ValueError) as context, requests_mock.Mocker() as m: m.get(request_url, text='Method Not Allowed', status_code=405) self.client.list_passwords() log.debug(f"context exception: {context.exception}") self.assertTrue(str(context.exception).endswith(exception_error)) class ClientFilesTestCase(unittest.TestCase): """Test cases for all file related queries.""" client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def setUp(self): self.client = tpm.TpmApiv5('https://tpm.example.com', username='USER', password='PASS') def test_function_list_password_files(self): """NEW v5: Test function list_password_files.""" path_to_mock = 'passwords/14/files.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_password_files('14') history = m.request_history log.debug(f"response: {history[0].url}") self.assertEqual(data, response) def test_function_upload_password(self): """NEW v5: Upload a file to password.""" path_to_mock = 'passwords/14/upload.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.upload_password_file('14', request_path, notes="some notes") self.assertEqual(response, data.get('id')) def test_function_list_project_files(self): """NEW v5: Test function list_project_files.""" path_to_mock = 'projects/4/files.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_project_files('4') # file list as from original json file. self.assertEqual(data, response) def test_function_upload_project(self): """NEW v5: Upload a file to project.""" path_to_mock = 'projects/4/upload.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.upload_project_file('4', request_path, notes="some notes") self.assertEqual(response, data.get('id')) def test_function_show_file_info(self): """NEW v5: Show info of a file.""" path_to_mock = 'files/4.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.show_file_info('4') # file list as from original json file. self.assertEqual(data, response) def test_function_update_file_notes(self): """NEW v5: Update notes on a file.""" path_to_mock = 'files/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.put(request_url, status_code=204) response = self.client.update_file_notes('4', "new notes") self.assertEqual(response, None) def test_function_max_upload_file_size(self): """NEW v5: Test function max_upload_file_size.""" path_to_mock = 'files/max_upload_file_size.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.max_upload_file_size() self.assertEqual(data, response) def test_function_uploads_folder_info(self): """NEW v5: Test function uploads_folder_info.""" path_to_mock = 'files/uploads_folder_info.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.uploads_folder_info() self.assertEqual(data, response) def test_function_download_file(self): """NEW v5: Test function download_file.""" path_to_mock = 'files/download/4.json' request_url = api_url + path_to_mock request_path = local_path + path_to_mock resource_file = os.path.normpath(request_path) with open(resource_file) as data_file: data = json.load(data_file) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.download_file("4") self.assertEqual(data, response) def test_function_delete_file(self): """NEW v5: Test function delete_file.""" path_to_mock = 'files/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.delete_file('4') self.assertEqual(response, None)peshay-tpm-d71ce81/tests/test_tpm_v6.py000066400000000000000000000304641523703711300202160ustar00rootroot00000000000000import json import logging import os.path import unittest import requests_mock import tpm log = logging.getLogger(__name__) api_url = 'https://tpm.example.com/index.php/api/v6/' local_path = 'tests/resources/' item_limit = 20 def fake_data(url, m, altpath=False): """ A stub urlopen() implementation that load json responses from the filesystem. """ # Map path from url to a file path_parts = url.split('/')[6:] if not altpath: path = '/'.join(path_parts) else: path = altpath resource_file = os.path.normpath(f'tests/resources/{path}') with open(resource_file, 'r') as data_file: data_txt = data_file.read() try: data = json.loads(data_txt) except ValueError: # Issue #14: serve non-JSON content as-is so tpm raises the error # through its own request handling, instead of the test helper # choking on json.loads. clean_url = url.replace(" ", "+") m.get(clean_url, text=data_txt) m.post(clean_url, text=data_txt) m.put(clean_url, text=data_txt) return data_len = len(data) log.debug(f'Data length: {data_len}') # Must return a json-like object header = {} count = 0 while True: count += 1 if data_len > item_limit and isinstance(data, list): returndata = data[:item_limit] returndata_txt = json.dumps(returndata) data = data[item_limit:] data_txt = json.dumps(data) pageingurl = url.replace('.json', f'/page/{count}.json') m.get(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) m.post(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) m.put(pageingurl.replace(" ", "+"), text=returndata_txt, headers=header.copy()) header = {'link': f'{pageingurl}; rel="next"'} data_len = len(data) else: m.get(url.replace(" ", "+"), text=data_txt, headers=header.copy()) m.post(url.replace(" ", "+"), text=data_txt, headers=header.copy()) m.put(url.replace(" ", "+"), text=data_txt, headers=header.copy()) header.clear() break def load_fixture(path_to_mock): """Load the expected json fixture from disk.""" resource_file = os.path.normpath(local_path + path_to_mock) with open(resource_file) as data_file: return json.load(data_file) class ClientInitTestCase(unittest.TestCase): """Test cases for the v6 client setup.""" def test_v6_api_version(self): """TpmApiv6 registers as api/v6/ and inherits v5 functions.""" client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') self.assertEqual(client.api, 'api/v6/') self.assertTrue(client.url.endswith('/index.php/api/v6/')) # inherited from TpmApiv5 / TpmApi self.assertTrue(hasattr(client, 'list_password_files')) self.assertTrue(hasattr(client, 'list_passwords')) def test_v6_inherited_function(self): """An inherited function works through the v6 client.""" client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'passwords.json' request_url = api_url + path_to_mock data = sorted(load_fixture(path_to_mock), key=lambda k: k['id']) with requests_mock.Mocker() as m: fake_data(request_url, m) response = sorted(client.list_passwords(), key=lambda k: k['id']) self.assertEqual(data, response) class MockHelperTestCase(unittest.TestCase): """Issue #14: fake_data serves non-JSON content as-is and lets tpm raise the error through its own request handling, instead of the helper choking on json.loads.""" def setUp(self): self.client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') def test_fake_data_non_json_response(self): """fake_data registers a non-JSON fixture without raising itself.""" path_to_mock = 'plain.txt' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: # Must not raise here (previously json.loads blew up in the helper). fake_data(request_url, m) # tpm is what surfaces the invalid-JSON response as a ValueError. with self.assertRaises(ValueError): self.client.get(path_to_mock) class ClientLogTestCase(unittest.TestCase): """Test cases for the v6 log endpoints.""" def setUp(self): self.client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') def test_function_list_log(self): """NEW v6: Test function list_log.""" path_to_mock = 'log.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_log() self.assertEqual(data, response) def test_function_list_log_search(self): """NEW v6: Test function list_log_search.""" search = 'facebook' path_to_mock = f'log/search/{search}.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_log_search(search) self.assertEqual(data, response) class ClientUserAccessTestCase(unittest.TestCase): """Test cases for the v6 user access endpoints.""" def setUp(self): self.client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') def test_function_list_user_passwords(self): """NEW v6: Test function list_user_passwords.""" path_to_mock = 'users/4/passwords.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_passwords('4') self.assertEqual(data, response) def test_function_list_user_projects(self): """NEW v6: Test function list_user_projects.""" path_to_mock = 'users/4/projects.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_user_projects('4') self.assertEqual(data, response) class ClientMyPasswordFavoriteTestCase(unittest.TestCase): """Test cases for the v6 my password favorite/archived endpoints.""" def setUp(self): self.client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') def test_function_list_mypasswords_archived(self): """NEW v6: Test function list_mypasswords_archived.""" path_to_mock = 'my_passwords/archived.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords_archived() self.assertEqual(data, response) def test_function_list_mypasswords_favorite(self): """NEW v6: Test function list_mypasswords_favorite.""" path_to_mock = 'my_passwords/favorite.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: fake_data(request_url, m) response = self.client.list_mypasswords_favorite() self.assertEqual(data, response) def test_function_set_favorite_mypassword(self): """NEW v6: Test function set_favorite_mypassword.""" path_to_mock = 'favorite_my_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_mypassword('4') self.assertEqual(response, None) def test_function_unset_favorite_mypassword(self): """NEW v6: Test function unset_favorite_mypassword.""" path_to_mock = 'favorite_my_passwords/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_mypassword('4') self.assertEqual(response, None) class ClientProjectFavoriteTestCase(unittest.TestCase): """Test cases for the v6 project favorite override (plural endpoint).""" def setUp(self): self.client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') def test_function_set_favorite_project(self): """NEW v6: set_favorite_project uses the plural favorite_projects endpoint.""" path_to_mock = 'favorite_projects/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.post(request_url, status_code=204) response = self.client.set_favorite_project('4') self.assertEqual('POST', m.last_request.method) self.assertTrue(m.last_request.url.endswith('/favorite_projects/4.json')) self.assertEqual(response, None) def test_function_unset_favorite_project(self): """NEW v6: unset_favorite_project uses the plural favorite_projects endpoint.""" path_to_mock = 'favorite_projects/4.json' request_url = api_url + path_to_mock with requests_mock.Mocker() as m: m.delete(request_url, status_code=204) response = self.client.unset_favorite_project('4') self.assertEqual('DELETE', m.last_request.method) self.assertTrue(m.last_request.url.endswith('/favorite_projects/4.json')) self.assertEqual(response, None) class ClientPageSizeTestCase(unittest.TestCase): """Test cases for the v6 X-Page-Size header option.""" def test_page_size_header_sent(self): """NEW v6: page_size sets the X-Page-Size header on requests.""" client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS', page_size=50) path_to_mock = 'log.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: # request_headers acts as a matcher: the call only matches if the # X-Page-Size header is present with this value. m.get(request_url, text=json.dumps(data), request_headers={'X-Page-Size': '50'}) response = client.list_log() self.assertEqual('50', m.last_request.headers.get('X-Page-Size')) self.assertEqual(data, response) def test_no_page_size_header_by_default(self): """Without page_size no X-Page-Size header is sent.""" client = tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS') path_to_mock = 'log.json' request_url = api_url + path_to_mock data = load_fixture(path_to_mock) with requests_mock.Mocker() as m: m.get(request_url, text=json.dumps(data)) client.list_log() self.assertIsNone(m.last_request.headers.get('X-Page-Size')) def test_page_size_too_small_raises(self): """page_size below 5 raises ConfigError.""" with self.assertRaises(tpm.TpmApi.ConfigError): tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS', page_size=4) def test_page_size_too_large_raises(self): """page_size above 1000 raises ConfigError.""" with self.assertRaises(tpm.TpmApi.ConfigError): tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS', page_size=1001) def test_page_size_non_integer_raises(self): """A non-integer page_size raises ConfigError.""" with self.assertRaises(tpm.TpmApi.ConfigError): tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS', page_size='big') def test_page_size_bool_raises(self): """A boolean page_size raises ConfigError.""" with self.assertRaises(tpm.TpmApi.ConfigError): tpm.TpmApiv6('https://tpm.example.com', username='USER', password='PASS', page_size=True) if __name__ == '__main__': unittest.main() peshay-tpm-d71ce81/tools/000077500000000000000000000000001523703711300153615ustar00rootroot00000000000000peshay-tpm-d71ce81/tools/__init__.py000066400000000000000000000000001523703711300174600ustar00rootroot00000000000000peshay-tpm-d71ce81/tools/check_public_artifacts.py000077500000000000000000000156421523703711300224210ustar00rootroot00000000000000#!/usr/bin/env python3 """Guard public artifacts for hygiene leaks before commit or CI publication.""" from __future__ import annotations import argparse import re import subprocess import sys from collections.abc import Iterable, Sequence from pathlib import Path PUBLIC_TEXT_SUFFIXES = { "", ".cfg", ".ini", ".md", ".rst", ".txt", ".toml", ".yaml", ".yml", } SKIP_DIRS = {".git", ".mypy_cache", ".pytest_cache", ".ruff_cache", "__pycache__", "dist", "build"} LITERAL_ESCAPED_NEWLINE_SUFFIXES = {"", ".md", ".rst", ".txt", ".yaml", ".yml"} PLACEHOLDER_VALUES = { "", "pass", "password", "secret", "token", "api_key", "apikey", "private_key", "public_key", "example", "example_password", "dummy", "test", "setdata", "changeme", "redacted", "placeholder", "user", } INTERNAL_AUTOMATION_NAME = "open" + "claw" RUNTIME_CONTEXT_NAME = "Subagent" + " Context" KANBAN_TOOLING_RE = "pl" + "anka|board" + "Id|list" + "Id|card" + "Id" LOCAL_OR_INTERNAL_PATTERNS = [ ("internal automation marker", re.compile(r"\b" + INTERNAL_AUTOMATION_NAME + r"\b", re.IGNORECASE)), ("local state path", re.compile(r"(?:~|/home/[^\s`'\"]+)/\." + INTERNAL_AUTOMATION_NAME + r"\b", re.IGNORECASE)), ("local home path", re.compile(r"/home/[A-Za-z0-9._-]+/[^\s`'\"]*", re.IGNORECASE)), ("mac local path", re.compile(r"/Users/[A-Za-z0-9._-]+/[^\s`'\"]*", re.IGNORECASE)), ("windows local path", re.compile(r"[A-Za-z]:\\\\Users\\\\[^\s`'\"]+", re.IGNORECASE)), ] PROMPT_OR_BOARD_PATTERNS = [ ("prompt leakage", re.compile(r"\b(system|developer|subagent) prompt\b", re.IGNORECASE)), ("runtime context leakage", re.compile(r"\b" + RUNTIME_CONTEXT_NAME + r"\b", re.IGNORECASE)), ("kanban tooling leakage", re.compile(r"\b(" + KANBAN_TOOLING_RE + r")\b", re.IGNORECASE)), ("private board/card id", re.compile(r"\b176\d{16}\b")), ] SECRET_PATTERNS = [ ("private key block", re.compile(r"-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----")), ("aws access key", re.compile(r"\bAKIA[0-9A-Z]{16}\b")), ("github token", re.compile(r"\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{30,}\b")), ("github fine-grained token", re.compile(r"\bgithub_pat_[A-Za-z0-9_]{20,}\b")), ("gitlab token", re.compile(r"\bglpat-[A-Za-z0-9_-]{20,}\b")), ("slack token", re.compile(r"\bxox[baprs]-[A-Za-z0-9-]{20,}\b")), ("openai token", re.compile(r"\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b")), ("bearer token", re.compile(r"\bBearer\s+(?!<|\$\{|TOKEN\b|REDACTED\b)[A-Za-z0-9._~+/=-]{16,}\b", re.IGNORECASE)), ] SECRET_ASSIGNMENT_RE = re.compile( r"\b(?Papi[_-]?key|auth[_-]?token|access[_-]?token|secret|password|priv(?:ate)?[_-]?key)\b" r"\s*[:=]\s*" r"(?P[\"'])?(?P[^\s,\"'`#}]+)", re.IGNORECASE, ) HEX_VALUE_RE = re.compile(r"^[0-9a-fA-F]{32,}$") HIGH_ENTROPY_RE = re.compile(r"^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9_./+=-]{24,}$") def is_probably_text(path: Path) -> bool: if path.suffix.lower() in {".pyc", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".zip", ".gz"}: return False try: chunk = path.read_bytes()[:4096] except OSError: return False return b"\0" not in chunk def git_files() -> list[str]: try: proc = subprocess.run( ["git", "ls-files"], check=True, capture_output=True, text=True, ) except (OSError, subprocess.CalledProcessError): return [] return [line for line in proc.stdout.splitlines() if line] def should_skip(path: Path) -> bool: if any(part in SKIP_DIRS for part in path.parts): return True if not path.is_file(): return True return not is_probably_text(path) def is_placeholder(value: str) -> bool: clean = value.strip().strip("'\"`<>{}[](),.;") normalized = clean.lower().replace("-", "_") return normalized in PLACEHOLDER_VALUES or normalized.startswith("example_") def suspicious_assignment_value(value: str) -> bool: clean = value.strip().strip("'\"`<>{}[](),.;") if is_placeholder(clean): return False if clean.startswith(("$", "${", "os.environ", "env.")): return False return bool(HEX_VALUE_RE.match(clean) or HIGH_ENTROPY_RE.match(clean)) def iter_findings(label: str, text: str, suffix: str) -> Iterable[tuple[int, str, str]]: if suffix in LITERAL_ESCAPED_NEWLINE_SUFFIXES: for line_no, line in enumerate(text.splitlines(), start=1): if r"\n" in line: yield line_no, "literal escaped newline", "replace backslash-n text with a real line break" for name, pattern in LOCAL_OR_INTERNAL_PATTERNS + PROMPT_OR_BOARD_PATTERNS + SECRET_PATTERNS: for match in pattern.finditer(text): line_no = text.count("\n", 0, match.start()) + 1 yield line_no, name, "remove or redact this before publishing" for match in SECRET_ASSIGNMENT_RE.finditer(text): value = match.group("value") if suspicious_assignment_value(value): line_no = text.count("\n", 0, match.start()) + 1 yield line_no, "secret-looking assignment", "use a placeholder or environment variable" def check_text(label: str, text: str, suffix: str = "") -> list[str]: findings = [] for line_no, name, advice in iter_findings(label, text, suffix.lower()): findings.append(f"{label}:{line_no}: {name}: {advice}") return findings def check_paths(paths: Sequence[str]) -> list[str]: findings: list[str] = [] for raw_path in paths: path = Path(raw_path) if should_skip(path): continue suffix = path.suffix.lower() try: text = path.read_text(encoding="utf-8") except UnicodeDecodeError: continue except OSError as exc: findings.append(f"{raw_path}:0: read error: {exc}") continue findings.extend(check_text(raw_path, text, suffix)) return findings def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("files", nargs="*", help="Files to scan; defaults to git-tracked files with --all") parser.add_argument("--all", action="store_true", help="Scan all git-tracked files") parser.add_argument("--stdin", action="store_true", help="Scan text from standard input") parser.add_argument("--label", default="stdin", help="Label to display for --stdin findings") args = parser.parse_args(argv) if args.stdin: findings = check_text(args.label, sys.stdin.read(), Path(args.label).suffix) else: files = git_files() if args.all or not args.files else list(args.files) findings = check_paths(files) if findings: print("Public artifact hygiene guard found issues:", file=sys.stderr) for finding in findings: print(f" {finding}", file=sys.stderr) return 1 return 0 if __name__ == "__main__": raise SystemExit(main()) peshay-tpm-d71ce81/tpm.py000066400000000000000000001061601523703711300153770ustar00rootroot00000000000000"""Team Password Manager API To simplify usage of Team Password Manager API. You can authenticate with username and password >>> import tpm >>> URL = "https://mypasswordmanager.example.com" >>> USER = 'example-user' >>> PASS = 'EXAMPLE_PASSWORD' >>> tpmconn = tpm.TpmApiv5(URL, username=USER, password=PASS) Or with Private/Public Key >>> pubkey = 'EXAMPLE_PUBLIC_KEY' >>> privkey = 'EXAMPLE_PRIVATE_KEY' >>> tpmconn = tpm.TpmApiv5(URL, private_key=privkey, public_key=pubkey) With the connection object you can use all TPM functions, like list all passwords: >>> tpmconn.list_passwords() All API functions from Team Password Manager are included. see http://teampasswordmanager.com/docs/api/ :copyright: (c) 2022 by Andreas Hubert. :license: The MIT License (MIT), see LICENSE for more details. """ from __future__ import annotations import base64 import hashlib import hmac import json import logging import re import time from collections.abc import Iterator from pathlib import Path from typing import Any from urllib.parse import quote_plus import requests __version__ = '5.0.1' # set logger log = logging.getLogger(__name__) # disable unsecure SSL warning requests.packages.urllib3.disable_warnings() # HTTP status codes handled explicitly in error handling. HTTP_FORBIDDEN = 403 HTTP_NOT_FOUND = 404 # Allowed range for the X-Page-Size header (API v6). MIN_PAGE_SIZE = 5 MAX_PAGE_SIZE = 1000 # Validate the base URL passed to the API client. REGEX_URL = re.compile( "^" "(?:(?:https?)://)" "(?:\\S+(?::\\S*)?@)?" "(?:" "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" "|" "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))?" ".?" ")" "(?::\\d{2,5})?" "(?:[/?#]\\S*)?" "$" ) class TPMException(Exception): pass class TpmApi: """Settings needed for the connection to Team Password Manager.""" class ConfigError(Exception): """To throw Exception based on wrong Settings.""" def __init__(self, value: str): self.value = value log.critical(value) def __str__(self) -> str: return repr(self.value) def __init__(self, api: str, base_url: str, kwargs: dict): """init thing.""" self.apiurl = f'api/{api}/' log.debug(f'Set as apiurl: {self.apiurl}') self.api = self.apiurl # Check if URL is not bullshit if REGEX_URL.match(base_url): self.base_url = base_url + '/index.php/' log.debug(f'Set Base URL to {self.base_url}') self.url = self.base_url + self.apiurl log.debug(f'Set URL to {self.url}') else: raise self.ConfigError(f'Invalid URL: {base_url}') # set headers self.headers = { 'Content-Type': 'application/json; charset=utf-8', 'User-Agent': f'tpm.py/{__version__}', } log.debug(f'Set header to {self.headers}') # check kwargs for either keys or user credentials self.private_key = kwargs.get('private_key', False) self.public_key = kwargs.get('public_key', False) self.username = kwargs.get('username', False) self.password = kwargs.get('password', False) self.unlock_reason = kwargs.get('unlock_reason', False) # TLS certificate verification. Defaults to True; pass verify=False # (or a CA bundle path) to override. self.verify = kwargs.get('verify', True) # Optional page size (X-Page-Size header, API v6). Must be an integer # between 5 and 1000 if set. self.page_size = kwargs.get('page_size', False) if self.page_size is not False and ( isinstance(self.page_size, bool) or not isinstance(self.page_size, int) or not MIN_PAGE_SIZE <= self.page_size <= MAX_PAGE_SIZE): raise self.ConfigError( 'page_size must be an integer between 5 and 1000') # Reuse a single session for connection pooling. self.session = requests.Session() if self.private_key is not False and self.public_key is not False and\ self.username is False and self.password is False: log.debug('Using Private/Public Key authentication.') elif self.username is not False and self.password is not False and\ self.private_key is False and self.public_key is False: log.debug('Using Basic authentication.') else: raise self.ConfigError('No authentication specified' ' (user/password or private/public key)') def _build_auth(self, path: str, data: Any) -> Any: """Set auth/unlock/page-size headers and return the request auth.""" auth = None # In case of key authentication if self.private_key and self.public_key: timestamp = str(int(time.time())) log.debug(f'Using timestamp: {timestamp}') unhashed = path + timestamp + str(data) log.debug(f'Using message: {unhashed}') self.hash = hmac.new(str.encode(self.private_key), msg=unhashed.encode('utf-8'), digestmod=hashlib.sha256).hexdigest() log.debug(f'Authenticating with hash: {self.hash}') self.headers['X-Public-Key'] = self.public_key self.headers['X-Request-Hash'] = self.hash self.headers['X-Request-Timestamp'] = timestamp # In case of user credentials authentication elif self.username and self.password: auth = requests.auth.HTTPBasicAuth(self.username, self.password) # Set unlock reason if self.unlock_reason: self.headers['X-Unlock-Reason'] = self.unlock_reason log.info(f'Unlock Reason: {self.unlock_reason}') # Set page size (API v6) if self.page_size: self.headers['X-Page-Size'] = str(self.page_size) log.debug(f'Page size: {self.page_size}') return auth def request(self, path: str, action: str, data: Any = '') -> Any: """To make a request to the API.""" # Check if the path includes URL or not. head = self.base_url if path.startswith(head): path = path[len(head):] path = quote_plus(path, safe='/') if not path.startswith(self.api): path = self.api + path log.debug(f'Using path {path}') # If we have data, convert to JSON if data: data = json.dumps(data) log.debug(f'Data to sent: {data}') auth = self._build_auth(path, data) url = head + path # Try API request and handle Exceptions try: log.debug(f'{action.upper()} request {url}') self.req = self.session.request(action, url, headers=self.headers, auth=auth, verify=self.verify, data=data or None) if self.req.content == b'': result = None log.debug('No result returned.') else: result = self.req.json() # Collection endpoints return a list, so guard on the type # before treating the payload as an error object. if isinstance(result, dict) and result.get('error'): raise TPMException(result['message']) # ValueError must be handled before RequestException: in modern # requests, response.json() raises requests.exceptions.JSONDecodeError, # which subclasses both ValueError and RequestException. except ValueError as e: if self.req.status_code == HTTP_FORBIDDEN: log.warning(f'{url} forbidden') raise TPMException(f'{url} forbidden') from e if self.req.status_code == HTTP_NOT_FOUND: log.warning(f'{url} not found') raise TPMException(f'{url} not found') from e message = f'{e}: {self.req.url} {self.req.text}' log.debug(message) raise ValueError(message) from e except requests.exceptions.RequestException as e: log.critical(f'Connection error for {e}') raise TPMException(f'Connection error for {e}') from e return result def post(self, path: str, data: Any = '') -> Any: """For post based requests.""" return self.request(path, 'post', data) def get(self, path: str) -> Any: """For get based requests.""" return self.request(path, 'get') def put(self, path: str, data: Any = '') -> Any: """For put based requests.""" return self.request(path, 'put', data) def delete(self, path: str) -> None: """For delete based requests.""" self.request(path, 'delete') def get_collection(self, path: str) -> Iterator[Any]: """To get pagewise data.""" while True: items = self.get(path) req = self.req yield from items if req.links and req.links['next'] and\ req.links['next']['rel'] == 'next': path = req.links['next']['url'] else: break def collection(self, path: str) -> list: """To return all items generated by get collection.""" return list(self.get_collection(path)) # From now on, Functions that work that way in all API Versions. # http://teampasswordmanager.com/docs/api-projects/#list_projects def list_projects(self) -> list: """List projects.""" log.debug('List all projects.') return self.collection('projects.json') def list_projects_archived(self) -> list: """List archived projects.""" log.debug('List all archived projects.') return self.collection('projects/archived.json') def list_projects_favorite(self) -> list: """List favorite projects.""" log.debug('List all favorite projects.') return self.collection('projects/favorite.json') def list_projects_search(self, searchstring: str) -> list: """List projects with searchstring.""" log.debug(f'List all projects with: {searchstring}') return self.collection(f'projects/search/{quote_plus(searchstring)}.json') def show_project(self, ID: int) -> Any: """Show a project.""" # http://teampasswordmanager.com/docs/api-projects/#show_project log.debug(f'Show project info: {ID}') return self.get(f'projects/{ID}.json') def list_passwords_of_project(self, ID: int) -> list: """List passwords of project.""" # http://teampasswordmanager.com/docs/api-projects/#list_pwds_prj log.debug(f'List passwords of project: {ID}') return self.collection(f'projects/{ID}/passwords.json') def list_user_access_on_project(self, ID: int) -> list: """List users who can access a project.""" # http://teampasswordmanager.com/docs/api-projects/#list_users_prj log.debug(f'List User access on project: {ID}') return self.collection(f'projects/{ID}/security.json') def create_project(self, data: dict) -> Any: """Create a project.""" # http://teampasswordmanager.com/docs/api-projects/#create_project log.info(f'Create project: {data}') new_id = self.post('projects.json', data).get('id') log.info(f'Project has been created with ID {new_id}') return new_id def update_project(self, ID: int, data: dict) -> None: """Update a project.""" # http://teampasswordmanager.com/docs/api-projects/#update_project log.info(f'Update project {ID} with {data}') self.put(f'projects/{ID}.json', data) def change_parent_of_project(self, ID: int, NewParentID: int) -> None: """Change parent of project.""" # http://teampasswordmanager.com/docs/api-projects/#change_parent log.info(f'Change parrent for project {ID} to {NewParentID}') data = {'parent_id': NewParentID} self.put(f'projects/{ID}/change_parent.json', data) def update_security_of_project(self, ID: int, data: dict) -> None: """Update security of project.""" # http://teampasswordmanager.com/docs/api-projects/#update_project_security log.info(f'Update project {ID} security {data}') self.put(f'projects/{ID}/security.json', data) def archive_project(self, ID: int) -> None: """Archive a project.""" # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project log.info(f'Archive project {ID}') self.put(f'projects/{ID}/archive.json') def unarchive_project(self, ID: int) -> None: """Un-Archive a project.""" # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project log.info(f'Unarchive project {ID}') self.put(f'projects/{ID}/unarchive.json') def delete_project(self, ID: int) -> None: """Delete a project.""" # http://teampasswordmanager.com/docs/api-projects/#delete_project log.info(f'Delete project {ID}') self.delete(f'projects/{ID}.json') # http://teampasswordmanager.com/docs/api-passwords/#list_passwords def list_passwords(self) -> list: """List passwords.""" log.debug('List all passwords.') return self.collection('passwords.json') def list_passwords_archived(self) -> list: """List archived passwords.""" log.debug('List archived passwords.') return self.collection('passwords/archived.json') def list_passwords_favorite(self) -> list: """List favorite passwords.""" log.debug('List favorite spasswords.') return self.collection('passwords/favorite.json') def list_passwords_search(self, searchstring: str) -> list: """List passwords with searchstring.""" log.debug(f'List all passwords with: {searchstring}') return self.collection(f'passwords/search/{quote_plus(searchstring)}.json') def show_password(self, ID: int) -> Any: """Show password.""" # http://teampasswordmanager.com/docs/api-passwords/#show_password log.info(f'Show password info: {ID}') return self.get(f'passwords/{ID}.json') def list_user_access_on_password(self, ID: int) -> list: """List users who can access a password.""" # http://teampasswordmanager.com/docs/api-passwords/#list_users_pwd log.debug(f'List user access on password {ID}') return self.collection(f'passwords/{ID}/security.json') def create_password(self, data: dict) -> Any: """Create a password.""" # http://teampasswordmanager.com/docs/api-passwords/#create_password log.info(f'Create new password {data}') new_id = self.post('passwords.json', data).get('id') log.info(f'Password has been created with ID {new_id}') return new_id def update_password(self, ID: int, data: dict) -> None: """Update a password.""" # http://teampasswordmanager.com/docs/api-passwords/#update_password log.info(f'Update Password {ID} with {data}') self.put(f'passwords/{ID}.json', data) def update_security_of_password(self, ID: int, data: dict) -> None: """Update security of a password.""" # http://teampasswordmanager.com/docs/api-passwords/#update_security_password log.info(f'Update security of password {ID} with {data}') self.put(f'passwords/{ID}/security.json', data) def update_custom_fields_of_password(self, ID: int, data: dict) -> None: """Update custom fields definitions of a password.""" # http://teampasswordmanager.com/docs/api-passwords/#update_cf_password log.info(f'Update custom fields of password {ID} with {data}') self.put(f'passwords/{ID}/custom_fields.json', data) def delete_password(self, ID: int) -> None: """Delete a password.""" # http://teampasswordmanager.com/docs/api-passwords/#delete_password log.info(f'Delete password {ID}') self.delete(f'passwords/{ID}.json') def lock_password(self, ID: int) -> None: """Lock a password.""" # http://teampasswordmanager.com/docs/api-passwords/#lock_password log.info(f'Lock password {ID}') self.put(f'passwords/{ID}/lock.json') def unlock_password(self, ID: int, reason: str) -> None: """Unlock a password.""" # http://teampasswordmanager.com/docs/api-passwords/#unlock_password log.info(f'Unlock password {ID}, Reason: {reason}') self.unlock_reason = reason self.put(f'passwords/{ID}/unlock.json') def list_mypasswords(self) -> list: """List my passwords.""" # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords log.debug('List MyPasswords') return self.collection('my_passwords.json') def list_mypasswords_search(self, searchstring: str) -> list: """List my passwords with searchstring.""" # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords log.debug(f'List MyPasswords with {searchstring}') return self.collection(f'my_passwords/search/{quote_plus(searchstring)}.json') def show_mypassword(self, ID: int) -> Any: """Show my password.""" # http://teampasswordmanager.com/docs/api-my-passwords/#show_password log.debug(f'Show MyPassword {ID}') return self.get(f'my_passwords/{ID}.json') def create_mypassword(self, data: dict) -> Any: """Create my password.""" # http://teampasswordmanager.com/docs/api-my-passwords/#create_password log.info(f'Create MyPassword with {data}') new_id = self.post('my_passwords.json', data).get('id') log.info(f'MyPassword has been created with {new_id}') return new_id def update_mypassword(self, ID: int, data: dict) -> None: """Update my password.""" # http://teampasswordmanager.com/docs/api-my-passwords/#update_password log.info(f'Update MyPassword {ID} with {data}') self.put(f'my_passwords/{ID}.json', data) def delete_mypassword(self, ID: int) -> None: """Delete my password.""" # http://teampasswordmanager.com/docs/api-my-passwords/#delete_password log.info(f'Delete password {ID}') self.delete(f'my_passwords/{ID}.json') def set_favorite_password(self, ID: int) -> None: """Set a password as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#set_fav log.info(f'Set password {ID} as favorite') self.post(f'favorite_passwords/{ID}.json') def unset_favorite_password(self, ID: int) -> None: """Unet a password as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#del_fav log.info(f'Unset password {ID} as favorite') self.delete(f'favorite_passwords/{ID}.json') def set_favorite_project(self, ID: int) -> None: """Set a project as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#set_fav log.info(f'Set project {ID} as favorite') self.post(f'favorite_project/{ID}.json') def unset_favorite_project(self, ID: int) -> None: """Unet a project as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#del_fav log.info(f'Unset project {ID} as favorite') self.delete(f'favorite_project/{ID}.json') def list_users(self) -> list: """List users.""" # http://teampasswordmanager.com/docs/api-users/#list_users log.debug('List users') return self.collection('users.json') def show_user(self, ID: int) -> Any: """Show a user.""" # http://teampasswordmanager.com/docs/api-users/#show_user log.debug(f'Show user {ID}') return self.get(f'users/{ID}.json') def show_me(self) -> Any: """Show me.""" # http://teampasswordmanager.com/docs/api-users/#show_me log.debug('Show Info about own user') return self.get('users/me.json') def who_am_i(self) -> Any: """Who am I.""" return self.show_me() def create_user(self, data: dict) -> Any: """Create a User.""" # http://teampasswordmanager.com/docs/api-users/#create_user log.info(f'Create user with {data}') new_id = self.post('users.json', data).get('id') log.info(f'User has been created with ID {new_id}') return new_id def update_user(self, ID: int, data: dict) -> None: """Update a User.""" # http://teampasswordmanager.com/docs/api-users/#update_user log.info(f'Update user {ID} with {data}') self.put(f'users/{ID}.json', data) def change_user_password(self, ID: int, data: dict) -> None: """Change password of a User.""" # http://teampasswordmanager.com/docs/api-users/#change_password log.info(f'Change user {ID} password') self.put(f'users/{ID}/change_password.json', data) def activate_user(self, ID: int) -> None: """Activate a User.""" # http://teampasswordmanager.com/docs/api-users/#activate_deactivate log.info(f'Activate user {ID}') self.put(f'users/{ID}/activate.json') def deactivate_user(self, ID: int) -> None: """Dectivate a User.""" # http://teampasswordmanager.com/docs/api-users/#activate_deactivate log.info(f'Deactivate user {ID}') self.put(f'users/{ID}/deactivate.json') def convert_user_to_ldap(self, ID: int, DN: str) -> None: """Convert a normal user to a LDAP user.""" # http://teampasswordmanager.com/docs/api-users/#convert_to_ldap data = {'login_dn': DN} log.info(f'Convert User {ID} to LDAP DN {DN}') self.put(f'users/{ID}/convert_to_ldap.json', data) def convert_ldap_user_to_normal(self, ID: int) -> None: """Convert a LDAP user to a normal user.""" log.info(f'Convert User {ID} from LDAP to normal user') self.put(f'users/{ID}/convert_to_normal.json') def delete_user(self, ID: int) -> None: """Delete a user.""" # http://teampasswordmanager.com/docs/api-users/#delete_user log.info(f'Delete user {ID}') self.delete(f'users/{ID}.json') def list_groups(self) -> list: """List Groups.""" # http://teampasswordmanager.com/docs/api-groups/#list_groups log.debug('List groups') return self.collection('groups.json') def show_group(self, ID: int) -> Any: """Show a Group.""" # http://teampasswordmanager.com/docs/api-groups/#show_group log.debug(f'Show group {ID}') return self.get(f'groups/{ID}.json') def create_group(self, data: dict) -> Any: """Create a Group.""" # http://teampasswordmanager.com/docs/api-groups/#create_group log.info(f'Create group with {data}') new_id = self.post('groups.json', data).get('id') log.info(f'Group has been created with ID {new_id}') return new_id def update_group(self, ID: int, data: dict) -> None: """Update a Group.""" # http://teampasswordmanager.com/docs/api-groups/#update_group log.info(f'Update group {ID} with {data}') self.put(f'groups/{ID}.json', data) def add_user_to_group(self, GroupID: int, UserID: int) -> None: """Add a user to a group.""" # http://teampasswordmanager.com/docs/api-groups/#add_user log.info(f'Add User {UserID} to Group {GroupID}') self.put(f'groups/{GroupID}/add_user/{UserID}.json') def delete_user_from_group(self, GroupID: int, UserID: int) -> None: """Delete a user from a group.""" # http://teampasswordmanager.com/docs/api-groups/#del_user log.info(f'Delete user {UserID} from group {GroupID}') self.put(f'groups/{GroupID}/delete_user/{UserID}.json') def delete_group(self, ID: int) -> None: """Delete a group.""" # http://teampasswordmanager.com/docs/api-groups/#delete_group log.info(f'Delete group {ID}') self.delete(f'groups/{ID}.json') def generate_password(self) -> Any: """Generate a new random password.""" # http://teampasswordmanager.com/docs/api-passwords-generator/ log.debug('Generate new password') return self.get('generate_password.json') def get_version(self) -> Any: """Get Version Information.""" # http://teampasswordmanager.com/docs/api-version/ log.debug('Get version information') return self.get('version.json') def get_latest_version(self) -> Any: """Check for latest version.""" # http://teampasswordmanager.com/docs/api-version/ log.debug('Get latest version') return self.get('version/check_latest.json') def up_to_date(self) -> bool: """Check if Team Password Manager is up to date.""" version_info = self.get_latest_version() current_version = version_info.get('version') latest_version = version_info.get('latest_version') if current_version == latest_version: log.info('TeamPasswordManager is up-to-date!') log.debug(f'Current Version: {latest_version} Latest Version: {latest_version}') return True log.warning('TeamPasswordManager is not up-to-date!') log.debug(f'Current Version: {latest_version} Latest Version: {latest_version}') return False class TpmApiv3(TpmApi): """API v3 based class.""" def __init__(self, url: str, **kwargs): super().__init__('v3', url, kwargs) """From now on, Functions that only work with API v3.""" class TpmApiv4(TpmApi): """API v4 based class.""" def __init__(self, url: str, **kwargs): super().__init__('v4', url, kwargs) """From now on, Functions that only work with API v4.""" def list_subprojects(self, ID: int) -> list: """List subprojects.""" # http://teampasswordmanager.com/docs/api-projects/#list_subprojects log.debug(f'List subprojects of {ID}') return self.collection(f'projects/{ID}/subprojects.json') def list_subprojects_action(self, ID: int, action: str) -> list: """List subprojects with allowed action.""" log.debug(f'List subprojects of {ID} with action: {action}') return self.collection(f'projects/{ID}/subprojects/{action}.json') class TpmApiv5(TpmApiv4): """API v5 based class.""" def __init__(self, url: str, **kwargs): # Deliberately skip TpmApiv4.__init__ to register as 'v5' on TpmApi. super(TpmApiv4, self).__init__('v5', url, kwargs) """From now on, Functions that only work with API v5.""" def list_project_files(self, ID: int) -> list: """List files of a project.""" return self.collection(f'projects/{ID}/files.json') def _upload_file(self, upload_path: str, file: str, **kwargs) -> Any: """Base64-encode a local file and upload it to the given API path.""" path = Path(file) if not path.is_file(): raise FileNotFoundError(f'File not found: {file}') encoded = base64.b64encode(path.read_bytes()) data = { "file_data_base64": encoded.decode('ascii'), "file_name": path.name, } if 'notes' in kwargs: data['notes'] = kwargs['notes'] new_id = self.post(upload_path, data).get('id') log.info(f'File has been uploaded with ID {new_id}') return new_id def upload_project_file(self, ID: int, file: str, **kwargs) -> Any: """Upload a file to a project.""" return self._upload_file(f'projects/{ID}/upload.json', file, **kwargs) def archive_password(self, ID: int) -> None: """Archive a password.""" # http://teampasswordmanager.com/docs/api-passwords/#arch_unarch_password log.info(f'Archive password {ID}') self.put(f'passwords/{ID}/archive.json') def unarchive_password(self, ID: int) -> None: """Un-Archive a project.""" # http://teampasswordmanager.com/docs/api-passwords/#arch_unarch_password log.info(f'Unarchive password {ID}') self.put(f'passwords/{ID}/unarchive.json') def move_password(self, ID: int, PROJECT_ID: int) -> None: """Move a password to another project.""" # http://teampasswordmanager.com/docs/api-passwords/#move_password log.info(f'Move password {ID} to Project {PROJECT_ID}') self.put(f'passwords/{ID}/move.json', data={"project_id": PROJECT_ID}) def list_password_files(self, ID: int) -> list: """List files of a password.""" # http://teampasswordmanager.com/docs/api-passwords/#list_files log.info(f'List files of password: {ID}') return self.collection(f'passwords/{ID}/files.json') def upload_password_file(self, ID: int, file: str, **kwargs) -> Any: """Upload a file to a password.""" return self._upload_file(f'passwords/{ID}/upload.json', file, **kwargs) def move_mypassword(self, ID: int, PROJECT_ID: int) -> Any: """Move a mypassword to another project.""" # https://teampasswordmanager.com/docs/api-my-passwords/#move_password log.info(f'Move my_password {ID} to Project {PROJECT_ID}') return self.put(f'my_passwords/{ID}/move.json', data={"project_id": PROJECT_ID}).get('id') def show_file_info(self, ID: int) -> Any: """Show info of a file.""" # https://teampasswordmanager.com/docs/api-files/#show_file log.info(f'Show info of file with ID: {ID}') return self.get(f'files/{ID}.json') def update_file_notes(self, ID: int, NOTES: str) -> None: """Update the notes on a file.""" # https://teampasswordmanager.com/docs/api-files/#update_file log.info(f'Update notes on file {ID} to: {NOTES}') self.put(f'files/{ID}.json', data={"notes": NOTES}) def max_upload_file_size(self) -> Any: """Show max upload file size.""" # https://teampasswordmanager.com/docs/api-files/#max_upload_file_size log.info('Show max_upload_file_size') return self.get('files/max_upload_file_size.json') def uploads_folder_info(self) -> Any: """Show uploads folder info.""" # https://teampasswordmanager.com/docs/api-files/#uploads_folder log.info('Show uploads_folder_info') return self.get('files/uploads_folder_info.json') def download_file(self, ID: int) -> Any: """Get the content of a file.""" # https://teampasswordmanager.com/docs/api-files/#download_file log.info(f'Download file with ID: {ID}') return self.get(f'files/download/{ID}.json') def delete_file(self, ID: int) -> None: """Delete a file.""" # https://teampasswordmanager.com/docs/api-files/#delete_file log.info(f'Delete file {ID}') self.delete(f'files/{ID}.json') def create_user_ldap(self, data: dict) -> Any: """Create a LDAP User.""" # http://teampasswordmanager.com/docs/api-users/#create_user_ldap log.info(f'Create LDAP user with {data}') new_id = self.post('users_ldap.json', data).get('id') log.info(f'LDAP User has been created with ID {new_id}') return new_id def create_user_saml(self, data: dict) -> Any: """Create a SAML User.""" # http://teampasswordmanager.com/docs/api-users/#create_user_saml log.info(f'Create SAML user with {data}') new_id = self.post('users_saml.json', data).get('id') log.info(f'SAML User has been created with ID {new_id}') return new_id def convert_user_to_ldap(self, ID: int, DN: str, SERVER_ID: int) -> None: """Convert a normal user to a LDAP user.""" # http://teampasswordmanager.com/docs/api-users/#convert_to_ldap data = {'login_dn': DN, "ldap_server_id": SERVER_ID} log.info(f'Convert User {ID} to LDAP DN {DN} at Server {SERVER_ID}') self.put(f'users/{ID}/convert_to_ldap.json', data) def convert_user_to_saml(self, ID: int) -> None: """Convert a normal user to a SAML user.""" # http://teampasswordmanager.com/docs/api-users/#convert_to_saml log.info(f'Convert User {ID} to SAML') self.put(f'users/{ID}/convert_to_saml.json') class TpmApiv6(TpmApiv5): """API v6 based class.""" def __init__(self, url: str, **kwargs): # Deliberately skip the intermediate __init__s to register as 'v6' # on TpmApi (super(TpmApiv4, self) resolves to TpmApi in the MRO). super(TpmApiv4, self).__init__('v6', url, kwargs) """From now on, Functions that only work with API v6.""" def list_log(self) -> list: """List the log.""" # https://teampasswordmanager.com/docs/api-log/ log.debug('List log') return self.collection('log.json') def list_log_search(self, searchstring: str) -> list: """Search the log.""" # https://teampasswordmanager.com/docs/api-log/ log.debug(f'Search log with: {searchstring}') return self.collection(f'log/search/{quote_plus(searchstring)}.json') def list_user_passwords(self, ID: int) -> list: """List passwords a user can access (Admin only).""" # http://teampasswordmanager.com/docs/api-users/ log.debug(f'List passwords accessible by user {ID}') return self.collection(f'users/{ID}/passwords.json') def list_user_projects(self, ID: int) -> list: """List projects a user can access (Admin only).""" # http://teampasswordmanager.com/docs/api-users/ log.debug(f'List projects accessible by user {ID}') return self.collection(f'users/{ID}/projects.json') def list_mypasswords_archived(self) -> list: """List archived my passwords.""" # http://teampasswordmanager.com/docs/api-my-passwords/ log.debug('List archived MyPasswords') return self.collection('my_passwords/archived.json') def list_mypasswords_favorite(self) -> list: """List favorite my passwords.""" # http://teampasswordmanager.com/docs/api-my-passwords/ log.debug('List favorite MyPasswords') return self.collection('my_passwords/favorite.json') def set_favorite_mypassword(self, ID: int) -> None: """Set a my password as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#set_fav log.info(f'Set my_password {ID} as favorite') self.post(f'favorite_my_passwords/{ID}.json') def unset_favorite_mypassword(self, ID: int) -> None: """Unset a my password as favorite.""" # http://teampasswordmanager.com/docs/api-favorites/#del_fav log.info(f'Unset my_password {ID} as favorite') self.delete(f'favorite_my_passwords/{ID}.json') def set_favorite_project(self, ID: int) -> None: """Set a project as favorite (v6 uses the plural endpoint).""" # http://teampasswordmanager.com/docs/api-favorites/#set_fav log.info(f'Set project {ID} as favorite') self.post(f'favorite_projects/{ID}.json') def unset_favorite_project(self, ID: int) -> None: """Unset a project as favorite (v6 uses the plural endpoint).""" # http://teampasswordmanager.com/docs/api-favorites/#del_fav log.info(f'Unset project {ID} as favorite') self.delete(f'favorite_projects/{ID}.json')