Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/association manager #302

Merged
merged 92 commits into from
Dec 20, 2024
Merged

Feat/association manager #302

merged 92 commits into from
Dec 20, 2024

Conversation

Aurelien9Code
Copy link
Contributor

@Aurelien9Code Aurelien9Code commented Dec 15, 2024

This PR aims to completely deploy the association permissions into the UI.
That means that the user is now able to :

  • Get automatically Owner role (so also Full Rights) by claiming the association presidential rights in the User Profile (three dots)
  • When having any role in an association, a cool layout shows your role in the association profile, in the color of your role badge
  • If you have a least one "important" permission in this association, the Association Profile is now divided in two pages : Overview - which is the screen seen by anyone who's not member of the association, and Actions - which allows you to complete actions on the association according to your permissions
  • In Actions the user can create, edit and delete an event - this event is automatically updated in the viewModels so that we can see the changes instantly without force fetched.
  • In Actions the user can create, edit and add roles - try changing the color ; )
  • In Actions the user will be able to map members to their roles [TO BE IMPLEMENTED]

Cool implementations :

  • When creating/editing a role, I thought a Color Picker is better than giving a HEX code or a Long. I found this superb Color Picker on github by SkyDoves - it's even compatible with Kotlin Multiplatform ! Good to know when we'll want to implement Swift.

  • Now Roles are only in the Association.roles and not copied in Association.members.role to avoid differences in the memory and better data optimization

Security measures :

  • Create and editing an association is now managed by cloud functions. That means that you don't directly perform the operations to the db - you just call a cloud function to check your permissions (and by that I mean the permissions of your roles) and proceed if you have at least "Add & Edit Association"

  • Cloud functions are now more safe : before, to know who's calling the function the userId was given as a string parameter. This is a dangerous security hole : as the uid of the users in the db is the same as the one visible in the Association dataclass, that means that everyone can know the uid of his comrade and thus give it the the cloud function instead of its own. Now, your userID is tokenized (only an authentificated user can have its own token) and then send to the cloud function which detokenize it to fall back on the userUid : ) If you think this is not the best way to proceed, maybe first read the documentation, it's right here - other possibilities are explained here.

If your Firebase client app communicates with a custom backend server, you might need to identify the currently signed-in user on that server. To do so securely, after a successful sign-in, send the user's ID token to your server using HTTPS. Then, on the server, verify the integrity and authenticity of the ID token and retrieve the uid from it. You can use the uid transmitted in this way to securely identify the currently signed-in user on your server.

Fixes :

  • The force fetch had some problems with my new implementation, now it works perfectly in both Overview and Actions page

Questions :

  • In the saveEvent cloud function you might ask why I send the Firebase Timestamp as a string. It's because there's no way to pass it via a json Object which is the type used for the parameters of the cloud functions. So the solution is to format all the informations in a string in Kotlin and then rebuild the Timestamp in javascript.

@Aurelien9Code Aurelien9Code self-assigned this Dec 15, 2024
…odel to add a Role locally to reduce fetches from the database
@Aurelien9Code
Copy link
Contributor Author

Thanks again for your review Oskar ! I implemented everything you asked ; )

@Aurelien9Code Aurelien9Code marked this pull request as ready for review December 20, 2024 05:12
Copy link
Collaborator

@armouldr armouldr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work, you achieved remarkable code quality given the size of this PR !

Comment on lines +119 to +121
# waiting for Arnaud's PR, temporarily commenting this
#- name: Run Node tests with Firestore and Storage emulators
# run: firebase emulators:exec --only firestore,storage 'npm run test'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to uncomment this as soon as we have merged my PR :)

Comment on lines +520 to +533
composeTestRule.waitUntil(10000) {
composeTestRule.onNodeWithTag(AssociationProfileTestTags.ACTIONS_PAGE).isDisplayed()
}
composeTestRule.onNodeWithTag(AssociationProfileTestTags.ACTIONS_PAGE).performClick()

composeTestRule.waitUntil(10000) {
composeTestRule
.onNodeWithTag(AssociationProfileActionsTestTags.ADD_EVENT_BUTTON)
.isDisplayed()
}

composeTestRule
.onNodeWithTag(AssociationProfileActionsTestTags.ADD_EVENT_BUTTON)
.assertIsDisplayed()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basic testing but it ensures that everything is well displayed.

@@ -199,14 +199,11 @@ class AccountDetailsTest : TearDown() {
.onNodeWithTag(SocialsOverlayTestTags.SAVE_BUTTON)
.performScrollTo()
.performClick()
Thread.sleep(20000)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this was for test reasons, tell me if I'm wrong

Comment on lines +172 to +205
fun testEventCardElementsExistEdit() {
setEventViewModel(listOf(sampleEvent))
setEventScreen(sampleEvent, true)

Thread.sleep(10000)
composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_TITLE, useUnmergedTree = true)
.assertExists()
.assertTextEquals("Sample Event")

composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_MAIN_TYPE, useUnmergedTree = true)
.assertExists()
.assertTextEquals("Trip")

composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_LOCATION, useUnmergedTree = true)
.assertExists()
.assertTextEquals("Sample Location")

composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_DATE, useUnmergedTree = true)
.assertExists()
.assertTextEquals("20/07")

composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_TIME, useUnmergedTree = true)
.assertExists()
.assertTextEquals("00:00")

composeTestRule
.onNodeWithTag(EventCardTestTags.EVENT_CATCHY_DESCRIPTION, useUnmergedTree = true)
.assertExists()
.assertTextEquals("This is a catchy description.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to add tests to some old code and not only to the new one ! 🚀

@@ -193,6 +193,7 @@ class EventDetailsTest : TearDown() {
composeTestRule
.onNodeWithTag(EventDetailsTestTags.SHARE_BUTTON)
.assertDisplayComponentInScroll()
Thread.sleep(20000)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, this seems like debug instruction

}

Row(
modifier = Modifier.fillMaxWidth().padding(vertical = 0.dp),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null padding

*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T> SearchBar(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesnt seem to be used anywhere :(

Comment on lines +24 to +31
*
* @param T The type of the entity (e.g., Event, Member, Association).
* @param items The list of items to display in the pager.
* @param searchViewModel The view model handling the search logic.
* @param onItemSelected Callback when an item is selected from search results.
* @param cardContent A composable lambda that defines how to render each pager content.
* @param title The title displayed above the section.
* @param searchBar Composable function for rendering the search bar.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadoc to update

// Sliding Progress Bar (if more than one item exists)
if (items.size > 1) {
// Search Bar Composable
// Box(modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp)) { searchBar() }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented code

Box(
modifier =
Modifier.fillMaxSize().drawBehind {
val totalWidth = sizeList.values.map { it.first }.sum()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused variable

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
68.83% Line Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@Aurelien9Code Aurelien9Code merged commit fbe54e8 into main Dec 20, 2024
2 of 3 checks passed
@Aurelien9Code Aurelien9Code deleted the feat/association-manager branch December 20, 2024 07:48
@Aurelien9Code Aurelien9Code linked an issue Dec 20, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants