feat: implement persistent token based remember me mechanism (#6131)

#### What type of PR is this?
/kind feature
/area core
/milestone 2.17.x

#### What this PR does / why we need it:
新增基于持久化 Token 的 RememberMe 机制

本次更新引入了一种新的 RememberMe 机制,该机制基于持久化 Token,以增强安全性和管理灵活性。在此之前,RememberMe 功能通过以下方式生成 Token,并将其作为 cookie 发送回客户端:
```
 username + ":" + expiryTime + ":" + algorithmName + ":"
   + algorithmHex(username + ":" + expiryTime + ":" + password + ":" + key)
```
此方法的优点在于无需存储 Token 就可以进行验证,并且用户密码的更改会自动使 Token 失效。然而,它的主要缺点是缺乏管理能力,例如无法手动撤销 Token。

鉴于最新的设备管理需求(见 PR #6100),我们需要一种支持设备撤销(revoke)的机制。因此,我们采用了持久化 Token 的方式,并通过随机生成的方法来提高安全性,而不将用户名和密码直接签名在 Token 中。新的 Token 格式如下:
```
base64(tokenValue:series)
```
此更改将为系统带来更高的安全保障和更灵活的管理选项,特别是在需要高度控制和监管设备访问时。

#### Does this PR introduce a user-facing change?
```release-note
引入基于持久化 Token 的新 RememberMe 机制以增强安全性和管理灵活性,升级后需要重新登录
```
pull/6142/head
guqing 2024-06-26 16:40:49 +08:00 committed by GitHub
parent 3f94cfc9a8
commit ae6724a2b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 2240 additions and 23 deletions

View File

@ -12403,6 +12403,243 @@
]
}
},
"/apis/security.halo.run/v1alpha1/remembermetokens": {
"get": {
"description": "List RememberMeToken",
"operationId": "listRememberMeToken",
"parameters": [
{
"description": "Page number. Default is 0.",
"in": "query",
"name": "page",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Size number. Default is 0.",
"in": "query",
"name": "size",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Label selector. e.g.: hidden!\u003dtrue",
"in": "query",
"name": "labelSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Field selector. e.g.: metadata.name\u003d\u003dhalo",
"in": "query",
"name": "fieldSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
"in": "query",
"name": "sort",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
],
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeTokenList"
}
}
},
"description": "Response remembermetokens"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"post": {
"description": "Create RememberMeToken",
"operationId": "createRememberMeToken",
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Fresh remembermetoken"
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetokens created just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
}
},
"/apis/security.halo.run/v1alpha1/remembermetokens/{name}": {
"delete": {
"description": "Delete RememberMeToken",
"operationId": "deleteRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Response remembermetoken deleted just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"get": {
"description": "Get RememberMeToken",
"operationId": "getRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response single remembermetoken"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"patch": {
"description": "Patch RememberMeToken",
"operationId": "patchRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/JsonPatch"
}
}
}
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetoken patched just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"put": {
"description": "Update RememberMeToken",
"operationId": "updateRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Updated remembermetoken"
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetokens updated just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
}
},
"/apis/storage.halo.run/v1alpha1/attachments": {
"get": {
"description": "List Attachment",
@ -19022,12 +19259,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},
@ -19524,6 +19761,114 @@
}
}
},
"RememberMeToken": {
"required": [
"apiVersion",
"kind",
"metadata",
"spec"
],
"type": "object",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"$ref": "#/components/schemas/Metadata"
},
"spec": {
"$ref": "#/components/schemas/RememberMeTokenSpec"
}
}
},
"RememberMeTokenList": {
"required": [
"first",
"hasNext",
"hasPrevious",
"items",
"last",
"page",
"size",
"total",
"totalPages"
],
"type": "object",
"properties": {
"first": {
"type": "boolean",
"description": "Indicates whether current page is the first page."
},
"hasNext": {
"type": "boolean",
"description": "Indicates whether current page has previous page."
},
"hasPrevious": {
"type": "boolean",
"description": "Indicates whether current page has previous page."
},
"items": {
"type": "array",
"description": "A chunk of items.",
"items": {
"$ref": "#/components/schemas/RememberMeToken"
}
},
"last": {
"type": "boolean",
"description": "Indicates whether current page is the last page."
},
"page": {
"type": "integer",
"description": "Page number, starts from 1. If not set or equal to 0, it means no pagination.",
"format": "int32"
},
"size": {
"type": "integer",
"description": "Size of each page. If not set or equal to 0, it means no pagination.",
"format": "int32"
},
"total": {
"type": "integer",
"description": "Total elements.",
"format": "int64"
},
"totalPages": {
"type": "integer",
"description": "Indicates total pages.",
"format": "int64"
}
}
},
"RememberMeTokenSpec": {
"required": [
"series",
"tokenValue",
"username"
],
"type": "object",
"properties": {
"lastUsed": {
"type": "string",
"format": "date-time"
},
"series": {
"minLength": 1,
"type": "string"
},
"tokenValue": {
"minLength": 1,
"type": "string"
},
"username": {
"minLength": 1,
"type": "string"
}
}
},
"RemoveOperation": {
"required": [
"op",
@ -20723,12 +21068,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},

View File

@ -5152,12 +5152,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},
@ -5660,12 +5660,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},

View File

