diff --git a/.circleci/config.yml b/.circleci/config.yml index 232d659c..a39a3d94 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,17 @@ commands: name: Danger check command: bundle exec danger <> --verbose --remove-previous-comments + move_directory: + parameters: + from: + description: directory to move + type: string + to: + description: destination directory + type: string + steps: + - run: cp -R <> <> + jobs: assemble: executor: android-executor @@ -155,6 +166,31 @@ jobs: - store_artifacts: path: /Users/distiller/test-results/ + android-sdk-size-report: + executor: android-executor + + steps: + - checkout + - android/restore-build-cache + - android/restore-gradle-cache + - ruby/install-deps + - run: + name: Android SDK size report + command: ./gradlew generateSizeReport + - store_artifacts: + path: "shared/build/outputs/sizeReport" + destination: sizeReport + - run: mkdir -p builds + - move_directory: + from: shared/build/outputs/sizeReport/ + to: builds + - danger-check: + danger_params: --danger_id=android_sdk_report --dangerfile=dangerfiles/dangerfile_android_sdk_size_report + - persist_to_workspace: + root: *workspace + paths: + - builds + ios-generate-framework: executor: mac-os-executor @@ -197,6 +233,9 @@ workflows: - lint-check: requires: - assemble + - android-sdk-size-report: + requires: + - assemble - detekt-check: requires: - assemble diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..7c4e4399 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +#These people are listed as being the code owners for this project. As such, they will be automatically added as a reviewer when a PR is created. +#For more details on how this is configured, see https://help.github.com/articles/about-code-owners/ + +* @twilio/accsec-apps-sdks diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..51a23426 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,161 @@ +# Contributing to `twilio-verify-passkeys` + +Thank you for your interest in contributing to `twilio-verify-passkeys`. We appreciate your help in making it better. Please take a moment to review these guidelines before getting started. + +- [Branches](#branches) +- [Code of Conduct](#code-of-conduct) +- [Question or Problem?](#question-or-problem) +- [Issues and Bugs](#issues-and-bugs) +- [Feature Requests](#feature-requests) +- [Documentation Fixes](#documentation-fixes) +- [Submission Guidelines](#submission-guidelines) +- [Coding Rules](#coding-rules) +- [License](#license) + +## Branches + +- **`main`**: The `main` branch is the stable branch containing production-ready code. It should always reflect the latest release. +- **`dev`**: The `dev` branch is where all new features and changes should be directed. This branch might contain work-in-progress code. +- Any other branch contains code with new features or improvements that are waiting to be merged into the `dev` branch. + +## Code of Conduct + +Help us keep `twilio-verify-passkeys` open and inclusive. Please be kind to and considerate of other developers, as we all have the same goal: make `twilio-verify-passkeys` as good as it can be. +By interacting with the project in any shape or form you are agreeing to the project's [Code of Conduct](https://github.com/twilio/twilio-verify-passkeys?tab=coc-ov-file). If you feel like another individual has violated the code of conduct, please raise a complaint to [open-source@twilio.com](mailto:open-source@twilio.com). + +## Question or Problem? + +If you have questions about how to use `twilio-verify-passkeys`, please see our [docs](../README.md), and if you don't find the answer there, please contact [Twilio Support](https://www.twilio.com/help/contact) with any issues you have. + +## Issues and Bugs + +If you find a bug in the source code or a mistake in the documentation, you can help us by submitting [an issue][issue-link]. + +**Please see the [Submission Guidelines](#submission-guidelines) below.** + +## Feature Requests + +You can request a new feature by submitting an issue to our [GitHub Repository][github]. If you would like to implement a new feature then consider what kind of change it is: + +* **Major Changes** that you wish to contribute to the project should be + discussed first with `twilio-verify-passkeys` contributors in an issue or pull request so + that we can develop a proper solution and better coordinate our efforts, + prevent duplication of work, and help you to craft the change so that it is + successfully accepted into the project. +* **Small Changes** can be crafted and submitted to the + [GitHub Repository][github] as a Pull Request. + +## Documentation Fixes + +If you want to help improve the documentation, it's a good idea to +let others know what you're working on to minimize duplication of effort. Create +a new issue (or comment on a related existing one) to let others know what +you're working on. + +For large fixes, please build and test the documentation before submitting the +PR to be sure you haven't accidentally introduced layout or formatting issues. + +## Submission Guidelines + +### Submitting an Issue +Before you submit your issue search the archive, maybe your question was already +answered. + +If your issue appears to be a bug, and hasn't been reported, open a new issue. +Help us to maximize the effort we can spend fixing issues and adding new +features by not reporting duplicate issues. Providing the following information +will increase the chances of your issue being dealt with quickly: + +* **Overview of the Issue** - if an error is being thrown a non-minified stack + trace helps +* **Motivation for or Use Case** - explain why this is a bug for you +* **`twilio-verify-passkeys` Version(s)** - is it a regression? +* **Operating System** - is this a problem with all systems or + only specific ones? +* **Reproduce the Error** - provide an isolated code snippet or an unambiguous + set of steps. +* **Related Issues** - has a similar issue been reported before? +* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point + to what might be causing the problem (line of code or commit) + +**If you get help, help others. Good karma rules!** + +### Submitting a Pull Request +Before you submit your pull request consider the following guidelines: + +* Search [GitHub][github] for an open or closed Pull Request that relates to + your submission. You don't want to duplicate effort. +* Make your changes in a new git branch from `dev` branch: + + ```bash + git checkout -b my-fix-branch dev + ``` + +* Create your patch, **including appropriate test cases**. +* Follow our [Coding Rules](#coding-rules). +* Commit your changes using a descriptive commit message. + We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification for our commit messages. Please ensure your commits adhere to this convention to maintain a clean and structured commit history. + + ```bash + git commit -a + ``` + Note: the optional commit `-a` command line option will automatically "add" + and "rm" edited files. + +* Build your changes locally to ensure all the tests pass: + + ```bash + ./gradlew :shared:iosSimulatorArm64Test :shared:testDebugUnitTest + ``` + +* Make sure you're following the code convention: + + * **Ktlint** + We use [ktlint](https://ktlint.github.io/) for enforcing Kotlin coding standards. Before submitting a pull request, please ensure your code complies with ktlint rules. You can run ktlint locally with: + + ```bash + ./gradlew ktlintCheck + ``` + + * **Detekt** + We use [Detekt](https://detekt.dev/) for static code analysis and enforcing coding standards. Please ensure your code passes Detekt checks before submitting a pull request. You can run Detekt locally with: + + ```bash + ./gradlew detekt + ``` + +* Push your branch to GitHub: + + ```bash + git push origin my-fix-branch + ``` + +In GitHub, send a pull request to `twilio-verify-passkeys:dev`. +If we suggest changes, then: + +* Make the required updates. +* Re-run the `twilio-verify-passkeys` test suite to ensure tests are still passing. +* Commit your changes to your branch (e.g. `my-fix-branch`). +* Push the changes to your GitHub repository (this will update your Pull Request). + +That's it! Thank you for your contribution! + +#### After your pull request is merged + +After your pull request is merged, you can safely delete your branch and pull +the changes from the main (upstream) repository. + +## Coding Rules + +To ensure consistency throughout the source code, keep these rules in mind as +you are working: + +* All features or bug fixes **must be tested** by one or more tests. +* All classes and methods **must be documented**. +* All classes must follow the code convention + +## License +All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project provided under. + +[issue-link]: https://github.com/twilio/twilio-verify-passkeys/issues/new +[github]: https://github.com/twilio/twilio-verify-passkeys diff --git a/.github/ISSUE_TEMPLATE/bug_report_template.md b/.github/ISSUE_TEMPLATE/bug_report_template.md new file mode 100644 index 00000000..296c6994 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_template.md @@ -0,0 +1,32 @@ +--- +name: Bug Report +about: Use this template for reporting a bug +labels: 'type:bug' + +--- + +Before you submit your issue search the archive, maybe your question was already addressed [existing issues](https://github.com/twilio/twilio-verify-passkeys/issues). +Please do not share any [Personally Identifiable Information](https://www.twilio.com/docs/glossary/what-is-personally-identifiable-information-pii) or sensitive information like API keys when creating an issue. + + +### Issue Summary +A summary of the issue and the environment in which it occurs. If suitable, include the steps required to reproduce the bug. Please feel free to include screenshots, screencasts, or code examples. + +### Steps to Reproduce +1. This is the first step +2. This is the second step +3. Further steps, etc. + +### Code Snippet +```kotlin +// paste code here +``` + +### Exception/Log +``` +# paste exception/log here +``` + +### Technical details: +* `twilio-verify-passkeys` version: +* OS specification: diff --git a/.github/ISSUE_TEMPLATE/feature_request_template.md b/.github/ISSUE_TEMPLATE/feature_request_template.md new file mode 100644 index 00000000..2a93b89f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request_template.md @@ -0,0 +1,18 @@ +--- +name: Feature Request +about: Use this template for raising a feature request +labels: 'type:feature' + +--- + +Before you submit your feature request search the archive, maybe your question was already addressed [existing issues](https://github.com/twilio/twilio-verify-passkeys/issues). +Please do not share any [Personally Identifiable Information](https://www.twilio.com/docs/glossary/what-is-personally-identifiable-information-pii) or sensitive information like API keys when creating a feature request. + +#### Feature Summary +A summary of the new feature you'd like to be implemented + +#### Solution You Would Like +What you want to happen + +#### Alternatives You Considered +Solutions or features you considered diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..8dd5d78b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,28 @@ + + + + + + +## Ticket +- [#####] + +## Github Issue +- ISSUE- + + +## Description +- + + +## Commit message +- + + +## Screenshot + + +## Testing +- [ ] Added unit tests +- [ ] Ran unit tests successfully +- [ ] Added documentation for public APIs and/or Wiki diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/LoginViewModel.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/LoginViewModel.kt deleted file mode 100644 index 95f5331e..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/LoginViewModel.kt +++ /dev/null @@ -1,156 +0,0 @@ -package com.twilio.passkeys.android - -import android.app.Activity -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.twilio.passkeys.AppContext -import com.twilio.passkeys.AuthenticatePasskeyResult -import com.twilio.passkeys.CreatePasskeyResult -import com.twilio.passkeys.TwilioPasskey -import com.twilio.passkeys.android.model.RegistrationStartResponse -import com.twilio.passkeys.android.repository.AuthenticateRepository -import com.twilio.passkeys.android.repository.CreateRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow -import kotlinx.coroutines.launch -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import javax.inject.Inject - -@HiltViewModel -class LoginViewModel -@Inject -constructor( - private val twilioPasskey: TwilioPasskey, - private val authenticateRepository: AuthenticateRepository, - private val createRepository: CreateRepository, -) : ViewModel() { - private val _state: MutableSharedFlow = - MutableSharedFlow( - replay = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) - val state = _state.asSharedFlow() - - fun create( - username: String, - activity: Activity, - ) { - viewModelScope.launch { - try { - val registrationStartResponse: RegistrationStartResponse = - createRepository.start( - username, - ) - val json = - Json { - encodeDefaults = true - ignoreUnknownKeys = true - explicitNulls = false - } - val challengePayload = json.encodeToString(registrationStartResponse) - when (val createPasskeyResult = twilioPasskey.create(challengePayload, AppContext(activity))) { - is CreatePasskeyResult.Error -> { - setErrorState(createPasskeyResult.error.message.toString()) - } - - is CreatePasskeyResult.Success -> { - try { - createRepository.verification( - rawId = createPasskeyResult.createPasskeyResponse.rawId, - id = createPasskeyResult.createPasskeyResponse.id, - clientDataJson = createPasskeyResult.createPasskeyResponse.clientDataJSON, - attestationObject = createPasskeyResult.createPasskeyResponse.attestationObject, - type = createPasskeyResult.createPasskeyResponse.type, - transports = createPasskeyResult.createPasskeyResponse.transports, - ) - _state.emit(LoginState.PasskeySuccess(username)) - } catch (e: Exception) { - setErrorState(e.message.toString()) - } - } - } - } catch (e: Exception) { - setErrorState(e.message.toString()) - } - } - } - - fun authenticate(activity: Activity) { - viewModelScope.launch { - try { - val authenticationStartResponse = authenticateRepository.start() - val json = Json { encodeDefaults = true } - val challengePayload = json.encodeToString(authenticationStartResponse) - when (val authenticatePasskeyResult = twilioPasskey.authenticate(challengePayload, AppContext(activity))) { - is AuthenticatePasskeyResult.Error -> { - - setErrorState( - authenticatePasskeyResult.error.message, - ) - } - - is AuthenticatePasskeyResult.Success -> { - try { - val response = - authenticatePasskeyResult.authenticatePasskeyResponse - authenticateRepository.verification( - rawId = response.rawId, - id = response.id, - clientDataJson = response.clientDataJSON, - userHandle = response.userHandle, - signature = response.signature, - authenticatorData = response.authenticatorData, - ) - _state.emit( - LoginState.PasskeySuccess( - "test", - ), - ) - } catch (e: Exception) { - setErrorState(e.message.toString()) - } - } - } - } catch (e: Exception) { - setErrorState(e.message.toString()) - } - } - } - - fun logout() { - viewModelScope.launch { - _state.emit(LoginState.Logout) - } - } - - fun areFieldsValid(phoneNumber: String): Boolean { - if (!android.util.Patterns.PHONE.matcher(phoneNumber).matches()) { - _state.tryEmit(LoginState.NumberError) - return false - } - return true - } - - private fun setErrorState(message: String) { - _state.tryEmit( - LoginState.PasskeyError( - message, - ), - ) - } -} - -sealed interface LoginState { - data object Initial : LoginState - - data object NumberError : LoginState - - data object Logout : LoginState - - data class PasskeySuccess(val number: String) : LoginState - - data class PasskeyError(val message: String) : LoginState -} diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/PasskeyApp.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/PasskeyApp.kt deleted file mode 100644 index c1885ce3..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/PasskeyApp.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.twilio.passkeys.android - -import android.app.Application -import dagger.hilt.android.HiltAndroidApp - -@HiltAndroidApp -class PasskeyApp : Application() diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateStartResponse.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateStartResponse.kt deleted file mode 100644 index d093cbe4..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateStartResponse.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.twilio.passkeys.android.model - -import kotlinx.serialization.Serializable - -@Serializable -data class AuthenticateStartResponse( - val publicKey: PublicKeyCredential, -) - -@Serializable -data class PublicKeyCredential( - val challenge: String, - val timeout: Int, - val rpId: String, - val allowCredentials: List, - val userVerification: String, -) - -@Serializable -data class AllowCredential( - val id: String, - val type: String, - val transports: List, -) diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateVerificationResponse.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateVerificationResponse.kt deleted file mode 100644 index e690b1aa..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/AuthenticateVerificationResponse.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.twilio.passkeys.android.model - -import kotlinx.serialization.Serializable - -@Serializable -data class AuthenticateVerificationResponse(val status: String) diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationStartResponse.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationStartResponse.kt deleted file mode 100644 index 7c4acd46..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationStartResponse.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.twilio.passkeys.android.model - -import kotlinx.serialization.Serializable - -@Serializable -data class RegistrationStartResponse( - val rp: RP, - val user: User, - val challenge: String, - val pubKeyCredParams: List, - val timeout: Int, - val excludeCredentials: List, - val authenticatorSelection: AuthenticatorSelection, - val attestation: String, -) - -@Serializable -data class RP( - val id: String, - val name: String, -) - -@Serializable -data class User( - val id: String, - val name: String, - val displayName: String?, -) - -@Serializable -data class PublicKeyCredentialParam( - val type: String, - val alg: Int, -) - -@Serializable -data class ExcludeCredential( - val id: String, - val type: String, - val transports: List, -) - -@Serializable -data class AuthenticatorSelection( - val authenticatorAttachment: String, - val requireResidentKey: Boolean, - val residentKey: String, - val userVerification: String, -) diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationVerificationResponse.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationVerificationResponse.kt deleted file mode 100644 index 8dde93e7..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/model/RegistrationVerificationResponse.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.twilio.passkeys.android.model - -import kotlinx.serialization.Serializable - -@Serializable -data class RegistrationVerificationResponse(val status: String) diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/Color.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/Color.kt deleted file mode 100644 index 48babff5..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/Color.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.twilio.passkeys.android.ui - -import androidx.compose.ui.graphics.Color - -val twilio = Color(0xFFF22F46) -val button_color = Color(0xFF0263E0) -val blue = Color(0xFF0263E0) diff --git a/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/MyApplicationTheme.kt b/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/MyApplicationTheme.kt deleted file mode 100644 index 1361a6a7..00000000 --- a/AndroidApp/src/main/java/com/twilio/passkeys/android/ui/MyApplicationTheme.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.twilio.passkeys.android.ui - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable - -@Suppress("FunctionName") -@Composable -fun MyApplicationTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - content: @Composable () -> Unit, -) { - MaterialTheme(content = content) -} diff --git a/AndroidApp/src/main/res/drawable/ic_launcher_background.xml b/AndroidApp/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index e477184d..00000000 --- a/AndroidApp/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 7353dbd1..00000000 --- a/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7353dbd1..00000000 --- a/AndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/AndroidApp/src/main/res/values/ic_launcher_background.xml b/AndroidApp/src/main/res/values/ic_launcher_background.xml deleted file mode 100644 index 0f55997d..00000000 --- a/AndroidApp/src/main/res/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #0878FF - \ No newline at end of file diff --git a/AndroidApp/src/main/res/values/strings.xml b/AndroidApp/src/main/res/values/strings.xml deleted file mode 100644 index d67614ee..00000000 --- a/AndroidApp/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - PasskeysDemo - diff --git a/AndroidApp/src/main/res/values/styles.xml b/AndroidApp/src/main/res/values/styles.xml deleted file mode 100644 index 6b4fa3d0..00000000 --- a/AndroidApp/src/main/res/values/styles.xml +++ /dev/null @@ -1,3 +0,0 @@ - -