-
Notifications
You must be signed in to change notification settings - Fork 173
Introduce User Sharing API v2 #1044
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
Open
BimsaraBodaragama
wants to merge
28
commits into
wso2:master
Choose a base branch
from
BimsaraBodaragama:user-sharing-v2
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
2b99e3d
Introducing User Sharing APIs V2
BimsaraBodaragama 6658088
Update the year of the license header in gen files.
BimsaraBodaragama 95120a2
Update API contract - Remove immediate support from general share.
BimsaraBodaragama 10deb85
Comment openapi-generator-plugin.
BimsaraBodaragama 6a3c072
Implement the api core logic.
BimsaraBodaragama 2545e70
Add debug logs to the starting of each end points.
BimsaraBodaragama a3b625b
Update snapshot version of user sharing v2
BimsaraBodaragama 381eb80
Address wso2-engineering bot comments.
BimsaraBodaragama 533154f
Format.
BimsaraBodaragama b6bdeef
Address comments of copilot
BimsaraBodaragama 18f4dc9
Update pom.
BimsaraBodaragama 795deca
Update pom version.
BimsaraBodaragama e8db4ea
Address code-rabbit comments.
BimsaraBodaragama 64a0a4c
Address code-rabbit comments -2.
BimsaraBodaragama 1bc3ef4
Address code-rabbit comments -3.
BimsaraBodaragama 2ddaf94
Address code-rabbit comments -4.
BimsaraBodaragama 936483d
Address code-rabbit comments -5.
BimsaraBodaragama a848cd5
Address code-rabbit comments -6.
BimsaraBodaragama b4b2dd4
Address code-rabbit comments -7.
BimsaraBodaragama 512480a
Address code-rabbit comments -8.
BimsaraBodaragama d8c4bf5
Address code-rabbit comments -9.
BimsaraBodaragama 693f836
Merge branch 'master' into user-sharing-v2
BimsaraBodaragama 270811b
Updating getUserSharedOrganizations business logic to handle pagination.
BimsaraBodaragama 250a505
Merge remote-tracking branch 'origin/user-sharing-v2' into user-shari…
BimsaraBodaragama d66d784
Update pom version and checkstyle.
BimsaraBodaragama 2573650
Update pom version and address coderabbit's suggestions.
BimsaraBodaragama c15bab8
Add organization metadata fields to UserSharedOrganization response m…
BimsaraBodaragama 6f8510d
Bug fixing - 1
BimsaraBodaragama File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
173 changes: 173 additions & 0 deletions
173
...ement/org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2/pom.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!-- | ||
| ~ Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||
| ~ | ||
| ~ WSO2 LLC. licenses this file to you under the Apache License, | ||
| ~ Version 2.0 (the "License"); you may not use this file except | ||
| ~ in compliance with the License. | ||
| ~ You may obtain a copy of the License at | ||
| ~ | ||
| ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
| ~ | ||
| ~ Unless required by applicable law or agreed to in writing, | ||
| ~ software distributed under the License is distributed on an | ||
| ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| ~ KIND, either express or implied. See the License for the | ||
| ~ specific language governing permissions and limitations | ||
| ~ under the License. | ||
| --> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.organization.user.sharing.management</artifactId> | ||
| <version>1.3.226-SNAPSHOT</version> | ||
| <relativePath>../pom.xml</relativePath> | ||
| </parent> | ||
|
|
||
| <artifactId>org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2</artifactId> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>javax.ws.rs</groupId> | ||
| <artifactId>javax.ws.rs-api</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.jaxrs</groupId> | ||
| <artifactId>jackson-jaxrs-json-provider</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.cxf</groupId> | ||
| <artifactId>cxf-rt-frontend-jaxrs</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.cxf</groupId> | ||
| <artifactId>cxf-rt-rs-service-description</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.swagger</groupId> | ||
| <artifactId>swagger-jaxrs</artifactId> | ||
| <exclusions> | ||
| <exclusion> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-databind</artifactId> | ||
| </exclusion> | ||
| <exclusion> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-annotations</artifactId> | ||
| </exclusion> | ||
| <exclusion> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-core</artifactId> | ||
| </exclusion> | ||
| <exclusion> | ||
| <groupId>com.fasterxml.jackson.dataformat</groupId> | ||
| <artifactId>jackson-dataformat-yaml</artifactId> | ||
| </exclusion> | ||
| <exclusion> | ||
| <groupId>javax.ws.rs</groupId> | ||
| <artifactId>jsr311-api</artifactId> | ||
| </exclusion> | ||
| <exclusion> | ||
| <groupId>com.google.guava</groupId> | ||
| <artifactId>guava</artifactId> | ||
| </exclusion> | ||
| </exclusions> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.organization.user.sharing.management.common</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.common</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.organization.management</groupId> | ||
| <artifactId>org.wso2.carbon.identity.organization.management.organization.user.sharing</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.organization.management</groupId> | ||
| <artifactId>org.wso2.carbon.identity.organization.resource.sharing.policy.management</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| </dependencies> | ||
| <build> | ||
| <plugins> | ||
| <!--<plugin> | ||
| <groupId>org.openapitools</groupId> | ||
| <artifactId>openapi-generator-maven-plugin</artifactId> | ||
| <version>4.1.2</version> | ||
| <executions> | ||
| <execution> | ||
| <goals> | ||
| <goal>generate</goal> | ||
| </goals> | ||
| <configuration> | ||
| <inputSpec>${project.basedir}/src/main/resources/organization-user-share-v2.yaml</inputSpec> | ||
| <generatorName>org.wso2.carbon.codegen.CxfWso2Generator</generatorName> | ||
| <configOptions> | ||
| <sourceFolder>src/gen/java</sourceFolder> | ||
| <apiPackage>org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2</apiPackage> | ||
| <modelPackage>org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model</modelPackage> | ||
| <packageName>org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2</packageName> | ||
| <dateLibrary>java8</dateLibrary> | ||
| <hideGenerationTimestamp>true</hideGenerationTimestamp> | ||
| </configOptions> | ||
| <output>.</output> | ||
| <skipOverwrite>false</skipOverwrite> | ||
| </configuration> | ||
| </execution> | ||
| </executions> | ||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.openapitools</groupId> | ||
| <artifactId>cxf-wso2-openapi-generator</artifactId> | ||
| <version>1.0.0</version> | ||
| </dependency> | ||
| </dependencies> | ||
| </plugin>--> | ||
| <plugin> | ||
| <groupId>org.codehaus.mojo</groupId> | ||
| <artifactId>build-helper-maven-plugin</artifactId> | ||
| <version>1.8</version> | ||
| <executions> | ||
| <execution> | ||
| <id>add-source</id> | ||
| <phase>generate-sources</phase> | ||
| <goals> | ||
| <goal>add-source</goal> | ||
| </goals> | ||
| <configuration> | ||
| <sources> | ||
| <source>src/gen/java</source> | ||
| </sources> | ||
| </configuration> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>${maven.compiler.plugin.version}</version> | ||
| <configuration> | ||
| <source>1.8</source> | ||
| <target>1.8</target> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
|
|
||
| <properties> | ||
| <maven.compiler.source>8</maven.compiler.source> | ||
| <maven.compiler.target>8</maven.compiler.target> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
| </project> |
183 changes: 183 additions & 0 deletions
183
...org/wso2/carbon/identity/api/server/organization/user/sharing/management/v2/UsersApi.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| /* | ||
| * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). | ||
BimsaraBodaragama marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * | ||
| * WSO2 LLC. licenses this file to you under the Apache License, | ||
| * Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| package org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2; | ||
|
|
||
| import org.apache.cxf.jaxrs.ext.multipart.Attachment; | ||
| import org.apache.cxf.jaxrs.ext.multipart.Multipart; | ||
| import java.io.InputStream; | ||
| import java.util.List; | ||
|
|
||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.factories.UsersApiServiceFactory; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.Error; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.ProcessSuccessResponse; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserShareAllRequestBody; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserShareSelectedRequestBody; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserSharedOrganizationsResponse; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserSharingPatchRequest; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserUnshareAllRequestBody; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.model.UserUnshareSelectedRequestBody; | ||
| import org.wso2.carbon.identity.api.server.organization.user.sharing.management.v2.UsersApiService; | ||
|
|
||
| import javax.validation.Valid; | ||
| import javax.ws.rs.*; | ||
| import javax.ws.rs.core.Response; | ||
| import io.swagger.annotations.*; | ||
|
|
||
| import javax.validation.constraints.*; | ||
|
|
||
| @Path("/users") | ||
| @Api(description = "The users API") | ||
|
|
||
| public class UsersApi { | ||
|
|
||
| private final UsersApiService delegate; | ||
|
|
||
| public UsersApi() { | ||
|
|
||
| this.delegate = UsersApiServiceFactory.getUsersApi(); | ||
| } | ||
|
|
||
| @Valid | ||
| @GET | ||
| @Path("/{userId}/share") | ||
|
|
||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "List organizations where the user has shared access", notes = "Retrieve the list of organizations where the specified user has shared access, including per-organization effective role assignments. This follows the same pattern as **`GET /applications/{applicationId}/share`**. **Scope required:** `internal_user_shared_access_view`", response = UserSharedOrganizationsResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Accessible Organizations", }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 200, message = "Successful response with the user's shared organizations.", response = UserSharedOrganizationsResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response getUserSharedOrganizations(@ApiParam(value = "The ID of the user.",required=true) @PathParam("userId") String userId, @Valid@ApiParam(value = "Base64 encoded cursor for forward pagination.") @QueryParam("after") String after, @Valid@ApiParam(value = "Base64 encoded cursor for backward pagination.") @QueryParam("before") String before, @Valid@ApiParam(value = "Maximum number of records to return.") @QueryParam("limit") Integer limit, @Valid@ApiParam(value = "Condition to filter the retrieval of records. Supports operations like `sw`, `co`, `ew`, and `eq` depending on implementation.") @QueryParam("filter") String filter, @Valid@ApiParam(value = "Whether to include shared organizations recursively in the hierarchy.") @QueryParam("recursive") Boolean recursive) { | ||
|
|
||
| return delegate.getUserSharedOrganizations(userId, after, before, limit, filter, recursive ); | ||
| } | ||
|
|
||
| @Valid | ||
| @PATCH | ||
| @Path("/share") | ||
| @Consumes({ "application/json" }) | ||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "Perform incremental role assignment operations for already shared users", notes = "Perform **incremental updates** to the role assignments of already shared users. This endpoint supports **SCIM-like PATCH semantics**: - `op: \"add\"` → assign additional roles. - `op: \"remove\"` → remove specific roles. > **Note:** > Only **role assignments** are managed here. Sharing/unsharing organizations > is handled via `/users/share`, `/users/share-with-all`, `/users/unshare`, > and `/users/unshare-with-all`. **Scope required:** `internal_user_share`", response = ProcessSuccessResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Sharing", }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 202, message = "Role assignment patch operation processed successfully.", response = ProcessSuccessResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 404, message = "Not Found", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response patchUserSharing(@ApiParam(value = "" ,required=true) @Valid UserSharingPatchRequest userSharingPatchRequest) { | ||
|
|
||
| return delegate.patchUserSharing(userSharingPatchRequest ); | ||
| } | ||
|
|
||
| @Valid | ||
| @POST | ||
| @Path("/share-with-all") | ||
| @Consumes({ "application/json" }) | ||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "Share users with all organizations", notes = "Share one or more users with **all organizations**, or all immediate child organizations, according to the specified policy. A common `roleAssignment` can be provided to assign roles in all matching organizations. This endpoint is treated as a **processing function** and responds with `202 Accepted`. **Scope required:** `internal_user_share`", response = ProcessSuccessResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Sharing", }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 202, message = "Share-all process triggered successfully.", response = ProcessSuccessResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response shareUsersWithAll(@ApiParam(value = "" ,required=true) @Valid UserShareAllRequestBody userShareAllRequestBody) { | ||
|
|
||
| return delegate.shareUsersWithAll(userShareAllRequestBody ); | ||
| } | ||
|
|
||
| @Valid | ||
| @POST | ||
| @Path("/share") | ||
| @Consumes({ "application/json" }) | ||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "Share users with specific organizations", notes = "Share one or more users with a selected set of organizations, optionally assigning roles to each shared user in each target organization. This endpoint is treated as a **processing function**: it triggers a sharing process and responds with `202 Accepted`. **Scope required:** `internal_user_share`", response = ProcessSuccessResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Sharing", }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 202, message = "User sharing process triggered successfully.", response = ProcessSuccessResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response shareUsersWithSelected(@ApiParam(value = "" ,required=true) @Valid UserShareSelectedRequestBody userShareSelectedRequestBody) { | ||
|
|
||
| return delegate.shareUsersWithSelected(userShareSelectedRequestBody ); | ||
| } | ||
|
|
||
| @Valid | ||
| @POST | ||
| @Path("/unshare-with-all") | ||
| @Consumes({ "application/json" }) | ||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "Unshare users from all organizations", notes = "Completely remove all shared access for one or more users from **all organizations**. This endpoint is treated as a **processing function** and responds with `202 Accepted`. **Scope required:** `internal_user_unshare`", response = ProcessSuccessResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Sharing", }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 202, message = "Unshare-all process triggered successfully.", response = ProcessSuccessResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response unshareUsersFromAll(@ApiParam(value = "" ,required=true) @Valid UserUnshareAllRequestBody userUnshareAllRequestBody) { | ||
|
|
||
| return delegate.unshareUsersFromAll(userUnshareAllRequestBody ); | ||
| } | ||
|
|
||
| @Valid | ||
| @POST | ||
| @Path("/unshare") | ||
| @Consumes({ "application/json" }) | ||
| @Produces({ "application/json" }) | ||
| @ApiOperation(value = "Unshare users from specific organizations", notes = "Unshare one or more users from a selected set of organizations. > **Note:** > This only removes the user from the specified organizations. If the user > was shared with a parent org plus its children via a broader policy, > you must explicitly include all relevant organization IDs when unsharing. This endpoint is treated as a **processing function** and responds with `202 Accepted`. **Scope required:** `internal_user_unshare`", response = ProcessSuccessResponse.class, authorizations = { | ||
| @Authorization(value = "BasicAuth"), | ||
| @Authorization(value = "OAuth2", scopes = { | ||
|
|
||
| }) | ||
| }, tags={ "User Sharing" }) | ||
| @ApiResponses(value = { | ||
| @ApiResponse(code = 202, message = "Unsharing process triggered successfully.", response = ProcessSuccessResponse.class), | ||
| @ApiResponse(code = 400, message = "Bad Request", response = Error.class), | ||
| @ApiResponse(code = 500, message = "Internal Server Error", response = Error.class) | ||
| }) | ||
| public Response unshareUsersFromSelected(@ApiParam(value = "" ,required=true) @Valid UserUnshareSelectedRequestBody userUnshareSelectedRequestBody) { | ||
|
|
||
| return delegate.unshareUsersFromSelected(userUnshareSelectedRequestBody ); | ||
| } | ||
|
|
||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.