@ -6179,6 +6179,243 @@
]
}
},
"/apis/security.halo.run/v1alpha1/remembermetokens": {
"get": {
"description": "List RememberMeToken",
"operationId": "listRememberMeToken",
"parameters": [
{
"description": "Page number. Default is 0.",
"in": "query",
"name": "page",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Size number. Default is 0.",
"in": "query",
"name": "size",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Label selector. e.g.: hidden!\u003dtrue",
"in": "query",
"name": "labelSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Field selector. e.g.: metadata.name\u003d\u003dhalo",
"in": "query",
"name": "fieldSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
"in": "query",
"name": "sort",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
],
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeTokenList"
}
}
},
"description": "Response remembermetokens"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"post": {
"description": "Create RememberMeToken",
"operationId": "createRememberMeToken",
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Fresh remembermetoken"
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetokens created just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
}
},
"/apis/security.halo.run/v1alpha1/remembermetokens/{name}": {
"delete": {
"description": "Delete RememberMeToken",
"operationId": "deleteRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Response remembermetoken deleted just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"get": {
"description": "Get RememberMeToken",
"operationId": "getRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response single remembermetoken"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"patch": {
"description": "Patch RememberMeToken",
"operationId": "patchRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/JsonPatch"
}
}
}
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetoken patched just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
},
"put": {
"description": "Update RememberMeToken",
"operationId": "updateRememberMeToken",
"parameters": [
{
"description": "Name of remembermetoken",
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Updated remembermetoken"
},
"responses": {
"200": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RememberMeToken"
}
}
},
"description": "Response remembermetokens updated just now"
}
},
"tags": [
"RememberMeTokenV1alpha1"
]
}
},
"/apis/storage.halo.run/v1alpha1/attachments": {
"get": {
"description": "List Attachment",
@ -10057,12 +10294,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},
@ -10140,6 +10377,114 @@
},
"description": "Extension reference object. The name is mandatory"
},
"RememberMeToken": {
"required": [
"apiVersion",
"kind",
"metadata",
"spec"
],
"type": "object",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"$ref": "#/components/schemas/Metadata"
},
"spec": {
"$ref": "#/components/schemas/RememberMeTokenSpec"
}
}
},
"RememberMeTokenList": {
"required": [
"first",
"hasNext",
"hasPrevious",
"items",
"last",
"page",
"size",
"total",
"totalPages"
],
"type": "object",
"properties": {
"first": {
"type": "boolean",
"description": "Indicates whether current page is the first page."
},
"hasNext": {
"type": "boolean",
"description": "Indicates whether current page has previous page."
},
"hasPrevious": {
"type": "boolean",
"description": "Indicates whether current page has previous page."
},
"items": {
"type": "array",
"description": "A chunk of items.",
"items": {
"$ref": "#/components/schemas/RememberMeToken"
}
},
"last": {
"type": "boolean",
"description": "Indicates whether current page is the last page."
},
"page": {
"type": "integer",
"description": "Page number, starts from 1. If not set or equal to 0, it means no pagination.",
"format": "int32"
},
"size": {
"type": "integer",
"description": "Size of each page. If not set or equal to 0, it means no pagination.",
"format": "int32"
},
"total": {
"type": "integer",
"description": "Total elements.",
"format": "int64"
},
"totalPages": {
"type": "integer",
"description": "Indicates total pages.",
"format": "int64"
}
}
},
"RememberMeTokenSpec": {
"required": [
"series",
"tokenValue",
"username"
],
"type": "object",
"properties": {
"lastUsed": {
"type": "string",
"format": "date-time"
},
"series": {
"minLength": 1,
"type": "string"
},
"tokenValue": {
"minLength": 1,
"type": "string"
},
"username": {
"minLength": 1,
"type": "string"
}
}
},
"RemoveOperation": {
"required": [
"op",
@ -11136,12 +11481,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},

View File

@ -1455,12 +1455,12 @@
},
"visible": {
"type": "string",
"default": "PUBLIC",
"enum": [
"PUBLIC",
"INTERNAL",
"PRIVATE"
],
"default": "PUBLIC"
]
}
}
},

View File

@ -0,0 +1,37 @@
package run.halo.app.core.extension;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Instant;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "security.halo.run", version = "v1alpha1", kind = "RememberMeToken", plural =
"remembermetokens", singular = "remembermetoken")
public class RememberMeToken extends AbstractExtension {
@Schema(requiredMode = REQUIRED)
private Spec spec;
@Data
@Accessors(chain = true)
@Schema(name = "RememberMeTokenSpec")
public static class Spec {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String username;
@Schema(requiredMode = REQUIRED, minLength = 1)
private String series;
@Schema(requiredMode = REQUIRED, minLength = 1)
private String tokenValue;
private Instant lastUsed;
}
}

View File

@ -22,6 +22,7 @@ import run.halo.app.core.extension.Counter;
import run.halo.app.core.extension.Menu;
import run.halo.app.core.extension.MenuItem;
import run.halo.app.core.extension.Plugin;
import run.halo.app.core.extension.RememberMeToken;
import run.halo.app.core.extension.ReverseProxy;
import run.halo.app.core.extension.Role;
import run.halo.app.core.extension.RoleBinding;
@ -432,6 +433,21 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
// security.halo.run
schemeManager.register(PersonalAccessToken.class);
schemeManager.register(RememberMeToken.class, indexSpecs -> {
indexSpecs.add(new IndexSpec()
.setName("spec.series")
.setUnique(true)
.setIndexFunc(simpleAttribute(RememberMeToken.class,
token -> token.getSpec().getSeries())
)
);
indexSpecs.add(new IndexSpec()
.setName("spec.username")
.setIndexFunc(simpleAttribute(RememberMeToken.class,
token -> token.getSpec().getUsername())
)
);
});
// migration.halo.run
schemeManager.register(Backup.class);

View File

@ -5,12 +5,15 @@ import static run.halo.app.security.authentication.WebExchangeMatchers.ignoringM
import java.net.URI;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler;
import org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter;
import org.springframework.stereotype.Component;
@ -22,27 +25,37 @@ import run.halo.app.security.authentication.rememberme.RememberMeServices;
@RequiredArgsConstructor
public class LogoutSecurityConfigurer implements SecurityConfigurer {
private final RememberMeServices rememberMeServices;
private final ApplicationContext applicationContext;
@Override
public void configure(ServerHttpSecurity http) {
http.logout(logout -> logout.logoutSuccessHandler(new LogoutSuccessHandler()));
var serverLogoutHandlers = getLogoutHandlers();
http.logout(
logout -> logout.logoutSuccessHandler(new LogoutSuccessHandler(serverLogoutHandlers)));
http.addFilterAt(new LogoutPageGeneratingWebFilter(), LOGOUT_PAGE_GENERATING);
}
private class LogoutSuccessHandler implements ServerLogoutSuccessHandler {
private final ServerLogoutSuccessHandler defaultHandler;
private final ServerLogoutHandler logoutHandler;
public LogoutSuccessHandler() {
public LogoutSuccessHandler(ServerLogoutHandler... logoutHandler) {
var defaultHandler = new RedirectServerLogoutSuccessHandler();
defaultHandler.setLogoutSuccessUrl(URI.create("/console/?logout"));
this.defaultHandler = defaultHandler;
if (logoutHandler.length == 1) {
this.logoutHandler = logoutHandler[0];
} else {
this.logoutHandler = new DelegatingServerLogoutHandler(logoutHandler);
}
}
@Override
public Mono<Void> onLogoutSuccess(WebFilterExchange exchange,
Authentication authentication) {
return rememberMeServices.loginFail(exchange.getExchange())
return logoutHandler.logout(exchange, authentication)
.then(rememberMeServices.loginFail(exchange.getExchange()))
.then(ignoringMediaTypeAll(MediaType.APPLICATION_JSON)
.matches(exchange.getExchange())
.flatMap(matchResult -> {
@ -56,4 +69,9 @@ public class LogoutSecurityConfigurer implements SecurityConfigurer {
);
}
}
private ServerLogoutHandler[] getLogoutHandlers() {
return applicationContext.getBeansOfType(ServerLogoutHandler.class).values()
.toArray(new ServerLogoutHandler[0]);
}
}

View File

@ -0,0 +1,15 @@
package run.halo.app.security.authentication.rememberme;
import java.time.Instant;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import reactor.core.publisher.Mono;
public interface PersistentRememberMeTokenRepository {
Mono<Void> createNewToken(PersistentRememberMeToken token);
Mono<Void> updateToken(String series, String tokenValue, Instant lastUsed);
Mono<PersistentRememberMeToken> getTokenForSeries(String seriesId);
Mono<Void> removeUserTokens(String username);
}

View File

@ -0,0 +1,90 @@
package run.halo.app.security.authentication.rememberme;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.RememberMeToken;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.selector.FieldSelector;
import run.halo.app.infra.ReactiveExtensionPaginatedOperatorImpl;
/**
* Extension based persistent remember me token repository implementation.
*
* @see RememberMeToken
*/
@Component
@RequiredArgsConstructor
public class PersistentRememberMeTokenRepositoryImpl
implements PersistentRememberMeTokenRepository {
private final ReactiveExtensionClient client;
private final ReactiveExtensionPaginatedOperatorImpl paginatedOperator;
@Override
public Mono<Void> createNewToken(PersistentRememberMeToken token) {
var rememberMeToken = new RememberMeToken();
var metadata = new Metadata();
rememberMeToken.setMetadata(metadata);
metadata.setGenerateName("token-");
var creationTime = Instant.ofEpochMilli(token.getDate().getTime());
metadata.setCreationTimestamp(creationTime);
rememberMeToken.setSpec(new RememberMeToken.Spec());
rememberMeToken.getSpec()
.setUsername(token.getUsername())
.setSeries(token.getSeries())
.setTokenValue(token.getTokenValue());
return client.create(rememberMeToken).then();
}
@Override
public Mono<Void> updateToken(String series, String tokenValue, Instant lastUsed) {
return Mono.defer(() -> getTokenExtensionForSeries(series)
.flatMap(token -> {
token.getSpec().setTokenValue(tokenValue)
.setLastUsed(lastUsed);
return client.update(token);
})
)
.retryWhen(Retry.backoff(8, Duration.ofMillis(100))
.filter(OptimisticLockingFailureException.class::isInstance))
.then();
}
@Override
public Mono<PersistentRememberMeToken> getTokenForSeries(String seriesId) {
return getTokenExtensionForSeries(seriesId)
.map(token -> new PersistentRememberMeToken(
token.getSpec().getUsername(),
token.getSpec().getSeries(),
token.getSpec().getTokenValue(),
new Date(token.getMetadata().getCreationTimestamp().toEpochMilli())
));
}
@Override
public Mono<Void> removeUserTokens(String username) {
var listOptions = new ListOptions();
listOptions.setFieldSelector(FieldSelector.of(equal("spec.username", username)));
return paginatedOperator.deleteInitialBatch(RememberMeToken.class, listOptions).then();
}
private Mono<RememberMeToken> getTokenExtensionForSeries(String seriesId) {
var listOptions = new ListOptions();
listOptions.setFieldSelector(FieldSelector.of(equal("spec.series", seriesId)));
return client.listBy(RememberMeToken.class, listOptions, PageRequestImpl.ofSize(1))
.flatMap(result -> Mono.justOrEmpty(ListResult.first(result)));
}
}

View File

@ -0,0 +1,187 @@
package run.halo.app.security.authentication.rememberme;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* <p>{@link RememberMeServices} implementation based on Barry Jaspan's <a href=
* "https://web.archive.org/web/20180819014446/http://jaspan
* .com/improved_persistent_login_cookie_best_practice">Improved
* Persistent Login Cookie Best Practice</a>.</p>
* <p>There is a slight modification to the described approach, in that the username is not
* stored as part of the cookie but obtained from the persistent store via an
* implementation of {@link PersistentTokenRepository}. The latter should place a unique
* constraint on the series identifier, so that it is impossible for the same identifier
* to be allocated to two different users.</p>
* <p>User management such as changing passwords, removing users and setting user status
* should be combined with maintenance of the user's persistent tokens.</p>
* <p>
* Note that while this class will use the date a token was created to check whether a
* presented cookie is older than the configured <tt>tokenValiditySeconds</tt> property
* and deny authentication in this case, it will not delete these tokens from storage. A
* suitable batch process should be run periodically to remove expired tokens from the
* database.
* </p>
*
* @author guqing
* @see
* <a href="https://github.com/spring-projects/spring-security/blob/902aff451f2f4d3f2ce44659bbef3645bf320ece/web/src/main/java/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java#L61">PersistentTokenBasedRememberMeServices</a>
* @since 2.17.0
*/
@Slf4j
@Setter
@Component
public class PersistentTokenBasedRememberMeServices extends TokenBasedRememberMeServices
implements RememberMeServices {
public static final int DEFAULT_SERIES_LENGTH = 16;
public static final int DEFAULT_TOKEN_LENGTH = 16;
private final SecureRandom random;
private final int seriesLength = DEFAULT_SERIES_LENGTH;
private final int tokenLength = DEFAULT_TOKEN_LENGTH;
private final PersistentRememberMeTokenRepository tokenRepository;
public PersistentTokenBasedRememberMeServices(
CookieSignatureKeyResolver cookieSignatureKeyResolver,
ReactiveUserDetailsService userDetailsService,
RememberMeCookieResolver rememberMeCookieResolver,
PersistentRememberMeTokenRepository tokenRepository) {
super(cookieSignatureKeyResolver, userDetailsService, rememberMeCookieResolver);
this.random = new SecureRandom();
this.tokenRepository = tokenRepository;
}
@Override
protected Mono<UserDetails> processAutoLoginCookie(String[] cookieTokens,
ServerWebExchange exchange) {
if (cookieTokens.length != 2) {
throw new InvalidCookieException(
"Cookie token did not contain " + 2 + " tokens, but contained '"
+ Arrays.asList(cookieTokens) + "'");
}
String presentedSeries = cookieTokens[0];
String presentedToken = cookieTokens[1];
return this.tokenRepository.getTokenForSeries(presentedSeries)
// No series match, so we can't authenticate using this cookie
.switchIfEmpty(Mono.error(new RememberMeAuthenticationException(
"No persistent token found for series id: " + presentedSeries))
)
.flatMap(token -> {
// We have a match for this user/series combination
if (!presentedToken.equals(token.getTokenValue())) {
// Token doesn't match series value. Delete all logins for this user and throw
// an exception to warn them.
return this.tokenRepository.removeUserTokens(token.getUsername())
.then(Mono.error(new CookieTheftException(
"Invalid remember-me token (Series/token) mismatch. Implies previous "
+ "cookie theft"
+ " attack.")));
}
if (isTokenExpired(token)) {
return Mono.error(
new RememberMeAuthenticationException("Remember-me login has expired"));
}
// Token also matches, so login is valid. Update the token value, keeping the
// *same* series number.
log.debug("Refreshing persistent login token for user '{}', series '{}'",
token.getUsername(), token.getSeries());
var newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(),
generateTokenData(), new Date());
return Mono.just(newToken);
})
.flatMap(newToken -> updateToken(newToken)
.doOnSuccess(unused -> addCookie(newToken, exchange))
.onErrorMap(ex -> {
log.error("Failed to update token: ", ex);
return new RememberMeAuthenticationException(
"Autologin failed due to data access problem");
})
.then(getUserDetailsService().findByUsername(newToken.getUsername()))
);
}
private boolean isTokenExpired(PersistentRememberMeToken token) {
return isTokenExpired(token.getDate().getTime() + getTokenValidityMillis());
}
private Mono<Void> updateToken(PersistentRememberMeToken newToken) {
return this.tokenRepository.updateToken(newToken.getSeries(),
newToken.getTokenValue(), dateToInstant(newToken.getDate()));
}
Instant dateToInstant(Date date) {
return Instant.ofEpochMilli(date.getTime());
}
/**
* Creates a new persistent login token with a new series number, stores the data in
* the persistent token repository and adds the corresponding cookie to the response.
*/
@Override
protected Mono<Void> onLoginSuccess(ServerWebExchange exchange,
Authentication successfulAuthentication) {
String username = successfulAuthentication.getName();
log.debug("Creating new persistent login for user {}", username);
PersistentRememberMeToken persistentToken =
new PersistentRememberMeToken(username, generateSeriesData(),
generateTokenData(), new Date());
return this.tokenRepository.createNewToken(persistentToken)
.doOnSuccess(unused -> addCookie(persistentToken, exchange))
.onErrorResume(Throwable.class, ex -> {
log.error("Failed to save persistent token ", ex);
return Mono.empty();
});
}
@Override
protected Mono<Void> onLogout(WebFilterExchange exchange, Authentication authentication) {
if (authentication != null) {
return this.tokenRepository.removeUserTokens(authentication.getName());
}
return Mono.empty();
}
private void addCookie(PersistentRememberMeToken token, ServerWebExchange exchange) {
setCookie(new String[] {token.getSeries(), token.getTokenValue()}, exchange);
}
protected String generateSeriesData() {
byte[] newSeries = new byte[this.seriesLength];
this.random.nextBytes(newSeries);
return new String(Base64.getEncoder().encode(newSeries));
}
protected String generateTokenData() {
byte[] newToken = new byte[this.tokenLength];
this.random.nextBytes(newToken);
return new String(Base64.getEncoder().encode(newToken));
}
private long getTokenValidityMillis() {
return rememberMeCookieResolver.getCookieMaxAge().toMillis();
}
}

View File

@ -0,0 +1,30 @@
package run.halo.app.security.authentication.rememberme;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import run.halo.app.event.user.PasswordChangedEvent;
/**
* Remember me token revoker.
* <p>
* Listen to password changed event and revoke remember me token.
* </p>
* Maybe you should consider revoke remember me token when user logout or username changed.
*
* @author guqing
* @since 2.17.0
*/
@Component
@RequiredArgsConstructor
public class RememberMeTokenRevoker {
private final PersistentRememberMeTokenRepository tokenRepository;
@Async
@EventListener(PasswordChangedEvent.class)
public void onPasswordChanged(PasswordChangedEvent event) {
tokenRepository.removeUserTokens(event.getUsername())
.block();
}
}

View File

@ -0,0 +1,58 @@
package run.halo.app.security.authentication.rememberme;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.isNull;
import static run.halo.app.extension.index.query.QueryFactory.lessThan;
import java.time.Duration;
import java.time.Instant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import run.halo.app.core.extension.RememberMeToken;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.router.selector.FieldSelector;
import run.halo.app.infra.ReactiveExtensionPaginatedOperator;
/**
* A cleaner for remember me tokens that cleans up expired tokens periodically.
*
* @author guqing
* @since 2.17.0
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class RememberTokenCleaner {
private final ReactiveExtensionPaginatedOperator paginatedOperator;
private final RememberMeCookieResolver rememberMeCookieResolver;
/**
* Clean up expired tokens every day at 3:00 AM.
*/
@Scheduled(cron = "0 0 3 * * ?")
public void cleanUpExpiredTokens() {
paginatedOperator.deleteInitialBatch(RememberMeToken.class, getExpiredTokensListOptions())
.then().block();
log.info("Expired remember me tokens have been cleaned up.");
}
ListOptions getExpiredTokensListOptions() {
var listOptions = new ListOptions();
listOptions.setFieldSelector(FieldSelector.of(
and(isNull("metadata.deletionTimestamp"),
lessThan("metadata.creationTimestamp", getExpirationThreshold().toString())
)
));
return listOptions;
}
protected Instant getExpirationThreshold() {
return Instant.now().minus(getTokenValidity());
}
protected Duration getTokenValidity() {
return rememberMeCookieResolver.getCookieMaxAge();
}
}

View File

@ -31,7 +31,8 @@ import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@ -54,9 +55,8 @@ import reactor.core.publisher.Mono;
@Slf4j
@Setter
@Getter
@Component
@RequiredArgsConstructor
public class TokenBasedRememberMeServices implements RememberMeServices {
public class TokenBasedRememberMeServices implements ServerLogoutHandler, RememberMeServices {
public static final int TWO_WEEKS_S = 1209600;
@ -66,11 +66,11 @@ public class TokenBasedRememberMeServices implements RememberMeServices {
private static final String DELIMITER = ":";
private final CookieSignatureKeyResolver cookieSignatureKeyResolver;
protected final CookieSignatureKeyResolver cookieSignatureKeyResolver;
private final ReactiveUserDetailsService userDetailsService;
protected final ReactiveUserDetailsService userDetailsService;
private final RememberMeCookieResolver rememberMeCookieResolver;
protected final RememberMeCookieResolver rememberMeCookieResolver;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
@ -218,6 +218,11 @@ public class TokenBasedRememberMeServices implements RememberMeServices {
log.debug("Remember-me login not requested.");
return Mono.empty();
}
return onLoginSuccess(exchange, successfulAuthentication);
}
protected Mono<Void> onLoginSuccess(ServerWebExchange exchange,
Authentication successfulAuthentication) {
return Mono.defer(() -> retrieveUsernamePassword(successfulAuthentication))
.flatMap(pair -> {
var username = pair.username();
@ -372,6 +377,19 @@ public class TokenBasedRememberMeServices implements RememberMeServices {
return cookieSignatureKeyResolver.resolveSigningKey();
}
@Override
public Mono<Void> logout(WebFilterExchange exchange, Authentication authentication) {
if (log.isDebugEnabled()) {
log.debug("Logout of user {}", (authentication != null) ? authentication.getName()
: "Unknown");
}
return onLogout(exchange, authentication);
}
protected Mono<Void> onLogout(WebFilterExchange exchange, Authentication authentication) {
return Mono.empty();
}
record UsernamePassword(String username, String password) {
}
}

View File

@ -0,0 +1,163 @@
package run.halo.app.security.authentication.rememberme;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
import org.springframework.security.web.server.WebFilterExchange;
import reactor.core.publisher.Mono;
/**
* Tests for {@link PersistentTokenBasedRememberMeServices}.
*
* @author guqing
* @since 2.17.0
*/
@ExtendWith(MockitoExtension.class)
class PersistentTokenBasedRememberMeServicesTest {
@Mock
private CookieSignatureKeyResolver cookieSignatureKeyResolver;
@Mock
private ReactiveUserDetailsService userDetailsService;
@Mock
private RememberMeCookieResolver rememberMeCookieResolver;
@Mock
private PersistentRememberMeTokenRepository tokenRepository;
@InjectMocks
private PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices;
@Nested
class ProcessAutoLoginCookieTest {
@Test
void invalidCookieTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
assertThatThrownBy(() -> persistentTokenBasedRememberMeServices.processAutoLoginCookie(
new String[] {"test"},
exchange).block())
.isInstanceOf(InvalidCookieException.class)
.hasMessage("Cookie token did not contain 2 tokens, but contained '[test]'");
}
@Test
void noPersistentTokenFoundTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
when(tokenRepository.getTokenForSeries(eq("test-series")))
.thenReturn(Mono.empty());
assertThatThrownBy(() -> persistentTokenBasedRememberMeServices.processAutoLoginCookie(
new String[] {"test-series", "test"},
exchange).block()
).isInstanceOf(RememberMeAuthenticationException.class)
.hasMessage("No persistent token found for series id: test-series");
}
@Test
void tokenMismatchTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
when(tokenRepository.getTokenForSeries(eq("fake-series")))
.thenReturn(Mono.just(
new PersistentRememberMeToken("test", "fake-series", "other-token-value",
new Date()))
);
when(tokenRepository.removeUserTokens(eq("test"))).thenReturn(Mono.empty());
assertThatThrownBy(() -> persistentTokenBasedRememberMeServices.processAutoLoginCookie(
new String[] {"fake-series", "token-value"},
exchange).block())
.isInstanceOf(CookieTheftException.class)
.hasMessage(
"Invalid remember-me token (Series/token) mismatch. Implies previous cookie "
+ "theft attack.");
}
@Test
void rememberMeLoginExpiredTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
when(tokenRepository.getTokenForSeries(eq("fake-series")))
.thenReturn(Mono.just(
new PersistentRememberMeToken("test", "fake-series", "token-value",
new Date(Instant.now().minusSeconds(10).toEpochMilli())))
);
when(rememberMeCookieResolver.getCookieMaxAge()).thenReturn(Duration.ofSeconds(5));
assertThatThrownBy(() -> persistentTokenBasedRememberMeServices.processAutoLoginCookie(
new String[] {"fake-series", "token-value"},
exchange).block())
.isInstanceOf(RememberMeAuthenticationException.class)
.hasMessage("Remember-me login has expired");
}
@Test
void successfulTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
when(tokenRepository.getTokenForSeries(eq("fake-series")))
.thenReturn(Mono.just(
new PersistentRememberMeToken("test", "fake-series", "token-value",
new Date()))
);
when(rememberMeCookieResolver.getCookieMaxAge()).thenReturn(Duration.ofSeconds(5));
var generatedTokenValue = new AtomicReference<String>();
when(tokenRepository.updateToken(eq("fake-series"), any(), any()))
.thenAnswer(invocation -> {
var tokenValue = (String) invocation.getArgument(1);
generatedTokenValue.compareAndSet(null, tokenValue);
return Mono.empty();
});
when(userDetailsService.findByUsername(eq("test"))).thenReturn(Mono.empty());
persistentTokenBasedRememberMeServices.processAutoLoginCookie(
new String[] {"fake-series", "token-value"}, exchange)
.block();
verify(rememberMeCookieResolver).setRememberMeCookie(eq(exchange),
eq(persistentTokenBasedRememberMeServices.encodeCookie(
new String[] {"fake-series", generatedTokenValue.get()})));
}
}
@Test
void onLoginSuccessTest() {
var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
var authentication = new UsernamePasswordAuthenticationToken("test", "test");
when(tokenRepository.createNewToken(any())).thenReturn(Mono.empty());
persistentTokenBasedRememberMeServices.onLoginSuccess(exchange, authentication).block();
verify(rememberMeCookieResolver).setRememberMeCookie(eq(exchange), any());
}
@Test
void onLogoutTest() {
var authentication = new UsernamePasswordAuthenticationToken("test", "test");
when(tokenRepository.removeUserTokens(eq("test"))).thenReturn(Mono.empty());
var filterExchange = mock(WebFilterExchange.class);
persistentTokenBasedRememberMeServices.onLogout(filterExchange, authentication).block();
}
}

View File

@ -0,0 +1,39 @@
package run.halo.app.security.authentication.rememberme;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.spy;
import java.time.Duration;
import java.time.Instant;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
/**
* Test for {@link RememberTokenCleaner}.
*
* @author guqing
* @since 2.17.0
*/
@ExtendWith(MockitoExtension.class)
class RememberTokenCleanerTest {
@InjectMocks
private RememberTokenCleaner rememberTokenCleaner;
@Test
void test() {
var spyRememberTokenCleaner = spy(rememberTokenCleaner);
Mockito.doReturn(Duration.ofSeconds(30)).when(spyRememberTokenCleaner).getTokenValidity();
var expiredTime = spyRememberTokenCleaner.getExpirationThreshold();
var creationTime = Instant.now().minus(Duration.ofSeconds(31));
// creationTime < expirationThreshold means it has expired
assertThat(creationTime).isBefore(expiredTime);
// not expired
creationTime = Instant.now().minus(Duration.ofSeconds(29));
assertThat(creationTime).isAfter(expiredTime);
}
}

View File

@ -46,6 +46,7 @@ api/post-v1alpha1-public-api.ts
api/post-v1alpha1-uc-api.ts
api/reason-type-v1alpha1-api.ts
api/reason-v1alpha1-api.ts
api/remember-me-token-v1alpha1-api.ts
api/reply-v1alpha1-api.ts
api/reply-v1alpha1-console-api.ts
api/reverse-proxy-v1alpha1-api.ts
@ -241,6 +242,9 @@ models/reason-type.ts
models/reason.ts
models/ref.ts
models/register-verify-email-request.ts
models/remember-me-token-list.ts
models/remember-me-token-spec.ts
models/remember-me-token.ts
models/remove-operation.ts
models/replace-operation.ts
models/reply-list.ts

View File

@ -59,6 +59,7 @@ export * from './api/post-v1alpha1-public-api';
export * from './api/post-v1alpha1-uc-api';
export * from './api/reason-type-v1alpha1-api';
export * from './api/reason-v1alpha1-api';
export * from './api/remember-me-token-v1alpha1-api';
export * from './api/reply-v1alpha1-api';
export * from './api/reply-v1alpha1-console-api';
export * from './api/reverse-proxy-v1alpha1-api';

View File

@ -0,0 +1,665 @@
/* tslint:disable */
/* eslint-disable */
/**
* Halo
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 2.17.0-SNAPSHOT
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import type { Configuration } from '../configuration';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError, operationServerMap } from '../base';
// @ts-ignore
import { JsonPatchInner } from '../models';
// @ts-ignore
import { RememberMeToken } from '../models';
// @ts-ignore
import { RememberMeTokenList } from '../models';
/**
* RememberMeTokenV1alpha1Api - axios parameter creator
* @export
*/
export const RememberMeTokenV1alpha1ApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
* Create RememberMeToken
* @param {RememberMeToken} [rememberMeToken] Fresh remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
createRememberMeToken: async (rememberMeToken?: RememberMeToken, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(rememberMeToken, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Delete RememberMeToken
* @param {string} name Name of remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteRememberMeToken: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('deleteRememberMeToken', 'name', name)
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens/{name}`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Get RememberMeToken
* @param {string} name Name of remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getRememberMeToken: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('getRememberMeToken', 'name', name)
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens/{name}`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* List RememberMeToken
* @param {number} [page] Page number. Default is 0.
* @param {number} [size] Size number. Default is 0.
* @param {Array<string>} [labelSelector] Label selector. e.g.: hidden!&#x3D;true
* @param {Array<string>} [fieldSelector] Field selector. e.g.: metadata.name&#x3D;&#x3D;halo
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRememberMeToken: async (page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
if (page !== undefined) {
localVarQueryParameter['page'] = page;
}
if (size !== undefined) {
localVarQueryParameter['size'] = size;
}
if (labelSelector) {
localVarQueryParameter['labelSelector'] = labelSelector;
}
if (fieldSelector) {
localVarQueryParameter['fieldSelector'] = fieldSelector;
}
if (sort) {
localVarQueryParameter['sort'] = sort;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Patch RememberMeToken
* @param {string} name Name of remembermetoken
* @param {Array<JsonPatchInner>} [jsonPatchInner]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
patchRememberMeToken: async (name: string, jsonPatchInner?: Array<JsonPatchInner>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('patchRememberMeToken', 'name', name)
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens/{name}`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(jsonPatchInner, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Update RememberMeToken
* @param {string} name Name of remembermetoken
* @param {RememberMeToken} [rememberMeToken] Updated remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updateRememberMeToken: async (name: string, rememberMeToken?: RememberMeToken, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('updateRememberMeToken', 'name', name)
const localVarPath = `/apis/security.halo.run/v1alpha1/remembermetokens/{name}`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication basicAuth required
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
// authentication bearerAuth required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(rememberMeToken, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
}
};
/**
* RememberMeTokenV1alpha1Api - functional programming interface
* @export
*/
export const RememberMeTokenV1alpha1ApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = RememberMeTokenV1alpha1ApiAxiosParamCreator(configuration)
return {
/**
* Create RememberMeToken
* @param {RememberMeToken} [rememberMeToken] Fresh remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async createRememberMeToken(rememberMeToken?: RememberMeToken, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RememberMeToken>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.createRememberMeToken(rememberMeToken, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.createRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Delete RememberMeToken
* @param {string} name Name of remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async deleteRememberMeToken(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteRememberMeToken(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.deleteRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Get RememberMeToken
* @param {string} name Name of remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getRememberMeToken(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RememberMeToken>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getRememberMeToken(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.getRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* List RememberMeToken
* @param {number} [page] Page number. Default is 0.
* @param {number} [size] Size number. Default is 0.
* @param {Array<string>} [labelSelector] Label selector. e.g.: hidden!&#x3D;true
* @param {Array<string>} [fieldSelector] Field selector. e.g.: metadata.name&#x3D;&#x3D;halo
* @param {Array<string>} [sort] Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listRememberMeToken(page?: number, size?: number, labelSelector?: Array<string>, fieldSelector?: Array<string>, sort?: Array<string>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RememberMeTokenList>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRememberMeToken(page, size, labelSelector, fieldSelector, sort, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.listRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Patch RememberMeToken
* @param {string} name Name of remembermetoken
* @param {Array<JsonPatchInner>} [jsonPatchInner]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async patchRememberMeToken(name: string, jsonPatchInner?: Array<JsonPatchInner>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RememberMeToken>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.patchRememberMeToken(name, jsonPatchInner, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.patchRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Update RememberMeToken
* @param {string} name Name of remembermetoken
* @param {RememberMeToken} [rememberMeToken] Updated remembermetoken
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async updateRememberMeToken(name: string, rememberMeToken?: RememberMeToken, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RememberMeToken>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.updateRememberMeToken(name, rememberMeToken, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RememberMeTokenV1alpha1Api.updateRememberMeToken']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
/**
* RememberMeTokenV1alpha1Api - factory interface
* @export
*/
export const RememberMeTokenV1alpha1ApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = RememberMeTokenV1alpha1ApiFp(configuration)
return {
/**
* Create RememberMeToken
* @param {RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
createRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<RememberMeToken> {
return localVarFp.createRememberMeToken(requestParameters.rememberMeToken, options).then((request) => request(axios, basePath));
},
/**
* Delete RememberMeToken
* @param {RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest, options?: RawAxiosRequestConfig): AxiosPromise<void> {
return localVarFp.deleteRememberMeToken(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* Get RememberMeToken
* @param {RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest, options?: RawAxiosRequestConfig): AxiosPromise<RememberMeToken> {
return localVarFp.getRememberMeToken(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* List RememberMeToken
* @param {RememberMeTokenV1alpha1ApiListRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiListRememberMeTokenRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<RememberMeTokenList> {
return localVarFp.listRememberMeToken(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, options).then((request) => request(axios, basePath));
},
/**
* Patch RememberMeToken
* @param {RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
patchRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest, options?: RawAxiosRequestConfig): AxiosPromise<RememberMeToken> {
return localVarFp.patchRememberMeToken(requestParameters.name, requestParameters.jsonPatchInner, options).then((request) => request(axios, basePath));
},
/**
* Update RememberMeToken
* @param {RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
updateRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest, options?: RawAxiosRequestConfig): AxiosPromise<RememberMeToken> {
return localVarFp.updateRememberMeToken(requestParameters.name, requestParameters.rememberMeToken, options).then((request) => request(axios, basePath));
},
};
};
/**
* Request parameters for createRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest {
/**
* Fresh remembermetoken
* @type {RememberMeToken}
* @memberof RememberMeTokenV1alpha1ApiCreateRememberMeToken
*/
readonly rememberMeToken?: RememberMeToken
}
/**
* Request parameters for deleteRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest {
/**
* Name of remembermetoken
* @type {string}
* @memberof RememberMeTokenV1alpha1ApiDeleteRememberMeToken
*/
readonly name: string
}
/**
* Request parameters for getRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest {
/**
* Name of remembermetoken
* @type {string}
* @memberof RememberMeTokenV1alpha1ApiGetRememberMeToken
*/
readonly name: string
}
/**
* Request parameters for listRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiListRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiListRememberMeTokenRequest {
/**
* Page number. Default is 0.
* @type {number}
* @memberof RememberMeTokenV1alpha1ApiListRememberMeToken
*/
readonly page?: number
/**
* Size number. Default is 0.
* @type {number}
* @memberof RememberMeTokenV1alpha1ApiListRememberMeToken
*/
readonly size?: number
/**
* Label selector. e.g.: hidden!&#x3D;true
* @type {Array<string>}
* @memberof RememberMeTokenV1alpha1ApiListRememberMeToken
*/
readonly labelSelector?: Array<string>
/**
* Field selector. e.g.: metadata.name&#x3D;&#x3D;halo
* @type {Array<string>}
* @memberof RememberMeTokenV1alpha1ApiListRememberMeToken
*/
readonly fieldSelector?: Array<string>
/**
* Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.
* @type {Array<string>}
* @memberof RememberMeTokenV1alpha1ApiListRememberMeToken
*/
readonly sort?: Array<string>
}
/**
* Request parameters for patchRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest {
/**
* Name of remembermetoken
* @type {string}
* @memberof RememberMeTokenV1alpha1ApiPatchRememberMeToken
*/
readonly name: string
/**
*
* @type {Array<JsonPatchInner>}
* @memberof RememberMeTokenV1alpha1ApiPatchRememberMeToken
*/
readonly jsonPatchInner?: Array<JsonPatchInner>
}
/**
* Request parameters for updateRememberMeToken operation in RememberMeTokenV1alpha1Api.
* @export
* @interface RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest
*/
export interface RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest {
/**
* Name of remembermetoken
* @type {string}
* @memberof RememberMeTokenV1alpha1ApiUpdateRememberMeToken
*/
readonly name: string
/**
* Updated remembermetoken
* @type {RememberMeToken}
* @memberof RememberMeTokenV1alpha1ApiUpdateRememberMeToken
*/
readonly rememberMeToken?: RememberMeToken
}
/**
* RememberMeTokenV1alpha1Api - object-oriented interface
* @export
* @class RememberMeTokenV1alpha1Api
* @extends {BaseAPI}
*/
export class RememberMeTokenV1alpha1Api extends BaseAPI {
/**
* Create RememberMeToken
* @param {RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public createRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiCreateRememberMeTokenRequest = {}, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).createRememberMeToken(requestParameters.rememberMeToken, options).then((request) => request(this.axios, this.basePath));
}
/**
* Delete RememberMeToken
* @param {RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public deleteRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiDeleteRememberMeTokenRequest, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).deleteRememberMeToken(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* Get RememberMeToken
* @param {RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public getRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiGetRememberMeTokenRequest, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).getRememberMeToken(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* List RememberMeToken
* @param {RememberMeTokenV1alpha1ApiListRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public listRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiListRememberMeTokenRequest = {}, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).listRememberMeToken(requestParameters.page, requestParameters.size, requestParameters.labelSelector, requestParameters.fieldSelector, requestParameters.sort, options).then((request) => request(this.axios, this.basePath));
}
/**
* Patch RememberMeToken
* @param {RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public patchRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiPatchRememberMeTokenRequest, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).patchRememberMeToken(requestParameters.name, requestParameters.jsonPatchInner, options).then((request) => request(this.axios, this.basePath));
}
/**
* Update RememberMeToken
* @param {RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof RememberMeTokenV1alpha1Api
*/
public updateRememberMeToken(requestParameters: RememberMeTokenV1alpha1ApiUpdateRememberMeTokenRequest, options?: RawAxiosRequestConfig) {
return RememberMeTokenV1alpha1ApiFp(this.configuration).updateRememberMeToken(requestParameters.name, requestParameters.rememberMeToken, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -161,6 +161,9 @@ export * from './reason-type-notifier-request';
export * from './reason-type-spec';
export * from './ref';
export * from './register-verify-email-request';
export * from './remember-me-token';
export * from './remember-me-token-list';
export * from './remember-me-token-spec';
export * from './remove-operation';
export * from './replace-operation';
export * from './reply';

View File

@ -0,0 +1,81 @@
/* tslint:disable */
/* eslint-disable */
/**
* Halo
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 2.17.0-SNAPSHOT
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
// May contain unused imports in some cases
// @ts-ignore
import { RememberMeToken } from './remember-me-token';
/**
*
* @export
* @interface RememberMeTokenList
*/
export interface RememberMeTokenList {
/**
* Indicates whether current page is the first page.
* @type {boolean}
* @memberof RememberMeTokenList
*/
'first': boolean;
/**
* Indicates whether current page has previous page.
* @type {boolean}
* @memberof RememberMeTokenList
*/
'hasNext': boolean;
/**
* Indicates whether current page has previous page.
* @type {boolean}
* @memberof RememberMeTokenList
*/
'hasPrevious': boolean;
/**
* A chunk of items.
* @type {Array<RememberMeToken>}
* @memberof RememberMeTokenList
*/
'items': Array<RememberMeToken>;
/**
* Indicates whether current page is the last page.
* @type {boolean}
* @memberof RememberMeTokenList
*/
'last': boolean;
/**
* Page number, starts from 1. If not set or equal to 0, it means no pagination.
* @type {number}
* @memberof RememberMeTokenList
*/
'page': number;
/**
* Size of each page. If not set or equal to 0, it means no pagination.
* @type {number}
* @memberof RememberMeTokenList
*/
'size': number;
/**
* Total elements.
* @type {number}
* @memberof RememberMeTokenList
*/
'total': number;
/**
* Indicates total pages.
* @type {number}
* @memberof RememberMeTokenList
*/
'totalPages': number;
}

View File

@ -0,0 +1,48 @@
/* tslint:disable */
/* eslint-disable */
/**
* Halo
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 2.17.0-SNAPSHOT
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/**
*
* @export
* @interface RememberMeTokenSpec
*/
export interface RememberMeTokenSpec {
/**
*
* @type {string}
* @memberof RememberMeTokenSpec
*/
'lastUsed'?: string;
/**
*
* @type {string}
* @memberof RememberMeTokenSpec
*/
'series': string;
/**
*
* @type {string}
* @memberof RememberMeTokenSpec
*/
'tokenValue': string;
/**
*
* @type {string}
* @memberof RememberMeTokenSpec
*/
'username': string;
}

View File

@ -0,0 +1,54 @@
/* tslint:disable */
/* eslint-disable */
/**
* Halo
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 2.17.0-SNAPSHOT
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
// May contain unused imports in some cases
// @ts-ignore
import { Metadata } from './metadata';
// May contain unused imports in some cases
// @ts-ignore
import { RememberMeTokenSpec } from './remember-me-token-spec';
/**
*
* @export
* @interface RememberMeToken
*/
export interface RememberMeToken {
/**
*
* @type {string}
* @memberof RememberMeToken
*/
'apiVersion': string;
/**
*
* @type {string}
* @memberof RememberMeToken
*/
'kind': string;
/**
*
* @type {Metadata}
* @memberof RememberMeToken
*/
'metadata': Metadata;
/**
*
* @type {RememberMeTokenSpec}
* @memberof RememberMeToken
*/
'spec': RememberMeTokenSpec;
}