diff --git a/devkit-core/pom.xml b/devkit-core/pom.xml index 15f579a..f4bf40e 100644 --- a/devkit-core/pom.xml +++ b/devkit-core/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 devkit-core diff --git a/devkit-utils/pom.xml b/devkit-utils/pom.xml index f99e4f7..1ddf6c5 100644 --- a/devkit-utils/pom.xml +++ b/devkit-utils/pom.xml @@ -6,7 +6,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 devkit-utils diff --git a/guid/pom.xml b/guid/pom.xml index 26e83f1..e3742fb 100644 --- a/guid/pom.xml +++ b/guid/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 guid diff --git a/pom.xml b/pom.xml index 77edffc..3ea9171 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 2023 pom diff --git a/property-guard-spring-boot-starter/pom.xml b/property-guard-spring-boot-starter/pom.xml index 6595ca7..8df59be 100644 --- a/property-guard-spring-boot-starter/pom.xml +++ b/property-guard-spring-boot-starter/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 property-guard-spring-boot-starter diff --git a/simple-jwt-authzero/pom.xml b/simple-jwt-authzero/pom.xml index 65e0e00..29e96b1 100644 --- a/simple-jwt-authzero/pom.xml +++ b/simple-jwt-authzero/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 simple-jwt-authzero diff --git a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java index 01d3359..c2d83ce 100644 --- a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java +++ b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java @@ -45,11 +45,6 @@ import java.util.*; * resolver provides functionality to create, extract, verify, and renew JWT * tokens using various algorithms and custom payload data. *

- * Dependencies: - * This implementation relies on the {@code com.auth0:java-jwt} library. Please - * ensure you have added this library as a dependency to your project before - * using this resolver. - *

* Usage: * To use the {@code AuthzeroTokenResolver}, first, create an instance of this * class: @@ -87,7 +82,7 @@ import java.util.*; * correctly configured in your project's dependencies. * * @author Zihlu Wang - * @version 1.1.0 + * @version 1.1.1 * @see GuidCreator * @see Algorithm * @see JWTVerifier @@ -279,7 +274,7 @@ public class AuthzeroTokenResolver implements TokenResolver { builder.withClaim(name, v); } else { log.warn(""" - Unable to determine the type of field {}, converting it to a string now.""", name); + Unable to determine the type of field {}, we will handle it as a String.""", name); builder.withClaim(name, value.toString()); } } else { diff --git a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java index 2cda8ea..1f0751a 100644 --- a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java +++ b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java @@ -35,19 +35,20 @@ import java.util.function.Function; * the {@link AuthzeroTokenResolver}. *

* This configuration is used to establish the mapping between the standard - * {@link TokenAlgorithm} defined within the {@link AuthzeroTokenResolver} - * facade and the specific algorithms used by the {@code com.auth0:java-jwt} - * library, which is the underlying library used by {@link - * AuthzeroTokenResolver} to handle JSON Web Tokens (JWTs). + * {@link TokenAlgorithm} defined in the + * {@code cn.org.codecrafters:simple-jwt-facade} and the specific algorithms + * used by the {@code com.auth0:java-jwt} library, which is the underlying + * library used by {@link AuthzeroTokenResolver} to handle JSON Web Tokens + * (JWTs). *

* Algorithm Mapping: - * The {@code AuthzeroTokenResolverConfig} allows specifying the relationship + * The {@code AuthzeroTokenResolverConfig} allows specifying the relationships * between the standard {@link TokenAlgorithm} instances supported by * {@link AuthzeroTokenResolver} and the corresponding algorithms used by the * {@code com.auth0:java-jwt} library. The mapping is achieved using a Map, - * where the keys are the standard TokenAlgorithm instances, and the values - * represent the algorithm functions used by Auth0 Java JWT library for each - * corresponding key. + * where the keys are the standard {@link TokenAlgorithm} instances, and the + * values represent the algorithm functions used by {@code com.auth0:java-jwt} + * library for each corresponding key. *

* Note: * The provided algorithm mapping should be consistent with the actual @@ -56,7 +57,7 @@ import java.util.function.Function; * validation and processing within the {@link AuthzeroTokenResolver}. * * @author Zihlu Wang - * @version 1.1.0 + * @version 1.1.1 * @since 1.0.0 */ public final class AuthzeroTokenResolverConfig implements TokenResolverConfig> { diff --git a/simple-jwt-facade/pom.xml b/simple-jwt-facade/pom.xml index bd72ec4..d16ecf6 100644 --- a/simple-jwt-facade/pom.xml +++ b/simple-jwt-facade/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 simple-jwt-facade diff --git a/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java b/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java index 2989a03..f29e198 100644 --- a/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java +++ b/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java @@ -21,8 +21,8 @@ import cn.org.codecrafters.simplejwt.TokenResolver; import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm; /** - * The {@code TokenResolverConfig} provides a mechanism to configure a - * {@link TokenResolver} with algorithm functions. + * The {@code TokenResolverConfig} provides a mechanism to configure an + * implementation of {@link TokenResolver} with algorithm functions. *

* This generic interface is used to define the configuration details for a * {@link TokenResolver} that utilizes algorithm functions. The interface diff --git a/simple-jwt-jjwt/pom.xml b/simple-jwt-jjwt/pom.xml index e5acdeb..ff49ffa 100644 --- a/simple-jwt-jjwt/pom.xml +++ b/simple-jwt-jjwt/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 simple-jwt-jjwt diff --git a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java index b8896ef..dbf146b 100644 --- a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java +++ b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java @@ -40,6 +40,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; import java.util.Map; +import java.util.Objects; import java.util.UUID; /** @@ -49,11 +50,6 @@ import java.util.UUID; * This resolver provides functionality to create, extract, verify, and renew * JWT tokens using various algorithms and custom payload data. *

- * Dependencies: - * This implementation relies on the {@code io.jsonwebtoken:jjwt} library. Please - * ensure you have added this library as a dependency to your project before - * using this resolver. - *

* Usage: * To use the {@code JjwtTokenResolver}, first, create an instance of this * class: @@ -113,7 +109,7 @@ public class JjwtTokenResolver implements TokenResolver> { private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance(); public JjwtTokenResolver(GuidCreator jtiCreator, TokenAlgorithm algorithm, String issuer, String secret) { - if (secret == null || secret.isBlank()) { + if (Objects.isNull(secret) || secret.isBlank()) { throw new IllegalArgumentException("A secret is required to build a JSON Web Token."); } @@ -209,8 +205,7 @@ public class JjwtTokenResolver implements TokenResolver> { */ @Override public String createToken(Duration expireAfter, String audience, String subject) { - var now = LocalDateTime.now(); - return buildToken(expireAfter, audience, subject, now, null); + return buildToken(expireAfter, audience, subject, LocalDateTime.now(), null); } /** @@ -225,8 +220,7 @@ public class JjwtTokenResolver implements TokenResolver> { */ @Override public String createToken(Duration expireAfter, String audience, String subject, Map payload) { - var now = LocalDateTime.now(); - return buildToken(expireAfter, audience, subject, now, payload); + return buildToken(expireAfter, audience, subject, LocalDateTime.now(), payload); } /** @@ -244,10 +238,9 @@ public class JjwtTokenResolver implements TokenResolver> { */ @Override public String createToken(Duration expireAfter, String audience, String subject, T payload) { - var now = LocalDateTime.now(); try { var claims = MapUtil.objectToMap(payload); - return buildToken(expireAfter, audience, subject, now, claims); + return buildToken(expireAfter, audience, subject, LocalDateTime.now(), claims); } catch (IllegalAccessException e) { log.error("An error occurs while accessing the fields of the object"); } diff --git a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java index a174665..89eefba 100644 --- a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java +++ b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java @@ -28,19 +28,20 @@ import java.util.HashMap; import java.util.Map; /** - * The {@code JjwtTokenResolverConfig} class provides the configuration for the - * {@link JjwtTokenResolver}. + * The {@code JjwtTokenResolverConfig} class provides the configuration for + * the {@link JjwtTokenResolver}. *

- * This configuration class is used to establish the mapping between the - * standard {@link TokenAlgorithm} defined within the - * {@code JjwtTokenResolverConfig} and the specific algorithms used by the - * {@code io.jsonwebtoken:jjwt} library, which is the underlying library used - * by {@code JjwtTokenResolver} to handle JSON Web Tokens (JWTs). + * This configuration is used to establish the mapping between the standard + * {@link TokenAlgorithm} defined in the + * {@code cn.org.codecrafters:simple-jwt-facade} and the specific algorithms + * used by the {@code io.jsonwebtoken:jjwt} library, which is the underlying + * library used by {@link JjwtTokenResolver} to handle JSON Web Tokens + * (JWTs). *

* Algorithm Mapping: - * The {@code JjwtTokenResolverConfig} allows specifying the relationship - * between the standard {@link TokenAlgorithm} instances supported by {@link - * JjwtTokenResolver} and the corresponding algorithms used by the + * The {@code JjwtTokenResolverConfig} allows specifying the relationships + * between the standard {@link TokenAlgorithm} instances supported by + * {@link JjwtTokenResolver} and the corresponding algorithms used by the * {@code io.jsonwebtoken:jjwt} library. The mapping is achieved using a Map, * where the keys are the standard {@link TokenAlgorithm} instances, and the * values represent the algorithm functions used by @@ -53,7 +54,7 @@ import java.util.Map; * validation and processing within the {@link JjwtTokenResolver}. * * @author Zihlu Wang - * @version 1.1.0 + * @version 1.1.1 * @since 1.0.0 */ public final class JjwtTokenResolverConfig implements TokenResolverConfig { diff --git a/simple-jwt-spring-boot-starter/pom.xml b/simple-jwt-spring-boot-starter/pom.xml index 9e6a49c..50a9890 100644 --- a/simple-jwt-spring-boot-starter/pom.xml +++ b/simple-jwt-spring-boot-starter/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 simple-jwt-spring-boot-starter diff --git a/webcal/pom.xml b/webcal/pom.xml index 4419d64..eb49cb2 100644 --- a/webcal/pom.xml +++ b/webcal/pom.xml @@ -23,7 +23,7 @@ cn.org.codecrafters jdevkit - 1.1.0 + 1.1.1 webcal diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java index e16b581..9a99469 100644 --- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java +++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java @@ -19,6 +19,7 @@ package cn.org.codecrafters.webcal; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * {@code WebCalendar} class represents a web calendar in iCalendar format. @@ -189,18 +190,22 @@ public final class WebCalendar { * @return the resolved iCalendar string */ public String resolve() { - var events = new StringBuilder(); + var eventBuilder = new StringBuilder(); if (!nodes.isEmpty()) { - nodes.forEach(item -> - events.append(item.setDomainName(domainName) - .resolve())); + for (var node : nodes) { + if (Objects.isNull(node.getDomainName()) || node.getDomainName().isBlank()) { + node.setDomainName(this.domainName); + } + + eventBuilder.append(node.resolve()); + } } return "BEGIN:" + TAG + "\n" + "PRODID:-//" + companyName + "//" + productName + "//EN\n" + "VERSION:" + version + "\n" + "X-WR-CALNAME:" + name + "\n" + - events + "\n" + + eventBuilder + "\n" + "END:" + TAG; } diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java index c073d19..2870246 100644 --- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java +++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java @@ -18,10 +18,12 @@ package cn.org.codecrafters.webcal; import cn.org.codecrafters.webcal.config.Classification; +import cn.org.codecrafters.webcal.config.Formatter; +import java.text.MessageFormat; import java.time.Duration; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; +import java.time.ZoneId; import java.util.Arrays; import java.util.Collection; import java.util.Optional; @@ -257,30 +259,34 @@ public final class WebCalendarEvent extends WebCalendarNode { */ @Override public String resolve() { - return "\nBEGIN:" + TAG + "\n" + - "UID:" + Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName + "\n" + - Optional.ofNullable(summary).map((item) -> "SUMMARY:" + item + "\n").orElse("") + - "DTSTART" + Optional.ofNullable(timezone).map(item -> ";TZID=" + item).orElse("") + ":" + start.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "\n" + + var now = LocalDateTime.now().atZone(ZoneId.systemDefault()); + return MessageFormat.format(""" + BEGIN:{0} + UID:{1} + DTSTAMP:{2} + DTSTART:{3} + DURATION:PT{6}S + {4}{5}{7}{8}{9}{10}{11}{12} + END:{0}""", + TAG, // 0 - tag + Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName, // 1 - uid + now.format(Formatter.getUtcDatetimeFormatter()), // 2 - dtstamp + start.atZone(ZoneId.systemDefault()).format(Formatter.getUtcDatetimeFormatter()), // 3 - start time + Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""), // 4 - summary Optional.ofNullable(categories) - .map((item) -> { - if (!item.isEmpty()) { - return "CATEGORIES:" + resolveCategories() + "\n"; - } - return null; - }).orElse("") + + .map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""), // 5 - categories Optional.ofNullable(duration) - .map((item) -> "DURATION:PT" + item.getSeconds() + "S\n").orElse("") + - Optional.ofNullable(end) - .map((item) -> "DTEND" + Optional.ofNullable(timezone).map(tz -> ";TZID=" + tz).orElse("") + ":" + - end.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "\n").orElse("") + - Optional.ofNullable(classification) - .map((item) -> "CLASS:" + item.name() + "\n").orElse("") + - Optional.ofNullable(comment).map((item) -> "COMMENT:" + item + "\n").orElse("") + - Optional.ofNullable(description).map((item) -> "DESCRIPTION:" + item + "\n").orElse("") + - Optional.ofNullable(location).map((item) -> "LOCATION:" + item + "\n").orElse("") + - Optional.ofNullable(percentComplete).map((item) -> "PERCENT-COMPLETE:" + item + "\n").orElse("") + - Optional.ofNullable(priority).map((item) -> "PRIORITY:" + item + "\n").orElse("") + - "END:" + TAG + "\n"; + .map((_duration) -> String.valueOf(_duration.getSeconds())) + .orElse(Optional.ofNullable(end) + .map((_end) -> String.valueOf(Duration.between(_end, start).getSeconds())) + .orElse("0")), // 6 - duration + Optional.ofNullable(classification).map((_classification) -> "\nCLASS:" + _classification + "\n").orElse(""), /* 7 - classification */ + Optional.ofNullable(comment).map((_comment) -> "\nCOMMENT:" + _comment + "\n").orElse(""), /* 8 - comment */ + Optional.ofNullable(location).map((_location) -> "\nLOCATION:" + _location).orElse("") /* 9 - location */, + Optional.ofNullable(percentComplete).map((_percentComplete) -> "\nPERCENT-COMPLETE:" + _percentComplete).orElse("") /* 10 = percentComplete */, + Optional.ofNullable(description).map((_description) -> "\nDESCRIPTION:" + _description).orElse("") /* 11 - description */, + Optional.ofNullable(priority).map((_priority) -> "\nPRIORITY:" + _priority).orElse("") /* 12 - priority */ + ); } } diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java index 5f56b11..75b0e43 100644 --- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java +++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java @@ -90,6 +90,15 @@ public abstract sealed class WebCalendarNode return this; } + /** + * Get the domain name. + * + * @return the domain name of this event + */ + public String getDomainName() { + return this.domainName; + } + /** * Resolve the list of categories into a comma-separated string. * diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java b/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java new file mode 100644 index 0000000..4760d79 --- /dev/null +++ b/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 CodeCraftersCN. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.org.codecrafters.webcal.config; + +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +/** + * DatetimeFormatters + * + * @author Zihlu Wang + * @since 21 Sept, 2023 + */ +public final class Formatter { + + public static DateTimeFormatter getUtcDatetimeFormatter() { + if (Objects.isNull(utcDateTimeFormatter)) { + utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC); + } + + 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 localDatetimeFormatter; + +}