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

Add Migration from Basic Authentication #4

Merged
merged 7 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add Text Import
  • Loading branch information
smashedr committed Aug 26, 2024
commit 9da027b5745cf631d1a4aed5b2423126aa457fa1
44 changes: 38 additions & 6 deletions src/html/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,18 @@ <h5 class="mt-3">

<h5><i class="fa-solid fa-key me-2"></i> Saved Credentials</h5>

<div class="mb-1">
<input type="file" id="hosts-input" style="display: none;" />
<a id="import-hosts" class="link-body-emphasis text-decoration-none fst-italic small" role="button">
Import <i class="fa-solid fa-file-arrow-up ms-1"></i></a>
<span class="ms-2 me-1">/</span>
<a id="export-hosts" class="link-body-emphasis text-decoration-none fst-italic small" role="button">
<div class="mb-1 small">
<a id="export-hosts" class="link-body-emphasis text-decoration-none" role="button">
Export <i class="fa-solid fa-file-arrow-down ms-1"></i></a>
<!-- <span class="mx-1">/</span>-->
<span class="mx-1">&bull;</span>
<input type="file" id="hosts-input" style="display: none;" />
<a id="import-file" class="link-body-emphasis text-decoration-none" role="button">
Import File <i class="fa-solid fa-file-arrow-up ms-1"></i></a>
<!-- <span class="mx-1">/</span>-->
<span class="mx-1">&bull;</span>
<a class="link-body-emphasis text-decoration-none" role="button" data-bs-toggle="modal" data-bs-target="#import-modal">
Import Text <i class="fa-solid fa-paste ms-1"></i></a>
</div>

<table id="hosts-table" class="table table-sm table-hover bg-transparent">
Expand Down Expand Up @@ -328,6 +333,33 @@ <h1 class="modal-title fs-5" id="edit-modal-label">Edit Host</h1>
</div> <!-- modal-dialog -->
</div><!-- edit-modal -->

<div class="modal fade" id="import-modal" tabindex="-1" aria-labelledby="import-modal-label" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="import-modal-label">Import Credentials</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" tabindex="-1"></button>
</div>
<div class="modal-body">
<div class="">
<label for="import-textarea" class="mb-1">Import Text</label>
<textarea class="form-control" placeholder="Paste text to import here..." id="import-textarea" style="height: 100px"></textarea>
<div class="invalid-feedback">
Please enter a message in the textarea.
</div>
</div>
</div> <!-- modal-body -->
<div class="modal-footer">
<button id="import-text" type="button" class="btn btn-success me-auto">
Import<i class="fa-solid fa-cloud-arrow-down ms-2"></i>
</button>
<button id="clear-import" type="button" class="btn btn-outline-warning">Clear</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</div> <!-- modal-content -->
</div> <!-- modal-dialog -->
</div><!-- import-modal -->

<button type="button" class="btn btn-outline-primary" id="back-to-top">
<i class="fa-regular fa-square-caret-up"></i>
</button> <!-- back-to-top -->
Expand Down
4 changes: 4 additions & 0 deletions src/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import { showToast } from './export.js'

document.querySelectorAll('.form-control').forEach((el) => {
el.addEventListener('focus', () => el.classList.remove('is-invalid'))
})

if (typeof ClipboardJS !== 'undefined') {
const clipboard = new ClipboardJS(
'[data-clipboard-text],[data-clipboard-target]'
Expand Down
115 changes: 79 additions & 36 deletions src/js/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ editForm.addEventListener('change', editChange)

const hostsInput = document.getElementById('hosts-input')
hostsInput.addEventListener('change', hostsInputChange)
document.getElementById('import-hosts').addEventListener('click', importHosts)
document.getElementById('export-hosts').addEventListener('click', exportHosts)
document.getElementById('import-file').addEventListener('click', importHosts)
document.getElementById('import-text').addEventListener('click', importText)

document
.querySelectorAll('.revoke-permissions')
Expand Down Expand Up @@ -88,6 +89,16 @@ editModalEl.addEventListener('hidePrevented.bs.modal', () => {
editModalAlert.classList.remove('d-none')
})

const importModalEl = document.getElementById('import-modal')
const importTextarea = document.getElementById('import-textarea')
document.getElementById('clear-import').addEventListener('click', () => {
importTextarea.value = ''
importTextarea.focus()
})
importModalEl.addEventListener('shown.bs.modal', () => {
importTextarea.focus()
})

/**
* Initialize Options
* @function initOptions
Expand Down Expand Up @@ -334,17 +345,6 @@ async function editChange(event) {
editModal._config.backdrop = 'static'
}

/**
* Import Hosts Click Callback
* @function importHosts
* @param {MouseEvent} event
*/
async function importHosts(event) {
console.debug('importHosts:', event)
event.preventDefault()
hostsInput.click()
}

/**
* Export Hosts Click Callback
* @function exportHosts
Expand All @@ -365,6 +365,41 @@ async function exportHosts(event) {
textFileDownload('auto-auth-secrets.txt', json)
}

/**
* Import Hosts Click Callback
* @function importHosts
* @param {MouseEvent} event
*/
async function importHosts(event) {
console.debug('importHosts:', event)
event.preventDefault()
hostsInput.click()
}

/**
* Import Text Click Callback
* @function importText
* @param {MouseEvent} event
*/
async function importText(event) {
console.debug('importText:', event)
event.preventDefault()
const text = importTextarea.value
console.debug('text:', text)
if (!text) {
importTextarea.focus()
return
}
try {
const data = JSON.parse(text)
console.debug('data:', data)
} catch (e) {
console.debug('JSON Parse Error:', e)
importTextarea.classList.add('is-invalid')
showToast('Error Parsing Input.', 'danger')
}
}

/**
* Hosts Input Change Callback
* @function hostsInputChange
Expand All @@ -375,31 +410,9 @@ async function hostsInputChange(event) {
event.preventDefault()
try {
const fileReader = new FileReader()
fileReader.onload = async function doBannedImport() {
fileReader.onload = async function () {
const results = JSON.parse(fileReader.result.toString())
// console.debug('results:', results)
// const { sites } = await chrome.storage.sync.get(['sites'])
const hosts = {}
let count = 0
for (const [key, value] of Object.entries(results)) {
try {
if (typeof value === 'object') {
const { username, password } = value
hosts[key] = `${username}:${password}`
} else if (typeof value === 'string') {
// const [username, password] = value.split(':')
hosts[key] = value
}
count += 1
} catch (e) {
console.log(`Error processing: ${key}`, 'color: Red')
}
}
// console.debug('hosts:', hosts)
// await chrome.storage.sync.set({ sites })
await Hosts.update(hosts)
const total = Object.keys(results).length
showToast(`Imported/Updated ${count}/${total} Hosts.`, 'success')
await importCredentials(results)
}
fileReader.readAsText(hostsInput.files[0])
} catch (e) {
Expand All @@ -408,6 +421,36 @@ async function hostsInputChange(event) {
}
}

/**
* Import Credentials
* @function importCredentials
* @param {Object} data
*/
async function importCredentials(data) {
console.debug('performImport:', data)
const hosts = {}
let count = 0
for (const [key, value] of Object.entries(data)) {
try {
if (typeof value === 'object') {
const { username, password } = value
hosts[key] = `${username}:${password}`
} else if (typeof value === 'string') {
// const [username, password] = value.split(':')
hosts[key] = value
}
count += 1
} catch (e) {
console.log(`Error processing: ${key}`, 'color: Red')
}
}
// console.debug('hosts:', hosts)
// await chrome.storage.sync.set({ sites })
await Hosts.update(hosts)
const total = Object.keys(data).length
showToast(`Imported/Updated ${count}/${total} Hosts.`, 'success')
}

/**
* Auth Background Change Callback
* @function backgroundChange
Expand Down
2 changes: 1 addition & 1 deletion tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async function getPage(browser, name, size) {

const [fileChooser] = await Promise.all([
options.waitForFileChooser(),
options.click('#import-hosts'),
options.click('#import-file'),
])
await fileChooser.accept(['./tests/secrets.txt'])
await scrollPage(options)
Expand Down