Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alexis tidying up notes #880

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/faq.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
# Frequently Asked Questions

**Q:** What is this and why should I use it?:
**Q:** What is this and why should I use it?

**A:** This is a complete redesign of the traditional password generator/storage system. Instead of relying on a hard drive to not to fail, or that backup you keep forgetting to make, Cloverleaf makes a password based on your master password and the application you want a password for. This generated password will be the same every time, no matter what device you're on. You can then copy this and paste it into the app you want to log into.

<br/>

**Q:** How do I know you're not looking at my passwords?:
**Q:** How do I know you're not looking at my passwords?

**A:** When you type, your computer takes the app name and your master password and using them makes a new password. Nothing is ever sent across the internet, other than the code for the website itself. If you really want, you can [download the files](https://github.com/cloverleaf/web/archive/refs/heads/master.zip) for the website, smash your router and run Cloverleaf offline (Not that I'd recommend smashing your router.)

<br/>

<a name="remake">**Q:** Why did you remake an existing product?:</a>
<a name="remake">**Q:** Why did you remake an existing product?</a>

**A:** I've openly acknowledged that Cloverleaf is based off the concept of "[Master Password](https://masterpasswordapp.com/)" but why would I spend all this time re-making a working piece of software? The answer is simple: *I don't like how Master Password works.* It has many different offshoots that all look different. It takes 6 variables to make a password and 30 seconds to load (Yes, I timed it.). It makes everything harder than it should be. And that was my motivation to make Cloverleaf. I absolutely love the concept of secure passwords without storing them but hate the current solutions.
**A:** I've openly acknowledged that Cloverleaf is based off the concept of "[Master Password](https://masterpasswordapp.com/)" but why would I spend all this time re-making a working piece of software? The answer is simple: *I don't like how Master Password works.* It has many different offshoots that all look different. It takes 6 variables to make a password and 30 seconds to load (Yes, I timed it.). It makes everything harder than it should be. And that was my motivation to make Cloverleaf. I absolutely love the concept of secure passwords without storing them but dislike the current solutions.

<br/>

**Q:** What if I have multiple accounts on one service?:
**Q:** What if I have multiple accounts on one service?

**A:** There isn't a system in place for this but there doesn't need to be since you can just type `ACCOUNTNAME PASSWORD` in the password field to get the password for that account.

<br/>

<a name="cookies">**Q:** What are cookies and why do you use them?:</a>
<a name="cookies">**Q:** What are cookies and why do you use them?</a>

**A:** A cookie is a small bit of information that a website stores on your computer so that when you come back to the site later, it can remember things from your previous visit. Cloverleaf uses these for remembering what theme you like and a few other things like that.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to show what exactly the cookies are used for, with links to where they are defined in the codebase.


Expand Down
2 changes: 1 addition & 1 deletion src/style.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@charset "UTF-8";
@charset "UTF-8";

// Import only what you need from Materialize

Expand Down
140 changes: 64 additions & 76 deletions unit_tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,141 +1,130 @@
import pytest
import pytest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.action_chains import ActionChains
from meta import pass_vis
from meta import get_var
from meta.get_var import getVar
import json
from urllib.parse import quote
import deep_merge
import warnings
import requests

getVar = get_var.getVar

# Assign initial variables
address = "http://localhost:8080/"
defaultMinLength = 4
defaultMaxLength = 512
options =

options = Options()
options.headless = True

sites = {}
logos = {}
configs = {}
results = {}

# Assign json file variables
with open("../node_modules/cloverleaf/data/sites.json", 'r') as json_file:
sites = json.load(json_file)

with open("../data/logos.json", 'r') as json_file:
logos = json.load(json_file)

with open("../node_modules/cloverleaf/unit_tests/configs.json", 'r') as json_file:
configs = json.load(json_file)

with open("../node_modules/cloverleaf/unit_tests/results.json", 'r') as json_file:
results = json.load(json_file)

sites = deep_merge.merge(sites, logos)


def status_code(driver, url):
js = '''
let callback = arguments[0];
let xhr = new XMLHttpRequest();
xhr.open('GET', ''' + "'" + url.replace("'", "\\\'") + "'" + ''', true);
xhr.onload = function () {
if (this.readyState === 4) {
callback(this.status);
}
};
xhr.onerror = function () {
callback('error');
};
xhr.send(null);
'''

return driver.execute_async_script(js)


def read_clipboard(driver):

box = driver.find_element_by_id("paste-box")
box.send_keys(Keys.CONTROL, "v")
toreturn = box.get_attribute("value")
box.clear()
return toreturn

def status_code(url):
try:
response = requests.head(url)
return response.status_code
except requests.exceptions.RequestException:
return 'error'

@pytest.fixture()
def driver():
driverInternal = webdriver.Firefox(options=options)
driverInternal = webdriver.Firefox(options=Options(headless=True))
try:
driverInternal.get(address)
except WebDriverException:
assert False, "You need to host the localhost before you can run a unit test on it"
yield driverInternal
# Close procedures
driverInternal.close()


def test_caps_equals_nocaps(driver):

pass_vis.show(driver)


# This method ensures no flakey tests.
@pytest.fixture()
def clearBoxes():
appElem = driver.find_element_by_id("app")
appElem.clear()
appElem.send_keys("Test site")

passElem = driver.find_element_by_id("pass")
passElem.clear()

# For the methods pasteBoxSetup and read_clipboard, we make a textbox in order to then paste out the clipboard into it.
@pytest.fixture()
def pasteBoxSetup():
driver.execute_script(
"""body = document.querySelector('body');
element = document.createElement('textarea');
element.id = "paste-box"
body.append(element);""")

def read_clipboard(driver):
box = driver.find_element_by_id("paste-box")
box.send_keys(Keys.CONTROL, "v")
toreturn = box.get_attribute("value")
box.clear()
return toreturn

def find_elements(driver):
app_elem = driver.find_element_by_id("app")
logo_elem = driver.find_element_by_id("logo")
label_elem = driver.find_element_by_xpath("/html/body/div[2]/div/div[1]/label")
pass_elem = driver.find_element_by_id("pass")

return app_elem, logo_elem, label_elem, pass_elem

def test_app_not_case_sensitive(driver):
app, logo, label, password = find_elements(driver)

pass_vis.show(driver)

# Set name to site with a Caps in it
appElem.send_keys("Test site")
passElem.send_keys("Test password")

# Get the end resulting password
caps = driver.find_element_by_id("result").get_attribute("value")

appElem.clear()

# Set name to site without Caps
appElem.send_keys("test site")


# Get the end resulting password
nocaps = driver.find_element_by_id("result").get_attribute("value")

# As app is not case sensitive, end resulting password should be the same
assert caps == nocaps, "Output with caps and without is different"


# Tests to make sure that hitting enter properly applies
# Tests to make sure that hitting enter properly applies a preset
def test_enter_preset(driver):
app, logo, label, password = find_elements(driver)

appElem = driver.find_element_by_id("app")
logo = driver.find_element_by_id("logo")
label = driver.find_element_by_xpath("/html/body/div[2]/div/div[1]/label")
passElem = driver.find_element_by_id("pass")

# Add box for reading paste
driver.execute_script(
"""body = document.querySelector('body');
element = document.createElement('textarea');
element.id = "paste-box"
body.append(element);""")

# For Preset Site Names (Apple, Protonmail...)
for site in sites:

label.click()
appElem.clear()
passElem.clear()
label.click() # unsure why click
appElem.send_keys(site)
appElem.send_keys(Keys.ENTER)

assert appElem.get_attribute("value") == site, "Enter not setting preset name - Preset: " + site

# TODO: Comment this code, as it is not readable to human readers
try :
if "minLength" in sites[site]:
assert getVar(driver, "minLength") == sites[site]["minLength"], "Enter not setting preset minLength - Preset: " + site

if "maxLength" in sites[site]:
assert getVar(driver, "maxLength") == sites[site]["maxLength"], "Enter not setting preset maxLength - Preset: " + site

# Logo
logoURL = ""
# TODO: Comment this code, as it is not readable to human readers
if "logo" in sites[site]:
logoURL = address + sites[site]["logo"]
else:
Expand Down Expand Up @@ -175,14 +164,13 @@ def test_enter_preset(driver):

# Tests to make sure that query strings presets are loaded properly
def test_qs_preset(driver):

app, logo, label, password = find_elements(driver)

# For Preset Site Names (Apple, Protonmail...)
for site in sites:

driver.get(address + "?app="+quote(site))

appElem = driver.find_element_by_id("app")
logo = driver.find_element_by_id("logo")

assert appElem.get_attribute("value") == site, "Query strings not setting preset name - Preset: " + site

if "minLength" in sites[site]:
Expand Down