Commit 1b068ebb authored by bazarbay's avatar bazarbay

first commit

parent 44cd2275
Pipeline #326 failed with stages
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
FROM xldevops/jdk17-lts
ARG JAR_FILE=build/libs/printedFormsService-app.jar
#RUN mkdir /app
COPY ${JAR_FILE} /spring-boot-application.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar","/spring-boot-application.jar"]
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Gradle documentation](https://docs.gradle.org)
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.5/gradle-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.5/gradle-plugin/reference/html/#build-image)
### Additional Links
These additional references should also help you:
* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle)
# templateService # printedFormsService
\ No newline at end of file
plugins {
id 'java'
id "org.springframework.boot" version "3.1.5"
id "io.spring.dependency-management" version "1.1.0"
}
group = 'kz.project'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
ext {
pluginVersion = '1.1'
set('springCloudVersion', "2022.0.3")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.boot:spring-boot-starter-actuator"
/*implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'*/
implementation 'org.springframework.cloud:spring-cloud-starter-feign:1.4.7.RELEASE'
runtimeOnly 'org.postgresql:postgresql:42.6.0'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
annotationProcessor 'org.projectlombok:lombok'
implementation 'net.sf.jasperreports:jasperreports:6.20.6'
implementation 'org.freemarker:freemarker:2.3.31'
implementation 'com.github.librepdf:openpdf:1.3.30'
implementation ('com.jlefebure:spring-boot-starter-minio:1.10')/*{
exclude('org.springframework.boot:spring-boot-starters')
}*/
compileOnly 'org.projectlombok:lombok:1.18.28'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
implementation 'org.modelmapper:modelmapper:3.2.0'
implementation 'commons-fileupload:commons-fileupload:1.4'
implementation 'commons-codec:commons-codec:1.16.0'
// implementation "org.flywaydb:flyway-core"
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
bootJar {
archiveFileName.set("${project.name}-app.jar")
}
jar { enabled = false }
test {
useJUnitPlatform()
}
\ No newline at end of file
version: '3'
services:
postgres:
image: postgres
environment:
POSTGRES_DB: template_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
expose:
- 5432
ports:
- "5432:5432"
client-backend:
image: templete-service:latest
build:
context: ./
dockerfile: Dockerfile
ports:
- "8081:8081"
depends_on:
- postgres
environment:
- SERVER_PORT= 8081
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/template_db
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'printedFormsService'
package kz.project.printedFormsService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PrintedFormsServiceApplication {
public static void main(String[] args) {
SpringApplication.run(PrintedFormsServiceApplication.class, args);
}
}
package kz.project.printedFormsService;
import lombok.Data;
import java.util.function.Supplier;
@Data
public class ValidationException extends Exception {
private String message;
private int code;
public ValidationException(String message){
super(message);
}
public ValidationException(String message, int code) {
this.message = message;
this.code = code;
}
}
package kz.project.printedFormsService.config;
import freemarker.template.TemplateExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FreemarkerTemplateConfiguration {
@Bean
public freemarker.template.Configuration freemarkerConfiguration() {
freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_30);
configuration.setDefaultEncoding("UTF-8");
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
configuration.setLogTemplateExceptions(false);
return configuration;
}
}
/*
package kz.project.printedFormsService.config;
import kz.project.printedFormsService.converter.JwtAuthConverter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {
private static final String[] WHITE_LIST_URL = {"/api/v1/auth/**",
"/v2/api-docs",
"/v3/api-docs",
"/v3/api-docs/**",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui/**",
"/webjars/**",
"/swagger-ui.html"};
private final JwtAuthConverter jwtAuthConverter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults())
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests(req ->
req.requestMatchers(WHITE_LIST_URL)
.permitAll()
.anyRequest()
.authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
.oauth2ResourceServer(oauth ->
oauth.jwt(jwt ->
jwt.jwtAuthenticationConverter(jwtAuthConverter)))
*/
/* .authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.logout(logout ->
logout.logoutUrl("/api/v1/auth/logout")
.addLogoutHandler(logoutHandler)
.logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext())*//*
;
*/
/* http
.csrf()
.disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated();*//*
*/
/* http
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthConverter);
http
.sessionManagement()
.sessionCreationPolicy(STATELESS);*//*
return http.build();
}
*/
/* @Bean
public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
return new RefreshTokenOAuth2UserService(delegate, clientRegistrationRepository, authorizedClientRepository);
}*//*
}*/
package kz.project.printedFormsService.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.context.annotation.Configuration;
@OpenAPIDefinition(
info = @Info(
title = "Template Service API",
description = "Loyalty System", version = "1.0.0",
contact = @Contact(
name = "Struchkov Mark",
email = "mark@struchkov.dev",
url = "https://mark.struchkov.dev"
)
)
)
@Configuration
public class SwaggerConfig {
}
package kz.project.printedFormsService.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import kz.project.printedFormsService.data.dto.DTemplateTypeDto;
import kz.project.printedFormsService.service.DTemplateTypeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/dict")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "DTemplate Controller", description = "API TemplateService")
public class DTemplateTypeController {
private final DTemplateTypeService service;
@GetMapping("get/all")
@Operation(description = "Метод для получения шаблона по идентификатору")
public List<DTemplateTypeDto> getDict() {
return service.getAllTemplateType();
}
}
package kz.project.printedFormsService.controller;
;
import kz.project.printedFormsService.ValidationException;
import kz.project.printedFormsService.data.dto.ResponseErrorDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.Optional;
@ControllerAdvice
public class RestErrorController extends ResponseEntityExceptionHandler {
@ExceptionHandler(ValidationException.class)
//@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Remote service response")
protected ResponseEntity<ResponseErrorDto> handleThereIsNoSuchUserException(ValidationException err) {
err.printStackTrace();
return new ResponseEntity<>(new ResponseErrorDto(err.getMessage(),err.getCode()),HttpStatus.BAD_REQUEST);
}
}
package kz.project.printedFormsService.controller;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import kz.project.printedFormsService.ValidationException;
import kz.project.printedFormsService.data.dto.TemplateDto;
import kz.project.printedFormsService.service.TemplateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/template")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Template Controller", description = "API TemplateService")
public class TemplateController {
private final TemplateService service;
@Hidden
@GetMapping("/{id}")
@Operation(description = "Метод для получения шаблона по идентификатору")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Map.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
public Map<String, byte[]> getTemplate(@Parameter(name = "id", required = true) @PathVariable Long id) throws ValidationException {
return service.getTemplate(id);
}
@GetMapping("get/{id}")
@Operation(description = "Метод для получения шаблона по идентификатору")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateDto.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
public ResponseEntity<TemplateDto> getTemplateData(@Parameter(name = "id", required = true) @PathVariable Long id) throws ValidationException {
TemplateDto templateData = service.getTemplateData(id);
return ResponseEntity.ok(templateData);
}
@PutMapping(value = "/save")
@Operation(description = "Метод сохранения шаблона")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateDto.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
public ResponseEntity<TemplateDto> seveTemplate(@Parameter(name = "data") @RequestParam("data") MultipartFile data,
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto
) throws IOException, ValidationException {
if (header != null) {
return ResponseEntity.ok(service.save(dto, List.of(data,header)));
} else {
return ResponseEntity.ok(service.save(dto, List.of(data)));
}
}
@PutMapping(value = "/edit")
@Operation(description = "Метод для сохранение изменения")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TemplateDto.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
public ResponseEntity<TemplateDto> editTemplate(@Parameter(name = "data") @RequestParam("data") MultipartFile data,
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto) throws IOException, ValidationException {
if (header != null) {
return ResponseEntity.ok(service.edit(dto, List.of(data, header)));
} else {
return ResponseEntity.ok(service.edit(dto, List.of(data)));
}
}
@DeleteMapping("/delete/{code}")
@Operation(description = "Метод для удаления шаблона по идентификатору")
public ResponseEntity<String> deleteTemplate(@Parameter(name = "code", required = true) @PathVariable("code") String code) {
service.delete(code);
return ResponseEntity.ok("delete is success");
}
@GetMapping("/all")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Page.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
@Operation(description = "Метод для получения всех шаблонов")
public Page<TemplateDto> getAll(@Parameter(name = "isActive") @RequestParam(value = "isActive", required = false) Boolean isActive,
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) {
return service.getAllTemplate(isActive, PageRequest.of(page, size));
}
@GetMapping("/allVersion/{code}")
@Operation(description = "Метод для получения всех шаблонов")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Данные получены успешно",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Page.class))
}),
@ApiResponse(
responseCode = "400",
description = "Ошибка сервиса",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationException.class))
})
})
public Page<TemplateDto> getAllByCode(@Parameter(name = "code") @PathVariable(value = "code") String code,
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) throws ValidationException {
return service.getAllTemplateByCode(code, PageRequest.of(page, size));
}
}
/*
package kz.project.printedFormsService.converter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
public class JwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {
private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter =
new JwtGrantedAuthoritiesConverter();
@Value("${jwt.auth.converter.principle-attribute}")
private String principleAttribute;
@Value("${jwt.auth.converter.resource-id}")
private String resourceId;
@Override
public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
Collection<GrantedAuthority> authorities = Stream.concat(
jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
extractResourceRoles(jwt).stream()
).collect(Collectors.toSet());
return new JwtAuthenticationToken(
jwt,
authorities,
getPrincipleClaimName(jwt)
);
}
private String getPrincipleClaimName(Jwt jwt) {
String claimName = JwtClaimNames.SUB;
if (principleAttribute != null) {
claimName = principleAttribute;
}
return jwt.getClaim(claimName);
}
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
Map<String, Object> resourceAccess;
Map<String, Object> resource;
Collection<String> resourceRoles;
if (jwt.getClaim("resource_access") == null) {
return Set.of();
}
resourceAccess = jwt.getClaim("resource_access");
if (resourceAccess.get(resourceId) == null) {
return Set.of();
}
resource = (Map<String, Object>) resourceAccess.get(resourceId);
resourceRoles = (Collection<String>) resource.get("roles");
return resourceRoles
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toSet());
}
}*/
package kz.project.printedFormsService.converter;
import com.fasterxml.jackson.databind.ObjectMapper;
import kz.project.printedFormsService.data.dto.TemplateDto;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
@Component
public class TempateDtoToStringConverter implements Converter<String, TemplateDto> {
@Autowired
private ObjectMapper objectMapper;
@Override
@SneakyThrows
public TemplateDto convert(String source) {
return objectMapper.readValue(source, TemplateDto.class);
}
}
package kz.project.printedFormsService.data.dto;
import kz.project.printedFormsService.data.entity.dict.DTemplateType;
import kz.project.printedFormsService.service.DTemplateTypeService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DTemplateTypeDto {
private String code;
private String name;
public static DTemplateTypeDto toDto(DTemplateType et){
return new DTemplateTypeDto(et.getCode(), et.getName());
}
public static List<DTemplateTypeDto>toDtoList(List<DTemplateType> ets){
List<DTemplateTypeDto> dtos = new ArrayList<>();
ets.stream().forEach(i->dtos.add(new DTemplateTypeDto(i.getCode(), i.getName())));
return dtos;
}
}
package kz.project.printedFormsService.data.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "MessageDto", description = "Ответ")
public class ResponseErrorDto {
@NotBlank
@Schema(name = "errorMessage")
private String errorMessage;
@NotBlank
@Schema(name = "code")
private int code;
}
package kz.project.printedFormsService.data.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import kz.project.printedFormsService.data.entity.TemplateEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "TemplateDto", description = "Модель")
public class TemplateDto {
@NotBlank
@Schema(name ="templateId", description = "Код шаблона", defaultValue = "123")
private Long templateId;
@NotBlank
@Schema(name ="code", description = "Код шаблона", defaultValue = "template_1")
private String code;
@NotBlank
@Schema(name ="name", description = "Наименование шаблона",defaultValue = "Шаблон 1")
private String name;
@NotBlank
@Schema(name = "type", description = "Тип фаила")
private String type;
@NotBlank
@Schema(name ="status", description = "Флаг активности", defaultValue = "1")
private Boolean status;
@NotBlank
@Schema(name ="version", description = "Версия активности")
private Integer version;
private TemplateFileDataDto templateFile;
private TemplateFileDataDto headerFile;
private List<GroupIndoDto>groups;
public static TemplateDto toDtoShort(TemplateEntity te) {
return TemplateDto.builder()
.code(te.getCode())
.status(te.getStatus())
.templateFile(new TemplateFileDataDto(te.getTemplate().getId(),te.getTemplate().getName()))
.headerFile(te.getTempleateHeader()!=null?new TemplateFileDataDto(te.getTempleateHeader().getId(),te.getTempleateHeader().getName()):null)
.type(te.getType().getCode())
.version(te.getVersion())
.groups(List.of(new GroupIndoDto("1","группа-1"),new GroupIndoDto("2","группа-2")))
.build();
}
public static TemplateDto toDto(TemplateEntity te) {
return TemplateDto.builder()
.templateId(te.getId())
.name(te.getTemplate().getName())
.code(te.getCode())
.status(te.getStatus())
.templateFile(new TemplateFileDataDto(te.getTemplate().getId(),te.getTemplate().getName()))
.headerFile(te.getTempleateHeader()!=null?new TemplateFileDataDto(te.getTempleateHeader().getId(),te.getTempleateHeader().getName()):null)
.type(te.getType().getCode())
.version(te.getVersion())
.groups(List.of(new GroupIndoDto("1","группа-1"),new GroupIndoDto("2","группа-2")))
.build();
}
public static Page<TemplateDto> toDtoList(Page<TemplateEntity> all){
if(all.getContent()==null)return null;
List<TemplateDto> dtos = new ArrayList<>();
for (TemplateEntity te:all.getContent()) {
dtos.add(TemplateDto.toDto(te));
}
return new PageImpl<>(dtos, PageRequest.of(all.getNumber(),all.getSize()),all.getTotalElements());
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class TemplateFileDataDto{
@NotBlank
@Schema(name ="fileId", description = "Идентификатор файла", defaultValue = "4654654646")
private Long fileId;
@NotBlank
@Schema(name ="fileName", description = "Название файла")
private String fileName;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class GroupIndoDto{
private String groupId;
private String name;
}
}
package kz.project.printedFormsService.data.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDto {
private String name;
private String email;
private List<String>projects;
private List<String> roles;
}
package kz.project.printedFormsService.data.entity;
import jakarta.persistence.*;
import kz.project.printedFormsService.data.entity.dict.DTemplateType;
import lombok.Data;
@Entity
@Table(name = "template", schema = "template_schema")
@Data
public class TemplateEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
private Boolean status;
private Integer version;
@ManyToOne
private DTemplateType type;
@OneToOne
private TemplateFileInfoEntity template;
@OneToOne
private TemplateFileInfoEntity templeateHeader;
}
package kz.project.printedFormsService.data.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "file_info", schema = "template_schema")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TemplateFileInfoEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Boolean isHeader;
private String path;
private Integer hash;
private byte[] data;
}
package kz.project.printedFormsService.data.entity.dict;
import jakarta.persistence.*;
import lombok.Data;
@Entity
@Table(name = "d_template_type", schema = "template_schema")
@Data
public class DTemplateType {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
private String name;
}
/*
package kz.project.printedFormsService.data.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.security.Permission;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public enum Role {
USER(Collections.emptySet()),
ADMIN(
Set.of(
ADMIN_READ,
ADMIN_UPDATE,
ADMIN_DELETE,
ADMIN_CREATE,
MANAGER_READ,
MANAGER_UPDATE,
MANAGER_DELETE,
MANAGER_CREATE
)
),
MANAGER(
Set.of(
MANAGER_READ,
MANAGER_UPDATE,
MANAGER_DELETE,
MANAGER_CREATE
)
)
;
@Getter
private final Set<Permission> permissions;
public List<SimpleGrantedAuthority> getAuthorities() {
var authorities = getPermissions()
.stream()
.map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
.collect(Collectors.toList());
authorities.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
return authorities;
}
}*/
package kz.project.printedFormsService.data.repository;
import kz.project.printedFormsService.data.entity.dict.DTemplateType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface DTemplateTypeRepository extends JpaRepository<DTemplateType, Long> {
Optional<DTemplateType>findByCode(String code);
}
package kz.project.printedFormsService.data.repository;
import kz.project.printedFormsService.data.entity.TemplateFileInfoEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TemplateFileInfoRepository extends JpaRepository<TemplateFileInfoEntity, Long> {
}
/*
package kz.project.printedFormsService.data.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TemplateHeaderRepository extends JpaRepository<TemplateHeaderRepository, Long> {
}
*/
package kz.project.printedFormsService.data.repository;
import kz.project.printedFormsService.data.entity.TemplateEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface TemplateRepository extends JpaRepository<TemplateEntity, Long> {
Optional<TemplateEntity> findByCode(String code);
Page<TemplateEntity> findAllByStatusTrue(Pageable pageable);
Page<TemplateEntity> findAllByStatusFalse(Pageable pageable);
Optional<TemplateEntity> findFirstByCodeOrderByVersionDesc(String code);
Page<TemplateEntity> findAllByCode(Pageable pageable, String code);
}
package kz.project.printedFormsService.service;
import kz.project.printedFormsService.data.dto.DTemplateTypeDto;
import java.util.List;
public interface DTemplateTypeService {
List<DTemplateTypeDto> getAllTemplateType();
}
package kz.project.printedFormsService.service;
import kz.project.printedFormsService.ValidationException;
import kz.project.printedFormsService.data.dto.TemplateDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public interface TemplateService {
Map<String, byte[]> getTemplate(Long id) throws ValidationException;
TemplateDto save(TemplateDto dto, List<MultipartFile> files) throws IOException, ValidationException;
TemplateDto edit(TemplateDto dto, List<MultipartFile> files) throws IOException, ValidationException;
void delete(String code);
Page<TemplateDto> getAllTemplate(Boolean isActive, Pageable pageable);
TemplateDto getTemplateData(Long id) throws ValidationException;
Page<TemplateDto> getAllTemplateByCode(String code, Pageable pageable) throws ValidationException;
}
package kz.project.printedFormsService.service.impl;
import kz.project.printedFormsService.data.dto.DTemplateTypeDto;
import kz.project.printedFormsService.data.entity.dict.DTemplateType;
import kz.project.printedFormsService.data.repository.DTemplateTypeRepository;
import kz.project.printedFormsService.service.DTemplateTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class DTemplateTypeServiceImpl implements DTemplateTypeService {
private final DTemplateTypeRepository repository;
public List<DTemplateTypeDto> getAllTemplateType(){
List<DTemplateType> all = repository.findAll();
return DTemplateTypeDto.toDtoList(all);
}
}
package kz.project.printedFormsService.service.impl;
import kz.project.printedFormsService.ValidationException;
import kz.project.printedFormsService.data.dto.TemplateDto;
import kz.project.printedFormsService.data.entity.TemplateEntity;
import kz.project.printedFormsService.data.entity.TemplateFileInfoEntity;
import kz.project.printedFormsService.data.repository.DTemplateTypeRepository;
import kz.project.printedFormsService.data.repository.TemplateFileInfoRepository;
import kz.project.printedFormsService.data.repository.TemplateRepository;
import kz.project.printedFormsService.service.TemplateService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class TemplateServiceImpl implements TemplateService {
private final TemplateRepository repository;
private final DTemplateTypeRepository dTemplateTypeRepository;
private final TemplateFileInfoRepository fileInfoRepository;
@Override
public Map<String, byte[]> getTemplate(Long id) throws ValidationException {
Map<String, byte[]> params = new HashMap<>();
TemplateEntity templateEntity = repository.findById(id).orElse(null);
if (templateEntity == null) throw new ValidationException("по данному параметру отсутствуют данные: "+id, 13);
params.put("body", templateEntity.getTemplate().getData());
params.put("header", templateEntity.getTempleateHeader()!=null?templateEntity.getTempleateHeader().getData():null);
return params;
}
@Override
@Transactional
public TemplateDto save(TemplateDto dto, List<MultipartFile> files) throws IOException, ValidationException {
if (!validateData(dto)) throw new ValidationException("Не переданы обязательные поля", 13);
TemplateEntity templateEntity = createTemplateEntity(dto, files);
TemplateEntity save = repository.save(templateEntity);
return TemplateDto.toDto(save);
}
@Override
@Transactional
public TemplateDto edit(TemplateDto dto, List<MultipartFile> files) throws IOException, ValidationException {
if (!validateData(dto) || dto.getTemplateId() == null || repository.findById(dto.getTemplateId()) == null)
throw new ValidationException("Не переданы обязательные поля", 13);
return TemplateDto.toDto(repository.save(createTemplateEntity(dto, files)));
}
@Override
public void delete(String code) {
repository.delete(repository.findByCode(code).get());
}
@Override
public Page<TemplateDto> getAllTemplate(Boolean isActive, Pageable pageable) {
if (isActive == null) return TemplateDto.toDtoList(repository.findAll(pageable));
else if (isActive)
return TemplateDto.toDtoList(repository.findAllByStatusTrue(pageable));
else return TemplateDto.toDtoList(repository.findAllByStatusFalse(pageable));
}
@Override
public TemplateDto getTemplateData(Long id) throws ValidationException {
if (id == null) throw new ValidationException("Не переданы обязательные поля", 13);
return TemplateDto.toDto(repository.findById(id).orElseThrow(() -> new ValidationException("Не найден шаблон с таким идентификатором или кодом", 13)));
}
@Override
public Page<TemplateDto> getAllTemplateByCode(String code, Pageable pageable) throws ValidationException {
if (code != null) {
Page<TemplateEntity> allByCode = repository.findAllByCode(pageable, code);
if (allByCode != null)
return TemplateDto.toDtoList(allByCode);
}
throw new ValidationException("Не переданы обязательные поля", 13);
}
private TemplateEntity createTemplateEntity(TemplateDto dto, List<MultipartFile> files) throws IOException, ValidationException {
createTempaleFiles(dto, files.get(0).getResource().getContentAsByteArray(), false);
TemplateEntity templateEntity = new TemplateEntity();
templateEntity.setCode(dto.getCode());
templateEntity.setTemplate(createTempaleFiles(dto, files.get(0).getResource().getContentAsByteArray(), false));
templateEntity.setCode(dto.getCode());
templateEntity.setStatus(dto.getStatus());
templateEntity.setType(dTemplateTypeRepository.findByCode(dto.getType()).orElseThrow(()->new ValidationException("Не найден справочное значение по коду: "+dto.getType(),13)));
templateEntity.setVersion(dto.getVersion() + 1);
if (files.size() == 2 && files.get(1) != null)
templateEntity.setTempleateHeader(createTempaleFiles(dto, files.get(1).getResource().getContentAsByteArray(), true));
templateEntity.setStatus(dto.getStatus());
templateEntity.setVersion(dto.getVersion() != null ? dto.getVersion() + 1 : 1);
return templateEntity;
}
private TemplateFileInfoEntity createTempaleFiles(TemplateDto dto, byte[] files, boolean isHeader) throws IOException {
if(files.length==0)
return null;
return fileInfoRepository.save(TemplateFileInfoEntity.builder()
.isHeader(isHeader)
.name(dto.getTemplateFile().getFileName())
.data(files)
.hash(files.hashCode())
.build());
}
private boolean validateData(TemplateDto dto) throws ValidationException {
if (dto == null
|| dto.getCode() == null
|| dto.getName() == null
|| dto.getStatus() == null
|| dto.getType() == null)
return false;
return true;
}
}
"<?xml version="1.0" encoding="UTF-8"?>"
"<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->"
"<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="JSONReport" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="d8b3a6dd-e841-46a3-84c5-8738634727d2">"
" <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSON Adapter 4.jrdax"/>"
" <queryString language="JSON">"
" <![CDATA[age]]>"
" </queryString>"
" <field name="node" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="."/>"
" <fieldDescription><![CDATA[.]]></fieldDescription>"
" </field>"
" <field name="type" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="type"/>"
" <fieldDescription><![CDATA[type]]></fieldDescription>"
" </field>"
" <field name="name" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="name"/>"
" <fieldDescription><![CDATA[name]]></fieldDescription>"
" </field>"
" <field name="age" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="age"/>"
" <fieldDescription><![CDATA[age]]></fieldDescription>"
" </field>"
" <field name="paws" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="paws"/>"
" <fieldDescription><![CDATA[paws]]></fieldDescription>"
" </field>"
" <field name="tail" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="tail"/>"
" <fieldDescription><![CDATA[tail]]></fieldDescription>"
" </field>"
" <field name="eyes" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="eyes"/>"
" <fieldDescription><![CDATA[eyes]]></fieldDescription>"
" </field>"
" <field name="breed" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="breed"/>"
" <fieldDescription><![CDATA[breed]]></fieldDescription>"
" </field>"
" <field name="photo" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="photo"/>"
" <fieldDescription><![CDATA[photo]]></fieldDescription>"
" </field>"
" <field name="thoroughbred" class="java.lang.String">"
" <property name="net.sf.jasperreports.json.field.expression" value="thoroughbred"/>"
" <fieldDescription><![CDATA[thoroughbred]]></fieldDescription>"
" </field>"
" <background>"
" <band splitType="Stretch"/>"
" </background>"
" <detail>"
" <band height="240" splitType="Stretch">"
" <textField>"
" <reportElement x="220" y="60" width="164" height="20" uuid="f5fa2510-f982-4dbf-85f7-f55928f1a569"/>"
" <textFieldExpression><![CDATA[$F{type}]]></textFieldExpression>"
" </textField>"
" <staticText>"
" <reportElement x="163" y="0" width="228" height="40" uuid="206c837b-aa7b-4433-9599-b78f00d628f3"/>"
" <textElement textAlignment="Center" verticalAlignment="Middle">"
" <font fontName="Arial" size="16" isBold="true" isItalic="true"/>"
" </textElement>"
" <text><![CDATA[Описание животного]]></text>"
" </staticText>"
" <staticText>"
" <reportElement x="104" y="60" width="116" height="20" uuid="8a3e1d8c-975d-4caf-a132-a6d3d88a822f"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Тип:]]></text>"
" </staticText>"
" <staticText>"
" <reportElement x="104" y="80" width="116" height="20" uuid="bd555d13-4f8e-4570-9dc7-bdeabe158467"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Кличка:]]></text>"
" </staticText>"
" <staticText>"
" <reportElement x="104" y="100" width="116" height="20" uuid="7d4d1764-eed1-4630-a2b1-10772296874a"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Возраст:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="220" y="80" width="164" height="20" uuid="97f17486-7d92-443b-b1ca-e3f64dcbdf32"/>"
" <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>"
" </textField>"
" <textField>"
" <reportElement x="220" y="100" width="164" height="20" uuid="cf3151fb-4926-449b-99f0-444ca0fc4c09"/>"
" <textFieldExpression><![CDATA[$F{age}]]></textFieldExpression>"
" </textField>"
" <staticText>"
" <reportElement x="104" y="120" width="116" height="20" uuid="d3e9f3f5-be7b-4d9b-bea0-df94e49dd339"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Свойства:]]></text>"
" </staticText>"
" <staticText>"
" <reportElement x="124" y="140" width="120" height="20" uuid="ef4121e6-a944-416b-bf0f-8c4af995f186"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Лапы:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="244" y="140" width="140" height="20" uuid="f36c8cee-dde9-49e2-9c86-fa44809a28fd"/>"
" <textFieldExpression><![CDATA[$F{paws}]]></textFieldExpression>"
" </textField>"
" <staticText>"
" <reportElement x="124" y="160" width="120" height="20" uuid="c5115378-8ff4-4813-9e58-52b9a561ad05"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Хвост:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="244" y="160" width="140" height="20" uuid="679c9859-9dbb-45ba-943a-68ce064f4338"/>"
" <textFieldExpression><![CDATA[$F{tail}]]></textFieldExpression>"
" </textField>"
" <image>"
" <reportElement x="386" y="60" width="124" height="120" uuid="8820e0be-749e-4bf7-b1f4-9252c84875c4"/>"
" <imageExpression><![CDATA[new java.io.ByteArrayInputStream(org.apache.commons.codec.binary.Base64.decodeBase64($F{photo}))]]></imageExpression>"
" </image>"
" <staticText>"
" <reportElement x="124" y="180" width="120" height="20" uuid="08be4f2f-5101-4c9c-a605-0f6bd63183ab"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Глаза:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="244" y="180" width="140" height="20" uuid="393ebbbb-3dff-462f-b689-8a1ee31030a5"/>"
" <textFieldExpression><![CDATA[$F{eyes}]]></textFieldExpression>"
" </textField>"
" <staticText>"
" <reportElement x="124" y="200" width="120" height="20" uuid="7a58acc4-d08f-4a1d-b1bb-5935dffb5fb8"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Порода:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="244" y="200" width="140" height="20" uuid="bc8afc8f-36ff-481f-bfe3-771e7162b019"/>"
" <textFieldExpression><![CDATA[$F{breed}]]></textFieldExpression>"
" </textField>"
" <staticText>"
" <reportElement x="124" y="220" width="120" height="20" uuid="d9d7d32c-6040-4fab-ad87-e016dcf882e0"/>"
" <textElement>"
" <font isBold="true"/>"
" </textElement>"
" <text><![CDATA[Породистый:]]></text>"
" </staticText>"
" <textField>"
" <reportElement x="244" y="220" width="140" height="20" uuid="c726f776-3357-4a2b-832d-046562b63884"/>"
" <textFieldExpression><![CDATA[$F{thoroughbred}]]></textFieldExpression>"
" </textField>"
" </band>"
" </detail>"
"</jasperReport>"
\ No newline at end of file
spring:
# security:
# oauth2:
# resourceserver:
# jwt:
# issuer-uri: http://localhost:8080/realms/external
# jwk-set-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs
# client:
# registration:
# keycloak:
# client-id: external-client
# client-secret: JaoJ4OvrzUqinB58gKiDGEjpTBSCCxJJ
# redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
# authorization-grant-type: authorization_code
# provider:
# keycloak:
# issuer-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}
# resource:
# token-info-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/token
jpa:
hibernate:
jdbc.time_zone: Asia/Almaty
ddl-auto: create
database-platform: org.hibernate.dialect.PostgreSQLDialect
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:template_db}?currentSchema=template_schema
username: ${DATASOURCE_USER:postgres}
password: ${DATASOURCE_PASSWORD:password}
hikari:
maximum-pool-size: ${MAXIMUM_POOL_SIZE:100}
minimum-idle: 2
leak-detection-threshold: 30000 # 30000 - 30 seconds
auto-commit: false
# flyway:
# enabled: ${FLYWAY_ENABLED:true}
# baseline-on-migrate: ${FLYWAY_BASELINE:true}
# out-of-order: ${FLYWAY_OUT_OF_ORDER:true}
server:
port: 8081
#jwt:
# auth:
# converter:
# resource-id: external-client
# principle-attribute: preferred_username
springdoc:
api-docs:
path: ${API_DOCS_PATH:/api-docs}
\ No newline at end of file
create database template_db;
CREATE SCHEMA template_schema;
\ No newline at end of file
{
"type": "cat",
"name": "Gorus",
"age": 11,
"paws": 4,
"tail": "long",
"eyes": "blue",
"thoroughbred": true,
"breed": "British",
"photo": "/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gOTAK/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgBGAFQAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A6ALyDV2BelU0G7tWharxyK+HZ+vFhU7dqdswKlVcilKEjmpHcqshzwKljjwBxzUmypETn6c1NhkiAZHT6VKtNTjPSpAM4xTFYcBmpowcZIpsa569asRoMDrRcAVOMmpUGRnFAj44qQJg1AWQKOpqRVJXinqowadjigBiqaev604DjHSgocVJSVx4Y4qdeQMVDGo6npViMdqES0OC5+vrTvL/ABqRUp4WmIr+UTThAB9asBPzo8vvSC5EsOMc04REe9SonJJNP20AV/LxnrSopqbZijy+eKAEReDzmnCL8T61Iqd85qQJxzxTViCqyMp6ZpjJ61dcZ6DNRMgx04osO5V28cUgX2qcp6frSbe+KRVyrsJPXmnqpPWpdmfSjZnP8qAI+Tx2FROmXqxs5qPbyTQA3Z261HLlTgYzVgAAEnPAzxUTDe2e9AIg2NnNOGcZqfbx14qOUDpmgCFkOc9TQFCc9DSscnAoWPdwc+lA2eTwA59q07deKz4cKfWtKFuBXQDLiKMVJs4xUcXNWVqWSRGM9qVY/epSuRxTlTbSHcakYIzyalVQAOKcV/ClApeY0yROe2KsxqSR2FQwrzzVyNcmkIeigCnFaesfenAYpAMVeeR+NSKoJpMdxUsanPTApXAXHTilKE09VGenNTKuTjFIREkIx05qZIgD05qVYsDIFSouTmnYLkax5P8ASpVhPGKlWL25qZI8dqdiWyt5JpDF7GrhjNBiPSiwJlQJgCnhM+9T+Vk9KTy8Gk0O5F5ee1Hkmp/LP4U5VzSFcjWPFLjFTbCKQg/SqAgYYqJgTVhhntSbM0ikV9vHrSbfarJjwOKjaLBpBcg2Zo8s4qXp060D60AQNH2xzTdoqfbk0CMGgCDYNpqHZjtVxoxj0qBk7YxQCZF9BULp854qztIz6VH3PFAyIxAfWlGAPapGyB05poXpQB5HGhJB9a0IFxioYIQep4q4kJHTmugbJ4jwKsJzUKLwPerMaEDpUkj1HA45p+3n9KFTvUwj3GkBEAc9KnjTBoVMDHep0Q5HrSAWOPJxVuGPpkUkKYqzGnNCE2KqHBpfLqdU4pdoOcVLBFcRgdqlRMin+X61NHHxxSQyNI8c96mReT2pyrjFSLGM5HWmAmCRUsSYFLGmTzwKmChRQS2Cgd6lVcikGKlXtVIgNhzzS+XT1BqTbVCuVymKbsqzsz15o8vmoaHchEeRT0i4qVY84FTLHVCbK/ldqb5R7iroi6UGOla4uYzzFxTRGBV9oQe1R+T6ilYrmuVDFxSGHIwauiLAppiosO5nPBioCMVpPFVd4TUtWLTuVQMZoOM8VKUx2ppXmkMjPPJqMpk1PspGHHPBoAqspAxTClWmTPamGMinYCq4ww65701vucZFSuuSajc5O09KQHmUMfOelXkTaoBOagiUHGKtA9MV0DZBqWq2ehx2cl9IYIrqYwRzEfIHC7sMf4cjOCeODWoqYrR1rwBH8RvhVqmkQxgaqp+12ciYy8iA4Q5GeQzAeua8K8CfFxtJvW0PV43AgbygxPzowOGUg9we35V1woe1g3H4l0PGljvZVnCp8Pc9qSPkZqQLzSW0sd1FHLE4kjdQyspyCD0NWAnOa42rHrRaauhix+lWIo8HpQqGp41wKQx8UftVlE6cUyNasoMUJEMUJTggx0p4X0qXMVvbzXNwzR2sC75XXqB0AGeMk8D/AABpStFXZLkoq7IGVYYnlkISJPvOxAUfUngVLEpaJCUaPcobDDBwRkfpXlGs3UnxGnviZJbxbcyJb2sVnI9vbR57tuCliQMtySQe1H7OXiK7nsNX8NXkzXEWmAXFk0q7XiiaTa8fU5XcysvplvWuanWjUny99hXmlzNaLfyPXFiwBUiJ2FS+VxTlTArosXcaE5qTZx0pVXmn96LCGAcipVHHNCruqVE4poTY5F4qRUoSOplXNWjNsiK80oQE1Lt56UYpAmMCVKsftSohzUoBx0ppCbGhc0hjHXpTxxzQSoHXn0oJIvL701k4qxgHoaTbmlYdysUpPLxVnZQY/Q0WKuU3iz7VA8WelaJjyOlMaLFQ0UpGVJFk9OahMRrVeEHrVeWHAzUNGsZXKJSmMnWrLQnNMZNopFFVgQaZJk1M/FRkUxlZxt6VFs96ssnOaYVNIDyyJ+f8Ksh8bfWs+KTNWgd446it2VY93+E63euaO/mQobe34V3iwoPP3SQcn19OPavkv9sz4Q3PhTVG+IWhxbrCaUJq8ES8QznOJQB0V8Yyejf7wr6c+DurS7JbM2a3kSkOZXCBYj0AO48+3TvWt4rtLCWG8stWsY7jSbuN4Lm3kQyJLG+Q2QM9fU9wCDkA10Kt7G1RfM+SxNJyrTh9x8K/Bv4/W9vqEdhqjxLBJGsSP521UcYwTng8HHY9PSvo/QfFWkeJiy6bfwTyA/6gOBJ9Np5P4V8V/tM/ATU/hZqs2qaH52qeFpJh5E5XM1mGLBYZ+Oowdr4AYehVhXnXgz4v6lpN0oeJZZgcK4YowOR0Pr6e9elKNHER5196MaWIrYZ8q27M/TTymUkMCCDjB7VMkRYjaM8V8cab+2dr4aytYLa11CR3VGuZ0LADuPl5JwO/P5V1ulftg6k1tE8um22BcNZjC4y/lq4B57bwPwrzvYPmtc9j6/Hlu0fUSROGHB5q1HbuSBtPPSvnh/2x2aCSQaZaiOJcrIq89+CPXiuZvf267qK/itrbToJpGcKDj5uehxnsSvHvWiwz7mbzFLVxPrX7PIpRfLYs5CqB/EScYH4mvNvGHiE+MNVl0CwEs+jWT4leK3ZxdXQYg8gFSigEDJHQn1xzsn7QWr6h8NU1fVpbLSTq+LTTdi4m+Z9ssoIOcBQUXA+/u6ba1vhvdpa6Pp80cEcwbLzvFbOySruYb0JBVDlmPmcgDH3ec+JiZc0lCOx0Ks5Q9o1tsek/Db4XHWPC8+m3uo6Ul1G4kktNKlEFxCpyU3lCzKRk4BLA7cZHbz7wBp9v4e+MN5psciyF7G5t327Sx2gSLuKkgEGP8iK9H8d/FnXfDui20uheF3eTYQl9eTWrKcHawaOOTceMchTg8kda4n4RX48WazquvalbPDrNrF9lGxH8rayYZgWJOcuE69F/LnnyQq0kt0y8G6sqVapJ+7LTfZ3R6XjH+FOPTpQKcOa9bZHUhoGe1PC9xSgAVIq0r6jEVKlQChVqZE9qLEtiouKkANCpgg5yD0pzERoWY4AGaoze4uzOePeqmoala6XGJLmVYl9WOP8APeuO+I3xb0jwBpN3cT3CPdRJ8lvvA3OQSoP4j9a+R/HPxP8AEvxJ1BGnngSCJvOjUXflQJ8pJMnG4hUKsNo/jXuwFYyqJaI0UbK8j7GuPihoNvMYVu1lZRucxndtFc1rf7QGjWEG6EtMxUNtXqBkAk5x6gDHWvjjXtauNLTVLy3nWRZcCUhX2jPAQAc/Nk4DHICgkg8Vc03VodM8PWMoa4fxVqDrLbT4jURytgbI9xboACXO4hiBhW3A83PUauthc0V0PorxV+0wdAgRzbhbh22Rq4AQH0HOdw75Ax9DXGWP7UNxLJK9xdqHxtymSoPYdgq85Jz6dTXlV14Xj1+WC9vdQstt02xLaB8iTewQZkZAV4C+rEI3/AczxD4N03RfFepTMim3so1nsjJeBYDvbiRwwDOw5J27eR0JyTpCz0k2ZyqSXwn0roX7RE1zqAt7iOcHGSltB5jdQMA5K9znPOcDrXonh/45+GtSAWTUEt3yoKSt8+SOh7D8yPevhS++Kth4eCwi6IeKPEdxYRMWuGZU+aQ78j+PAVjjAGBzV+DxB4i1GWxtbXRo9NSV02HVY5CzEjIKxoAAcZJb1bFddOm/tHNKvZW3P0asdcsdTjV7e5jkD9AGBJq6pU9xX58aH491rSrkRRXkNlch/LmlaXaq5JGdmSevGenTivXPCv7Ql3oqQHWb2O6jikMTuGJjjPOM46EgHG7HTitvZN/CxLER+0rH1cYwaaYsdq47wZ8YPDHjC0R7TVLbzSMmIyru/wDr/hXbhlcZUhgemKynBxdmjeM1LWLuVWj9RVd4s5rQePNRPHioaNlIzXjwKqypgc1qSR5GapzR5GKyaN4u5msvftUTe3NWZFOMdKgZME5qUzSxGFpeCMDrSlePagDt0qhHjsMeTVyKIbvpUEXbtV2IYrZltnZ/DfXDpmqLA2nf2jHKf9UAWJP+7nB/EV6h4vt7TVrH99Hc6YQBv2yYIH/AFPr0yK8MtGeKRShYHp8pIJHpxXXReKLo+Ta+U/kgYCrEPl/3R6/7RyfoOKHrBxPIxOHcqiqRPOPjXbf8IxqC6hH9nvLDb9iuYLlhIskLHB3ofxz6ZBP3ePjTx58GPD2ta5e6t4YYJYybpm0yKRibc/NnYWB3KMFsHBAAHWvvzx/a+DdU8Oj7be/ZW1JvJNxch1BlUnKsCc5JB6cHPB5FfLvi3wf4fncnQ9TtoLnbuFvEm4S/vVDBUzwMn7xxgNz154cHUqYduPf5o56sIV4pvdHgWmfDbWvDthNqP2RriwtnnLySBkWABlZOTwNwVwMdyR2q/wDD/wAKSD4f6t4u1qIjTtNu21COKQOrXzb3RY0wR8vmBQzdvkUdTX0FbaJp/iDw5baRrmoTmzs0lJtiSElCowLPInDEsgyScgSvwWRjWXpXwR8SeKJPFP8AaxtrrR5Fil/sy1Yxp5cS7liUkgIqyMQzZJHlNwc5Hr+2Wrl5Hn+zaSSPEpNBl1TwHJLBBLDNc6dJrARyGmeKNGIYhThASrEZHQg5IYVnfCXwhZX3ibR9Q8RSFdJuh9tuDG+JBbjO1VJ6M+AoPbOT0r2bVfC2seG9ajsNNhXVLrTD9jkaSIzR3QOVKk7RhQOByAAMDoa4zw18OdU1LQ1axmk0SNJlm+wTqJDDEAC6RTZAVWU7lQ84xjg5p06vPTk07XZUqfLKKeuhvfE8a9488XWl/wCHdPYabbMtvDHbSDy7WPgRoIskptUDkYPzgHk8++fDHXPEX9l6bfQm5Eqx+Vb2lrcBDIkaqgZxhty8jsR0APOT434S8O6bo+vSQ6drSfbrRIRJDeIhaTahVom42MolmGWb5R5BLFttfTHgr4m+Dp44I9Ut9Pt715/LS4iYzhsqSJWwgJLKCcYVVDggZrzqsVpFHV7RqL0ujrvHfxo1vQvCsl7e6G0VpbRiV7a4v4klA3Iq5RRycspwTkdhXmXwv8Z3PiP4hLe3GjtpsOp6O98jRySN5jfaIowzjgEbTxlQQWIFcp+2h8VZ/BD6OfDVx59pqMbYmDj5olI8wjkeWpJICxjsdxGNpyfgB48tdW0OTXrWwu7/AFTTbOKwu5mnRozAGlkARODzIfmOBkgHtXVRw/tJxcjGNeOGpSaW59aAZGeCPY04cHFeWP441ldDGo6fYtYQqBLK9yx2qoJ3AHbzyRyDjH60bP4/W6aitlfoPMCgmeJtySHP8IAzjg8kD6cV0Sws0rrVHZRx9Gpo3Z+Z7IvTpUiCuZ0jxrY6mgMU0bZGSFcHb7H3roIr2JmYFwCOoz0rjWjPRunqXEHPSplXjNNiKsoOaxPG3jTTvAugXGpahMqJGvyx5+Z26BQOtNtJXYlq7Is694qsPDcAa8uEiDsAm7qT0/qP8ivAvHn7SJuJ2tdCdPNkleK3Ln/WlQen4468dfpXgfxK+O978QfHs0dgJLm3heNIbUSbXG0rk4xxuBbJPAz3IrP8d6jH4X8HWivbLBreqK0ptgoVUCHy1ZcjDBWwuD3BJHccNSdSbUYrfY3jyQ1OT+J/xOu9c10287TXOLhIpGeTCtKGO5uCSFIXGR056EivSYfDljp91Fc3b2kMe8yQ2VuBOqhGUbmAJ3uWZOGyPl/3SfCvh74MuvFHiW4l1WB20HS5GlubiSNlWSdmwqEjHVypPoobkZr6N8N6da/ZftbTQWtxIXgCXkjKYZCxUEqynjaWYA7MsVAI2g08Qo4eKjHXuYU+as22cv4pvbGR5dQ1C3s4RBOy2enSRAoC+SXcLtTzcgZPyqgJADHlvOvDd/f+NPHq2EotLBIoJFjt0t0mMagHoBjdgFhjhf8AZzgVt/Fjxk+nWcrRXdwLiMuGk8ybePmCKYww2D5R67iDnbjObP7OnhGW20j+1L2zvoW1aR44JUmVH1BE8zzAgcfdBxkdCRjI5rpj7mGdSW72/r+mc7V63Ij1Fbax8K28N+YJtRuA4gMd8TNfXzEZLhyimJUDDOAMbCo5yRyHi7T9W8Y63HazCXT7a1WKWSW4nHnqO0YWIM8f3mAEnfJ45rbm1XQta8dJb6dpotJdhDT/AGSSKGCJgS0bRsF37QCd4C4ZurYyec+JviSPRvC62seppp1t5jeZa3YZ1lyhUOivGS21QqhSeBg/3hUUVJztb3hzSUb9DA02y8IaEqTzT3MeoS/PYRNm5SZsdCg2nLLgcKSCRkktgdUb/VE0ZIltVVIwWjguY5DFCWHzssU0ZOVBAwxOQnAGa888CSX/AI28aPNqeo3i2Fmq3UkL2iqFn2qoDIWPy5CruAHy4yFXOPSf7H1eWMXupapBoENoWjtWuZra6l2IvKFgHQIy5I/dMcq3zYAB7ZRcXaTOfR6pHPav4rns1nhMFrcQQo6Jc3pBRWRRgm385hEMgnHBOO4wK428+IFzpDIZPEzfZ3IkAs7KOLzn7kIgOAORzj6DNdff6e9lrLXN/FPf3Ukp+y6dFep5U7bsBsxK0e3hfvCMsQCCMmqPiX+wrq7jvbOz0zTbKR28+GSKaZiY1KncElZgwLDgjrtIbHI6oSjHock4Slpcd4U8fTXd3G0V1OJWcBJWtG3Kfwy3p2r6O8DftD694VmjtdYSTUIPubtuG4YqeGIYYIPBAPtXyh4c8ZWR1+eHT4rzVHkgRYp/tz232fCjIDsxKgfMuSx6DntXe3f9ra5DDqB0zUb4kCCS4sZYruQKCwXlyCM44HP1ByB0tptKS0OZc0buD1P0D8D+PrfxzYLcwWV3agj/AJeISoP0JGDXTkZHPFfm/wCF/jz4i8C3kU8V/fxwZGbK9tfJxzwCzEgnAHfvX2d8IPjnYfErToTMrWl+UBeN8YPYkbSR1+n0rlq4ZxXPDVHfQxcZy9nLSR6VIvpVWVM81fcZGRyKruvWvOkerFmZPFuqo0ZU+ua1XQVC8Q9KwaOhSsZhTH0oAB+pq5LADUBi2NnGRRqirpni8DEtz1q/EflzWfbjrWjAvTmuopluI4FPu/Ecvh/Tb9rRZGvZbeSOFYyBliDjOSP8eOhpsY/E1BqRi2qr26zlNzozf8s3C/K3XJ5PQdfXrWNRuEG0c1a3LZnm9xCdD+H+l2mtTjU7yWeW8jhjlbyZpWGSEbOVAyDhxg4PAySLNv4cjunutSXTLWbVL9Xmt2l/deShZCAuQV5VMbup5OAxGei+InhC6v8A4g6XokwCabbiJbeKNRiXYoxu3H5fmyBg4AAH11vEXgG9t9c0rVPsU10bCdZZIo1yrRMSu1cMOQCwxk544J5rzYRcWmzz3OMo9jy/xlrZ8OaxcyCOAag1uIFjRceeyxsJgyltyg54ycA7sn+Kui+BGtaF4f0vxdp99fvfarbOZvEWotkDylATyQHAAjCE9P749MnC8OaOvjX9uUQ3UQi07Rrdr+NCFVZI2VceYc4IGDk+oHQ1q3OmRtqfxrurfysa/cw2FqZYz5Z2WyeanqylliTHIwrDtgdqcbNN9E/x/pnLUi21FIw/D/jjSvhv4D1j/hJku9MuPFMhS0vJWMogjeCMK+GyAQZXYrjkH/ZFeJ/Diy8RfDjxLL4f8QyLI9xLFcW14ZVX7Rbu5VSO+10ViOepXgkDHffFjTbKfwf8J9M1zTjcalHqVkl3cIvmJdRRvskUncAzP5aA5KnH0Fc/+1tatoXjn4dahFMsxYw2+YwN8zIQvI7lSNoyOijjFejSaceVdb/gc7TU+Z3PTLzSrS60ezivUtJ4oojDF+/8ttQnEQW3McQJWMElwQMhSqjGQVbiJZ5Yob+K9js9Mgj8yKW1ePDzFDGzrJtXeeVcAOMHIxzxXpnijwlrHiHXNE0/S4rm20HTbNGY2EscIklYgsGkIO0AO4ZQBwBksRzX+Jvw5tlsn1W3uZFnlkRJ7PYrMyklA3lgAkYI+Zc5HIHU1FJJPUJybR5bq/gvT/HfhbRXsNTlisbEnT4lURxrHGNzMSDgtyc8rgknHc16x8IbpvBGpW2lTRJq+gXMb2Vw97b72VOTtLkcLyeCDwQQR0riPD3hO28U2l9FZx3yx20f/LQYXywqkOzyPn6IPuqi8cZNT4YTWMeuXiza1rcwiRYzb6hcRpDGxHQR7FKgEHGWHqeeK7YXg3c4qnvx0NW88Zx6FrOreH5bx7eOOZ4U80iaML2QFgCflOOcY5+o8E+LPiS40O6VrTUDcCUmRFDFeDg4IHGenGOO/NdJ8YvDmvaP4oudRmsxbw3kxRZ/PjlEuRnJCk8nk4PJ57ivGPHmtWWrzkyXLoythURBgnqQMEf1PPfNepTilU8mebP+Hdbnd/Db48a14dXEs+6Nn5LHLc/3ehzwBx09c19EaF+0DIUjdNejsCeX847tgPPXOCfrzx+FfEGnalG8Rth9oj8uPA8mJXJIDHJDMOOQfYAd6tWd3f6rpEqx3ASWGXy2QuQyj+8DycZAyO1c9XDxu5bHdQxM0lG59vp+100hmt7K/jdrZfmuSgUFSSB1OBjg8Y968wg+I+t/HHxDEW1ZZVlDKkbIoFvEqh2zkHGcMB3LMM8DjzbRPg94oe1gtrnSprSxkhJW4lgDJK4YMFboWDFFHXAyCQOo7X4afDjxF8MviZaaXqVmtrDfpjz5B8iAbS4LDC4KbcHj/XD0rwMUqapylGV2uh9NhZzcoxktyx4E0C20v4xXiKY9QSCBvJ8kMTOJMjcT3A6dRjGADXYfGbRbLTdCsru6jkmnnU2CR+Ypl84SNhUBJIOxgOnylRjua4tYNT0z4i31xpbRWsz6glpCVTDKiqgAYc7idxx6gkZ543fid4d1bxb4nhtW0m8+yae22WebKeawwdzdWO5B8wU8HPIHTyubmr05uVlZf1956fI405K2pwnxC1aHT/B9jpsVvaJqupwJItoIQePLGJNxQKrKFVcA8g5IbJr2f4WaVDoHw/sLSWM3V5cK068KxmlcAALMvUK3uWOeMZr5z1a0spvF+nNDJJcQ6e0VvJbMzKoULztJ3L8yhEODncTx3r6s0Ay+Mba4a0sEs7C2DRBleVjOQ7ZdJF+Qpsd0CFsEuc4CnPTjY2pQiuurbOajL3pPotLHjfjy8bxj4iTR9KU3d3bMyyMuYDaqyE7mDLjPJUIvYYJxXZ6p4ktvDXhu9ttPuNSupLKB1lla0WHZtUI6+ThfMwCwxuAIOTniuZ06XTtD+Nt1p80s9zaX0uDPaXSyTo47b43YhAzFcbiRyM8V23xS0q40z4aqml311pDXc88KRlo7ZIgGLbnKEvg4P3yAdw46EbtLnhSktDJu0XOL1ON8FXkknhzUr+1hvpbm4EskFmjSBpI0QyDBlkywy5JUHJ2hgTwD5TdrrfxG8RzWF3dTzeRhfOmkDqxyNu/BCjb8owcn5QDjjb658PY4B8LL+G6mtkeJZfMupdPMjtEVfyymCDuBBALZI5wSMBa/wv0i8gTVNWgmmk1GTdJLqwhadWVcEP8AMTIOq/NxjHQ9R0KoqKnK2tyJQ9pKKvpY2vCHgS98LaLbXd9gm7ic2cFvCSGmVWDriELu24fO5mbIHDYApuqaZeeIdRF3pVvJpFvHCsd/PcIjJFn5XwrsMo6kEsrKFZeSvzY6jxf4Tso7BJbm+S2WS7V5Zor/AH+aDE53o43Ag+ZkDLYwSoz8rcvLHps2k6bYrdWd3Cl9NdOJVS4mkETbWfLkBFYKGIy2QWO7O0Hlp1ZVJc/9I1lTSjyo898d2ljoOm3dvo7y6ZOg8yRTK8azRSBSDIjIA4PzKuxpBtzk4AryO41a41rUhIQJNqRookIYtwBwNxG7kk59/pXu7+EBrGhaXE9jb6nfRzMY7i4YyQ20cjgCJy0e32XqcIcEjFc3N4T07wNaXcV9bxadrkyusUM6zwEH5iGRy4UjKjGVY8kFeCR7FLEU3otzzKlGotWYMfhTXJ9F03V/D2kSRyyxbmk8tXDDLBnjDO3A4yyj5Sf4auTaB4ttportfER09UVIWvNIuLmElCRtDgryRk8Y7dcYrPj8SWeuyWEjW19DePMHvnuvKaZmySjhioLqVJz1+63BVgB1nh3W5NGhUw6dFcWsc2H8mSC3kjaThyCrCQKVIx0A2Dhe28qsranOqKuLoo1fRrM7vEtzq6Su8M7/AGJJ3ABBIkCyhmKjn5uByDnt13gz4vQ6FqNz9i/0K6ifJ8uAxebg5DbGX5f5896861DwnrFx4ovF0a21CC4ciaeLUPLgEr5yeQwVjk9OSMntk1evvD3i4aXHc3fhOSdkQ4uYg7SIijB4wUIIIxjJwa3pTipe807nFWhOz5Lpo/QD4JfGtfiRYR28sbSXsaAySDA3H6dR+VersOO4r8svhf8AFG78I+J7e8gCRuCQ0crGOQD1U9G/zkCv0f8Ahl43Xxz4cgvSGRmUZDja3T6D9K5cbhPZPnjsz0sBjPbLkn8SOnZO9RMnNXGTFQsOfavHZ7iZVdQKgkA5q265J9Kryrt6VDNEeHwoB9KvQjHNUoTlh71fgwMA5xXSassQnB5NZ3iaz8YapplxYeHdIF7b3cbLJeJK0b27gqVbI4IHXGMEitmG5SEfuoV3f35AHP68D8q0fDXjN/C3iO1uJYPtkNzmC4kZwzBTyDzzgED269OtY1rKm7nDiOZx91GHL8HhJq1jrGsfEXxLdXUaxvPYtLbuJJSobajeVmNQSD17dKqTtZeBPjXdR+NNY1OTwdrthB/wjeopq0ght51z51v5uQNzfKwByCOgwDi78Sl8M+IPDur6qsuqadBPOYri4tbZg6OgHLDGMkenB9Dk15J4X8SpceHr6ximl8SeF22iXR/FVsPLvhjlolk5DqdozGBg8jPWvKhPnvJvpuedKnKUFFP5Hr3hjwTqHh/xbrHinUZbWHVJWm0+zvxs8oWkko8nzmHG8kphwB1Ax1NZ/izwrfAx2eqW8dteW5kiVQA24/xYYkD5lZWIOMjucEV8/ftSz+EPAfhXwXc+E5das7i/uhNHpQ1ue5t1eEllH2dmZSA5XDD0GK+vfG7n4ieH4tSlgazu5bLzSiEq0JcRkAsBncFVScHqAK5qMJU2qrlfmb6W0XbUqTmrQl/wfK58++PviFbWljPZWlhZz6jKn2aCS1TannlwVZiVPTzDznjdx148R+LGvQXXiXwBo2qXNvdeLLCYTwjaXjgB6GXPDHcMgADOBz6+z+PNG/4RH7XqARJ57WQXkQWNR5zKuWBLD7xDOBjpgAV82fCfQfDv7UH7Quq3Ov3V/pUEyNPAbOVY3jWLaq5LZzwOffntXvRgkpVW7RSe3d6GcpWSpx1k31+9nqvijUfiFpl7K8vjDV4NKa2kcXVrc/Z8y74wiKseNp2F8KuenevXB8EPi5cfC/QbzUvEQl1eeL7TcQ+IAxFvGzBkSTay/Mq7SwbnIYex6/SvC3g/4Yqur6ZFNq7222a01vxFqH2wRDhvMihwER9u4BwobGCOpA4fVfFnxB8TXdte3+o6Lpum3IaWS8vr7dcSoclfLB5QcE7eCB0xXJSqtrlvf8BKEr3S0/E4Hx541+JHwp0q8SFfDWrwW8ebwDTZIznI+ZW8078ZzuYd68T8KeNF1OB7yST7O5JIUuFIPXauWyBzjntn3z9B+I7K3uXvRFN50eo2yxh7QlIokDcEEHJLN1x1968G8TfALR/DNjdane3ksU8mMW8jM8u44ycBgMD3J+lfQUZpxXtHqcFSDT9xaG98Q/E1vrfhFZWm8yaFQUa4kx8/PIO4difX2Pr8z+K5bdLuNXLvLtGDGwEa/gME8+nFem69pl5FocxVbqZVkVI7dWB2qR1KHBySB0H415qumahqWoOs2lT24ZiFeSBy+RwAoI47dfz617FJKMeZnjVfelyoo6JCZVmkhZDKZYztMTMQ3G0Aru4LYHTsPavpn9lz4Y2N/qc8mpyRza1eyC2jE/79LdslpAQf48lSQcnG/wDHitH0zSvCulsYbeC81i12PPcsyH7Oic4jJHAJyA23PcE/dHWfsi63e3njqJWjM27UDclmBKkFsseOBtJHIwBuHTNeBmOKnPDzlS2R9Nl+CjSqxVX4mnbyPr/9o7Urjw3p2lG1SFba3cO6hTgAYPK9NuCcfWuc8EiD4jaVCJr55HjRRDvTMscgU7AD83r+OF+ley+ONAi8b2mxyHjxt2+XnKj730yPp/SvHBYxfD6SVIiY/wB6bkiJgqL7YYNzt4Prxk9BX5osbZtPdn2VGjGpSSW6PGfiM83w58ZaND5X2qL7VIhaN9z/AL0gA/NgAh1xgdw2Oox6d8SPHUPh34VtfvDLAXi228FqwLeYY2EgIblcFmB+XOO4ANeOeN/F+neL/H9taatbww2scu9r2Fdyxpnj3yScZzxnipvjNbtPo0GiWZSaW8nhhtpInVX2b25IHP8AGctzjGeBxXpQiqjoRktX+Vy5x5eeV9vzPPvgV4En8Szazr94017cecWeynkHlzLnLLtb59+cZwP617n4lmuda0Wy0XSLO5ktHBhWa3keK3lAQgrmNk4A+RQpPOMkknHufwp/Zt0vwfplvaaqIFMce9LGJECqSA252KguQdy564bnvjo/Fdv4V0OecG1soPMjIMiqF8vcNpU4HKfcx6bK9TE4xSrOq+mx4lGK5FSgr9z5b+EP7OGt+H9Re6vbbS4nmkNpGk0B/cAsqvKMA7m2BvmIOTnBB5r1fWfhpCdGRvFd5pU66cW22rRrMXYsg3JKwchhyTt25weQOvV6t8XtLluzFo8FtcapFx9jVgQsjHGEAJJ6H5cA9xXgnivxt8Q7/WtNVtCnjuL+WRLYXrpF8qIWJKt90AEEk8fKOuRWP1ypiKvNbXvexssM4Qtsuxr+NPg/YRaP5kfjC80Rtxd7Wyj+ZThgBGqbQgCqMDnBLD5ABnhNNvb/AOC9uEivI9YsC0zWrmWQXbbnXd5vzsqgbSDgZIY55AI4zx34e8aa1eJcmVLq9uZfLWJLkKIxyrZdiFxyBkZHzY9q5+3+AHxBvVF/qL6XHpsyukc9veoOUVGfy+2dpJxwCc969Wgo1Kf7yorPoctXmpS0i2zptd+JWp6TbW23wzbXWlwTEW327TozaxzDaSH4ZMhWkyeu3JwMk1sfD63u9Ya3luJNPiurSXyobDTmeKO1dXYMGeIhow7rlRwuGHK81esPAkHg3Tbm01CMSbGRI7m71VViXKg+WY0V2VSykbQy5O0ZORjIs7rQvBurzTW0EVpZ6lYLLJp0Dk7N8YAxIcyKWYHAJyCyng4NdV6fI40l537mLlNS5pndeLINWsdAlZ7NtLmZEWOGa5aIKsaqu8rGA0RLn/Wjb8zDftyK8Gt/CmoTCZ9GvL/ULK3iM7LNMyTW4fdujKqdqnG9ju2nEch+cHFdf4u8Yah4o1TTJLSS/jvVfyQudhkgx8zGLd1KBgwBCthDtTnd0vw18M3+gWWuX1+1tpmrarKqBNQtioLZcyCEBsbmRSNpIDZxhlJI0i/q9NvqzP8AjSSfQ5zwxY2+iTJbaZoU+tXUEwEVwFdJIMo52swUHacqRyAx2jAJOPO9T8a22kXz3mm29tOGbBitoiIc8HDI7uzc78xuxAKkgFTz7Z4i8CJrhFlDqKX8lpbi4u3mSeSe2Chklw+DxEAuch9oBXcQoA8v0H4IPrN7HJeaxZMHt2mYGQMw/u/Oufb5iBjjg8Z3oVqPK3JmVWlUcrRRmweOvEur7Y4xftpcm57S3jWSNIgxwQuznavln5MkDbkdK3tP1TxRdRWn9oTTWw2b0Jk2LKFJKjblo3OC3BAPzdTuzXc+HdMstK1aKEat/YmqW3kRSWyRSTCaQAfcCRKN+S/IBydpBO7nhtf1Sz8NWnmxxLIEupJBEEkLpn7uW37QwJPyA8Bj16jojUjN8sInLKEoe9OQatB5WpSxXlulypkIDRiIOh4OWhDHbnPYkfqK9T+CPxwu/h/q1vaXN3K2lFutmzLgHqrRtwO/HvXlLa9pfimwuCY5tOt2kaT7T9n82CJycsHRcsh4OGxjjHHNcpqDT6Hq0LrKk8KkNFe224K4znlW7Hj/AOv1r1sO/bQdOqtTxsTehUVWi9D9d/CvirT/ABho8V/p85mhcd+GB7g+9arpivjz9l/43NePDYXl9bxRqqgo48vaOB8qZ5564HHB5Br7DSVZo1dSCGGQRXg4mj7KbXQ+pwtf21NSe5Ay5BqtMCBjvV1xzVeVa4Gj0EzwaI8jtV2Ns4rPifJGatxkH1rc3ZeR9p5AIrc0C6ghuYzO0oiLbXQKGDL6dc4rno9gILZ298GtjS4jId8MU7xqfmlDbFUf73OPzFDjzKzMKtnFpnuFzpkS6VImkmxgvryJWJnhBEnoSuQWxz34r5d8VfDbxZpOv6prOt28V7cyLiA2AS3gzn5SqFmJ6ZJZiT6YyK+hrPX9Nu/Dps7y/jsriJAwFtK5YIBkYYHBJ68HnpjrTrnULDxnocukjVNUivYFSfz7DTtz7Qw5AKEHPAIz3rwK1OUJuC+R4dOpKi7tHyn4k/Zp1rVLKfxZdQwzaxYxIujadFGg+zPnc0rg5BfsoxtBGTnt7romuwaP8PbNbohLi6hxLGeSNwY/NwDk8ccZya6z4XwWFhb3eh/aLmeNgxgS60mW1EcZzvQ7vvksXbP+3xxivBPjHo9n8F9bhj8QXcT6BeqX024nuJll84SoHhY7yGOHVxnb8qtw2CRxznUla3vW7Ho4bkr1PZTaV3deZ5x+0v4iln0uGK1iaa7mlCuiHkEqdpHYAHjp6+przj4UfDrUvC1zoXjiztYnu/KeDVLSC2/1i8FnGGBRiOCAR0JGa6X4a/BfXPjjrf8Awl2t26aH4RknLWA+0PJJqEKMRk7nAEZKg9OQO469L8XtU0WIppln4l0vTNLihmW/gFk1yxTIRT8nBCucHn24r6CnNcio316mNWnHnclqltY0/FvxQ1O40m3vPDl/HqcfmuJbG6dxDGDIT8zmXeGymMdD1xzg8KPiLZajqt7qEPg6z0XWJoQkl61z56SMBjcYmUqOgPXPeszwH4Bew1sT6V4v0fxLY28OJLdIZbeZEAUjB+bPXPJ4+XPNX/GM9voqLcTxWdkqnIeRvMB554OOfx+lclT/AGaShHW5vSgqseZ6WPPY/EXjnR7/AFa4Nh9uN1Jn7X9pxGo445yABxxgVzl/LqGtyNqGrahFPfc7Yliwm0n+HGGwD1OCPWug13xNe6+8kZieHSFYPvhRNzHs2AoYZ6c5zXBeN/iBaw6Ottoa/ZnVmUsqRruyBuCsVYjk/wAQGOgzXsYedWpJRUdTzq8acIuV9DgPGmqpqGoR6fHJ8kDl5gqHy0BIG7GMk+/v0qG0ljsbO2v2ETQRrhImbBL84LevBJxjn6VSi0u4u4IogryahfsXbcVO1QQRknGO2PX0rpNW8KNbeFIY2lkeVSojWePywuMNJ82eAuR1H8Wa9qpUj7tO/kedhqM1zVGtf6sdXJG8vhgS200UlzKACVAYiMKAQBkbTy4C98DsQa0PgDf/APCG+KLXVpNNleG3vxG0L/KkbOWjwSXJIBHTPY5Oa4r4aatCkCWFzGdkt2SJY8bWZFUrGQU+bPPcdCOhrf8ACt6NF8a2d68MkFubkSPFIgJbY43YUYJyAB8pxxnnt51ajalUpPqevRqKc6dTtp95+ofgPxdbeMLWeNIpJrWJTulw0S7sY2qGX68/4Vx/jHSYF1Bv9GMzsjRmOJwFZsZIY9DwCMYPOPTIyvh78S1vbS10vTHS5W4VGlgjQKVY/MyLtjy2P4jwBtxjmuk8cXKaVqw+138cUCo7XTiNskgDG3j5fmKqOf4vrj8frQlCpytH11H3KjaejPkv4sacs/ijT9HhkiskH+l3GzjO3JVRs+YDgc4GDk4xX0r8D/A0aJaeJtTg+2GQRraM0QCQZAAcKRncSeoXH9fG9E0S+174vwaer3GnLJGwlMUIkVecAn5gMZzyN/3T1r6NudctfC9g1tcFIZVBfzYZCPNIAQMPlUkj+7jjHp0+glU+rYenKW9vzMsRetVlTh1Mr4z/ABNTw48tsLgtN0+0KNrqyk4IPcEdhwc9q8R8Iwj4h3F9rutzx2mk2koEsUxdTKoBIK4Ybee+e3T1teMN3xI18adZRtdBm2Fkzn5mwWJxnHPQZzWpcfCGeLQm03Up003ToiWFtZ586dQDkNIw/dA8jGAxPdec+dCrdOc3Z/kjs9lGjFU47/izy/xT+0homm6//Y3grw7HqlxDvJ8pN5VRkKWdjkYJwSSOOvpXDeNviv4m8V+JoYLBJXvYVKtPK2IEcgfdBAPTnBznpWh420/SvDtt9g0vT7PQYLoEsYMl5uTgFjlpM5PUnGSByKd8NfDNv8Kr+G/vryDVLy7ilkWG5aSHJQ7MBhhvuiQ5Hy4YYJr6WlHDKl7aMW2tr7t/lY82aqqXs5NK/bol5vqbnw1+E9hqeoJdeIpdV1m+iDO93d3C2tssgw+EAYZXnkjPJz05re8Va1ofg3RI7u8s7GbSZw7taDUJDI5BxIRJ5qlXYA4OzcR2I5bhvF/xU1XV7U6jZand6eQ6Mji0wZoXWRwiq25TF8gAJ4ypzgcV5Dp/w2F5qUqOomwUklmvneEW5dT5auDwFk3RgOcAEfeAw1enQw0qj9piJ28kcVWbguWkrnceOvGXg7xWto1nrEljavcpbRRTebLHZwqrZYxFmMm0ySEYZScn5Tk5xtL+FdlNq5uLfxHDd6fbCGdrq3maPJkCZDlskfMzLjORg8HmuvufhhoOnWWkvZ6Hd6xrdzNMtvPbTiKOaKHepj8tN7LMzeW25sHHIJ6jN0/4jWun6fO97pGoadvkMt5LFfkXH+sWNrfbIu5sdgChwBlmGWr04VGocuHu/uPLlSTletb8Sxq3w2v7XVJtPtbm+uHt7BZordoWIkmIV3CycYLFFxkZwPl6Vd1LxZqStoJhsJr3W4bjfdC5LsiiQb22yqyqTukJ+c8bjye2Dd/FS1muXvLjT7yxdURY7i0QRLKE+aHJXIClQuM7jnHUrVm0s9U+IeuT3d94o024t5/JtYboJKzYjQRqWVCoQIMffUg+SCflGalJtKVdar+ugm7PlpPcZoPibWdb1bSLG7truyivI4mkuY7yYPeK+1PP2gFsFssD0yGGTnFez69a2OjaNoxZ5dOnsWmZtWgsFme2+TDpNC0m9klQbhj5cDoCpzwel6NB4Q8R3Wl/2w08ipc2YtxBtDQsxRUCPtaPa4UNyVBVs4wuczVfiZ4YktEnbWtXtNV0IvF5Nq5j8zeZt6op2nY0hTeCMjccIQMnCcFUqXgtF69TaM3CHvPfUpeOviFqNpkhLY6eoivrK6uZTu3JujIVEc5VmZwcgEh+VwDjzbVPGxml2z6ZbtC6bl+xTuELlw4GHPy7FLIvYKeNw68vrGs2d1qV55DTShpSLVn3BQjdFIJ428YHI6jpir0elXvhjUYbu+jSK2uozLamWU5hbOVf5SWwCCOfzB5r26VCFGNjx6leVWTsd14Oa38QK3/CIT3On6onJs3nDTo2MMEwFLowA+mByOM6XiV7W6topL1GsL6ZGE8csexRIDjCnHboVYAjueePKLm705HGuQQs8xmBk0+Uybd3B/dSg5GTv+mBgnNdzoXxD0bx5Y3UF9dnTbxQP3V2zOrYHyqSctkYxvOcj7xB5PTHmpzU1t1OObjUi4SfvdDY8AaimjeJhciaSBcbGWIhsdPmxjnj0IPHU9K/RX4FfEUeLfDsNvID51uuwOxBMijofavy9awe01KOWAzbsjYydRx0z379ODX2n+yrrqT2WmYlIYyGJEjh+Rhyc5HGTnuAfc4rTG0ozg2Tl1WcKij8j7DYgjNV5T8pqUHKDniq8x69q+UZ9mkfP8Rz04NaNvdLGgH2eGQ+sm4/1xWbFgd881q2lokUaz3RKRMMpGvDye49F/2j+Ge3QbyaW5oWtzcTgmP7PbRr96XykUJ/wLbnPXgZJ9K2YzDE0UlwzSEDKzXmWcj/AKZxZ446Fj7gisuS7e22IEQXC/chUfLb59Aer+pOSPr0uwWsWlzC41qN5J2+dbJyQ7k9GlPVV74+8fQA5OqVjz5+9r9yW7/r7jd0eBr2UXMdokcRYst1fZkJPdljGAfxyB/erWtprYXYaCWS9lWRWlleTyIS68gZj+9/u/MAMnJFcld61ca27mWUxWigb/LGBjsoHT2C+3oOC31Hz2SIrtiA2iPPyouefqe5J60p+zlGzRzfV6k37z+Xb5nsB8N304WXR7+SDz4yDuuZZVB/vKsmecjj2znNfJn7YR1yXRbrQL2K48SidlnW3lR0hh2n5SWwOcjjGTnuea+mPDGtXc+pQ7JSFhZlxnAXCqPwA5/KvQp5ND8RxldVtYHePGySZAckc/p1rwJYOnSqqcXZp330OaNWeHdpx5k/vPilfj7dWPhLTEUTWs8cccD6ZLal0gwVQYdCPlGxj1HYdq5jUYvEfiDxJJPpmpSwxSKGzY2kTMsrDcwxIN3zcr1646bq+rPFfg/w3DCLuyt4BA548iPIfJAIGeOTivAPiVeTW9vqFnppSyiit5QZLUlSwXlXB64DBc46AnsM15/PToz31fzPXoy9tH3F+h5J428dv8P1MN3dWev61klZntUt7q04B+9GMn5cN16NkcDnyPWPi5b+JG87XoJomPC6hBteSAEjrGdqyqQe5DAkfN1Fdd8SdOs/iVband6cVTxFZSxl5YztBkJG12PaN3lUMx6NcI24KCB5fYWFp8VtHn0J4o9H8W2ClJJFTy4pVB5Z1zxjHzd0IDfc3eV9nSwUZRU29DxKmJkm4W1uZfia81i6tTEt8L/QI9zRXung+XLjkxsuAUbjO1grDnqDmuDltbW71NIEunniVyiLHAm5SDz+8yO3OeetegXsC/CtZ7EXCwXe7bNb3URlWZQeVljPfI4yeD0IIBGpoXhXQ/EWqw6j4ahlV7dBcXGkIDvWQ8BoSNzSpkMCOJEAwd/3j1U5wjTc6S9DKdKftIwqM5bUXubHX7WKCEGaFSksUzhGHGDGVGG4DHqMnkA8cdv4j1CG2sBp17pqGa5jYIX3kbTuAwAcbSQ+QfVW4xmuc8N6BeXHiF7u52zptjnC+Z8rnIKjBAJOXODnjDDnBxb+I2mibxZoaW90kkyKuZIpT5ryFmIB4xn5kA7kDrwdvnScZVYQvqk2e1Ti405StuzQ0vQ/7P0G7vZLWGGa4RTbfvHwF2tlchs8MiYOG4UjOVFc14glnj1Rbt9QhkmWGQLIUdF+cZbaHA5I8xT06V6f4surXQtKLRq9/I5Zi5PlARMCwZyc4IYLkbXU7m56EeYvcW3jPQLvz4FFxbztdCMbVkl3RheWOdwAHUDPfnIAeEqyqR9rPZuwsRTjB+zho1qfV37NOqXF9Db6lZT/AG6e9kzJ9nt/LMcQLHJZsseBjgAfKccKCfVviws1nottqTWs0qujCWEjeGQEM2FJxnILA+4NeHfsjao1vo1vb28FpHc3DNDJIkReaUNhyR2WPaOSMdycbefaviFDd6roUdkwilSMyyB2Qs0sroTxyAfu4Y5wMHOMCvz/ADSm4Y+66M+gwc+anFu3mcP8ItGt47vWPG9+91CZ1W38obohI4yzfKASwyTgcDGMZPS14++Ik96trpWlRvLLcqXedQUwXJJyvbGQD0J+tdPaW1tJ4X03TrWK5srYyJGYEvdxmO3AVWZtoJ64AJ54HIrKsNBc+L5ZbbSlnurfYA944OyQ9AzAcYxkZHG055NZYiop1FzbI6aFo3n1L+h6XdeCdDnL3Vkl/JGZy0vDQ5Prn5e/ykjI/hGa8v8AFXx1aS9uNP0WS71e98p2N7s2wQy7gVwWOFUYX5uMH8q3v2gL+6sI7S1tpDK87m2lnQEsP4SvJOAA3A46g968ds9RvbS7t9M8OPI8UhaCWaKSXfIdmGfABGBgg9cZxmrwlCNZuo1ddO3zNJtwim92a+meD7e1abV9V1TfeXAEW+JFZ0csTvRySVYYAHXOTjGRXDa945l1HxBFpOk+HnRfJLy3s0WWaN12uHAPz4YyrvyOxPIr1/XNa8P+DtLhk1qGK41JPLKpDJlopWbCoN2dgxuYZ7p9a8B1vxtZ3GnfYrGzuZryV2+zT3DkNao0pd9wGcZHT1Dkn2+gy2NSrzVJxv26Jf52PPxbirQi/U6vRvh7/bTW8JSK8huGWCKaWR1eIAFoyYtwIyVY4BIHzcZArufELeFtPeKaZLqG4uUe5F0sfUbEEieWQHXD4AwSF2RkAlWxHpF7LqEP/CS3UMOlut3via+uyjSx5VmkYN1wGAUg9EYbWzWD4v8AF0ek3/2M6rLcQ26xm4kuY0vVi8yMRs7NGCCAPM2kHkn5hyCu0faV6nK3tfqZPkpw5jr/ABj4mvo9KjtbEJPqTRTLcSs8V9FGqo5cruUsgPmOPLPO7blsZrw7VZxrviaVZUtY7i4wC6I6W9xbsx8uMpHuCDeGwpYAALj1bG+InxFutRvpLLTIoFjWYiWfa0f2mZZQBJIrMQ+VjG4tjdu+ZTtBG74Mi1PxffJfXGm4t75fKkmaMo7SFSI2jcZ3LsGG6k4YnnBHt0qH1Wk5vQ8WVT6xU5UtEdhqOkeKNC8OTR2mkpc2umxiWaa7jT7PdqBG5cJ5bbSdu/7wLgN825QK5HUPFt/daNfSTQwNJdMWuNQs7BRCoBZRKGi+5lsE5HbB4+96j448T33w2hdZNIgGmLMtvdaXGQreWCxg2Op+fYQyMM5BQYKhiF4GfVPB/iDxHYafAL3Qlu1li1CCMm1E7LAyhCAOJG2yLwuGfKkAHdWVCo5q843W90XVpqL9129TM8NfDi3TVrrUPHeomBNJjE0ls8A810MhBbymdN6ljhtrZ5Y59TxN468MR3ur+GrHw+81vDdFba7mXbLFsbLgjHzEKnyK27O3kne4Ora+HvA76jf2Wpane3Nu0Z8j7QzmbaYnHmDHK7nMLYPBWR8njjEu/EPg3T7bULXRYZrxJS0NxeSoJpZHMXm20nUcibKlwFIGQchsV1Qn7SV2m/lZI5p03BcqaX4lV7vwB4w8LwTyaT/wjeu2Pl2tyLV223CMp2XWyT5SC4AIG3Ak74yCx+G0WlaXDqUd5b39vLKpkgktn8qNCjPgkr8u5RkHcPvL944rn4o9NgWGXX9N1HRZbhxG9/DGJbcqWXCmM4yAhkyCxJ2p05zeu759AhvNJlK20CFo7jMbBpINqMGw+DhhhgCSCSBgdB0NNq1N/qc3Nyv94jb1e30ePxHLoNtLbWWsQFoltmnLWWoWzDeFV2O2JxgjaVAyRznBrkvHnw4ttItYdRsLC7tZJP30Fxu+XaBteNhzypVjvVmBB5A61gax4Dm1WG7a3vYJru22MYmmUyuCOWjI4YBgcgcgbTzkVmaN401bQbZNPvozc6d5hdcrh4nIwSrflkcjivQpwkrShLVbo8itVveNSPozsPBesx6na/YrxWkwcAqcNGc5yB+v5+1fXn7OOvxeFdQWK7IEV7goVBCt/tYHcsuD06jPt8exaVEY/wC19K/10LATxFdpU9sjoMj+XB7V9TfATUbTxBbWVvcxGGUSgLcY/wBUwAOfTB5HTt9c9M4qUPI5acnCotdT72srlLy0jliOUdQRk54pJeprN8L6X/Y+mRQBw8YAK7en4Y4rRm68/pXyU7Xdj72F2lc8Mt3gtRnC3E/YMMxp+H8R+vH1q9buY830zmWdm/dbzks3Qufp29/oax7OL7RKke4KGOSx/hHUn8Bk/hW4kyWMwuZYwZ8bba1Y8RAdGf39B3OSffoXccuy1NW0m/sSMXDxqL1hmOLBJX/aYnk/TpntnOM7M1/dEuWlnlbOWPLMe5NUzcyTSmSRiztyWPetCJ/s9sXPEsoKL7J0Y/j936BvWhu/oSocmvVjp3ACwxNmJDncB99u7f4egA75ohfy3Bx+FQo3zc96mTBNZt3ZqopKxuW+pOt4Ru2p5pcr2c56t6/54ruLm/uPEGnxw2rSIMMXZRh1XnoMn5j29M+vFecWz7Jt5PPX8a6Pw/rBsLhZfMkRU+Yqp++R90H8ea5MVRVem11OerT1UluaniBPsFnYW0rokNkrNJEhyuY13fpsJB9ea+dvjDLLd3sGl6JJHNqV1IYoAGxvgl+cvle3lsoI/wBr6V9O6tpo8WeH7iaOFoncSRsw+8Ny7W/Hk/SvJF+GkmkSanqFw7tf2tkLa1kOAYVOV+T6HaR6Ad+lfn1Xnw1V861Wx14Rxa9527o+O9eFn4a8f23hO3iF+bthLqKAiMSR4VHjJHYwmRV752t2BrtNU+F9r8L49S8SpI32mALFNqE2BNcu2BHcKcfeZBuYjq6uT97FWPhV4Ls/FHxM8U6+AHi04jyUDGR2QEPIWbnHG1c92c+1dn8eddTVItL0CPfJG8r2molVO6JMJskDZwCjCNgO5OP4jj6WGNnU5MGm1om3+P4GtWhClVddJPp5f0z5k8babZ/E/RW8RpD9mu7eNjc2schIKpnA289FywJx8ivziEluf8MTP4R0O9vYoRPcWr5tpIt+UYyjBL7VORg4OOCMcdu88O6bL4R8bX2jXUsflyH7LcOw3iPZ9yUddwVmBIHBVWHQtWxq+i2OkwSNJYGKBYvLjtnUyuzorgIysNpRCjrkjkRnHTdX0dbEqpSjp1VzyKVBwqyTelnb+vI4ySbUvFS2tzOsFlrTSIFiH7oXXYbAOI3xkAZAbIAzkYi1nT0m06fW5EjhuoYm8yW7cqVb02ActnPXqc965/WPE1348iRLOI77IGPzo41CyRKh2gcls7VUegKg8c13XifTD4m8CrCJJ7aeKE+ZeNGckKmRHKAxYtwQSenHODmuavKUZU3PR3s/TzO+glafLqv62OdsteTWfA13eSxDMZMU17JCZ1Ocq7FSMqp3Kd3GGJOTlVG74c8Hx6RDDJbskKRlp7WUqI2D4QZw5HqDn+EgHq3NC78M2PgPwjapqhmvBNuleyKlZNpR2YA5PAXOFJ+bHU1zP/C4Z9QsFtI1C21uRLFGy/KGJ2GNVOfu5yOTx9KcIzrRbw69278ipzhCS9q/esj6L/ZOS5j1LVfJt4JdN/11w5HELED5RkAhSEJwSf4QxwTt9U+ICRaHomtG/CStdxotvExcrvLlnywGQB5gDY57EYOB4H+zb44ntvGmoxXMh2a4YkYQfuoucruODlSdqjaBkmTOcLz6p8VtXv7fUTLNZKdI05QIEK7IGkaTlgAMscqCADyI/Vhj53MYv66l5fedGFV4NrY6fWPETaZq2jzXA0yWO0gkeYW5KxQMo52htuCMgZwMgHHYDmvCHivUk0vUNVkjv47V42kt4vLaIcY/elG3ZbBG0gKBlRzkGn+IPC8dx4f09LCS3N1KrJdTSxxtgFvnJ4J9toPbB754n4g6paaRqMdhL5PkCFY7O3t7dgCz4CBmITJGSSzADgYA+bHn+zjVv1k2ehT91JdDkPib4+m8Z3rW1i9zDMoDskKYkIUKPvDnBAznHUDt00rTwTH8J/BFtrtzLa3epSW7G3hlcb3bzFGFHXdvLD/gDH3qT4PeCzfa7q91CN4sswm7Yl43dsKVLD5eQ7DA4HBJOQCfG3xXY3fibTtBuha6vBIsUSN53yo4VWBznIDGRWJ4+X3Jr0aVL3o4amtN35/0ialTVzb8jzWzS4+KXxJsb7WMJYzM0zxTvhuc7cAkk/NnBb1PQVueO307wtAEs7QWVteRXBg1Jx/ozSIVKKQeVXaJQPvZLjH8Vbnh3wzpmieRfW4NnvjJuBcHbvQAuxBH+yJeB08tcHPNZl9puh6p4fEl1NZi1eNUt1Ep/eS7mcGTOcrmIKVHIJTOAQD6SqxqV1peC0sjmdNxpvX3meYr4+1vWJ9R1HVrO4uZLmH7NDAoVFHmBiCQRzs2x4x0AAPHBTXU8Qa9cR6faW6W9hLF5iJcSOVkiaT5QUb+FASN2MjaSDxmt2PxTpyeJ7G1067eewDskbyyElyowWfcVCDftY7T0Y9xXbad4q8MaT4tl1r7QIrCfytOuVltjGhPmM0rIcMV+4pzjGxmGAea9n2k6TvCmlpoeU4wqK0ps4rwb8Bzq+nzX+tT+YkGbaYiRUe2lSM/eHORhBx945yAcEV6Hptvplh4RutOt9NEttbl71pUu1PlRhlEalB1JEsmcEhnlKgDcCdJhpVnfR6dp7w3tve2Ulxa3OjyvK81wY5AFYuDypMuSQeHx8wUY4DWYvE1lcyWEpf7NZ2Hlh7e42SKLlxOgJUj92W2/IMqrE9Bg15yqzxM37SXnbb8DocI0YrkRuXfxd8Lanq9hDZaC6S7o4VW8be6rFhiITnk8PGVfg4XGMkDjPEVu+paZdaZpge+ub+JtTa5vESRkki3mNo5VwykiSQnGPnCk5GSangv4MJcTalPePdJazo375eJAxYMuCcjIZQDnB5NekH4U2Hh7Qjrljq8sctrLbsmmQbpBJC4QzoobgMCjPg9QortdTD4adqT1/U4lCtWj+8Wh5Kvwv8AEerR6TqKRzzTTQtK5dVwCEVuSTgrtLknHGTmtrUvCNv4OeVZPIuJ1hMMkN4hDRzpuCxRvnBBKNgg44XqFrovEPjW28N6pfXq3jxxQ+dbRWsMuUc7JVSYAjlCA8WcDpzjoPPh4sm8XastuJbm6tNxA8qJgCpJzsBYncN5xjpv9Rmtaf1iprPSJFSVCDtD4izrnxtutWur23eS3+wagZRd2N1ArqhYSMyoVGVwWIXGSCWIPzGuXu/HV5qTmO5Z9SlC+XHNMp/eQBCoiY5BZVGwAeij2x2ugfBGyk1CP7X5lzp806I8tsN7QZ/etx1LLGkhwOSCRgkEV1cOi+Eda8Mxww6cmlaxFqTRQ3MIY2l6VREGVbIQsroeepkX+8QOmFbDw0hFs4qlGvP45HmMHl2moRi60ldGmgZSq28xHy5OPXAwdob1A6kHOpq1vpOsyX63sE9yHZjBfTRlWdgueRk4zghhluWz257PRD4f1KwTQdQ1WbR76ONQk+or5sLt5mAS5xwT16rwTjNUvHXhqz/sprvQtSjuYg6pJDDKcKB0UIRk7WBOcnII+tbQqe0qKDTT+f5nJUp+yhzKzRwOgaPJp89vLp0pm42TIefMQ5+UjuMDP/1+v0t8FtKhtnW7tpgyI4V0UkSpkEK2O+Dwf69K+W4tUv8AwfqK38SNLZH55kRdzQHs4HdDX1N8PPE9oun6VqVhETBd5VnRd6wTYyvI6owGOe4U9c495QcI73PnpVFJ6Kx9weFbg3Ph+zkLlz5YBJGMkDnjtz2rQmfFct8OtbXW/DFrcBl80qN6qcgNjn9c10Mz5HrXyGIXLUlE/QcO+enF+R4lZ3Rs0do12ysMb/7o9vfjr+VCSbj1zn1qujAipUPOMVqzosty/aRmeZIwQuerHoB1J/AZP4VcnmE0pKgrGAFRT2UcAf571ThJgtGcf6yU7B7KOT+ZwPwNPjc44P0oeiFu7lsYBB71MtUxIcehqdH3YNRuMtxk8VcgnZCMHkdKoI4zirEbdOaAPTPA3iLyLm102TmNwxJ9WOMfrzWH8cdbg0LwRrt88iwp5BLNJnCnaxzjv06dD0PWqfhCZbfWY7l8sIhu6Z5/zx+IrZ+Lvw7ufid4ROjShbKxvFWS5kJ3EKCMKPY5H4V8vm9NOUZW9TihyU8QnLRM+cPgzpumeAfgla6wIkSXVER5JuQ915nzKd3UbizHB7EdMCsnxIVvJPEN1dwpJeXImntlA4fG2QDtgBd5JHPBNe+a58OLXSPDOieHkjRNO0y3WOaVhl2SPpgc/wAWSfpgYHTyHxPfrf8AirSraG2SaN70W6sJNpVQn7wn6o7Kf6bc181Cq6mLb7v8D6CnOE6Lkv6seB+I9PuRP4dieOa7uL5prVJXk+VJQW2SHnjcqJkcklG4J61PiDZahrXw4s0tbcNfade/2RqGmCSN8o6Ax7HfjP7kbQRkEnjJr0L4habqmkalqNy9pCiSxma3TjbHeRgsCAcfwCZB2J69QK53wLpNz8Q/C99YXMy2lxdxPKb8SmQQBJopBImejKoA425Dt1Ybm+0wmI91VJWt19dTycTS3Uf6RzHhnwRa6no+kyabbxwC7h2m6cFS0hLbXUjgEkHDDHVge2OzupNP8FeH7g26wQPtORcRiSdJA207nKbGVixI39cYBBxXX+LNBPwi8P6Q6tOLOzuovtklviNlEkfyYUehzkDjBI78/KmurrfjvXb6OeacRwXbtFdBiylSvMauuOgCgEj1+6cijCU3jW69V2pp9Sa9X2SVKiryt0/rYp+PvijL42t59Oi0yeO8sbnzbS8t1GYz5hLRsAxURkvkYz8y4zjgM0zwq+g6vpUsNq14mGIV1BeQ+ZjODwDhu2RkD6V2eseFtL+Gen6loLXEb6lBA9zbTsMh2Vd24N1KtsZSp9G4yK4H/hOH1rVPsFrdHT2jtgLWUsyeWc7jGOQCNwB54yG7GvosOnVh+5jamu/U8urWjSnarK83+B7b+yuq23jnU77U8omjQuEudm9XDkKrB8cD5CRjJO4j6+9ePPFB8RaygiYIjSmJGljcBQMN8u0/MwzGu4fNllAyxGflXQ9bm0DwvHZQ30lmLgo93co21UBXamXALdAcY+YjHoM+qeGZ/wDiUabE80YiaRNz3Ee51i35wVye+eCcnjPXA+RzSjJ4hV3fl0R9FgeT2bjf3j2nQ8a34Qa8e2dvskLo3lGMQqMHOHRtu/j5iC2N2CetfMtzYvqXjK4S9Z0t5EmKvJJklwQWK5yDyVGc8lgO5r6q+Gfh++03RfEGkzlZFgt2luJliXbsbftUMRggLxkZ9sZ+b520iy+2/FUwuBLpEDm4uJzFiNFjOFdM9cE4XI2kjPPAHnYZpVpPZWf4ndCV6cl1TR28+myfCz4TajJZJHNf3c8dtbxu+8SzbWJAzjdyecZXBJHXNeP2Pw71rTdO1rxF4laNDZ2UjrGygSmSabyvlVR1xux6Db2r6Q0jRLPViniDXEEDx20V5aGdyUhYxCUsE6BFJRNxz0J5PFeca0ZfiL42itbSzxo9hD5xheUZMyGJRkNw20nHOQMHHJrbD16kJTi/+3n+hMowmk+vQwtH0X/hMY77xRe3FvomlRWK28UHO/AkGcJz6umcHOzOPmo8WfAnUIraCylVLq3YiV1wImt4lMeChBBZiNwwcfcj9DXofjLxJB4ZtLhYBE1za2jSJbW5UJgKhjYAAbFEjwLyR/GMnBz423x31LWrD99pyrb3EpLyqQQSJYGKlSDlVWRwc5zuAHC11YX6zVftKekf06GNeVOK5XqS+D/hNY6JqNtqV7dQX1lN9peGUxiVhcRkJKWhYHKEBQeD1yOlch8RvBd1oGiWQhsRbLMiXMqQ4wu/AhYYHzBsHHcFcHk/Nb8E6h4ga/WyRZ5jMX+ymZHRUJdmPU4VQw6HoGz/AAg1rfEv/hJtWgW+vbm1SzigktLVbQIdw2G4CsF5AznnHVc4zXuwdSFZc0ro8mraVO9rFWHwBr+jarFay3o068juEureZpNpYTSIQUUYwqukmUJyDuwMkCu70ZB4YN7pDKmp313NDcOlwfmngmgeNVVjwFXcD2yYwe4xz0/ibxFeTWeqiO4vHhtdyPcsd0YF1HIpVgOoKgsWJ4ZvauVOj+Kob6fS9VSfSriKc232fzAEbYBHlW9QsZwPVQRncK5pxdaNpSRopcj2NfxBf6u2tXEcenBLe4vzIsZOY443l8xOgwAskjru44PpxWVc2fiLVNDu5ba/W1MzuxtJWCSK7LIrn5jyEaIYI6CZfUY0vDmsqJbqxurjzns5nuxcQNkIQdu3B6r5iglTzjPcCtPVfDvibVL2/u7y5ttSkhaWeQwgKZIGk2/IOm7n2PA7qKFVUHaVl9+v3icedabHK6d8FNPGm3esateSXc8crtcRiQq8iPs/egEdAXYFepbPYYrR1jTdP8LaPaSWtjcHTLpypjQ7JI54WGWDA5Bww468P6DFO51qe+tX+0tHc5ufOMcJKBjJvw68DC7kQ7RwDGAeGNdRonh2W5uI9WEMcE8UrFobuPywpb5ndWYEFk83/vlOc4NaVak1aVSV/IzhGNnGmreZ53Y32vtrE2oWNuwjnfAjAfYrRRM8a44/eKrAbh1znBzXRS+GvENrZ2bXMMVjpN5aeTFLIPl3mMBtwJwoZSEBPG5VxjJx0tr49046rBb211a6Zaxt/aFlAm1RvURyosoY/wBwSocYJKjABGK5yf43XOoQxaVLcwW0Vk0DvL5e8BkBGw5G4lHOMd1x0CgDoTrTfuwWhi1TitZFG60oeEtCsV1iFdTuLSRoyLiUMhgcEogXllO8ycg4O7rwMYeoajp9rqK2sknl3cKEFojuVpAoJU9OMMADjk56gjEPibxND4huI9d1OJI4JIiIoYRuRcyMfu9ssshGeMHFcjdsdSubYG2S3uLcGCXy87n+Z2BIxnI5H0C17WDpyqSTnuv6seFjKqpRahsdzqOnJdwi5tvLeW3+cqW+SSIj5lIx7HB/DHFd78E7keGTc6dAxGhXoN1ZYJIi5G+PPP3W/Qjg14/c381gLU7jI8ZIdhj94hwOfQqc9exFez/B3T31VHtHDJvP2i27q0iffAP+0pP+RX0Oy1PmXdyPuD4W7JfDEF0gCPJlmAwQc/TjB6+3Sutml4NcD8KdMu9C0g2s8vnJtRozj+Ejv/L8BXZTyt/9eviMX/Gk0fpeBTdCF+x4vFKvIIqVZQTgZyegrME44ycfSpfO3cg/lWh0pG3NPmXYjZRFCLj0Hf8AE5P40+F+lZcMx2+v1q1FNRcFGxopJnIxU8b888VnpLz6D1q3E+DUsTL0ZyMk1YjbHWqSNz1qZW5xS2JNvRrjybyI/wC0M56Yz/n8cV7Je3Vx4n0lo7KZItuGUDkllOR+GcV4TDMYyCCQa6rQfGMukuuzLDAG0etcWLwyxEOU5K1JzalFao3fFMs9vp6xbCrCJ43eQZLBcA5PvkH614rpPhV1u7ee5sS7W7mUkcNlhtbjuclmH0r6hSG08Q6MLtSrMI/3ig52sQCa+Uvjt8U7bwlqJ0aIhNWNnPeOkQI4Utsj69gSfoCe9fn1TB1qVflW514HEKUHSt6nh3xi8ZanqHj+50jRgbm3sY5Z0RQHEknlo7MSR8o3Rr0x1bkd+20XSLHwHpvhjSHtxNewWM8k0WwhTb580buMfMcJyScKuMVrfCX4btp/hIa3qdls13WrpQ8+D5kVu4MuCDyB87r+AFbnxU1PRfDt/JcySKphwXj4y6IknyDvgO547lk9q9OeK55LC01pHt1f+V7ndGEI+8zkv2iLWXVPH3hC2jnEWkXgOlalnGyPex5x0LqwEgJx8yivBtZ1+30DQIbPw5ZrC88c8M9wxzlZJTEMDpjywpye+DXqB8faZ4j0zUrvWUBmu71r2R1JJhbcsYA75IkB9l3Dqa858e6ZZQ+KI4bGJltZHktmhcHCEoX9f7yqPrX0WDi6cY0an2fu8zyKs7pyh/wTybxvcX81ppd3dXIkvIj5V3LJynmxvhznqCybWOOD0PJrkdI0yK3ZC5fUoYYwrGFv9agUZQEchvlwpI53Dj17DWfDtxeW2taPcXDCUO7RxyAruYMRwem7ey8f3SeoHHnQ8Lat4cZhMVhtpVwskQypdV+XcPcH6fMPevtqNWEoqKkl5Hy1WlNS53Fu/U6i88RR3XhPT4bWCIznJCsPlgDOcAj+JsIT/wBtO/Ar334MXt7eyWCTynUL+WSO5kZ8FRHkA7F6KoIJLEdScZ28fO2k3NnqWntaXZNvC3CxqqLhsYJUE4JBHQn0wV6H1fwF4sHgS0aC7W3u9TnWSCWUniW3YqFAz0TDYbI6MwPSvKzGnz0HTitWelgZuFZTb6H194T8WXmvC+srWLbDNu+0Tq7YncMyqi4yT83fIwOg7HiLrwfPpuo36DDfKHliX5ftUrEJs5JIH3VBPJBJ4Ar0j4aXYtbazJeed5IY02qAN07biTnu4Y4wOhYHkg1veLvDiXd+uo20S3VvbIGlZQfLLICgwQORudvXgDHbH5XOXsnc+6pVVGo4WsmeTfFx77w34AtIdLO77T9i0oTOP9Yix+STng8nDY/2unFZ06H4eeG9UnV4rzV/s8szzRoGI3TYRVXPQDJ6ck9OBXpfjjwPN4k8Jtp6sTcRJ58Uak4EpUpDkeqnyz7ZrhbPSGvPEVml9dOmlWOjfY1dSEMkocEMRjHzeQ2AQcBx1Nehg6scRCSe6bb8zGsvZpNao5X4IfDTUda0u81DxCVWe4drcI8fyxogZyQi4MhJZj7lMc8CvQV+G/g74fXFnqF7bR200ULeZcl9r2+HkgwTjJGHQjrxGe2awvH/AMXbbwzr8UNrpb3Ot6fbC0JVTJCXxtO1ehZVbqerDPYV5SZPEEMt5BrUl22oyQwRCC6y5kZM/M+7B2rHcTfe6sE6mvYhTlWbq1JWT6eR5znJpKKN25ubd5jHbSWpubaX+z9knT7QZQULHGNv7ifnI2iMYPavJ73x7CuiyRjT7m1Z5nhZZsSM7LO8hdpGX5TiXGcnO3n27vxV8PPEl1aQ3hWNZprjyksYWCmSYu2HK5wEQS7ctgAuR82TjZfwKNY8BLZz23mX95MtzJcwxq23dKscicDOEaWUbT1IXtXqQrUqEU90zmnTnWbV7HFfCb4jxyfYYLq9ktI1Z7ezhLDIkEglyScALtXZ27HtXReKdUXxx4Mubq5mayvJLrzI5LdQyq9swzvwckLuYgcna2TnjHPeOvhzFomz+zmht9OvdyxGVg6Ah8IAoOQXUNkHrlsHmuW0V2tPs7XeovpkLTiNYSuwwo4dFOcHOQrZYZzhh1zVunTq/vqWj/4IJzp+5U1Or0n4b6rp08Gsz29zfXuWmk8tQI5FcsRKGGQ25jJkfX3rol8UXdpevFcxTterYy2/zRbVbzIjKSwBwCJEG7PDLk4GDXpuhajJq2hNHHfR24uLCCCby3UiFg2+FgABtcs0rAggE4OQGxXnXjhrOKCHWLd2nihUCVDGHAZV8og7DjYTgYH8JH4ecq7qz5aq1Oj2ShH3NjnoPDem+KtIsrmdEsJQ7wPZNKwaSNUJVyTwoQ+Z6YI74OO58RR3Wk2troen6jBfwy2m+FhCJFg8xysizOPmz5RTDf7BI5FcdoM9xqz6tcWemQSWQu5YJRKocIygsCn8IBXevGMh/U1yCavd634qli0yMC1uLffOBOWTycAs0hPQZDDHUDjOa61RnUk1fSOpzOpGCT7lY+C9Lg1aJ7i4mjmuCimHbhZ2GNhwT90uSMg4JK9N2A3xb4o0y80/UdJhsitjZ6f5VksRCyNdCRY1d2AO8BFZtvXp6k1fuILW210Tov8AbE1zKsX2Qlo0QrujQMAcoQWBABAP4Vm3EzXE7W11aJbWSK8qHTR8okSNtjM/JPEp5GM8kdK9ei/aSUnrZHBXSpxaWlzkZ9Rl1XT41jg22tvbxWwlOEdShjJ2qR82Du477s1y91riW+ty6naputp2V/LIKiOTOdvuASQD3GD7Vv8AiDTrvRRcmd/OnN2Lu4gjRgm1wQjrIO/JP5DkVk6fpsN5Z3ieWIlfJVmPAfnkf+O/lX0WEjGMXJbHy2MnKUlFndrY2OoSQKsqyR3kcyx/7Mifczx/HscfXB4r1X4T3MlisKwSbm2edbK4+7L/AHSffP6e9eH6IGluLS2TYZY59qYGPmIUgn25I59DX0P+z5YRa/cXGlzBreTzFeNz1XBBBz2I4+vNdfMrXfQ4nFuSS6n158Nr2K/8JWk8YwGzxnO3POP1roZzhap6LpyaLp8drGoVV67RgH3qWaUliP0r4evJSqSa2P07CQlClGMt7Hga3APU1PFcg8VkJMCetTpLg9a6zWxtwz4PX9atwzkEZP4Vixy8DmrUcxAyDU2EbiTAYqzHNk9axoZyRyatJPnvSE0bSTArzUwl71kw3APerCT5OM1IrWNNZPc1PFMc5zg1lpNz1qZJ+QO9FwSZ3nh/xdPolqRE+WcjIbkbcHj+VZ/jT4F6P8ZPsWvq4tdbiEiOwAAkVwFYHv0+X8a5+CdiRzmup0vxNcaHatKUlEa7cBF698fpXDicPTrRvLTzOacZUnz0tJHIfGBdf8E+N4Lm1ti+h29pHEVVCVLncAWx3GQR6ba+R/iBe6x8Q/Hd2kcz2KyqFy+SsK4y78dNoCn649q+rviF+0lfaSzrNYWk0AQ7oNQXeM7iOdhwvrjJNfP8PxL0rxBruore6bHorTRyBp4twiKhtxAVwD1OM8gk5O3jPzdCn7Cq6lFXtc6budJUqqs9Pmcdq/w+zpw08O0chnLtLCDtbaAWbqcoBKn4gegFc14j0rxLpOs3LyWstzJ9vDqzMQCm4AED3GOP9qvVtE0WDT9JtSNUtr+2Deassf3jGVIJxzj+BR7BciuJ8ZeNZG11LC4nhuHkjW3lnMZwCAhidenBKKDjqQp6EivYpVqsnyrX+rs4p06cfe2POL2G9kkv5DqiyxXGJXtbhg+0n+PHrwvzD5gR6ACq+q37QW7qYIr21lTa4uTuKk5B569QGz6gd1IqHxbrlvKqm5JgvpWKyyKmV+8ck9z0z6EehNeZPqt21/PFubiQlSWztJJzg+mSa9+hRnVjzS6HmV6ypy5EdHrOjW11bxyQh4pFPzITkZx1/lz34qfw54b8R6/eQ2lvZz37FGFv5JySOCyj68cDnJ9zXqfw88BaGvhHTNV129lS5vpQlvHDKEj2htuWbBAPB4LL27c19efBz4E2mji3vktIrnT52E3k3MQgmgcch1bO08kcgqSDz0BrkqY6VJuO9jT2MFFSbseN/Bz4q3XhrWNPtNeJRIrc+Vj5fswYFZGweC4CqB3GPU8faXgw6bqHh20sY1j+zSxBvkbcNobsfdiMdzz/AHcV4d8erLRZJ4Jb7TrWO/BIS6MJiaZWBDDcAATtYHPXrg9Vrjf2e/i1f6P400fRtVLf2WIHjtZH586QyTMm31+T04BU96+br4WOKTqRVn1X+R3SqSVNK/ofUF7YpZ63do8QULbs544X5wR+PPPsBXzofF9he3T2scP+iuYiuOA+Wzn8Vix9DnvXtPxf+IOlaZ4Tt7j7V5cmuTeRFtbLtGxyQCD/AHEUk/1Iz+fXjr4zS6bqJh023MdwbgsS3Plu47D1VJMAdiK8vBZdUrzcYL/I9OjiY06LnVe9kfTmraIuna1r+rw3MbzRS3V19nuYw8biIsx49AF/Va1/F+q6RbKur2It0t4z9quJLqQCRB5EiDaM46yvJ82M7OnANfN2o/tCp5css8qy3RkkHlRHA2PGqsCehz8w/D6V03hG2034kq1hfSrCPsz3NuZJAYd5R/LDjPIygJz0217CoVaa5qydkzFzpzfuSKXxXuNV0a3meN2fUbdUSOe0yRlMEtKzEZGXk28bsp04xWLo3xZuZNGmnunuYJpb+aX7PH0Me2TaHU9Fy+CQOqrjGcjctLjV7a0uZtJuX1GHzLeNxcxM0js0chAIHP3C2ec5bvWndafpWsxWph06K1nMP9qA2xSJkCpGix7nJARWZ3IA6RtjO7J7oVI8nJKN7feOVNp817GDr+vaN4mtNLlUiRbKG2j1IySL+5JfZKAP7q7znOcCRSe1UNR+Fel6wstzaXTBQwkhlWWKNWk3TOQyjGwlMyKMY+dh6VDpnw4ubzwhqmtiH7M91cTw+XLMPNeJwr/KTycmJhjHRzWH4Q8Qajc+MbnS7wItu+miV2mQoZQvmR+aCM8qZCBjoARit4xXvewl8O4m2kvabPQ1fg3rk3g3x5beGdVuLcxSXZ083BwxMbbAwycqduAwHBDE98429dlE9pMLtlcX0c2kPDPEjKJixRCFTGGTyoQSQMGXPesbVvC7atLNrd6o03ymkdphkAyCQCR2JxtVvMG30OAOBU/gj4WeOPjFcxTaFbyW+jyGSa41bVJCltGGIKqn8UjAhuVzyevAqn7OpL2r07vzMXzU48j17ehi3076T4dubCwszcW13IZLW4jBiKrE4Lu5DAZc5Cjsqk9wak0HwvD4c0w32r6hJaXt7CsxsoJFGI32MoIwcfejwp5BVh7D2LUv2fLPwjDDaa3rovLpI2RY/IO2Q4LErHjgAMeSWY4BO0AA8h4y+C+h+GE826hNxdXIjMVrFdM8mSMK0hIwvzEZ4B5IGAOef69TqSdOL37LctYWUYqoebapf3Uzat/Yku5lT7Db29jEZI97qQ0jS/KHkHmY4HDFcAkZrHiv7uawZYUbS9KnW6lhRssXdIghjVzyeNgX0Bx6mvQ/FPiBfDPhiXRNOls1j0m1a4kSELhbuVFhcs52ncFVWOP43PcYHjPg/wARxeJr+105me2Se9itEkViY13HG0KOQxBPPsfWvfwd5ptLRHiYxxp25nqzQ8d311eX8UZthbW8iNmOLIQttQAYPYYyvoCK5nTMGxvQ+C6lHyM5ALHI/IfpXrN14dGm3F99slN1sjdozMfnKmJeTjkEhB+deU+GWW/1sx3DYt5rsHOTgJvHGfxNfS0eVU04nyWJc3UalubGiWFyutQTRIzx+aWRR6gE/wA8/lX1/wDAvwfdWeuQX8kCixuj5sZ5DY64/DNeKfDuxSe+tJwo3JcFpSF5hDbNhOB3c49sH15+rPhxO+rXNo9zCttJHCvk7RjBVjkHsT1B4zxXLUqSV7bHXh6alKEXvc9feXCY74qpLL+tLJOMdAPrzVKaXJNfGyep+mwjZI8CSxvccWlwffyW/wAKsR2V4etpcD/tk3+FfY8firRZJGET7W43F0ZQxyMAep56VcttciiP7l1kBchjGSCp64YE5/8A1V7ajSe0z5R5pUX/AC7/ABPjWOC5VebeZQOOUP8AhVq3jnI/1EpH+4a+vZfGNrBFeT308dnFAMiWVmKkdOOgOSMYFYuo/Fu0tIGbSLJtXcSmPMcnlJwM7ucnH4VL9hH4qhUczqy2pfifMsccwbHkyAnoNhzViJZS20Rybj22HNfU9n8QrxbI3d/pk2mQ4XMhl3gFugGQM9hWnH448yLzXkjWJuFd2JJHrgUctG1+cX9qVU/4f4nybGzj+FuParKs3XB+uK+vk1aFLdZJpViiZdwLZ5/DFZ8PiyyaURLcuOQPltWcEkAjoeOvcUnCj/z8Qv7Wk/8Al3+P/APlhZf8amSUA5Jr67tIlu13R3qSLgHAtirdB6sMfjUk9sfMjVZI4XUZDTRht34BuPXNU6EbX5hLOGtPZ/j/AMA+TLW4XzFAkC89c13Ovatp/hzwFHqKlG3RuizGQn5udw5wM4A/M19DR2aPEN1yhJH3kjBHSuI+JXhnw54/8J3/AId1C+wtyNqzW6gNFJzgqRkZB7fmMVx4vDxdGUVPcj+01WnHmhZI/O4aXaeP9RufFt/fZjs2MVvp7n91I4AychhyASBkMBgnFeOeKvEZ02/u44rwxW9xuaOBzncgAIyQO5x8p55JPIr6Qs/2CNY8LW2sabeePbc6VJdPcWl39gUToxxkn98Dg5AKgH7ueM88NqH/AATh8Z+IWWObxnaPpwlJjk+ziORkyNzbWcD0wcnP0xXl4eGHp1bTqe6ttHt9x3VcU50+aC19TwXS/jbbaKZ4meS3MyrMJbeQlY1CtuGDwSTt65GcjHAxi6p8RB4rgNvDF9pvooUdJF43bVG8gD0Ylse59BX11p//AASd0RGEWo+LtUurpwXEVv5MG/HJxlX9q9A8Hf8ABMLw/oUUMkeoa3bTgeYc31vmNiMEBzbcjFe7Grl8Pep3b9GeDOviW7Tat6o+Z/2dfgBqPxj1G1tjb7dLgKtf6lIMhUZFby1Pd+h49TmvZ/j9+y94J8C+GBcaTZk3SExo27BYbdoJ/wC+c8etfSGhfs9av4Pht7NfHer2ltHGFjgGsW4wB0UL9i/l6Vi/Fj4VG78J3Udz4jn1G9jjZo4dUukdGUf9sI/Trnr64rmr4yio+7e/oa4aznaaufM37PvhnSNb1mSw1qzF9AUA2bSzpxjK4B+b3xyM9eK+sZvEfh/4NeHrex06G6trWLJWKR8xuNox8pJPpzgnp0r4LF5eeH9Tbyne1ngk3K8bZZCOMg16LqPx8ufFGnx2eq3UzzOoil+dUjZe25dp6E9Rj+teNUpzk7p6M9f3ZO0uh6NYav4e+JWuahFd6beahplz/rF0qWTfbgkANtSPGARzuI/HjPomjeDtFs9Gh0iZI9Rj80MqXkJt7gDGBKSAP3gX5fMAD9QTyRXO+C/DXhjS/D9reRaZZ3N2+/8AfzGe4UAZGQihmUk4zg4B/GmXHxDtdAtZ4tT1qC309JMQi2EiLuPKlFLZ69Rgj1NS7RXLAbTqPsjC8b/s+Q+IrXTJdF8ZzSSaYjwWMQAukiIZm8uXaS4b1bHIAzXgF7+xN8YZbu6l0/SbfX8O0jTQyiFmz32zbTzx096+qvDGpyXGpTa7crDe2sW4wXUiYJ443BC/Hc4AHrXsHhrxzPqQDabb2wVXCgrEEJQAclTltvOAwFa0a06F9E/6+8iu5290/If4j/AP4ueB2L6t4F1yxiiODcQWzyw4Gf40yB+JGKyPBPj7UrPWdMgeSS3ubdNriVim0rvGXB7YIz7A1+uOt+NvEN7eTR2lijBefOub82qewy2MduV4PfPfltY+FunfFqC5Pi3RdMVh8v2p54rsnpj51j9APvSZ4GK9WOawqQ5atLTy/wCD/mcCw1WE/ae0+R8wfD/xPF4z8KST2ksZu5VzNuwvmOn7tcYJx8rNzzwCMfNTtd8LOPDlycpbX7Ko+zRMWkdlZEPI+75meh6Lyc16Zp/7M/gjwVrEE/hXW9WhvLd3LaTaygxuWxyd4kwOAeWx7dj0mg/CbU9LnVNNittFt5ZDcT3txMs0qjB+cnkkkjPy4zjHAr5itCMarlQlofXUMSvZ/vtGeDavrF5Nouj394UiiRZw7T42gFBGiog+YfLJkkZ+5gc8Vc+DP7J/ijxxdPrmpx/8Ixp4bZAdWUiWeDIKjygwdeMdhkrwe9fSvgv4d+EPD6x3+n6RFd6gGbOtakSZMA5doo2zs5AwVHB4zxXSax4w03w9FHJJLHb3cr+VA4yzn+8V9zxkjPYAk4zqsRKnFxgrXOarP2jSgtv6+R59bfs0eHPCepx6n4rvLrxZEtwJILC6iSC0MnTCwjG5Rx8rEqMLwxAx1Xjbx7psepWun2Vt+9uAvmPA+xYIx2QD7x2hvu9M/wAXfhNc+LS/2nquqXd8totrH/oTzRtNcP8AJksEwCq4bPIxwfXj5q8Y+NPEGh+I4VuNUutOvfMeXNxH5kkEciFd8ijgSHjCEnbsAx2rKnRrYr3ZPTp/SB8kHzz1Z7H418WRaxr8GpeE/nvHgIkkeUy/Z1IGXMjnanRuh4EYOe1fP/xX8eyTWTXrW6jRvtUrWrFn3zdFDs/UjCgDgAc46nMOvfGS3Fja6Xo1lBMiwku2oMClsQMHLZO9zhQcAAHOM5Jrzbxp4xm+Inie00q4n/tGwsUVd0KMsYCglgFwMDA4UbVHf1r3cHl0oVLzjovyOXE45ez5YPV6GJ4s8ZSz+E4LNjC/mpuHk4+VSd3OACznGSTkKCB1zjlfAuuPaeMtJa0sxvN7DKkWSwDBsjAPX8T0zzzV34gXi/bJYo7aG0USsxjjbcy8g7WPfHHTA449tf4V/DjxR4k1WK70vTZNxGEkdCRgjBPQkDnr/KvsIOnQoOTskz42s518RGKd7dj0z4s+MhpmtXa+cftctn5cgVs4YrgDPQ/KT/nivMdBtpzcaaVBSNUfnqMnb/IEV9D6T+xJ4p8VXEx1HXrCxZkOdtrLIXxxtGSoBwO56V6p4N/4J+azBqiveeKbWzWNTJj+yifLyBgD96ex9ONtcdLMMLTpqmqidiq2FryqOpKNrnH/AA08PrbW9kImaeR4ifNjONrI2/B/vZBGPwr3v4Z6Ze2kvmSzGVM7ssPTr+mK6/wB+yxbaFHa48VmWJEIIawjDOcjp8/AwTXrmmfDjRNP09WLXk+5f4yIjjPGe3OM8fjXHVxdOSapzWp24WMKUlOqnddjz95eTVWeaus8daz8Nfh3a2cmtXsy3Fykjx28UrszBBliCqsODx26ivGdT/ag+FqM0dh4f12/wzDebtYdwBAyAyng57gdD7E+YsLKeqkvx/yPpVnGHjun+H+ZoJ8TL21tWaJf9JU5jhZ/Jdyx4IYsR0PPGeuK6Hw3r99rNhPejZq5Z3DWnmsWjl2A7QTs3Z5OevBrhLXTG1GXbqertCSxJj1UGMrgcEMM44xyT6Vu6JYvaWRMWs/aLWJtiNYTKWjdupCv0bBPb1xmvkHXmtjCVKDWm5d1GTVLK8SU2WoWliluryxxs88I3PnAEpbBAwDg9s1cttXgSwhuWsI7mKR2BitCLd3QoRllJKY6gEEcisnwzqcdxeXKXd5cw21wHggeVXG/nbjA9Tg5BwPakuPBlmkty3ni+uYgqRgTKrwLgEgZYEgbj1IBNT9YqN6slQitDovDHjFopFt9O1O+hkebMVnc2+0qD8u0dnweMqeealv/ABjiaa3vLe9VFlKSXenxN5WTzjy2HzdDwD61yGnpNod/dxwwCS9jh2CJQUkB2k8YIPOPR+c9TipIfH9pNeLDcWmtWbwQPCPIbDKTgB2ICNkDjO1utbe3qPToDoxvdI77SvjHpbveQWF5bXkpPmra3cptnB6bNshJJ4J+XNOuPiJqNxG73WnJ4fDIjDzombYqg5CkqATwM5yemK4OW/S9tLg6rbWGq6lcIWmhYJvALAIdpKsOhyOfauUlih0i98+ODXPDV0x+VrC4YKzHLZClowOSBjnv3GDk58z3sxKhHex69afEIWhW5/tnzm8wqHjikUNgZBGxGO3g89OORWlefGSzgumaW6gurdmOQ0MrEHJBGccnjuew4Ga8Wg1O8vo5Bba8l+7Ah21mx8zKnGMny3zwB827v+WrENTtpIYZrDw1qt052TW8Ie28ogjkEzgDBYHaFBAzwK2VastFIHh6Td5I9if406LLDa2MUiG2kjAEdvC5CBsjgKo5xuHXjPTpVT/hIfDuq6w8iaxc2canEaKiMxZlzkbgpUnj1zg9Qa83tPCeoPqltIvhO3lPM5ksLmUkkAnbkiQAA5xjI4PrXaRatZXskMbaJqul+XExkVtoj3KpAX94i7uOd3uc0TxNZ/FZmXsaMPgv+B2Glazp0072WnX7XhAOUupcFkx1wxKgD1x+tXv7OJe2lNssMWVHlQcxvweFKjn9O/XrXkNtqljPqkOoaVE1hJax+Tdz3mkELICehKPjcfnA2kDk8ECu+1DxJY6xdi3srzTr2EKEa2ecKYxsBLKrhSjc8EE546ZNc/tJz6fiROCj8P4l6/17UBqcsfm3Uu2UbZEYyomMAIVUEjGTnI5NL4muNQsH+0XDwKXbZ5hQqjKQQQzKT2Ofmx90dzV2O6GioVgN7qMvlEho2WTdL8/3Uj4OOc84/p51491DW9VkaP7Vbq0ExmjTULVDhx1YkKMY3MO+PXI5znOUE+aTuFNc8kkkNmvLPQ783cuo2wuJpB9ogCxyxmI7fvHG7g4OQRxtHfm/qHjfRpb5oXgsLqCOPEO2coWJGHZht3ZyBgE9gciuPtmv5bl5tS0vT72EQhHmsQUbBx8pDNg4bBJA3EYAGc49Sj+H3hy08QpFB9o1MJaqJoWug4icxgoSoAJDAEAknGRxzwoVZpXujoqKnF++mfH/AI5+Hel6xdXlxpQc6o1wYltLeM+USeeHy2ScngndXkuo6Fd+Gr1YtV06e0kTD+XcIUfb7g8g/Wv058O6BpNm66ja6ULS5mV0ihubXyslVxncoJVcNjoOwxXCfGL4BWPxM0mO4lRE1hYjnypy3zEnhVOOOnXHTtXoUcdKlZVF7pDq06s7LQ8D8HfFDSPE/h59PgcZSP8Ae292jEOQeGKgcHIGMMcnOayrfxjc3+kXEcTWelaY52KuoX8MOW5wwRcvjORn5j+teO+Lfh5qPw91a7iSS5jMLZAGQQfUgZH61ws3ix7ZiLrzblf4WZixX8GOM/hXsU6UZvnpu6Y5VORWmrH1f4Xin1eEwHUpfsQGYna83M75A3qrR7EGCB/e9Aa9nttSfQdAitrZ729vNhV45ZJHUcYyeEVF6nPB6cGvj34M/EC+sJBeQxwXCxOskkupTITsGeFLrtGMjkNnHAUV77qPirS9ftILe71R7iUoWCWUqRpExByx8vKKOBy24npWOJUqcrG0F7VX6HHy+Pb3VPEo0610eyvpY282SR5pnjjUZPAyvOPXOT2wa9stdWuv+Eft3ntLnfcfNDZ6VCAUJTJLy/IirnA3Hk4wGIr461Dx5feCfEZv7GJrpkLLFFNKUCuD99hvzjnggpnpx0rvNG/aG1TxLbLJrV/JEbndG8EsvkSy4xhPLUFggLY6MCTznqXKlNU047Gj5Zzsdj/wsmayv2sLZLlLVwQEguP9dJkn93tBY8k52E/dOGzXe2+vBfD9r88EN/dptgto3DyS4GTKzAZbAzk89snOAPmb4k+K/EEdlc60LeGysr1PI4SRnuuOFZgc7c8Afd9Tniqngv42fYriF5717mUW4Wa/kcI5UDAtbcsPkiG0ZKrljgZBAUJYaU6TlDoaSmlNJ7nrfir4lxeAhcu4ZWXEgidAiRRrwoZsgrzysY+buTwMmi+PPtPgXUtV1i4tLP7ZF8jq/wA1tERkqCAAufm+UDPXLNjjxr4mfES48fiKC2m8i3sCbqZEjCrJccAFmcA8Yzlt3Q8cV8/+IfiBPcSNHLc3c0S/IhyMtj7z5PVmPcj8BjFb4fL/AKxCy0fUmvio0HeWx6v4t8Ra74duF1DQWn0xNQjLwXDLgQRBxtk5/wCWjMu7J56egrg5PiHpmL1Lm2M17IRG98zh32Z4O7nDHGWbBPTA4GOQ174o6xrVkILq9e64K7ZckIvYZ6nH+A6VyLGe9bPl7IzySBgH3r6fD4Llj+9/A8HEY9OX7rU3PEXiDTbvTI7DSLIAqD5t/IpDyHOcKM9O3OeB6k0ngzSdYnvdtgsqzSqylgDtwQQSf1rX8H+Dp9duUhhgBZgDvJBAH0zX1z8K/gpZxWKTXSTLKAMeQwUE9wACew/DmufG5lSwUHCKuycLg6uKqKpJ2sebfCL9kp9b1uDUNVE9/pdsoeR4IXJkcfwhSMkD8elfb3w58DHRVDWGj3UEQjWGOVbF0duM/dZCM8H247dKh8FfD/RbCxy1jceauQoMis2BjPBCknr09B0zXb20OjWimFYNYSMLtJjjjI3EZKjgYIxj/Jr84xuaVcZL33ovM+hhRpYZONJavyOu0LT7qCzj87Rb+adZTiUfux0wGKkDHToOvH4b2mWjhxC8YVgPMdS/zSE+ucEc5rzaSy0nU4vMGl660aKF3XFykZ3/AN4AHJPzDkDH5VZi8O6DpVtHPaadfpdCTat7BcKJCuCBk8kDlvzz7VyLFqHX8UccqTlv18v+CeqWWnRC3glmtAZgvCwr9wHsXzzjHXipv7Us9JtXnvkstPgQbnuJpUHlg+vp1xXng0zTLCG3H2S5uDccEnUpmVW/u/Kvb8O9Je2Wnvot7HbW1rPdNFsnSSaaXLYIB2kjnn15BxXbTzNRtZfj/wAA45Ya+7dv68z4K+PPxYn+J3xT1jV4LpruwLPDprElVSEHC4H91iRke1efu3nQRXMZUQxLuUuRuWJQcgnjPH48fSoLtytyfMiVJI5CrqAFC8kDAHA5yce1XNWtIo4VkQbwVPn9SH+ZmLEeoyM+o6+/6VRilCNux4VVvmaPrOz0977ULe7MTxQ3AIZpSyl2IwMgDDAkdDVPUhfXcRgvYIfLtFwl9aFY5VG0AFWUBsDAxnOK6TQF0vU9Mhiiu7ljEAnzqqJG248KF9Qeatax5WlB4LVfPt51+WRIQXLEELEOnB5ySOBz2r832Vz7C+pkxm01JGGm3FzApYFotdkMmwhQMpIQSflUdcDk0s9hNbXAiFzFp0nm4M0iloCACFAbIZSxB6EYwfSnaetrdIY1ifS4lRGWGV/MQnGCu4Hr0I9cnvT9X1HUdPa3dbqXULNWWVpIIUEzrggrkfM55bJIJ68+sSdxq97GWIpdWtYItYjZniQbL5kaQ7QOVkkGWUgnGCCORk1dNtjQ3hicaxYMx2PMfOO0gnyxIT8vzE/cx9we9S+CtTmv/E6LI3maJdK09xbk7PLQrlQM8g56jPTPFdlrJ8Pw2f2yK2t9NggGwiEuJAOpAKjrySDtP6c6WvHVkylyuzRwujppeoyZns7vTGAG92YXMZ5xgKwyufd8c1be1tdOV57LUo4zO4aDGoeUoAPOUkXYCOQOfTBrS0e2/tuCae6vfOiWPBQwb5AobjeYlU9OckA9OlYzWEHiO0sV+wSJDCXlMKoGKEkrhlyh564O7HXrioatrYtO+ly3ZRSpdedFbb4beEEKsCXAkz947oscjgg8D0x1qu0bWbx3lmJY73eTNJHcFHww/hSTqCoPtn2PHI3nhbR9OEUEOvJaTQuzMtzcS2oIwpZfnAK9Qep7+1df4C0G8S5Fva+Jby8sYoZXkjBS9gyHBBP38ZBHy8Zw3Sml2f4A3ZXLtisdxbB7nQ5dLghhVJTCkCyYB3GQsrKdxGQfQZ78jc07xPZRzyLZeIZwbchUtY7/ABIQSVB8pyC55BI9s9K5/UY/EKapPMbS11u1G3bZzTNbGKMkkTGMNwSODwT0BpmoT6JYST2mraRLpyo6nzisVxGzEFlw5ZWJOFJHP3RnkVLbWq/BmckmrM7ywuRqOtXAl0q1uocI32vUIDDIxPH3l7deCT0PXrV6607S7vUYpba3ubS6dWQwLsZLj5WXZ83PtyeB+nP+G9F0yxtJG00XMhnfMkNo5heWRSTjY59GAIUNnH0rQtRc20F3cajLtltMOtsbHaQM8BvLUMTx1HXJ4OaIXt734mD3uv6+QahJZ3VzNBbziFY7jzHsWWW3khzz0AZegx2zg/SkTQdR0+GzNpqOtTvLJ5znTNRjkhjXklTGfmIOBwQRkg5p+ix3z2EV/d20kUoQrcm0UTRliQoyoUSHrwMHkkj1rHttOtJ9YaTT5Fu0WVZnggdjcgZYkKjMrJwB1HGBgVDutfyDTZs6DWbWfVN7faLe6s8faJreS18tBlyWUshUngnKnI3LntxreHNX+yCaG6tZrBxAiwNZOXCxKduY9+7AAHQEgkdq5e91nUdGnWRNVmuIZ2HlrqMIaR4/mKKxZS4xkjjBGCe5rca+sjYW2rPpk6XCFmm+yM3Mf8I2ZbgkgnaBnHbFKL8/vREou2q08joIviitsDa3seolE+W3lNmxZk2kkud4BII5wOn5nUttZg1SBb+w1CPIcRSRywPGY125+6OcncDgjv7Vxlpe6YLozXcmp5kxmFZABGcZwDjoSeSD/D789voksMkHkQ3kttczsUkSVgsm4NwSMdACOmBggcYraC59JJM5akVBXSaPPPF/wd0zxtFN52oW9/dXOXZEupETgnHyknrgd8jv2x8afGj9lrXfBN1Le29nFfWRy2IZPM2AZ+9k47H17V+jr6bpstx9mfUd/lkttUorZJBAJA9e2fSsXxL4Itb5zbx3Ec07Rhn861UttwQCGXGDnjBzx24r0KUquG96H3XKhXU3y1Hp6H4+a9p+u6AiyfZprGN8OAUMYbn5WHTOOx/WpNB+LvibSndBPC4cFZJmQSTqCMEhmBCnA6kf/W/SLx1+zLp3ijQpDNY20cqg8W0gWQnGcZIOf1PT1xXzTqX7FepOHlS1uIYOqhgGc+4HT/61etSzGjJWrxsbeyk3ejM+WfFfxK1LVbtLiSWQyxKUhIO1UB/2RxnHfp7VzWk+PdV0K6muEmUzyLt82QZZR7d+nH4CvozxD+yRc6TcSRyXoco20eUpOOM9TjJ+grgNT+Bq6K2bm3km3A4Yck46ZGeO55xXr0cfgeXlRzzw2Lcua5iar8ddQ11Fhvbq8lskjMbRAhAQQOAQ2VHtz+WQfNtU8Ry3FyHtN1nEpGxEckj0Oe5969D1H4HaxPN/oto6wkA5dlVs+yZyeh7VVs/gzqkNy6S27BlIwGTPtnA4/wD1V2Uq+Coq8LLyMKtPGVXab+Zww1rVby28g3Vw8AJYqXO1iRgk+px+g9KoC3mmLDa2PUV60fhfdxFY5ELA8hUTG38u3/1q6jw58GJLqYK6kMTgggjsOTx6mlLMqNNXQlgalSybbPHtE8CXGp7dsbMdu7gdq77TPhVFdWLzfvkaPrvkVs9MYA7HcOmee9e+/D/4WaZo0UN1fRK8Aky7b2ACfxZ4Oc9Pl+tetaT4JsLeZpLDR4b94fl86SdY4ZMkBW2dRgFRhjz1zXz2JzmTlaJ6tLLoQV5HnPwr+CtzYCOOWzbypU+R/sfnIcAYOcjJ46fXpX0h4I+FcWjWgOEjlmV5YliJ8qIrkhiMnaCMkjgdOMitLTPh9pVtpFuRCs90j7zEso3MRGx53EDBwOPbPWux0/SC+mqFZbeV0VJIYZowXGQTg7Qec7j1+93NfK16tSvK7O11Y04csCHTNEvb1J2tFtXeSHy5ZIHkffIAMYJfaGx149Bkc41l0fUzZC1ItEaMZcyxuU9Dkebjp6nt1rJWWydrhFmjV43aWQWt38zH+7woyTkggDvWnp8NpdJ5dpLaWdu379z9ocKVJJDcLzk9fTnNeVKLd7L8jnlJ7t/195HNaXllYwxC6tGnTlBFEic4PIQthuf5cdcjQtIZbrUo459SdIiAVjtktwFzk/MdpP5f/XrOmsNM0++W7ml0+3CyiySUyPlWLfKmQOOeOvGa17PUdHju0HnWEojBjeIRB2JxkKGLe/t70oxae1vuMpPTTX5DvEMGlh4o59VMk0fynEu1iMnjIGTgnnHoOMYrhfFC6NbaE1y2rSWitl5HtZLl5iM9ATyeg46V30fibTZ4V8kRJkYISCNjG2T8pG/OV5B965Xxf4q0O006aVxqFzcDEZSNFTcM8KoXjHB6np3qqkVrJW+80oOcbKz/AK+R+ZlzJbTyGSBCbdyWQScHaTgAj9Kku71/s/k8mJNwARuXXqynjrt498UkpDWolltpbVZQ0qwSjDIpYkDoP9rnFMeQQWUhcxsGAiWReqvu3En3I2dO2emef2Km0oJHyVV3nL1Pq7wppd9pegWyrcfb7a7O+OfABi+oGeoHU+tdXZS6jqV5FFHAqx28f2hpyAQ38IGCPlYjIGAf1oor82aTPs5vc0b+yxutrQxwnYJAZ4wysOSQyj3B6daxddme2tLe/voDcKpVTbg4WBccMGBBx9M8/Siik0mkmTDVlXQmtVea704T3WDnfbyFZI22glGyQR16njkY7024vLy3W2WztLW9fmTZqLeXKxJVc71yAM45IPWiipkknY3WozTvHlp4jkNhdh7K4QeU0ckrRxNznG7djswyxHTnGMVp3cRtAJZNVl0y2jjSRHZi0YzgJhX4PzAfXPpRRVziopWFZKVjgr/WYY9VSK80qXVoIxFMDFfGAuGxnI+bHB/p3ro7WPw3rsGnabcWMVjdpuEks0fkCNRyD5gYd27lfUcnIKKS2RrOKs2dZLu0k6dHpF9cTPEhZrmW5+0ZAzlEBXOASMkHGBx1rpdM1XVL9HbUtEeK3mwQ4m8+FI2yoARzjqASC38RwMUUVCk5NpnJKK5E+pe/sDTzJHPAyxOjeY0cA8plCkdUA5UHofmA+orDufD2uWFheXOka5LHJcSl5bbGFAIzgKxxwO5BJ9s0UUqrcZJIxjJ9Sv4a8Ta94d1AQ6po8V7aEBIHhlaAkhtu4sgZWPbAUZCjHFbXiS60nWbi3nWUt5cgjlhlCy5GF2hfLIZSEB9jnBGM4KKhy05bHR7KMpc2xH9j0+Ga2j07W7iW1ikET2xBO45Yhm3Kfl25XAA5Oep21K0l99ola5hgkhTMaNdWhcFGA+Vijryy7sALznB6EUUVjKbTbRzNaWZf07RtQnVZZtPhhSCZdsMOqOgePGQ6rtYAEjO1nJx16AV2qazFe2TSXCzWodfluWxK4CnA5VlOCQvAPOeaKK7bKEeZLocrXPJJlQ6SYr+S7h1FLtZYXK27TMrkEdSPqexHIyW7VdttH1S31KXULnzLiOVFUOsm/JHUnaSepJxnGB60UVqqUZRv8zGdSUZWI/8AhIbqyF2HyqlykY65OM5wwyenboCPesptdh1CKF717a3Mo81mc5Qg4LZOMc5H59OaKK87nlpqdihHsJqdi0+mtH9kOI8kIpR1lI6lQ3B65x6CuB8VeENLuSZBbn7aq42myjjK/Ju+/tIBO7sD17YyCiq5mtjajN81jj7T4c6c8t1cPp8EhYKSzWwn2bc5w+S2Djngdeg4pIfAmi3EdzFcRrcRPIymHzEj2qCMfdCk8EnjFFFHtJdz0k76FfWPCHhCzb7PYaROJPK+Z7Ysyo2f4skc46E/iKu6f4M8O2kNn59ncZ8rc6+bJhHJHQAgfXr0HHaiis5VZdzXl5VZM2rXQ9D1KedkR5LOSPafLdsgDOBjyxxknk8nd7V12n2Gi6RpMsXlsLmOBBDIrbSXYnnAXqDk9O+OaKKwcnc56ie12bHhZbexsBPcvDIJg00kctwJHRs7sZCgcD0Hb3rYt/EenTfZo9PlKQykobdGXaM9ySg9CAfQUUVcZtKyON01O8mZN9fi11DY9lN9nQk2zSXccjMQG5wQuRxjBYYAGcVV0zx5oPiaK5i02VLiaJX3209kAibSQ20jcGGcjIyOO+c0UVikpqV0bRpqUOZ9DmPD/wAUrPxHrMkHg3Rp/F91bzGGaaxiSK2hkJPBmlZVbtkoGx0PPFT38fxTa7iDW2g+HIXJfzPtRJiG7AVv3PzE89B70UV6mIwtHD3UY3t3Ob2rU0rJ3M2w8Ktq94moar45a4to5B/o9hGyxySYyQzEEkA9toHqBW+ukW1hBJHDo/26aGICK5ubyR1OSf4icjgZICgdeaKK8epK/Q9FuSe/9fI/NbXL24i1q/eaDaxu5vNgXjy23nIGeuCDwab9rMVgECkfNkeobqf54/Ciiv2Km/3cfRfkfBV/4kvU/9k="
}
\ No newline at end of file
{
"issuer": "http://localhost:8080/realms/external",
"authorization_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/token",
"introspection_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/token/introspect",
"userinfo_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/userinfo",
"end_session_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/logout",
"frontchannel_logout_session_supported": true,
"frontchannel_logout_supported": true,
"jwks_uri": "http://localhost:8080/realms/external/protocol/openid-connect/certs",
"check_session_iframe": "http://localhost:8080/realms/external/protocol/openid-connect/login-status-iframe.html",
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials",
"urn:ietf:params:oauth:grant-type:device_code",
"urn:openid:params:grant-type:ciba"
],
"response_types_supported": [
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"subject_types_supported": [
"public",
"pairwise"
],
"id_token_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"id_token_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"id_token_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"userinfo_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_object_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_object_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"request_object_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"response_modes_supported": [
"query",
"fragment",
"form_post",
"query.jwt",
"fragment.jwt",
"form_post.jwt",
"jwt"
],
"registration_endpoint": "http://localhost:8080/realms/external/clients-registrations/openid-connect",
"token_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"token_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"introspection_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"introspection_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"authorization_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"authorization_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"authorization_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"claims_supported": [
"aud",
"sub",
"iss",
"auth_time",
"name",
"given_name",
"family_name",
"preferred_username",
"email",
"acr"
],
"claim_types_supported": [
"normal"
],
"claims_parameter_supported": true,
"scopes_supported": [
"openid",
"email",
"roles",
"profile",
"microprofile-jwt",
"phone",
"web-origins",
"offline_access",
"address"
],
"request_parameter_supported": true,
"request_uri_parameter_supported": true,
"require_request_uri_registration": true,
"code_challenge_methods_supported": [
"plain",
"S256"
],
"tls_client_certificate_bound_access_tokens": true,
"revocation_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/revoke",
"revocation_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"revocation_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"backchannel_logout_supported": true,
"backchannel_logout_session_supported": true,
"device_authorization_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/auth/device",
"backchannel_token_delivery_modes_supported": [
"poll",
"ping"
],
"backchannel_authentication_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/ext/ciba/auth",
"backchannel_authentication_request_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"ES256",
"RS256",
"ES512",
"PS256",
"PS512",
"RS512"
],
"require_pushed_authorization_requests": false,
"pushed_authorization_request_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/ext/par/request",
"mtls_endpoint_aliases": {
"token_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/token",
"revocation_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/revoke",
"introspection_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/token/introspect",
"device_authorization_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/auth/device",
"registration_endpoint": "http://localhost:8080/realms/external/clients-registrations/openid-connect",
"userinfo_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/userinfo",
"pushed_authorization_request_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/ext/par/request",
"backchannel_authentication_endpoint": "http://localhost:8080/realms/external/protocol/openid-connect/ext/ciba/auth"
}
}
\ No newline at end of file
package kz.project.printedFormsService;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
byte[] bytes = Files.readAllBytes(Path.of("/home/bazarbay/IdeaProjects/printedFormsService/src/main/resources/Request.xml"));
System.out.println(new String(bytes));
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment