[DEV] basic functionnal version without history

This commit is contained in:
Edouard DUPIN 2020-10-02 21:57:48 +02:00
parent 12f30c29f8
commit ca8274295e
200 changed files with 38995 additions and 3 deletions

64
.gitignore vendored Normal file
View File

@ -0,0 +1,64 @@
out
.idea
/dist
/dist-server
/tmp
/out-tsc
/bdd/
/front/coverage/
/front/dist
config.env
*.class
dataPush
node_modules
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store
Thumbs.db
backPY/env
*.pyc
__pycache__
.design/
.vscode/
back/env_dev/data/
*.sql
public_key*

28
.project Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>OAuth</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.jdt.core.javabuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

70
Dockerfile Normal file
View File

@ -0,0 +1,70 @@
######################################################################################
##
## buyilding-end install applications:
##
######################################################################################
FROM archlinux:base-devel AS builder
# update system
RUN pacman -Syu --noconfirm && pacman-db-upgrade \
&& pacman -S --noconfirm jdk-openjdk maven npm \
&& pacman -Scc --noconfirm
ENV PATH /tmp/node_modules/.bin:$PATH
WORKDIR /tmp
######################################################################################
##
## Build back:
##
######################################################################################
FROM builder AS buildBack
COPY back/pom.xml /tmp
COPY back/src /tmp/src/
RUN mvn clean compile assembly:single
######################################################################################
##
## Build front:
##
######################################################################################
FROM builder AS buildFront
ADD front/package-lock.json \
front/package.json \
front/karma.conf.js \
front/protractor.conf.js \
/tmp/
# install and cache app dependencies
RUN npm install
ADD front/e2e \
front/tsconfig.json \
front/tslint.json \
front/angular.json \
/tmp/
ADD front/src /tmp/src
# generate build
RUN ng build --output-path=dist --configuration=production --base-href=/karso/ --deploy-url=/karso/
######################################################################################
##
## Production area:
##
######################################################################################
FROM bellsoft/liberica-openjdk-alpine:latest
# add wget to manage the health check...
RUN apk add --no-cache wget
ENV LANG=C.UTF-8
COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar
COPY --from=buildFront /tmp/dist /application/front/
WORKDIR /application/
EXPOSE 80
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karso.WebLauncher"]

View File

@ -1,3 +0,0 @@
Generic OAuth interface
=======================

27
back/.classpath Normal file
View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="out/maven/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="out/maven/test-classes" path="test/src">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="out/maven/classes"/>
</classpath>

44
back/.project Normal file
View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>karso_back</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.jdt.core.javabuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
<filteredResources>
<filter>
<id>1647191868592</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

1
back/.properties Normal file
View File

@ -0,0 +1 @@
io.scenarium.web.karso.address=sqdfsqdfqsdf

66
back/CheckStyle.xml Executable file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Check Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
This configuration file was written by the eclipse-cs plugin configuration editor
-->
<!--
Checkstyle-Configuration: Marc Checks
Description:
Checkstyle configuration that checks the sun coding conventions.
-->
<module name="Checker">
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<module name="TreeWalker">
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<module name="AvoidStarImport"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="false"/>
</module>
<module name="ModifierOrder"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="IllegalInstantiation"/>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
<module name="ArrayTypeStyle"/>
<module name="TodoComment"/>
<module name="UpperEll"/>
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
<module name="PackageAnnotation"/>
<module name="SuppressWarnings"/>
<module name="AnnotationLocation"/>
<module name="ClassTypeParameterName"/>
<module name="MethodTypeParameterName"/>
<module name="InterfaceTypeParameterName"/>
<module name="CatchParameterName"/>
<module name="LambdaParameterName"/>
<module name="Regexp"/>
<module name="RegexpSinglelineJava"/>
</module>
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<module name="Translation"/>
<module name="Header"/>
<module name="RegexpHeader"/>
<module name="RegexpMultiline"/>
<module name="RegexpOnFilename"/>
<module name="RegexpSingleline"/>
</module>

66
back/CleanUp.xml Normal file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE xml>
<profiles version="2">
<profile kind="CleanUpProfile" name="Scenarium" version="2">
<setting id="cleanup.use_autoboxing" value="false"/>
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.organize_imports" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
<setting id="cleanup.format_source_code_changes_only" value="false"/>
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
<setting id="cleanup.remove_redundant_semicolons" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
<setting id="cleanup.remove_redundant_type_arguments" value="true"/>
<setting id="cleanup.remove_unused_imports" value="true"/>
<setting id="cleanup.insert_inferred_type_arguments" value="false"/>
<setting id="cleanup.make_private_fields_final" value="true"/>
<setting id="cleanup.use_lambda" value="true"/>
<setting id="cleanup.always_use_blocks" value="false"/>
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="false"/>
<setting id="cleanup.sort_members_all" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
<setting id="cleanup.add_missing_annotations" value="true"/>
<setting id="cleanup.always_use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.make_parameters_final" value="false"/>
<setting id="cleanup.sort_members" value="false"/>
<setting id="cleanup.remove_private_constructors" value="true"/>
<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
<setting id="cleanup.remove_unused_local_variables" value="false"/>
<setting id="cleanup.convert_to_enhanced_for_loop" value="false"/>
<setting id="cleanup.remove_unused_private_fields" value="true"/>
<setting id="cleanup.remove_redundant_modifiers" value="false"/>
<setting id="cleanup.never_use_blocks" value="true"/>
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
<setting id="cleanup.add_missing_nls_tags" value="false"/>
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
<setting id="cleanup.use_unboxing" value="false"/>
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
<setting id="cleanup.format_source_code" value="true"/>
<setting id="cleanup.convert_functional_interfaces" value="true"/>
<setting id="cleanup.add_default_serial_version_id" value="true"/>
<setting id="cleanup.remove_unused_private_methods" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
<setting id="cleanup.add_serial_version_id" value="true"/>
<setting id="cleanup.use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="true"/>
<setting id="cleanup.use_anonymous_class_creation" value="false"/>
<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
<setting id="cleanup.remove_unused_private_members" value="false"/>
<setting id="cleanup.make_local_variable_final" value="false"/>
<setting id="cleanup.add_missing_methods" value="false"/>
<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
<setting id="cleanup.use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.add_missing_override_annotations" value="true"/>
<setting id="cleanup.use_blocks" value="true"/>
<setting id="cleanup.make_variable_declarations_final" value="true"/>
<setting id="cleanup.correct_indentation" value="true"/>
<setting id="cleanup.remove_unused_private_types" value="true"/>
</profile>
</profiles>

20
back/Dockerfile Normal file
View File

@ -0,0 +1,20 @@
FROM maven:3-openjdk-18 AS build
COPY pom.xml /tmp/
COPY src /tmp/src/
WORKDIR /tmp/
RUN mvn clean compile assembly:single
FROM bellsoft/liberica-openjdk-alpine:latest
ENV LANG=C.UTF-8
# add wget to manage the health check...
RUN apk add --no-cache wget
RUN mkdir /application/
COPY --from=build /tmp/out/maven/*.jar /application/application.jar
WORKDIR /application/
EXPOSE 17080
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karso.WebLauncher"]

366
back/Formatter.xml Normal file
View File

@ -0,0 +1,366 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE xml>
<profiles version="18">
<profile kind="CodeFormatterProfile" name="Scenarium" version="18">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="200"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

6
back/LICENSE Normal file
View File

@ -0,0 +1,6 @@
PROPIETARY licence
==================
Copyright at Edouard DUPIN
you have no right

25
back/README.md Normal file
View File

@ -0,0 +1,25 @@
Generic karso interface
=======================
mvn install
mvn compile
mvn package
// download all dependency in out/maven/dependency
mvn dependency:copy-dependencies
java -cp out/maven/scenarium-karso-0.1.0.jar org.kar.oauth.WebLauncher
// create a single package jar
mvn clean compile assembly:single
java -cp out/maven/karso-0.1.0-jar-with-dependencies.jar org.kar.karso.WebLauncher

View File

@ -0,0 +1,28 @@
services:
db_service:
image: mysql:latest
restart: always
environment:
- MYSQL_ROOT_PASSWORD=base_db_password
volumes: # !!!! the folder is not the default set it on ssh not on long-storage data
- ./data:/var/lib/mysql
#- /workspace/data/global/db:/var/lib/mysql
mem_limit: 300m
ports:
- 3306:3306
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
timeout: 10s
retries: 5
start_period: 20s
adminer_service:
image: adminer:latest
restart: always
ports:
- 10079:8080
links:
- db_service:db
#read_only: true
mem_limit: 100m

186
back/pom.xml Normal file
View File

@ -0,0 +1,186 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.kar</groupId>
<artifactId>karso</artifactId>
<version>0.1.0</version>
<properties>
<!--
<jaxb.version>2.3.1</jaxb.version>
<istack.version>4.1.1</istack.version>
-->
<maven.compiler.version>3.1</maven.compiler.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.dependency.version>3.1.1</maven.dependency.version>
</properties>
<repositories>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.2.1</version>
</dependency>
<!-- testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test/src</testSourceDirectory>
<directory>${project.basedir}/out/maven/</directory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<mainClass>org.kar.karso.WebLauncher</mainClass>
</configuration>
</plugin>
<!-- Create the source bundle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- junit results -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- Create coverage -->
<!--
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
-->
<!-- Java-doc generation for stand-alone site -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
</configuration>
</plugin>
<!-- Check the style of the code -->
<!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<configLocation>CheckStyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failOnViolation>true</failOnViolation>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
</plugin>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.12.2</version>
<configuration>
<encoding>UTF-8</encoding>
<lineEnding>LF</lineEnding>
<configFile>Formatter.xml</configFile>
<directories>
<directory>src/</directory>
<directory>test/src</directory>
</directories>
<includes>
<include>**/*.java</include>
</includes>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
<!-- Generate Java-docs As Part Of Project Reports -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>public</show>
</configuration>
</plugin>
</plugins>
</reporting>
</project>

6
back/properties.txt Normal file
View File

@ -0,0 +1,6 @@
org.kar..karso.db.host=localhost
org.kar..karso.db.port=15306
org.kar..karso.db.login=root
org.kar..karso.db.password=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
org.kar..karso.db.name=oauth
org.kar..karso.address=http://localhost:17080/oauth/api/

View File

