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

Commit

Permalink
Render names in authorization list (#1066)
Browse files Browse the repository at this point in the history
Fixes #1060

- Fetch name of authorizations
- Render in list view
- Move to `.contextMenu` for revocation and sharing


https://github.com/subconsciousnetwork/subconscious/assets/5009316/ddb7206d-45b1-40bb-9cec-d891a41a55a8
  • Loading branch information
bfollington authored Jan 16, 2024
1 parent ba20217 commit 4b93044
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,37 +106,36 @@ struct AuthorizationSettingsView: View {

Section(
content: {
List {
ForEach(state.authorizations, id: \.self) { auth in
HStack {
Text(auth)
.font(.callout.monospaced())
.foregroundColor(.secondary)
.multilineTextAlignment(.leading)

Menu(
content: {
Button(
action: {
app.send(.authorization(.requestRevoke(auth)))
},
label: {
Label(
title: {
Text("Revoke")
},
icon: {
Image(systemName: "exclamationmark.octagon.fill")
}
)
}
)
},
label: {
EllipsisLabelView()
}
)
}
ForEach(state.authorizations, id: \.self) { auth in
VStack(alignment: .leading, spacing: AppTheme.unit) {
Text(auth.name)
.foregroundColor(.primary)
Text(auth.authorization)
.font(.caption.monospaced())
.foregroundColor(.secondary)
.lineLimit(1)
.truncationMode(.middle)
}
.padding(.vertical, AppTheme.unit)
.contextMenu {
Button(
action: {
app.send(.authorization(.requestRevoke(auth)))
},
label: {
Label(
title: {
Text("Revoke")
},
icon: {
Image(systemName: "exclamationmark.octagon.fill")
}
)
}
)
.tint(.red)

ShareLink(item: auth.authorization)
}
}
},
Expand Down Expand Up @@ -254,7 +253,7 @@ struct AuthorizationSettingsFormModel: ModelProtocol {
enum AuthorizationSettingsAction: Hashable {
case appear
case listAuthorizations
case succeedListAuthorizations([Authorization])
case succeedListAuthorizations([NamedAuthorization])
case failListAuthorizations(_ error: String)

case form(AuthorizationSettingsFormAction)
Expand All @@ -266,7 +265,7 @@ enum AuthorizationSettingsAction: Hashable {
case qrCodeScanned(scannedContent: String)
case qrCodeScanError(error: String)

case requestRevoke(Authorization)
case requestRevoke(NamedAuthorization)
case confirmRevoke
case cancelRevoke
case succeedRevoke
Expand All @@ -291,12 +290,12 @@ struct AuthorizationSettingsModel: ModelProtocol {
var isConfirmRevokePresented = false

var form: AuthorizationSettingsFormModel = AuthorizationSettingsFormModel()
var authorizations: [Authorization] = ["Test"]
var authorizations: [NamedAuthorization] = []

var errorMessage: String? = nil
var lastAuthorization: Authorization? = nil

var revokeCandidate: Authorization? = nil
var revokeCandidate: NamedAuthorization? = nil

static func update(
state: Self,
Expand Down Expand Up @@ -416,7 +415,7 @@ struct AuthorizationSettingsModel: ModelProtocol {

let fx: Fx<AuthorizationSettingsAction> = Future.detached {
do {
try await environment.noosphere.revoke(authorization: candidate)
try await environment.noosphere.revoke(authorization: candidate.authorization)
let _ = try await environment.noosphere.save()
return .succeedRevoke
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,18 @@ actor NoosphereService:
}
}

func listAuthorizations() async throws -> [Authorization] {
func listAuthorizations() async throws -> [NamedAuthorization] {
try await errorLoggingService.capturing {
try await sphere().listAuthorizations()
}
}

func authorizationName(authorization: Authorization) async throws -> String {
try await errorLoggingService.capturing {
try await sphere().authorizationName(authorization: authorization)
}
}

func verify(authorization: Authorization) async throws -> Bool {
try await errorLoggingService.capturing {
try await sphere().verify(authorization: authorization)
Expand Down
51 changes: 49 additions & 2 deletions xcode/Subconscious/Shared/Services/Noosphere/Sphere.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import os

public typealias Cid = String
public typealias Authorization = String
public struct NamedAuthorization: Equatable, Hashable {
public let name: String
public let authorization: Authorization
}

/// Describes a Sphere.
/// See `Sphere` for a concrete implementation.
Expand Down Expand Up @@ -68,7 +72,8 @@ public protocol SphereProtocol {
func escalateAuthority(mnemonic: String) async throws -> Sphere
func authorize(name: String, did: Did) async throws -> Authorization
func revoke(authorization: Authorization) async throws -> Void
func listAuthorizations() async throws -> [Authorization]
func listAuthorizations() async throws -> [NamedAuthorization]
func authorizationName(authorization: Authorization) async throws -> String
func verify(authorization: Authorization) async throws -> Bool
}

Expand Down Expand Up @@ -921,7 +926,21 @@ public actor Sphere: SphereProtocol, SpherePublisherProtocol {
}
}

public func listAuthorizations() async throws -> [Authorization] {
public func listAuthorizations() async throws -> [NamedAuthorization] {
let values = try await listAuthorizationValues()
var authorizations: [NamedAuthorization] = []

for value in values {
let name = try await authorizationName(authorization: value)
authorizations.append(
NamedAuthorization(name: name, authorization: value)
)
}

return authorizations
}

private func listAuthorizationValues() async throws -> [Authorization] {
try await withCheckedThrowingContinuation { continuation in
nsSphereAuthorityAuthorizationsList(
noosphere.noosphere,
Expand Down Expand Up @@ -949,6 +968,34 @@ public actor Sphere: SphereProtocol, SpherePublisherProtocol {
}
}

public func authorizationName(authorization: Authorization) async throws -> String {
try await withCheckedThrowingContinuation { continuation in
nsSphereAuthorityAuthorizationName(
noosphere.noosphere,
self.sphere,
authorization
) { error, name in
if let error = Noosphere.readErrorMessage(error) {
continuation.resume(
throwing: NoosphereError.foreignError(error)
)
return
}

guard let name = name else {
continuation.resume(throwing: NoosphereError.nullPointer)
return
}
defer {
ns_string_free(name)
}

continuation.resume(returning: String(cString: name))
return
}
}
}

public func authorize(name: String, did: Did) async throws -> Authorization {
try await withCheckedThrowingContinuation { continuation in
nsSphereAuthorityAuthorize(
Expand Down
11 changes: 9 additions & 2 deletions xcode/Subconscious/SubconsciousTests/Tests_Sphere.swift
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,14 @@ final class Tests_Sphere: XCTestCase {

let authorizations = try await sphere.listAuthorizations()
XCTAssertEqual(authorizations.count, 2)
XCTAssertTrue(authorizations.contains(where: { auth in auth == authorization }))
XCTAssertTrue(
authorizations.contains(where: {
auth in auth.authorization == authorization && auth.name == "ben"
})
)

let name = try await sphere.authorizationName(authorization: authorization)
XCTAssertEqual(name, "ben")

let verified = try await sphere.verify(authorization: authorization)
XCTAssertTrue(verified)
Expand All @@ -560,7 +567,7 @@ final class Tests_Sphere: XCTestCase {

let authorizations2 = try await sphere.listAuthorizations()
XCTAssertEqual(authorizations2.count, 1)
XCTAssertFalse(authorizations2.contains(where: { auth in auth == authorization }))
XCTAssertFalse(authorizations2.contains(where: { auth in auth.authorization == authorization }))

}
}

0 comments on commit 4b93044

Please sign in to comment.