Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add oauth 2 Angular #1701

Merged
merged 18 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ jobs:
- svelteapp
- kafkaapp
- reactiveapp
- angularoauth2app
steps:
- name: 'Setup: checkout project'
uses: actions/checkout@v3
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/tech/jhipster/lite/common/domain/WordUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public class WordUtils {
public static final String OB = "\\{";
public static final String CB = "\\}";

public static final String COMA = ",";
public static final String O_BRACKET = "[";
public static final String C_BRACKET = "]";

private static final String VALUE_FIELD = "value";

private WordUtils() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Angular

## Description

This context is used to manipulate existing angular files :

- Add imports in .ts
- Add constants in .ts
- Add declarations, providers in decorated classes
- Add new config in environment.ts files
- ...

## Maintainers

- [Bolo](https://github.com/Bolo89)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package tech.jhipster.lite.generator.client.angular.common.application;

import org.springframework.stereotype.Service;
import tech.jhipster.lite.generator.client.angular.common.domain.AngularCommonService;
import tech.jhipster.lite.generator.project.domain.Project;

@Service
public class AngularCommonApplicationService {

private final AngularCommonService angularCommonService;

public AngularCommonApplicationService(AngularCommonService angularCommonService) {
this.angularCommonService = angularCommonService;
}

public void addImports(Project project, String filePath, String imports) {
angularCommonService.addImports(project, filePath, imports);
}

public void addInExistingImport(Project project, String filePath, String imports, String existingImportName) {
angularCommonService.addInExistingImport(project, filePath, imports, existingImportName);
}

public void addConstants(Project project, String filePath, String constants) {
angularCommonService.addConstants(project, filePath, constants);
}

public void addDeclarations(Project project, String filePath, String declarations) {
angularCommonService.addDeclarations(project, filePath, declarations);
}

public void addProviders(Project project, String filePath, String providers) {
angularCommonService.addProviders(project, filePath, providers);
}

public void addEnvVariables(Project project, String envFilePath, String values) {
angularCommonService.addEnvVariables(project, envFilePath, values);
}

public void addHtml(Project project, String htmlFilePath, String htmlToAdd, String htmlTagRegexToReplace) {
angularCommonService.addHtml(project, htmlFilePath, htmlToAdd, htmlTagRegexToReplace);
}

public void addTest(Project project, String specTsFilePath, String testToAdd, String afterTestName) {
angularCommonService.addTest(project, specTsFilePath, testToAdd, afterTestName);
}

public void addAllowedCommonJsDependenciesAngularJson(Project project, String libToAdd) {
angularCommonService.addAllowedCommonJsDependenciesAngularJson(project, libToAdd);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package tech.jhipster.lite.generator.client.angular.common.domain;

import java.util.List;

public class AngularCommon {

protected static final String ANGULAR_JSON_FILE_NAME = "angular.json";

protected static final String IMPORT_REGEX = "(^import[\\s]+[^;]+;)";
protected static final String EXISTING_IMPORT_PATTERN = "^(import[\\s]+\\{[^\\}]+)\\} from '[%s]+';";

protected static final List<String> DECORATOR_REGEX_LIST = List.of("(^@[A-Z]{1}[\\w]+\\(\\{)");

protected static final String DECLARATIONS_REGEX = "^([\\s]+declarations:[\\s]+\\[[^\\]]+\\][\\s,]*)";

protected static final List<String> DECLARATIONS_WITH_ARRAY_VALUES_REGEX_LIST = List.of(
"^([\\s]+declarations:[\\s]+\\[[^\\]]+)\\]",
"^([\\s]+declarations:[\\s]+\\[)\\]"
);

protected static final List<String> PROVIDERS_WITH_ARRAY_VALUES_REGEX_LIST = List.of(
"^([\\s]+providers:[\\s]+\\[[^\\]]+)\\]",
"^([\\s]+providers:[\\s]+\\[)\\]"
);

protected static final List<String> ENV_VARIABLES_WITH_VALUES_REGEX_LIST = List.of(
"(export const environment = [^(\\};)]+[\\}]?[\\s,]*)\\};"
);

protected static final String TEST_REGEX_FORMAT = "([\\s]+it\\('%s',[^}]+}\\);)";

protected static final List<String> ALLOWED_COMMON_JS_DEPENDENCIES_REGEX_LIST = List.of(
"^([\\s]+\"allowedCommonJsDependencies\": [^\\]]+)\\]"
);

private AngularCommon() {
// Cannot be instantiated
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package tech.jhipster.lite.generator.client.angular.common.domain;

import static tech.jhipster.lite.common.domain.WordUtils.COMA;
import static tech.jhipster.lite.common.domain.WordUtils.C_BRACKET;
import static tech.jhipster.lite.common.domain.WordUtils.O_BRACKET;
import static tech.jhipster.lite.common.domain.WordUtils.indent;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.ALLOWED_COMMON_JS_DEPENDENCIES_REGEX_LIST;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.ANGULAR_JSON_FILE_NAME;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.DECLARATIONS_REGEX;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.DECLARATIONS_WITH_ARRAY_VALUES_REGEX_LIST;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.DECORATOR_REGEX_LIST;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.ENV_VARIABLES_WITH_VALUES_REGEX_LIST;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.EXISTING_IMPORT_PATTERN;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.PROVIDERS_WITH_ARRAY_VALUES_REGEX_LIST;
import static tech.jhipster.lite.generator.client.angular.common.domain.AngularCommon.TEST_REGEX_FORMAT;

import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import tech.jhipster.lite.common.domain.FileUtils;
import tech.jhipster.lite.error.domain.GeneratorException;
import tech.jhipster.lite.generator.project.domain.Project;

public class AngularCommonDomainService implements AngularCommonService {

@Override
public void addImports(Project project, String tsFilePath, String imports) {
String fullFilePath = FileUtils.getPath(project.getFolder(), tsFilePath);
String fileContent = getFileContent(fullFilePath);

String newFileContent = getLastImportInFile(fileContent)
.map(lastImport -> fileContent.replace(lastImport, lastImport + project.getEndOfLine() + imports))
.orElse(imports + project.getEndOfLine() + fileContent);

writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addInExistingImport(Project project, String tsFilePath, String importToAdd, String existingImportName) {
String fullFilePath = FileUtils.getPath(project.getFolder(), tsFilePath);
String fileContent = getFileContent(fullFilePath);

String newFileContent = getFirstMatchInFile(List.of(String.format(EXISTING_IMPORT_PATTERN, existingImportName)), fileContent)
.map(importPrefix -> appendValuesInList(fileContent, importPrefix, importToAdd, ""))
.orElseThrow(() -> new GeneratorException("Cannot find declarations array in file " + fullFilePath));

writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addConstants(Project project, String tsFilePath, String constants) {
String fullFilePath = FileUtils.getPath(project.getFolder(), tsFilePath);
String fileContent = getFileContent(fullFilePath);
String newFileContent = getFirstMatchInFile(DECORATOR_REGEX_LIST, fileContent)
.map(decoratorPrefix -> fileContent.replace(decoratorPrefix, constants + project.getEndOfLine() + decoratorPrefix))
.orElse(fileContent + project.getEndOfLine() + constants);

writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addDeclarations(Project project, String tsFilePath, String declarations) {
String fullFilePath = FileUtils.getPath(project.getFolder(), tsFilePath);
String fileContent = getFileContent(fullFilePath);
String newFileContent = getFirstMatchInFile(DECLARATIONS_WITH_ARRAY_VALUES_REGEX_LIST, fileContent)
.map(declarationsPrefix -> appendValuesInList(fileContent, declarationsPrefix, declarations, project.getEndOfLine()))
.orElseThrow(() -> new GeneratorException("Cannot find declarations array in file " + fullFilePath));

writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addProviders(Project project, String tsFilePath, String providers) {
String fullFilePath = FileUtils.getPath(project.getFolder(), tsFilePath);
String fileContent = getFileContent(fullFilePath);

String newFileContent = getFirstMatchInFile(PROVIDERS_WITH_ARRAY_VALUES_REGEX_LIST, fileContent)
.map(providersPrefix -> appendValuesInList(fileContent, providersPrefix, providers, project.getEndOfLine()))
.orElseGet(() -> appendProvidersAfterDeclarations(fileContent, fullFilePath, providers, project));

writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addEnvVariables(Project project, String envFilePath, String values) {
String fullFilePath = FileUtils.getPath(project.getFolder(), envFilePath);
String fileContent = getFileContent(fullFilePath);
String newFileContent = getFirstMatchInFile(ENV_VARIABLES_WITH_VALUES_REGEX_LIST, fileContent)
.map(prefixEnvVariables -> {
String updatedEnvVariablesStr = prefixEnvVariables.stripTrailing();
if (!updatedEnvVariablesStr.endsWith(COMA)) {
updatedEnvVariablesStr += COMA;
}
updatedEnvVariablesStr += project.getEndOfLine() + values.stripTrailing() + project.getEndOfLine();
return fileContent.replace(prefixEnvVariables, updatedEnvVariablesStr);
})
.orElseThrow(() -> new GeneratorException("Cannot find environnement const in " + fullFilePath));
writeInFile(fullFilePath, newFileContent, project);
}

@Override
public void addHtml(Project project, String htmlFilePath, String htmlToAdd, String htmlTagRegexToReplace) {
replaceTextByRegex(project, htmlFilePath, htmlToAdd, htmlTagRegexToReplace);
}

@Override
public void addTest(Project project, String specTsFilePath, String testToAdd, String afterTestName) {
String testRegex = String.format(TEST_REGEX_FORMAT, afterTestName.replaceAll("\\s", "[\\\\s]+"));
replaceTextByRegex(project, specTsFilePath, testToAdd, testRegex);
}

@Override
public void addAllowedCommonJsDependenciesAngularJson(Project project, String libToAdd) {
String fullFilePath = FileUtils.getPath(project.getFolder(), ANGULAR_JSON_FILE_NAME);
String fileContent = getFileContent(fullFilePath);
String newFileContent = getFirstMatchInFile(ALLOWED_COMMON_JS_DEPENDENCIES_REGEX_LIST, fileContent)
.map(dependenciesPrefix -> appendValuesInList(fileContent, dependenciesPrefix, libToAdd, project.getEndOfLine()))
.orElseThrow(() -> new GeneratorException("Cannot find allowed common js dependencies array in file " + fullFilePath));

writeInFile(fullFilePath, newFileContent, project);
}

private String getFileContent(String fullFilePath) {
String fileContent;
try {
fileContent = FileUtils.read(fullFilePath);
} catch (IOException e) {
throw new GeneratorException("Cannot read file " + fullFilePath + ": " + e.getMessage());
}
return fileContent;
}

private void writeInFile(String fullFilePath, String newFileContent, Project project) {
try {
FileUtils.write(fullFilePath, newFileContent, project.getEndOfLine());
} catch (IOException e) {
throw new GeneratorException("Cannot write content in file " + fullFilePath + ": " + e.getMessage());
}
}

private Optional<String> getLastImportInFile(String fileContent) {
Pattern pattern = Pattern.compile(AngularCommon.IMPORT_REGEX, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(fileContent);
String lastMatchFound = null;
while (matcher.find()) {
lastMatchFound = matcher.group(1);
}
return Optional.ofNullable(lastMatchFound);
}

private Optional<String> getFirstMatchInFile(List<String> regexList, String fileContent) {
return regexList
.stream()
.map(regex -> {
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
return pattern.matcher(fileContent);
})
.filter(Matcher::find)
.findFirst()
.map(matcher -> matcher.group(1));
}

private String appendValuesInList(String fileContent, String prefixWithArrayValuesStr, String arrayValuesToAdd, String endOfLine) {
StringBuilder updatedArrayValuesStr = new StringBuilder(prefixWithArrayValuesStr.stripTrailing());
if (!prefixWithArrayValuesStr.trim().endsWith(O_BRACKET) && !updatedArrayValuesStr.toString().endsWith(COMA)) {
updatedArrayValuesStr.append(COMA);
}
int prefixIdx = prefixWithArrayValuesStr.indexOf(prefixWithArrayValuesStr.trim());
String spaceBeforePrefix = prefixWithArrayValuesStr.substring(0, prefixIdx);
updatedArrayValuesStr.append(endOfLine).append(arrayValuesToAdd.stripTrailing()).append(endOfLine).append(spaceBeforePrefix);
return fileContent.replace(prefixWithArrayValuesStr, updatedArrayValuesStr.toString());
}

private String appendProvidersAfterDeclarations(String fileContent, String fullFilePath, String providers, Project project) {
String declarationsStr = getFirstMatchInFile(List.of(DECLARATIONS_REGEX), fileContent)
.map(String::stripTrailing)
.orElseThrow(() -> new GeneratorException("Missing declarations in file: " + fullFilePath));
String newProvidersArrayStr =
indent(1) +
"providers: " +
O_BRACKET +
project.getEndOfLine() +
providers.stripTrailing() +
project.getEndOfLine() +
indent(1) +
C_BRACKET +
COMA;
String declarationsAndProvidersStr = declarationsStr.trim().endsWith(COMA) ? declarationsStr : declarationsStr + COMA;
declarationsAndProvidersStr += project.getEndOfLine() + newProvidersArrayStr;
return fileContent.replace(declarationsStr, declarationsAndProvidersStr);
}

private void replaceTextByRegex(Project project, String filePath, String textToAdd, String textToReplaceRegex) {
String fullFilePath = FileUtils.getPath(project.getFolder(), filePath);
String fileContent = getFileContent(fullFilePath);
Pattern pattern = Pattern.compile(textToReplaceRegex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(fileContent);
if (!matcher.find()) {
throw new GeneratorException("Cannot find " + textToReplaceRegex + " in file " + fullFilePath);
}
String textFound = matcher.group(1);
String newFileContent = fileContent.replace(textFound, textFound.stripTrailing() + project.getEndOfLine() + textToAdd);
writeInFile(fullFilePath, newFileContent, project);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package tech.jhipster.lite.generator.client.angular.common.domain;

import tech.jhipster.lite.generator.project.domain.Project;

public interface AngularCommonService {
void addImports(Project project, String tsFilePath, String imports);

void addInExistingImport(Project project, String tsFilePath, String importToAdd, String existingImportName);

void addConstants(Project project, String tsFilePath, String constants);

void addDeclarations(Project project, String tsFilePath, String declarations);

void addProviders(Project project, String tsFilePath, String providers);

void addEnvVariables(Project project, String envFilePath, String values);

void addHtml(Project project, String htmlFilePath, String htmlToAdd, String htmlTagRegexToReplace);

void addTest(Project project, String specTsFilePath, String testToAdd, String afterTestName);

void addAllowedCommonJsDependenciesAngularJson(Project project, String libToAdd);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package tech.jhipster.lite.generator.client.angular.common.infrastructure;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tech.jhipster.lite.generator.client.angular.common.domain.AngularCommonDomainService;
import tech.jhipster.lite.generator.client.angular.common.domain.AngularCommonService;

@Configuration
public class AngularCommonBeanConfiguration {

@Bean
public AngularCommonService angularCommonService() {
return new AngularCommonDomainService();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@tech.jhipster.lite.SharedKernel
package tech.jhipster.lite.generator.client.angular.common;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Angular

## Description

This context is used to add oauth2 (with keycloak) in angular project.

## Maintainers

- [Bolo](https://github.com/Bolo89)
Loading