@ -0,0 +1,109 @@
package org.kar.karso;
import org.kar.archidata.filter.OptionFilter;
import org.kar.archidata.model.User;
import org.kar.karso.api.ApplicationResource;
import org.kar.karso.api.Front;
import org.kar.karso.api.HealthCheck;
import org.kar.karso.api.PublicKeyResource;
import org.kar.karso.api.SystemConfigResource;
import org.kar.karso.api.UserResource;
import org.kar.karso.model.Application;
import org.kar.karso.model.Settings;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.catcher.ExceptionCatcher;
import org.kar.archidata.catcher.FailExceptionCatcher;
import org.kar.archidata.catcher.InputExceptionCatcher;
import org.kar.archidata.catcher.SystemExceptionCatcher;
import org.kar.archidata.filter.AuthenticationFilter;
import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.util.ConfigBaseVariable;
import org.kar.archidata.util.JWTWrapper;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
public class WebLauncher {
private WebLauncher() {}
private static URI getBaseURI() {
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
}
public static void main(String[] args) throws InterruptedException {
ConfigBaseVariable.bdDatabase = "karso";
try {
JWTWrapper.initLocalToken();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("Wait 10 seconds ....");
Thread.sleep(10000);
return;
}
// generate the BDD:
try {
String out = "";
out += SqlWrapper.createTable(Settings.class);
out += SqlWrapper.createTable(User.class);
out += SqlWrapper.createTable(Application.class);
System.out.println(out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// ===================================================================
// Configure resources
// ===================================================================
ResourceConfig rc = new ResourceConfig();
// global authentication system
rc.register(new OptionFilter());
// remove cors ==> all time called by an other system...
rc.register(new CORSFilter());
rc.registerClasses(AuthenticationFilter.class);
// register exception catcher
rc.register(InputExceptionCatcher.class);
rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// add default resource:
rc.registerClasses(UserResource.class);
rc.registerClasses(PublicKeyResource.class);
rc.registerClasses(ApplicationResource.class);
rc.registerClasses(SystemConfigResource.class);
rc.registerClasses(Front.class);
rc.registerClasses(HealthCheck.class);
// add jackson to be discover when we are ins stand-alone server
rc.register(JacksonFeature.class);
// enable this to show low level request
//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Stopping server..");
server.shutdownNow();
}
}, "shutdownHook"));
// ===================================================================
// run JERSEY
// ===================================================================
try {
server.start();
System.out.println("Jersey app started at " + getBaseURI());
System.out.println("Press CTRL^C to exit..");
Thread.currentThread().join();
} catch (Exception e) {
System.out.println("There was an error while starting Grizzly HTTP server.");
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,17 @@
package org.kar.karso;
import org.kar.archidata.util.ConfigBaseVariable;
public class WebLauncherLocal {
private WebLauncherLocal() {}
public static void main(String[] args) throws InterruptedException {
if (true) {
// for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:15080/karso/api/";
ConfigBaseVariable.dbPort = "3306";
}
WebLauncher.main(args);
}
}

View File

@ -0,0 +1,182 @@
package org.kar.karso.api;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.filter.GenericContext;
import org.kar.karso.model.*;
import org.kar.archidata.util.JWTWrapper;
import org.kar.archidata.annotation.security.PermitAll;
import org.kar.archidata.annotation.security.RolesAllowed;
import java.util.List;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
@Path("/application")
@Produces( MediaType.APPLICATION_JSON)
public class ApplicationResource {
public ApplicationResource() {
}
@GET
@RolesAllowed(value= {"USER", "ADMIN"})
public List<Application> getApplications() {
System.out.println("getApplications");
try {
return SqlWrapper.gets(Application.class, false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@GET
@Path("small")
@RolesAllowed(value= {"USER", "ADMIN"})
public List<ApplicationSmall> getApplicationsSmall() {
System.out.println("getApplications");
try {
return SqlWrapper.gets(ApplicationSmall.class, false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@GET
@Path("get_token")
@RolesAllowed(value= {"USER", "ADMIN"})
public Response getClientToken(@Context SecurityContext sc, @QueryParam("application") String application) {
System.out.println("=====================================");
System.out.println("Get client Token()");
System.out.println("=====================================");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("== USER ? " + gc.user);
if (application == null) {
String result = "Input error missing parameter: 'application'";
System.out.println(" result: " + result);
return Response.status(406).entity(result).build();
}
String applicationName = application;
boolean isDev = false;
if (applicationName.endsWith("-dev")) {
applicationName = applicationName.substring(0, applicationName.length()-4);
isDev = true;
}
System.out.println("Search for '" + applicationName + "' base of '" + application + "'");
Application appl = null;
try {
appl = SqlWrapper.getWhere(Application.class, "name", "=", applicationName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "SERVER Internal error";
System.out.println(" result: " + result);
return Response.status(500).entity(result).build();
}
if (appl == null) {
String result = "Authentiocate-wrong email/login '" + applicationName + "')";
System.out.println(" result: " + result);
return Response.status(404).entity(result).build();
}
// Manage application right here...
String ret = JWTWrapper.generateJWToken(gc.user.id, gc.user.login, "KarAuth", applicationName, appl.ttl);
//System.out.println(" ==> generate token: " + ret);
String returnAdress = appl.redirect;
if (isDev) {
returnAdress = appl.redirectDev;
}
return Response.status(201).entity("{ \"url\":\"" + returnAdress + "\", \"jwt\":\"" + ret + "\"}").build();
}
@GET
@Path("return")
@RolesAllowed(value= {"USER", "ADMIN"})
public Response logOut(@Context SecurityContext sc, @QueryParam("application") String application) {
System.out.println("=====================================");
System.out.println("Get log_out()");
System.out.println("=====================================");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("== USER ? " + gc.user);
if (application == null) {
String result = "Input error missing parameter: 'application'";
System.out.println(" result: " + result);
return Response.status(406).entity(result).build();
}
String applicationName = application;
boolean isDev = false;
if (applicationName.endsWith("-dev")) {
applicationName = applicationName.substring(0, applicationName.length()-4);
isDev = true;
}
System.out.println("Search for '" + applicationName + "' base of '" + application + "'");
Application appl = null;
try {
appl = SqlWrapper.getWhere(Application.class, "name", "=", applicationName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "SERVER Internal error";
System.out.println(" result: " + result);
return Response.status(500).entity(result).build();
}
if (appl == null) {
String result = "Authentiocate-wrong email/login '" + applicationName + "')";
System.out.println(" result: " + result);
return Response.status(404).entity(result).build();
}
String returnAdress = appl.redirect;
if (isDev) {
returnAdress = appl.redirectDev;
}
return Response.status(201).entity("{ \"url\":\"" + returnAdress + "\"}").build();
}
}

View File

@ -0,0 +1,14 @@
package org.kar.karso.api;
import javax.ws.rs.*;
import org.kar.archidata.api.FrontGeneric;
import org.kar.karso.util.ConfigVariable;
@Path("/karso")
public class Front extends FrontGeneric {
public Front() {
this.baseFrontFolder = ConfigVariable.getFrontFolder();
}
}

View File

@ -0,0 +1,22 @@
package org.kar.karso.api;
import org.kar.archidata.annotation.security.PermitAll;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
@Path("/health_check")
@Produces(MediaType.APPLICATION_JSON)
public class HealthCheck {
public class HealthResult {
public String value;
public HealthResult(String value) {
this.value = value;
}
}
// todo : do it better...
@GET
@PermitAll
public HealthResult getHealth() {
return new HealthResult("alive and kicking");
}
}

View File

@ -0,0 +1,55 @@
package org.kar.karso.api;
import org.kar.archidata.util.JWTWrapper;
import org.kar.archidata.util.JWTWrapper.PublicKey;
import org.kar.archidata.annotation.security.PermitAll;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
@Path("/public_key")
@Produces(MediaType.APPLICATION_JSON)
public class PublicKeyResource {
public PublicKeyResource() {
}
// curl http://localhost:9993/public_key
@GET
@PermitAll
public PublicKey getKey() {
return new PublicKey(JWTWrapper.getPublicKey());
}
}

View File

@ -0,0 +1,102 @@
package org.kar.karso.api;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.filter.GenericContext;
import org.kar.karso.model.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.kar.archidata.util.JWTWrapper;
import org.kar.archidata.annotation.security.PermitAll;
import org.kar.archidata.annotation.security.RolesAllowed;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
@Path("/system_config")
@Produces( MediaType.APPLICATION_JSON)
public class SystemConfigResource {
public SystemConfigResource() {
}
@GET
@Path("is_sign_up_availlable")
@PermitAll
public Response isSignUpAvaillable() {
Settings set = null;
try {
set = SqlWrapper.getWhere(Settings.class, "key", "=", "SIGN_UP_ENABLE");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "SERVER Internal error";
System.out.println(" result: " + result);
return Response.status(500).entity(result).build();
}
System.out.println(" get data: " + set);
boolean availlable = "true".equalsIgnoreCase(set.value);
return Response.status(200).entity("{ \"signup\":" + availlable + "}").build();
}
@GET
@Path("key/{key}")
@RolesAllowed(value= {"USER", "ADMIN"})
public Response getKey(@Context SecurityContext sc, @PathParam("key") String key) {
Settings set = null;
try {
set = SqlWrapper.getWhere(Settings.class, "key", "=", key);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "Can not find the Key";
return Response.status(404).entity(result).build();
}
if (set.type.equals("BOOLEAN")) {
boolean availlable = "true".equalsIgnoreCase(set.value);
return Response.status(200).entity("{ \"value\":" + availlable + "}").build();
}
if (set.type.equals("NUMBER")) {
double value = Double.parseDouble(set.value);
return Response.status(200).entity("{ \"value\":" + value + "}").build();
}
return Response.status(200).entity("{ \"value\":\"" + set.value + "\"}").build();
}
@PUT
@Path("key/{key}")
@RolesAllowed(value= {"USER", "ADMIN"})
@Consumes(MediaType.APPLICATION_JSON)
public Response setKey(@Context SecurityContext sc, @PathParam("key") String key, String jsonRequest) throws Exception {
Settings res = null;
try {
res = SqlWrapper.getWhere(Settings.class, "key", "=", key);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "Can not find the Key";
return Response.status(404).entity(result).build();
}
ObjectMapper mapper = new ObjectMapper();
// Read the tree to filter injection of data:
JsonNode root = mapper.readTree(jsonRequest);
JsonNode value = root.findPath("value");
res.value = value.asText();
SqlWrapper.update(res, res.id, Arrays.asList("value"));
return Response.status(201).entity("{ \"value\":\"" + res.value + "\"}").build();
}
}

View File

@ -0,0 +1,268 @@
package org.kar.karso.api;
import org.kar.archidata.model.GetToken;
import org.kar.archidata.model.User;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.WhereCondition;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.exception.FailException;
import org.kar.archidata.exception.InputException;
import org.kar.archidata.exception.SystemException;
import org.kar.archidata.filter.GenericContext;
import org.kar.karso.model.*;
import org.kar.karso.util.ConfigVariable;
import org.kar.archidata.util.JWTWrapper;
import org.kar.archidata.annotation.security.PermitAll;
import org.kar.archidata.annotation.security.RolesAllowed;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@Path("/users")
@Produces( MediaType.APPLICATION_JSON)
public class UserResource {
public UserResource() {
}
// curl http://localhost:9993/api/users
@GET
@RolesAllowed("ADMIN")
public List<UserAuth> getUsers() throws Exception {
return SqlWrapper.gets(UserAuth.class, false);
}
// curl http://localhost:9993/api/users/3
@GET
@Path("{id}")
@RolesAllowed("ADMIN")
public UserAuth getUser(@Context SecurityContext sc, @PathParam("id") long userId) throws Exception {
GenericContext gc = (GenericContext) sc.getUserPrincipal();
return SqlWrapper.get(UserAuth.class, userId);
}
@POST
@RolesAllowed("ADMIN")
public Response createUser(UserAuth user) {
System.out.println("getUser " + user);
/*
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
String query = "SELECT * FROM user WHERE id = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, userId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
User out = new User(rs);
entry.disconnect();
return out;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
entry = null;
return null;
*/
String result = "User saved ... : " + user;
return Response.status(201).entity(result).build();
}
@GET
@Path("me")
@RolesAllowed("USER")
public User getMe(@Context SecurityContext sc) {
System.out.println("getMe()");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("== USER ? " + gc.user);
return gc.user;
}
@POST
@Path("password")
@RolesAllowed("USER")
public Response changePassword(@Context SecurityContext sc, ChangePassword data) throws Exception {
System.out.println("ChangePassword()");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("== USER ? " + gc.user);
if(data == null) {
throw new InputException("data", "No data set...");
}
if(data.password == null) {
throw new InputException("password", "null password");
}
if(data.password.length() != 128) {
throw new InputException("password", "password has not the correct hash size");
}
// TODO: check every char are in the range 0-9a-f
// with security level 1: (No e-mail system)
UserAuth user = SqlWrapper.get(UserAuth.class, gc.user.id);
if (user == null) {
throw new SystemException("Fail to retrieve the user... (impossible case)");
}
user.password = data.password;
SqlWrapper.update(user, gc.user.id, List.of("password"));
return Response.status(Response.Status.OK).build();
// With security level 2:
// TODO: Set the new password in the passwordChange
// TODO: set a uniqueID in the correct passwordValidation zone
// TODO: Set the data in the BDD
// TODO: send an e-mail
}
/*
@GET
@Path("validipass")
@PermitAll
public Response validatePasswordFromEMail(@QueryParam("uuid") String uuid, @QueryParam("securityId") String securityId) {
// Validate new password if OK
// clear the passwordChange, passwordValidation fields
// send an e-mail to confirm the new password has been set.
return Response.status(500).build();
}
*/
@GET
@Path("/check_login")
@PermitAll
public Response checkLogin(@QueryParam("login") String login) throws Exception {
System.out.println("checkLogin: " + login );
List<UserAuth> out = SqlWrapper.getsWhere(UserAuth.class, List.of(
new WhereCondition("login", "=", login)
), false);
if (out.size() >= 1) {
return Response.ok().build();
}
return Response.status(404).build();
}
@GET
@Path("/check_email")
@PermitAll
public Response checkEmail(@QueryParam("email") String email) throws Exception {
System.out.println("checkEmail: " + email );
List<UserAuth> out = SqlWrapper.getsWhere(UserAuth.class, List.of(
new WhereCondition("email", "=", email)
), false);
if (out.size() >= 1) {
return Response.ok().build();
}
return Response.status(404).build();
}
@POST
@Path("/get_token")
@PermitAll
@Consumes(MediaType.APPLICATION_JSON)
public GetToken getToken(DataGetToken data) throws Exception {
System.out.println("login: " + data.login );
// check good version:
if (!data.method.contentEquals("v1")) {
throw new InputException("method", "Authentiocate-method-error (wrong version: '" + data.method + "')");
}
// verify login or email is correct:
if (data.login.length() < 6) {
throw new InputException("login", "Authentiocate-method-error (email or login too small: '" + data.login + "')");
}
// email or login?
String query = "login";
if (data.login.contains("@")) {
query = "email";
}
UserAuth user = SqlWrapper.getWhere(UserAuth.class,
List.of(
new WhereCondition(query, "=", data.login)
),
false );
if (user == null) {
throw new FailException(Response.Status.PRECONDITION_FAILED , "FAIL Authentiocate-wrong email/login '" + data.login + "')");
}
// Check the password:
String passwodCheck = getSHA512("login='" + data.login + "';pass='" + user.password + "';date='" + data.time + "'");
if (!passwodCheck.contentEquals(data.password)) {
throw new FailException(Response.Status.PRECONDITION_FAILED , "Password error ...");
}
System.out.println(" ==> pass nearly all test : admin=" + user.admin + " blocked=" + user.blocked + " removed=" + user.removed);
if (user.blocked || user.removed) {
throw new FailException(Response.Status.UNAUTHORIZED, "FAIL Authentiocate");
}
int expirationTimeInMinutes = ConfigVariable.getAuthExpirationTime();
String ret = JWTWrapper.generateJWToken(user.id, user.login, ".", "sso", expirationTimeInMinutes);
//System.out.println(" ==> generate token: " + ret);
return new GetToken(ret);
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public String getSHA512(String passwordToHash){
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
return bytesToHex(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,60 @@
package org.kar.karso.internal;
//import io.scenarium.logger.LogLevel;
//import io.scenarium.logger.Logger;
public class Log {
// private static final String LIB_NAME = "logger";
// private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
// private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL);
// private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR);
// private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING);
// private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO);
// private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG);
// private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE);
// private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO);
// private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
//
// private Log() {}
//
// public static void print(String data) {
// if (PRINT_PRINT)
// Logger.print(LIB_NAME_DRAW, data);
// }
//
// public static void todo(String data) {
// if (PRINT_TODO)
// Logger.todo(LIB_NAME_DRAW, data);
// }
//
// public static void critical(String data) {
// if (PRINT_CRITICAL)
// Logger.critical(LIB_NAME_DRAW, data);
// }
//
// public static void error(String data) {
// if (PRINT_ERROR)
// Logger.error(LIB_NAME_DRAW, data);
// }
//
// public static void warning(String data) {
// if (PRINT_WARNING)
// Logger.warning(LIB_NAME_DRAW, data);
// }
//
// public static void info(String data) {
// if (PRINT_INFO)
// Logger.info(LIB_NAME_DRAW, data);
// }
//
// public static void debug(String data) {
// if (PRINT_DEBUG)
// Logger.debug(LIB_NAME_DRAW, data);
// }
//
// public static void verbose(String data) {
// if (PRINT_VERBOSE)
// Logger.verbose(LIB_NAME_DRAW, data);
// }
}

View File

@ -0,0 +1,62 @@
package org.kar.karso.model;
/*
CREATE TABLE `application` (
`id` bigint NOT NULL COMMENT 'Unique ID of the application' AUTO_INCREMENT PRIMARY KEY,
`description` text COMMENT 'description of the application',
`token` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'Token (can be not unique)'
) AUTO_INCREMENT=10;
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.kar.archidata.annotation.SQLAutoIncrement;
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLNotNull;
import org.kar.archidata.annotation.SQLPrimaryKey;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.GenericTable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@SQLTableName ("application")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Application extends GenericTable{
@SQLLimitSize(512)
public String name;
@SQLLimitSize(512)
public String description;
@SQLLimitSize(512)
@SQLNotNull
public String redirect;
@SQLLimitSize(512)
public String redirectDev;
@SQLLimitSize(512)
public String notification;
@SQLNotNull
@SQLComment("Expiration time ")
public int ttl;
public Application() {
}
@Override
public String toString() {
return "Application{" +
"id=" + id +
", description='" + description + '\'' +
", redirect='" + redirect + '\'' +
", redirectDev='" + redirectDev + '\'' +
", notification='" + notification + '\'' +
", ttl='" + ttl + '\'' +
'}';
}
}

View File

@ -0,0 +1,43 @@
package org.kar.karso.model;
/*
CREATE TABLE `application` (
`id` bigint NOT NULL COMMENT 'Unique ID of the application' AUTO_INCREMENT PRIMARY KEY,
`description` text COMMENT 'description of the application',
`token` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'Token (can be not unique)'
) AUTO_INCREMENT=10;
*/
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.kar.archidata.annotation.SQLAutoIncrement;
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLNotNull;
import org.kar.archidata.annotation.SQLPrimaryKey;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.GenericTable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@SQLTableName ("application")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class ApplicationSmall{
@SQLLimitSize(512)
public String name;
@SQLLimitSize(512)
public String description;
@SQLLimitSize(512)
@SQLNotNull
public String redirect;
public ApplicationSmall() {
}
}

View File

@ -0,0 +1,5 @@
package org.kar.karso.model;
public class ChangePassword {
public String password;
}

View File

@ -0,0 +1,8 @@
package org.kar.karso.model;
public class DataGetToken {
public String login;
public String method;
public String time;
public String password;
}

View File

@ -0,0 +1,5 @@
package org.kar.karso.model;
public class DataGetTokenApplication {
public String application;
}

View File

@ -0,0 +1,56 @@
package org.kar.karso.model;
/*
CREATE TABLE `application` (
`id` bigint NOT NULL COMMENT 'Unique ID of the application' AUTO_INCREMENT PRIMARY KEY,
`description` text COMMENT 'description of the application',
`token` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'Token (can be not unique)'
) AUTO_INCREMENT=10;
*/
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLDefault;
import org.kar.archidata.annotation.SQLForeignKey;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLNotNull;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.GenericTable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
enum PropertyType {
STRING,
NUMBER,
BOOLEAN,
}
@SQLTableName ("settings")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Settings extends GenericTable {
@SQLLimitSize(512)
@SQLNotNull
public String key;
@SQLComment("Right for the specific element(ADMIN [rw] USER [rw] other [rw])")
@SQLNotNull
@SQLLimitSize(6)
@SQLDefault("rw----")
public String right;
@SQLComment("Type Of the data")
@SQLNotNull
//public PropertyType type;
@SQLLimitSize(10)
public String type;
@SQLComment("Value of the configuration")
@SQLNotNull
public String value;
@Override
public String toString() {
return "Settings [key=" + key + ", value=" + value + ", id=" + id + ", deleted=" + deleted + "]";
}
}

View File

@ -0,0 +1,37 @@
package org.kar.karso.model;
import java.sql.Timestamp;
import org.kar.archidata.annotation.SQLDefault;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLNotNull;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.User;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@SQLTableName ("user")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class UserAuth extends User {
@SQLLimitSize(128)
@SQLNotNull
public String password;
/*
@SQLLimitSize(128)
public String passwordChange; //!< When change a password, the new password is set in temporary area and wait the email validation
@SQLLimitSize(128)
public String passwordValidation; //!< UniqueId to validate the new password
*/
@SQLLimitSize(512)
@SQLNotNull
public String email;
@SQLNotNull
public Timestamp emailValidate; // time of validation
@SQLLimitSize(512)
public String newEmail;
@SQLDefault("'0'")
@SQLNotNull
public boolean avatar = false;
}

View File

@ -0,0 +1,10 @@
package org.kar.karso.old;
public class Group {
// Unique ID of the group
public long id;
// Unique ID of the parent group
public long parentGroupId = -1;
// Name of the group (Must be unique)
public String groupName;
}

View File

@ -0,0 +1,21 @@
package org.kar.karso.old;
public class Package {
// Unique ID of the package/module
public long id;
// name of the package
public String name;
// version of the package
public String version;
// current coverage of the package
public double coverage;
// have module deployed
public long refBinary;
// have test deployed
public long refTest;
// have source deployed
public long refSource;
// have java-doc deployed
public long refJavaDoc;
}

View File

@ -0,0 +1,22 @@
package org.kar.karso.util;
public class ConfigVariable {
public static final String BASE_NAME = "ORG_KARAUTH_";
public static String getFrontFolder() {
String out = System.getenv(BASE_NAME + "FRONT_FOLDER");
if (out == null) {
return "/application/front";
}
return out;
}
public static int getAuthExpirationTime() {
String out = System.getenv(BASE_NAME + "AUTH_EXPIRATION_TIME");
if (out == null) {
// default expiration is 33 days for the master Oauth token
return 60*24*33;
}
return Integer.valueOf(out);
}
}

View File

@ -0,0 +1,36 @@
package test.kar.karso;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class TestBase {
@Test
public void getData() throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
//HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:5125/health_check" + System.currentTimeMillis()))
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://gitea.atria-soft.org/"))
.GET().build();
/*
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:9200/indexname/typename/" + System.currentTimeMillis()))
.POST(HttpRequest.BodyPublishers.ofString(jsonString)).setHeader("Content-Type", "application/json").build();
*/
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
Assertions.assertEquals(httpResponse.statusCode(), 200);
System.out.println("========================================");
System.out.println("retValue: " + httpResponse.statusCode());
System.out.println("response: " + httpResponse.body());
System.out.println("========================================");
}
}

32
docker-compose.yaml Normal file
View File

@ -0,0 +1,32 @@
version: '3'
services:
karauth_db_service:
image: mysql:latest
restart: always
command: --default-authentication-plugin=mysql_native_password
env_file:
- ./config.env
ports:
- 3306:3306
volumes:
- /workspace/data/global/db:/var/lib/mysql
mem_limit: 400m
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
timeout: 10s
retries: 3
karauth_adminer_service:
image: adminer:latest
restart: always
depends_on:
- karauth_db_service
# # condition: service_healthy
ports:
- 17079:8080
links:
- karauth_db_service:db
#read_only: true
mem_limit: 100m

12
front/.browserslistrc Normal file
View File

@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

13
front/.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

4
front/.eslintignore Normal file
View File

@ -0,0 +1,4 @@
node_modules/*
build/*
out/*
dist/*

241
front/.eslintrc.js Normal file
View File

@ -0,0 +1,241 @@
var OFF = 0,
WARN = 1,
ERROR = 2;
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: ['eslint:recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
rules: {
// Possible Errors (overrides from recommended set)
'no-extra-parens': ERROR,
'no-unexpected-multiline': ERROR,
// All JSDoc comments must be valid
'valid-jsdoc': [
OFF,
{
requireReturn: false,
requireReturnDescription: false,
requireParamDescription: true,
prefer: {
return: 'returns',
},
},
],
// Best Practices
// Allowed a getter without setter, but all setters require getters
'accessor-pairs': [
OFF,
{
getWithoutSet: false,
setWithoutGet: true,
},
],
'block-scoped-var': WARN,
'consistent-return': OFF,
curly: ERROR,
'default-case': WARN,
// the dot goes with the property when doing multiline
'dot-location': [WARN, 'property'],
'dot-notation': WARN,
eqeqeq: [ERROR, 'smart'],
'guard-for-in': WARN,
'no-alert': ERROR,
'no-caller': ERROR,
'no-case-declarations': WARN,
'no-div-regex': WARN,
'no-else-return': WARN,
'no-empty-pattern': WARN,
'no-eq-null': ERROR,
'no-eval': ERROR,
'no-extend-native': ERROR,
'no-extra-bind': WARN,
'no-floating-decimal': WARN,
'no-implicit-coercion': [
WARN,
{
boolean: true,
number: true,
string: true,
},
],
'no-implied-eval': ERROR,
'no-invalid-this': ERROR,
'no-iterator': ERROR,
'no-labels': WARN,
'no-lone-blocks': WARN,
'no-loop-func': ERROR,
'no-magic-numbers': OFF,
'no-multi-spaces': ERROR,
'no-multi-str': WARN,
'no-native-reassign': ERROR,
'no-new-func': ERROR,
'no-new-wrappers': ERROR,
'no-new': ERROR,
'no-octal-escape': ERROR,
'no-param-reassign': ERROR,
'no-process-env': WARN,
'no-proto': ERROR,
'no-redeclare': ERROR,
'no-return-assign': ERROR,
'no-script-url': ERROR,
'no-self-compare': ERROR,
'no-throw-literal': ERROR,
'no-unused-expressions': ERROR,
'no-useless-call': ERROR,
'no-useless-concat': ERROR,
'no-void': WARN,
// Produce warnings when something is commented as TODO or FIXME
'no-warning-comments': [
WARN,
{
terms: ['TODO', 'FIXME'],
location: 'start',
},
],
'no-with': WARN,
radix: WARN,
'vars-on-top': ERROR,
// Enforces the style of wrapped functions
'wrap-iife': [ERROR, 'outside'],
yoda: ERROR,
// Strict Mode - for ES6, never use strict.
strict: [ERROR, 'never'],
// Variables
'init-declarations': [OFF, 'always'],
'no-catch-shadow': WARN,
'no-delete-var': ERROR,
'no-label-var': ERROR,
'no-shadow-restricted-names': ERROR,
'no-shadow': WARN,
// We require all vars to be initialized (see init-declarations)
// If we NEED a var to be initialized to undefined, it needs to be explicit
'no-undef-init': OFF,
'no-undef': ERROR,
'no-undefined': OFF,
'no-unused-vars': OFF,
// Disallow hoisting - let & const don't allow hoisting anyhow
'no-use-before-define': ERROR,
// Node.js and CommonJS
'callback-return': [WARN, ['callback', 'next']],
'global-require': ERROR,
'handle-callback-err': WARN,
'no-mixed-requires': WARN,
'no-new-require': ERROR,
// Use path.concat instead
'no-path-concat': ERROR,
'no-process-exit': ERROR,
'no-restricted-modules': OFF,
'no-sync': WARN,
// ECMAScript 6 support
'arrow-body-style': [ERROR, 'always'],
'arrow-parens': [ERROR, 'always'],
'arrow-spacing': [ERROR, { before: true, after: true }],
'constructor-super': ERROR,
'generator-star-spacing': [ERROR, 'before'],
'no-confusing-arrow': ERROR,
'no-class-assign': ERROR,
'no-const-assign': ERROR,
'no-dupe-class-members': ERROR,
'no-this-before-super': ERROR,
'no-var': WARN,
'object-shorthand': [WARN, 'never'],
'prefer-arrow-callback': WARN,
'prefer-spread': WARN,
'prefer-template': WARN,
'require-yield': ERROR,
// Stylistic - everything here is a warning because of style.
'array-bracket-spacing': [WARN, 'always'],
'block-spacing': [WARN, 'always'],
'brace-style': [WARN, '1tbs', { allowSingleLine: false }],
camelcase: WARN,
'comma-spacing': [WARN, { before: false, after: true }],
'comma-style': [WARN, 'last'],
'computed-property-spacing': [WARN, 'never'],
'consistent-this': [WARN, 'self'],
'eol-last': WARN,
'func-names': WARN,
'func-style': [WARN, 'declaration'],
'id-length': [WARN, { min: 2, max: 32 }],
indent: [WARN, 'spaces'],
'jsx-quotes': [WARN, 'prefer-double'],
'linebreak-style': [WARN, 'unix'],
'lines-around-comment': [OFF, { beforeBlockComment: true }],
'max-depth': [WARN, 8],
'max-len': [WARN, 182],
'max-nested-callbacks': [WARN, 8],
'max-params': [WARN, 10],
'new-cap': OFF,
'new-parens': WARN,
'no-array-constructor': WARN,
'no-bitwise': OFF,
'no-continue': OFF,
'no-inline-comments': OFF,
'no-lonely-if': OFF,
'no-mixed-spaces-and-tabs': OFF,
'no-multiple-empty-lines': WARN,
'no-negated-condition': OFF,
'no-nested-ternary': WARN,
'no-new-object': WARN,
'no-plusplus': OFF,
'no-spaced-func': WARN,
'no-ternary': OFF,
'no-trailing-spaces': WARN,
'no-underscore-dangle': WARN,
'no-unneeded-ternary': WARN,
'object-curly-spacing': [WARN, 'always'],
'one-var': OFF,
'operator-assignment': [WARN, 'never'],
'operator-linebreak': [WARN, 'after'],
'padded-blocks': [WARN, 'never'],
'quote-props': [WARN, 'consistent-as-needed'],
quotes: [WARN, 'single'],
'require-jsdoc': [
OFF,
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: false,
},
},
],
'semi-spacing': [WARN, { before: false, after: true }],
semi: [ERROR, 'always'],
'sort-vars': OFF,
'keyword-spacing': [
WARN,
{
overrides: {
if: { after: false },
for: { after: false },
while: { after: false },
static: { after: false },
as: { after: false },
},
},
],
'space-before-blocks': [WARN, 'always'],
'space-before-function-paren': [WARN, 'never'],
'space-in-parens': [WARN, 'never'],
'space-infix-ops': [WARN, { int32Hint: true }],
'space-unary-ops': ERROR,
'spaced-comment': [WARN, 'always'],
'wrap-regex': WARN,
},
};

6
front/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/node_modules/
/.angular/
/.idea/
/test-results/
/playwright-report/
/playwright/.cache/

5
front/.prettierignore Normal file
View File

@ -0,0 +1,5 @@
.angular
coverage
httpd
node_modules
playwright-report

11
front/.prettierrc.json Normal file
View File

@ -0,0 +1,11 @@
{
"tabWidth": 4,
"useTabs": true,
"singleQuote": true,
"semi": true,
"bracketSpacing": true,
"arrowParens": "avoid",
"trailingComma": "es5",
"bracketSameLine": true,
"printWidth": 120
}

39
front/Dockerfile Normal file
View File

@ -0,0 +1,39 @@
# base image
FROM node:lts as build
# add `/application/node_modules/.bin` to $PATH
ENV PATH /application/node_modules/.bin:$PATH
ADD package-lock.json /application/
ADD package.json /application/
#ADD browserslist /application/
ADD karma.conf.js /application/
ADD protractor.conf.js /application/
WORKDIR /application/
# install and cache app dependencies
RUN npm install
ADD e2e /application/e2e
ADD tsconfig.json /application/
ADD tslint.json /application/
ADD angular.json /application/
ADD src /application/src
# generate build
RUN ng build --output-path=dist --configuration=production --base-href=/karso/ --deploy-url=/karso/
############
### prod ###
############
# base image
FROM httpd:latest
# copy artifact build from the 'build environment'
COPY --from=build /application/dist /usr/local/apache2/htdocs/
COPY httpd/httpd.conf /usr/local/apache2/conf/httpd.conf
# jules

24
front/Dockerfile.dev Normal file
View File

@ -0,0 +1,24 @@
# base image
FROM node:latest
ADD src /application/src
ADD e2e /application/e2e
ADD package-lock.json /application/
ADD package.json /application/
ADD angular.json /application/
ADD browserslist /application/
ADD karma.conf.js /application/
ADD protractor.conf.js /application/
ADD tsconfig.json /application/
ADD tslint.json /application/
WORKDIR /application/
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install and cache app dependencies
RUN npm install
# start app
CMD ["npx", "ng", "serve", "--host", "0.0.0.0"]

148
front/angular.json Normal file
View File

@ -0,0 +1,148 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"defaultProject": "karso",
"projects": {
"karso": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": ["src/assets", "src/favicon.ico"],
"styles": [
"src/styles.less",
"src/generic_page.less",
"src/theme.color.blue.less",
"src/theme.checkbox.less",
"src/theme.modal.less"
],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
"develop": {
"optimization": false,
"outputHashing": "none",
"sourceMap": true,
"namedChunks": true,
"aot": true,
"extractLicenses": true,
"vendorChunk": true,
"buildOptimizer": false
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "karso:build"
},
"configurations": {
"production": {
"browserTarget": "karso:build:production"
},
"develop": {
"browserTarget": "karso:build:develop"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "karso:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"src/styles.less",
"src/generic_page.less",
"src/theme.color.blue.less",
"src/theme.checkbox.less",
"src/theme.modal.less"
],
"assets": ["src/assets", "src/favicon.ico"]
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"fix": true,
"eslintConfig": ".eslintrc.js",
"lintFilePatterns": ["src/**/*.spec.ts", "src/**/*.ts"]
}
},
"TTTTTTlint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"],
"exclude": ["**/node_modules/**"]
}
}
}
},
"karso-e2e": {
"root": "e2e",
"sourceRoot": "e2e",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "karso:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["e2e/tsconfig.e2e.json"],
"exclude": ["**/node_modules/**"]
}
}
}
}
},
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"style": "less"
},
"@schematics/angular:directive": {
"prefix": "app"
}
},
"cli": {
"analytics": false
}
}

9
front/docker-compose.yaml Executable file
View File

@ -0,0 +1,9 @@
version: '3'
services:
karideo_service:
build: .
restart: always
image: yui.heero/karso
container_name: karso
ports:
- 15082:80

14
front/e2e/app.e2e-spec.ts Normal file
View File

@ -0,0 +1,14 @@
import { AppPage } from './app.po';
describe('karideo App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});

11
front/e2e/app.po.ts Normal file
View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@ -0,0 +1,10 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": ["jasmine", "jasminewd2", "node"]
}
}

541
front/httpd/httpd.conf Normal file
View File

@ -0,0 +1,541 @@
#
# This is the main Apache HTTP server configuration file. It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
# for a discussion of each configuration directive.
#
# Do NOT simply read the instructions in here without understanding
# what they do. They're here only as hints or reminders. If you are unsure
# consult the online docs. You have been warned.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path. If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
# will be interpreted as '/logs/access_log'.
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path. If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used. If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
ServerRoot "/usr/local/apache2"
#
# Mutex: Allows you to set the mutex mechanism and mutex file directory
# for individual mutexes, or change the global defaults
#
# Uncomment and change the directory if mutexes are file-based and the default
# mutex file directory is not on a local disk or is not appropriate for some
# other reason.
#
# Mutex default:logs
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
Listen 80
Listen 443
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule mpm_event_module modules/mod_mpm_event.so
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule authn_file_module modules/mod_authn_file.so
#LoadModule authn_dbm_module modules/mod_authn_dbm.so
#LoadModule authn_anon_module modules/mod_authn_anon.so
#LoadModule authn_dbd_module modules/mod_authn_dbd.so
#LoadModule authn_socache_module modules/mod_authn_socache.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
#LoadModule authz_dbm_module modules/mod_authz_dbm.so
#LoadModule authz_owner_module modules/mod_authz_owner.so
#LoadModule authz_dbd_module modules/mod_authz_dbd.so
LoadModule authz_core_module modules/mod_authz_core.so
#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule auth_form_module modules/mod_auth_form.so
#LoadModule auth_digest_module modules/mod_auth_digest.so
#LoadModule allowmethods_module modules/mod_allowmethods.so
#LoadModule isapi_module modules/mod_isapi.so
#LoadModule file_cache_module modules/mod_file_cache.so
#LoadModule cache_module modules/mod_cache.so
#LoadModule cache_disk_module modules/mod_cache_disk.so
#LoadModule cache_socache_module modules/mod_cache_socache.so
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule socache_dbm_module modules/mod_socache_dbm.so
#LoadModule socache_memcache_module modules/mod_socache_memcache.so
#LoadModule watchdog_module modules/mod_watchdog.so
#LoadModule macro_module modules/mod_macro.so
#LoadModule dbd_module modules/mod_dbd.so
#LoadModule bucketeer_module modules/mod_bucketeer.so
#LoadModule dumpio_module modules/mod_dumpio.so
#LoadModule echo_module modules/mod_echo.so
#LoadModule example_hooks_module modules/mod_example_hooks.so
#LoadModule case_filter_module modules/mod_case_filter.so
#LoadModule case_filter_in_module modules/mod_case_filter_in.so
#LoadModule example_ipc_module modules/mod_example_ipc.so
#LoadModule buffer_module modules/mod_buffer.so
#LoadModule data_module modules/mod_data.so
#LoadModule ratelimit_module modules/mod_ratelimit.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
#LoadModule ext_filter_module modules/mod_ext_filter.so
#LoadModule request_module modules/mod_request.so
#LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
#LoadModule reflector_module modules/mod_reflector.so
#LoadModule substitute_module modules/mod_substitute.so
#LoadModule sed_module modules/mod_sed.so
#LoadModule charset_lite_module modules/mod_charset_lite.so
#LoadModule deflate_module modules/mod_deflate.so
LoadModule xml2enc_module modules/mod_xml2enc.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule mime_module modules/mod_mime.so
#LoadModule ldap_module modules/mod_ldap.so
LoadModule log_config_module modules/mod_log_config.so
#LoadModule log_debug_module modules/mod_log_debug.so
#LoadModule log_forensic_module modules/mod_log_forensic.so
#LoadModule logio_module modules/mod_logio.so
#LoadModule lua_module modules/mod_lua.so
LoadModule env_module modules/mod_env.so
#LoadModule mime_magic_module modules/mod_mime_magic.so
#LoadModule cern_meta_module modules/mod_cern_meta.so
#LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
#LoadModule ident_module modules/mod_ident.so
#LoadModule usertrack_module modules/mod_usertrack.so
#LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
#LoadModule remoteip_module modules/mod_remoteip.so
LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#LoadModule proxy_express_module modules/mod_proxy_express.so
#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
#LoadModule session_module modules/mod_session.so
#LoadModule session_cookie_module modules/mod_session_cookie.so
#LoadModule session_crypto_module modules/mod_session_crypto.so
#LoadModule session_dbd_module modules/mod_session_dbd.so
#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
LoadModule ssl_module modules/mod_ssl.so
#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
#LoadModule dialup_module modules/mod_dialup.so
#LoadModule http2_module modules/mod_http2.so
#LoadModule proxy_http2_module modules/mod_proxy_http2.so
#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
LoadModule unixd_module modules/mod_unixd.so
#LoadModule heartbeat_module modules/mod_heartbeat.so
#LoadModule heartmonitor_module modules/mod_heartmonitor.so
#LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
#LoadModule asis_module modules/mod_asis.so
#LoadModule info_module modules/mod_info.so
#LoadModule suexec_module modules/mod_suexec.so
<IfModule !mpm_prefork_module>
#LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
#LoadModule cgi_module modules/mod_cgi.so
</IfModule>
#LoadModule dav_fs_module modules/mod_dav_fs.so
#LoadModule dav_lock_module modules/mod_dav_lock.so
#LoadModule vhost_alias_module modules/mod_vhost_alias.so
#LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
#LoadModule imagemap_module modules/mod_imagemap.so
#LoadModule actions_module modules/mod_actions.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User daemon
Group daemon
</IfModule>
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin@your-domain.com
#
ServerAdmin yui.heero@gmail.com
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80
#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
AllowOverride none
Require all denied
</Directory>
# intermediate configuration, tweak to your needs
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
<VirtualHost *:80>
ServerName my-app
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow HTML5 state links
RewriteRule ^ index.html [L]
</Directory>
</VirtualHost>
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ".ht*">
Require all denied
</Files>
#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog /proc/self/fd/2
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn
<IfModule log_config_module>
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
#
CustomLog /proc/self/fd/1 common
#
# If you prefer a logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
#CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
#
# Redirect: Allows you to tell clients about documents that used to
# exist in your server's namespace, but do not anymore. The client
# will make a new request for the document at its new location.
# Example:
# Redirect permanent /foo http://www.example.com/bar
#
# Alias: Maps web paths into filesystem paths and is used to
# access content that does not live under the DocumentRoot.
# Example:
# Alias /webpath /full/filesystem/path
#
# If you include a trailing / on /webpath then the server will
# require it to be present in the URL. You will also likely
# need to provide a <Directory> section to allow access to
# the filesystem path.
#
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the target directory are treated as applications and
# run by the server when requested rather than as documents sent to the
# client. The same rules about trailing "/" apply to ScriptAlias
# directives as to Alias.
#
ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
</IfModule>
<IfModule cgid_module>
#
# ScriptSock: On threaded servers, designate the path to the UNIX
# socket used to communicate with the CGI daemon of mod_cgid.
#
#Scriptsock cgisock
</IfModule>
#
# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/usr/local/apache2/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule headers_module>
#
# Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
# backend servers which have lingering "httpoxy" defects.
# 'Proxy' request header is undefined by the IETF, not listed by IANA
#
RequestHeader unset Proxy early
</IfModule>
<IfModule mime_module>
#
# TypesConfig points to the file containing the list of mappings from
# filename extension to MIME-type.
#
TypesConfig conf/mime.types
#
# AddType allows you to add to or override the MIME configuration
# file specified in TypesConfig for specific file types.
#
#AddType application/x-gzip .tgz
#
# AddEncoding allows you to have certain browsers uncompress
# information on the fly. Note: Not all browsers support this.
#
#AddEncoding x-compress .Z
#AddEncoding x-gzip .gz .tgz
#
# If the AddEncoding directives above are commented-out, then you
# probably should define those extensions to indicate media types:
#
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
#
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
# For type maps (negotiated resources):
#AddHandler type-map var
#
# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
#AddType text/html .shtml
#AddOutputFilter INCLUDES .shtml
</IfModule>
#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type. The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
#MIMEMagicFile conf/magic
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#
# MaxRanges: Maximum number of Ranges in a request before
# returning the entire resource, or one of the special
# values 'default', 'none' or 'unlimited'.
# Default setting is to accept 200 Ranges.
#MaxRanges unlimited
#
# EnableMMAP and EnableSendfile: On systems that support it,
# memory-mapping or the sendfile syscall may be used to deliver
# files. This usually improves server performance, but must
# be turned off when serving from networked-mounted
# filesystems or if support for these functions is otherwise
# broken on your system.
# Defaults: EnableMMAP On, EnableSendfile Off
#
#EnableMMAP off
#EnableSendfile on
# Supplemental configuration
#
# The configuration files in the conf/extra/ directory can be
# included to add extra features or to modify the default configuration of
# the server, or you may simply copy their contents here and change as
# necessary.
# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf
# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf
# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf
# Language settings
#Include conf/extra/httpd-languages.conf
# User home directories
#Include conf/extra/httpd-userdir.conf
# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf
# Virtual hosts
#Include conf/extra/httpd-vhosts.conf
# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf
# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf
# Various default settings
#Include conf/extra/httpd-default.conf
# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>
# Secure (SSL/TLS) connections
#Include conf/extra/httpd-ssl.conf
#
# Note: The following must must be present to support
# starting without SSL on platforms with no /dev/random equivalent
# but a statically compiled-in mod_ssl.
#
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

43
front/karma.conf.js Normal file
View File

@ -0,0 +1,43 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-firefox-launcher'),
//require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('karma-coverage-istanbul-reporter'),
require('karma-spec-reporter'), // reporst in console
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage'),
subdir: '.',
includeAllSources: true, // force to include all sorce to have the global report
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'json', file: 'coverage_report.json' }],
check: {
global: {
statements: 80,
branches: 80,
functions: 80,
lines: 80,
},
},
},
reporters: ['spec'], //['progress', 'html'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['FirefoxHeadless'],
singleRun: true,
});
};

24819
front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

54
front/package.json Normal file
View File

@ -0,0 +1,54 @@
{
"name": "karideo",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"all": "npm run build && npm run test",
"ng": "ng",
"start": "ng serve --configuration=develop --watch --port 4200",
"build": "ng build --prod",
"test": "ng test",
"test-coverage": "ng test --code-coverage",
"lint": "ng lint",
"style": "prettier --write .",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^14.2.10",
"@angular/cdk": "^14.2.7",
"@angular/common": "^14.2.10",
"@angular/compiler": "^14.2.10",
"@angular/core": "^14.2.10",
"@angular/forms": "^14.2.10",
"@angular/material": "^14.2.7",
"@angular/platform-browser": "^14.2.10",
"@angular/platform-browser-dynamic": "^14.2.10",
"@angular/router": "^14.2.10",
"rxjs": "^7.5.7",
"zone.js": "^0.12.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.2.9",
"@angular-eslint/builder": "14.2.0",
"@angular-eslint/eslint-plugin": "14.2.0",
"@angular-eslint/eslint-plugin-template": "14.2.0",
"@angular-eslint/schematics": "14.2.0",
"@angular-eslint/template-parser": "14.2.0",
"@angular/cli": "^14.2.9",
"@angular/compiler-cli": "^14.2.10",
"@angular/language-service": "^14.2.10",
"@playwright/test": "^1.28.1",
"@types/jest": "^29.2.4",
"jasmine": "^4.5.0",
"jasmine-core": "^4.5.0",
"karma": "^6.4.1",
"karma-coverage": "^2.2.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-firefox-launcher": "^2.1.2",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.0.0",
"karma-spec-reporter": "^0.0.36",
"prettier": "^2.8.1"
}
}

110
front/playwright.config.ts Normal file
View File

@ -0,0 +1,110 @@
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './tests',
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://localhost:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
/*
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
*/
{
name: 'firefox',
use: {
...devices['Desktop Firefox'],
},
},
/*
{
name: 'webkit',
use: {
...devices['Desktop Safari'],
},
},
*/
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: {
// ...devices['Pixel 5'],
// },
// },
// {
// name: 'Mobile Safari',
// use: {
// ...devices['iPhone 12'],
// },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: {
// channel: 'msedge',
// },
// },
// {
// name: 'Google Chrome',
// use: {
// channel: 'chrome',
// },
// },
],
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
// outputDir: 'test-results/',
/* Run your local dev server before starting the tests */
/*
webServer: {
command: 'npm run start',
port: 3000,
},*/
};
export default config;

26
front/protractor.conf.js Normal file
View File

@ -0,0 +1,26 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: ['./e2e/**/*.e2e-spec.ts'],
capabilities: {
browserName: 'chrome',
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function () {},
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json',
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
},
};

37
front/readme.md Normal file
View File

@ -0,0 +1,37 @@
Start the application:
```
npm install
```
upgrade package
```
npm audit fix
```
## npm install -g angular-cli
start the application:
```
npx ng serve --watch
```
plus facilement:
npm install @angular-devkit/build-angular@0.901.9
npm start
# Apply linter:
```
npx ng lint
```
build the local image:
docker build -t gitea.atria-soft.org/kangaroo-and-rabbit/karso:latest .
docker login gitea.atria-soft.org
docker push gitea.atria-soft.org/kangaroo-and-rabbit/karso:latest

View File

@ -0,0 +1,83 @@
/** @file
* @author Edouard DUPIN
* @copyright 2022, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; // CLI imports router
import {
ChangePasswordScene,
ForgotPasswordScene,
HelpScene,
HomeScene,
SettingsScene,
SignInScene,
SignOutScene,
SignUpScene,
HomeUnregisteredScene,
} from './scene';
import { OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome } from 'common/service/session';
import { ForbiddenScene, NotFound404Scene } from 'common/scene';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'forbidden', component: ForbiddenScene },
// ------------------------------------
// -- home global interface
// ------------------------------------
{
path: 'home',
component: HomeScene,
canActivate: [OnlyUsersGuardHome], // this route to unregistered path when not logged ==> permit to simplify display
},
{
path: 'unregistered',
component: HomeUnregisteredScene,
canActivate: [OnlyUnregisteredGuardHome], // jump to the home when registered
},
{ path: 'forgot-password', component: ForgotPasswordScene },
{ path: 'help/:page', component: HelpScene },
{ path: 'help', component: HelpScene },
{ path: 'signin', component: SignInScene },
// SSO connection mode ==> redirect to the second part data package
{ path: 'signin/:applicationId/:dataReturn', component: SignInScene },
{ path: 'signin/:applicationId', component: SignInScene },
{ path: 'signup', component: SignUpScene },
{ path: 'signup/:applicationId/:dataReturn', component: SignUpScene },
{ path: 'signup/:applicationId', component: SignUpScene },
{ path: 'signout/:applicationId/:dataReturn', component: SignOutScene },
{ path: 'signout/:applicationId', component: SignOutScene },
{ path: 'signout', component: SignOutScene },
{
path: 'password',
component: ChangePasswordScene,
canActivate: [OnlyUsersGuard],
},
{
path: 'settings',
component: SettingsScene,
canActivate: [OnlyUsersGuard],
},
{
path: '**',
component: NotFound404Scene,
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {
//enableTracing: true, // <-- debugging purposes only
}),
],
exports: [RouterModule],
})
export class AppRoutingModule {}

View File

@ -0,0 +1,6 @@
<!-- Generig global menu -->
<app-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)"></app-top-menu>
<!-- all interfaced pages -->
<div class="main-content">
<router-outlet *ngIf="autoConnectedDone"></router-outlet>
</div>

View File

@ -0,0 +1,44 @@
#create-exercice-button {
position: fixed;
display: block;
right: 0;
bottom: 0;
margin-right: 40px;
margin-bottom: 40px;
z-index: 900;
}
#save-exercice-button {
position: fixed;
display: block;
right: 0;
bottom: 0;
margin-right: 110px;
margin-bottom: 40px;
z-index: 900;
}
.main-content {
position: absolute;
//width: ~"calc(calc(100% / 5 ) * 5)";
width: 100%;
height: ~'calc(100% - 56px)';
top: 56px;
left: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
overflow-y: auto;
//background-color:#FF0;
/*
.main-reduce {
width: 40%;
height: 100%;
margin: 0;
padding: 0px 10% 0px 10%;
display: block;
overflow-y:scroll;
}
*/
}

View File

@ -0,0 +1,151 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { EventOnMenu } from 'common/component/top-menu/top-menu';
import { UserService } from 'common/service/user';
import { SessionService } from 'common/service/session';
import { MenuItem, MenuPosition } from 'common/model/menu-item';
import { SSOService } from 'common/service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less'],
})
export class AppComponent implements OnInit {
title: string = 'Karideo';
autoConnectedDone: boolean = false;
isConnected: boolean = false;
signUpEnable: boolean = true;
currentMenu: MenuItem[] = [];
constructor(
private userService: UserService,
private sessionService: SessionService,
private ssoService: SSOService
) {}
ngOnInit() {
console.log(`call with: ${window.location.href}`);
this.autoConnectedDone = false;
this.isConnected = false;
this.updateMainMenu();
let self = this;
this.sessionService.change.subscribe(isConnected => {
console.log(`receive event from session ...${isConnected}`);
self.isConnected = isConnected;
self.updateMainMenu();
});
this.userService
.checkAutoConnect()
.then(() => {
console.log(` ==>>>>> Autoconnect THEN !!!`);
self.autoConnectedDone = true;
})
.catch(error => {
console.log(` ==>>>>> Autoconnect CATCH !!! ${error}`);
self.autoConnectedDone = true;
})
.finally(() => {
console.log(` ==>>>>> Autoconnect FINALLY !!!`);
self.autoConnectedDone = true;
});
this.ssoService
.checkSignUpEnable()
.then((value: boolean) => {
console.log(`Get value signUp = ${value}`);
self.signUpEnable = value;
self.updateMainMenu();
})
.catch((error: any) => {
console.log(`Can not call the sso to check the sign-up_interface: ${error}`);
});
}
eventOnMenu(data: EventOnMenu): void {}
updateMainMenu(): void {
console.log('update main menu :');
if (this.isConnected) {
console.log(' ==> is connected');
this.currentMenu = [
{
position: MenuPosition.LEFT,
hover: `You are logged as: ${this.sessionService.getLogin()}`,
icon: 'menu',
title: 'Menu',
subMenu: [
{
position: MenuPosition.LEFT,
hover: 'Go to Home page',
icon: 'home',
title: 'Home',
navigateTo: 'home',
},
{
position: MenuPosition.LEFT,
hover: 'Change the Password of your account',
icon: 'key',
title: 'Change Password',
navigateTo: 'password',
},
/*{
position: MenuPosition.LEFT,
hover: "Change your Avatar",
icon: "account_box",
title: "Change Avatar",
navigateTo: "avatar",
}, */ {
position: MenuPosition.LEFT,
hover: 'Change Other configuration',
icon: 'settings',
title: 'Settings',
navigateTo: 'settings',
},
],
},
{
position: MenuPosition.LEFT,
hover: `You are logged as: ${this.sessionService.getLogin()}`,
title: this.sessionService.getLogin(),
},
{
position: MenuPosition.RIGHT,
hover: 'Exit connection',
icon: 'exit_to_app',
title: 'Sign out',
navigateTo: 'signout',
},
];
} else {
this.currentMenu = [
{
position: MenuPosition.LEFT,
hover: 'Go to Home page',
icon: 'home',
title: 'Home',
navigateTo: 'home',
},
{
position: MenuPosition.RIGHT,
hover: 'Create a new account',
icon: 'add_circle_outline',
title: 'Sign-up',
model: this.signUpEnable ? undefined : 'disable',
navigateTo: 'signup',
},
{
position: MenuPosition.RIGHT,
hover: 'Login page',
icon: 'account_circle',
title: 'Sign-in',
navigateTo: 'signin',
},
];
}
console.log(' ==> DONE');
}
}

116
front/src/app/app.module.ts Normal file
View File

@ -0,0 +1,116 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; // this is needed for dynamic selection of the select
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {
SignInScene,
SignUpScene,
ValidateEmailScene,
HomeScene,
ErrorViewerScene,
ForgotPasswordScene,
HelpScene,
SignOutScene,
ChangePasswordScene,
SettingsScene,
HomeUnregisteredScene,
} from 'app/scene';
import {
BddService,
CookiesService,
HttpWrapperService,
OnlyAdminGuard,
OnlyUnregisteredGuardHome,
OnlyUsersGuard,
OnlyUsersGuardHome,
PopInService,
SessionService,
SSOService,
StorageService,
UserService,
} from 'common/service';
import { CommonModule } from '@angular/common';
import { ErrorComponent, PopInComponent, TopMenuComponent, UploadFileComponent } from 'common/component';
import { ForbiddenScene } from 'common/scene';
import { AdminUserService, ApplicationService, SettingsService } from 'app/service';
import { PopInUploadProgress, PopInDeleteConfirm } from 'common/popin';
import { PasswordEntryComponent } from './component';
@NgModule({
declarations: [
AppComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
PasswordEntryComponent,
PopInComponent,
PopInUploadProgress,
PopInDeleteConfirm,
SignInScene,
SignUpScene,
SignOutScene,
ValidateEmailScene,
HomeScene,
ErrorViewerScene,
HelpScene,
ForgotPasswordScene,
SettingsScene,
ForbiddenScene,
ChangePasswordScene,
HomeUnregisteredScene,
],
imports: [
BrowserModule,
RouterModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
CommonModule,
],
// injectable element
providers: [
// application
AdminUserService,
ApplicationService,
// common
BddService,
CookiesService,
HttpWrapperService,
StorageService,
PopInService,
SessionService,
UserService,
SSOService,
SettingsService,
OnlyUsersGuard,
OnlyAdminGuard,
OnlyUsersGuardHome,
OnlyUnregisteredGuardHome,
],
exports: [
AppComponent,
TopMenuComponent,
PasswordEntryComponent,
UploadFileComponent,
ErrorComponent,
PopInComponent,
PopInUploadProgress,
PopInDeleteConfirm,
],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
})
export class AppModule {}

View File

@ -0,0 +1,5 @@
import { PasswordEntryComponent } from "./password-entry/password-entry";
export {
PasswordEntryComponent
};

View File

@ -0,0 +1,12 @@
<div class="top">
<input
[type]="passwordVisibility?'text':'password'"
[placeholder]="placeholder"
required=""
[style.border]="hasError? '2px dashed red' : ''"
[value]="value"
(input)="onChangeValue($event.target.value)" />
<button class="eye-button" (click)="onVisibility()" type="submit">
<i class="material-icons">{{passwordVisibility?"visibility":"visibility_off"}}</i>
</button>
</div>

View File

@ -0,0 +1,25 @@
.eye-button {
margin-left: -44px;
margin-top: 15px;
float: right;
position: relative;
display: block;
border: none;
z-index: 15;
background: none;
padding: 4 1 13 1;
:hover {
background: none;
}
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
z-index: 5;
}

View File

@ -0,0 +1,68 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { PasswordEntryComponent } from './password-entry';
describe('PasswordEntryComponent global test', () => {
let component: PasswordEntryComponent;
let fixture: ComponentFixture<PasswordEntryComponent>;
let input: HTMLInputElement;
let button: HTMLButtonElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PasswordEntryComponent],
}).compileComponents();
fixture = TestBed.createComponent(PasswordEntryComponent);
component = fixture.componentInstance;
input = fixture.nativeElement.querySelector('div').querySelector('input');
button = fixture.nativeElement.querySelector('div').querySelector('button');
});
it('Test mode password (default)', () => {
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
});
it('Test mode text', () => {
component.passwordVisibility = true;
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
});
it('test click on hide button', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(true);
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
}));
it('Set password', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
let tmpData = 'My beautifull Password';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
tmpData = '';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
}));
});

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-password-entry',
templateUrl: 'password-entry.html',
styleUrls: ['password-entry.less'],
})
export class PasswordEntryComponent {
/// Value of the password
@Input() value: string = '';
/// Placeholder of the Value
@Input() placeholder: string = 'Write password.';
/// The element has an error
@Input() hasError: boolean = false;
/// event when change the value of the password
@Output() changeValue: EventEmitter<string> = new EventEmitter();
/// Local value of the password viwibility
public passwordVisibility: boolean = false;
/**
* Ov visibility request change (toggle the visibility)
*/
onVisibility(): void {
this.passwordVisibility = !this.passwordVisibility;
}
/**
* When input value change, need update the display and change the internal value.
* @param newValue New value set on the password
*/
onChangeValue(newValue: string): void {
this.value = newValue;
this.changeValue.emit(this.value);
}
}

View File

@ -0,0 +1,49 @@
<div class="full">
<div class="color-background-vignette container-global">
<div class="containerCenter">
<label><b>Change Password</b></label>
</div>
<div class="imgContainer">
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar" />
</div>
<div class="container">
<!-- Previous password section -->
<label for="passwordOld"><b>Previous password</b></label>
<app-password-entry
[value]="passwordOld"
placeholder="Enter current password"
[hasError]="passwordOldState !== true"
(changeValue)="checkPasswordOld($event)"></app-password-entry>
<div class="error color-shadow-black" *ngIf="passwordOldState !== true && passwordOldState !== false">{{passwordOldState}}</div>
<!-- New password section -->
<label for="password1"><b>New password</b></label>
<app-password-entry
[value]="password1"
placeholder="Enter new password"
[hasError]="password1State !== true"
(changeValue)="checkPassword($event)"></app-password-entry>
<div class="error color-shadow-black" *ngIf="password1State !== true && password1State !== false">{{password1State}}</div>
<!-- New password section (verify) -->
<label for="password2"><b>New password (2<sup>nd</sup> time)</b></label>
<app-password-entry
[value]="password2"
placeholder="Enter new password (verify)"
[hasError]="password2State !== true"
(changeValue)="checkPassword2($event)"></app-password-entry>
<div class="error color-shadow-black" *ngIf="password2State !== true && password2State !== false">{{password2State}}</div>
</div>
<div class="container">
<button class="button cancel color-button-cancel color-shadow-black" (click)="onCancel()">Cancel</button>
<button
class="button login color-button-validate color-shadow-black"
id="login-button"
[disabled]="validateButtonDisabled"
(click)="onChangePassword()"
type="submit">
Change Password
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,84 @@
.full {
width: 100%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.login {
margin: 2% 2%;
width: 45%;
}
.cancel {
margin: 2% 2%;
width: 45%;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
}
.containerCenter {
text-align: center;
}
img.avatar {
width: 150px;
border-radius: 50%;
}
.container-global {
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}
.container {
padding: 16px 0 0 0;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}

View File

@ -0,0 +1,96 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { createPasswordState } from 'common/utils';
@Component({
selector: 'app-change-password',
templateUrl: './change-password.html',
styleUrls: ['./change-password.less'],
})
export class ChangePasswordScene {
/// status of the 3 fields:
public passwordOldState: boolean|string = false;
public password1State: boolean|string = false;
public password2State: boolean|string = false;
/// data of the 3 field
public passwordOld: string = '';
public password1: string = '';
public password2: string = '';
/// Validation button state
public validateButtonDisabled: boolean = true;
constructor(
private locate: Location
) {}
/**
* update the state of the validation button. if all is OK, the button will became clickable
*/
updateButtonVisibility(): void {
if (this.password1State === true
&& this.password2State === true
&& this.passwordOldState === true
&& this.password2 === this.password1) {
this.validateButtonDisabled = false;
} else {
this.validateButtonDisabled = true;
}
}
/**
* Check if the current password is valid or not (update error message)
* @param newValue New password value.
*/
checkPasswordOld(newValue: string): void {
this.passwordOld = newValue;
this.passwordOldState = createPasswordState(this.passwordOld);
this.checkPassword(this.password1);
this.updateButtonVisibility();
}
/**
* Check if the new password is valid or not
* @param newValue New password value.
*/
checkPassword(newValue: string): void {
this.password1 = newValue;
this.password1State = createPasswordState(this.password1);
if (this.password1State === true
&& this.passwordOld === this.password1) {
this.password1State = 'Wrong new password (identical with current)';
}
this.checkPassword2(this.password2);
this.updateButtonVisibility();
}
/**
* Check if the new password is conform with the previous one
* @param newValue New password value.
*/
checkPassword2(newValue: string): void {
this.password2 = newValue;
this.password2State = createPasswordState(this.password2);
if (this.password2State === true
&& this.password2 !== this.password1) {
this.password2State = 'Wrong 2nd password (not identical)';
}
this.updateButtonVisibility();
}
/**
* Summit change password.
*/
onChangePassword(): void {
}
/**
* Apply cancel on this page
*/
onCancel(): void {
this.locate.back();
}
}

View File

@ -0,0 +1 @@
<p>error-viewer works!</p>

View File

@ -0,0 +1,19 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-error-viewer',
templateUrl: './error-viewer.html',
styleUrls: ['./error-viewer.less'],
})
export class ErrorViewerScene implements OnInit {
constructor(private route: ActivatedRoute) {}
ngOnInit() {}
}

View File

@ -0,0 +1,43 @@
<div class="full">
<div class="color-background-vignette container-global">
<div class="containerCenter">
<label><b>Forgot Password</b></label>
</div>
<div class="imgContainer">
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar" />
</div>
<div class="container">
<label for="login_field"><b>{{loginType}}</b></label>
<input
id="username"
name="username"
type="text"
required=""
placeholder="Enter Username/e-mail"
[value]="login"
(input)="checkLogin($event.target.value)" />
<label class="container-checkbox">
I am not a robot !
<input
type="checkbox"
#notARobotCheckBox
id="notARobotCheckBox"
[checked]="notARobot"
(change)="checkIAmNotARobot(notARobotCheckBox.checked)" />
<span class="checkmark"></span>
</label>
</div>
<div class="container">
<button class="button cancel color-button-cancel color-shadow-black" (click)="onCancel()">Cancel</button>
<button
class="button login color-button-validate color-shadow-black"
id="login-button"
[disabled]="loginButtonDisabled"
(click)="onRetreive()"
type="submit">
Send e-mail
</button>
</div>
<div class="container">{{error}}</div>
</div>
</div>

View File

@ -0,0 +1,100 @@
.full {
width: 100%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
.login {
margin: 2% 2%;
width: 45%;
}
.cancel {
margin: 2% 2%;
width: 45%;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
}
img.avatar {
width: 150px;
border-radius: 50%;
}
.container-global {
padding: 16px 32px 16px 32px;
}
.container {
padding: 16px 0 0 0;
}
.containerCenter {
text-align: center;
}
span.psw {
float: right;
padding-top: 16px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}
.container-global {
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -0,0 +1,123 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { UserService } from 'common/service';
import { AdminUserService } from 'app/service';
export function checkLoginValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.-]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
export function checkEmailValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.@-]+@[a-zA-Z0-9_\\.-]+\\.[a-zA-Z]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
export function checkPasswordValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>-£€]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
@Component({
selector: 'app-forgot-password',
templateUrl: './forgot-password.html',
styleUrls: ['./forgot-password.less'],
})
export class ForgotPasswordScene implements OnInit {
public loginOK: boolean = false;
public loginHelp: string = '';
public login: string = '';
public loginButtonDisabled: boolean = true;
public error: string = '';
public loginType: string = 'Username/E-mail';
public notARobot: boolean = true;
constructor(
private router: Router,
private locate: Location,
private userService: UserService,
private adminUserService: AdminUserService
) {}
ngOnInit() {}
updateButtonVisibility(): void {
if (this.loginOK === true && this.notARobot === true) {
this.loginButtonDisabled = false;
} else {
this.loginButtonDisabled = true;
}
this.error = '';
}
checkIAmNotARobot(newValue: boolean): void {
this.notARobot = newValue;
this.updateButtonVisibility();
}
/**
* Check the login writing rules
*/
checkLogin(newValue: string): void {
console.error(`checkLogin: ${newValue}`);
this.login = newValue;
if (this.login === null) {
this.loginOK = false;
this.loginHelp = '';
this.updateButtonVisibility();
return;
}
if (this.login.length < 6) {
this.loginOK = false;
this.loginHelp = 'Need 6 characters';
this.loginType = 'Username/E-mail';
this.updateButtonVisibility();
return;
}
if (checkLoginValidity(this.login) === true) {
this.loginOK = true;
this.loginHelp = '';
this.loginType = 'Username';
} else if (checkEmailValidity(this.login) === true) {
this.loginOK = true;
this.loginHelp = '';
this.loginType = 'E-mail';
} else {
this.loginOK = false;
this.loginHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
this.updateButtonVisibility();
}
onRetreive(): void {
let self = this;
this.adminUserService
.retreivePassword(this.login)
.then(() => {
// go to the retreive page
self.router.navigate(['retreive']);
})
.catch(() => {
self.error = 'Wrong e-mail/login';
});
}
onCancel(): void {
this.locate.back();
}
}

View File

@ -0,0 +1,7 @@
<div class="generic-page">
<div class="title">Karso (SSO)</div>
<div class="fill-all colomn_mutiple">
Generic interface for login of Kar environment (SSO)
<div class="clear"></div>
</div>
</div>

View File

@ -0,0 +1,69 @@
.title {
//background-color: green;
font-size: 45px;
font-weight: bold;
line-height: 60px;
width: 100%;
align: left;
text-align: center;
vertical-align: middle;
margin: 10px 0 10px 0;
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
text-transform: uppercase;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}
.item-home {
background-color: rgba(200, 200, 200, 0.5);
font-size: 20px;
height: 190px;
width: 200px;
margin: 5px;
padding: 0;
overflow: hidden;
// box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
line-height: normal;
border: none;
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0;
will-change: box-shadow;
outline: none;
cursor: pointer;
text-decoration: none;
text-align: center;
vertical-align: middle;
transition-duration: 0.4s;
float: left;
display: block;
h1 {
font-size: 24px;
}
&:hover {
background-color: rgba(200, 200, 200, 1);
//box-shadow: 0px 2px 4px 0 rgba(255, 0, 0, 0.6);
}
.material-icons {
vertical-align: middle;
}
.material-icons {
position: absolute;
top: 50%;
left: 50%;
transform: ~'translate(-12px,-12px)';
line-height: 24px;
width: 24px;
}
}
@media all and (min-width: 1310px) {
.colomn_mutiple {
width: ~'calc(210px * 5)';
margin: auto;
}
}

View File

@ -0,0 +1,33 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-help',
templateUrl: './help.html',
styleUrls: ['./help.less'],
})
export class HelpScene implements OnInit {
page = '';
constructor(private route: ActivatedRoute) {}
ngOnInit() {
const page = this.route.snapshot.paramMap.get('page');
if (page == null) {
this.page = undefined;
} else {
this.page = page;
}
console.error(`MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`);
console.error(`get parameter update: ${this.page}`);
console.error(`MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`);
}
onSelectType(_event: any, _idSelected: number): void {}
}

View File

@ -0,0 +1,13 @@
<div class="left">
<div class="global-help">
<div class="title">Karso (SSO)</div>
</div>
</div>
<div class="right">
<div class="global-help">
<div class="image sso"><label class="unselectable">Single Sign-On for K.A.R.</label></div>
<div class="image person"><label class="unselectable">Personal authentication</label></div>
<div class="image service"><label class="unselectable">Application authentication</label></div>
<div class="image group"><label class="unselectable">Group Management</label></div>
</div>
</div>

View File

@ -0,0 +1,107 @@
.title {
font-size: 45px;
font-weight: bold;
line-height: 60px;
width: 100%;
text-align: center;
vertical-align: middle;
margin: 10px 0 10px 0;
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
text-transform: uppercase;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}
@media all and (min-width: 1250px) {
.right {
width: 50%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 50%;
height: 100%;
left: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.global-help {
position: relative;
max-width: 500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
@media all and (max-width: 1251px) {
.right {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.global-help {
//position:relative;
//max-width:500px;
padding: 16px 32px 16px 32px;
//top: 50%;
//left: 50%;
//transform: ~"translate(0, -50%)";
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
.image {
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow: 0px 0px 4px #2b3137;
color: white;
}
.sso {
background-image: url('../../../assets/images/share.svg');
}
.service {
background-image: url('../../../assets/images/lan.svg');
}
.group {
background-image: url('../../../assets/images/group.svg');
}
.person {
background-image: url('../../../assets/images/person.svg');
}

View File

@ -0,0 +1,16 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component } from '@angular/core';
@Component({
selector: 'app-home-unregistered',
templateUrl: './home-unregistered.html',
styleUrls: ['./home-unregistered.less'],
})
export class HomeUnregisteredScene {
constructor() {}
}

View File

@ -0,0 +1,14 @@
<div class="left">
<div class="global-help">
<div class="title">Karso (SSO)</div>
</div>
</div>
<div class="right">
<div class="global-help">
<div class="image" *ngFor="let data of dataList">
<button class="button" (click)="onClick($event, data)" (auxclick)="onClick($event, data)">
{{data.name}}
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,94 @@
.title {
font-size: 45px;
font-weight: bold;
line-height: 60px;
width: 100%;
text-align: center;
vertical-align: middle;
margin: 10px 0 10px 0;
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
text-transform: uppercase;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}
@media all and (min-width: 1250px) {
.right {
width: 50%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 50%;
height: 100%;
left: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.global-help {
position: relative;
max-width: 500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
@media all and (max-width: 1251px) {
.right {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.global-help {
//position:relative;
//max-width:500px;
padding: 16px 32px 16px 32px;
//top: 50%;
//left: 50%;
//transform: ~"translate(0, -50%)";
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
.image {
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow: 0px 0px 4px #2b3137;
color: white;
}

View File

@ -0,0 +1,53 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ApplicationService } from 'app/service';
import { GetApplicationSmallnResponse, SpecificTokenResponse } from 'app/service/application';
import { UserService } from 'common/service';
@Component({
selector: 'app-home',
templateUrl: './home.html',
styleUrls: ['./home.less'],
})
export class HomeScene implements OnInit {
error = '';
dataList: GetApplicationSmallnResponse[];
constructor(private applicationService: ApplicationService, private userService: UserService) {}
ngOnInit() {
let self = this;
this.applicationService
.getApplicationsSmall()
.then((data: GetApplicationSmallnResponse[]) => {
self.dataList = data;
})
.catch(error => {
console.log(`fail to keep data : ${error}`);
});
}
onClick(_event: any, data: GetApplicationSmallnResponse): void {
//window.location.href = data.redirect;
let self = this;
this.applicationService
.getApplicationSpecificToken(data.name)
.then((result: SpecificTokenResponse) => {
self.transferToApplicationThatRequiredTheSSO2(result.url, result.jwt);
})
.catch((error: any) => {
console.error(`Can not retreive the application interface: ${error}`);
});
}
private transferToApplicationThatRequiredTheSSO2(url: string, token: string): void {
if (url.slice(-1) === '/') {
url = url.slice(0, -1);
}
let ssoApplicationReturnUrl = `${url}/aG9tZQ/${this.userService.getRememberMe()}/`;
window.location.href = ssoApplicationReturnUrl + token;
}
}

View File

@ -0,0 +1,25 @@
import { ChangePasswordScene } from './change-password/change-password';
import { ErrorViewerScene } from './error-viewer/error-viewer';
import { ForgotPasswordScene } from './forgot-password/forgot-password';
import { HelpScene } from './help/help';
import { HomeUnregisteredScene } from './home-unregistered/home-unregistered';
import { HomeScene } from './home/home';
import { SettingsScene } from './settings/settings';
import { SignInScene } from './sign-in/sign-in';
import { SignOutScene } from './sign-out/sign-out';
import { SignUpScene } from './sign-up/sign-up';
import { ValidateEmailScene } from './validate-email/validate-email';
export {
ErrorViewerScene,
ForgotPasswordScene,
HelpScene,
HomeScene,
SignInScene,
SignUpScene,
SignOutScene,
ValidateEmailScene,
ChangePasswordScene,
SettingsScene,
HomeUnregisteredScene,
};

View File

@ -0,0 +1,55 @@
<div class="generic-page">
<div class="title">{{menu.title}}</div>
<div class="fill-all">
<div *ngFor="let data of menu.value">
<div class="settings-title">
<div class="group-title">{{data.title}}</div>
<div class="group-description">{{data.description}}</div>
</div>
<div class="settings-elements">
<div *ngFor="let elem of data.value" class="settings-element">
<div *ngIf="elem.type === 'LINE'">
<div class="elem-hr"></div>
</div>
<div *ngIf="elem.type === 'BOOLEAN'">
<div class="elem-checkbox">
<input
type="checkbox"
[checked]="elem.value"
(change)="changeValueElement($event.target.checked, elem, data)" />
{{elem.title}}
</div>
<div class="elem-description">{{elem.description}}</div>
</div>
<div *ngIf="elem.type === 'STRING'">
<div class="elem-title">{{elem.title}}:</div>
<div class="elem-description">{{elem.description}}</div>
<div class="elem-input">
<input
type="text"
[value]="elem.value"
(input)="changeValueElement($event.target.value, elem, data)" />
</div>
</div>
<div *ngIf="elem.type === 'PASSWORD'">
<div class="elem-title">{{elem.title}}</div>
<div class="elem-description">{{elem.description}}</div>
<div class="elem-input">
<input [value]="elem.value" />
</div>
</div>
</div>
</div>
<div class="settings-validation">
<button
class="button login color-button-validate color-shadow-black"
[disabled]="!data.newValue"
(click)="onUpdate(data)"
type="submit">
Update ...
</button>
</div>
</div>
<div class="clear"></div>
</div>
</div>

View File

@ -0,0 +1,151 @@
.settings-title {
width: 80%;
border: solid;
border-width: 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 10px 10px 0px 0px;
background-color: gray;
.group-title {
font-size: 24px;
font-weight: bold;
line-height: 24px;
vertical-align: middle;
margin: 10px 0 10px 0;
text-align: Left;
}
.group-description {
font-size: 16px;
line-height: 16px;
vertical-align: middle;
margin: 10px 0 10px 0;
text-align: Left;
}
}
.settings-elements {
width: 80%;
border: solid;
border-width: 0px 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 0px;
background-color: lightgray;
vertical-align: middle;
text-align: Left;
.elem-hr {
width: 100%;
border-color: black;
border: dashed;
border-width: 1px 0 0 0;
margin: 10px auto;
}
.elem-checkbox {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 10px;
}
.elem-title {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 36px;
}
.elem-description {
font-size: 14px;
margin: 0 20px 10px 50px;
font-style: italic;
}
.elem-input {
font-size: 14px;
margin: 0 20px 10px 36px;
input {
width: 100%;
}
}
}
.settings-validation {
width: 80%;
border: solid;
border-width: 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 0px 0px 10px 10px;
background-color: gray;
}
.title {
//background-color: green;
font-size: 45px;
font-weight: bold;
line-height: 60px;
width: 100%;
text-align: center;
vertical-align: middle;
margin: 10px 0 10px 0;
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
text-transform: uppercase;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
}
.item-home {
background-color: rgba(200, 200, 200, 0.5);
font-size: 20px;
height: 190px;
width: 200px;
margin: 5px;
padding: 0;
overflow: hidden;
// box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
line-height: normal;
border: none;
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0;
will-change: box-shadow;
outline: none;
cursor: pointer;
text-decoration: none;
text-align: center;
transition-duration: 0.4s;
float: left;
display: block;
h1 {
font-size: 24px;
}
&:hover {
background-color: rgba(200, 200, 200, 1);
//box-shadow: 0px 2px 4px 0 rgba(255, 0, 0, 0.6);
}
.material-icons {
vertical-align: middle;
}
.material-icons {
position: absolute;
top: 50%;
left: 50%;
transform: ~'translate(-12px,-12px)';
line-height: 24px;
width: 24px;
}
}
@media all and (min-width: 1310px) {
.colomn_mutiple {
width: ~'calc(210px * 5)';
margin: auto;
}
}

View File

@ -0,0 +1,189 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SettingsService } from 'app/service';
import {
isArrayOf,
isBoolean,
isInArray,
isNullOrUndefined,
isNumber,
isObject,
isOptionalArrayOf,
isOptionalOf,
isString,
isUndefined,
} from 'common/utils';
export enum SettingType {
TITLE = 'TITLE',
GROUP = 'GROUP',
LINE = 'LINE',
BOOLEAN = 'BOOLEAN',
STRING = 'STRING',
PASSWORD = 'PASSWORD',
}
export function isSettingType(data: any): data is SettingType {
return isInArray(data, ['TITLE', 'GROUP', 'LINE', 'BOOLEAN', 'STRING', 'PASSWORD']);
}
export interface SettingsItem {
// Type of the menu Node
type: SettingType;
// Displayed Title
title?: string;
// Description of the parameter
description?: string;
// Image to dsplay that describe the parameter
image?: string;
// If true the parameter is applied directly to the backend
directApply?: boolean;
// Parameter key to SET/GET
key?: string;
// Parameter key to SET/GET or the sub-menu
value?: SettingsItem[] | boolean | string | Number;
// whendata is change the value is set here:
newValue?: boolean | string | Number;
}
export function isSettingsItem(data: any): data is SettingsItem {
if (isNullOrUndefined(data)) {
return false;
}
if (!isObject(data)) {
return false;
}
if (!isSettingType(data.type)) {
return false;
}
if (!isOptionalOf(data.title, isString)) {
return false;
}
if (!isOptionalOf(data.description, isString)) {
return false;
}
if (!isOptionalOf(data.image, isString)) {
return false;
}
if (!isOptionalOf(data.directApply, isBoolean)) {
return false;
}
if (!isOptionalOf(data.key, isString)) {
return false;
}
if (
!isOptionalOf(data.value, isBoolean) &&
!isOptionalOf(data.value, isString) &&
!isOptionalOf(data.value, isNumber) &&
!isOptionalArrayOf(data.value, isSettingsItem)
) {
return false;
}
if (
!isOptionalOf(data.newValue, isBoolean) &&
!isOptionalOf(data.newValue, isString) &&
!isOptionalOf(data.newValue, isNumber)
) {
return false;
}
return true;
}
@Component({
selector: 'app-settings',
templateUrl: './settings.html',
styleUrls: ['./settings.less'],
})
export class SettingsScene implements OnInit {
page = '';
constructor(private settingService: SettingsService) {}
menu: SettingsItem = {
type: SettingType.TITLE,
title: 'Global SSO Management',
value: [
{
type: SettingType.GROUP,
title: 'Authentication:',
description: 'Manage the right of access to the web-services',
newValue: false,
value: [
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-in',
description: 'Enable User to sign-in (only authorize administrators).',
key: 'SIGN_IN_ENABLE',
value: true,
},
{
type: SettingType.LINE,
},
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-up',
description: 'Enable unregister user to sign-up (register) on this web-site.',
key: 'SIGN_UP_ENABLE',
value: false,
},
{
type: SettingType.STRING,
title: 'Sign-up e-mail filter',
description: 'Specify the e-mail filtering to sign-up (regex).',
key: 'SIGN_UP_FILTER',
value: '^.*$',
},
{
type: SettingType.BOOLEAN,
title: 'e-mail validation required',
description: 'Force-user to validate his e-mail to access on service.',
key: 'EMAIL_VALIDATION_REQUIRED',
value: false,
},
],
},
],
};
ngOnInit() {
this.settingService
.gets(['SIGN_IN_ENABLE', 'SIGN_UP_ENABLE', 'SIGN_UP_FILTER', 'EMAIL_VALIDATION_REQUIRED'])
.then((response: object) => {
console.log(`??? get full response: ${JSON.stringify(response, null, 4)}`);
})
.catch((error: any) => {
console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`);
});
}
onSelectType(_event: any, _idSelected: number): void {}
changeValueElement(newValue: string, elem: SettingsItem, parent: SettingsItem): void {
if (elem.value === newValue) {
elem.newValue = undefined;
this.updateSendNeeded(parent);
return;
}
elem.newValue = newValue;
this.updateSendNeeded(parent);
}
updateSendNeeded(parent: SettingsItem) {
if (isNullOrUndefined(parent.value)) {
return;
}
if (!isArrayOf(parent.value, isSettingsItem)) {
console.log('Error Can not convert type setting menu');
return;
}
let needUpdate = false;
for (let elem of parent.value) {
if (!isUndefined(elem.newValue)) {
needUpdate = true;
break;
}
}
parent.newValue = needUpdate;
}
onUpdate(parent: SettingsItem) {}
}

View File

@ -0,0 +1,60 @@
<div class="full">
<div class="color-background-vignette container-global">
<div class="containerCenter">
<label><b>Sign-in</b></label>
</div>
<div class="imgContainer">
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar" />
</div>
<div class="container">
<label for="login_field"><b>{{loginType}}</b></label>
<input
id="username"
name="username"
type="text"
required=""
placeholder="Enter Username/e-mail"
[value]="login"
(input)="checkLogin($event.target.value)" />
<div class="error color-shadow-black" *ngIf="loginState !== true && loginState !== false">{{loginState}}</div>
<label for="password"><b>Password</b></label> <a class="forgot" href="#">Forgot password?</a>
<app-password-entry
[value]="password"
placeholder="Enter new password (verify)"
[hasError]="passwordState !== true"
(changeValue)="checkPassword($event)"></app-password-entry>
<div class="error color-shadow-black" *ngIf="passwordState !== true && passwordState !== false">{{passwordState}}</div>
<label class="container-checkbox">
Remember me
<input
type="checkbox"
#rememberMeCheckBox
id="rememberMeCheckBox"
[checked]="rememberMe"
(change)="checkRememberMe(rememberMeCheckBox.checked)" />
<span class="checkmark"></span>
</label>
</div>
<div class="container">
<button class="button cancel color-button-cancel color-shadow-black" (click)="onCancel()">Cancel</button>
<button
class="button login color-button-validate color-shadow-black"
*ngIf="ssoReady"
id="login-button"
[disabled]="loginButtonDisabled"
(click)="onLogin()"
type="submit">
Login
</button>
<button
class="button login color-button-validate color-shadow-black"
*ngIf="!ssoReady"
[disabled]="true"
type="submit">
Login (wait info)
</button>
</div>
<div class="container">{{error}}</div>
</div>
</div>

View File

@ -0,0 +1,107 @@
.full {
width: 100%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
.login {
margin: 2% 2%;
width: 45%;
}
.cancel {
margin: 2% 2%;
width: 45%;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
}
.containerCenter {
text-align: center;
}
img.avatar {
width: 150px;
border-radius: 50%;
}
.container-global {
padding: 16px 32px 16px 32px;
}
.container {
padding: 16px 0 0 0;
}
span.psw {
float: right;
padding-top: 16px;
}
.forgot {
color: #00b;
font-size: 14px;
float: right;
buttum: 0;
line-height: 24px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}
.container-global {
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -0,0 +1,174 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Location } from '@angular/common';
import { SessionService } from 'common/service';
import { checkEmailValidity, checkLoginValidity, checkPasswordValidity, createLoginState, createPasswordState, getLoginType, isNullOrUndefined } from 'common/utils';
import { AdminUserService, ApplicationService } from 'app/service';
import { SpecificTokenResponse } from 'app/service/application';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.html',
styleUrls: ['./sign-in.less'],
})
export class SignInScene implements OnInit {
public loginState: boolean|string = false;
public login: string = '';
public passwordState: boolean|string = false;
public password: string = '';
public loginButtonDisabled: boolean = true;
public error: string = '';
public loginType: string = 'Username/E-mail';
public rememberMe: boolean = true;
public loginButtonIsClicked: boolean = false;
private ssoApplicationId: string | undefined;
private ssoReturnData: string | undefined;
private ssoApplicationReturnUrl: string | undefined;
public ssoReady: boolean = true;
constructor(
private router: Router,
private route: ActivatedRoute,
private locate: Location,
private sessionService: SessionService,
private applicationService: ApplicationService,
private adminUserService: AdminUserService
) {}
ngOnInit() {
const ssoApplicationId = this.route.snapshot.paramMap.get('applicationId');
if (isNullOrUndefined(ssoApplicationId)) {
this.ssoApplicationId = undefined;
} else {
this.ssoApplicationId = ssoApplicationId;
}
const ssoReturnData = this.route.snapshot.paramMap.get('dataReturn');
if (isNullOrUndefined(ssoReturnData)) {
this.ssoReturnData = undefined;
} else {
this.ssoReturnData = ssoReturnData;
}
// TODO: check auto-reconnection !!!
let self = this;
if (this.sessionService.islogged() == true && self.loginButtonIsClicked === false) {
// in theory it is the inly one case possible, the system loading page after retreiving session ....
if (!isNullOrUndefined(self.ssoApplicationId)) {
// detect an auto-relog...
self.transferToApplicationThatRequiredTheSSO();
}
} else {
this.sessionService.change.subscribe(isConnected => {
console.log(
`receive event from session ...${isConnected} , ssoApplicationI=${self.ssoApplicationId}, loginButtonIsClicked=${self.loginButtonIsClicked}`
);
if (isConnected === true && self.loginButtonIsClicked === false) {
if (!isNullOrUndefined(self.ssoApplicationId)) {
// detect an auto-relog...
self.transferToApplicationThatRequiredTheSSO();
}
}
});
}
}
updateButtonVisibility(): void {
if (this.loginState === true && this.passwordState === true) {
this.loginButtonDisabled = false;
} else {
this.loginButtonDisabled = true;
}
this.error = '';
}
checkRememberMe(newValue: boolean): void {
this.rememberMe = newValue;
this.updateButtonVisibility();
}
/**
* Check the login writing rules
*/
checkLogin(newValue: string): void {
this.login = newValue;
this.loginState = createLoginState(this.login);
this.loginType = getLoginType(this.login);
this.updateButtonVisibility();
}
/**
* Check the password writing rules
*/
checkPassword(newValue: string): void {
this.password = newValue;
this.passwordState = createPasswordState(this.password);
this.updateButtonVisibility();
}
onLogin(): void {
this.loginButtonIsClicked = true;
let self = this;
this.adminUserService
.login(this.login, this.password, this.rememberMe)
.then(() => {
// go to the home page
//console.log(`Request Sign-in for other application ... ==> ${self.ssoApplicationId}`);
if (!isNullOrUndefined(self.ssoApplicationId)) {
self.transferToApplicationThatRequiredTheSSO();
} else {
self.router.navigate(['home']);
}
})
.catch((error: any) => {
self.error = `Wrong e-mail/login or password: ${error}`;
});
}
private transferToApplicationThatRequiredTheSSO(): void {
let self = this;
this.applicationService
.getApplicationSpecificToken(this.ssoApplicationId)
.then((result: SpecificTokenResponse) => {
self.transferToApplicationThatRequiredTheSSO2(result.url, result.jwt);
})
.catch((error: any) => {
self.error = `Can not retreive the application interface`;
});
}
private transferToApplicationThatRequiredTheSSO2(url: string, token: string): void {
if (url.slice(-1) === '/') {
url = url.slice(0, -1);
}
if (isNullOrUndefined(this.ssoReturnData)) {
this.ssoApplicationReturnUrl = `${url}/aG9tZQ/${this.rememberMe}/`;
} else {
this.ssoApplicationReturnUrl = `${url}/${this.ssoReturnData}/${this.rememberMe}/`;
}
//console.log(`generate in new URL: ${this.ssoApplicationReturnUrl + token}`);
//this.router.navigate([ this.ssoApplicationReturnUrl+"aBeautifullToken" ], { replaceUrl: true });
window.location.href = this.ssoApplicationReturnUrl + token;
}
onCancel(): void {
//console.log(`onCancel ... '${ this.login }':'${ this.password }'`);
// go to the home page
if (this.ssoApplicationId !== undefined) {
//this.ssoApplicationReturnUrl = this.generateBaseSSOReturn(this.ssoApplicationId, this.rememberMe);
//window.location.href = this.ssoApplicationReturnUrl + "__CANCEL__";
// we can not do it anymore ==> need to be logged to know the remotre adresses !!! Otherwise it is a "security fail"
this.router.navigate(['home']);
} else {
this.locate.back();
}
}
}

View File

@ -0,0 +1,13 @@
<div class="full">
<div class="color-background-vignette container-global">
<div class="containerCenter">
<label for="login_field"><b>LOGIN (after SSO)</b></label>
</div>
<div class="imgContainer">
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar" />
</div>
<div class="container">
<label for="login_field"><b>Dis-Connected: </b> Redirect soon!</label>
</div>
</div>
</div>

View File

@ -0,0 +1,107 @@
.full {
width: 100%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
.login {
margin: 2% 2%;
width: 45%;
}
.cancel {
margin: 2% 2%;
width: 45%;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
}
.containerCenter {
text-align: center;
}
img.avatar {
width: 150px;
border-radius: 50%;
}
.container-global {
padding: 16px 32px 16px 32px;
}
.container {
padding: 16px 0 0 0;
}
span.psw {
float: right;
padding-top: 16px;
}
.forgot {
color: #00b;
font-size: 14px;
float: right;
buttum: 0;
line-height: 24px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}
.container-global {
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -0,0 +1,107 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Location } from '@angular/common';
import { UserService } from 'common/service/user';
import { isNullOrUndefined } from 'common/utils';
import { AdminUserService, ApplicationService } from 'app/service';
import { SpecificReturnResponse } from 'app/service/application';
export function checkLoginValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.-]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
export function checkEmailValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.@-]+@[a-zA-Z0-9_\\.-]+\\.[a-zA-Z]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
export function checkPasswordValidity(value: string): boolean {
let regexCheck = new RegExp('^[a-zA-Z0-9_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>-£€]+$');
if (regexCheck.test(value)) {
return true;
}
return false;
}
@Component({
selector: 'app-sign-out',
templateUrl: './sign-out.html',
styleUrls: ['./sign-out.less'],
})
export class SignOutScene implements OnInit {
private ssoApplicationId: string | undefined;
private ssoReturnData: string | undefined;
private ssoApplicationReturnUrl: string | undefined;
constructor(
private router: Router,
private route: ActivatedRoute,
private locate: Location,
private userService: UserService,
private applicationService: ApplicationService,
private adminUserService: AdminUserService
) {}
ngOnInit() {
const ssoApplicationId = this.route.snapshot.paramMap.get('applicationId');
if (ssoApplicationId == null) {
this.ssoApplicationId = undefined;
} else {
this.ssoApplicationId = ssoApplicationId;
}
const ssoReturnData = this.route.snapshot.paramMap.get('dataReturn');
if (ssoReturnData == null) {
this.ssoReturnData = undefined;
} else {
this.ssoReturnData = ssoReturnData;
}
/*
console.error(`MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`);
console.error(`get parameter update: ${this.ssoApplicationId}`);
console.error(`get parameter update: ${this.ssoReturnData}`);
console.error(`MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM`);
*/
this.logout();
}
logout(): void {
let self = this;
if (isNullOrUndefined(self.ssoApplicationId)) {
this.userService.removeSession();
this.router.navigate(['home']);
} else {
this.applicationService
.getApplicationReturn(this.ssoApplicationId)
.then((result: SpecificReturnResponse) => {
self.transferToApplicationThatRequiredTheSSO2(result.url);
})
.catch((error: any) => {
// TODO: self.error = `Can not retreive the application interface`;
this.userService.removeSession();
this.router.navigate(['home']);
});
}
}
private transferToApplicationThatRequiredTheSSO2(url: string): void {
// TODO: redirect sso caller after getting an application specific token ...
if (url.slice(-1) === '/') {
url = url.slice(0, -1);
}
this.userService.removeSession();
window.location.href = `${url}/${this.ssoReturnData}/false/__LOGOUT__`;
}
}

View File

@ -0,0 +1,84 @@
<div class="full-mode" *ngIf="!signUpEnable">
<div class="global-help">
<div class="sso"><label class="unselectable">Sign-up is disable !!! </label></div>
</div>
</div>
<div class="left" *ngIf="signUpEnable">
<div class="global-help">
<div class="sso"><label class="unselectable">Single Sign On interface (SSO)</label></div>
<div><label class="unselectable">For:</label></div>
<div class="time"><label class="unselectable">Karideo (Video streaming)</label></div>
<div class="time"><label class="unselectable">Karusic (Music streaming)</label></div>
<div class="time"><label class="unselectable">Karoto (Picture / Photo)</label></div>
<div class="comment"><label class="unselectable">Karcom (Messaging)</label></div>
<div class="time"><label class="unselectable">Karidiary (Parsonal diary)</label></div>
<!--
<div class="comment"><label class="unselectable">Rate and comment your medias</label></div>
<div class="time"><label class="unselectable">Keep last view position</label></div>
-->
</div>
</div>
<div class="right" *ngIf="signUpEnable">
<div class="modal-content color-background-vignette container-global">
<div class="logo"></div>
<div class="containerCenter">
<label><b>Sign-up</b></label>
</div>
<div class="container">
<label for="login_field"><b>Login</b></label>
<input
id="username"
name="username"
class="{{loginIcon}}"
type="text"
required=""
placeholder="Pick a Username"
[value]="login"
(input)="checkLogin($event.target.value)" />
<div class="error color-shadow-black" *ngIf="loginHelp">{{loginHelp}}</div>
<label for="login_field"><b>E-mail</b></label>
<input
id="email"
name="e-mail"
class="{{emailIcon}}"
type="text"
required=""
placeholder="you@example.com"
[value]="email"
(input)="checkEmail($event.target.value)" />
<div class="error color-shadow-black" *ngIf="emailHelp">{{emailHelp}}</div>
<label for="password"><b>Password</b></label>
<input
type="password"
id="password"
name="password"
class="{{passIcon}}"
placeholder="Enter Password"
required=""
[value]="password"
(input)="checkPassword($event.target.value)" />
<div class="error color-shadow-black" *ngIf="passHelp">{{passHelp}}</div>
</div>
<div class="container">
<button
class="button fill-x color-button-validate color-shadow-black"
id="onSignUp-button"
[disabled]="signUpButtonDisabled"
(click)="onSignUp()"
type="submit">
<i class="material-icons">mode_edit</i> Sign up for Karideo
</button>
</div>
<div class="container commmon-policy">
By clicking "Sign up for Karideo", you agree to our <a href="help/terms">terms of service</a> and
<a href="help/privacy">privacy policy</a>.<br />
Well occasionally send you account related emails.
</div>
<div class="container">
<a class="forgot" href="forgot-password">Forgot password?</a>
</div>
<div class="container">{{error}}</div>
</div>
</div>

View File

@ -0,0 +1,217 @@
.sso {
background-image: url('../../../assets/images/share.svg');
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow: 0px 0px 4px #2b3137;
color: white;
}
.comment {
background-image: url('../../../assets/images/comments.svg');
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow: 0px 0px 4px #2b3137;
color: white;
}
.time {
background-image: url('../../../assets/images/time.svg');
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow: 0px 0px 4px #2b3137;
color: white;
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 35px 12px 15px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
@media all and (min-width: 1250px) {
.right {
width: 50%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 50%;
height: 100%;
left: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.global-help {
position: relative;
max-width: 500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
@media all and (max-width: 1251px) {
.right {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
.left {
width: 100%;
top: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
visibility: hidden;
}
.global-help {
//position:relative;
//max-width:500px;
padding: 16px 32px 16px 32px;
//top: 50%;
//left: 50%;
//transform: ~"translate(0, -50%)";
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
}
.full-mode {
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
padding: 0;
border: 0;
float: left;
display: block;
}
.container-global {
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}
.container {
padding: 16px 0 0 0;
}
.containerCenter {
text-align: center;
}
span.psw {
float: right;
padding-top: 16px;
}
.help {
color: #e44;
font-size: 14px;
}
.forgot {
color: #00b;
font-size: 14px;
float: right;
bottom: 0;
line-height: 24px;
}
.commmon-policy {
font-size: 13px;
font-weight: 300;
text-align: center;
}
.icon-right-load {
background: white url('../../../assets/images/load.svg') right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.icon-right-validate {
background: white url('../../../assets/images/validate.svg') right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.icon-right-not-validate {
background: white url('../../../assets/images/validate-not.svg') right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}

View File

@ -0,0 +1,238 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { SSOService, UserService } from 'common/service';
import { AdminUserService } from 'app/service';
import { checkLoginValidity, checkEmailValidity, checkPasswordValidity } from '../forgot-password/forgot-password';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.html',
styleUrls: ['./sign-up.less'],
})
export class SignUpScene implements OnInit {
private signUpIconWrong: string = 'icon-right-not-validate';
private signUpIconWait: string = 'icon-right-load';
private signUpIconRight: string = 'icon-right-validate';
public login: string = '';
public loginOK: boolean = false;
public loginHelp: string = '';
public loginIcon: string = '';
public email: string = '';
public emailOK: boolean = false;
public emailHelp: string = '';
public emailIcon: string = '';
public password: string = '';
public passOK: boolean = false;
public passHelp: string = '';
public passIcon: string = '';
public signUpButtonDisabled: boolean = true;
public error: string = '';
public rememberMe: boolean = true;
public signUpEnable: boolean = true;
constructor(
private userService: UserService,
private router: Router,
private ssoService: SSOService,
private adminUserService: AdminUserService
) {
this.signUpEnable = false;
}
ngOnInit() {
let self = this;
this.signUpEnable = false;
this.ssoService
.checkSignUpEnable()
.then((value: boolean) => {
console.log(`Get value signUp = ${value}`);
self.signUpEnable = value;
})
.catch((error: any) => {
self.error = `Can not call the sso to check the sign-up_interface: ${error}`;
});
}
updateButtonVisibility(): void {
if (this.loginOK === true && this.passOK === true && this.emailOK === true) {
this.signUpButtonDisabled = false;
} else {
this.signUpButtonDisabled = true;
}
this.error = '';
}
checkLogin(newValue: string): void {
// this.userService.loginSha("loooogin", "ekljkj", true);
this.login = newValue;
if (this.login === null || this.login.length === 0) {
this.loginOK = false;
this.loginIcon = '';
//this.loginIcon = this.signUpIconWrong;
this.loginHelp = '';
this.updateButtonVisibility();
return;
}
if (this.login.length < 6) {
this.loginOK = false;
this.loginHelp = 'Need 6 characters';
this.loginIcon = this.signUpIconWrong;
this.updateButtonVisibility();
return;
}
if (checkLoginValidity(this.login) === true) {
this.loginOK = false;
// this.loginHelp = "check in progress...";
this.loginIcon = this.signUpIconWait;
let self = this;
this.adminUserService
.checkLogin(this.login)
.then((isNotUsed: boolean) => {
// check if the answer is correct with the question
if (newValue !== self.login) {
return;
}
if (isNotUsed === false) {
// the login exist ... ==> it is found...
self.loginOK = false;
self.loginHelp = 'Login already used ...';
self.loginIcon = self.signUpIconWrong;
self.updateButtonVisibility();
} else {
self.loginOK = true;
self.loginHelp = '';
self.loginIcon = self.signUpIconRight;
self.updateButtonVisibility();
return;
}
})
.catch((error: number) => {
console.log(`Status ${error}`);
self.loginOK = false;
self.loginHelp = 'ErrorOccured in fetching data ...';
self.loginIcon = self.signUpIconWrong;
self.updateButtonVisibility();
});
} else {
this.loginOK = false;
this.loginHelp = 'Not valid: characters, numbers and "_-."';
}
this.updateButtonVisibility();
}
checkEmail(newValue: string): void {
this.email = newValue;
if (this.email === null || this.email.length === 0) {
this.emailOK = false;
this.updateButtonVisibility();
this.emailIcon = '';
this.emailHelp = '';
return;
}
if (this.email.length < 6) {
this.emailOK = false;
this.emailHelp = 'Need 6 characters';
this.updateButtonVisibility();
this.passIcon = '';
this.emailIcon = this.signUpIconWrong;
return;
}
if (checkEmailValidity(this.email) === true) {
this.emailOK = false;
this.emailHelp = '';
// this.loginHelp = "check in progress...";
this.emailIcon = this.signUpIconWait;
let self = this;
this.adminUserService.checkEMail(this.email).then(
(isNotUsed: boolean) => {
// check if the answer is correct with the question
if (newValue !== self.email) {
return;
}
if (isNotUsed === false) {
// the email exist ... ==> it is found...
self.emailOK = false;
self.emailHelp = 'email already used ...';
self.emailIcon = self.signUpIconWrong;
self.updateButtonVisibility();
} else {
self.emailOK = true;
self.emailHelp = '';
self.emailIcon = self.signUpIconRight;
self.updateButtonVisibility();
return;
}
},
(error: number) => {
console.log(`Status ${error}`);
self.emailOK = false;
self.emailHelp = 'ErrorOccured in fetching data ...';
self.emailIcon = self.signUpIconWrong;
self.updateButtonVisibility();
}
);
} else {
this.emailOK = false;
this.emailHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
this.updateButtonVisibility();
}
checkPassword(newValue: string): void {
this.password = newValue;
//console.log(`ooooooooooooooo ${ this.password}`);
if (this.password === null) {
this.passOK = false;
this.passHelp = '';
this.updateButtonVisibility();
return;
}
if (this.password.length < 6) {
this.passOK = false;
this.passHelp = 'Need 6 characters';
} else if (checkPasswordValidity(this.password) === true) {
this.passOK = true;
this.passHelp = '';
} else {
this.passOK = false;
this.passHelp = 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\\<>"';
}
this.updateButtonVisibility();
}
onSignUp(): void {
console.log('Validate ... ');
if (this.signUpButtonDisabled === true) {
// ... notify user ...
console.log('Not permited action ... ==> control does not validate this action ...');
return;
}
let self = this;
// disable the currect button
this.signUpButtonDisabled = true;
this.userService.create(this.login, this.email, this.password).then(
value => {
console.log('User created');
self.router.navigate(['login']);
// send a generic message in the pop-up enevts... self.emailHelp = "email already used ... (error 2)";
},
value => {
console.log('User NOT created');
// send a generic message in the pop-up enevts... self.emailHelp = "email already used ... (error 2)";
}
);
}
onCancel(): void {
console.log(`onCancel ... '${this.login}':'${this.password}'`);
// $rootScope.currentModal = "";
}
}

View File

@ -0,0 +1,20 @@
<div class="sign" ng-controller="controlerValidateEmail">
<div class="full-back">
<div class="global-help">
<i class="material-icons big-one">email</i>
<div>Waiting email validation ...</div>
</div>
</div>
<button
class="button sender color-button-validate color-shadow-light"
ng-disabled="syncButtonDisabled"
(click)="onSend()">
<i class="material-icons">send</i> re-send the validation code.
</button>
<button
class="button last-update color-button-normal color-shadow-light"
ng-disabled="sendButtonDisabled"
(click)="onCheck()">
<i class="material-icons">loop</i> 18h15
</button>
</div>

Some files were not shown because too many files have changed in this diff Show More