├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jhipster ├── Album.json ├── Photo.json └── Tag.json ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── .yo-rc.json ├── LICENSE ├── Procfile ├── README.md ├── gallery.jh ├── mvnw ├── mvnw.cmd ├── package.json ├── pom.xml ├── src ├── main │ ├── docker │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── app.yml │ │ ├── entrypoint.sh │ │ ├── keycloak.yml │ │ ├── postgresql.yml │ │ ├── realm-config │ │ │ ├── jhipster-realm.json │ │ │ └── jhipster-users-0.json │ │ └── sonar.yml │ ├── java │ │ └── com │ │ │ └── okta │ │ │ └── developer │ │ │ ├── ApplicationWebXml.java │ │ │ ├── GalleryApp.java │ │ │ ├── aop │ │ │ └── logging │ │ │ │ └── LoggingAspect.java │ │ │ ├── config │ │ │ ├── ApplicationProperties.java │ │ │ ├── AsyncConfiguration.java │ │ │ ├── CacheConfiguration.java │ │ │ ├── CloudDatabaseConfiguration.java │ │ │ ├── Constants.java │ │ │ ├── DatabaseConfiguration.java │ │ │ ├── DateTimeFormatConfiguration.java │ │ │ ├── DefaultProfileUtil.java │ │ │ ├── JacksonConfiguration.java │ │ │ ├── LocaleConfiguration.java │ │ │ ├── LoggingAspectConfiguration.java │ │ │ ├── LoggingConfiguration.java │ │ │ ├── MetricsConfiguration.java │ │ │ ├── OAuth2Configuration.java │ │ │ ├── SecurityConfiguration.java │ │ │ ├── WebConfigurer.java │ │ │ ├── audit │ │ │ │ ├── AuditEventConverter.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── domain │ │ │ ├── AbstractAuditingEntity.java │ │ │ ├── Album.java │ │ │ ├── Authority.java │ │ │ ├── PersistentAuditEvent.java │ │ │ ├── Photo.java │ │ │ ├── Tag.java │ │ │ ├── User.java │ │ │ └── package-info.java │ │ │ ├── repository │ │ │ ├── AlbumRepository.java │ │ │ ├── AuthorityRepository.java │ │ │ ├── CustomAuditEventRepository.java │ │ │ ├── PersistenceAuditEventRepository.java │ │ │ ├── PhotoRepository.java │ │ │ ├── TagRepository.java │ │ │ ├── UserRepository.java │ │ │ └── package-info.java │ │ │ ├── security │ │ │ ├── AuthoritiesConstants.java │ │ │ ├── OAuth2AuthenticationSuccessHandler.java │ │ │ ├── SecurityUtils.java │ │ │ ├── SpringSecurityAuditorAware.java │ │ │ └── package-info.java │ │ │ ├── service │ │ │ ├── AuditEventService.java │ │ │ ├── UserService.java │ │ │ ├── dto │ │ │ │ ├── UserDTO.java │ │ │ │ └── package-info.java │ │ │ ├── mapper │ │ │ │ ├── UserMapper.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ └── web │ │ │ └── rest │ │ │ ├── AccountResource.java │ │ │ ├── AlbumResource.java │ │ │ ├── AuditResource.java │ │ │ ├── LogsResource.java │ │ │ ├── PhotoResource.java │ │ │ ├── TagResource.java │ │ │ ├── UserResource.java │ │ │ ├── errors │ │ │ ├── BadRequestAlertException.java │ │ │ ├── CustomParameterizedException.java │ │ │ ├── EmailAlreadyUsedException.java │ │ │ ├── EmailNotFoundException.java │ │ │ ├── ErrorConstants.java │ │ │ ├── ExceptionTranslator.java │ │ │ ├── FieldErrorVM.java │ │ │ ├── InternalServerErrorException.java │ │ │ ├── InvalidPasswordException.java │ │ │ ├── LoginAlreadyUsedException.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── util │ │ │ ├── HeaderUtil.java │ │ │ └── PaginationUtil.java │ │ │ └── vm │ │ │ ├── LoggerVM.java │ │ │ ├── ManagedUserVM.java │ │ │ └── package-info.java │ ├── resources │ │ ├── .h2.server.properties │ │ ├── banner.txt │ │ ├── config │ │ │ ├── application-dev.yml │ │ │ ├── application-heroku.yml │ │ │ ├── application-prod.yml │ │ │ ├── application.yml │ │ │ ├── bootstrap-heroku.yml │ │ │ └── liquibase │ │ │ │ ├── authorities.csv │ │ │ │ ├── changelog │ │ │ │ ├── 00000000000000_initial_schema.xml │ │ │ │ ├── 20180625042224_added_entity_Album.xml │ │ │ │ ├── 20180625042224_added_entity_constraints_Album.xml │ │ │ │ ├── 20180625042225_added_entity_Photo.xml │ │ │ │ ├── 20180625042225_added_entity_constraints_Photo.xml │ │ │ │ └── 20180625042226_added_entity_Tag.xml │ │ │ │ ├── master.xml │ │ │ │ ├── users.csv │ │ │ │ └── users_authorities.csv │ │ ├── i18n │ │ │ ├── messages.properties │ │ │ ├── messages_en.properties │ │ │ └── messages_fr.properties │ │ ├── logback-spring.xml │ │ └── templates │ │ │ └── error.html │ └── webapp │ │ ├── 404.html │ │ ├── app │ │ ├── app.css │ │ ├── app.tsx │ │ ├── config │ │ │ ├── axios-interceptor.ts │ │ │ ├── constants.ts │ │ │ ├── devtools.tsx │ │ │ ├── error-middleware.ts │ │ │ ├── icon-loader.ts │ │ │ ├── logger-middleware.ts │ │ │ ├── notification-middleware.ts │ │ │ ├── store.ts │ │ │ └── translation.ts │ │ ├── entities │ │ │ ├── album │ │ │ │ ├── album-delete-dialog.tsx │ │ │ │ ├── album-detail.tsx │ │ │ │ ├── album-update.tsx │ │ │ │ ├── album.reducer.ts │ │ │ │ ├── album.tsx │ │ │ │ └── index.tsx │ │ │ ├── index.tsx │ │ │ ├── photo │ │ │ │ ├── index.tsx │ │ │ │ ├── photo-delete-dialog.tsx │ │ │ │ ├── photo-detail.tsx │ │ │ │ ├── photo-update.tsx │ │ │ │ ├── photo.reducer.ts │ │ │ │ └── photo.tsx │ │ │ └── tag │ │ │ │ ├── index.tsx │ │ │ │ ├── tag-delete-dialog.tsx │ │ │ │ ├── tag-detail.tsx │ │ │ │ ├── tag-update.tsx │ │ │ │ ├── tag.reducer.ts │ │ │ │ └── tag.tsx │ │ ├── index.tsx │ │ ├── modules │ │ │ ├── administration │ │ │ │ ├── administration.reducer.ts │ │ │ │ ├── audits │ │ │ │ │ └── audits.tsx │ │ │ │ ├── configuration │ │ │ │ │ └── configuration.tsx │ │ │ │ ├── docs │ │ │ │ │ └── docs.tsx │ │ │ │ ├── health │ │ │ │ │ ├── health-modal.tsx │ │ │ │ │ └── health.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── logs │ │ │ │ │ └── logs.tsx │ │ │ │ └── metrics │ │ │ │ │ ├── metrics-modal.tsx │ │ │ │ │ ├── metrics.tsx │ │ │ │ │ └── thread-item.tsx │ │ │ ├── home │ │ │ │ ├── home.css │ │ │ │ └── home.tsx │ │ │ └── login │ │ │ │ └── logout.tsx │ │ ├── routes.tsx │ │ ├── shared │ │ │ ├── auth │ │ │ │ └── private-route.tsx │ │ │ ├── error │ │ │ │ ├── error-boundary-route.tsx │ │ │ │ └── error-boundary.tsx │ │ │ ├── layout │ │ │ │ ├── footer │ │ │ │ │ ├── footer.css │ │ │ │ │ └── footer.tsx │ │ │ │ ├── header │ │ │ │ │ ├── header-components.tsx │ │ │ │ │ ├── header.css │ │ │ │ │ ├── header.tsx │ │ │ │ │ └── menus │ │ │ │ │ │ ├── account.tsx │ │ │ │ │ │ ├── admin.tsx │ │ │ │ │ │ ├── entities.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── locale.tsx │ │ │ │ └── password │ │ │ │ │ ├── password-strength-bar.css │ │ │ │ │ └── password-strength-bar.tsx │ │ │ ├── model │ │ │ │ ├── album.model.ts │ │ │ │ ├── photo.model.ts │ │ │ │ ├── tag.model.ts │ │ │ │ └── user.model.ts │ │ │ ├── reducers │ │ │ │ ├── action-type.util.ts │ │ │ │ ├── application-profile.ts │ │ │ │ ├── authentication.ts │ │ │ │ ├── index.ts │ │ │ │ ├── locale.ts │ │ │ │ └── user-management.ts │ │ │ └── util │ │ │ │ ├── date-utils.ts │ │ │ │ ├── entity-utils.ts │ │ │ │ ├── pagination.constants.ts │ │ │ │ └── url-utils.ts │ │ └── typings.d.ts │ │ ├── favicon.ico │ │ ├── i18n │ │ ├── en │ │ │ ├── activate.json │ │ │ ├── album.json │ │ │ ├── audits.json │ │ │ ├── configuration.json │ │ │ ├── error.json │ │ │ ├── gateway.json │ │ │ ├── global.json │ │ │ ├── health.json │ │ │ ├── home.json │ │ │ ├── login.json │ │ │ ├── logs.json │ │ │ ├── metrics.json │ │ │ ├── password.json │ │ │ ├── photo.json │ │ │ ├── register.json │ │ │ ├── reset.json │ │ │ ├── sessions.json │ │ │ ├── settings.json │ │ │ ├── tag.json │ │ │ └── user-management.json │ │ └── fr │ │ │ ├── activate.json │ │ │ ├── album.json │ │ │ ├── audits.json │ │ │ ├── configuration.json │ │ │ ├── error.json │ │ │ ├── gateway.json │ │ │ ├── global.json │ │ │ ├── health.json │ │ │ ├── home.json │ │ │ ├── login.json │ │ │ ├── logs.json │ │ │ ├── metrics.json │ │ │ ├── password.json │ │ │ ├── photo.json │ │ │ ├── register.json │ │ │ ├── reset.json │ │ │ ├── sessions.json │ │ │ ├── settings.json │ │ │ ├── tag.json │ │ │ └── user-management.json │ │ ├── index.html │ │ ├── manifest.webapp │ │ ├── robots.txt │ │ ├── static │ │ └── images │ │ │ ├── hipster.png │ │ │ ├── hipster192.png │ │ │ ├── hipster256.png │ │ │ ├── hipster2x.png │ │ │ ├── hipster384.png │ │ │ ├── hipster512.png │ │ │ ├── logo-jhipster-react.svg │ │ │ └── logo-jhipster.png │ │ └── swagger-ui │ │ ├── dist │ │ └── images │ │ │ └── throbber.gif │ │ └── index.html └── test │ ├── java │ └── com │ │ └── okta │ │ └── developer │ │ ├── config │ │ ├── WebConfigurerTest.java │ │ └── WebConfigurerTestController.java │ │ ├── repository │ │ └── CustomAuditEventRepositoryIntTest.java │ │ ├── security │ │ └── SecurityUtilsUnitTest.java │ │ ├── service │ │ └── UserServiceIntTest.java │ │ └── web │ │ └── rest │ │ ├── AccountResourceIntTest.java │ │ ├── AlbumResourceIntTest.java │ │ ├── AuditResourceIntTest.java │ │ ├── LogsResourceIntTest.java │ │ ├── PhotoResourceIntTest.java │ │ ├── TagResourceIntTest.java │ │ ├── TestUtil.java │ │ ├── UserResourceIntTest.java │ │ ├── errors │ │ ├── ExceptionTranslatorIntTest.java │ │ └── ExceptionTranslatorTestController.java │ │ └── util │ │ └── PaginationUtilUnitTest.java │ ├── javascript │ ├── e2e │ │ ├── entities │ │ │ ├── album │ │ │ │ ├── album-update.page-object.ts │ │ │ │ ├── album.page-object.ts │ │ │ │ └── album.spec.ts │ │ │ ├── photo │ │ │ │ ├── photo-update.page-object.ts │ │ │ │ ├── photo.page-object.ts │ │ │ │ └── photo.spec.ts │ │ │ └── tag │ │ │ │ ├── tag-update.page-object.ts │ │ │ │ ├── tag.page-object.ts │ │ │ │ └── tag.spec.ts │ │ ├── modules │ │ │ ├── account │ │ │ │ └── account.spec.ts │ │ │ └── administration │ │ │ │ └── administration.spec.ts │ │ ├── page-objects │ │ │ ├── base-component.ts │ │ │ ├── navbar-page.ts │ │ │ └── signin-page.ts │ │ └── util │ │ │ └── utils.ts │ ├── enzyme-setup.ts │ ├── jest.conf.js │ ├── protractor.conf.js │ ├── spec │ │ └── app │ │ │ ├── config │ │ │ └── notification-middleware.spec.ts │ │ │ ├── entities │ │ │ ├── album │ │ │ │ └── album-reducer.spec.ts │ │ │ ├── photo │ │ │ │ └── photo-reducer.spec.ts │ │ │ └── tag │ │ │ │ └── tag-reducer.spec.ts │ │ │ ├── modules │ │ │ └── administration │ │ │ │ └── administration.reducer.spec.ts │ │ │ ├── shared │ │ │ ├── auth │ │ │ │ └── private-route.spec.tsx │ │ │ ├── error │ │ │ │ ├── error-boundary-route.spec.tsx │ │ │ │ └── error-boundary.spec.tsx │ │ │ ├── layout │ │ │ │ └── header │ │ │ │ │ ├── header.spec.tsx │ │ │ │ │ └── menus │ │ │ │ │ └── account.spec.tsx │ │ │ ├── reducers │ │ │ │ ├── application-profile.spec.ts │ │ │ │ ├── authentication.spec.ts │ │ │ │ └── user-management.spec.ts │ │ │ └── util │ │ │ │ └── entity-utils.spec.ts │ │ │ └── utils.ts │ ├── storage-mock.ts │ └── tsconfig.e2e.json │ └── resources │ ├── config │ └── application.yml │ └── logback.xml ├── tsconfig.json ├── tslint.json ├── webpack ├── logo-jhipster.png ├── utils.js ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 4 12 | max_line_length = 180 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.{ts,tsx,js,jsx,json,css,scss,sql,ejs}] 21 | indent_style = space 22 | indent_size = 2 23 | 24 | [*.md] 25 | trim_trailing_whitespace = false 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ###################### 2 | # Project Specific 3 | ###################### 4 | /target/www/** 5 | /src/test/javascript/coverage/ 6 | 7 | ###################### 8 | # Node 9 | ###################### 10 | /node/ 11 | node_tmp/ 12 | node_modules/ 13 | npm-debug.log.* 14 | /.awcache/* 15 | /.cache-loader/* 16 | 17 | ###################### 18 | # SASS 19 | ###################### 20 | .sass-cache/ 21 | 22 | ###################### 23 | # Eclipse 24 | ###################### 25 | *.pydevproject 26 | .project 27 | .metadata 28 | tmp/ 29 | tmp/**/* 30 | *.tmp 31 | *.bak 32 | *.swp 33 | *~.nib 34 | local.properties 35 | .classpath 36 | .settings/ 37 | .loadpath 38 | .factorypath 39 | /src/main/resources/rebel.xml 40 | 41 | # External tool builders 42 | .externalToolBuilders/** 43 | 44 | # Locally stored "Eclipse launch configurations" 45 | *.launch 46 | 47 | # CDT-specific 48 | .cproject 49 | 50 | # PDT-specific 51 | .buildpath 52 | 53 | ###################### 54 | # Intellij 55 | ###################### 56 | .idea/ 57 | *.iml 58 | *.iws 59 | *.ipr 60 | *.ids 61 | *.orig 62 | classes/ 63 | out/ 64 | 65 | ###################### 66 | # Visual Studio Code 67 | ###################### 68 | .vscode/ 69 | 70 | ###################### 71 | # Maven 72 | ###################### 73 | /log/ 74 | /target/ 75 | 76 | ###################### 77 | # Gradle 78 | ###################### 79 | .gradle/ 80 | /build/ 81 | 82 | ###################### 83 | # Package Files 84 | ###################### 85 | *.jar 86 | *.war 87 | *.ear 88 | *.db 89 | 90 | ###################### 91 | # Windows 92 | ###################### 93 | # Windows image file caches 94 | Thumbs.db 95 | 96 | # Folder config file 97 | Desktop.ini 98 | 99 | ###################### 100 | # Mac OSX 101 | ###################### 102 | .DS_Store 103 | .svn 104 | 105 | # Thumbnails 106 | ._* 107 | 108 | # Files that might appear on external disk 109 | .Spotlight-V100 110 | .Trashes 111 | 112 | ###################### 113 | # Directories 114 | ###################### 115 | /bin/ 116 | /deploy/ 117 | 118 | ###################### 119 | # Logs 120 | ###################### 121 | *.log* 122 | 123 | ###################### 124 | # Others 125 | ###################### 126 | *.class 127 | *.*~ 128 | *~ 129 | .merge_file* 130 | 131 | ###################### 132 | # Gradle Wrapper 133 | ###################### 134 | !gradle/wrapper/gradle-wrapper.jar 135 | 136 | ###################### 137 | # Maven Wrapper 138 | ###################### 139 | !.mvn/wrapper/maven-wrapper.jar 140 | 141 | ###################### 142 | # ESLint 143 | ###################### 144 | .eslintcache 145 | -------------------------------------------------------------------------------- /.jhipster/Album.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Album", 3 | "fields": [ 4 | { 5 | "fieldName": "title", 6 | "fieldType": "String", 7 | "fieldValidateRules": [ 8 | "required" 9 | ] 10 | }, 11 | { 12 | "fieldName": "description", 13 | "fieldType": "byte[]", 14 | "fieldTypeBlobContent": "text" 15 | }, 16 | { 17 | "fieldName": "created", 18 | "fieldType": "Instant" 19 | } 20 | ], 21 | "relationships": [ 22 | { 23 | "relationshipType": "many-to-one", 24 | "relationshipName": "user", 25 | "otherEntityName": "user", 26 | "otherEntityField": "login" 27 | } 28 | ], 29 | "changelogDate": "20180625042224", 30 | "entityTableName": "album", 31 | "dto": "no", 32 | "pagination": "pagination", 33 | "service": "no", 34 | "jpaMetamodelFiltering": false, 35 | "fluentMethods": true, 36 | "clientRootFolder": "", 37 | "applications": "*" 38 | } -------------------------------------------------------------------------------- /.jhipster/Photo.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Photo", 3 | "fields": [ 4 | { 5 | "fieldName": "title", 6 | "fieldType": "String", 7 | "fieldValidateRules": [ 8 | "required" 9 | ] 10 | }, 11 | { 12 | "fieldName": "description", 13 | "fieldType": "byte[]", 14 | "fieldTypeBlobContent": "text" 15 | }, 16 | { 17 | "fieldName": "image", 18 | "fieldType": "byte[]", 19 | "fieldTypeBlobContent": "image", 20 | "fieldValidateRules": [ 21 | "required" 22 | ] 23 | }, 24 | { 25 | "fieldName": "height", 26 | "fieldType": "Integer" 27 | }, 28 | { 29 | "fieldName": "width", 30 | "fieldType": "Integer" 31 | }, 32 | { 33 | "fieldName": "taken", 34 | "fieldType": "Instant" 35 | }, 36 | { 37 | "fieldName": "uploaded", 38 | "fieldType": "Instant" 39 | } 40 | ], 41 | "relationships": [ 42 | { 43 | "relationshipType": "many-to-one", 44 | "relationshipName": "album", 45 | "otherEntityName": "album", 46 | "otherEntityField": "title" 47 | }, 48 | { 49 | "relationshipType": "many-to-many", 50 | "otherEntityRelationshipName": "photo", 51 | "relationshipName": "tag", 52 | "otherEntityName": "tag", 53 | "otherEntityField": "name", 54 | "ownerSide": true 55 | } 56 | ], 57 | "changelogDate": "20180625042225", 58 | "entityTableName": "photo", 59 | "dto": "no", 60 | "pagination": "infinite-scroll", 61 | "service": "no", 62 | "jpaMetamodelFiltering": false, 63 | "fluentMethods": true, 64 | "clientRootFolder": "", 65 | "applications": "*" 66 | } -------------------------------------------------------------------------------- /.jhipster/Tag.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tag", 3 | "fields": [ 4 | { 5 | "fieldName": "name", 6 | "fieldType": "String", 7 | "fieldValidateRules": [ 8 | "required", 9 | "minlength" 10 | ], 11 | "fieldValidateRulesMinlength": 2 12 | } 13 | ], 14 | "relationships": [ 15 | { 16 | "relationshipType": "many-to-many", 17 | "relationshipName": "photo", 18 | "otherEntityName": "photo", 19 | "ownerSide": false, 20 | "otherEntityRelationshipName": "tag" 21 | } 22 | ], 23 | "changelogDate": "20180625042226", 24 | "entityTableName": "tag", 25 | "dto": "no", 26 | "pagination": "infinite-scroll", 27 | "service": "no", 28 | "jpaMetamodelFiltering": false, 29 | "fluentMethods": true, 30 | "clientRootFolder": "", 31 | "applications": "*" 32 | } -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oktadev/okta-react-photo-gallery-example/c0ba0bbfbcd66ca20c7a2637e8fbf6a18892a0f3/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | target 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | # Prettier configuration 2 | 3 | printWidth: 140 4 | singleQuote: true 5 | tabWidth: 2 6 | useTabs: false 7 | 8 | # js and ts rules: 9 | arrowParens: avoid 10 | 11 | # jsx and tsx rules: 12 | jsxBracketSameLine: false 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | services: 4 | - docker 5 | language: node_js 6 | node_js: 7 | - 8.11.2 8 | jdk: 9 | - oraclejdk8 10 | sudo: false 11 | cache: 12 | directories: 13 | - node 14 | - node_modules 15 | - "$HOME/.m2" 16 | - "$HOME/.yarn-cache" 17 | env: 18 | global: 19 | - NODE_VERSION=8.11.2 20 | - SPRING_OUTPUT_ANSI_ENABLED=ALWAYS 21 | - SPRING_JPA_SHOW_SQL=false 22 | before_install: 23 | - jdk_switcher use oraclejdk8 24 | - java -version 25 | - sudo /etc/init.d/mysql stop 26 | - sudo /etc/init.d/postgresql stop 27 | - curl -o- -L https://yarnpkg.com/install.sh | bash 28 | - export PATH=$HOME/.yarn/bin:$PATH 29 | install: 30 | - yarn install 31 | script: 32 | - chmod +x mvnw 33 | - "./mvnw clean test" 34 | - yarn test 35 | notifications: 36 | webhooks: 37 | on_success: change 38 | on_failure: always 39 | on_start: false -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-jhipster": { 3 | "promptValues": { 4 | "packageName": "com.okta.developer", 5 | "nativeLanguage": "en" 6 | }, 7 | "jhipsterVersion": "5.0.1", 8 | "applicationType": "monolith", 9 | "baseName": "gallery", 10 | "packageName": "com.okta.developer", 11 | "packageFolder": "com/okta/developer", 12 | "serverPort": "8080", 13 | "authenticationType": "oauth2", 14 | "cacheProvider": "ehcache", 15 | "enableHibernateCache": true, 16 | "websocket": false, 17 | "databaseType": "sql", 18 | "devDatabaseType": "h2Disk", 19 | "prodDatabaseType": "postgresql", 20 | "searchEngine": false, 21 | "messageBroker": false, 22 | "serviceDiscoveryType": false, 23 | "buildTool": "maven", 24 | "enableSwaggerCodegen": false, 25 | "clientFramework": "react", 26 | "useSass": false, 27 | "clientPackageManager": "yarn", 28 | "testFrameworks": [ 29 | "protractor" 30 | ], 31 | "jhiPrefix": "jhi", 32 | "enableTranslation": true, 33 | "nativeLanguage": "en", 34 | "languages": [ 35 | "en", 36 | "fr" 37 | ], 38 | "herokuDeployType": "git", 39 | "herokuAppName": "gallery-pwa" 40 | } 41 | } -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: java $JAVA_OPTS -Xmx256m -jar target/*.war --spring.profiles.active=prod,heroku --server.port=$PORT 2 | -------------------------------------------------------------------------------- /gallery.jh: -------------------------------------------------------------------------------- 1 | entity Album { 2 | title String required, 3 | description TextBlob, 4 | created Instant 5 | } 6 | 7 | entity Photo { 8 | title String required, 9 | description TextBlob, 10 | image ImageBlob required, 11 | height Integer, 12 | width Integer, 13 | taken Instant, 14 | uploaded Instant 15 | } 16 | 17 | entity Tag { 18 | name String required minlength(2) 19 | } 20 | 21 | relationship ManyToOne { 22 | Album{user(login)} to User, 23 | Photo{album(title)} to Album 24 | } 25 | 26 | relationship ManyToMany { 27 | Photo{tag(name)} to Tag{photo} 28 | } 29 | 30 | paginate Album with pagination 31 | paginate Photo, Tag with infinite-scroll 32 | -------------------------------------------------------------------------------- /src/main/docker/.dockerignore: -------------------------------------------------------------------------------- 1 | # https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | classes/ 3 | generated-sources/ 4 | generated-test-sources/ 5 | h2db/ 6 | maven-archiver/ 7 | maven-status/ 8 | reports/ 9 | surefire-reports/ 10 | test-classes/ 11 | test-results/ 12 | www/ 13 | !*.jar 14 | !*.war 15 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | 3 | ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \ 4 | JHIPSTER_SLEEP=0 \ 5 | JAVA_OPTS="" 6 | 7 | # Add a jhipster user to run our application so that it doesn't need to run as root 8 | RUN adduser -D -s /bin/sh jhipster 9 | WORKDIR /home/jhipster 10 | 11 | ADD entrypoint.sh entrypoint.sh 12 | RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh 13 | USER jhipster 14 | 15 | ADD *.war app.war 16 | 17 | ENTRYPOINT ["./entrypoint.sh"] 18 | 19 | EXPOSE 8080 20 | 21 | -------------------------------------------------------------------------------- /src/main/docker/app.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | gallery-app: 4 | image: gallery 5 | environment: 6 | # - _JAVA_OPTIONS=-Xmx512m -Xms256m 7 | - SPRING_PROFILES_ACTIVE=prod,swagger 8 | - SPRING_DATASOURCE_URL=jdbc:postgresql://gallery-postgresql:5432/gallery 9 | - SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI=http://keycloak:9080/auth/realms/jhipster/protocol/openid-connect/token 10 | - SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI=http://keycloak:9080/auth/realms/jhipster/protocol/openid-connect/auth 11 | - SECURITY_OAUTH2_CLIENT_CLIENT_ID=web_app 12 | - SECURITY_OAUTH2_CLIENT_CLIENT_SECRET=web_app 13 | - SECURITY_OAUTH2_CLIENT_SCOPE=openid profile email 14 | - SECURITY_OAUTH2_RESOURCE_USER_INFO_URI=http://keycloak:9080/auth/realms/jhipster/protocol/openid-connect/userinfo 15 | - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application 16 | ports: 17 | - 8080:8080 18 | gallery-postgresql: 19 | extends: 20 | file: postgresql.yml 21 | service: gallery-postgresql 22 | keycloak: 23 | extends: 24 | file: keycloak.yml 25 | service: keycloak 26 | -------------------------------------------------------------------------------- /src/main/docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP} 4 | exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar "${HOME}/app.war" "$@" 5 | -------------------------------------------------------------------------------- /src/main/docker/keycloak.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | keycloak: 4 | image: jboss/keycloak:4.0.0.Final 5 | command: ["-b", "0.0.0.0", "-Dkeycloak.migration.action=import", "-Dkeycloak.migration.provider=dir", "-Dkeycloak.migration.dir=/opt/jboss/keycloak/realm-config", "-Dkeycloak.migration.strategy=OVERWRITE_EXISTING", "-Djboss.socket.binding.port-offset=1000"] 6 | volumes: 7 | - ./realm-config:/opt/jboss/keycloak/realm-config 8 | environment: 9 | - KEYCLOAK_USER=admin 10 | - KEYCLOAK_PASSWORD=admin 11 | - DB_VENDOR=h2 12 | ports: 13 | - 9080:9080 14 | - 9443:9443 15 | - 10990:10990 16 | -------------------------------------------------------------------------------- /src/main/docker/postgresql.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | gallery-postgresql: 4 | image: postgres:10.4 5 | # volumes: 6 | # - ~/volumes/jhipster/gallery/postgresql/:/var/lib/postgresql/data/ 7 | environment: 8 | - POSTGRES_USER=gallery 9 | - POSTGRES_PASSWORD= 10 | ports: 11 | - 5432:5432 12 | -------------------------------------------------------------------------------- /src/main/docker/realm-config/jhipster-users-0.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm" : "jhipster", 3 | "users" : [ { 4 | "id" : "4c973896-5761-41fc-8217-07c5d13a004b", 5 | "createdTimestamp" : 1505479415590, 6 | "username" : "admin", 7 | "enabled" : true, 8 | "totp" : false, 9 | "emailVerified" : true, 10 | "firstName" : "Admin", 11 | "lastName" : "Administrator", 12 | "email" : "admin@localhost", 13 | "credentials" : [ { 14 | "type" : "password", 15 | "hashedSaltedValue" : "4pf9K2jWSCcHC+CwsZP/qidN5pSmDUe6AX6wBerSGdBVKkExay8MWKx+EKmaaObZW6FVsD8vdW/ZsyUFD9gJ1Q==", 16 | "salt" : "1/qNkZ5kr77jOMOBPBogGw==", 17 | "hashIterations" : 27500, 18 | "counter" : 0, 19 | "algorithm" : "pbkdf2-sha256", 20 | "digits" : 0, 21 | "period" : 0, 22 | "createdDate" : 1505479429154, 23 | "config" : { } 24 | } ], 25 | "disableableCredentialTypes" : [ "password" ], 26 | "requiredActions" : [ ], 27 | "realmRoles" : [ "offline_access", "uma_authorization" ], 28 | "clientRoles" : { 29 | "account" : [ "view-profile", "manage-account" ] 30 | }, 31 | "notBefore" : 0, 32 | "groups" : [ "/Users", "/Admins" ] 33 | }, { 34 | "id" : "c4af4e2f-b432-4c3b-8405-cca86cd5b97b", 35 | "createdTimestamp" : 1505479373742, 36 | "username" : "user", 37 | "enabled" : true, 38 | "totp" : false, 39 | "emailVerified" : true, 40 | "firstName" : "", 41 | "lastName" : "User", 42 | "email" : "user@localhost", 43 | "credentials" : [ { 44 | "type" : "password", 45 | "hashedSaltedValue" : "MbKsMgWPnZyImih8s4SaoCSCq+XIY/c6S9F93sXEidHF1TjPWxCqMkec0+o3860CMLXHt3az61cIJOWI0FW9aw==", 46 | "salt" : "fmpBI1r8R1u75hDLMUlwBw==", 47 | "hashIterations" : 27500, 48 | "counter" : 0, 49 | "algorithm" : "pbkdf2-sha256", 50 | "digits" : 0, 51 | "period" : 0, 52 | "createdDate" : 1505479392766, 53 | "config" : { } 54 | } ], 55 | "disableableCredentialTypes" : [ "password" ], 56 | "requiredActions" : [ ], 57 | "realmRoles" : [ "offline_access", "uma_authorization" ], 58 | "clientRoles" : { 59 | "account" : [ "view-profile", "manage-account" ] 60 | }, 61 | "notBefore" : 0, 62 | "groups" : [ "/Users" ] 63 | } ] 64 | } 65 | -------------------------------------------------------------------------------- /src/main/docker/sonar.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | gallery-sonar: 4 | image: sonarqube:7.1-alpine 5 | ports: 6 | - 9000:9000 7 | - 9092:9092 8 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/ApplicationWebXml.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer; 2 | 3 | import com.okta.developer.config.DefaultProfileUtil; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 6 | 7 | /** 8 | * This is a helper Java class that provides an alternative to creating a web.xml. 9 | * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc. 10 | */ 11 | public class ApplicationWebXml extends SpringBootServletInitializer { 12 | 13 | @Override 14 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 15 | /** 16 | * set a default to use when no profile is configured. 17 | */ 18 | DefaultProfileUtil.addDefaultProfile(application.application()); 19 | return application.sources(GalleryApp.class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/ApplicationProperties.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | /** 6 | * Properties specific to Gallery. 7 | *

