From 9ecbbd0300c55682a97c75e2ddba6278bd45703d Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Mon, 28 Nov 2022 00:21:55 +0100 Subject: [PATCH 01/11] feat: introduce user input validation --- .../shell/validation/DateValidator.java | 33 +++++++++++++++++++ .../shell/validation/InputValidator.java | 7 ++++ .../shell/validation/TeamNameValidator.java | 11 +++++++ .../shell/validation/UserNameValidator.java | 22 +++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/InputValidator.java create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java new file mode 100644 index 00000000..c56bfa44 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java @@ -0,0 +1,33 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateValidator implements InputValidator { + + private final DateTimeFormatter formatter; + + public DateValidator() { + String datePattern = "dd/MM/yy HH:mm"; + formatter = DateTimeFormatter.ofPattern(datePattern); + } + + /** + * @param input Must be MM/yy, must be prior to the current month + */ + @Override + public boolean validate(String input) { + if (input == null || input.isBlank()) return false; + + try { + LocalDateTime date = LocalDateTime.parse("01/" + input + " 00:00", formatter); + LocalDateTime now = LocalDateTime.now(); + return date.isBefore(now.minusMonths(1)); + } catch (DateTimeParseException e) { + // Input was not properly formatted + return false; + } + } + +} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/InputValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/InputValidator.java new file mode 100644 index 00000000..9d0373f0 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/InputValidator.java @@ -0,0 +1,7 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +public interface InputValidator { + + boolean validate(T input); + +} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java new file mode 100644 index 00000000..e7fbbbfd --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java @@ -0,0 +1,11 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +public class TeamNameValidator implements InputValidator { + + public TeamNameValidator() {} + + @Override + public boolean validate(String input) { + return input != null && !input.isBlank(); + } +} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java new file mode 100644 index 00000000..298a7426 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java @@ -0,0 +1,22 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +public class UserNameValidator implements InputValidator { + + public UserNameValidator() {} + + /** + * @param input Must pass the Github username creation constraints: + * - Username may only contain alphanumeric characters or hyphens. + * - Username cannot have multiple consecutive hyphens. + * - Username cannot begin or end with a hyphen. + * - Maximum is 39 characters. + */ + @Override + public boolean validate(String input) { + if (input == null || input.isBlank()) return false; + return !input.matches("^-") + && !input.matches("-$") + && input.matches("[a-zA-Z0-9\\-]{0,39}") + && !input.matches("--"); + } +} From 5e468ebeda31c3de82157dc575a991e411f88db0 Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Mon, 28 Nov 2022 00:23:18 +0100 Subject: [PATCH 02/11] feat: components for the 'team' and 'user' shell commands --- .../shell/components/TeamComponent.java | 33 +++++++++++++++++++ .../shell/components/UserComponent.java | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/TeamComponent.java create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/UserComponent.java diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/TeamComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/TeamComponent.java new file mode 100644 index 00000000..5acc6ab8 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/TeamComponent.java @@ -0,0 +1,33 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.components; + +import io.pakland.mdas.githubstats.infrastructure.shell.validation.DateValidator; +import io.pakland.mdas.githubstats.infrastructure.shell.validation.TeamNameValidator; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellOption; + +@ShellComponent +public class TeamComponent { + + private boolean team( + @ShellOption(value = {"n"}) String teamName, + @ShellOption(value = {"from"}) String fromDate, + @ShellOption(value = {"to"}) String toDate + ) { + DateValidator dateValidator = new DateValidator(); + TeamNameValidator teamNameValidator = new TeamNameValidator(); + + boolean isInputValid = dateValidator.validate(fromDate) + && dateValidator.validate(toDate) + && teamNameValidator.validate(teamName); + + if (!isInputValid) { + // Alert user, and halt command + return false; + } + + // ... Perform request ... + + return true; + } + +} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/UserComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/UserComponent.java new file mode 100644 index 00000000..814a59a0 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/UserComponent.java @@ -0,0 +1,33 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.components; + +import io.pakland.mdas.githubstats.infrastructure.shell.validation.DateValidator; +import io.pakland.mdas.githubstats.infrastructure.shell.validation.UserNameValidator; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellOption; + +@ShellComponent +public class UserComponent { + + private boolean user( + @ShellOption(value = {"n"}) String userName, + @ShellOption(value = {"from"}) String fromDate, + @ShellOption(value = {"to"}) String toDate + ) { + DateValidator dateValidator = new DateValidator(); + UserNameValidator userNameValidator = new UserNameValidator(); + + boolean isInputValid = dateValidator.validate(fromDate) + && dateValidator.validate(toDate) + && userNameValidator.validate(userName); + + if (!isInputValid) { + // Alert user, and halt command + return false; + } + + // ... Perform request ... + + return true; + } + +} From fdccd4a24435a8051f02f6c594141eacd00afcee Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Mon, 28 Nov 2022 00:23:40 +0100 Subject: [PATCH 03/11] feat: bean configuration for the 'team' and 'user' shell commands --- .../configuration/CommandConfiguration.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java new file mode 100644 index 00000000..3f14b2b1 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java @@ -0,0 +1,80 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.configuration; + +import io.pakland.mdas.githubstats.infrastructure.shell.components.TeamComponent; +import io.pakland.mdas.githubstats.infrastructure.shell.components.UserComponent; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.shell.command.CommandRegistration; + +@Configuration +public class CommandConfiguration { + + @Bean + public CommandRegistration buildUserCommand() { + UserComponent userComponent = new UserComponent(); + + return CommandRegistration.builder() + .command("user") + .description("Get data from a specified user.") + .withTarget() + .method(userComponent, "user") + .and() + .withOption() + .shortNames('n') + .label("USER_NAME") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .withOption() + .longNames("from") + .label("FROM_DATE") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .withOption() + .longNames("to") + .label("TO_DATE") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .build(); + } + + @Bean + public CommandRegistration buildTeamCommand() { + TeamComponent teamComponent = new TeamComponent(); + + return CommandRegistration.builder() + .command("team") + .description("Get data from a specified team and its sub teams.") + .withTarget() + .method(teamComponent, "team") + .and() + .withOption() + .shortNames('n') + .label("TEAM_NAME") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .withOption() + .longNames("from") + .label("FROM_DATE") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .withOption() + .longNames("to") + .label("TO_DATE") + .arity(CommandRegistration.OptionArity.EXACTLY_ONE) + .type(String.class) + .required() + .and() + .build(); + } + +} From fd3b161e5ccac69b1a6027cc57dcb73ca9acdb86 Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Mon, 28 Nov 2022 00:23:57 +0100 Subject: [PATCH 04/11] chore: remove old commands --- .../shell/components/CommitComponent.java | 32 --------------- .../components/LinesOfCodeComponent.java | 31 -------------- .../components/PullRequestComponent.java | 41 ------------------- 3 files changed, 104 deletions(-) delete mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/CommitComponent.java delete mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LinesOfCodeComponent.java delete mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/PullRequestComponent.java diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/CommitComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/CommitComponent.java deleted file mode 100644 index 921abbf8..00000000 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/CommitComponent.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.pakland.mdas.githubstats.infrastructure.shell.components; - -import org.springframework.context.annotation.Bean; -import org.springframework.shell.command.CommandRegistration; -import org.springframework.shell.standard.ShellComponent; - -@ShellComponent -public class CommitComponent { - - public void commits(String user) { - System.out.println("commits"); - } - - @Bean - CommandRegistration commitCommandRegistration() { - CommitComponent commitComponent = new CommitComponent(); - - return CommandRegistration.builder() - .command("commits") - .description("Number of commits by user") - .withTarget() - .method(commitComponent, "commits") - .and() - .withOption() - .shortNames('u') - .required() - .type(String.class) - .and() - .build(); - } - -} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LinesOfCodeComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LinesOfCodeComponent.java deleted file mode 100644 index 0e04971f..00000000 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LinesOfCodeComponent.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.pakland.mdas.githubstats.infrastructure.shell.components; - -import org.springframework.context.annotation.Bean; -import org.springframework.shell.command.CommandRegistration; -import org.springframework.shell.standard.ShellComponent; - -@ShellComponent -public class LinesOfCodeComponent { - - public void locChanges(String user) { - System.out.println("locChanges"); - } - - @Bean - CommandRegistration linesOfCodeCommandRegistration() { - LinesOfCodeComponent linesOfCodeComponent = new LinesOfCodeComponent(); - - return CommandRegistration.builder() - .command("locChanges") - .description("Lines of code deleted and added") - .withTarget() - .method(linesOfCodeComponent, "locChanges") - .and() - .withOption() - .shortNames('u') - .required() - .type(String.class) - .and() - .build(); - } -} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/PullRequestComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/PullRequestComponent.java deleted file mode 100644 index c0e016e8..00000000 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/PullRequestComponent.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.pakland.mdas.githubstats.infrastructure.shell.components; - -import org.springframework.context.annotation.Bean; -import org.springframework.shell.command.CommandRegistration; -import org.springframework.shell.standard.ShellComponent; - -@ShellComponent -public class PullRequestComponent { - - private void prExecuted(String user) { - System.out.println("prExecuted"); - } - - private void prReviewed(String user) { - System.out.println("prReviewed"); - } - - private void prCommentLength(String user) { - System.out.println("prCommentLength"); - } - - - @Bean - CommandRegistration pullRequestCommandRegistration() { - PullRequestComponent pullRequestComponent = new PullRequestComponent(); - - return CommandRegistration.builder() - .command("prExecuted") - .description("Number of pull requests executed") - .withTarget() - .method(pullRequestComponent, "prExecuted") - .and() - .withOption() - .shortNames('u') - .required() - .type(String.class) - .and() - .build(); - } - -} From ee76fbbb25d85451b3f842bef686c2a388aac3a7 Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Tue, 29 Nov 2022 11:25:42 +0100 Subject: [PATCH 05/11] refactor: extract function --- .../infrastructure/shell/validation/DateValidator.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java index c56bfa44..de9f0da4 100644 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidator.java @@ -14,14 +14,14 @@ public DateValidator() { } /** - * @param input Must be MM/yy, must be prior to the current month + * @param input Must be MM/yy, and prior to the current month. Starting year: 2000 (01/01/99 parses to 01/01/2099) */ @Override public boolean validate(String input) { if (input == null || input.isBlank()) return false; try { - LocalDateTime date = LocalDateTime.parse("01/" + input + " 00:00", formatter); + LocalDateTime date = LocalDateTime.parse(getInitialDateFromMMYY(input), formatter); LocalDateTime now = LocalDateTime.now(); return date.isBefore(now.minusMonths(1)); } catch (DateTimeParseException e) { @@ -30,4 +30,8 @@ public boolean validate(String input) { } } + private String getInitialDateFromMMYY(String input) { + return "01/" + input + " 00:00"; + } + } From 3391cde16a40c044585d9ef5e5ab02a7bcce6d1f Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Tue, 29 Nov 2022 11:26:42 +0100 Subject: [PATCH 06/11] test: add tests for validators --- .../shell/validation/DateValidatorTest.java | 29 ++++++++++++++++++ .../validation/TeamNameValidatorTest.java | 29 ++++++++++++++++++ .../validation/UserNameValidatorTest.java | 30 +++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java create mode 100644 src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java create mode 100644 src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java new file mode 100644 index 00000000..f856b127 --- /dev/null +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java @@ -0,0 +1,29 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class DateValidatorTest { + + @Test + void testValidation() { + DateValidator dateValidator = new DateValidator(); + + assertTrue(dateValidator.validate("12/01")); + assertTrue(dateValidator.validate("03/22")); + assertTrue(dateValidator.validate("09/22")); + assertTrue(dateValidator.validate("10/20")); + assertTrue(dateValidator.validate("07/15")); + + assertFalse(dateValidator.validate("aa")); + assertFalse(dateValidator.validate("")); + assertFalse(dateValidator.validate("01-02")); + assertFalse(dateValidator.validate("13/9")); + assertFalse(dateValidator.validate("00/00")); + assertFalse(dateValidator.validate("1/4444444444444")); + assertFalse(dateValidator.validate("2/22")); + assertFalse(dateValidator.validate(" / ")); + } + +} diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java new file mode 100644 index 00000000..7153e817 --- /dev/null +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java @@ -0,0 +1,29 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TeamNameValidatorTest { + + @Test + void testValidation() { + TeamNameValidator teamNameValidator = new TeamNameValidator(); + + assertTrue(teamNameValidator.validate("name")); + assertTrue(teamNameValidator.validate("test-hello-world")); + assertTrue(teamNameValidator.validate("22312")); + assertTrue(teamNameValidator.validate("alphanumeric-and-hyphens-23")); + assertTrue(teamNameValidator.validate("UPPERcase")); + + assertFalse(teamNameValidator.validate("name with spaces")); + assertFalse(teamNameValidator.validate("very-very-very-very-very-very-very-very-very-very-long-name")); + assertFalse(teamNameValidator.validate("-name")); + assertFalse(teamNameValidator.validate("name-")); + assertFalse(teamNameValidator.validate("i-have--2-hyphens")); + assertFalse(teamNameValidator.validate("")); + assertFalse(teamNameValidator.validate(" ")); + assertFalse(teamNameValidator.validate(" - ")); + } +} diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java new file mode 100644 index 00000000..d5fc80c5 --- /dev/null +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java @@ -0,0 +1,30 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.validation; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class UserNameValidatorTest { + + @Test + void testValidation() { + UserNameValidator userNameValidator = new UserNameValidator(); + + assertTrue(userNameValidator.validate("name")); + assertTrue(userNameValidator.validate("test-hello-world")); + assertTrue(userNameValidator.validate("22312")); + assertTrue(userNameValidator.validate("alphanumeric-and-hyphens-23")); + assertTrue(userNameValidator.validate("UPPERcase")); + + assertFalse(userNameValidator.validate("name with spaces")); + assertFalse(userNameValidator.validate("very-very-very-very-very-very-very-very-very-very-long-name")); + assertFalse(userNameValidator.validate("-name")); + assertFalse(userNameValidator.validate("name-")); + assertFalse(userNameValidator.validate("i-have--2-hyphens")); + assertFalse(userNameValidator.validate("")); + assertFalse(userNameValidator.validate(" ")); + assertFalse(userNameValidator.validate(" - ")); + } + +} From 360072f02265337bb4a8e505ad8a150340095544 Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Tue, 29 Nov 2022 11:28:33 +0100 Subject: [PATCH 07/11] fix: refine validations to pass tests --- .../shell/validation/TeamNameValidator.java | 14 +++++++++++++- .../shell/validation/UserNameValidator.java | 8 ++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java index e7fbbbfd..d1fc51a2 100644 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidator.java @@ -4,8 +4,20 @@ public class TeamNameValidator implements InputValidator { public TeamNameValidator() {} + /** + * @param input Must pass the Github team name creation constraints: + * - Team name may only contain alphanumeric characters or hyphens. + * - Team name cannot have multiple consecutive hyphens. + * - Team name cannot begin or end with a hyphen. + * - Maximum is 39 characters. + */ @Override public boolean validate(String input) { - return input != null && !input.isBlank(); + if (input == null || input.isBlank()) return false; + return !input.matches("^-.*") + && !input.matches(".*-$") + && input.matches("[a-zA-Z0-9\\-]{0,39}") + && !input.matches(".*--.*"); } + } diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java index 298a7426..da72a423 100644 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidator.java @@ -14,9 +14,9 @@ public UserNameValidator() {} @Override public boolean validate(String input) { if (input == null || input.isBlank()) return false; - return !input.matches("^-") - && !input.matches("-$") - && input.matches("[a-zA-Z0-9\\-]{0,39}") - && !input.matches("--"); + return !input.matches("^-.*") + && !input.matches(".*-$") + && input.matches("[a-zA-Z0-9\\-]{0,39}") + && !input.matches(".*--.*"); } } From 46e2a020634add0865f5960c339a62b991681a8d Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Tue, 29 Nov 2022 11:41:36 +0100 Subject: [PATCH 08/11] feat: add login command --- .../shell/components/LoginComponent.java | 13 ++++++++++++ .../configuration/CommandConfiguration.java | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LoginComponent.java diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LoginComponent.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LoginComponent.java new file mode 100644 index 00000000..e9efb161 --- /dev/null +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/components/LoginComponent.java @@ -0,0 +1,13 @@ +package io.pakland.mdas.githubstats.infrastructure.shell.components; + +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellOption; + +@ShellComponent +public class LoginComponent { + + private boolean login(@ShellOption(value = {"token"}) String token) { + return token != null; + } + +} diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java index 3f14b2b1..f1e483f9 100644 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java @@ -1,5 +1,6 @@ package io.pakland.mdas.githubstats.infrastructure.shell.configuration; +import io.pakland.mdas.githubstats.infrastructure.shell.components.LoginComponent; import io.pakland.mdas.githubstats.infrastructure.shell.components.TeamComponent; import io.pakland.mdas.githubstats.infrastructure.shell.components.UserComponent; import org.springframework.context.annotation.Bean; @@ -77,4 +78,23 @@ public CommandRegistration buildTeamCommand() { .build(); } + @Bean + public CommandRegistration buildLoginCommand() { + LoginComponent loginComponent = new LoginComponent(); + + return CommandRegistration.builder() + .command("login") + .description("Log in to the Github API before making any requests.") + .withTarget() + .method(loginComponent, "login") + .and() + .withOption() + .longNames("token") + .label("TOKEN") + .type(String.class) + .required() + .and() + .build(); + } + } From 3988741b9e4e5aad0ba3d3251f72a170b74b8fa7 Mon Sep 17 00:00:00 2001 From: Sergi Domingo Date: Tue, 29 Nov 2022 12:10:20 +0100 Subject: [PATCH 09/11] docs: update README with available commands --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 14818fc7..38902ee7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,26 @@ # github-stats +## Available commands + +`github-stats` runs in an interactive shell where you can run commands that fetch Github data. + +Command definition: + +``` +login - Log in to the Github API before making any requests. +Usage: login --token + +team - Get data from a specified team and its sub teams. +Usage: team -n --from --to + FROM_DATE: month and year in MM/yy format (starting Jan 2000) + TO_DATE: same format as FROM_DATE, accepts until current_month - 1 + +user - Get data from a specified user. +Usage: user -n --from --to + FROM_DATE: month and year in MM/yy format (starting Jan 2000) + TO_DATE: same format as FROM_DATE, accepts until current_month - 1 +``` + ## Software stack - Java 17 - Spring Boot 2.7.5 From 814293c47c428066c926d9bd87d6405f45b3cb2f Mon Sep 17 00:00:00 2001 From: Miquel de Domingo Date: Tue, 29 Nov 2022 18:21:57 +0100 Subject: [PATCH 10/11] test: separate truthy/falsy tests --- .../shell/validation/DateValidatorTest.java | 9 +++++---- .../shell/validation/TeamNameValidatorTest.java | 8 +++++--- .../shell/validation/UserNameValidatorTest.java | 9 +++++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java index f856b127..9c025959 100644 --- a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/DateValidatorTest.java @@ -5,17 +5,19 @@ import static org.junit.jupiter.api.Assertions.*; public class DateValidatorTest { + DateValidator dateValidator = new DateValidator(); @Test - void testValidation() { - DateValidator dateValidator = new DateValidator(); - + void testValidationShouldPass() { assertTrue(dateValidator.validate("12/01")); assertTrue(dateValidator.validate("03/22")); assertTrue(dateValidator.validate("09/22")); assertTrue(dateValidator.validate("10/20")); assertTrue(dateValidator.validate("07/15")); + } + @Test + void testValidationShouldFail() { assertFalse(dateValidator.validate("aa")); assertFalse(dateValidator.validate("")); assertFalse(dateValidator.validate("01-02")); @@ -25,5 +27,4 @@ void testValidation() { assertFalse(dateValidator.validate("2/22")); assertFalse(dateValidator.validate(" / ")); } - } diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java index 7153e817..7d2afd3a 100644 --- a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/TeamNameValidatorTest.java @@ -6,17 +6,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class TeamNameValidatorTest { + TeamNameValidator teamNameValidator = new TeamNameValidator(); @Test - void testValidation() { - TeamNameValidator teamNameValidator = new TeamNameValidator(); - + void testValidationShouldPass() { assertTrue(teamNameValidator.validate("name")); assertTrue(teamNameValidator.validate("test-hello-world")); assertTrue(teamNameValidator.validate("22312")); assertTrue(teamNameValidator.validate("alphanumeric-and-hyphens-23")); assertTrue(teamNameValidator.validate("UPPERcase")); + } + @Test + void testValidationShouldFail() { assertFalse(teamNameValidator.validate("name with spaces")); assertFalse(teamNameValidator.validate("very-very-very-very-very-very-very-very-very-very-long-name")); assertFalse(teamNameValidator.validate("-name")); diff --git a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java index d5fc80c5..aca3d582 100644 --- a/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java +++ b/src/test/java/io/pakland/mdas/githubstats/infrastructure/shell/validation/UserNameValidatorTest.java @@ -6,17 +6,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class UserNameValidatorTest { + UserNameValidator userNameValidator = new UserNameValidator(); @Test - void testValidation() { - UserNameValidator userNameValidator = new UserNameValidator(); - + void testValidationShouldPass() { assertTrue(userNameValidator.validate("name")); assertTrue(userNameValidator.validate("test-hello-world")); assertTrue(userNameValidator.validate("22312")); assertTrue(userNameValidator.validate("alphanumeric-and-hyphens-23")); assertTrue(userNameValidator.validate("UPPERcase")); + } + @Test + void testValidationShouldFail() { assertFalse(userNameValidator.validate("name with spaces")); assertFalse(userNameValidator.validate("very-very-very-very-very-very-very-very-very-very-long-name")); assertFalse(userNameValidator.validate("-name")); @@ -26,5 +28,4 @@ void testValidation() { assertFalse(userNameValidator.validate(" ")); assertFalse(userNameValidator.validate(" - ")); } - } From d3ed191e64ae02561b7d9e52eabc74a233d6d9f1 Mon Sep 17 00:00:00 2001 From: Miquel de Domingo Date: Tue, 29 Nov 2022 18:46:09 +0100 Subject: [PATCH 11/11] feat: add longname to name option --- .../shell/configuration/CommandConfiguration.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java index f1e483f9..1092eb91 100644 --- a/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java +++ b/src/main/java/io/pakland/mdas/githubstats/infrastructure/shell/configuration/CommandConfiguration.java @@ -22,6 +22,7 @@ public CommandRegistration buildUserCommand() { .and() .withOption() .shortNames('n') + .longNames("name") .label("USER_NAME") .arity(CommandRegistration.OptionArity.EXACTLY_ONE) .type(String.class) @@ -56,6 +57,7 @@ public CommandRegistration buildTeamCommand() { .and() .withOption() .shortNames('n') + .longNames("name") .label("TEAM_NAME") .arity(CommandRegistration.OptionArity.EXACTLY_ONE) .type(String.class)