Skip to content

[MDS-6681] MineSpace User Access Login flow#3803

Merged
matbusby-fw merged 7 commits intodevelopfrom
mds-6681-ms-user-access
Jan 26, 2026
Merged

[MDS-6681] MineSpace User Access Login flow#3803
matbusby-fw merged 7 commits intodevelopfrom
mds-6681-ms-user-access

Conversation

@taraepp
Copy link
Contributor

@taraepp taraepp commented Jan 21, 2026

Objective

  • new landing page
  • new behaviour:
    • basically we are saving their access request form data in our database
    • handling keycloak calls ourselves
    • giving MS users roles within mines

More specific behaviour:
MS Landing Page

  • the "Join MineSpace" and "Log in with BCeID" actually do the same thing- direct you to log in with bceid. After you log in, it'll determine if you have any keycloak roles. If you have none, it'll direct you to "/access-request". Otherwise, you'll go to the same place you did before (I think My Mines? Anyway, it's unchanged)
  • if you try to navigate to access-request while not authenticated through BCeID, you'll get an authentication error
    (must be logged in and submit BCeID info in order to create request)

MS Access Request Form

  • there's a lot of required/optional depending on what role the user selects.
    • Permittee is not required to submit an authorization letter
    • Otherwise, user must submit auth letter or provide Permittee's contact info (they can do both)
    • Additionally, MineSpace Admin must submit Proof of Delegation Letter
    • selecting General Public/Researcher won't create any pending roles in the BE, and all of the same form requirements are still there (documents, must put in business name, mine numbers, agree to terms, etc).
  • documents have to be uploaded without user roles, and without a mine_guid, so there's some changes in the BE to accommodate this. They still require a BCeID though, and will get uploaded with the username pre-pended (doesn't show up anywhere on the FE though). Upload returns guid which then gets put in the form to be submitted
  • when the form is submitted:
    • it'll create a minespace_user_request record with the request_status of 0/pending
    • for each mine selected in the list, it'll create a pending user role. If they selected Permittee and mines A, B, and C, the result will be 3 pending user roles, each of them Permittee, one for each mine
    • a minespace_user record is also created. No minespace_user_mds_mine_acess though
    • user will be redirected to a confirmation that their request was submitted. They can't modify their request.

Core MineSpace Management

  • this page: http://localhost:3000/admin/dashboard/manage-minespace/users
  • table now has "Status" column which will show Approved/Pending/Rejected for each user (depending on access request- if there is no access request, record is assumed to be "legacy" and thus Approved)
  • DELETE (Actions): this is changed!
    • The minespace_user record is now soft deleted
    • their keycloak access is revoked
    • all mine access and user roles are also removed, if there's an access request, it'll be deleted too
    • a deleted user can go ahead and make another access request this is very helpful for testing FYI

Core: MineSpace User Access Modal Form

  • documents/delegation letter is combined on the same "documents" field (not expecting lots of documents, and should be able to distinguish them, so kept it simple in structure)
  • most of the form is read-only, it's intended to show what the user submitted
  • admin can make whatever changes they want- up until changing User Access Status to Approved, they will not have keycloak access and thus nothing will actually take effect
  • roles can be approved or deleted. If they're not deleted though, they can't be removed from the mine access list
  • new roles can be added manually. Manually added roles don't have a pending state, they're assumed to be approved. Mine access can also be added without a specific role
  • at this point, can't really change Access Status once it's been Approved or Rejected, may want to change this in the future. 😅
  • if the user is approved, they'll have appropriate MS roles, access to the mines in the Mine Access list, and any roles that have been approved
  • the roles don't do anything at this point, or show up anywhere
  • also no emails get sent out

MDS-6681

MS Landing page:
HEADER BAR: Note that this is a global change.

  • The menu when I am not logged in has the options of "Log in with BCeID" and "Join MineSpace"
  • when I am logged in, I have the option to log out, and it has my email address instead of "Menu" for text
  • it's gov-yellow on hover
  • the header is now a little bit shorter in height
image image

Logged in header bar:
image

MS Request Access Form:
image
image
image
image

After Submitting (will show after log out/in again as well):
image

Core MineSpace Users:

  • if user is "Rejected", it'll show a red dot.
  • for Pending users, the Last Login may not be accurate... it doesn't update after they submit the form. So it's really more of a "date of request"
image

Core: MineSpace User Access Modal Form
image
image
image

