Initial user management

This commit is contained in:
Andrew Cope 2022-02-27 18:04:54 -05:00
parent ee20f0a93f
commit 9f53188f71
8 changed files with 123 additions and 26 deletions

View file

@ -7,7 +7,7 @@
import Foundation
class NtfyUser {
class NtfyUser: Identifiable {
var baseUrl: String
var username: String
var password: String

View file

@ -321,18 +321,32 @@ class Database {
}
}
func findUser(baseUrl: String) -> NtfyUser? {
func deleteUser(user: NtfyUser) {
do {
if let result = try db?.pluck(users.filter(user_base_url == baseUrl)) {
return NtfyUser(
baseUrl: try result.get(user_base_url),
username: try result.get(user_username),
password: try result.get(user_password)
)
let line = users.filter(user_base_url == user.baseUrl && user_username == user.username)
try db?.run(line.delete())
} catch {
print(error)
}
}
func findUsers(baseUrl: String) -> [NtfyUser] {
var ntfyUsers = [NtfyUser]()
do {
let query = users.filter(user_base_url == baseUrl)
if let result = try db?.prepare(query) {
for line in result {
let user = NtfyUser(
baseUrl: try line.get(user_base_url),
username: try line.get(user_username),
password: try line.get(user_password)
)
ntfyUsers.append(user)
}
}
} catch {
print(error)
}
return nil
return ntfyUsers
}
}

View file

@ -18,7 +18,7 @@ struct AddSubscriptionView: View {
@State private var activeAlert: AddSubscriptionView.ActiveAlert = .invalidTopic
@State private var authFailureError = ""
@Binding var addingSubscription: Bool
@Binding var currentView: CurrentView
var body: some View {
NavigationView {
@ -45,7 +45,7 @@ struct AddSubscriptionView: View {
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
addingSubscription = false
currentView = .subscriptionList
}) {
Text("Cancel")
}
@ -84,7 +84,7 @@ struct AddSubscriptionView: View {
4. Fetch cached messages
5. Switch to SubscriptionDetail view
*/
var user = Database.current.findUser(baseUrl: baseUrl)
var user = Database.current.findUsers(baseUrl: baseUrl).first
if showLogin {
print("Authorization via UI forms")
if (user != nil) {
@ -106,7 +106,7 @@ struct AddSubscriptionView: View {
subscription.subscribe(to: sanitizedTopic)
}
subscription.fetchNewNotifications(user: user, completionHandler: nil)
addingSubscription = false
currentView = .subscriptionList
showLogin = false
} else {
showLogin = true
@ -130,7 +130,7 @@ struct AddSubscriptionView: View {
}) {
Text("Subscribe")
}
.disabled(!isTopicValid(topic: sanitizeTopic(topic: topic)) && addingSubscription)
.disabled(!isTopicValid(topic: sanitizeTopic(topic: topic)) && currentView == CurrentView.addingSubscription)
}
}
.alert(isPresented: $showAlert) {

View file

@ -9,14 +9,21 @@ import SwiftUI
struct ContentView: View {
@State var addingSubscription = false
@State var managingUsers = false
@State var currentView = CurrentView.subscriptionList
var body: some View {
return Group {
if addingSubscription {
AddSubscriptionView(addingSubscription: $addingSubscription)
} else {
SubscriptionsList(addingSubscription: $addingSubscription)
}
switch (currentView) {
case .managingUsers:
UserManagementView(currentView: $currentView)
case .addingSubscription:
AddSubscriptionView(currentView: $currentView)
case .subscriptionList:
SubscriptionsList(currentView: $currentView)
}
}
}
enum CurrentView {
case addingSubscription, managingUsers, subscriptionList
}

View file

@ -25,7 +25,7 @@ struct SubscriptionDetail: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
let user = Database.current.findUser(baseUrl: subscription.baseUrl)
let user = Database.current.findUsers(baseUrl: subscription.baseUrl).first
NavigationView {
List(selection: $selection) {
ForEach(subscription.notifications, id: \.self) { notification in

View file

@ -10,7 +10,7 @@ import SwiftUI
struct SubscriptionsList: View {
@ObservedObject var subscriptions = NtfySUbscriptionList()
@Binding var addingSubscription: Bool
@Binding var currentView: CurrentView
var body: some View {
NavigationView {
@ -40,10 +40,19 @@ struct SubscriptionsList: View {
.listStyle(PlainListStyle())
.navigationTitle("Subscribed Topics")
.toolbar {
Button(action: {
addingSubscription = true
}) {
Image(systemName: "plus")
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
currentView = .addingSubscription
}) {
Image(systemName: "plus")
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
currentView = .managingUsers
}) {
Text("Users")
}
}
}
.overlay(Group {

View file

@ -0,0 +1,63 @@
//
// UserManagementView.swift
// ntfy.sh
//
// Created by Andrew Cope on 2/27/22.
//
import Foundation
import SwiftUI
struct UserManagementView: View {
@ObservedObject var viewModel = UserManagementViewModel()
@Binding var currentView: CurrentView
var body: some View {
NavigationView {
List {
Section(header: Text(Configuration.appBaseUrl)) {
ForEach(viewModel.users) { user in
Text(user.username)
.swipeActions {
Button(role: .destructive) {
viewModel.deleteUser(user: user)
} label: {
Label("Delete", systemImage: "trash.circle")
}
}
}
}
}
.listStyle(GroupedListStyle())
.navigationTitle("Manage Users")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
currentView = .subscriptionList
}) {
Text("Topics")
}
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
.onAppear {
viewModel.loadUsers()
}
}
}
class UserManagementViewModel: ObservableObject {
@Published var users = [NtfyUser]()
func loadUsers() {
self.users = Database.current.findUsers(baseUrl: Configuration.appBaseUrl)
}
func deleteUser(user: NtfyUser) {
Database.current.deleteUser(user: user)
self.loadUsers()
}
}

View file

@ -33,6 +33,7 @@
80856C8027BDE0A7008AC8B8 /* ApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80856C7E27BDE0A7008AC8B8 /* ApiService.swift */; };
8086EB242794630800C3628A /* AddSubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8086EB232794630800C3628A /* AddSubscriptionView.swift */; };
8086EB2627946FCE00C3628A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8086EB2527946FCE00C3628A /* ContentView.swift */; };
808833B427CC32010098927E /* UserManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 808833B327CC32010098927E /* UserManagementView.swift */; };
80A313F52793B1CF00F1A639 /* NtfySubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A313F42793B1CF00F1A639 /* NtfySubscription.swift */; };
80A313F72793B56800F1A639 /* NtfyNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A313F62793B56800F1A639 /* NtfyNotification.swift */; };
80A313F92793C0D800F1A639 /* SubscriptionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A313F82793C0D800F1A639 /* SubscriptionRow.swift */; };
@ -94,6 +95,7 @@
80856C7E27BDE0A7008AC8B8 /* ApiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiService.swift; sourceTree = "<group>"; };
8086EB232794630800C3628A /* AddSubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSubscriptionView.swift; sourceTree = "<group>"; };
8086EB2527946FCE00C3628A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
808833B327CC32010098927E /* UserManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserManagementView.swift; sourceTree = "<group>"; };
80910E1127C420B50074B05A /* GETTING_STARTED.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = GETTING_STARTED.md; sourceTree = "<group>"; };
80910E1227C422140074B05A /* TECHNICAL_LIMITATIONS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = TECHNICAL_LIMITATIONS.md; sourceTree = "<group>"; };
809D244827C5E0A900F1FC21 /* GoogleService-Info-prod.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info-prod.plist"; sourceTree = "<group>"; };
@ -231,6 +233,7 @@
8086EB232794630800C3628A /* AddSubscriptionView.swift */,
8086EB2527946FCE00C3628A /* ContentView.swift */,
8079FF4E27C29D3300FB3D18 /* NotificationAttachmentView.swift */,
808833B327CC32010098927E /* UserManagementView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -426,6 +429,7 @@
80E8CED727B56DB200FDC5E0 /* EmojiManager.swift in Sources */,
8086EB242794630800C3628A /* AddSubscriptionView.swift in Sources */,
8079FF5227C2C38700FB3D18 /* NtfyUser.swift in Sources */,
808833B427CC32010098927E /* UserManagementView.swift in Sources */,
80A313FD2793C42000F1A639 /* NotificationRow.swift in Sources */,
80A313FB2793C2EA00F1A639 /* SubscriptionDetail.swift in Sources */,
8079FF4C27C2874A00FB3D18 /* NtfyAttachment.swift in Sources */,