-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #340 from buttercup/vault_source_entry_search
Vault source entry search
- Loading branch information
Showing
6 changed files
with
302 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { SearchResult, SearcherFactory } from "./BaseSearch.js"; | ||
import { VaultSource } from "../core/VaultSource.js"; | ||
import { Vault } from "../core/Vault.js"; | ||
import { StorageInterface } from "../storage/StorageInterface.js"; | ||
import { VaultEntrySearch } from "./VaultEntrySearch.js"; | ||
import { VaultSourceStatus } from "../types.js"; | ||
|
||
export class VaultSourceEntrySearch extends VaultEntrySearch { | ||
_sources: Array<VaultSource>; | ||
|
||
constructor( | ||
sources: Array<VaultSource>, | ||
memory?: StorageInterface, | ||
searcherFactory?: SearcherFactory | ||
) { | ||
const vaults: Array<Vault> = sources.reduce((output, source) => { | ||
if (source.status === VaultSourceStatus.Unlocked) { | ||
return [...output, source.vault]; | ||
} | ||
return output; | ||
}, []); | ||
super(vaults, memory, searcherFactory); | ||
this._sources = [...sources]; | ||
} | ||
|
||
/** | ||
* Last search results | ||
* @deprecated Use `getResults` instead | ||
*/ | ||
get results(): Array<SearchResult> { | ||
return this.getResults(); | ||
} | ||
|
||
/** | ||
* Get last search results | ||
* @returns An array of results | ||
*/ | ||
getResults(): Array<SearchResult> { | ||
return super.getResults().map((res) => { | ||
const output = res; | ||
const source = this._sources.find((src) => src?.vault?.id === output.vaultID); | ||
if (source) { | ||
output.sourceID = source.id; | ||
} | ||
return output; | ||
}); | ||
} | ||
|
||
/** | ||
* Search for entries by term | ||
* @param term The term to search for | ||
* @returns An array of search results | ||
*/ | ||
searchByTerm(term: string): Array<SearchResult> { | ||
const results = super.searchByTerm(term); | ||
return results.map((res) => { | ||
const output = res; | ||
const source = this._sources.find((src) => src?.vault?.id === output.vaultID); | ||
if (source) { | ||
output.sourceID = source.id; | ||
} | ||
return output; | ||
}); | ||
} | ||
|
||
/** | ||
* Search for entries by URL | ||
* @param url The URL to search with | ||
* @returns An array of search results | ||
*/ | ||
searchByURL(url: string): Array<SearchResult> { | ||
const results = super.searchByURL(url); | ||
return results.map((res) => { | ||
const output = res; | ||
const source = this._sources.find((src) => src?.vault?.id === output.vaultID); | ||
if (source) { | ||
output.sourceID = source.id; | ||
} | ||
return output; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,10 @@ | ||
import { expect } from "chai"; | ||
import { | ||
Entry, | ||
EntryType, | ||
Group, | ||
MemoryStorageInterface, | ||
Vault, | ||
VaultEntrySearch | ||
} from "../../../dist/node/index.js"; | ||
import { EntryType, MemoryStorageInterface, VaultEntrySearch } from "../../../dist/node/index.js"; | ||
import { createSampleVault } from "./helpers.js"; | ||
|
||
describe("VaultEntrySearch", function () { | ||
beforeEach(function () { | ||
const vault = (this.vault = new Vault()); | ||
const groupA = vault.createGroup("Email"); | ||
groupA | ||
.createEntry("Personal Mail") | ||
.setProperty("username", "[email protected]") | ||
.setProperty("password", "df98Sm2.109x{91") | ||
.setProperty("url", "https://fastmail.com") | ||
.setAttribute(Entry.Attributes.FacadeType, EntryType.Website); | ||
groupA | ||
.createEntry("Work") | ||
.setProperty("username", "[email protected]") | ||
.setProperty("password", "#f05c.*skU3") | ||
.setProperty("URL", "gmov.edu.au/portal/auth") | ||
.addTags("job"); | ||
groupA | ||
.createEntry("Work logs") | ||
.setProperty("username", "[email protected]") | ||
.setProperty("password", "#f05c.*skU3") | ||
.setProperty("URL", "https://logs.gmov.edu.au/sys30/atc.php") | ||
.addTags("job"); | ||
const groupB = vault.createGroup("Bank"); | ||
groupB | ||
.createEntry("MyBank") | ||
.setProperty("username", "324654356346") | ||
.setProperty("PIN", "1234") | ||
.setAttribute(Entry.Attributes.FacadeType, EntryType.Login) | ||
.addTags("finance", "banking"); | ||
groupB | ||
.createEntry("Insurance") | ||
.setProperty("username", "testing-user") | ||
.setProperty("URL", "http://test.org/portal-int/login.aspx") | ||
.addTags("finance"); | ||
const groupC = vault.createGroup("General"); | ||
groupC | ||
.createEntry("Clipart") | ||
.setProperty("username", "gmonkey123") | ||
.setProperty("password", "test93045") | ||
.setProperty("Url", "clipart.com"); | ||
groupC | ||
.createEntry("Wordpress") | ||
.setProperty("username", "gmonkey1234") | ||
.setProperty("password", "passw0rd") | ||
.setProperty("Url", "https://wordpress.com/") | ||
.setProperty("Login URL", "https://wordpress.com/account/login.php"); | ||
const trashGroup = vault.createGroup("Trash"); | ||
trashGroup | ||
.createEntry("Ebay") | ||
.setProperty("username", "[email protected]") | ||
.setProperty("password", "passw0rd") | ||
.setProperty("Url", "https://ebay.com/"); | ||
trashGroup.setAttribute(Group.Attribute.Role, "trash"); | ||
this.vault = createSampleVault(); | ||
}); | ||
|
||
it("can be instantiated", function () { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { expect } from "chai"; | ||
import { | ||
EntryType, | ||
MemoryStorageInterface, | ||
VaultSourceEntrySearch | ||
} from "../../../dist/node/index.js"; | ||
import { createSampleManager } from "./helpers.js"; | ||
|
||
describe("VaultSourceEntrySearch", function () { | ||
beforeEach(async function () { | ||
const [, source] = await createSampleManager(); | ||
this.source = source; | ||
this.vault = source.vault; | ||
}); | ||
|
||
it("can be instantiated", function () { | ||
expect(() => { | ||
new VaultSourceEntrySearch([this.source]); | ||
}).to.not.throw(); | ||
}); | ||
|
||
describe("instance", function () { | ||
beforeEach(function () { | ||
this.storage = new MemoryStorageInterface(); | ||
this.search = new VaultSourceEntrySearch([this.source], this.storage); | ||
return this.search.prepare(); | ||
}); | ||
|
||
describe("searchByTerm", function () { | ||
it("finds results by term", function () { | ||
const results = this.search.searchByTerm("work").map((res) => res.properties.title); | ||
expect(results[0]).to.equal("Work"); | ||
expect(results[1]).to.equal("Work logs"); | ||
expect(results[2]).to.equal("Wordpress"); | ||
}); | ||
|
||
it("excludes trash entries", function () { | ||
const results = this.search.searchByTerm("ebay"); | ||
expect(results).to.have.lengthOf(0); | ||
}); | ||
|
||
it("returns resulting entry type", function () { | ||
const [res] = this.search.searchByTerm("Personal Mail"); | ||
expect(res).to.have.property("entryType", EntryType.Website); | ||
}); | ||
|
||
it("returns results including entry group IDs", function () { | ||
const [res] = this.search.searchByTerm("Personal Mail"); | ||
expect(res).to.have.property("groupID").that.is.a("string"); | ||
}); | ||
|
||
it("returns results using a single tag, no search", function () { | ||
const results = this.search.searchByTerm("#job").map((res) => res.properties.title); | ||
expect(results).to.deep.equal(["Work", "Work logs"]); | ||
}); | ||
|
||
it("returns results using multiple tags, no search", function () { | ||
const results = this.search | ||
.searchByTerm("#finance #banking") | ||
.map((res) => res.properties.title); | ||
expect(results).to.deep.equal(["MyBank"]); | ||
}); | ||
|
||
it("returns results using tags and search", function () { | ||
const results = this.search | ||
.searchByTerm("#job logs") | ||
.map((res) => res.properties.title); | ||
expect(results).to.deep.equal(["Work logs"]); | ||
}); | ||
|
||
describe("results", function () { | ||
it("contain source ID", function () { | ||
const [res] = this.search.searchByTerm("Personal Mail"); | ||
expect(res).to.have.property("sourceID", this.source.id); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("searchByURL", function () { | ||
it("finds results by URL", function () { | ||
const results = this.search.searchByURL("https://wordpress.com/homepage/test/org"); | ||
expect(results).to.have.length.above(0); | ||
expect(results[0]).to.have.nested.property("properties.title", "Wordpress"); | ||
}); | ||
|
||
it("excludes trash entries", function () { | ||
const results = this.search.searchByURL("ebay.com"); | ||
expect(results).to.have.lengthOf(0); | ||
}); | ||
|
||
it("finds multiple similar results", function () { | ||
const results = this.search.searchByURL("https://gmov.edu.au/portal/"); | ||
expect(results).to.have.lengthOf(2); | ||
expect(results[0].properties.title).to.equal("Work"); | ||
expect(results[1].properties.title).to.equal("Work logs"); | ||
}); | ||
|
||
it("supports ordering", function () { | ||
const [entry] = this.vault.findEntriesByProperty("title", "Work logs"); | ||
return this.storage | ||
.setValue( | ||
`bcup_search_${this.vault.id}`, | ||
JSON.stringify({ | ||
[entry.id]: { | ||
"gmov.edu.au": 1 | ||
} | ||
}) | ||
) | ||
.then(() => this.search.prepare()) | ||
.then(() => { | ||
const results = this.search.searchByURL("https://gmov.edu.au/portal/"); | ||
expect(results).to.have.lengthOf(2); | ||
expect(results[0].properties.title).to.equal("Work logs"); | ||
expect(results[1].properties.title).to.equal("Work"); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.