id={props.id ?? props.input.name}
onSearch={debouncedSearch}
options={data}
value={input.value === "" ? [] : input.value}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had weird issues with the mines not being pre-populated from the form values and had to make this change. In making this change, I had to manually apply the aria-required (a bunch of snapshot tests showed it being removed. Now it added in a few aria-required=false but I'm okay with that)

return user_emails

@staticmethod
def get_roles_by_user(username: str):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New functions can be used to handle any keycloak role management! If we wanted to give CORE users roles from within the app...

* CORE/IDIR users are authenticated programmatically when MineSpace mounts,
*/

export const AuthenticationGuard =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This file was really just typescripted. No effort made to improve it otherwise (probably wouldn't use window.location)

import * as Strings from "@mds/common/constants/strings";
import PropTypes from "prop-types";
// Uncomment when image is re-introduced
// import { MAP_LOGO } from "@/constants/assets";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There was a lot of stuff in this file that was basically half-implemented, in testing only functionality that was either commented out, or only available on test.
I removed all of that. If we want to implement logging in with verifiable credentials or whatever was going on with the commented out stuff, we'll do that properly.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a new self-service user access request flow for MineSpace, where BCeID users can submit access requests through a comprehensive form. The system saves access request data to the database and manages Keycloak role assignments. Key features include:

Changes:

  • New landing page with updated design and "Join MineSpace" functionality
  • Self-service access request form for new MineSpace users with authorization workflow
  • Backend API endpoints for managing user access requests and document uploads
  • Feature flag controlled rollout (MINESPACE_SIGNUP)

Reviewed changes

Copilot reviewed 90 out of 91 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
services/minespace-web/src/components/pages/MinespaceAccessRequest.tsx New access request form component with Terms of Use and Privacy Notice
services/minespace-web/src/components/pages/LandingPage.tsx Redesigned landing page with feature flag support for new signup flow
services/minespace-web/src/HOC/AuthenticationGuard.tsx Updated authentication logic to store user access data from Keycloak
services/document-manager/backend/app/docman/resources/document.py Added authorization bypass for minespace access request document uploads
services/core-web/src/components/admin/MinespaceUserAccessModal.tsx Admin interface for reviewing and approving access requests
services/core-api/tests/users/resources/test_new_minespace_user_resource.py Comprehensive test coverage for new API endpoints

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<Typography.Paragraph>Typical processing time: 5-10 business days</Typography.Paragraph>
<Typography.Paragraph strong>What you'll need:</Typography.Paragraph>
<ul>
<li>Your role and associated business name (as registered with Business BCeiD)</li>
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Spelling error: "BCeiD" should be "BCeID" (lowercase 'e') to match the official branding and other instances in the codebase.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it actually means that the "i" should be uppercase. 😅
Fixing


assert user is not None
assert user.bceid_username == bceid_username
assert user.deleted_ind == None
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Testing for None should use the 'is' operator.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

current_app.logger.info('Existing Mine: {}'.format(existing_minespace_user_mine))
if not existing_minespace_user_mine:
new_minespace_user_mine = MinespaceUserMine.create(user_id, mine.mine_guid)
new_minespace_user_mine = MinespaceUserMine.create(user_id, mine.mine_guid)
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Variable new_minespace_user_mine is not used.

Suggested change
new_minespace_user_mine = MinespaceUserMine.create(user_id, mine.mine_guid)
MinespaceUserMine.create(user_id, mine.mine_guid)

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

mine2 = MineFactory()

# complete permittee form submission with mines
request = MinespaceUserRequest.create_or_update_request(
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Variable request is not used.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

@@ -0,0 +1,164 @@
from datetime import datetime
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Import of 'datetime' is not used.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

@@ -0,0 +1,164 @@
from datetime import datetime
from pytz import utc
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

Import of 'utc' is not used.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed for 'bcgov-sonarcloud_mds_minespace-web'

Failed conditions
70.9% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed for 'bcgov-sonarcloud_mds_core-web'

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

See analysis details on SonarQube Cloud

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed for 'bcgov-sonarcloud_mds_core-api'

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

See analysis details on SonarQube Cloud

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed for 'bcgov-sonarcloud_mds_common'

Failed conditions
31.2% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@matbusby-fw matbusby-fw merged commit 31625f4 into develop Jan 26, 2026
17 of 22 checks passed
@matbusby-fw matbusby-fw deleted the mds-6681-ms-user-access branch January 26, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants