Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Offline deletion is now possible, added button to lock unlocked vault…
Browse files Browse the repository at this point in the history
…, set notes fields of ciphers as multiline, clearing vault is possible only when device is online, manual syncing vault is prevented when offline
  • Loading branch information
aeoliux committed Feb 27, 2024
1 parent bef20d5 commit be62003
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 33 deletions.
16 changes: 12 additions & 4 deletions LibrePass/API/LibrePassAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ struct LibrePassClient {
self.loginData = nil
self.sharedKey = nil
self.credentialsDatabase = nil
self.vault.vault = []
self.vault = LibrePassDecryptedVault(lastSync: 0)
}

mutating func fetchCiphers() throws {
Expand Down Expand Up @@ -215,6 +215,14 @@ struct LibrePassClient {
newVaultToSync.append(false)
}

for index in stride(from: self.vault.idstoDelete.count - 1, through: 0, by: -1) {
if let _ = try? self.delete(id: self.vault.idstoDelete[index]) {
if let _ = try? self.vault.remove(id: self.vault.idstoDelete[index], save: true) {
self.vault.idstoDelete.remove(at: index)
}
}
}

for encCipher in updated.ciphers {
if self.vault.vault.firstIndex(where: { cipher in encCipher.id == cipher.id }) == nil {
newVault.append(try LibrePassCipher(encCipher: encCipher, key: self.sharedKey!))
Expand Down Expand Up @@ -251,11 +259,11 @@ struct LibrePassClient {
mutating func delete(id: String) throws {
if networkMonitor.isConnected {
_ = try self.client.request(path: "/api/cipher/" + id, body: nil, method: "DELETE")

try self.vault.remove(id: id, save: true)
} else {
throw LibrePassApiErrors.WithMessage(message: "Offline deletion is unsupported")
self.vault.idstoDelete.append(id)
}

try self.vault.remove(id: id, save: true)
}

func generateId() -> String {
Expand Down
6 changes: 4 additions & 2 deletions LibrePass/API/Vault.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CryptoKit
struct LibrePassEncryptedVault: Codable {
var vault: [LibrePassEncryptedCipher] = []
var toSync: [Bool] = []
var idsToDelete: [String] = []
var lastSync: Int64

static func loadVault() throws -> Self {
Expand All @@ -26,7 +27,7 @@ struct LibrePassEncryptedVault: Codable {
}

func decryptVault(key: SymmetricKey) throws -> LibrePassDecryptedVault {
var ciphers: LibrePassDecryptedVault = LibrePassDecryptedVault(toSync: self.toSync, lastSync: self.lastSync, key: key)
var ciphers: LibrePassDecryptedVault = LibrePassDecryptedVault(toSync: self.toSync, idstoDelete: self.idsToDelete, lastSync: self.lastSync, key: key)
for (i, encCipher) in self.vault.enumerated() {
try ciphers.addOrReplace(cipher: try LibrePassCipher(encCipher: encCipher, key: key), toSync: self.toSync[i], save: false)
}
Expand All @@ -42,6 +43,7 @@ struct LibrePassEncryptedVault: Codable {
struct LibrePassDecryptedVault {
var vault: [LibrePassCipher] = []
var toSync: [Bool] = []
var idstoDelete: [String] = []
var lastSync: Int64
var key: SymmetricKey?

Expand Down Expand Up @@ -77,7 +79,7 @@ struct LibrePassDecryptedVault {
}

func encryptVault() throws -> LibrePassEncryptedVault {
var encCiphers: LibrePassEncryptedVault = LibrePassEncryptedVault(toSync: self.toSync, lastSync: self.lastSync)
var encCiphers: LibrePassEncryptedVault = LibrePassEncryptedVault(toSync: self.toSync, idsToDelete: self.idstoDelete, lastSync: self.lastSync)
for cipher in self.vault {
encCiphers.vault.append(try LibrePassEncryptedCipher(cipher: cipher, key: self.key!))
}
Expand Down
3 changes: 2 additions & 1 deletion LibrePass/LibrePassApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct MainWindow: View {
} else {
NavigationView {
List {
NavigationLink(destination: LibrePassLoginWindow(lClient: $lClient, loggedIn: $loggedIn)) {
NavigationLink(destination: LibrePassLoginWindow(lClient: $lClient, loggedIn: $loggedIn, localLogIn: $localLogIn)) {
Text("Log in")
}
NavigationLink(destination: LibrePassRegistrationWindow(lClient: $lClient)) {
Expand Down Expand Up @@ -78,6 +78,7 @@ struct MainWindow: View {
Text("Copyright © 2024 LibrePass Team")
Text("LibrePass server: Medzik (Oskar) and contributors")
Text("LibrePass app for iOS: Zapomnij (Jacek)")
Text("App is licensed under GPL v3 license")

Link("See on Github", destination: URL(string: "https://github.com/LibrePass")!)
.padding()
Expand Down
8 changes: 4 additions & 4 deletions LibrePass/LibrePassCipherView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ struct CipherLoginDataView: View {
}

Section(header: Text("Notes")) {
TextField("Notes", text: self.$notes)
TextField("Notes", text: self.$notes, axis: .vertical)
}

Section {
Expand Down Expand Up @@ -107,8 +107,8 @@ struct CipherSecureNoteView: View {

var body: some View {
List {
TextFieldWithCopyButton(text: "Title", textBind: self.$title)
TextFieldWithCopyButton(text: "Note", textBind: self.$note)
TextField("Title", text: self.$title)
TextField("Note", text: self.$note, axis: .vertical)

ButtonWithSpinningWheel(text: "Save", task: self.saveCipher)
}
Expand Down Expand Up @@ -151,7 +151,7 @@ struct CipherCardDataView: View {
}

Section(header: Text("Notes")) {
TextFieldWithCopyButton(text: "Notes", textBind: self.$notes)
TextField("Note", text: self.$notes, axis: .vertical)
}

Section {
Expand Down
22 changes: 11 additions & 11 deletions LibrePass/LibrePassLocalLogin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@ struct LibrePassLocalLogin: View {
ButtonWithSpinningWheel(text: "Unlock vault", task: self.login)
}

Section(header: Text("If you're encountering crashes after update, try clearing local saved Vault. WARNING! THIS WILL DELETE VAULT SAVED ON THE DISK")) {
Section(header: Text("WARNING! THIS WILL DELETE VAULT SAVED ON THE DISK, but can fix crashes")) {
ButtonWithSpinningWheel(text: "Clear vault", task: self.clearVault, color: Color.red)
}
}
}

func clearVault() throws {
self.errorString = " "

let credentials = try LibrePassCredentialsDatabase.load()
self.lClient = try LibrePassClient(credentials: credentials, password: self.password)

try self.lClient.fetchCiphers()

self.lClient.unAuth()
if networkMonitor.isConnected {
let credentials = try LibrePassCredentialsDatabase.load()
self.lClient = try LibrePassClient(credentials: credentials, password: self.password)

try self.lClient.fetchCiphers()

self.lClient.unAuth()
} else {
throw LibrePassApiErrors.WithMessage(message: "Offline clearing vault can't be done")
}
}

func login() throws {
self.errorString = " "

let credentials = try LibrePassCredentialsDatabase.load()
self.lClient = try LibrePassClient(credentials: credentials, password: self.password)
try self.lClient.syncVault()
Expand Down
2 changes: 2 additions & 0 deletions LibrePass/LibrePassLoginWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct LibrePassLoginWindow: View {
@State private var apiServer = "https://api.librepass.org"

@Binding var loggedIn: Bool
@Binding var localLogIn: Bool

var body: some View {
List {
Expand Down Expand Up @@ -42,5 +43,6 @@ struct LibrePassLoginWindow: View {
try lClient.login(email: self.email, password: self.password)
try self.lClient.fetchCiphers()
self.loggedIn = true
self.localLogIn = true
}
}
23 changes: 12 additions & 11 deletions LibrePass/LibrePassManagerWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ struct LibrePassManagerWindow: View {
.foregroundStyle(Color.red)

}

Button(action: {
self.lClient.unAuth()
self.loggedIn = false
}) {
Image(systemName: "lock")
.foregroundColor(Color.yellow)
}

Button(action: {
self.refreshIndicator = true
}) {
Expand All @@ -73,16 +82,6 @@ struct LibrePassManagerWindow: View {
}
}

.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now()) {
while !self.loggedIn {

}

self.refreshIndicator = true
}
}

.alert(self.errorString, isPresented: self.$showAlert) {
Button("OK", role: .cancel) {
lClient.unAuth()
Expand Down Expand Up @@ -119,7 +118,9 @@ struct LibrePassManagerWindow: View {
}

func syncVault() throws {
try self.lClient.syncVault()
if networkMonitor.isConnected {
try self.lClient.syncVault()
}
}

func deleteCiphers() throws {
Expand Down

0 comments on commit be62003

Please sign in to comment.