Merge pull request #25 from OnixByte/development
Migrate group id from cn.org.codecrafters to com.onixbyte
This commit is contained in:
@@ -58,8 +58,8 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scm {
|
scm {
|
||||||
connection = "scm:git:git://github.com:CodeCraftersCN/JDevKit.git"
|
connection = "scm:git:git://github.com:OnixByte/JDevKit.git"
|
||||||
developerConnection = "scm:git:git://github.com:CodeCraftersCN/JDevKit.git"
|
developerConnection = "scm:git:git://github.com:OnixByte/JDevKit.git"
|
||||||
url = projectGithubUrl
|
url = projectGithubUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.core.exceptions;
|
package com.onixbyte.devkit.core.exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code NotImplementedException} class is a custom runtime exception
|
* The {@code NotImplementedException} class is a custom runtime exception
|
||||||
+1
-1
@@ -21,4 +21,4 @@
|
|||||||
* @author Zihlu Wang
|
* @author Zihlu Wang
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.devkit.core.exceptions;
|
package com.onixbyte.devkit.core.exceptions;
|
||||||
+1
-1
@@ -40,4 +40,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.devkit.core;
|
package com.onixbyte.devkit.core;
|
||||||
+1
-1
@@ -39,4 +39,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.devkit;
|
package com.onixbyte.devkit;
|
||||||
@@ -51,7 +51,7 @@ implementation 'cn.org.codecrafters:devkit-utils:${devkit-utils.version}'
|
|||||||
If you are trying to encode a string to Base64 string or decode a Base64 string to normal string, then you can try this:
|
If you are trying to encode a string to Base64 string or decode a Base64 string to normal string, then you can try this:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.Base64Util;
|
import utils.com.onixbyte.devkit.Base64Util;
|
||||||
|
|
||||||
// To reduce sample codes, let me use the simplified main method that is upcoming in Java 21
|
// To reduce sample codes, let me use the simplified main method that is upcoming in Java 21
|
||||||
void main(String... args) {
|
void main(String... args) {
|
||||||
@@ -68,7 +68,7 @@ void main(String... args) {
|
|||||||
I believe those `if...else...` blocks make you headache, and Java imported lambda since Java 8, why not try to replace those `if...else` with lambda expressions?
|
I believe those `if...else...` blocks make you headache, and Java imported lambda since Java 8, why not try to replace those `if...else` with lambda expressions?
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.BranchUtil;
|
import utils.com.onixbyte.devkit.BranchUtil;
|
||||||
|
|
||||||
void main(String... args) {
|
void main(String... args) {
|
||||||
var a = 1;
|
var a = 1;
|
||||||
@@ -106,7 +106,7 @@ If you have faced high-precision mathematical calculation in Java, you might kno
|
|||||||
In Java, we usually do high-precision mathematical calculation with `BigDecimal` which is quite tricky when using it.
|
In Java, we usually do high-precision mathematical calculation with `BigDecimal` which is quite tricky when using it.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.ChainedCalcUtil;
|
import utils.com.onixbyte.devkit.ChainedCalcUtil;
|
||||||
|
|
||||||
void main(String... args) {
|
void main(String... args) {
|
||||||
// If you are trying to calculate the expression of 1 * 2 / 2 - 3 + 4
|
// If you are trying to calculate the expression of 1 * 2 / 2 - 3 + 4
|
||||||
@@ -133,7 +133,7 @@ This `HashUtil` supports these following hash or message digest algorithms:
|
|||||||
If you want to run a hash calculation to a string, you can use the following codes:
|
If you want to run a hash calculation to a string, you can use the following codes:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.HashUtil;
|
import utils.com.onixbyte.devkit.HashUtil;
|
||||||
|
|
||||||
void main(String... args) {
|
void main(String... args) {
|
||||||
var plaintext = "This is a plain text";
|
var plaintext = "This is a plain text";
|
||||||
@@ -156,7 +156,7 @@ Imagine you are developing a website where users can register an account and sto
|
|||||||
In order to store the Map in a database, you need to convert the Map to an Object. An Object is a generic data type that can store any type of data.
|
In order to store the Map in a database, you need to convert the Map to an Object. An Object is a generic data type that can store any type of data.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.MapUtil;
|
import utils.com.onixbyte.devkit.MapUtil;
|
||||||
|
|
||||||
class Data {
|
class Data {
|
||||||
private String name;
|
private String name;
|
||||||
|
|||||||
+17
-8
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@@ -44,13 +44,6 @@ import java.util.UUID;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public final class AesUtil {
|
public final class AesUtil {
|
||||||
|
|
||||||
private AesUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String AES = "AES";
|
|
||||||
|
|
||||||
private static final String AES_CBC_CIPHER = "AES/CBC/PKCS5Padding";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts the data using the AES algorithm with the given secret.
|
* Encrypts the data using the AES algorithm with the given secret.
|
||||||
*
|
*
|
||||||
@@ -133,4 +126,20 @@ public final class AesUtil {
|
|||||||
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
|
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor will protect this class from being instantiated.
|
||||||
|
*/
|
||||||
|
private AesUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm AES.
|
||||||
|
*/
|
||||||
|
private static final String AES = "AES";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm AES/CBC/PKCS5Padding.
|
||||||
|
*/
|
||||||
|
private static final String AES_CBC_CIPHER = "AES/CBC/PKCS5Padding";
|
||||||
|
|
||||||
}
|
}
|
||||||
+9
-9
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -56,14 +56,6 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class Base64Util {
|
public final class Base64Util {
|
||||||
|
|
||||||
private static Base64.Encoder encoder;
|
|
||||||
|
|
||||||
private static Base64.Decoder decoder;
|
|
||||||
|
|
||||||
private static Base64.Encoder urlEncoder;
|
|
||||||
|
|
||||||
private static Base64.Decoder urlDecoder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that there is only one Base64 Encoder.
|
* Ensure that there is only one Base64 Encoder.
|
||||||
*
|
*
|
||||||
@@ -210,4 +202,12 @@ public final class Base64Util {
|
|||||||
return decodeUrlComponents(value, StandardCharsets.UTF_8);
|
return decodeUrlComponents(value, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Base64.Encoder encoder;
|
||||||
|
|
||||||
|
private static Base64.Decoder decoder;
|
||||||
|
|
||||||
|
private static Base64.Encoder urlEncoder;
|
||||||
|
|
||||||
|
private static Base64.Decoder urlDecoder;
|
||||||
|
|
||||||
}
|
}
|
||||||
+6
-6
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -77,11 +77,6 @@ import java.util.function.Supplier;
|
|||||||
*/
|
*/
|
||||||
public final class BranchUtil<T> {
|
public final class BranchUtil<T> {
|
||||||
|
|
||||||
/**
|
|
||||||
* The final result of the boolean expression.
|
|
||||||
*/
|
|
||||||
private final boolean result;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@code BranchUtil} instance.
|
* Create a {@code BranchUtil} instance.
|
||||||
*
|
*
|
||||||
@@ -239,4 +234,9 @@ public final class BranchUtil<T> {
|
|||||||
handle(ifHandler, null);
|
handle(ifHandler, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The final result of the boolean expression.
|
||||||
|
*/
|
||||||
|
private final boolean result;
|
||||||
|
|
||||||
}
|
}
|
||||||
+7
-7
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -95,12 +95,6 @@ import java.util.function.Function;
|
|||||||
@Getter
|
@Getter
|
||||||
public final class ChainedCalcUtil {
|
public final class ChainedCalcUtil {
|
||||||
|
|
||||||
/**
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns the current value as a BigDecimal.
|
|
||||||
*/
|
|
||||||
private BigDecimal value;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code ChainedCalcUtil} instance with the specified initial
|
* Creates a {@code ChainedCalcUtil} instance with the specified initial
|
||||||
* value.
|
* value.
|
||||||
@@ -359,4 +353,10 @@ public final class ChainedCalcUtil {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the current value as a BigDecimal.
|
||||||
|
*/
|
||||||
|
private BigDecimal value;
|
||||||
|
|
||||||
}
|
}
|
||||||
+43
-43
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -69,48 +69,6 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public final class HashUtil {
|
public final class HashUtil {
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor to prevent instantiation
|
|
||||||
*/
|
|
||||||
private HashUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the hash value of the specified string using the specified
|
|
||||||
* algorithm and charset.
|
|
||||||
*
|
|
||||||
* @param method the hash algorithm to use
|
|
||||||
* @param value the string to calculate the hash value for
|
|
||||||
* @param charset the charset to use for encoding the string (default is
|
|
||||||
* UTF-8 if null)
|
|
||||||
* @return the hash value as a hexadecimal string, or an empty string if
|
|
||||||
* the algorithm is not available
|
|
||||||
* @throws RuntimeException if an unknown algorithm name is provided
|
|
||||||
* (should not occur under controlled usage)
|
|
||||||
*/
|
|
||||||
private static String hash(String method, String value, Charset charset) {
|
|
||||||
try {
|
|
||||||
var messageDigest = MessageDigest.getInstance(method);
|
|
||||||
messageDigest.update(value.getBytes(charset));
|
|
||||||
var bytes = messageDigest.digest();
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
|
|
||||||
for (var b : bytes) {
|
|
||||||
var str = Integer.toHexString(b & 0xff);
|
|
||||||
if (str.length() == 1) {
|
|
||||||
builder.append(0);
|
|
||||||
}
|
|
||||||
builder.append(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
} catch (NoSuchAlgorithmException ignored) {
|
|
||||||
// This should not occur under controlled usage
|
|
||||||
// Only trusted algorithms are allowed
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the MD2 hash value of the specified string using the given
|
* Calculates the MD2 hash value of the specified string using the given
|
||||||
* charset.
|
* charset.
|
||||||
@@ -286,4 +244,46 @@ public final class HashUtil {
|
|||||||
return hash("SHA-512", value, StandardCharsets.UTF_8);
|
return hash("SHA-512", value, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor will protect this class from being instantiated.
|
||||||
|
*/
|
||||||
|
private HashUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the hash value of the specified string using the specified
|
||||||
|
* algorithm and charset.
|
||||||
|
*
|
||||||
|
* @param method the hash algorithm to use
|
||||||
|
* @param value the string to calculate the hash value for
|
||||||
|
* @param charset the charset to use for encoding the string (default is
|
||||||
|
* UTF-8 if null)
|
||||||
|
* @return the hash value as a hexadecimal string, or an empty string if
|
||||||
|
* the algorithm is not available
|
||||||
|
* @throws RuntimeException if an unknown algorithm name is provided
|
||||||
|
* (should not occur under controlled usage)
|
||||||
|
*/
|
||||||
|
private static String hash(String method, String value, Charset charset) {
|
||||||
|
try {
|
||||||
|
var messageDigest = MessageDigest.getInstance(method);
|
||||||
|
messageDigest.update(value.getBytes(charset));
|
||||||
|
var bytes = messageDigest.digest();
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (var b : bytes) {
|
||||||
|
var str = Integer.toHexString(b & 0xff);
|
||||||
|
if (str.length() == 1) {
|
||||||
|
builder.append(0);
|
||||||
|
}
|
||||||
|
builder.append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
} catch (NoSuchAlgorithmException ignored) {
|
||||||
|
// This should not occur under controlled usage
|
||||||
|
// Only trusted algorithms are allowed
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+7
-7
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@@ -37,12 +37,6 @@ import java.util.Map;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public final class MapUtil {
|
public final class MapUtil {
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor to prevent instantiation of MapUtil.
|
|
||||||
*/
|
|
||||||
private MapUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an object to a map by mapping the field names to their
|
* Converts an object to a map by mapping the field names to their
|
||||||
* corresponding values.
|
* corresponding values.
|
||||||
@@ -219,4 +213,10 @@ public final class MapUtil {
|
|||||||
return String.valueOf(obj);
|
return String.valueOf(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor will protect this class from being instantiated.
|
||||||
|
*/
|
||||||
|
private MapUtil() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -25,4 +25,4 @@
|
|||||||
* @author Zihlu Wang
|
* @author Zihlu Wang
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
+3
-3
@@ -26,9 +26,9 @@ okhttpVersion=4.12.0
|
|||||||
springVersion=6.1.3
|
springVersion=6.1.3
|
||||||
springBootVersion=3.2.3
|
springBootVersion=3.2.3
|
||||||
|
|
||||||
buildGroupId=cn.org.codecrafters
|
buildGroupId=com.onixbyte
|
||||||
buildVersion=1.4.0
|
buildVersion=1.4.0
|
||||||
projectUrl=https://codecrafters.org.cn/JDevKit
|
projectUrl=https://onixbyte.com/JDevKit
|
||||||
projectGithubUrl=https://github.com/CodeCraftersCN/JDevKit
|
projectGithubUrl=https://github.com/OnixByte/JDevKit
|
||||||
licenseName=The Apache License, Version 2.0
|
licenseName=The Apache License, Version 2.0
|
||||||
licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.txt
|
licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.txt
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.guid;
|
package com.onixbyte.guid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code GuidCreator} is a generic interface for generating globally unique
|
* The {@code GuidCreator} is a generic interface for generating globally unique
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.guid.exceptions;
|
package com.onixbyte.guid.exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code TimingException} class represents an exception that is thrown
|
* The {@code TimingException} class represents an exception that is thrown
|
||||||
+2
-2
@@ -21,7 +21,7 @@
|
|||||||
* during the generation or processing of global unique identifiers (GUIDs).
|
* during the generation or processing of global unique identifiers (GUIDs).
|
||||||
* <p>
|
* <p>
|
||||||
* The main exception class in this package is {@link
|
* The main exception class in this package is {@link
|
||||||
* cn.org.codecrafters.guid.exceptions.TimingException}, which is a runtime
|
* com.onixbyte.guid.exceptions.TimingException}, which is a runtime
|
||||||
* exception and serves as the base exception for all other custom exceptions
|
* exception and serves as the base exception for all other custom exceptions
|
||||||
* related to GUID generation.
|
* related to GUID generation.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -38,4 +38,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.guid.exceptions;
|
package com.onixbyte.guid.exceptions;
|
||||||
+46
-45
@@ -15,13 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.guid;
|
package com.onixbyte.guid.impl;
|
||||||
|
|
||||||
import cn.org.codecrafters.guid.exceptions.TimingException;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
|
import com.onixbyte.guid.exceptions.TimingException;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code SnowflakeGuidCreator} generates unique identifiers using the
|
* The {@code SnowflakeGuidCreator} generates unique identifiers using the
|
||||||
@@ -49,48 +49,6 @@ import java.time.ZoneOffset;
|
|||||||
*/
|
*/
|
||||||
public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default custom epoch.
|
|
||||||
*
|
|
||||||
* @value 2015-01-01T00:00:00Z
|
|
||||||
*/
|
|
||||||
private static final long DEFAULT_CUSTOM_EPOCH = 1_420_070_400_000L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The start epoch timestamp to generate IDs from.
|
|
||||||
*/
|
|
||||||
private final long startEpoch;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of bits reserved for the worker ID.
|
|
||||||
*/
|
|
||||||
private final long workerIdBits = 5L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of bits reserved for the data centre ID.
|
|
||||||
*/
|
|
||||||
private final long dataCentreIdBits = 5L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The worker ID assigned to this generator.
|
|
||||||
*/
|
|
||||||
private final long workerId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data centre ID assigned to this generator.
|
|
||||||
*/
|
|
||||||
private final long dataCentreId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current sequence number.
|
|
||||||
*/
|
|
||||||
private long sequence = 0L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The timestamp of the last generated ID.
|
|
||||||
*/
|
|
||||||
private long lastTimestamp = -1L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a SnowflakeGuidGenerator with the default start epoch and
|
* Constructs a SnowflakeGuidGenerator with the default start epoch and
|
||||||
* custom worker ID, data centre ID.
|
* custom worker ID, data centre ID.
|
||||||
@@ -204,5 +162,48 @@ public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
|||||||
private long currentTimestamp() {
|
private long currentTimestamp() {
|
||||||
return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default custom epoch.
|
||||||
|
*
|
||||||
|
* @value 2015-01-01T00:00:00Z
|
||||||
|
*/
|
||||||
|
private static final long DEFAULT_CUSTOM_EPOCH = 1_420_070_400_000L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start epoch timestamp to generate IDs from.
|
||||||
|
*/
|
||||||
|
private final long startEpoch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of bits reserved for the worker ID.
|
||||||
|
*/
|
||||||
|
private final long workerIdBits = 5L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of bits reserved for the data centre ID.
|
||||||
|
*/
|
||||||
|
private final long dataCentreIdBits = 5L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The worker ID assigned to this generator.
|
||||||
|
*/
|
||||||
|
private final long workerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data centre ID assigned to this generator.
|
||||||
|
*/
|
||||||
|
private final long dataCentreId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current sequence number.
|
||||||
|
*/
|
||||||
|
private long sequence = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timestamp of the last generated ID.
|
||||||
|
*/
|
||||||
|
private long lastTimestamp = -1L;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
-1
@@ -32,4 +32,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.guid;
|
package com.onixbyte.guid;
|
||||||
@@ -48,12 +48,12 @@ implementation 'cn.org.codecrafters:property-guard-spring-boot-starter:${propert
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
First, you need a 16-bit-long secret. If you don't have a good way to get a secret, you could consider using our `cn.org.codecrafters.devkit.utils.AesUtil` or `cn.org.codecrafters.simplejwt.SecretCreator` to create a secret.
|
First, you need a 16-bit-long secret. If you don't have a good way to get a secret, you could consider using our `utils.com.onixbyte.devkit.AesUtil` or `com.onixbyte.simplejwt.SecretCreator` to create a secret.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.AesUtil;
|
import utils.com.onixbyte.devkit.AesUtil;
|
||||||
import cn.org.codecrafters.simplejwt.SecretCreator;
|
import com.onixbyte.simplejwt.SecretCreator;
|
||||||
|
|
||||||
class GenerateRandomKeySample {
|
class GenerateRandomKeySample {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@@ -66,7 +66,7 @@ class GenerateRandomKeySample {
|
|||||||
Then, remember this secret and encrypt the configuration properties that are required high security. For example:
|
Then, remember this secret and encrypt the configuration properties that are required high security. For example:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import cn.org.codecrafters.devkit.utils.AesUtil;
|
import utils.com.onixbyte.devkit.AesUtil;
|
||||||
|
|
||||||
class EncryptSample {
|
class EncryptSample {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
+4
-4
@@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.propertyguard.autoconfiguration;
|
package com.onixbyte.propertyguard.autoconfiguration;
|
||||||
|
|
||||||
import cn.org.codecrafters.devkit.utils.AesUtil;
|
import com.onixbyte.devkit.utils.AesUtil;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
import org.springframework.boot.env.OriginTrackedMapPropertySource;
|
import org.springframework.boot.env.OriginTrackedMapPropertySource;
|
||||||
@@ -70,8 +70,6 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public class PropertyGuard implements EnvironmentPostProcessor {
|
public class PropertyGuard implements EnvironmentPostProcessor {
|
||||||
|
|
||||||
private final String PREFIX = "pg";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the encryption environment variables.
|
* Process the encryption environment variables.
|
||||||
*
|
*
|
||||||
@@ -108,4 +106,6 @@ public class PropertyGuard implements EnvironmentPostProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String PREFIX = "pg";
|
||||||
}
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
org.springframework.boot.env.EnvironmentPostProcessor=cn.org.codecrafters.propertyguard.autoconfiguration.PropertyGuard
|
org.springframework.boot.env.EnvironmentPostProcessor=com.onixbyte.propertyguard.autoconfiguration.PropertyGuard
|
||||||
@@ -50,7 +50,7 @@ implementation 'cn.org.codecrafters:simple-jwt-authzero:${simple-jwt-authzero.ve
|
|||||||
|
|
||||||
## Use the `AuthzeroTokenResolver`
|
## Use the `AuthzeroTokenResolver`
|
||||||
|
|
||||||
We have implemented `TokenResolver` to make sure you can add JWT to your Java application as soon as possible. All you need to do is to create an instance of `cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver` and other operations to JWT could follow our instruction in [`simple-jwt-facade`](../simple-jwt-facade/README.md).
|
We have implemented `TokenResolver` to make sure you can add JWT to your Java application as soon as possible. All you need to do is to create an instance of `com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver` and other operations to JWT could follow our instruction in [`simple-jwt-facade`](../simple-jwt-facade/README.md).
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
|
|||||||
+142
-144
@@ -15,34 +15,29 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.authzero;
|
package com.onixbyte.simplejwt.authzero;
|
||||||
|
|
||||||
import cn.org.codecrafters.devkit.utils.Base64Util;
|
import com.onixbyte.devkit.utils.Base64Util;
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import cn.org.codecrafters.simplejwt.SecretCreator;
|
import com.onixbyte.simplejwt.SecretCreator;
|
||||||
import cn.org.codecrafters.simplejwt.TokenPayload;
|
import com.onixbyte.simplejwt.TokenPayload;
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.annotations.ExcludeFromPayload;
|
import com.onixbyte.simplejwt.annotations.ExcludeFromPayload;
|
||||||
import cn.org.codecrafters.simplejwt.annotations.TokenEnum;
|
import com.onixbyte.simplejwt.annotations.TokenEnum;
|
||||||
import cn.org.codecrafters.simplejwt.authzero.config.AuthzeroTokenResolverConfig;
|
import com.onixbyte.simplejwt.authzero.config.AuthzeroTokenResolverConfig;
|
||||||
import cn.org.codecrafters.simplejwt.config.TokenResolverConfig;
|
import com.onixbyte.simplejwt.constants.PredefinedKeys;
|
||||||
import cn.org.codecrafters.simplejwt.constants.PredefinedKeys;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
|
||||||
import com.auth0.jwt.JWT;
|
import com.auth0.jwt.JWT;
|
||||||
import com.auth0.jwt.JWTCreator;
|
import com.auth0.jwt.JWTCreator;
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
import com.auth0.jwt.interfaces.Claim;
|
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -51,7 +46,7 @@ import java.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code AuthzeroTokenResolver} class is an implementation of the {@link
|
* The {@code AuthzeroTokenResolver} class is an implementation of the {@link
|
||||||
* cn.org.codecrafters.simplejwt.TokenResolver} interface. It uses the {@code
|
* TokenResolver} interface. It uses the {@code
|
||||||
* com.auth0:java-jwt} library to handle JSON Web Token (JWT) resolution. This
|
* com.auth0:java-jwt} library to handle JSON Web Token (JWT) resolution. This
|
||||||
* resolver provides functionality to create, extract, verify, and renew JWT
|
* resolver provides functionality to create, extract, verify, and renew JWT
|
||||||
* tokens using various algorithms and custom payload data.
|
* tokens using various algorithms and custom payload data.
|
||||||
@@ -104,34 +99,6 @@ import java.util.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
||||||
|
|
||||||
/**
|
|
||||||
* GuidCreator used for generating unique identifiers for "jti" claim in
|
|
||||||
* JWT tokens.
|
|
||||||
*/
|
|
||||||
private final GuidCreator<?> jtiCreator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The algorithm used for signing and verifying JWT tokens.
|
|
||||||
*/
|
|
||||||
private final Algorithm algorithm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The issuer claim value to be included in JWT tokens.
|
|
||||||
*/
|
|
||||||
private final String issuer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The JSON Web Token resolver.
|
|
||||||
*/
|
|
||||||
private final JWTVerifier verifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jackson JSON handler.
|
|
||||||
*/
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
private final AuthzeroTokenResolverConfig config = AuthzeroTokenResolverConfig.getInstance();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of {@code AuthzeroTokenResolver} with the
|
* Creates a new instance of {@code AuthzeroTokenResolver} with the
|
||||||
* provided configurations.
|
* provided configurations.
|
||||||
@@ -150,7 +117,7 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
|
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secret.length() <= 32) {
|
if (secret.length() < 32) {
|
||||||
log.warn("The provided secret which owns {} characters is too weak. Please consider replacing it with a stronger one.", secret.length());
|
log.warn("The provided secret which owns {} characters is too weak. Please consider replacing it with a stronger one.", secret.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,104 +191,6 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
log.info("The secret has been set to {}.", secret);
|
log.info("The secret has been set to {}.", secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the basic information of the JSON Web Token (JWT) using the
|
|
||||||
* provided parameters and adds it to the JWTCreator.Builder.
|
|
||||||
*
|
|
||||||
* @param subject the subject claim value to be included in the JWT
|
|
||||||
* @param audience an array of audience claim values to be included in
|
|
||||||
* the JWT
|
|
||||||
* @param expireAfter the duration after which the JWT will expire
|
|
||||||
* @param builder the JWTCreator.Builder instance to which the basic
|
|
||||||
* information will be added
|
|
||||||
*/
|
|
||||||
private void buildBasicInfo(JWTCreator.Builder builder, Duration expireAfter, String subject, String... audience) {
|
|
||||||
var now = LocalDateTime.now();
|
|
||||||
|
|
||||||
// bind issuer (iss)
|
|
||||||
builder.withIssuer(issuer);
|
|
||||||
// bind issued at (iat)
|
|
||||||
builder.withIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
|
|
||||||
// bind not before (nbf)
|
|
||||||
builder.withNotBefore(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
|
|
||||||
// bind audience (aud)
|
|
||||||
builder.withAudience(audience);
|
|
||||||
// bind subject (sub)
|
|
||||||
builder.withSubject(subject);
|
|
||||||
// bind expire at (exp)
|
|
||||||
builder.withExpiresAt(Date.from(now.plus(expireAfter).atZone(ZoneId.systemDefault()).toInstant()));
|
|
||||||
// bind JWT Id (jti)
|
|
||||||
builder.withJWTId(jtiCreator.nextId().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a claim to a builder.
|
|
||||||
*
|
|
||||||
* @param builder the builder to build this JSON Web Token
|
|
||||||
* @param name the property name
|
|
||||||
* @param value the property value
|
|
||||||
*/
|
|
||||||
private void addClaim(JWTCreator.Builder builder, String name, Object value) {
|
|
||||||
if (Objects.nonNull(value)) {
|
|
||||||
if (value instanceof Boolean v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof Double v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof Float v) {
|
|
||||||
builder.withClaim(name, v.doubleValue());
|
|
||||||
} else if (value instanceof Integer v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof Long v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof String v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof Date v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else if (value instanceof List<?> v) {
|
|
||||||
builder.withClaim(name, v);
|
|
||||||
} else {
|
|
||||||
log.warn("""
|
|
||||||
Unable to determine the type of field {}, we will handle it as a String.""", name);
|
|
||||||
builder.withClaim(name, value.toString());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
builder.withNullClaim(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the custom claims of the JSON Web Token (JWT) using the provided
|
|
||||||
* Map of claims and adds them to the JWTCreator.Builder.
|
|
||||||
* <p>
|
|
||||||
* This method is used to add custom claims to the JWT. It takes a Map of
|
|
||||||
* claims, where each entry represents a custom claim name (key) and its
|
|
||||||
* corresponding value (value). The custom claims will be added to the JWT
|
|
||||||
* using the JWTCreator.Builder.
|
|
||||||
*
|
|
||||||
* @param claims a Map containing the custom claims to be added to the JWT
|
|
||||||
* @param builder the JWTCreator.Builder instance to which the custom
|
|
||||||
* claims will be added
|
|
||||||
*/
|
|
||||||
private void buildMapClaims(JWTCreator.Builder builder, Map<String, Object> claims) {
|
|
||||||
if (Objects.nonNull(claims)) {
|
|
||||||
for (var e : claims.entrySet()) {
|
|
||||||
addClaim(builder, e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish creating a token.
|
|
||||||
* <p>
|
|
||||||
* This is the final step of create a token, to sign this token.
|
|
||||||
*
|
|
||||||
* @param builder the builder to build this JWT
|
|
||||||
* @return the generated token as a {@code String}
|
|
||||||
*/
|
|
||||||
private String buildToken(JWTCreator.Builder builder) {
|
|
||||||
return builder.sign(algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new token with the specified expiration duration, subject, and
|
* Creates a new token with the specified expiration duration, subject, and
|
||||||
* audience.
|
* audience.
|
||||||
@@ -552,8 +421,137 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
return renew(oldToken, Duration.ofMinutes(30), payload);
|
return renew(oldToken, Duration.ofMinutes(30), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the basic information of the JSON Web Token (JWT) using the
|
||||||
|
* provided parameters and adds it to the JWTCreator.Builder.
|
||||||
|
*
|
||||||
|
* @param subject the subject claim value to be included in the JWT
|
||||||
|
* @param audience an array of audience claim values to be included in
|
||||||
|
* the JWT
|
||||||
|
* @param expireAfter the duration after which the JWT will expire
|
||||||
|
* @param builder the JWTCreator.Builder instance to which the basic
|
||||||
|
* information will be added
|
||||||
|
*/
|
||||||
|
private void buildBasicInfo(JWTCreator.Builder builder, Duration expireAfter, String subject, String... audience) {
|
||||||
|
var now = LocalDateTime.now();
|
||||||
|
|
||||||
|
// bind issuer (iss)
|
||||||
|
builder.withIssuer(issuer);
|
||||||
|
// bind issued at (iat)
|
||||||
|
builder.withIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
// bind not before (nbf)
|
||||||
|
builder.withNotBefore(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
// bind audience (aud)
|
||||||
|
builder.withAudience(audience);
|
||||||
|
// bind subject (sub)
|
||||||
|
builder.withSubject(subject);
|
||||||
|
// bind expire at (exp)
|
||||||
|
builder.withExpiresAt(Date.from(now.plus(expireAfter).atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
// bind JWT Id (jti)
|
||||||
|
builder.withJWTId(jtiCreator.nextId().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a claim to a builder.
|
||||||
|
*
|
||||||
|
* @param builder the builder to build this JSON Web Token
|
||||||
|
* @param name the property name
|
||||||
|
* @param value the property value
|
||||||
|
*/
|
||||||
|
private void addClaim(JWTCreator.Builder builder, String name, Object value) {
|
||||||
|
if (Objects.nonNull(value)) {
|
||||||
|
if (value instanceof Boolean v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof Double v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof Float v) {
|
||||||
|
builder.withClaim(name, v.doubleValue());
|
||||||
|
} else if (value instanceof Integer v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof Long v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof String v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof Date v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else if (value instanceof List<?> v) {
|
||||||
|
builder.withClaim(name, v);
|
||||||
|
} else {
|
||||||
|
log.warn("""
|
||||||
|
Unable to determine the type of field {}, we will handle it as a String.""", name);
|
||||||
|
builder.withClaim(name, value.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.withNullClaim(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the custom claims of the JSON Web Token (JWT) using the provided
|
||||||
|
* Map of claims and adds them to the JWTCreator.Builder.
|
||||||
|
* <p>
|
||||||
|
* This method is used to add custom claims to the JWT. It takes a Map of
|
||||||
|
* claims, where each entry represents a custom claim name (key) and its
|
||||||
|
* corresponding value (value). The custom claims will be added to the JWT
|
||||||
|
* using the JWTCreator.Builder.
|
||||||
|
*
|
||||||
|
* @param claims a Map containing the custom claims to be added to the JWT
|
||||||
|
* @param builder the JWTCreator.Builder instance to which the custom
|
||||||
|
* claims will be added
|
||||||
|
*/
|
||||||
|
private void buildMapClaims(JWTCreator.Builder builder, Map<String, Object> claims) {
|
||||||
|
if (Objects.nonNull(claims)) {
|
||||||
|
for (var e : claims.entrySet()) {
|
||||||
|
addClaim(builder, e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish creating a token.
|
||||||
|
* <p>
|
||||||
|
* This is the final step of create a token, to sign this token.
|
||||||
|
*
|
||||||
|
* @param builder the builder to build this JWT
|
||||||
|
* @return the generated token as a {@code String}
|
||||||
|
*/
|
||||||
|
private String buildToken(JWTCreator.Builder builder) {
|
||||||
|
return builder.sign(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default type reference for Map.
|
||||||
|
*/
|
||||||
private static class MapTypeReference extends TypeReference<Map<String, Object>> {
|
private static class MapTypeReference extends TypeReference<Map<String, Object>> {
|
||||||
MapTypeReference() {
|
MapTypeReference() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GuidCreator used for generating unique identifiers for "jti" claim in
|
||||||
|
* JWT tokens.
|
||||||
|
*/
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm used for signing and verifying JWT tokens.
|
||||||
|
*/
|
||||||
|
private final Algorithm algorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The issuer claim value to be included in JWT tokens.
|
||||||
|
*/
|
||||||
|
private final String issuer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JSON Web Token resolver.
|
||||||
|
*/
|
||||||
|
private final JWTVerifier verifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jackson JSON handler.
|
||||||
|
*/
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private final AuthzeroTokenResolverConfig config = AuthzeroTokenResolverConfig.getInstance();
|
||||||
}
|
}
|
||||||
+42
-42
@@ -15,13 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.authzero.config;
|
package com.onixbyte.simplejwt.authzero.config;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver;
|
import com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.config.TokenResolverConfig;
|
import com.onixbyte.simplejwt.config.TokenResolverConfig;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
import cn.org.codecrafters.simplejwt.exceptions.UnsupportedAlgorithmException;
|
import com.onixbyte.simplejwt.exceptions.UnsupportedAlgorithmException;
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -62,42 +62,6 @@ import java.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
public final class AuthzeroTokenResolverConfig implements TokenResolverConfig<Function<String, Algorithm>> {
|
public final class AuthzeroTokenResolverConfig implements TokenResolverConfig<Function<String, Algorithm>> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of {@code AuthzeroTokenResolverConfig}.
|
|
||||||
* <p>
|
|
||||||
* The constructor is set as private to enforce the singleton pattern for
|
|
||||||
* this configuration class. Instances of
|
|
||||||
* {@code AuthzeroTokenResolverConfig} should be obtained through the
|
|
||||||
* {@link #getInstance()} method.
|
|
||||||
*/
|
|
||||||
private AuthzeroTokenResolverConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The singleton instance of {@code AuthzeroTokenResolverConfig}.
|
|
||||||
* <p>
|
|
||||||
* This instance is used to ensure that only one instance of
|
|
||||||
* {@code AuthzeroTokenResolverConfig} is created and shared throughout the
|
|
||||||
* application. The singleton pattern is implemented to provide centralised
|
|
||||||
* configuration and avoid redundant object creation.
|
|
||||||
*/
|
|
||||||
private static AuthzeroTokenResolverConfig instance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The supported algorithms and their corresponding algorithm functions.
|
|
||||||
* <p>
|
|
||||||
* This map stores the supported algorithms as keys and their corresponding
|
|
||||||
* algorithm functions as values. The algorithm functions represent the
|
|
||||||
* functions used by the {@code com.auth0:java-jwt} library to handle the
|
|
||||||
* specific algorithms. The mapping is used to provide proper algorithm
|
|
||||||
* resolution and processing within the {@link AuthzeroTokenResolver}.
|
|
||||||
*/
|
|
||||||
private static final Map<TokenAlgorithm, Function<String, Algorithm>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
|
|
||||||
put(TokenAlgorithm.HS256, Algorithm::HMAC256);
|
|
||||||
put(TokenAlgorithm.HS384, Algorithm::HMAC384);
|
|
||||||
put(TokenAlgorithm.HS512, Algorithm::HMAC512);
|
|
||||||
}};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the instance of {@code AuthzeroTokenResolverConfig}.
|
* Gets the instance of {@code AuthzeroTokenResolverConfig}.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -140,4 +104,40 @@ public final class AuthzeroTokenResolverConfig implements TokenResolverConfig<Fu
|
|||||||
return Optional.of(SUPPORTED_ALGORITHMS).map((entry) -> entry.get(algorithm))
|
return Optional.of(SUPPORTED_ALGORITHMS).map((entry) -> entry.get(algorithm))
|
||||||
.orElseThrow(() -> new UnsupportedAlgorithmException("The specified algorithm is not supported yet."));
|
.orElseThrow(() -> new UnsupportedAlgorithmException("The specified algorithm is not supported yet."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of {@code AuthzeroTokenResolverConfig}.
|
||||||
|
* <p>
|
||||||
|
* The constructor is set as private to enforce the singleton pattern for
|
||||||
|
* this configuration class. Instances of
|
||||||
|
* {@code AuthzeroTokenResolverConfig} should be obtained through the
|
||||||
|
* {@link #getInstance()} method.
|
||||||
|
*/
|
||||||
|
private AuthzeroTokenResolverConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The singleton instance of {@code AuthzeroTokenResolverConfig}.
|
||||||
|
* <p>
|
||||||
|
* This instance is used to ensure that only one instance of
|
||||||
|
* {@code AuthzeroTokenResolverConfig} is created and shared throughout the
|
||||||
|
* application. The singleton pattern is implemented to provide centralised
|
||||||
|
* configuration and avoid redundant object creation.
|
||||||
|
*/
|
||||||
|
private static AuthzeroTokenResolverConfig instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported algorithms and their corresponding algorithm functions.
|
||||||
|
* <p>
|
||||||
|
* This map stores the supported algorithms as keys and their corresponding
|
||||||
|
* algorithm functions as values. The algorithm functions represent the
|
||||||
|
* functions used by the {@code com.auth0:java-jwt} library to handle the
|
||||||
|
* specific algorithms. The mapping is used to provide proper algorithm
|
||||||
|
* resolution and processing within the {@link AuthzeroTokenResolver}.
|
||||||
|
*/
|
||||||
|
private static final Map<TokenAlgorithm, Function<String, Algorithm>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
|
||||||
|
put(TokenAlgorithm.HS256, Algorithm::HMAC256);
|
||||||
|
put(TokenAlgorithm.HS384, Algorithm::HMAC384);
|
||||||
|
put(TokenAlgorithm.HS512, Algorithm::HMAC512);
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
+8
-8
@@ -18,37 +18,37 @@
|
|||||||
/**
|
/**
|
||||||
* The package {@code cn.org.codecrafters.simplejwt.authzero.config} contains
|
* The package {@code cn.org.codecrafters.simplejwt.authzero.config} contains
|
||||||
* configuration classes related to the {@link
|
* configuration classes related to the {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver}
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver}
|
||||||
* implementation.
|
* implementation.
|
||||||
* <p>
|
* <p>
|
||||||
* The classes in this package provide configuration options and settings for
|
* The classes in this package provide configuration options and settings for
|
||||||
* the {@link cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver},
|
* the {@link com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver},
|
||||||
* which is used for resolving JSON Web Tokens (JWT) using the Auth0 library.
|
* which is used for resolving JSON Web Tokens (JWT) using the Auth0 library.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link
|
* The {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.config.AuthzeroTokenResolverConfig}
|
* com.onixbyte.simplejwt.authzero.config.AuthzeroTokenResolverConfig}
|
||||||
* class is a configuration class that defines the mapping between standard
|
* class is a configuration class that defines the mapping between standard
|
||||||
* {@link cn.org.codecrafters.simplejwt.constants.TokenAlgorithm} and the
|
* {@link com.onixbyte.simplejwt.constants.TokenAlgorithm} and the
|
||||||
* corresponding function implementation used by {@link
|
* corresponding function implementation used by {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver} for handling
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver} for handling
|
||||||
* JWT algorithms. It enables developers to specify and customize the
|
* JWT algorithms. It enables developers to specify and customize the
|
||||||
* algorithm functions according to the chosen JWT algorithm and the library
|
* algorithm functions according to the chosen JWT algorithm and the library
|
||||||
* being used.
|
* being used.
|
||||||
* <p>
|
* <p>
|
||||||
* The configuration options in this package help developers integrate and
|
* The configuration options in this package help developers integrate and
|
||||||
* configure the {@link
|
* configure the {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver} seamlessly
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver} seamlessly
|
||||||
* into their Spring Boot applications. Developers can fine-tune the token
|
* into their Spring Boot applications. Developers can fine-tune the token
|
||||||
* resolution process and customize algorithm handling to align with their
|
* resolution process and customize algorithm handling to align with their
|
||||||
* specific requirements and desired level of security.
|
* specific requirements and desired level of security.
|
||||||
* <p>
|
* <p>
|
||||||
* It is recommended to explore the classes in this package to understand how
|
* It is recommended to explore the classes in this package to understand how
|
||||||
* to configure and use the {@link
|
* to configure and use the {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver} effectively
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver} effectively
|
||||||
* in the Spring Boot environment to handle JWT authentication and
|
* in the Spring Boot environment to handle JWT authentication and
|
||||||
* authorisation securely and efficiently.
|
* authorisation securely and efficiently.
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.authzero.config;
|
package com.onixbyte.simplejwt.authzero.config;
|
||||||
+7
-7
@@ -25,15 +25,15 @@
|
|||||||
* the {@code com.auth0:java-jwt} library.
|
* the {@code com.auth0:java-jwt} library.
|
||||||
* <p>
|
* <p>
|
||||||
* The main class in this package is the {@link
|
* The main class in this package is the {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver}, which
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver}, which
|
||||||
* implements the {@link cn.org.codecrafters.simplejwt.TokenResolver} interface
|
* implements the {@link com.onixbyte.simplejwt.TokenResolver} interface
|
||||||
* and uses the {@code com.auth0:java-jwt} library to handle JWT operations. It
|
* and uses the {@code com.auth0:java-jwt} library to handle JWT operations. It
|
||||||
* provides the functionality to create, validate, and extract JWTs using the
|
* provides the functionality to create, validate, and extract JWTs using the
|
||||||
* {@code com.auth0:java-jwt} library. Developers can use this class as the
|
* {@code com.auth0:java-jwt} library. Developers can use this class as the
|
||||||
* main token resolver in the Simple JWT project when integrating {@code
|
* main token resolver in the Simple JWT project when integrating {@code
|
||||||
* com.auth0:java-jwt} as the JWT management library.
|
* com.auth0:java-jwt} as the JWT management library.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver}
|
* The {@link com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver}
|
||||||
* relies on the {@code com.auth0:java-jwt} library to handle the underlying
|
* relies on the {@code com.auth0:java-jwt} library to handle the underlying
|
||||||
* JWT operations, including token creation, validation, and extraction. It
|
* JWT operations, including token creation, validation, and extraction. It
|
||||||
* utilizes the {@code com.auth0:java-jwt} {@link
|
* utilizes the {@code com.auth0:java-jwt} {@link
|
||||||
@@ -41,12 +41,12 @@
|
|||||||
* algorithms for JWT signing and verification.
|
* algorithms for JWT signing and verification.
|
||||||
* <p>
|
* <p>
|
||||||
* To use the {@link
|
* To use the {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver}, developers
|
* com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver}, developers
|
||||||
* must provide the necessary configurations and dependencies, such as the
|
* must provide the necessary configurations and dependencies, such as the
|
||||||
* {@link cn.org.codecrafters.guid.GuidCreator} for generating unique JWT IDs
|
* {@link com.onixbyte.guid.GuidCreator} for generating unique JWT IDs
|
||||||
* (JTI), the supported algorithm function, the issuer name, and the secret key
|
* (JTI), the supported algorithm function, the issuer name, and the secret key
|
||||||
* used for token signing and validation. The {@link
|
* used for token signing and validation. The {@link
|
||||||
* cn.org.codecrafters.simplejwt.authzero.config.AuthzeroTokenResolverConfig}
|
* com.onixbyte.simplejwt.authzero.config.AuthzeroTokenResolverConfig}
|
||||||
* class provides a convenient way to configure these dependencies.
|
* class provides a convenient way to configure these dependencies.
|
||||||
* <p>
|
* <p>
|
||||||
* Developers using the {@code com.auth0:java-jwt} integration should be
|
* Developers using the {@code com.auth0:java-jwt} integration should be
|
||||||
@@ -56,4 +56,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.authzero;
|
package com.onixbyte.simplejwt.authzero;
|
||||||
+3
-3
@@ -15,10 +15,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.authzero.test;
|
package com.onixbyte.simplejwt.authzero.test;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver;
|
import com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
+31
-32
@@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt;
|
package com.onixbyte.simplejwt;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.exceptions.WeakSecretException;
|
import com.onixbyte.simplejwt.exceptions.WeakSecretException;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@@ -32,36 +32,6 @@ import java.util.Random;
|
|||||||
*/
|
*/
|
||||||
public final class SecretCreator {
|
public final class SecretCreator {
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor to prevent instantiation
|
|
||||||
*/
|
|
||||||
private SecretCreator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The string containing all lowercase characters that can be used to
|
|
||||||
* generate the secret.
|
|
||||||
*/
|
|
||||||
private static final String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The string containing all uppercase characters that can be used to
|
|
||||||
* generate the secret.
|
|
||||||
*/
|
|
||||||
private static final String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The string containing all digit characters that can be used to generate
|
|
||||||
* the secret.
|
|
||||||
*/
|
|
||||||
private static final String DIGITS = "0123456789";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The string containing all special sign characters that can be used to
|
|
||||||
* generate the secret.
|
|
||||||
*/
|
|
||||||
private static final String SPECIAL_SIGNS = "!@#$%^&,*()_+-=,[]{}|;:,'\",.<>/?";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a secure secret with the specified length and character sets.
|
* Generates a secure secret with the specified length and character sets.
|
||||||
*
|
*
|
||||||
@@ -153,4 +123,33 @@ public final class SecretCreator {
|
|||||||
return createSecret(length, false, false, false);
|
return createSecret(length, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor will protect this class from being instantiated.
|
||||||
|
*/
|
||||||
|
private SecretCreator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string containing all lowercase characters that can be used to
|
||||||
|
* generate the secret.
|
||||||
|
*/
|
||||||
|
private static final String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string containing all uppercase characters that can be used to
|
||||||
|
* generate the secret.
|
||||||
|
*/
|
||||||
|
private static final String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string containing all digit characters that can be used to generate
|
||||||
|
* the secret.
|
||||||
|
*/
|
||||||
|
private static final String DIGITS = "0123456789";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string containing all special sign characters that can be used to
|
||||||
|
* generate the secret.
|
||||||
|
*/
|
||||||
|
private static final String SPECIAL_SIGNS = "!@#$%^&,*()_+-=,[]{}|;:,'\",.<>/?";
|
||||||
}
|
}
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt;
|
package com.onixbyte.simplejwt;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
+1
-2
@@ -15,9 +15,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt;
|
package com.onixbyte.simplejwt;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.annotations;
|
package com.onixbyte.simplejwt.annotations;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
+2
-2
@@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.annotations;
|
package com.onixbyte.simplejwt.annotations;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenDataType;
|
import com.onixbyte.simplejwt.constants.TokenDataType;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
+1
-1
@@ -24,4 +24,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.annotations;
|
package com.onixbyte.simplejwt.annotations;
|
||||||
+3
-3
@@ -15,10 +15,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.config;
|
package com.onixbyte.simplejwt.config;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code TokenResolverConfig} provides a mechanism to configure an
|
* The {@code TokenResolverConfig} provides a mechanism to configure an
|
||||||
+1
-1
@@ -29,4 +29,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.config;
|
package com.onixbyte.simplejwt.config;
|
||||||
+2
-6
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.constants;
|
package com.onixbyte.simplejwt.constants;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -88,11 +88,7 @@ public final class PredefinedKeys {
|
|||||||
public static final List<String> KEYS = List.of(ISSUER, SUBJECT, AUDIENCE, EXPIRATION_TIME, NOT_BEFORE, ISSUED_AT, JWT_ID);
|
public static final List<String> KEYS = List.of(ISSUER, SUBJECT, AUDIENCE, EXPIRATION_TIME, NOT_BEFORE, ISSUED_AT, JWT_ID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor to prevent instantiation of the
|
* Private constructor will protect this class from being instantiated.
|
||||||
* {@code PredefinedKeys} class.
|
|
||||||
* <p>
|
|
||||||
* This class is intended to be used as a utility class with only static
|
|
||||||
* constants and methods.
|
|
||||||
*/
|
*/
|
||||||
private PredefinedKeys() {
|
private PredefinedKeys() {
|
||||||
}
|
}
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.constants;
|
package com.onixbyte.simplejwt.constants;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
+4
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.constants;
|
package com.onixbyte.simplejwt.constants;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -63,6 +63,9 @@ public enum TokenDataType {
|
|||||||
*/
|
*/
|
||||||
private final Class<?> mappedClass;
|
private final Class<?> mappedClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TokenDataType with a mapped class.
|
||||||
|
*/
|
||||||
TokenDataType(Class<?> mappedClass) {
|
TokenDataType(Class<?> mappedClass) {
|
||||||
this.mappedClass = mappedClass;
|
this.mappedClass = mappedClass;
|
||||||
}
|
}
|
||||||
+1
-1
@@ -23,4 +23,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.constants;
|
package com.onixbyte.simplejwt.constants;
|
||||||
+4
-2
@@ -15,12 +15,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.exceptions;
|
package com.onixbyte.simplejwt.exceptions;
|
||||||
|
|
||||||
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@code UnsupportedAlgorithmException} represents the given
|
* This {@code UnsupportedAlgorithmException} represents the given
|
||||||
* algorithm is not supported by {@link
|
* algorithm is not supported by {@link
|
||||||
* cn.org.codecrafters.simplejwt.TokenResolver} yet.
|
* TokenResolver} yet.
|
||||||
* <p>
|
* <p>
|
||||||
* If you want the supports to an unsupported algorithm, you could
|
* If you want the supports to an unsupported algorithm, you could
|
||||||
* <ul>
|
* <ul>
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.exceptions;
|
package com.onixbyte.simplejwt.exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code WeakSecretException} represents that your secret is too weak to be
|
* {@code WeakSecretException} represents that your secret is too weak to be
|
||||||
+1
-1
@@ -36,4 +36,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.exceptions;
|
package com.onixbyte.simplejwt.exceptions;
|
||||||
+1
-1
@@ -37,4 +37,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt;
|
package com.onixbyte.simplejwt;
|
||||||
@@ -45,7 +45,7 @@ implementation 'cn.org.codecrafters:simple-jwt-authzero:${simple-jwt-authzero.ve
|
|||||||
|
|
||||||
## Use the `JjwtTokenResolver`
|
## Use the `JjwtTokenResolver`
|
||||||
|
|
||||||
We have implemented `TokenResolver` to make sure you can add JWT to your Java application as soon as possible. All you need to do is to create an instance of `cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver` and other operations to JWT could follow our instruction in [`simple-jwt-facade`](../simple-jwt-facade/README.md).
|
We have implemented `TokenResolver` to make sure you can add JWT to your Java application as soon as possible. All you need to do is to create an instance of `jjwt.com.onixbyte.simplejwt.JjwtTokenResolver` and other operations to JWT could follow our instruction in [`simple-jwt-facade`](../simple-jwt-facade/README.md).
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
|
|||||||
+46
-22
@@ -15,19 +15,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.jjwt;
|
package com.onixbyte.simplejwt.jjwt;
|
||||||
|
|
||||||
import cn.org.codecrafters.devkit.utils.MapUtil;
|
import com.onixbyte.devkit.utils.MapUtil;
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import cn.org.codecrafters.simplejwt.SecretCreator;
|
import com.onixbyte.simplejwt.SecretCreator;
|
||||||
import cn.org.codecrafters.simplejwt.TokenPayload;
|
import com.onixbyte.simplejwt.TokenPayload;
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.annotations.ExcludeFromPayload;
|
import com.onixbyte.simplejwt.annotations.ExcludeFromPayload;
|
||||||
import cn.org.codecrafters.simplejwt.annotations.TokenEnum;
|
import com.onixbyte.simplejwt.annotations.TokenEnum;
|
||||||
import cn.org.codecrafters.simplejwt.constants.PredefinedKeys;
|
import com.onixbyte.simplejwt.constants.PredefinedKeys;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
import cn.org.codecrafters.simplejwt.exceptions.WeakSecretException;
|
import com.onixbyte.simplejwt.exceptions.WeakSecretException;
|
||||||
import cn.org.codecrafters.simplejwt.jjwt.config.JjwtTokenResolverConfig;
|
import com.onixbyte.simplejwt.jjwt.config.JjwtTokenResolverConfig;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jws;
|
import io.jsonwebtoken.Jws;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
@@ -98,16 +98,6 @@ import java.util.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
|
public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
|
||||||
|
|
||||||
private final GuidCreator<?> jtiCreator;
|
|
||||||
|
|
||||||
private final SecureDigestAlgorithm<SecretKey, SecretKey> algorithm;
|
|
||||||
|
|
||||||
private final String issuer;
|
|
||||||
|
|
||||||
private final SecretKey key;
|
|
||||||
|
|
||||||
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a resolver with specified algorithm, issuer, secret and guid strategy.
|
* Create a resolver with specified algorithm, issuer, secret and guid strategy.
|
||||||
*
|
*
|
||||||
@@ -432,6 +422,15 @@ public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
|
|||||||
return renew(oldToken, Duration.ofMinutes(30), payload);
|
return renew(oldToken, Duration.ofMinutes(30), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new token with specified data.
|
||||||
|
*
|
||||||
|
* @param expireAfter the validity time of the token
|
||||||
|
* @param audience the audience of the token
|
||||||
|
* @param subject the subject of the token
|
||||||
|
* @param claims the data to be included in the token
|
||||||
|
* @return the built token
|
||||||
|
*/
|
||||||
private String buildToken(Duration expireAfter, String audience, String subject, Map<String, Object> claims) {
|
private String buildToken(Duration expireAfter, String audience, String subject, Map<String, Object> claims) {
|
||||||
var now = LocalDateTime.now();
|
var now = LocalDateTime.now();
|
||||||
var builder = Jwts.builder()
|
var builder = Jwts.builder()
|
||||||
@@ -453,4 +452,29 @@ public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
|
|||||||
return builder.signWith(key, algorithm)
|
return builder.signWith(key, algorithm)
|
||||||
.compact();
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID creator for creating unique JWT IDs.
|
||||||
|
*/
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm to sign this token.
|
||||||
|
*/
|
||||||
|
private final SecureDigestAlgorithm<SecretKey, SecretKey> algorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The issuer of this token.
|
||||||
|
*/
|
||||||
|
private final String issuer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature key of this token.
|
||||||
|
*/
|
||||||
|
private final SecretKey key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The config of this token resolver.
|
||||||
|
*/
|
||||||
|
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
|
||||||
}
|
}
|
||||||
+27
-19
@@ -15,16 +15,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.jjwt.config;
|
package com.onixbyte.simplejwt.jjwt.config;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.config.TokenResolverConfig;
|
import com.onixbyte.simplejwt.config.TokenResolverConfig;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
import cn.org.codecrafters.simplejwt.exceptions.UnsupportedAlgorithmException;
|
import com.onixbyte.simplejwt.exceptions.UnsupportedAlgorithmException;
|
||||||
import cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver;
|
import com.onixbyte.simplejwt.jjwt.JjwtTokenResolver;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.security.MacAlgorithm;
|
|
||||||
import io.jsonwebtoken.security.SecureDigestAlgorithm;
|
import io.jsonwebtoken.security.SecureDigestAlgorithm;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
@@ -63,17 +61,6 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public final class JjwtTokenResolverConfig implements TokenResolverConfig<SecureDigestAlgorithm<SecretKey, SecretKey>> {
|
public final class JjwtTokenResolverConfig implements TokenResolverConfig<SecureDigestAlgorithm<SecretKey, SecretKey>> {
|
||||||
|
|
||||||
private JjwtTokenResolverConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<TokenAlgorithm, SecureDigestAlgorithm<SecretKey, SecretKey>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
|
|
||||||
put(TokenAlgorithm.HS256, Jwts.SIG.HS256);
|
|
||||||
put(TokenAlgorithm.HS384, Jwts.SIG.HS384);
|
|
||||||
put(TokenAlgorithm.HS512, Jwts.SIG.HS512);
|
|
||||||
}};
|
|
||||||
|
|
||||||
private static JjwtTokenResolverConfig instance;
|
|
||||||
|
|
||||||
public static JjwtTokenResolverConfig getInstance() {
|
public static JjwtTokenResolverConfig getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new JjwtTokenResolverConfig();
|
instance = new JjwtTokenResolverConfig();
|
||||||
@@ -106,4 +93,25 @@ public final class JjwtTokenResolverConfig implements TokenResolverConfig<Secure
|
|||||||
}
|
}
|
||||||
return SUPPORTED_ALGORITHMS.get(algorithm);
|
return SUPPORTED_ALGORITHMS.get(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor will protect this class from being instantiated.
|
||||||
|
*/
|
||||||
|
private JjwtTokenResolverConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code Map} to map a {@link TokenAlgorithm} to {@link SecureDigestAlgorithm}.
|
||||||
|
*/
|
||||||
|
private static final Map<TokenAlgorithm, SecureDigestAlgorithm<SecretKey, SecretKey>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
|
||||||
|
put(TokenAlgorithm.HS256, Jwts.SIG.HS256);
|
||||||
|
put(TokenAlgorithm.HS384, Jwts.SIG.HS384);
|
||||||
|
put(TokenAlgorithm.HS512, Jwts.SIG.HS512);
|
||||||
|
}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance of this config class.
|
||||||
|
*/
|
||||||
|
private static JjwtTokenResolverConfig instance;
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-8
@@ -18,36 +18,36 @@
|
|||||||
/**
|
/**
|
||||||
* The package {@code cn.org.codecrafters.simplejwt.jjwt.config} contains
|
* The package {@code cn.org.codecrafters.simplejwt.jjwt.config} contains
|
||||||
* configuration classes related to the {@link
|
* configuration classes related to the {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver}
|
* com.onixbyte.simplejwt.jjwt.JjwtTokenResolver}
|
||||||
* implementation.
|
* implementation.
|
||||||
* <p>
|
* <p>
|
||||||
* The classes in this package provide configuration options and settings for
|
* The classes in this package provide configuration options and settings for
|
||||||
* the {@link cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver},
|
* the {@link com.onixbyte.simplejwt.jjwt.JjwtTokenResolver},
|
||||||
* which is used for resolving JSON Web Tokens (JWT) using the Auth0 library.
|
* which is used for resolving JSON Web Tokens (JWT) using the Auth0 library.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link
|
* The {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.config.JjwtTokenResolverConfig}
|
* com.onixbyte.simplejwt.jjwt.config.JjwtTokenResolverConfig}
|
||||||
* class is a configuration class that defines the mapping between standard
|
* class is a configuration class that defines the mapping between standard
|
||||||
* {@link cn.org.codecrafters.simplejwt.constants.TokenAlgorithm} and the
|
* {@link com.onixbyte.simplejwt.constants.TokenAlgorithm} and the
|
||||||
* corresponding function implementation used by {@link
|
* corresponding function implementation used by {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver} for handling
|
* com.onixbyte.simplejwt.jjwt.JjwtTokenResolver} for handling
|
||||||
* JWT algorithms. It enables developers to specify and customize the
|
* JWT algorithms. It enables developers to specify and customize the
|
||||||
* algorithm functions according to the chosen JWT algorithm and the library
|
* algorithm functions according to the chosen JWT algorithm and the library
|
||||||
* being used.
|
* being used.
|
||||||
* <p>
|
* <p>
|
||||||
* The configuration options in this package help developers integrate and
|
* The configuration options in this package help developers integrate and
|
||||||
* configure the {@link
|
* configure the {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver} seamlessly
|
* com.onixbyte.simplejwt.jjwt.JjwtTokenResolver} seamlessly
|
||||||
* into their Spring Boot applications. Developers can fine-tune the token
|
* into their Spring Boot applications. Developers can fine-tune the token
|
||||||
* resolution process and customize algorithm handling to align with their
|
* resolution process and customize algorithm handling to align with their
|
||||||
* specific requirements and desired level of security.
|
* specific requirements and desired level of security.
|
||||||
* <p>
|
* <p>
|
||||||
* It is recommended to explore the classes in this package to understand how
|
* It is recommended to explore the classes in this package to understand how
|
||||||
* to configure and use the {@link
|
* to configure and use the {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver} effectively
|
* com.onixbyte.simplejwt.jjwt.JjwtTokenResolver} effectively
|
||||||
* in the Spring Boot environment to handle JWT authentication and
|
* in the Spring Boot environment to handle JWT authentication and
|
||||||
* authorisation securely and efficiently.
|
* authorisation securely and efficiently.
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.jjwt.config;
|
package com.onixbyte.simplejwt.jjwt.config;
|
||||||
+7
-7
@@ -25,27 +25,27 @@
|
|||||||
* the {@code io.jsonwebtoken:jjwt-api} library.
|
* the {@code io.jsonwebtoken:jjwt-api} library.
|
||||||
* <p>
|
* <p>
|
||||||
* The main class in this package is the {@link
|
* The main class in this package is the {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver}, which
|
* com.onixbyte.simplejwt.jjwt.JjwtTokenResolver}, which
|
||||||
* implements the {@link cn.org.codecrafters.simplejwt.TokenResolver} interface
|
* implements the {@link com.onixbyte.simplejwt.TokenResolver} interface
|
||||||
* and uses the {@code io.jsonwebtoken:jjwt-api} library to handle JWT
|
* and uses the {@code io.jsonwebtoken:jjwt-api} library to handle JWT
|
||||||
* operations. It provides the functionality to create, validate, and extract
|
* operations. It provides the functionality to create, validate, and extract
|
||||||
* JWTs using the {@code io.jsonwebtoken:jjwt-api} library. Developers can use
|
* JWTs using the {@code io.jsonwebtoken:jjwt-api} library. Developers can use
|
||||||
* this class as the main token resolver in the Simple JWT project when
|
* this class as the main token resolver in the Simple JWT project when
|
||||||
* integrating {@code io.jsonwebtoken:jjwt-api} as the JWT management library.
|
* integrating {@code io.jsonwebtoken:jjwt-api} as the JWT management library.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver} relies on
|
* The {@link com.onixbyte.simplejwt.jjwt.JjwtTokenResolver} relies on
|
||||||
* the {@code io.jsonwebtoken:jjwt-api}
|
* the {@code io.jsonwebtoken:jjwt-api}
|
||||||
* library to handle the underlying JWT operations, including token creation,
|
* library to handle the underlying JWT operations, including token creation,
|
||||||
* validation, and extraction. It utilizes the {@code io.jsonwebtoken:jjwt-api}
|
* validation, and extraction. It utilizes the {@code io.jsonwebtoken:jjwt-api}
|
||||||
* {@link io.jsonwebtoken.SignatureAlgorithm} class to define and use different
|
* {@link io.jsonwebtoken.SignatureAlgorithm} class to define and use different
|
||||||
* algorithms for JWT signing and verification.
|
* algorithms for JWT signing and verification.
|
||||||
* <p>
|
* <p>
|
||||||
* To use the {@link cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver},
|
* To use the {@link com.onixbyte.simplejwt.jjwt.JjwtTokenResolver},
|
||||||
* developers must provide the necessary configurations and dependencies, such
|
* developers must provide the necessary configurations and dependencies, such
|
||||||
* as the {@link cn.org.codecrafters.guid.GuidCreator} for generating unique
|
* as the {@link com.onixbyte.guid.GuidCreator} for generating unique
|
||||||
* JWT IDs (JTI), the supported algorithm function, the issuer name, and the
|
* JWT IDs (JTI), the supported algorithm function, the issuer name, and the
|
||||||
* secret key used for token signing and validation. The
|
* secret key used for token signing and validation. The
|
||||||
* {@link cn.org.codecrafters.simplejwt.jjwt.config.JjwtTokenResolverConfig}
|
* {@link com.onixbyte.simplejwt.jjwt.config.JjwtTokenResolverConfig}
|
||||||
* class provides a convenient way to configure these dependencies.
|
* class provides a convenient way to configure these dependencies.
|
||||||
* <p>
|
* <p>
|
||||||
* Developers using the {@code io.jsonwebtoken:jjwt-api} integration should be
|
* Developers using the {@code io.jsonwebtoken:jjwt-api} integration should be
|
||||||
@@ -55,4 +55,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.jjwt;
|
package com.onixbyte.simplejwt.jjwt;
|
||||||
@@ -66,7 +66,7 @@ implementation 'cn.org.codecrafters:simple-jwt-spring-boot-starter:${simple-jwt-
|
|||||||
|
|
||||||
We need a `GuidCreator` instance to create JWT ID, though we did implemented a simple `GuidCreator`, but you can still customize it.
|
We need a `GuidCreator` instance to create JWT ID, though we did implemented a simple `GuidCreator`, but you can still customize it.
|
||||||
|
|
||||||
First, please implement the `cn.org.codecrafters.guid.GuidCreator` interface based on your own rules for generating JWT IDs.
|
First, please implement the `com.onixbyte.guid.GuidCreator` interface based on your own rules for generating JWT IDs.
|
||||||
|
|
||||||
Then, add the instance of your own guid creator to spring container, whose name is `jtiCreator`.
|
Then, add the instance of your own guid creator to spring container, whose name is `jtiCreator`.
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -15,12 +15,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration;
|
package com.onixbyte.simplejwt.autoconfiguration;
|
||||||
|
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver;
|
import com.onixbyte.simplejwt.authzero.AuthzeroTokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.autoconfiguration.properties.SimpleJwtProperties;
|
import com.onixbyte.simplejwt.autoconfiguration.properties.SimpleJwtProperties;
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -65,19 +65,6 @@ import org.springframework.context.annotation.Bean;
|
|||||||
@AutoConfigureAfter(value = GuidAutoConfiguration.class)
|
@AutoConfigureAfter(value = GuidAutoConfiguration.class)
|
||||||
public class AuthzeroTokenResolverAutoConfiguration {
|
public class AuthzeroTokenResolverAutoConfiguration {
|
||||||
|
|
||||||
/**
|
|
||||||
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
|
||||||
*/
|
|
||||||
private final GuidCreator<?> jtiCreator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code SimpleJwtProperties} instance containing the configuration
|
|
||||||
* properties for Simple JWT.
|
|
||||||
*/
|
|
||||||
private final SimpleJwtProperties simpleJwtProperties;
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
|
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
|
||||||
* provided SimpleJwtProperties.
|
* provided SimpleJwtProperties.
|
||||||
@@ -112,4 +99,17 @@ public class AuthzeroTokenResolverAutoConfiguration {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
||||||
|
*/
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SimpleJwtProperties} instance containing the configuration
|
||||||
|
* properties for Simple JWT.
|
||||||
|
*/
|
||||||
|
private final SimpleJwtProperties simpleJwtProperties;
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-5
@@ -15,14 +15,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration;
|
package com.onixbyte.simplejwt.autoconfiguration;
|
||||||
|
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import cn.org.codecrafters.simplejwt.autoconfiguration.conditions.GuidCreatorCondition;
|
import com.onixbyte.simplejwt.autoconfiguration.conditions.GuidCreatorCondition;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
|
||||||
@@ -39,6 +37,11 @@ import java.util.UUID;
|
|||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
public class GuidAutoConfiguration {
|
public class GuidAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a default {@code jtiCreator} with UUID.
|
||||||
|
*
|
||||||
|
* @return UUID creator
|
||||||
|
*/
|
||||||
@Bean(name = "jtiCreator")
|
@Bean(name = "jtiCreator")
|
||||||
@Conditional(GuidCreatorCondition.class)
|
@Conditional(GuidCreatorCondition.class)
|
||||||
public GuidCreator<?> jtiCreator() {
|
public GuidCreator<?> jtiCreator() {
|
||||||
+16
-16
@@ -15,12 +15,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration;
|
package com.onixbyte.simplejwt.autoconfiguration;
|
||||||
|
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import com.onixbyte.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.autoconfiguration.properties.SimpleJwtProperties;
|
import com.onixbyte.simplejwt.autoconfiguration.properties.SimpleJwtProperties;
|
||||||
import cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver;
|
import com.onixbyte.simplejwt.jjwt.JjwtTokenResolver;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jws;
|
import io.jsonwebtoken.Jws;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -65,17 +65,6 @@ import org.springframework.context.annotation.Bean;
|
|||||||
@AutoConfigureAfter(value = GuidAutoConfiguration.class)
|
@AutoConfigureAfter(value = GuidAutoConfiguration.class)
|
||||||
public class JjwtTokenResolverAutoConfiguration {
|
public class JjwtTokenResolverAutoConfiguration {
|
||||||
|
|
||||||
/**
|
|
||||||
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
|
||||||
*/
|
|
||||||
private final GuidCreator<?> jtiCreator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code SimpleJwtProperties} instance containing the configuration
|
|
||||||
* properties for Simple JWT.
|
|
||||||
*/
|
|
||||||
private final SimpleJwtProperties simpleJwtProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
|
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
|
||||||
* provided SimpleJwtProperties.
|
* provided SimpleJwtProperties.
|
||||||
@@ -107,4 +96,15 @@ public class JjwtTokenResolverAutoConfiguration {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
||||||
|
*/
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SimpleJwtProperties} instance containing the configuration
|
||||||
|
* properties for Simple JWT.
|
||||||
|
*/
|
||||||
|
private final SimpleJwtProperties simpleJwtProperties;
|
||||||
|
|
||||||
}
|
}
|
||||||
+14
-2
@@ -1,6 +1,6 @@
|
|||||||
package cn.org.codecrafters.simplejwt.autoconfiguration.conditions;
|
package com.onixbyte.simplejwt.autoconfiguration.conditions;
|
||||||
|
|
||||||
import cn.org.codecrafters.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Condition;
|
import org.springframework.context.annotation.Condition;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
@@ -17,6 +17,18 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class GuidCreatorCondition implements Condition {
|
public class GuidCreatorCondition implements Condition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The condition to create bean {@code jtiCreator}.
|
||||||
|
* <p>
|
||||||
|
* If Spring does not have a bean of type
|
||||||
|
* {@link GuidCreator} named {@code jtiCreator}
|
||||||
|
* in the application context, then create {@code jtiCreator}.
|
||||||
|
*
|
||||||
|
* @param context the spring application context
|
||||||
|
* @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
|
||||||
|
* or {@link org.springframework.core.type.MethodMetadata method} being checked
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||||
final var beanFactory = Objects.requireNonNull(context.getBeanFactory());
|
final var beanFactory = Objects.requireNonNull(context.getBeanFactory());
|
||||||
+1
-1
@@ -35,4 +35,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration;
|
package com.onixbyte.simplejwt.autoconfiguration;
|
||||||
+7
-6
@@ -15,11 +15,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration.properties;
|
package com.onixbyte.simplejwt.autoconfiguration.properties;
|
||||||
|
|
||||||
import cn.org.codecrafters.simplejwt.SecretCreator;
|
import com.onixbyte.simplejwt.SecretCreator;
|
||||||
import cn.org.codecrafters.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration;
|
import com.onixbyte.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import com.onixbyte.simplejwt.constants.TokenAlgorithm;
|
||||||
|
import com.onixbyte.simplejwt.jjwt.JjwtTokenResolver;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
* {@code SimpleJwtProperties} provides configuration options for the JWT
|
* {@code SimpleJwtProperties} provides configuration options for the JWT
|
||||||
* algorithm, issuer, and secret. The properties are used by the {@link
|
* algorithm, issuer, and secret. The properties are used by the {@link
|
||||||
* AuthzeroTokenResolverAutoConfiguration} and {@link
|
* AuthzeroTokenResolverAutoConfiguration} and {@link
|
||||||
* cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver} to set up the
|
* JjwtTokenResolver} to set up the
|
||||||
* necessary configurations for JWT generation and validation.
|
* necessary configurations for JWT generation and validation.
|
||||||
* <p>
|
* <p>
|
||||||
* Developers can customise the JWT algorithm, issuer, and secret by setting
|
* Developers can customise the JWT algorithm, issuer, and secret by setting
|
||||||
@@ -45,7 +46,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ConfigurationProperties(prefix = "code-crafters.simple-jwt")
|
@ConfigurationProperties(prefix = "onixbyte.simple-jwt")
|
||||||
public class SimpleJwtProperties {
|
public class SimpleJwtProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+2
-2
@@ -27,9 +27,9 @@
|
|||||||
* the corresponding properties in the application's properties file with the
|
* the corresponding properties in the application's properties file with the
|
||||||
* prefix "code-crafters.simple-jwt". The SimpleJwtAutoConfiguration class
|
* prefix "code-crafters.simple-jwt". The SimpleJwtAutoConfiguration class
|
||||||
* reads these properties and uses them to create the {@link
|
* reads these properties and uses them to create the {@link
|
||||||
* cn.org.codecrafters.simplejwt.TokenResolver} bean with the desired
|
* com.onixbyte.simplejwt.TokenResolver} bean with the desired
|
||||||
* configuration.
|
* configuration.
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration.properties;
|
package com.onixbyte.simplejwt.autoconfiguration.properties;
|
||||||
+3
-3
@@ -1,3 +1,3 @@
|
|||||||
cn.org.codecrafters.simplejwt.autoconfiguration.GuidAutoConfiguration
|
com.onixbyte.simplejwt.autoconfiguration.GuidAutoConfiguration
|
||||||
cn.org.codecrafters.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration
|
com.onixbyte.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration
|
||||||
cn.org.codecrafters.simplejwt.autoconfiguration.JjwtTokenResolverAutoConfiguration
|
com.onixbyte.simplejwt.autoconfiguration.JjwtTokenResolverAutoConfiguration
|
||||||
+52
-50
@@ -15,7 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal;
|
package com.onixbyte.webcal;
|
||||||
|
|
||||||
|
import com.onixbyte.webcal.impl.WebCalendarEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -50,55 +52,6 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class WebCalendar {
|
public final class WebCalendar {
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code VCALENDAR} tag for iCalendar format
|
|
||||||
*/
|
|
||||||
private final static String TAG = "VCALENDAR";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of this calendar.
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The company who produces this calendar.
|
|
||||||
* <p>
|
|
||||||
* This property will be used in {@code PRODID}.
|
|
||||||
*/
|
|
||||||
private String companyName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The product name.
|
|
||||||
* <p>
|
|
||||||
* This property will be used in {@code PRODID}
|
|
||||||
*/
|
|
||||||
private String productName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The producer's domain name.
|
|
||||||
*/
|
|
||||||
private String domainName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scale of this calendar.
|
|
||||||
*/
|
|
||||||
private final String scale = "GREGORIAN";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method of this calendar.
|
|
||||||
*/
|
|
||||||
private String method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version of this calendar.
|
|
||||||
*/
|
|
||||||
private final String version = "2.0";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of calendar components and events
|
|
||||||
*/
|
|
||||||
private final List<WebCalendarNode> nodes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for WebCalendar class, initializes the list of calendar
|
* Constructor for WebCalendar class, initializes the list of calendar
|
||||||
* components and events.
|
* components and events.
|
||||||
@@ -209,5 +162,54 @@ public final class WebCalendar {
|
|||||||
"END:" + TAG;
|
"END:" + TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code VCALENDAR} tag for iCalendar format
|
||||||
|
*/
|
||||||
|
private final static String TAG = "VCALENDAR";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this calendar.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The company who produces this calendar.
|
||||||
|
* <p>
|
||||||
|
* This property will be used in {@code PRODID}.
|
||||||
|
*/
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product name.
|
||||||
|
* <p>
|
||||||
|
* This property will be used in {@code PRODID}
|
||||||
|
*/
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The producer's domain name.
|
||||||
|
*/
|
||||||
|
private String domainName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale of this calendar.
|
||||||
|
*/
|
||||||
|
private final String scale = "GREGORIAN";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method of this calendar.
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of this calendar.
|
||||||
|
*/
|
||||||
|
private final String version = "2.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of calendar components and events
|
||||||
|
*/
|
||||||
|
private final List<WebCalendarNode> nodes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-4
@@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal;
|
package com.onixbyte.webcal;
|
||||||
|
|
||||||
import cn.org.codecrafters.webcal.config.Classification;
|
import com.onixbyte.webcal.config.Classification;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -37,8 +37,7 @@ import java.util.List;
|
|||||||
* @version 1.1.0
|
* @version 1.1.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public abstract sealed class WebCalendarNode
|
public abstract class WebCalendarNode {
|
||||||
permits WebCalendarEvent {
|
|
||||||
|
|
||||||
// Common properties for all calendar components and events
|
// Common properties for all calendar components and events
|
||||||
protected List<String> categories;
|
protected List<String> categories;
|
||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal.config;
|
package com.onixbyte.webcal.config;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
+10
-14
@@ -15,20 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal.config;
|
package com.onixbyte.webcal.config;
|
||||||
|
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DatetimeFormatters
|
* A formatter to format {@link java.time.LocalDateTime}.
|
||||||
*
|
*
|
||||||
* @author Zihlu Wang
|
* @author Zihlu Wang
|
||||||
* @since 21 Sept, 2023
|
|
||||||
*/
|
*/
|
||||||
public final class Formatter {
|
public final class DateAndTimeFormatter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link java.time.format.DateTimeFormatter datetime formatter}
|
||||||
|
* with UTC pattern and timezone.
|
||||||
|
*
|
||||||
|
* @return the {@link java.time.format.DateTimeFormatter datetime formatter}
|
||||||
|
* with UTC pattern and timezone
|
||||||
|
*/
|
||||||
public static DateTimeFormatter getUtcDatetimeFormatter() {
|
public static DateTimeFormatter getUtcDatetimeFormatter() {
|
||||||
if (Objects.isNull(utcDateTimeFormatter)) {
|
if (Objects.isNull(utcDateTimeFormatter)) {
|
||||||
utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC);
|
utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC);
|
||||||
@@ -37,16 +43,6 @@ public final class Formatter {
|
|||||||
return utcDateTimeFormatter;
|
return utcDateTimeFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static DateTimeFormatter getLocalDatetimeFormatter() {
|
|
||||||
// if (Objects.isNull(localDatetimeFormatter)) {
|
|
||||||
// localDatetimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return localDatetimeFormatter;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private static DateTimeFormatter utcDateTimeFormatter;
|
private static DateTimeFormatter utcDateTimeFormatter;
|
||||||
|
|
||||||
// private static DateTimeFormatter localDatetimeFormatter;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -23,11 +23,11 @@
|
|||||||
* <p>The classes in this package include:</p>
|
* <p>The classes in this package include:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* {@link cn.org.codecrafters.webcal.config.Classification}: An enum
|
* {@link com.onixbyte.webcal.config.Classification}: An enum
|
||||||
* representing the classification of events in the web calendar.
|
* representing the classification of events in the web calendar.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.webcal.config;
|
package com.onixbyte.webcal.config;
|
||||||
+21
-20
@@ -15,10 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal;
|
package com.onixbyte.webcal.impl;
|
||||||
|
|
||||||
import cn.org.codecrafters.webcal.config.Classification;
|
import com.onixbyte.webcal.WebCalendarNode;
|
||||||
import cn.org.codecrafters.webcal.config.Formatter;
|
import com.onixbyte.webcal.config.Classification;
|
||||||
|
import com.onixbyte.webcal.config.DateAndTimeFormatter;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -47,8 +48,6 @@ import java.util.UUID;
|
|||||||
*/
|
*/
|
||||||
public final class WebCalendarEvent extends WebCalendarNode {
|
public final class WebCalendarEvent extends WebCalendarNode {
|
||||||
|
|
||||||
private final static String TAG = "VEVENT";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add categories to the event.
|
* Add categories to the event.
|
||||||
*
|
*
|
||||||
@@ -268,25 +267,27 @@ public final class WebCalendarEvent extends WebCalendarNode {
|
|||||||
DURATION:PT{6}S
|
DURATION:PT{6}S
|
||||||
{4}{5}{7}{8}{9}{10}{11}{12}
|
{4}{5}{7}{8}{9}{10}{11}{12}
|
||||||
END:{0}""",
|
END:{0}""",
|
||||||
TAG, // 0 - tag
|
/* 0 - tag */TAG,
|
||||||
Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName, // 1 - uid
|
/* 1 - uid */ Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName,
|
||||||
now.format(Formatter.getUtcDatetimeFormatter()), // 2 - dtstamp
|
/* 2 - dtstamp */ now.format(DateAndTimeFormatter.getUtcDatetimeFormatter()),
|
||||||
start.atZone(ZoneId.systemDefault()).format(Formatter.getUtcDatetimeFormatter()), // 3 - start time
|
/* 3 - start time */ start.atZone(ZoneId.systemDefault()).format(DateAndTimeFormatter.getUtcDatetimeFormatter()),
|
||||||
Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""), // 4 - summary
|
/* 4 - summary */ Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""),
|
||||||
Optional.ofNullable(categories)
|
/* 5 - categories */ Optional.ofNullable(categories)
|
||||||
.map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""), // 5 - categories
|
.map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""),
|
||||||
Optional.ofNullable(duration)
|
/* 6 - duration */ Optional.ofNullable(duration)
|
||||||
.map((_duration) -> String.valueOf(_duration.getSeconds()))
|
.map((_duration) -> String.valueOf(_duration.getSeconds()))
|
||||||
.orElse(Optional.ofNullable(end)
|
.orElse(Optional.ofNullable(end)
|
||||||
.map((_end) -> String.valueOf(Duration.between(_end, start).getSeconds()))
|
.map((_end) -> String.valueOf(Duration.between(_end, start).getSeconds()))
|
||||||
.orElse("0")), // 6 - duration
|
.orElse("0")),
|
||||||
Optional.ofNullable(classification).map((_classification) -> "\nCLASS:" + _classification + "\n").orElse(""), /* 7 - classification */
|
/* 7 - classification */ Optional.ofNullable(classification).map((_classification) -> "\nCLASS:" + _classification + "\n").orElse(""),
|
||||||
Optional.ofNullable(comment).map((_comment) -> "\nCOMMENT:" + _comment + "\n").orElse(""), /* 8 - comment */
|
/* 8 - comment */ Optional.ofNullable(comment).map((_comment) -> "\nCOMMENT:" + _comment + "\n").orElse(""),
|
||||||
Optional.ofNullable(location).map((_location) -> "\nLOCATION:" + _location).orElse("") /* 9 - location */,
|
/* 9 - location */ Optional.ofNullable(location).map((_location) -> "\nLOCATION:" + _location).orElse(""),
|
||||||
Optional.ofNullable(percentComplete).map((_percentComplete) -> "\nPERCENT-COMPLETE:" + _percentComplete).orElse("") /* 10 = percentComplete */,
|
/* 10 = percentComplete */ Optional.ofNullable(percentComplete).map((_percentComplete) -> "\nPERCENT-COMPLETE:" + _percentComplete).orElse(""),
|
||||||
Optional.ofNullable(description).map((_description) -> "\nDESCRIPTION:" + _description).orElse("") /* 11 - description */,
|
/* 11 - description */ Optional.ofNullable(description).map((_description) -> "\nDESCRIPTION:" + _description).orElse(""),
|
||||||
Optional.ofNullable(priority).map((_priority) -> "\nPRIORITY:" + _priority).orElse("") /* 12 - priority */
|
/* 12 - priority */ Optional.ofNullable(priority).map((_priority) -> "\nPRIORITY:" + _priority).orElse("")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static String TAG = "VEVENT";
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-4
@@ -23,16 +23,16 @@
|
|||||||
* The main classes and modules in this package include:
|
* The main classes and modules in this package include:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* {@link cn.org.codecrafters.webcal.WebCalendar}: A class for
|
* {@link com.onixbyte.webcal.WebCalendar}: A class for
|
||||||
* generating web calendars with customisable settings and events.
|
* generating web calendars with customisable settings and events.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* {@link cn.org.codecrafters.webcal.WebCalendarEvent}: A class
|
* {@link com.onixbyte.webcal.impl.WebCalendarEvent}: A class
|
||||||
* representing a single event in a web calendar with various
|
* representing a single event in a web calendar with various
|
||||||
* attributes and options.
|
* attributes and options.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* {@link cn.org.codecrafters.webcal.WebCalendarNode}: An abstract
|
* {@link com.onixbyte.webcal.WebCalendarNode}: An abstract
|
||||||
* class serving as the base class for web calendar nodes, providing
|
* class serving as the base class for web calendar nodes, providing
|
||||||
* common attributes and functionality for events.
|
* common attributes and functionality for events.
|
||||||
* </li>
|
* </li>
|
||||||
@@ -40,4 +40,4 @@
|
|||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
package cn.org.codecrafters.webcal;
|
package com.onixbyte.webcal;
|
||||||
+4
-4
@@ -15,11 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.org.codecrafters.webcal.test;
|
package com.onixbyte.webcal.test;
|
||||||
|
|
||||||
import cn.org.codecrafters.webcal.WebCalendar;
|
import com.onixbyte.webcal.WebCalendar;
|
||||||
import cn.org.codecrafters.webcal.WebCalendarEvent;
|
import com.onixbyte.webcal.impl.WebCalendarEvent;
|
||||||
import cn.org.codecrafters.webcal.config.Classification;
|
import com.onixbyte.webcal.config.Classification;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
Reference in New Issue
Block a user