8 | * Properties are configured in the application.yml file. 9 | * See {@link io.github.jhipster.config.JHipsterProperties} for a good example. 10 | */ 11 | @ConfigurationProperties(prefix = "application", ignoreUnknownFields = false) 12 | public class ApplicationProperties { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/AsyncConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor; 4 | import io.github.jhipster.config.JHipsterProperties; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 9 | import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.scheduling.annotation.*; 13 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 14 | 15 | import java.util.concurrent.Executor; 16 | 17 | @Configuration 18 | @EnableAsync 19 | @EnableScheduling 20 | public class AsyncConfiguration implements AsyncConfigurer { 21 | 22 | private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class); 23 | 24 | private final JHipsterProperties jHipsterProperties; 25 | 26 | public AsyncConfiguration(JHipsterProperties jHipsterProperties) { 27 | this.jHipsterProperties = jHipsterProperties; 28 | } 29 | 30 | @Override 31 | @Bean(name = "taskExecutor") 32 | public Executor getAsyncExecutor() { 33 | log.debug("Creating Async Task Executor"); 34 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 35 | executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize()); 36 | executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize()); 37 | executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity()); 38 | executor.setThreadNamePrefix("gallery-Executor-"); 39 | return new ExceptionHandlingAsyncTaskExecutor(executor); 40 | } 41 | 42 | @Override 43 | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 44 | return new SimpleAsyncUncaughtExceptionHandler(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/CloudDatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import io.github.jhipster.config.JHipsterConstants; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.cloud.config.java.AbstractCloudConfig; 8 | import org.springframework.context.annotation.*; 9 | 10 | import javax.sql.DataSource; 11 | 12 | @Configuration 13 | @Profile(JHipsterConstants.SPRING_PROFILE_CLOUD) 14 | public class CloudDatabaseConfiguration extends AbstractCloudConfig { 15 | 16 | private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class); 17 | 18 | @Bean 19 | public DataSource dataSource() { 20 | log.info("Configuring JDBC datasource from a cloud provider"); 21 | return connectionFactory().dataSource(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/Constants.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | /** 4 | * Application constants. 5 | */ 6 | public final class Constants { 7 | 8 | // Regex for acceptable logins 9 | public static final String LOGIN_REGEX = "^[_.@A-Za-z0-9-]*$"; 10 | 11 | public static final String SYSTEM_ACCOUNT = "system"; 12 | public static final String ANONYMOUS_USER = "anonymoususer"; 13 | public static final String DEFAULT_LANGUAGE = "en"; 14 | 15 | private Constants() { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/DateTimeFormatConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.format.FormatterRegistry; 5 | import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | public class DateTimeFormatConfiguration implements WebMvcConfigurer { 10 | 11 | @Override 12 | public void addFormatters(FormatterRegistry registry) { 13 | DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); 14 | registrar.setUseIsoFormat(true); 15 | registrar.registerFormatters(registry); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/DefaultProfileUtil.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import io.github.jhipster.config.JHipsterConstants; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.core.env.Environment; 7 | 8 | import java.util.*; 9 | 10 | /** 11 | * Utility class to load a Spring profile to be used as default 12 | * when there is no spring.profiles.active set in the environment or as command line argument. 13 | * If the value is not available in application.yml then dev profile will be used as default. 14 | */ 15 | public final class DefaultProfileUtil { 16 | 17 | private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default"; 18 | 19 | private DefaultProfileUtil() { 20 | } 21 | 22 | /** 23 | * Set a default to use when no profile is configured. 24 | * 25 | * @param app the Spring application 26 | */ 27 | public static void addDefaultProfile(SpringApplication app) { 28 | Map defProperties = new HashMap<>(); 29 | /* 30 | * The default profile to use when no other profiles are defined 31 | * This cannot be set in the application.yml file. 32 | * See https://github.com/spring-projects/spring-boot/issues/1219 33 | */ 34 | defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT); 35 | app.setDefaultProperties(defProperties); 36 | } 37 | 38 | /** 39 | * Get the profiles that are applied else get default profiles. 40 | * 41 | * @param env spring environment 42 | * @return profiles 43 | */ 44 | public static String[] getActiveProfiles(Environment env) { 45 | String[] profiles = env.getActiveProfiles(); 46 | if (profiles.length == 0) { 47 | return env.getDefaultProfiles(); 48 | } 49 | return profiles; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/JacksonConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; 4 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 5 | 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.zalando.problem.ProblemModule; 9 | import org.zalando.problem.validation.ConstraintViolationProblemModule; 10 | 11 | @Configuration 12 | public class JacksonConfiguration { 13 | 14 | /* 15 | * Support for Hibernate types in Jackson. 16 | */ 17 | @Bean 18 | public Hibernate5Module hibernate5Module() { 19 | return new Hibernate5Module(); 20 | } 21 | 22 | /* 23 | * Jackson Afterburner module to speed up serialization/deserialization. 24 | */ 25 | @Bean 26 | public AfterburnerModule afterburnerModule() { 27 | return new AfterburnerModule(); 28 | } 29 | 30 | /* 31 | * Module for serialization/deserialization of RFC7807 Problem. 32 | */ 33 | @Bean 34 | ProblemModule problemModule() { 35 | return new ProblemModule(); 36 | } 37 | 38 | /* 39 | * Module for serialization/deserialization of ConstraintViolationProblem. 40 | */ 41 | @Bean 42 | ConstraintViolationProblemModule constraintViolationProblemModule() { 43 | return new ConstraintViolationProblemModule(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/LocaleConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import io.github.jhipster.config.locale.AngularCookieLocaleResolver; 4 | 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.servlet.LocaleResolver; 8 | import org.springframework.web.servlet.config.annotation.*; 9 | import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; 10 | 11 | @Configuration 12 | public class LocaleConfiguration implements WebMvcConfigurer { 13 | 14 | @Bean(name = "localeResolver") 15 | public LocaleResolver localeResolver() { 16 | AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver(); 17 | cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY"); 18 | return cookieLocaleResolver; 19 | } 20 | 21 | @Override 22 | public void addInterceptors(InterceptorRegistry registry) { 23 | LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); 24 | localeChangeInterceptor.setParamName("language"); 25 | registry.addInterceptor(localeChangeInterceptor); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/LoggingAspectConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.config; 2 | 3 | import com.okta.developer.aop.logging.LoggingAspect; 4 | 5 | import io.github.jhipster.config.JHipsterConstants; 6 | 7 | import org.springframework.context.annotation.*; 8 | import org.springframework.core.env.Environment; 9 | 10 | @Configuration 11 | @EnableAspectJAutoProxy 12 | public class LoggingAspectConfiguration { 13 | 14 | @Bean 15 | @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) 16 | public LoggingAspect loggingAspect(Environment env) { 17 | return new LoggingAspect(env); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/audit/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Audit specific code. 3 | */ 4 | package com.okta.developer.config.audit; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/config/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring Framework configuration files. 3 | */ 4 | package com.okta.developer.config; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/domain/AbstractAuditingEntity.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import org.hibernate.envers.Audited; 7 | import org.springframework.data.annotation.CreatedBy; 8 | import org.springframework.data.annotation.CreatedDate; 9 | import org.springframework.data.annotation.LastModifiedBy; 10 | import org.springframework.data.annotation.LastModifiedDate; 11 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 12 | import java.time.Instant; 13 | import javax.persistence.Column; 14 | import javax.persistence.EntityListeners; 15 | import javax.persistence.MappedSuperclass; 16 | 17 | /** 18 | * Base abstract class for entities which will hold definitions for created, last modified by and created, 19 | * last modified by date. 20 | */ 21 | @MappedSuperclass 22 | @Audited 23 | @EntityListeners(AuditingEntityListener.class) 24 | public abstract class AbstractAuditingEntity implements Serializable { 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | @CreatedBy 29 | @Column(name = "created_by", nullable = false, length = 50, updatable = false) 30 | @JsonIgnore 31 | private String createdBy; 32 | 33 | @CreatedDate 34 | @Column(name = "created_date", nullable = false, updatable = false) 35 | @JsonIgnore 36 | private Instant createdDate = Instant.now(); 37 | 38 | @LastModifiedBy 39 | @Column(name = "last_modified_by", length = 50) 40 | @JsonIgnore 41 | private String lastModifiedBy; 42 | 43 | @LastModifiedDate 44 | @Column(name = "last_modified_date") 45 | @JsonIgnore 46 | private Instant lastModifiedDate = Instant.now(); 47 | 48 | public String getCreatedBy() { 49 | return createdBy; 50 | } 51 | 52 | public void setCreatedBy(String createdBy) { 53 | this.createdBy = createdBy; 54 | } 55 | 56 | public Instant getCreatedDate() { 57 | return createdDate; 58 | } 59 | 60 | public void setCreatedDate(Instant createdDate) { 61 | this.createdDate = createdDate; 62 | } 63 | 64 | public String getLastModifiedBy() { 65 | return lastModifiedBy; 66 | } 67 | 68 | public void setLastModifiedBy(String lastModifiedBy) { 69 | this.lastModifiedBy = lastModifiedBy; 70 | } 71 | 72 | public Instant getLastModifiedDate() { 73 | return lastModifiedDate; 74 | } 75 | 76 | public void setLastModifiedDate(Instant lastModifiedDate) { 77 | this.lastModifiedDate = lastModifiedDate; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/domain/Authority.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.domain; 2 | 3 | import org.hibernate.annotations.Cache; 4 | import org.hibernate.annotations.CacheConcurrencyStrategy; 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | import javax.persistence.Table; 8 | import javax.persistence.Column; 9 | import javax.validation.constraints.NotNull; 10 | import javax.validation.constraints.Size; 11 | import java.io.Serializable; 12 | 13 | /** 14 | * An authority (a security role) used by Spring Security. 15 | */ 16 | @Entity 17 | @Table(name = "jhi_authority") 18 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 19 | public class Authority implements Serializable { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @NotNull 24 | @Size(max = 50) 25 | @Id 26 | @Column(length = 50) 27 | private String name; 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | @Override 38 | public boolean equals(Object o) { 39 | if (this == o) { 40 | return true; 41 | } 42 | if (o == null || getClass() != o.getClass()) { 43 | return false; 44 | } 45 | 46 | Authority authority = (Authority) o; 47 | 48 | return !(name != null ? !name.equals(authority.name) : authority.name != null); 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return name != null ? name.hashCode() : 0; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "Authority{" + 59 | "name='" + name + '\'' + 60 | "}"; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/domain/PersistentAuditEvent.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.domain; 2 | 3 | import javax.persistence.*; 4 | import javax.validation.constraints.NotNull; 5 | import java.io.Serializable; 6 | import java.time.Instant; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * Persist AuditEvent managed by the Spring Boot actuator. 12 | * 13 | * @see org.springframework.boot.actuate.audit.AuditEvent 14 | */ 15 | @Entity 16 | @Table(name = "jhi_persistent_audit_event") 17 | public class PersistentAuditEvent implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") 23 | @SequenceGenerator(name = "sequenceGenerator") 24 | @Column(name = "event_id") 25 | private Long id; 26 | 27 | @NotNull 28 | @Column(nullable = false) 29 | private String principal; 30 | 31 | @Column(name = "event_date") 32 | private Instant auditEventDate; 33 | 34 | @Column(name = "event_type") 35 | private String auditEventType; 36 | 37 | @ElementCollection 38 | @MapKeyColumn(name = "name") 39 | @Column(name = "value") 40 | @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id")) 41 | private Map data = new HashMap<>(); 42 | 43 | public Long getId() { 44 | return id; 45 | } 46 | 47 | public void setId(Long id) { 48 | this.id = id; 49 | } 50 | 51 | public String getPrincipal() { 52 | return principal; 53 | } 54 | 55 | public void setPrincipal(String principal) { 56 | this.principal = principal; 57 | } 58 | 59 | public Instant getAuditEventDate() { 60 | return auditEventDate; 61 | } 62 | 63 | public void setAuditEventDate(Instant auditEventDate) { 64 | this.auditEventDate = auditEventDate; 65 | } 66 | 67 | public String getAuditEventType() { 68 | return auditEventType; 69 | } 70 | 71 | public void setAuditEventType(String auditEventType) { 72 | this.auditEventType = auditEventType; 73 | } 74 | 75 | public Map getData() { 76 | return data; 77 | } 78 | 79 | public void setData(Map data) { 80 | this.data = data; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/domain/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JPA domain objects. 3 | */ 4 | package com.okta.developer.domain; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/AlbumRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.Album; 4 | import org.springframework.data.jpa.repository.*; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Spring Data repository for the Album entity. 11 | */ 12 | @SuppressWarnings("unused") 13 | @Repository 14 | public interface AlbumRepository extends JpaRepository { 15 | 16 | @Query("select album from Album album where album.user.login = ?#{principal.username}") 17 | List findByUserIsCurrentUser(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/AuthorityRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.Authority; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | /** 8 | * Spring Data JPA repository for the Authority entity. 9 | */ 10 | public interface AuthorityRepository extends JpaRepository { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/PersistenceAuditEventRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.PersistentAuditEvent; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import java.time.Instant; 9 | import java.util.List; 10 | 11 | /** 12 | * Spring Data JPA repository for the PersistentAuditEvent entity. 13 | */ 14 | public interface PersistenceAuditEventRepository extends JpaRepository { 15 | 16 | List findByPrincipal(String principal); 17 | 18 | List findByAuditEventDateAfter(Instant after); 19 | 20 | List findByPrincipalAndAuditEventDateAfter(String principal, Instant after); 21 | 22 | List findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principle, Instant after, String type); 23 | 24 | Page findAllByAuditEventDateBetween(Instant fromDate, Instant toDate, Pageable pageable); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/PhotoRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.Photo; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.*; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Spring Data repository for the Photo entity. 15 | */ 16 | @SuppressWarnings("unused") 17 | @Repository 18 | public interface PhotoRepository extends JpaRepository { 19 | 20 | @Query(value = "select distinct photo from Photo photo left join fetch photo.tags", 21 | countQuery = "select count(distinct photo) from Photo photo") 22 | Page findAllWithEagerRelationships(Pageable pageable); 23 | 24 | @Query(value = "select distinct photo from Photo photo left join fetch photo.tags") 25 | List findAllWithEagerRelationships(); 26 | 27 | @Query("select photo from Photo photo left join fetch photo.tags where photo.id =:id") 28 | Optional findOneWithEagerRelationships(@Param("id") Long id); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/TagRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.Tag; 4 | import org.springframework.data.jpa.repository.*; 5 | import org.springframework.stereotype.Repository; 6 | 7 | 8 | /** 9 | * Spring Data repository for the Tag entity. 10 | */ 11 | @SuppressWarnings("unused") 12 | @Repository 13 | public interface TagRepository extends JpaRepository { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.repository; 2 | 3 | import com.okta.developer.domain.User; 4 | 5 | import org.springframework.cache.annotation.Cacheable; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.data.jpa.repository.EntityGraph; 9 | import org.springframework.data.jpa.repository.JpaRepository; 10 | import org.springframework.stereotype.Repository; 11 | import java.util.List; 12 | import java.util.Optional; 13 | import java.time.Instant; 14 | 15 | /** 16 | * Spring Data JPA repository for the User entity. 17 | */ 18 | @Repository 19 | public interface UserRepository extends JpaRepository { 20 | 21 | String USERS_BY_LOGIN_CACHE = "usersByLogin"; 22 | 23 | String USERS_BY_EMAIL_CACHE = "usersByEmail"; 24 | 25 | List findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime); 26 | 27 | Optional findOneByEmailIgnoreCase(String email); 28 | 29 | Optional findOneByLogin(String login); 30 | 31 | @EntityGraph(attributePaths = "authorities") 32 | Optional findOneWithAuthoritiesById(Long id); 33 | 34 | @EntityGraph(attributePaths = "authorities") 35 | @Cacheable(cacheNames = USERS_BY_LOGIN_CACHE) 36 | Optional findOneWithAuthoritiesByLogin(String login); 37 | 38 | @EntityGraph(attributePaths = "authorities") 39 | @Cacheable(cacheNames = USERS_BY_EMAIL_CACHE) 40 | Optional findOneWithAuthoritiesByEmail(String email); 41 | 42 | Page findAllByLoginNot(Pageable pageable, String login); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/repository/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring Data JPA repositories. 3 | */ 4 | package com.okta.developer.repository; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/security/AuthoritiesConstants.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.security; 2 | 3 | /** 4 | * Constants for Spring Security authorities. 5 | */ 6 | public final class AuthoritiesConstants { 7 | 8 | public static final String ADMIN = "ROLE_ADMIN"; 9 | 10 | public static final String USER = "ROLE_USER"; 11 | 12 | public static final String ANONYMOUS = "ROLE_ANONYMOUS"; 13 | 14 | private AuthoritiesConstants() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/security/SpringSecurityAuditorAware.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.security; 2 | 3 | import com.okta.developer.config.Constants; 4 | 5 | import java.util.Optional; 6 | 7 | import org.springframework.data.domain.AuditorAware; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * Implementation of AuditorAware based on Spring Security. 12 | */ 13 | @Component 14 | public class SpringSecurityAuditorAware implements AuditorAware { 15 | 16 | @Override 17 | public Optional getCurrentAuditor() { 18 | return Optional.of(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM_ACCOUNT)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/security/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring Security configuration. 3 | */ 4 | package com.okta.developer.security; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/service/AuditEventService.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.service; 2 | 3 | import com.okta.developer.config.audit.AuditEventConverter; 4 | import com.okta.developer.repository.PersistenceAuditEventRepository; 5 | import org.springframework.boot.actuate.audit.AuditEvent; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.time.Instant; 12 | import java.util.Optional; 13 | 14 | /** 15 | * Service for managing audit events. 16 | *

17 | * This is the default implementation to support SpringBoot Actuator AuditEventRepository 18 | */ 19 | @Service 20 | @Transactional 21 | public class AuditEventService { 22 | 23 | private final PersistenceAuditEventRepository persistenceAuditEventRepository; 24 | 25 | private final AuditEventConverter auditEventConverter; 26 | 27 | public AuditEventService( 28 | PersistenceAuditEventRepository persistenceAuditEventRepository, 29 | AuditEventConverter auditEventConverter) { 30 | 31 | this.persistenceAuditEventRepository = persistenceAuditEventRepository; 32 | this.auditEventConverter = auditEventConverter; 33 | } 34 | 35 | public Page findAll(Pageable pageable) { 36 | return persistenceAuditEventRepository.findAll(pageable) 37 | .map(auditEventConverter::convertToAuditEvent); 38 | } 39 | 40 | public Page findByDates(Instant fromDate, Instant toDate, Pageable pageable) { 41 | return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable) 42 | .map(auditEventConverter::convertToAuditEvent); 43 | } 44 | 45 | public Optional find(Long id) { 46 | return Optional.ofNullable(persistenceAuditEventRepository.findById(id)) 47 | .filter(Optional::isPresent) 48 | .map(Optional::get) 49 | .map(auditEventConverter::convertToAuditEvent); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/service/dto/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Data Transfer Objects. 3 | */ 4 | package com.okta.developer.service.dto; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/service/mapper/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MapStruct mappers for mapping domain objects and Data Transfer Objects. 3 | */ 4 | package com.okta.developer.service.mapper; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/service/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Service layer beans. 3 | */ 4 | package com.okta.developer.service; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/LogsResource.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest; 2 | 3 | import com.okta.developer.web.rest.vm.LoggerVM; 4 | 5 | import ch.qos.logback.classic.Level; 6 | import ch.qos.logback.classic.LoggerContext; 7 | import com.codahale.metrics.annotation.Timed; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * Controller for view and managing Log Level at runtime. 17 | */ 18 | @RestController 19 | @RequestMapping("/management") 20 | public class LogsResource { 21 | 22 | @GetMapping("/logs") 23 | @Timed 24 | public List getList() { 25 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 26 | return context.getLoggerList() 27 | .stream() 28 | .map(LoggerVM::new) 29 | .collect(Collectors.toList()); 30 | } 31 | 32 | @PutMapping("/logs") 33 | @ResponseStatus(HttpStatus.NO_CONTENT) 34 | @Timed 35 | public void changeLevel(@RequestBody LoggerVM jsonLogger) { 36 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 37 | context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/BadRequestAlertException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import org.zalando.problem.AbstractThrowableProblem; 4 | import org.zalando.problem.Status; 5 | 6 | import java.net.URI; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class BadRequestAlertException extends AbstractThrowableProblem { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | private final String entityName; 15 | 16 | private final String errorKey; 17 | 18 | public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) { 19 | this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey); 20 | } 21 | 22 | public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) { 23 | super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey)); 24 | this.entityName = entityName; 25 | this.errorKey = errorKey; 26 | } 27 | 28 | public String getEntityName() { 29 | return entityName; 30 | } 31 | 32 | public String getErrorKey() { 33 | return errorKey; 34 | } 35 | 36 | private static Map getAlertParameters(String entityName, String errorKey) { 37 | Map parameters = new HashMap<>(); 38 | parameters.put("message", "error." + errorKey); 39 | parameters.put("params", entityName); 40 | return parameters; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/CustomParameterizedException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import org.zalando.problem.AbstractThrowableProblem; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import static org.zalando.problem.Status.BAD_REQUEST; 9 | 10 | /** 11 | * Custom, parameterized exception, which can be translated on the client side. 12 | * For example: 13 | * 14 | *

15 |  * throw new CustomParameterizedException("myCustomError", "hello", "world");
16 |  * 
17 | * 18 | * Can be translated with: 19 | * 20 | *
21 |  * "error.myCustomError" :  "The server says {{param0}} to {{param1}}"
22 |  * 
23 | */ 24 | public class CustomParameterizedException extends AbstractThrowableProblem { 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | private static final String PARAM = "param"; 29 | 30 | public CustomParameterizedException(String message, String... params) { 31 | this(message, toParamMap(params)); 32 | } 33 | 34 | public CustomParameterizedException(String message, Map paramMap) { 35 | super(ErrorConstants.PARAMETERIZED_TYPE, "Parameterized Exception", BAD_REQUEST, null, null, null, toProblemParameters(message, paramMap)); 36 | } 37 | 38 | public static Map toParamMap(String... params) { 39 | Map paramMap = new HashMap<>(); 40 | if (params != null && params.length > 0) { 41 | for (int i = 0; i < params.length; i++) { 42 | paramMap.put(PARAM + i, params[i]); 43 | } 44 | } 45 | return paramMap; 46 | } 47 | 48 | public static Map toProblemParameters(String message, Map paramMap) { 49 | Map parameters = new HashMap<>(); 50 | parameters.put("message", message); 51 | parameters.put("params", paramMap); 52 | return parameters; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/EmailAlreadyUsedException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | public class EmailAlreadyUsedException extends BadRequestAlertException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public EmailAlreadyUsedException() { 8 | super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email is already in use!", "userManagement", "emailexists"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/EmailNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import org.zalando.problem.AbstractThrowableProblem; 4 | import org.zalando.problem.Status; 5 | 6 | public class EmailNotFoundException extends AbstractThrowableProblem { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public EmailNotFoundException() { 11 | super(ErrorConstants.EMAIL_NOT_FOUND_TYPE, "Email address not registered", Status.BAD_REQUEST); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/ErrorConstants.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import java.net.URI; 4 | 5 | public final class ErrorConstants { 6 | 7 | public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure"; 8 | public static final String ERR_VALIDATION = "error.validation"; 9 | public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem"; 10 | public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message"); 11 | public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation"); 12 | public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized"); 13 | public static final URI ENTITY_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/entity-not-found"); 14 | public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password"); 15 | public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used"); 16 | public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used"); 17 | public static final URI EMAIL_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/email-not-found"); 18 | 19 | private ErrorConstants() { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/FieldErrorVM.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import java.io.Serializable; 4 | 5 | public class FieldErrorVM implements Serializable { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | private final String objectName; 10 | 11 | private final String field; 12 | 13 | private final String message; 14 | 15 | public FieldErrorVM(String dto, String field, String message) { 16 | this.objectName = dto; 17 | this.field = field; 18 | this.message = message; 19 | } 20 | 21 | public String getObjectName() { 22 | return objectName; 23 | } 24 | 25 | public String getField() { 26 | return field; 27 | } 28 | 29 | public String getMessage() { 30 | return message; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/InternalServerErrorException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import org.zalando.problem.AbstractThrowableProblem; 4 | import org.zalando.problem.Status; 5 | 6 | /** 7 | * Simple exception with a message, that returns an Internal Server Error code. 8 | */ 9 | public class InternalServerErrorException extends AbstractThrowableProblem { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | public InternalServerErrorException(String message) { 14 | super(ErrorConstants.DEFAULT_TYPE, message, Status.INTERNAL_SERVER_ERROR); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/InvalidPasswordException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | import org.zalando.problem.AbstractThrowableProblem; 4 | import org.zalando.problem.Status; 5 | 6 | public class InvalidPasswordException extends AbstractThrowableProblem { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public InvalidPasswordException() { 11 | super(ErrorConstants.INVALID_PASSWORD_TYPE, "Incorrect password", Status.BAD_REQUEST); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/LoginAlreadyUsedException.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.errors; 2 | 3 | public class LoginAlreadyUsedException extends BadRequestAlertException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public LoginAlreadyUsedException() { 8 | super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login name already used!", "userManagement", "userexists"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/errors/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Specific errors used with Zalando's "problem-spring-web" library. 3 | * 4 | * More information on https://github.com/zalando/problem-spring-web 5 | */ 6 | package com.okta.developer.web.rest.errors; 7 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring MVC REST controllers. 3 | */ 4 | package com.okta.developer.web.rest; 5 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/util/HeaderUtil.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpHeaders; 6 | 7 | /** 8 | * Utility class for HTTP headers creation. 9 | */ 10 | public final class HeaderUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class); 13 | 14 | private static final String APPLICATION_NAME = "galleryApp"; 15 | 16 | private HeaderUtil() { 17 | } 18 | 19 | public static HttpHeaders createAlert(String message, String param) { 20 | HttpHeaders headers = new HttpHeaders(); 21 | headers.add("X-galleryApp-alert", message); 22 | headers.add("X-galleryApp-params", param); 23 | return headers; 24 | } 25 | 26 | public static HttpHeaders createEntityCreationAlert(String entityName, String param) { 27 | return createAlert(APPLICATION_NAME + "." + entityName + ".created", param); 28 | } 29 | 30 | public static HttpHeaders createEntityUpdateAlert(String entityName, String param) { 31 | return createAlert(APPLICATION_NAME + "." + entityName + ".updated", param); 32 | } 33 | 34 | public static HttpHeaders createEntityDeletionAlert(String entityName, String param) { 35 | return createAlert(APPLICATION_NAME + "." + entityName + ".deleted", param); 36 | } 37 | 38 | public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) { 39 | log.error("Entity processing failed, {}", defaultMessage); 40 | HttpHeaders headers = new HttpHeaders(); 41 | headers.add("X-galleryApp-error", "error." + errorKey); 42 | headers.add("X-galleryApp-params", entityName); 43 | return headers; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/util/PaginationUtil.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.util; 2 | 3 | import org.springframework.data.domain.Page; 4 | import org.springframework.http.HttpHeaders; 5 | import org.springframework.web.util.UriComponentsBuilder; 6 | 7 | /** 8 | * Utility class for handling pagination. 9 | * 10 | *

11 | * Pagination uses the same principles as the GitHub API, 12 | * and follow RFC 5988 (Link header). 13 | */ 14 | public final class PaginationUtil { 15 | 16 | private PaginationUtil() { 17 | } 18 | 19 | public static HttpHeaders generatePaginationHttpHeaders(Page page, String baseUrl) { 20 | 21 | HttpHeaders headers = new HttpHeaders(); 22 | headers.add("X-Total-Count", Long.toString(page.getTotalElements())); 23 | String link = ""; 24 | if ((page.getNumber() + 1) < page.getTotalPages()) { 25 | link = "<" + generateUri(baseUrl, page.getNumber() + 1, page.getSize()) + ">; rel=\"next\","; 26 | } 27 | // prev link 28 | if ((page.getNumber()) > 0) { 29 | link += "<" + generateUri(baseUrl, page.getNumber() - 1, page.getSize()) + ">; rel=\"prev\","; 30 | } 31 | // last and first link 32 | int lastPage = 0; 33 | if (page.getTotalPages() > 0) { 34 | lastPage = page.getTotalPages() - 1; 35 | } 36 | link += "<" + generateUri(baseUrl, lastPage, page.getSize()) + ">; rel=\"last\","; 37 | link += "<" + generateUri(baseUrl, 0, page.getSize()) + ">; rel=\"first\""; 38 | headers.add(HttpHeaders.LINK, link); 39 | return headers; 40 | } 41 | 42 | private static String generateUri(String baseUrl, int page, int size) { 43 | return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/vm/LoggerVM.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.vm; 2 | 3 | import ch.qos.logback.classic.Logger; 4 | 5 | /** 6 | * View Model object for storing a Logback logger. 7 | */ 8 | public class LoggerVM { 9 | 10 | private String name; 11 | 12 | private String level; 13 | 14 | public LoggerVM(Logger logger) { 15 | this.name = logger.getName(); 16 | this.level = logger.getEffectiveLevel().toString(); 17 | } 18 | 19 | public LoggerVM() { 20 | // Empty public constructor used by Jackson. 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getLevel() { 32 | return level; 33 | } 34 | 35 | public void setLevel(String level) { 36 | this.level = level; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "LoggerVM{" + 42 | "name='" + name + '\'' + 43 | ", level='" + level + '\'' + 44 | '}'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/vm/ManagedUserVM.java: -------------------------------------------------------------------------------- 1 | package com.okta.developer.web.rest.vm; 2 | 3 | import com.okta.developer.service.dto.UserDTO; 4 | 5 | /** 6 | * View Model extending the UserDTO, which is meant to be used in the user management UI. 7 | */ 8 | public class ManagedUserVM extends UserDTO { 9 | 10 | public ManagedUserVM() { 11 | // Empty constructor needed for Jackson. 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "ManagedUserVM{" + 17 | "} " + super.toString(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/okta/developer/web/rest/vm/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * View Models used by Spring MVC REST controllers. 3 | */ 4 | package com.okta.developer.web.rest.vm; 5 | -------------------------------------------------------------------------------- /src/main/resources/.h2.server.properties: -------------------------------------------------------------------------------- 1 | #H2 Server Properties 2 | 0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/gallery|gallery 3 | webAllowOthers=true 4 | webPort=8082 5 | webSSL=false 6 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ${AnsiColor.GREEN} ██╗${AnsiColor.BLUE} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗ 3 | ${AnsiColor.GREEN} ██║${AnsiColor.BLUE} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗ 4 | ${AnsiColor.GREEN} ██║${AnsiColor.BLUE} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝ 5 | ${AnsiColor.GREEN}██╗ ██║${AnsiColor.BLUE} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║ 6 | ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.BLUE} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗ 7 | ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.BLUE} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝ 8 | 9 | ${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} :: 10 | :: https://www.jhipster.tech ::${AnsiColor.DEFAULT} 11 | -------------------------------------------------------------------------------- /src/main/resources/config/application-heroku.yml: -------------------------------------------------------------------------------- 1 | # =================================================================== 2 | # Spring Boot configuration for the "heroku" profile. 3 | # 4 | # This configuration overrides the application.yml file. 5 | # =================================================================== 6 | 7 | # =================================================================== 8 | # Standard Spring Boot properties. 9 | # Full reference is available at: 10 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html 11 | # =================================================================== 12 | 13 | eureka: 14 | instance: 15 | hostname: gallery-pwa.herokuapp.com 16 | non-secure-port: 80 17 | prefer-ip-address: false 18 | client: 19 | service-url: 20 | defaultZone: ${JHIPSTER_REGISTRY_URL}/eureka/ 21 | 22 | spring: 23 | datasource: 24 | type: com.zaxxer.hikari.HikariDataSource 25 | url: ${JDBC_DATABASE_URL} 26 | username: ${JDBC_DATABASE_USERNAME} 27 | password: ${JDBC_DATABASE_PASSWORD} 28 | hikari: 29 | maximumPoolSize: 8 30 | -------------------------------------------------------------------------------- /src/main/resources/config/bootstrap-heroku.yml: -------------------------------------------------------------------------------- 1 | # =================================================================== 2 | # Spring Cloud Config bootstrap configuration for the "heroku" profile 3 | # =================================================================== 4 | 5 | spring: 6 | cloud: 7 | config: 8 | fail-fast: true 9 | uri: ${JHIPSTER_REGISTRY_URL}/config 10 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/authorities.csv: -------------------------------------------------------------------------------- 1 | name 2 | ROLE_ADMIN 3 | ROLE_USER 4 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/changelog/20180625042224_added_entity_Album.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/changelog/20180625042224_added_entity_constraints_Album.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/changelog/20180625042225_added_entity_constraints_Photo.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 11 | 16 | 17 | 22 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/changelog/20180625042226_added_entity_Tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/master.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/users.csv: -------------------------------------------------------------------------------- 1 | id;login;first_name;last_name;email;image_url;activated;lang_key;created_by;last_modified_by 2 | 1;system;System;System;system@localhost;;true;en;system;system 3 | 2;anonymoususer;Anonymous;User;anonymous@localhost;;true;en;system;system 4 | -------------------------------------------------------------------------------- /src/main/resources/config/liquibase/users_authorities.csv: -------------------------------------------------------------------------------- 1 | user_id;authority_name 2 | 1;ROLE_ADMIN 3 | 1;ROLE_USER 4 | 3;ROLE_ADMIN 5 | 3;ROLE_USER 6 | 4;ROLE_USER 7 | -------------------------------------------------------------------------------- /src/main/resources/i18n/messages.properties: -------------------------------------------------------------------------------- 1 | # Error page 2 | error.title=Your request cannot be processed 3 | error.subtitle=Sorry, an error has occurred. 4 | error.status=Status: 5 | error.message=Message: 6 | 7 | # Activation email 8 | email.activation.title=gallery account activation 9 | email.activation.greeting=Dear {0} 10 | email.activation.text1=Your gallery account has been created, please click on the URL below to activate it: 11 | email.activation.text2=Regards, 12 | email.signature=gallery Team. 13 | 14 | # Creation email 15 | email.creation.text1=Your gallery account has been created, please click on the URL below to access it: 16 | 17 | # Reset email 18 | email.reset.title=gallery password reset 19 | email.reset.greeting=Dear {0} 20 | email.reset.text1=For your gallery account a password reset was requested, please click on the URL below to reset it: 21 | email.reset.text2=Regards, 22 | -------------------------------------------------------------------------------- /src/main/resources/i18n/messages_en.properties: -------------------------------------------------------------------------------- 1 | # Error page 2 | error.title=Your request cannot be processed 3 | error.subtitle=Sorry, an error has occurred. 4 | error.status=Status: 5 | error.message=Message: 6 | 7 | # Activation email 8 | email.activation.title=gallery account activation 9 | email.activation.greeting=Dear {0} 10 | email.activation.text1=Your gallery account has been created, please click on the URL below to activate it: 11 | email.activation.text2=Regards, 12 | email.signature=gallery Team. 13 | 14 | # Creation email 15 | email.creation.text1=Your gallery account has been created, please click on the URL below to access it: 16 | 17 | # Reset email 18 | email.reset.title=gallery password reset 19 | email.reset.greeting=Dear {0} 20 | email.reset.text1=For your gallery account a password reset was requested, please click on the URL below to reset it: 21 | email.reset.text2=Regards, 22 | -------------------------------------------------------------------------------- /src/main/resources/i18n/messages_fr.properties: -------------------------------------------------------------------------------- 1 | # Error page 2 | error.title=Votre demande ne peut être traitée 3 | error.subtitle=Désolé, une erreur s'est produite. 4 | error.status=Statut : 5 | error.message=Message : 6 | 7 | # Activation email 8 | email.activation.title=Activation de votre compte gallery 9 | email.activation.greeting=Cher {0} 10 | email.activation.text1=Votre compte gallery a été créé, pour l'activer merci de cliquer sur le lien ci-dessous : 11 | email.activation.text2=Cordialement, 12 | email.signature=gallery. 13 | 14 | # Creation email 15 | email.creation.text1=Votre compte gallery a été créé, merci de cliquer sur le lien ci-dessous pour y accéder : 16 | 17 | # Reset email 18 | email.reset.title=gallery Réinitialisation de mot de passe 19 | email.reset.greeting=Cher {0} 20 | email.reset.text1=Un nouveau mot de passe pour votre compte gallery a été demandé, veuillez cliquer sur le lien ci-dessous pour le réinitialiser : 21 | email.reset.text2=Cordialement, 22 | -------------------------------------------------------------------------------- /src/main/webapp/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found 6 | 7 | 8 | 55 | 56 | 57 |

Page Not Found

58 |

Sorry, but the page you were trying to view does not exist.

59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/axios-interceptor.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { getBasePath, Storage } from 'react-jhipster'; 3 | 4 | const TIMEOUT = 1000000; // 10000 5 | const setupAxiosInterceptors = onUnauthenticated => { 6 | const onRequestSuccess = config => { 7 | const token = Storage.local.get('jhi-authenticationToken') || Storage.session.get('jhi-authenticationToken'); 8 | if (token) { 9 | config.headers.Authorization = `Bearer ${token}`; 10 | } 11 | config.timeout = TIMEOUT; 12 | config.url = `${getBasePath().replace(/\/$/, '')}${config.url}`; 13 | return config; 14 | }; 15 | const onResponseSuccess = response => response; 16 | const onResponseError = err => { 17 | const status = err.status || err.response.status; 18 | if (status === 403 || status === 401) { 19 | onUnauthenticated(); 20 | } 21 | return Promise.reject(err); 22 | }; 23 | axios.interceptors.request.use(onRequestSuccess); 24 | axios.interceptors.response.use(onResponseSuccess, onResponseError); 25 | }; 26 | 27 | export default setupAxiosInterceptors; 28 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/constants.ts: -------------------------------------------------------------------------------- 1 | const config = { 2 | VERSION: process.env.VERSION, 3 | SERVER_API_URL: process.env.SERVER_API_URL 4 | }; 5 | 6 | export default config; 7 | 8 | export const SERVER_API_URL = ''; 9 | 10 | export const AUTHORITIES = { 11 | ADMIN: 'ROLE_ADMIN', 12 | USER: 'ROLE_USER' 13 | }; 14 | 15 | export const messages = { 16 | DATA_ERROR_ALERT: 'Internal Error' 17 | }; 18 | 19 | export const APP_DATE_FORMAT = 'DD/MM/YY HH:mm'; 20 | export const APP_TIMESTAMP_FORMAT = 'DD/MM/YY HH:mm:ss'; 21 | export const APP_LOCAL_DATE_FORMAT = 'DD/MM/YYYY'; 22 | export const APP_LOCAL_DATETIME_FORMAT = 'YYYY-MM-DDThh:mm'; 23 | export const APP_WHOLE_NUMBER_FORMAT = '0,0'; 24 | export const APP_TWO_DIGITS_AFTER_POINT_NUMBER_FORMAT = '0,0.[00]'; 25 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/devtools.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { createDevTools } from 'redux-devtools'; 3 | import LogMonitor from 'redux-devtools-log-monitor'; 4 | import DockMonitor from 'redux-devtools-dock-monitor'; 5 | // You can toggle visibility of devTools with ctrl + H 6 | // and change their position with ctrl + Q 7 | export default createDevTools( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/error-middleware.ts: -------------------------------------------------------------------------------- 1 | import { isPromise } from 'react-jhipster'; 2 | 3 | const getErrorMessage = errorData => { 4 | let message = errorData.message; 5 | if (errorData.fieldErrors) { 6 | errorData.fieldErrors.forEach(fErr => { 7 | message += `\nfield: ${fErr.field}, Object: ${fErr.objectName}, message: ${fErr.message}\n`; 8 | }); 9 | } 10 | return message; 11 | }; 12 | 13 | export default () => next => action => { 14 | // If not a promise, continue on 15 | if (!isPromise(action.payload)) { 16 | return next(action); 17 | } 18 | 19 | /** 20 | * 21 | * The error middleware serves to dispatch the initial pending promise to 22 | * the promise middleware, but adds a `catch`. 23 | * It need not run in production 24 | */ 25 | if (process.env.NODE_ENV === 'development') { 26 | // Dispatch initial pending promise, but catch any errors 27 | return next(action).catch(error => { 28 | console.error(`${action.type} caught at middleware with reason: ${JSON.stringify(error.message)}.`); 29 | if (error && error.response && error.response.data) { 30 | const message = getErrorMessage(error.response.data); 31 | console.error(`Actual cause: ${message}`); 32 | } 33 | 34 | return Promise.reject(error); 35 | }); 36 | } 37 | return next(action); 38 | }; 39 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/icon-loader.ts: -------------------------------------------------------------------------------- 1 | import { 2 | faSort, 3 | faEye, 4 | faSync, 5 | faBan, 6 | faTrash, 7 | faArrowLeft, 8 | faSave, 9 | faPlus, 10 | faPencilAlt, 11 | faUser, 12 | faTachometerAlt, 13 | faHeart, 14 | faList, 15 | faTasks, 16 | faBook, 17 | faHdd, 18 | faClock, 19 | faSignInAlt, 20 | faSignOutAlt, 21 | faWrench, 22 | faThList, 23 | faUserPlus, 24 | faAsterisk, 25 | faFlag, 26 | faBell, 27 | faHome, 28 | faTimesCircle, 29 | faSearch 30 | } from '@fortawesome/fontawesome-free-solid'; 31 | import fontawesome from '@fortawesome/fontawesome'; 32 | 33 | export const loadIcons = () => { 34 | fontawesome.library.add( 35 | faSort, 36 | faEye, 37 | faSync, 38 | faBan, 39 | faTrash, 40 | faArrowLeft, 41 | faSave, 42 | faPlus, 43 | faPencilAlt, 44 | faUser, 45 | faTachometerAlt, 46 | faHeart, 47 | faList, 48 | faTasks, 49 | faBook, 50 | faHdd, 51 | faClock, 52 | faSignInAlt, 53 | faSignOutAlt, 54 | faWrench, 55 | faThList, 56 | faUserPlus, 57 | faAsterisk, 58 | faFlag, 59 | faBell, 60 | faHome 61 | ); 62 | }; 63 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/logger-middleware.ts: -------------------------------------------------------------------------------- 1 | export default () => next => action => { 2 | if (process.env.NODE_ENV !== 'production') { 3 | const { type, payload, meta } = action; 4 | 5 | console.groupCollapsed(type); 6 | // tslint:disable-next-line 7 | console.log('Payload:', payload); 8 | // tslint:disable-next-line 9 | console.log('Meta:', meta); 10 | console.groupEnd(); 11 | } 12 | 13 | return next(action); 14 | }; 15 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/store.ts: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose, GenericStoreEnhancer } from 'redux'; 2 | import promiseMiddleware from 'redux-promise-middleware'; 3 | import thunkMiddleware from 'redux-thunk'; 4 | import reducer, { IRootState } from 'app/shared/reducers'; 5 | import DevTools from './devtools'; 6 | import errorMiddleware from './error-middleware'; 7 | import notificationMiddleware from './notification-middleware'; 8 | import loggerMiddleware from './logger-middleware'; 9 | import { loadingBarMiddleware } from 'react-redux-loading-bar'; 10 | 11 | const defaultMiddlewares = [ 12 | thunkMiddleware, 13 | errorMiddleware, 14 | notificationMiddleware, 15 | promiseMiddleware(), 16 | loadingBarMiddleware(), 17 | loggerMiddleware 18 | ]; 19 | const composedMiddlewares = middlewares => 20 | process.env.NODE_ENV === 'development' 21 | ? (compose(applyMiddleware(...defaultMiddlewares, ...middlewares), DevTools.instrument()) as GenericStoreEnhancer) 22 | : compose(applyMiddleware(...defaultMiddlewares, ...middlewares)); 23 | 24 | const initialize = (initialState?: IRootState, middlewares = []) => createStore(reducer, initialState, composedMiddlewares(middlewares)); 25 | 26 | export default initialize; 27 | -------------------------------------------------------------------------------- /src/main/webapp/app/config/translation.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { TranslatorContext, Storage } from 'react-jhipster'; 3 | 4 | import { setLocale } from 'app/shared/reducers/locale'; 5 | 6 | export const locales = ['en', 'fr']; 7 | 8 | let currentLocale; 9 | const savedLocale = Storage.session.get('locale', 'en'); 10 | TranslatorContext.setDefaultLocale('en'); 11 | TranslatorContext.setRenderInnerTextForMissingKeys(false); 12 | 13 | export const registerLocales = store => { 14 | locales.forEach(locale => { 15 | axios.get(`/i18n/${locale}.json`).then(response => { 16 | TranslatorContext.registerTranslations(locale, response.data); 17 | }); 18 | }); 19 | store.subscribe(() => { 20 | const previousLocale = currentLocale; 21 | currentLocale = store.getState().locale.currentLocale; 22 | if (previousLocale !== currentLocale) { 23 | Storage.session.set('locale', currentLocale); 24 | TranslatorContext.setLocale(currentLocale); 25 | } 26 | }); 27 | store.dispatch(setLocale(savedLocale)); 28 | }; 29 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/album/album-delete-dialog.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { RouteComponentProps } from 'react-router-dom'; 4 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; 5 | import { Translate, ICrudGetAction, ICrudDeleteAction } from 'react-jhipster'; 6 | import FontAwesomeIcon from '@fortawesome/react-fontawesome'; 7 | 8 | import { IAlbum } from 'app/shared/model/album.model'; 9 | import { IRootState } from 'app/shared/reducers'; 10 | import { getEntity, deleteEntity } from './album.reducer'; 11 | 12 | export interface IAlbumDeleteDialogProps extends StateProps, DispatchProps, RouteComponentProps<{ id: number }> {} 13 | 14 | export class AlbumDeleteDialog extends React.Component { 15 | componentDidMount() { 16 | this.props.getEntity(this.props.match.params.id); 17 | } 18 | 19 | confirmDelete = event => { 20 | this.props.deleteEntity(this.props.albumEntity.id); 21 | this.handleClose(event); 22 | }; 23 | 24 | handleClose = event => { 25 | event.stopPropagation(); 26 | this.props.history.goBack(); 27 | }; 28 | 29 | render() { 30 | const { albumEntity } = this.props; 31 | return ( 32 | 33 | 34 | Confirm delete operation 35 | 36 | 37 | 38 | Are you sure you want to delete this Album? 39 | 40 | 41 | 42 | 46 | 50 | 51 | 52 | ); 53 | } 54 | } 55 | 56 | const mapStateToProps = ({ album }: IRootState) => ({ 57 | albumEntity: album.entity 58 | }); 59 | 60 | const mapDispatchToProps = { getEntity, deleteEntity }; 61 | 62 | type StateProps = ReturnType; 63 | type DispatchProps = typeof mapDispatchToProps; 64 | 65 | export default connect(mapStateToProps, mapDispatchToProps)(AlbumDeleteDialog); 66 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/album/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Switch } from 'react-router-dom'; 3 | 4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route'; 5 | 6 | import Album from './album'; 7 | import AlbumDetail from './album-detail'; 8 | import AlbumUpdate from './album-update'; 9 | import AlbumDeleteDialog from './album-delete-dialog'; 10 | 11 | const Routes = ({ match }) => ( 12 | <> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default Routes; 24 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Switch } from 'react-router-dom'; 3 | 4 | // tslint:disable-next-line:no-unused-variable 5 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route'; 6 | 7 | import Album from './album'; 8 | import Photo from './photo'; 9 | import Tag from './tag'; 10 | /* jhipster-needle-add-route-import - JHipster will add routes here */ 11 | 12 | const Routes = ({ match }) => ( 13 |
14 | 15 | {/* prettier-ignore */} 16 | 17 | 18 | 19 | {/* jhipster-needle-add-route-path - JHipster will routes here */} 20 | 21 |
22 | ); 23 | 24 | export default Routes; 25 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/photo/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Switch } from 'react-router-dom'; 3 | 4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route'; 5 | 6 | import Photo from './photo'; 7 | import PhotoDetail from './photo-detail'; 8 | import PhotoUpdate from './photo-update'; 9 | import PhotoDeleteDialog from './photo-delete-dialog'; 10 | 11 | const Routes = ({ match }) => ( 12 | <> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default Routes; 24 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/photo/photo-delete-dialog.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { RouteComponentProps } from 'react-router-dom'; 4 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; 5 | import { Translate, ICrudGetAction, ICrudDeleteAction } from 'react-jhipster'; 6 | import FontAwesomeIcon from '@fortawesome/react-fontawesome'; 7 | 8 | import { IPhoto } from 'app/shared/model/photo.model'; 9 | import { IRootState } from 'app/shared/reducers'; 10 | import { getEntity, deleteEntity } from './photo.reducer'; 11 | 12 | export interface IPhotoDeleteDialogProps extends StateProps, DispatchProps, RouteComponentProps<{ id: number }> {} 13 | 14 | export class PhotoDeleteDialog extends React.Component { 15 | componentDidMount() { 16 | this.props.getEntity(this.props.match.params.id); 17 | } 18 | 19 | confirmDelete = event => { 20 | this.props.deleteEntity(this.props.photoEntity.id); 21 | this.handleClose(event); 22 | }; 23 | 24 | handleClose = event => { 25 | event.stopPropagation(); 26 | this.props.history.goBack(); 27 | }; 28 | 29 | render() { 30 | const { photoEntity } = this.props; 31 | return ( 32 | 33 | 34 | Confirm delete operation 35 | 36 | 37 | 38 | Are you sure you want to delete this Photo? 39 | 40 | 41 | 42 | 46 | 50 | 51 | 52 | ); 53 | } 54 | } 55 | 56 | const mapStateToProps = ({ photo }: IRootState) => ({ 57 | photoEntity: photo.entity 58 | }); 59 | 60 | const mapDispatchToProps = { getEntity, deleteEntity }; 61 | 62 | type StateProps = ReturnType; 63 | type DispatchProps = typeof mapDispatchToProps; 64 | 65 | export default connect(mapStateToProps, mapDispatchToProps)(PhotoDeleteDialog); 66 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/tag/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Switch } from 'react-router-dom'; 3 | 4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route'; 5 | 6 | import Tag from './tag'; 7 | import TagDetail from './tag-detail'; 8 | import TagUpdate from './tag-update'; 9 | import TagDeleteDialog from './tag-delete-dialog'; 10 | 11 | const Routes = ({ match }) => ( 12 | <> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default Routes; 24 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/tag/tag-delete-dialog.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { RouteComponentProps } from 'react-router-dom'; 4 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; 5 | import { Translate, ICrudGetAction, ICrudDeleteAction } from 'react-jhipster'; 6 | import FontAwesomeIcon from '@fortawesome/react-fontawesome'; 7 | 8 | import { ITag } from 'app/shared/model/tag.model'; 9 | import { IRootState } from 'app/shared/reducers'; 10 | import { getEntity, deleteEntity } from './tag.reducer'; 11 | 12 | export interface ITagDeleteDialogProps extends StateProps, DispatchProps, RouteComponentProps<{ id: number }> {} 13 | 14 | export class TagDeleteDialog extends React.Component { 15 | componentDidMount() { 16 | this.props.getEntity(this.props.match.params.id); 17 | } 18 | 19 | confirmDelete = event => { 20 | this.props.deleteEntity(this.props.tagEntity.id); 21 | this.handleClose(event); 22 | }; 23 | 24 | handleClose = event => { 25 | event.stopPropagation(); 26 | this.props.history.goBack(); 27 | }; 28 | 29 | render() { 30 | const { tagEntity } = this.props; 31 | return ( 32 | 33 | 34 | Confirm delete operation 35 | 36 | 37 | 38 | Are you sure you want to delete this Tag? 39 | 40 | 41 | 42 | 46 | 50 | 51 | 52 | ); 53 | } 54 | } 55 | 56 | const mapStateToProps = ({ tag }: IRootState) => ({ 57 | tagEntity: tag.entity 58 | }); 59 | 60 | const mapDispatchToProps = { getEntity, deleteEntity }; 61 | 62 | type StateProps = ReturnType; 63 | type DispatchProps = typeof mapDispatchToProps; 64 | 65 | export default connect(mapStateToProps, mapDispatchToProps)(TagDeleteDialog); 66 | -------------------------------------------------------------------------------- /src/main/webapp/app/entities/tag/tag-detail.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Link, RouteComponentProps } from 'react-router-dom'; 4 | import { Button, Row, Col } from 'reactstrap'; 5 | // tslint:disable-next-line:no-unused-variable 6 | import { Translate, ICrudGetAction } from 'react-jhipster'; 7 | import FontAwesomeIcon from '@fortawesome/react-fontawesome'; 8 | 9 | import { IRootState } from 'app/shared/reducers'; 10 | import { getEntity } from './tag.reducer'; 11 | import { ITag } from 'app/shared/model/tag.model'; 12 | // tslint:disable-next-line:no-unused-variable 13 | import { APP_DATE_FORMAT, APP_LOCAL_DATE_FORMAT } from 'app/config/constants'; 14 | 15 | export interface ITagDetailProps extends StateProps, DispatchProps, RouteComponentProps<{ id: number }> {} 16 | 17 | export class TagDetail extends React.Component { 18 | componentDidMount() { 19 | this.props.getEntity(this.props.match.params.id); 20 | } 21 | 22 | render() { 23 | const { tagEntity } = this.props; 24 | return ( 25 | 26 | 27 |

28 | Tag [{tagEntity.id}] 29 |

30 |
31 |
32 | 33 | Name 34 | 35 |
36 |
{tagEntity.name}
37 |
38 |   44 | 50 | 51 |
52 | ); 53 | } 54 | } 55 | 56 | const mapStateToProps = ({ tag }: IRootState) => ({ 57 | tagEntity: tag.entity 58 | }); 59 | 60 | const mapDispatchToProps = { getEntity }; 61 | 62 | type StateProps = ReturnType; 63 | type DispatchProps = typeof mapDispatchToProps; 64 | 65 | export default connect(mapStateToProps, mapDispatchToProps)(TagDetail); 66 | -------------------------------------------------------------------------------- /src/main/webapp/app/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { bindActionCreators } from 'redux'; 5 | import { AppContainer } from 'react-hot-loader'; 6 | 7 | import DevTools from './config/devtools'; 8 | import initStore from './config/store'; 9 | import { registerLocales } from './config/translation'; 10 | import setupAxiosInterceptors from './config/axios-interceptor'; 11 | import { clearAuthentication } from './shared/reducers/authentication'; 12 | import ErrorBoundary from './shared/error/error-boundary'; 13 | import AppComponent from './app'; 14 | import { loadIcons } from './config/icon-loader'; 15 | 16 | const devTools = process.env.NODE_ENV === 'development' ? : null; 17 | 18 | const store = initStore(); 19 | registerLocales(store); 20 | 21 | const actions = bindActionCreators({ clearAuthentication }, store.dispatch); 22 | setupAxiosInterceptors(() => actions.clearAuthentication('login.error.unauthorized')); 23 | 24 | loadIcons(); 25 | 26 | const rootEl = document.getElementById('root'); 27 | 28 | const render = Component => 29 | ReactDOM.render( 30 | 31 | 32 | 33 |
34 | {/* If this slows down the app in dev disable it and enable when required */} 35 | {devTools} 36 | 37 |
38 |
39 |
40 |
, 41 | rootEl 42 | ); 43 | 44 | render(AppComponent); 45 | 46 | // This is quite unstable 47 | // if (module.hot) { 48 | // module.hot.accept('./app', () => { 49 | // const NextApp = require<{ default: typeof AppComponent }>('./app').default; 50 | // render(NextApp); 51 | // }); 52 | // } 53 | -------------------------------------------------------------------------------- /src/main/webapp/app/modules/administration/docs/docs.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const DocsPage = () => ( 4 |
5 |