mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
[platform] IJPL-176930 Move intellij.platform.ide.provisioner to the platform
(cherry picked from commit de2b62ede7c49f30046f519d97a76f769ce42702) IJ-MR-154430 GitOrigin-RevId: 9c1b221162411c9251c1feff666328b00c1385ec
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e68cf608d9
commit
eecf7977e2
@@ -0,0 +1,37 @@
|
||||
package com.intellij.platform.ide.provisioner
|
||||
|
||||
import com.intellij.platform.ide.provisioner.endpoint.ServiceEndpoint
|
||||
|
||||
data class ProvisionedServiceConfiguration(
|
||||
/** Generic Key-Value map of service-specific properties. */
|
||||
private val properties: Map<String, String>,
|
||||
|
||||
/** Endpoint descriptor in case the service involves a remote server. */
|
||||
val endpoint: ServiceEndpoint?,
|
||||
) {
|
||||
operator fun get(key: String): String? = properties[key]
|
||||
}
|
||||
|
||||
sealed interface ProvisionedServiceConfigurationResult {
|
||||
/**
|
||||
* Represents the successfully loaded state.
|
||||
*/
|
||||
sealed interface Success : ProvisionedServiceConfigurationResult {
|
||||
data class ServiceProvisioned(val configuration: ProvisionedServiceConfiguration) : Success
|
||||
data object ServiceNotProvisioned : Success
|
||||
}
|
||||
|
||||
/**
|
||||
* Denotes that the provisioner could not load the configuration of the service due to an error.
|
||||
* Depending on the particular service, there may be different ways of treating this state.
|
||||
* For example, the client may fall back to some predefined default configuration,
|
||||
* or it may choose to prohibit the use of the corresponding IDE functionality altogether
|
||||
* until a proper configuration becomes available.
|
||||
*/
|
||||
sealed interface Failure : ProvisionedServiceConfigurationResult {
|
||||
val message: String
|
||||
|
||||
data class LoginRequired(override val message: String) : Failure
|
||||
data class GenericError(override val message: String, val cause: Throwable? = null) : Failure
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.intellij.platform.ide.provisioner
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Descriptor for a (potentially provisioned) piece of IDE functionality.
|
||||
*/
|
||||
interface ProvisionedServiceDescriptor {
|
||||
/** Unique identifier for accessing the service endpoint using [ProvisionedServiceRegistry.getServiceById]. */
|
||||
val id: String
|
||||
|
||||
/**
|
||||
* The state of whether the service is provisioned (with its configuration in that case) or not.
|
||||
*
|
||||
* Note that it may take some time for the initial value to become available in the flow
|
||||
* while the configuration is still loading.
|
||||
*/
|
||||
val configurationFlow: Flow<ProvisionedServiceConfigurationResult>
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.intellij.platform.ide.provisioner
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
|
||||
interface ProvisionedServiceRegistry {
|
||||
/**
|
||||
* Retrieves a [ProvisionedServiceDescriptor] by its [ProvisionedServiceDescriptor.id],
|
||||
* or null if the provisioner doesn't recognize the ID.
|
||||
* Note that a non-null result only means that the installed version of the provisioner plugin
|
||||
* is aware and support the requested service; it doesn't mean that the service is available and/or enabled -
|
||||
* this is what [ProvisionedServiceDescriptor.configurationFlow] is for.
|
||||
*/
|
||||
fun getServiceById(id: String): ProvisionedServiceDescriptor?
|
||||
|
||||
companion object {
|
||||
fun getInstance(): ProvisionedServiceRegistry = ApplicationManager.getApplication().service()
|
||||
}
|
||||
}
|
||||
|
||||
internal class DefaultProvisionedServiceRegistry : ProvisionedServiceRegistry {
|
||||
override fun getServiceById(id: String): ProvisionedServiceDescriptor? = null
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.ide.provisioner
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import javax.swing.Icon
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface ProvisionerCompanyBrandingProvider{
|
||||
val companyBranding: Flow<CompanyBranding>
|
||||
|
||||
@ApiStatus.Experimental
|
||||
fun getCurrentEnterpriseState(): CompanyBranding
|
||||
|
||||
companion object {
|
||||
fun getInstance(): ProvisionerCompanyBrandingProvider = ApplicationManager.getApplication().service()
|
||||
}
|
||||
}
|
||||
|
||||
internal class DefaultProvisionerCompanyBrandingProvider: ProvisionerCompanyBrandingProvider {
|
||||
override val companyBranding = flowOf(CompanyBranding.NotProvisioned)
|
||||
override fun getCurrentEnterpriseState(): CompanyBranding = CompanyBranding.NotProvisioned
|
||||
}
|
||||
|
||||
sealed class CompanyBranding {
|
||||
data object NotReady: CompanyBranding()
|
||||
data class Provisioned(val info: EnterpriseInfo): CompanyBranding()
|
||||
data object NotProvisioned: CompanyBranding()
|
||||
}
|
||||
|
||||
data class EnterpriseInfo(
|
||||
val logo: Icon,
|
||||
val companyName: @NlsSafe String,
|
||||
val browserUrl: String,
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.intellij.platform.ide.provisioner.endpoint
|
||||
|
||||
data class AuthToken(
|
||||
/**
|
||||
* The map of HTTP request headers required for authenticating with the corresponding [ServiceEndpoint].
|
||||
* Typically, it contains at least the `"Authorization"` credentials, but that's not guaranteed.
|
||||
*/
|
||||
val requestHeaders: Map<String, String>,
|
||||
) {
|
||||
@Deprecated("For backward compatibility, until TBE plugin is updated")
|
||||
@Suppress("unused")
|
||||
constructor(
|
||||
tokenValue: String,
|
||||
tokenSchema: String,
|
||||
additionalHeaders: Map<String, String>,
|
||||
) : this(requestHeaders = mapOf("Authorization" to "${tokenSchema} ${tokenValue}") + additionalHeaders)
|
||||
}
|
||||
|
||||
sealed interface AuthTokenResult {
|
||||
data class Success(val token: AuthToken) : AuthTokenResult
|
||||
|
||||
sealed interface Failure : AuthTokenResult {
|
||||
val message: String
|
||||
|
||||
data class Timeout(override val message: String) : Failure
|
||||
data class NetworkError(override val message: String) : Failure
|
||||
data class LoginRequired(override val message: String) : Failure
|
||||
data class ValidationError(override val message: String) : Failure
|
||||
data class GenericError(override val message: String, val cause: Throwable? = null) : Failure
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.intellij.platform.ide.provisioner.endpoint
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Describes a server endpoint for the provisioned service.
|
||||
*/
|
||||
interface ServiceEndpoint {
|
||||
/** The URL of the service endpoint. */
|
||||
val serverUrl: String
|
||||
|
||||
/**
|
||||
* The current [token][AuthTokenResult] required to access the [server][serverUrl].
|
||||
* The implementation is responsible for refreshing the token, so that the latest token value
|
||||
* available in the flow is always usable (unless there's an [AuthTokenResult.Failure]).
|
||||
*
|
||||
* Note that an [AuthTokenResult.Success] doesn't guarantee that the token is going to stay
|
||||
* valid up until its expiration time.
|
||||
* The client code should still be able to handle an authorization error properly,
|
||||
* and the [reportAuthFailure] method can be helpful in facilitating that.
|
||||
*/
|
||||
val authTokenFlow: Flow<AuthTokenResult>
|
||||
|
||||
/**
|
||||
* The client is advised to call this method as part of graceful error handling if a request
|
||||
* to the endpoint fails because of an authentication failure ("401 Unauthorized").
|
||||
*
|
||||
* The token may become invalid due to an external change; for instance, the SSO provider
|
||||
* may forcibly log the user out. An event like that may go unnoticed by the provisioner,
|
||||
* and the new state may not be reflected in the [authTokenFlow] automatically.
|
||||
*
|
||||
* By calling this method, the client notifies the provisioner that the token is no more
|
||||
* usable. The provisioner then makes the best effort to revalidate the token, which may
|
||||
* hopefully result in a new token state (probably an [AuthTokenResult.Failure.LoginRequired])
|
||||
* being pushed eventually through the [authTokenFlow].
|
||||
*
|
||||
* Note that the contract of this method should indeed be only treated as "best effort".
|
||||
* The client must not rely on a new token state becoming available in the [authTokenFlow]
|
||||
* right after calling this method, and should design the interaction with the user accordingly.
|
||||
* In this sense, the default "noop" way of how the provisioner could implement this method
|
||||
* is perfectly fine.
|
||||
*/
|
||||
fun reportAuthFailure(authToken: AuthToken) {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@ApiStatus.Internal
|
||||
package com.intellij.platform.ide.provisioner.endpoint;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@ApiStatus.Internal
|
||||
package com.intellij.platform.ide.provisioner;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -1864,6 +1864,10 @@
|
||||
<applicationService serviceInterface="com.intellij.auth.GenericAuthService"
|
||||
serviceImplementation="com.intellij.auth.LocalGenericAuthService"
|
||||
client="local"/>
|
||||
<applicationService serviceInterface="com.intellij.platform.ide.provisioner.ProvisionedServiceRegistry"
|
||||
serviceImplementation="com.intellij.platform.ide.provisioner.DefaultProvisionedServiceRegistry"/>
|
||||
<applicationService serviceInterface="com.intellij.platform.ide.provisioner.ProvisionerCompanyBrandingProvider"
|
||||
serviceImplementation="com.intellij.platform.ide.provisioner.DefaultProvisionerCompanyBrandingProvider"/>
|
||||
</extensions>
|
||||
|
||||
<applicationListeners>
|
||||
|
||||
Reference in New Issue
Block a user