diff --git a/Documentation.docc/Auth.md b/Documentation.docc/Auth.md new file mode 100644 index 000000000..234e06319 --- /dev/null +++ b/Documentation.docc/Auth.md @@ -0,0 +1,114 @@ +# Auth + +Scribble Lab's Auth Services + +## Overview + +The ScribbleLab Auth Service is a secure, reliable and easy-to-use authentication service that allows users to gain access to the application's resources through a simple and straightforward process. The ScribbleLab Auth Service is built on top of Firebase, a powerful and scalable database service, ensuring that user authentication is done in a secure and robust manner. + +We offer our users three ways to authenticate: +- Google Sign In **``(GID)``** +- SignInWithApple **``(SIWA)``** +- ScribbleLabApp Account **``(SLA)`** + +All three ways are secure due to our secured database. + +### How is Firebase connected to our App? +- In order to use Firebase you need to import Firebase via SPM and import it in your AppFile as following: + ```swift + import SwiftUI + import FirebaseCore + ``` + +- Then you need to add Firebase to your AppDelegate: + ```swift + class AppDelegate: NSObject, UIApplicationDelegate { + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + FirebaseApp.configure() + + return true + } + } + ``` + + > For the use for GID: + > In order to use GID (= GoogleSignIn) you need to add GoogleSignIn to your Project via SPM. Then import it in your AppFile. + >```swift + > import SwiftUI + > import FirebaseCore + > import GoogleSignIn + > ``` + > + > Then add the following code to your AppDelegate in order to let GID run properly: + > ```swift + > // The method should call the handleURL method of GIDSignIn instance, which will properly handle the URL that SL recieves at the end of the auth process. + >@available(iOS 9.0, *) + >func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + > return GIDSignIn.sharedInstance.handle(url) + >} + > ``` + +- Firebase is now succesfully conected from your App site 🎉 + +### How does our Authentication work? +While the App is launching it checks wether you have a valide UserSession (email, password, uuid). In order to do that we call our ``ContentViewModel`` that asks FirebaseAuth after a valide user session: + +```swift +private let service = SLAuthService.shared +private var canellables = Set() + +@Published var userSession: FirebaseAuth.User? +@Published var currentUser: User? + +init() { + setupSubscribers() +} + +func setupSubscribers() { + service.$userSession.sink { [weak self] userSession in + self?.userSession = userSession + } + .store(in: &canellables) + + service.$currentUser.sink { [weak self] currentUser in + self?.currentUser = currentUser + } + .store(in: &canellables) +} +``` + + + +> ContentView.swift: +> ```swift +> import SwiftUI +> +> struct ContentView: View { +> @StateObject var viewModel = ContentViewModel() +> +> var body: some View { +> Group { +> if $viewModel.userSession == nil { +> SignUpView() +> } else if let currentUser = viewModel.currentUser { +> SLSideBarView() +> } +> } +> } +>} +> ``` + +While this is all happening our ``ContentViewModel`` also calls the ``SLAuthService`` that tries to fetch the user: +```swift +@MainActor +func loadUserData() async throws { + self.userSession = Auth.auth().currentUser + guard let currentUid = userSession?.uid else { return } + self.currentUser = try await UserService.fetchUser(withUid: currentUid) +} +``` + +### Section header + +Text diff --git a/Documentation.docc/AuthFlow.md b/Documentation.docc/AuthFlow.md new file mode 100644 index 000000000..b88132e3f --- /dev/null +++ b/Documentation.docc/AuthFlow.md @@ -0,0 +1,25 @@ +# AuthFlow + +ScribbleLab's Auth flow + +## Overview + +The Auth Flow is a process that allows users to securely access an application or service by verifying their identity. This process typically involves the use of a username and password, but may also incorporate other forms of authentication such as biometric identification or two-factor authentication. + +Here is a breakdown of the steps involved in the Auth Flow: + +1. User initiates the Auth Flow: At the first launch the user will be navigated to our ``SignUpView``. If the user already has an account they'll be navigated to the ``LogInView``. + +2. User enters their login credentials: The user provides their username/email and password, or other forms of authentication such as biometric identification or two-factor authentication. + +3. Application verifies credentials: The application verifies the user's credentials against our Firestore Database. If the credentials are valid, the application grants the user access to the service. + +4. Session creation: Once the user has been authenticated, the application creates a session for the user. This session is a unique identifier that allows the application to recognize the user and their access rights for the duration of their visit to the application or service. + +5. User performs actions within the application: The user is now able to perform actions within the application or service according to their access rights. + +6. Session expiration: Once the user has finished using the application or service, the session is terminated. This is done to ensure the security of the user's data and prevent unauthorized access. + +### Section header + +Text diff --git a/Documentation.docc/Documentation.md b/Documentation.docc/Documentation.md index f0c23a64c..9d00e70fd 100644 --- a/Documentation.docc/Documentation.md +++ b/Documentation.docc/Documentation.md @@ -64,7 +64,7 @@ where personal information can fall into the wrong hands. But with ScribbleLab i When you create a ScribbleLab account, you are agreeing to our [License Agreement](LICENSE_AGREEMENT.md) as well as the licenses of our third-party packages. You might be wondering if it's safe to create an account with ScribbleLab. The answer is yes! We use [Google Firebase](https://firebase.google.com/), which includes [FirebaseAuth](https://firebase.google.com/docs/auth?hl=en), [FirebaseStorage](https://firebase.google.com/docs/storage?hl=en), and [Cloud Firestore](https://firebase.google.com/docs/firestore?hl=en), to securely store your data. This means that no one can access your data, not even us. We cannot see any of your personal data, such as created documents or cloud services. The only thing we can see is how many people have a ScribbleLab account. Furthermore we use Additionally, we use [Google Analytics](https://developers.google.com/analytics?hl=en) and [Google Crashlytics](https://firebase.google.com/docs/crashlytics?hl=en) to track crashes and other unusual events or bugs. > Developer note: -> +> It is not permissible for you to alter any authentication code unless you have been explicitly authorized to do so. If you do so we'll close your PR accordingly ⛔️. Ensuring the security of our software is a top priority for us, we regularly release software updates that include bug fixes and security patches to keep your data and system secure. It is important to install these updates as soon as they become available to ensure that @@ -80,10 +80,23 @@ instructions carefully to ensure a smooth update process. Remember, staying up to date with software updates is an essential part of maintaining the security and integrity of your system. > Note: -> No warranty is provided for testing Alpha, Beta, nightly, or RC builds. Use at your own risk. +> No warranty is provided for testing Alpha, Beta, nightly, or RC builds. Use at your own risk. You also need Xcode 15 installed and the iPadOS 17 Simualtor. +> ### Device Reccomendation +> We reccomend testing our App on those devices: +> | iPadOS | iOS | macOS| visionOS | +> | :----: | :--: | :--: | :----: | +> | iPad Pro 11 | iPhone 15 Pro | n/a | Apple Vision Pro | ## Topics +- +- + +### Application +- ``ScribbleLabApp`` +- ``ContentView`` +- ``SLAuthService`` +- ``LogInView`` +- ``SignUpView`` +- ``SLSideBarView`` -### Group -- ``Symbol`` diff --git a/ScribbleLab.xcodeproj/project.xcworkspace/xcuserdata/neviohirani.xcuserdatad/Bookmarks/bookmarks.plist b/ScribbleLab.xcodeproj/project.xcworkspace/xcuserdata/neviohirani.xcuserdatad/Bookmarks/bookmarks.plist index bc75ea3ca..9a15b11af 100644 --- a/ScribbleLab.xcodeproj/project.xcworkspace/xcuserdata/neviohirani.xcuserdatad/Bookmarks/bookmarks.plist +++ b/ScribbleLab.xcodeproj/project.xcworkspace/xcuserdata/neviohirani.xcuserdatad/Bookmarks/bookmarks.plist @@ -34,16 +34,16 @@ text-context focused - // .environmentObject(RegistrationViewModel()) + /// then call the declared isDarkMode argument. leading - .environmentObject(ContentViewModel()) -// SignUpView() + /// + /// To call the darkmode state add the @AppStorage property at the top in your Struct trailing - // .environmentObject(SignInWithGoogleModel()) - .preferredColorScheme(isDarkMode ? .dark : .light) - } + @AppStorage("isDarkMode") private var isDarkMode = false + + var body: some Scene { type @@ -98,16 +98,16 @@ text-context focused - ContentView() + /// - true: Dark mode is enabled leading - var body: some Scene { - WindowGroup { + /// Possible values: + /// - false: Dark mode isn't enabled trailing - .environmentObject(ContentViewModel()) -// SignUpView() -// .environmentObject(RegistrationViewModel()) + /// + /// To call the darkmode state add the @AppStorage property at the top in your Struct + /// then call the declared isDarkMode argument. title diff --git a/ScribbleLab/Ressources/Localizable.xcstrings b/ScribbleLab/Ressources/Localizable.xcstrings index d2ee7e15d..7d896ea1a 100644 --- a/ScribbleLab/Ressources/Localizable.xcstrings +++ b/ScribbleLab/Ressources/Localizable.xcstrings @@ -57,10 +57,23 @@ } }, "[Terms of Use](https://github.com/ScribbleLabApp/ScribbleLab/blob/main/LICENSE_AGREEMENT.md)" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "[Terms of Use](https://github.com/ScribbleLabApp/ScribbleLab/blob/main/LICENSE_AGREEMENT.md)" + } + } + } }, "%lld %@" : { "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld%2$@" + } + }, "en" : { "stringUnit" : { "state" : "new", @@ -70,13 +83,34 @@ } }, "%lld hr" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld hr" + } + } + } }, "%lld min" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld min" + } + } + } }, "%lld sec" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld sec" + } + } + } }, "© 2023 - 2024 ScribbleLabApp. All rights reserved." : { "localizations" : { @@ -89,7 +123,14 @@ } }, "1. Definitions." : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Definition" + } + } + } }, "2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form." : { @@ -181,13 +222,27 @@ }, "Bottom %@" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "" + } + } + } }, "Build Number" : { }, "Build sha" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Build sha" + } + } + } }, "By continuing I agree with ScribbleLabApp's " : { @@ -231,13 +286,27 @@ }, "Confirm" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Bestätigen" + } + } + } }, "Continue with Apple" : { }, "Continue with Google" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mit Google fortahren" + } + } + } }, "Contributors" : { @@ -258,16 +327,44 @@ }, "Dangerzone" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gefahrenzone" + } + } + } }, "Darkmode" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dunkelmodus" + } + } + } }, "Darkmode (BETA)" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dunkelmodus (BETA)" + } + } + } }, "Darkmode settings" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dunkelmodus Einstellungen" + } + } + } }, "Delete account" : { @@ -531,22 +628,50 @@ }, "Item at %@" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Item ar %@" + } + } + } }, "Kickstart your note-taking experience" : { }, "L" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "L" + } + } + } }, "Language" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sprache" + } + } + } }, "Leading" : { }, "License" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lizenz" + } + } + } }, "LICENSE AGREEMENT" : { @@ -555,16 +680,37 @@ }, "Licenses" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lizenzen" + } + } + } }, "Locations" : { }, "Log In" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anmelden" + } + } + } }, "Log in with email" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mit Email anmelden" + } + } + } }, "Login" : { "extractionState" : "stale", @@ -584,10 +730,24 @@ }, "n/a" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "n/a" + } + } + } }, "Next" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Weiter" + } + } + } }, "No" : { @@ -640,7 +800,14 @@ } }, "Other" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Andere" + } + } + } }, "Pinned" : { @@ -682,7 +849,14 @@ } }, "Q&A" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Q&A" + } + } + } }, "Recently opened" : { @@ -776,7 +950,14 @@ }, "Store" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Store" + } + } + } }, "Study Timer" : { "localizations" : { @@ -789,7 +970,14 @@ } }, "T %@" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "T %@" + } + } + } }, "Tab on a gift code to redeem it" : { @@ -857,7 +1045,14 @@ }, "Trash" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Papierkorb" + } + } + } }, "Units" : { "localizations" : { @@ -930,7 +1125,20 @@ } }, "Warning" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Warnung" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attentione" + } + } + } }, "We are currently working on it. Please check out this module later." : { @@ -964,6 +1172,12 @@ "state" : "translated", "value" : "Wilkommen zu ScribbleLab, %@" } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benvenuto a ScribbleLab, %@" + } } } }, @@ -977,10 +1191,24 @@ }, "Yellow" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gelb" + } + } + } }, "Yes" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ja" + } + } + } }, "You have no unread notifications" : {