Showing preview only (412K chars total). Download the full file or copy to clipboard to get everything.
Repository: iainporter/rest-java
Branch: master
Commit: 30a904561b85
Files: 146
Total size: 368.0 KB
Directory structure:
gitextract_6sr2pa59/
├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src/
├── main/
│ ├── config/
│ │ └── ci/
│ │ └── gradle.properties
│ ├── java/
│ │ └── com/
│ │ └── porterhead/
│ │ └── rest/
│ │ ├── api/
│ │ │ ├── ErrorResponse.java
│ │ │ ├── PagedQueryRequest.java
│ │ │ ├── PagedResponse.java
│ │ │ └── ValidationError.java
│ │ ├── authorization/
│ │ │ ├── AuthorizationRequestContext.java
│ │ │ ├── AuthorizationService.java
│ │ │ ├── exception/
│ │ │ │ └── InvalidAuthorizationHeaderException.java
│ │ │ └── impl/
│ │ │ ├── RequestSigningAuthorizationService.java
│ │ │ ├── SecurityContextImpl.java
│ │ │ └── SessionTokenAuthorizationService.java
│ │ ├── config/
│ │ │ ├── ApplicationConfig.java
│ │ │ ├── ApplicationDevConfig.java
│ │ │ ├── ApplicationProductionConfig.java
│ │ │ └── ApplicationStagingConfig.java
│ │ ├── exception/
│ │ │ ├── ApplicationRuntimeException.java
│ │ │ ├── BaseWebApplicationException.java
│ │ │ ├── NotFoundException.java
│ │ │ └── ValidationException.java
│ │ ├── filter/
│ │ │ ├── ResourceFilterFactory.java
│ │ │ └── SecurityContextFilter.java
│ │ ├── gateway/
│ │ │ └── EmailServicesGateway.java
│ │ ├── model/
│ │ │ └── BaseEntity.java
│ │ ├── resource/
│ │ │ ├── GenericExceptionMapper.java
│ │ │ └── HealthCheckResource.java
│ │ ├── service/
│ │ │ └── BaseService.java
│ │ ├── user/
│ │ │ ├── EmailServiceTokenModel.java
│ │ │ ├── SocialUserRepository.java
│ │ │ ├── UserRepository.java
│ │ │ ├── UserService.java
│ │ │ ├── UserServiceImpl.java
│ │ │ ├── VerificationTokenRepository.java
│ │ │ ├── VerificationTokenService.java
│ │ │ ├── VerificationTokenServiceImpl.java
│ │ │ ├── api/
│ │ │ │ ├── AuthenticatedUserToken.java
│ │ │ │ ├── CreateUserRequest.java
│ │ │ │ ├── EmailVerificationRequest.java
│ │ │ │ ├── ExternalUser.java
│ │ │ │ ├── LoginRequest.java
│ │ │ │ ├── LostPasswordRequest.java
│ │ │ │ ├── OAuth2Request.java
│ │ │ │ ├── PasswordRequest.java
│ │ │ │ ├── SocialProfile.java
│ │ │ │ └── UpdateUserRequest.java
│ │ │ ├── domain/
│ │ │ │ ├── AuthorizationToken.java
│ │ │ │ ├── Role.java
│ │ │ │ ├── SocialUser.java
│ │ │ │ ├── SocialUserBuilder.java
│ │ │ │ ├── User.java
│ │ │ │ └── VerificationToken.java
│ │ │ ├── exception/
│ │ │ │ ├── AlreadyVerifiedException.java
│ │ │ │ ├── AuthenticationException.java
│ │ │ │ ├── AuthorizationException.java
│ │ │ │ ├── DuplicateUserException.java
│ │ │ │ ├── TokenHasExpiredException.java
│ │ │ │ ├── TokenNotFoundException.java
│ │ │ │ └── UserNotFoundException.java
│ │ │ ├── mail/
│ │ │ │ ├── MailSenderService.java
│ │ │ │ ├── MockJavaMailSender.java
│ │ │ │ └── impl/
│ │ │ │ └── MailSenderServiceImpl.java
│ │ │ ├── resource/
│ │ │ │ ├── PasswordResource.java
│ │ │ │ ├── UserResource.java
│ │ │ │ └── VerificationResource.java
│ │ │ └── social/
│ │ │ ├── JpaConnectionRepository.java
│ │ │ ├── JpaUsersConnectionRepository.java
│ │ │ └── SocialConfig.java
│ │ └── util/
│ │ ├── DateUtil.java
│ │ ├── HashUtil.java
│ │ └── StringUtil.java
│ ├── resources/
│ │ ├── META-INF/
│ │ │ ├── persistence.xml
│ │ │ ├── spring/
│ │ │ │ ├── component-scan-context.xml
│ │ │ │ ├── data-context.xml
│ │ │ │ ├── email-services-context.xml
│ │ │ │ ├── email-template-context.xml
│ │ │ │ ├── root-context.xml
│ │ │ │ └── social-configuration-context.xml
│ │ │ └── velocity/
│ │ │ ├── LostPasswordEmail.vm
│ │ │ ├── RegistrationEmail.vm
│ │ │ └── VerifyEmail.vm
│ │ ├── logback.xml
│ │ ├── properties/
│ │ │ ├── app.properties
│ │ │ ├── dev-app.properties
│ │ │ ├── production-app.properties
│ │ │ └── staging-app.properties
│ │ └── schema/
│ │ ├── indexes.sql
│ │ ├── message_store.sql
│ │ └── truncate_data.sql
│ └── webapp/
│ ├── META-INF/
│ │ └── MANIFEST.MF
│ ├── WEB-INF/
│ │ ├── spring/
│ │ │ └── appservlet/
│ │ │ └── servlet-context.xml
│ │ └── web.xml
│ ├── css/
│ │ └── styles.css
│ ├── dashboard.html
│ ├── forgot_password.html
│ ├── index.html
│ ├── js/
│ │ ├── bootstrap.js
│ │ ├── cookie.js
│ │ ├── enc-base64-min.js
│ │ ├── grid.locale-en.js
│ │ ├── javarest.js
│ │ ├── jquery-full-house.js
│ │ ├── sha256.js
│ │ ├── store.js
│ │ ├── user.js
│ │ └── verify.js
│ ├── request_email.html
│ ├── reset_password.html
│ ├── signup.html
│ └── validate.html
└── test/
├── groovy/
│ ├── BaseIntegrationTst.groovy
│ └── UserIntegrationTest.groovy
├── java/
│ └── com/
│ └── porterhead/
│ └── rest/
│ ├── authorization/
│ │ ├── BaseAuthorizationTst.java
│ │ ├── RequestSigningAuthorizationServiceTest.java
│ │ ├── SecurityContextTest.java
│ │ └── SessionTokenAuthorizationServiceTest.java
│ ├── filter/
│ │ └── SecurityContextFilterTest.java
│ ├── mock/
│ │ └── AppMockConfiguration.java
│ ├── resource/
│ │ ├── BaseResourceTst.java
│ │ ├── ConsumerSimpleSecurityFilter.java
│ │ ├── HealthCheckResourceTest.java
│ │ └── SimpleSecurityFilter.java
│ └── user/
│ ├── BaseServiceTest.java
│ ├── MailSenderServiceTest.java
│ ├── UserServiceTest.java
│ ├── VerificationServiceTest.java
│ ├── api/
│ │ ├── CreateUserRequestTest.java
│ │ ├── LoginRequestTest.java
│ │ ├── PasswordRequestTest.java
│ │ └── ValidationTst.java
│ ├── builder/
│ │ └── ExternalUserBuilder.java
│ ├── resource/
│ │ ├── PasswordResourceTest.java
│ │ ├── UserResourceTest.java
│ │ └── VerificationResourceTest.java
│ └── social/
│ ├── AbstractSocialTst.java
│ ├── JpaConnectionRepositoryTest.java
│ └── JpaUsersConnectionRepositoryTest.java
└── resources/
├── integration-test-context.xml
└── social-test-context.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
.gradle/*
build/*
out/*
*.iml
*.ipr
*.iws
/build/
/bin/
# eclipse
.settings/
.project
.classpath
# Intellij
.idea/
*.iml
*.iws
================================================
FILE: LICENSE.md
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
JAVA REST Application
====================
Simple and easily understandable web project that demonstrates the use of:
* Jersey + JAX-RS
* Spring Integration
* Spring Data + Hibernate
* Groovy Integration tests
* OAuth
* Velocity + Java Mail
* Facebook Login
* Password Reset
* Login/Sign Up + Email Verification
* JSR 303 Validation
NOTE. For a similar project that uses most of the same components but is built around OAuth2 see
<a href="http://porterhead.blogspot.co.uk/2014/05/securing-rest-services-with-spring.html">Securing Rest Services with OAuth2 and Spring Security</a>
to build:
gradle clean build integrationTest
or use the gradle wrapper:
./gradlew clean build integrationTest
go to /build/reports/emma for test coverage reports
to run:
gradle tomcatRun
navigate to http://localhost:8080/java-rest/
see blog posts:
THANK YOU
<ul>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-1.html">Part 1: An introduction to writing REST Services in Java</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-2.html">Part 2: User sign up and login</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-3.html">Part 3: Email Verification</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-4.html">Part 4: Facebook Authentication</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-5.html">Part 5: Lost Password</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-6.html">Part 6: Security & Authorization</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/03/writing-rest-services-in-java-part-7.html">Part 7: Moving to Production</a></li>
<li><a href="http://porterhead.blogspot.co.uk/2013/05/writing-rest-services-in-java-part-8.html">Part 8: JSR 303 Validation</a></li>
</ul>
================================================
FILE: build.gradle
================================================
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'tomcat'
apply plugin: 'war'
apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'jetty'
ext {
springVersion = "4.1.5.RELEASE"
h2Version = "1.3.155"
springDataVersion = "1.1.0.RELEASE"
springSocialVersion = "1.0.2.RELEASE"
springSocialFacebookVersion = "1.0.1.RELEASE"
springSocialTwitterVersion = "1.0.2.RELEASE"
springSecurity = "3.1.2.RELEASE"
springIntegrationVersion = "4.1.2.RELEASE"
aspectjrtVersion = "1.6.11"
jacksonVersion = "1.9.3"
commonsIoVersion = "1.4"
jerseyVersion = "1.9.1"
hibernateVersion = "3.6.7.Final"
h2Version = "1.3.154"
slf4jVersion = "1.6.1"
logbackVersion = "1.0.1"
velocityVersion = "1.7"
groovyVersion = "2.0.0"
guavaVersion = "12.0"
hibernateValidatorVersion = "4.3.1.Final"
environmentBase = 'src/main/config/'
env = "ci"
tomcatVersion = '7.0.25'
}
configurations {
emma
}
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.0'
}
}
repositories {
mavenCentral()
maven {
url "http://maven.springframework.org/milestone"
}
}
// A list of all of our project dependencies.
dependencies {
compile "org.hibernate:hibernate-core:$hibernateVersion",
"org.hibernate:hibernate-entitymanager:$hibernateVersion",
"org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
"org.hibernate:hibernate-validator:4.1.0.Final",
"org.springframework.data:spring-data-jpa:$springDataVersion",
"com.h2database:h2:$h2Version",
"mysql:mysql-connector-java:5.1.16",
"commons-dbcp:commons-dbcp:1.3",
"commons-codec:commons-codec:1.6",
"org.springframework.social:spring-social-core:$springSocialVersion",
"org.springframework.social:spring-social-facebook:$springSocialFacebookVersion",
"org.springframework.social:spring-social-twitter:$springSocialTwitterVersion",
"org.springframework.social:spring-social-test:$springSocialVersion",
"org.springframework.security:spring-security-core:$springSecurity",
"org.aspectj:aspectjrt:$aspectjrtVersion",
"org.codehaus.jackson:jackson-core-asl:$jacksonVersion",
"org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion",
"org.codehaus.jackson:jackson-xc:$jacksonVersion",
"commons-io:commons-io:$commonsIoVersion",
"javax.ws.rs:jsr311-api:1.1",
"javax.annotation:jsr250-api:1.0",
"com.sun.jersey:jersey-core:$jerseyVersion",
"com.sun.jersey:jersey-server:$jerseyVersion",
"com.sun.jersey:jersey-json:$jerseyVersion",
"com.sun.jersey.contribs:jersey-spring:$jerseyVersion",
"org.springframework:spring-core:$springVersion",
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-aop:$springVersion",
"org.springframework:spring-webmvc:$springVersion",
"org.springframework:spring-tx:$springVersion",
"org.springframework:spring-orm:$springVersion",
"org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-aspects:$springVersion",
"org.aspectj:aspectjweaver:1.5.4",
"cglib:cglib:2.2",
"com.google.guava:guava:$guavaVersion",
"org.hibernate:hibernate-validator:$hibernateValidatorVersion",
"javax.validation:validation-api:1.1.0.Final",
"org.slf4j:slf4j-api:$slf4jVersion",
"ch.qos.logback:logback-classic:$logbackVersion",
"ch.qos.logback:logback-core:$logbackVersion",
"org.mockito:mockito-all:1.8.5",
"org.springframework.integration:spring-integration-core:$springIntegrationVersion",
"org.springframework.integration:spring-integration-jdbc:$springIntegrationVersion",
"org.springframework.integration:spring-integration-mail:$springIntegrationVersion",
"org.springframework.integration:spring-integration-http:$springIntegrationVersion",
"org.apache.velocity:velocity:$velocityVersion",
"javax.mail:mail:1.4.5",
"joda-time:joda-time:2.1",
"commons-lang:commons-lang:2.6",
"commons-cli:commons-cli:1.2"
// Pull in test-time dependencies.
testCompile "junit:junit:4.12",
"org.springframework:spring-test:$springVersion",
//"org.codehaus.groovy.modules.http-builder:http-builder:0.5.2",
//"org.codehaus.groovy:groovy-all:$groovyVersion",
"org.hamcrest:hamcrest-all:1.1",
"com.sun.jersey:jersey-test-framework:$jerseyVersion",
"com.sun.jersey.jersey-test-framework:jersey-test-framework-grizzly2:$jerseyVersion",
"com.sun.jersey.jersey-test-framework:jersey-test-framework-core:$jerseyVersion",
"com.sun.jersey:jersey-grizzly2:$jerseyVersion",
"org.glassfish.grizzly:grizzly-http:2.1.2",
"org.glassfish.gmbal:gmbal-api-only:3.0.0-b023",
"org.glassfish.external:management-api:3.0.0-b012",
"org.glassfish.grizzly:grizzly-http-server:2.1.2",
"org.glassfish.grizzly:grizzly-rcm:2.1.2",
"org.glassfish.grizzly:grizzly-http-servlet:2.1.2",
"org.glassfish:javax.servlet:3.1",
"com.sun.jersey:jersey-client:$jerseyVersion"
testCompile("org.codehaus.groovy.modules.http-builder:http-builder:0.5.2") {
exclude group: 'org.codehaus.groovy'
}
testCompile "org.codehaus.groovy:groovy-all:2.0.0"
providedCompile "javax.servlet:servlet-api:2.5"
// Pull in tomcat dependencies
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
exclude group: "org.eclipse.jdt.core.compiler", module: "ecj"
}
emma "emma:emma:2.1.5320"
emma "emma:emma_ant:2.1.5320"
}
war {
baseName = "java-rest"
}
test {
exclude("**/*IntegrationTest*")
// jvmArgs "-XX:-UseSplitVerifier", "-Demma.coverage.out.file=$buildDir/tmp/emma/metadata.emma", "-Demma.coverage.out.merge=true"
//
// doFirst {
// println "Instrumenting the classes at " + sourceSets.main.output.classesDir.absolutePath
// // define the custom EMMA ant tasks
// ant.taskdef(resource: "emma_ant.properties", classpath: configurations.emma.asPath)
//
// ant.path(id: "run.classpath") {
// pathelement(location: sourceSets.main.output.classesDir.absolutePath)
// }
// def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma/instr")
// emmaInstDir.mkdirs()
// println "Creating $emmaInstDir to instrument from " + sourceSets.main.output.classesDir.absolutePath
// // instruct our compiled classes and store them at $buildDir/tmp/emma/instr
// ant.emma(enabled: 'true', verbosity: 'trace1') {
// instr(filter: "-com.porterhead.com.porterhead.rest.command.*", merge: "true", destdir: emmaInstDir.absolutePath, instrpathref: "run.classpath",
// metadatafile: new File(emmaInstDir, '/metadata.emma').absolutePath) {
// instrpath {
// fileset(dir: sourceSets.main.output.classesDir.absolutePath, includes: "**/*.class")
// }
// }
// }
// setClasspath(files("$buildDir/tmp/emma/instr") + configurations.emma + getClasspath())
// }
// doLast {
// def srcDir = sourceSets.main.java.srcDirs.toArray()[0]
// println "Creating test coverage reports for classes " + srcDir
// def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma")
// ant.emma(enabled: "true", verbosity: 'trace1') {
// new File("$buildDir/reports/emma").mkdirs()
// report(sourcepath: srcDir) {
// fileset(dir: emmaInstDir.absolutePath) {
// include(name: "**/*.emma")
// }
// txt(outfile: "$buildDir/reports/emma/coverage.txt")
// html(outfile: "$buildDir/reports/emma/coverage.html")
// xml(outfile: "$buildDir/reports/emma/coverage.xml")
// }
// }
// println "Test coverage reports available at $buildDir/reports/emma."
// println "txt: $buildDir/reports/emma/coverage.txt"
// println "Test $buildDir/reports/emma/coverage.html"
// println "Test $buildDir/reports/emma/coverage.xml"
// }
}
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
[jettyRun, jettyRunWar, jettyStop]*.stopPort = 8081
[jettyRun, jettyRunWar, jettyStop]*.stopKey = 'stopKey'
task integrationTest(type: Test) {
include '**/*IntegrationTest*.*'
doFirst {
jettyRun.daemon = true
jettyRun.execute()
}
doLast {
jettyStop.execute()
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Tue Jul 29 21:04:58 BST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-2.0-bin.zip
================================================
FILE: gradle.properties
================================================
systemProp.spring.profiles.active=dev
please accept pull request
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: src/main/config/ci/gradle.properties
================================================
tomcatContainerId=tomcat6x
tomcatPort=8080
tomcatHostname=localhost
tomcatUsername=admin
tomcatPassword=admin
tomcatContext=rest-java
================================================
FILE: src/main/java/com/porterhead/rest/api/ErrorResponse.java
================================================
package com.porterhead.rest.api;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 19/10/2012
*/
@XmlRootElement
public class ErrorResponse {
private String errorCode;
private String consumerMessage;
private String applicationMessage;
private List<ValidationError> validationErrors = new ArrayList<ValidationError>();
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getConsumerMessage() {
return consumerMessage;
}
public void setConsumerMessage(String consumerMessage) {
this.consumerMessage = consumerMessage;
}
public String getApplicationMessage() {
return applicationMessage;
}
public void setApplicationMessage(String applicationMessage) {
this.applicationMessage = applicationMessage;
}
public List<ValidationError> getValidationErrors() {
return validationErrors;
}
public void setValidationErrors(List<ValidationError> validationErrors) {
this.validationErrors = validationErrors;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/api/PagedQueryRequest.java
================================================
package com.porterhead.rest.api;
/**
* @version 1.0
* @author: Iain Porter
* @since 28/02/2013
*/
public class PagedQueryRequest {
public final static int DEFAULT_PAGE_SIZE = 50;
public final static int MAX_PAGE_SIZE = 100;
public final static String SORT_ORDER_ASCENDING = "asc";
public final static String SORT_ORDER_DESCENDING = "desc";
private int page;
private int pageSize;
private String sortProperty;
private String sortDirection;
private String searchToken;
public PagedQueryRequest(){}
public PagedQueryRequest(int page, int pageSize) {
this.page = page;
this.pageSize = pageSize;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getPageSize() {
return pageSize == 0 ? DEFAULT_PAGE_SIZE : pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public String getSortProperty() {
return sortProperty;
}
public void setSortProperty(String sortProperty) {
this.sortProperty = sortProperty;
}
public String getSortDirection() {
return sortDirection;
}
public void setSortDirection(String sortDirection) {
this.sortDirection = sortDirection;
}
public String getSearchToken() {
return searchToken;
}
public void setSearchToken(String searchToken) {
this.searchToken = searchToken;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/api/PagedResponse.java
================================================
package com.porterhead.rest.api;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
/**
* @version 1.0
* @author: Iain Porter
* @since 28/02/2013
*/
@XmlRootElement
public class PagedResponse<T> {
private int total;
private int page;
private long records;
private List<T> rows;
public PagedResponse() {}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public long getRecords() {
return records;
}
public void setRecords(long records) {
this.records = records;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/api/ValidationError.java
================================================
package com.porterhead.rest.api;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @version 1.0
* @author: Iain Porter
* @since 08/05/2013
*/
@XmlRootElement
public class ValidationError {
private String propertyName;
private String propertyValue;
private String message;
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public String getPropertyValue() {
return propertyValue;
}
public void setPropertyValue(String propertyValue) {
this.propertyValue = propertyValue;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/AuthorizationRequestContext.java
================================================
package com.porterhead.rest.authorization;
/**
*
* @version 1.0
* @author: Iain Porter
* @since 28/01/2013
*/
public class AuthorizationRequestContext {
/**
* The relative url of the request which starts at the root of the requested resource
*/
private final String requestUrl;
/**
* The Http method (POST, GET, DELETE, PUT)
*/
private final String httpMethod;
/**
* An Iso8061 formatted date timestamp
*/
private final String requestDateString;
/**
* Client generated unique nonce value
*/
private final String nonceToken;
/**
* The AuthorizationToken which should be in a format that the appropriate AuthorizationService can understand
*/
private final String authorizationToken;
public AuthorizationRequestContext(String requestUrl, String httpMethod, String requestDateString, String nonceToken, String hashedToken) {
this.requestUrl = requestUrl;
this.httpMethod = httpMethod;
this.requestDateString = requestDateString;
this.nonceToken = nonceToken;
this.authorizationToken = hashedToken;
}
public String getRequestUrl() {
return requestUrl;
}
public String getHttpMethod() {
return httpMethod;
}
public String getRequestDateString() {
return requestDateString;
}
public String getNonceToken() {
return nonceToken;
}
public String getAuthorizationToken() {
return authorizationToken;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/AuthorizationService.java
================================================
package com.porterhead.rest.authorization;
import com.porterhead.rest.user.api.ExternalUser;
/**
*
* @author: Iain Porter
*/
public interface AuthorizationService {
/**
* Given an AuthorizationRequestContext validate and authorize a User
*
* @param authorizationRequestContext the context required to authorize a user for a particular request
* @return ExternalUser
*/
public ExternalUser authorize(AuthorizationRequestContext authorizationRequestContext);
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/exception/InvalidAuthorizationHeaderException.java
================================================
package com.porterhead.rest.authorization.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 20/10/2012
*/
public class InvalidAuthorizationHeaderException extends BaseWebApplicationException {
public static final String DEVELOPER_MESSAGE = "Authorization failed. This could be due to missing properties in the header or" +
" the Authorization header may have been incorrectly hashed";
public InvalidAuthorizationHeaderException() {
super(401, "40101", "Authorization failed", DEVELOPER_MESSAGE);
}
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/impl/RequestSigningAuthorizationService.java
================================================
package com.porterhead.rest.authorization.impl;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.porterhead.rest.authorization.AuthorizationRequestContext;
import com.porterhead.rest.authorization.AuthorizationService;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.user.UserRepository;
import com.porterhead.rest.user.UserService;
import com.porterhead.rest.user.api.ExternalUser;
import com.porterhead.rest.user.domain.AuthorizationToken;
import com.porterhead.rest.user.domain.User;
import com.porterhead.rest.user.exception.AuthorizationException;
import com.porterhead.rest.util.DateUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Any Resource that requires a role must have a header property of the following format:
* <p/>
* <code>
* Authorization: <uuid of user>:<Signed Request>
* </code>
* <p/>
* The signed request hash is comprised of the session token + : + the relative url + , + the Http method + , + Date + , + nonce
* This string is then Sha-256 encoded and then Base64 encoded
* <p/>
* An example:
* <code>
* Example:
* 9fbc6f9a-af1b-4767-a492-c8462fd2a4d9:user/2e2ce9e8-798e-42b6-9326-fd2e56aef7aa/cards,POST,2012-06-30T12:00:00+01:00,34e321a7c4
* <p/>
* </code>
* <p/>
* This will be SHA-256 hashed and then Base64 encoded to produce:
* <p/>
* <code>
* HR/3DJp8RCGo50Wu+/3cr7ibdoNXKg1eYMt3HO5QoP4=
* </code>
* <p/>
* Authorization: 2e2ce9e8-798e-42b6-9326-fd2e56aef7aa:HR/3DJp8RCGo50Wu+/3cr7ibdoNXKg1eYMt3HO5QoP4=
*
* @author: Iain Porter
*/
public class RequestSigningAuthorizationService implements AuthorizationService {
Logger LOG = LoggerFactory.getLogger(RequestSigningAuthorizationService.class);
/**
* If the nonce already exists in the cache the difference between its timestamp and the current time will be
* greater than this value
*/
private static final int NONCE_CHECK_TOLERANCE_IN_MILLIS = 20;
/**
* Maximum Number of Nonce values in the cache
* The capacity will never be reached as long as the number of requests is below this value within the time range specified by
* ApplicationConfig.getSessionDateOffsetInMinutes()
*/
private static final int NONCE_CACHE_SIZE = 10000;
/**
* A an expiry cache that evicts nonce values after a configurable time period
*/
private LoadingCache<String, Nonce> nonceCache;
/**
* The configuration for the application
*/
private ApplicationConfig config;
/**
* User service required for persisting user objects
*/
private UserService userService;
/**
* directly access user objetcs
*/
private final UserRepository userRepository;
@Autowired
public RequestSigningAuthorizationService(UserRepository userRepository, UserService userService, ApplicationConfig applicationConfig) {
this.userService = userService;
this.userRepository = userRepository;
this.config = applicationConfig;
initNonceCache();
}
private void initNonceCache() {
nonceCache = CacheBuilder.newBuilder()
.maximumSize(NONCE_CACHE_SIZE)
.expireAfterWrite(config.getSessionDateOffsetInMinutes(), TimeUnit.MINUTES)
.build(
new CacheLoader<String, Nonce>() {
public Nonce load(String key) throws Exception {
return new Nonce(new DateTime(), key);
}
});
}
/**
* If the request contains values in the AuthorizationRequestContext attempt to find and validate a user
*
* @param context
* @return The request signature was valid and a user is returned or null if the context did not contain the information necessary
* to load a user
*/
public ExternalUser authorize(AuthorizationRequestContext context) {
ExternalUser externalUser = null;
if (context.getAuthorizationToken() != null && context.getRequestDateString() != null && context.getNonceToken() != null) {
String userId = null;
String hashedToken = null;
String[] token = context.getAuthorizationToken().split(":");
if (token.length == 2) {
userId = token[0];
hashedToken = token[1];
//make sure date and nonce is valid
validateRequestDate(context.getRequestDateString());
validateNonce(context.getNonceToken());
User user = userRepository.findByUuid(userId);
if (user != null) {
externalUser = new ExternalUser(user);
if (!isAuthorized(user, context, hashedToken)) {
throw new AuthorizationException("Request rejected due to an authorization failure");
}
}
}
}
return externalUser;
}
/**
* Authorize a hashed token against a request string
* The hashed token will be comprised of:
* the User's session token + the relative request Url + the Http Verb + the Date as ISO 8061 String + a nonce token generated by the client
* <code>
* Example:
* 9fbc6f9a-af1b-4767-a492-c8462fd2a4d9:user/2e2ce9e8-798e-42b6-9326-fd2e56aef7aa,GET,2012-06-30T12:00:00+01:00,34e321a7c4
* <p/>
* </code>
* <p/>
* This will be SHA-256 hashed and then Base64 encoded to produce:
* <p/>
* <code>
* HR/3DJp8RCGo50Wu+/3cr7ibdoNXKg1eYMt3HO5QoP4=
* </code>
*
* @param user should have a session token that will validate the request signature
* @param authorizationRequest the request containing all the details needed to authorize the request
* @param hashedToken the token to match against
* @return true if the token is authorized
*/
private boolean isAuthorized(User user, AuthorizationRequestContext authorizationRequest, String hashedToken) {
Assert.notNull(user);
Assert.notNull(authorizationRequest.getAuthorizationToken());
String unEncodedString = composeUnEncodedRequest(authorizationRequest);
AuthorizationToken authorizationToken = user.getAuthorizationToken();
String userTokenHash = encodeAuthToken(authorizationToken.getToken(), unEncodedString);
if (hashedToken.equals(userTokenHash)) {
return true;
}
LOG.error("Hash check failed for hashed token: {} for the following request: {} for user: {}",
new Object[]{authorizationRequest.getAuthorizationToken(), unEncodedString, user.getId()});
return false;
}
/**
* Encode the token by prefixing it with the User's Session Token
*
* @param token
* @return encoded token
*/
private String encodeAuthToken(String token, String unencodedRequest) {
byte[] digest = DigestUtils.sha256(token + ":" + unencodedRequest);
return new String(Base64.encodeBase64(digest));
}
/**
* The recipe to compose a signed request
*
* @param authRequest
* @return the string value to hash
*/
private String composeUnEncodedRequest(AuthorizationRequestContext authRequest) {
StringBuilder sb = new StringBuilder();
sb.append(authRequest.getRequestUrl());
sb.append(',');
sb.append(authRequest.getHttpMethod().toUpperCase());
sb.append(',');
sb.append(authRequest.getRequestDateString());
sb.append(',').append(authRequest.getNonceToken());
return sb.toString();
}
/**
* Ensure that the date of the request falls within the configured range
* @param requestDateString
*/
private void validateRequestDate(String requestDateString) {
Date date = DateUtil.getDateFromIso8061DateString(requestDateString);
DateTime now = new DateTime();
DateTime offset = new DateTime(date);
if (!(offset.isAfter(now.minusMinutes(config.getSessionDateOffsetInMinutes())) &&
offset.isBefore(now.plusMinutes(config.getSessionDateOffsetInMinutes())))) {
LOG.error("Date in header is out of range: {}", requestDateString);
throw new AuthorizationException("Date in header is out of range: " + requestDateString);
}
}
/**
* The nonce value sent by the client and used in the request signature should be unique across the system
* Nonce values will only be considered unique within the time limits of the cache.
* The value will be protected if the cache expiry time is within the limits of the request date range.
* If the date in the request is stale then the nonce value wil be irrelevant
*
* Note that the caching strategy will not work in a cluster. A distributed cache will be needed.
*
* @param nonceValue
*/
private void validateNonce(String nonceValue) {
Nonce nonce = nonceCache.getUnchecked(nonceValue);
Duration tolerance = new Duration(nonce.timestamp, new DateTime());
if (tolerance.isLongerThan(Duration.millis(NONCE_CHECK_TOLERANCE_IN_MILLIS))) {
LOG.error("Nonce value was not unique: {}", nonceValue);
throw new AuthorizationException("Nonce value is not unique");
}
}
private static class Nonce {
private DateTime timestamp;
private String nonceValue;
Nonce(DateTime time, String nonce) {
this.timestamp = time;
this.nonceValue = nonce;
}
}
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/impl/SecurityContextImpl.java
================================================
package com.porterhead.rest.authorization.impl;
import com.porterhead.rest.authorization.exception.InvalidAuthorizationHeaderException;
import com.porterhead.rest.user.api.ExternalUser;
import com.porterhead.rest.user.domain.Role;
import javax.ws.rs.core.SecurityContext;
import java.security.Principal;
/**
* Implementation of {@link javax.ws.rs.core.SecurityContext}
*
* User: porter
* Date: 16/03/2012
* Time: 16:13
*/
public class SecurityContextImpl implements SecurityContext {
private final ExternalUser user;
public SecurityContextImpl(ExternalUser user) {
this.user = user;
}
public Principal getUserPrincipal() {
return user;
}
public boolean isUserInRole(String role) {
if(role.equalsIgnoreCase(Role.anonymous.name())) {
return true;
}
if(user == null) {
throw new InvalidAuthorizationHeaderException();
}
return user.getRole().equalsIgnoreCase(role);
}
public boolean isSecure() {
return false;
}
public String getAuthenticationScheme() {
return SecurityContext.BASIC_AUTH;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/authorization/impl/SessionTokenAuthorizationService.java
================================================
package com.porterhead.rest.authorization.impl;
import com.porterhead.rest.authorization.AuthorizationRequestContext;
import com.porterhead.rest.authorization.AuthorizationService;
import com.porterhead.rest.user.UserRepository;
import com.porterhead.rest.user.api.ExternalUser;
import com.porterhead.rest.user.domain.AuthorizationToken;
import com.porterhead.rest.user.domain.User;
import com.porterhead.rest.user.exception.AuthorizationException;
import java.util.Date;
/**
*
* Simple authorization service that requires a session token in the Authorization header
* This is then matched to a user
*
* @version 1.0
* @author: Iain Porter
* @since 29/01/2013
*/
public class SessionTokenAuthorizationService implements AuthorizationService {
/**
* directly access user objects
*/
private final UserRepository userRepository;
public SessionTokenAuthorizationService(UserRepository repository) {
this.userRepository = repository;
}
public ExternalUser authorize(AuthorizationRequestContext securityContext) {
String token = securityContext.getAuthorizationToken();
ExternalUser externalUser = null;
if(token == null) {
return externalUser;
}
User user = userRepository.findBySession(token);
if(user == null) {
throw new AuthorizationException("Session token not valid");
}
AuthorizationToken authorizationToken = user.getAuthorizationToken();
if (authorizationToken.getToken().equals(token)) {
externalUser = new ExternalUser(user);
}
return externalUser;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/config/ApplicationConfig.java
================================================
package com.porterhead.rest.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
/**
* User: porter
* Date: 17/05/2012
* Time: 19:07
*/
@Configuration
@PropertySource({"classpath:/properties/app.properties"})
public class ApplicationConfig {
private final static String HOSTNAME_PROPERTY = "hostNameUrl";
private final static String SECURITY_AUTHORIZATION_REQUIRE_SIGNED_REQUESTS = "security.authorization.requireSignedRequests";
private final static String AUTHORIZATION_EXPIRY_DURATION = "authorization.timeToLive.inSeconds";
private final static String SESSION_DATE_OFFSET_IN_MINUTES = "session.date.offset.inMinutes";
private final static String TOKEN_EMAIL_REGISTRATION_DURATION = "token.emailRegistration.timeToLive.inMinutes";
private final static String TOKEN_EMAIL_VERIFICATION_DURATION = "token.emailVerification.timeToLive.inMinutes";
private final static String TOKEN_LOST_PASSWORD_DURATION = "token.lostPassword.timeToLive.inMinutes";
private final static String EMAIL_SERVICES_FROM_ADDRESS = "email.services.fromAddress";
private final static String EMAIL_SERVICES_REPLYTO_ADDRESS = "email.services.replyTo";
private final static String EMAIL_SERVICES_VERIFICATION_EMAIL_SUBJECT_TEXT = "email.services.emailVerificationSubjectText";
private final static String EMAIL_SERVICES_REGISTRATION_EMAIL_SUBJECT_TEXT = "email.services.emailRegistrationSubjectText";
private final static String EMAIL_SERVICES_LOST_PASSWORD_SUBJECT_TEXT = "email.services.lostPasswordSubjectText";
@Autowired
protected Environment environment;
public String getHostNameUrl() {
return environment.getProperty(HOSTNAME_PROPERTY);
}
public String getFacebookClientId() {
return environment.getProperty("facebook.clientId");
}
public String getFacebookClientSecret() {
return environment.getProperty("facebook.clientSecret");
}
public int getAuthorizationExpiryTimeInSeconds() {
return Integer.parseInt(environment.getProperty(AUTHORIZATION_EXPIRY_DURATION));
}
public int getSessionDateOffsetInMinutes() {
return Integer.parseInt(environment.getProperty(SESSION_DATE_OFFSET_IN_MINUTES));
}
public int getEmailRegistrationTokenExpiryTimeInMinutes() {
return Integer.parseInt(environment.getProperty(TOKEN_EMAIL_REGISTRATION_DURATION));
}
public int getEmailVerificationTokenExpiryTimeInMinutes() {
return Integer.parseInt(environment.getProperty(TOKEN_EMAIL_VERIFICATION_DURATION));
}
public int getLostPasswordTokenExpiryTimeInMinutes() {
return Integer.parseInt(environment.getProperty(TOKEN_LOST_PASSWORD_DURATION));
}
public String getEmailVerificationSubjectText() {
return environment.getProperty(EMAIL_SERVICES_VERIFICATION_EMAIL_SUBJECT_TEXT);
}
public String getEmailRegistrationSubjectText() {
return environment.getProperty(EMAIL_SERVICES_REGISTRATION_EMAIL_SUBJECT_TEXT);
}
public String getLostPasswordSubjectText() {
return environment.getProperty(EMAIL_SERVICES_LOST_PASSWORD_SUBJECT_TEXT);
}
public String getEmailFromAddress() {
return environment.getProperty(EMAIL_SERVICES_FROM_ADDRESS);
}
public String getEmailReplyToAddress() {
return environment.getProperty(EMAIL_SERVICES_REPLYTO_ADDRESS);
}
public Boolean requireSignedRequests() {
return environment.getProperty(SECURITY_AUTHORIZATION_REQUIRE_SIGNED_REQUESTS).equalsIgnoreCase("true");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/config/ApplicationDevConfig.java
================================================
package com.porterhead.rest.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 21/09/2012
*/
@Configuration
@Profile(value={"dev", "local"})
@PropertySource({"classpath:/properties/dev-app.properties"})
public class ApplicationDevConfig {
@Bean
public TextEncryptor textEncryptor() {
return Encryptors.noOpText();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/config/ApplicationProductionConfig.java
================================================
package com.porterhead.rest.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 21/09/2012
*/
@Configuration
@Profile(value="production")
@PropertySource({"classpath:/properties/production-app.properties"})
public class ApplicationProductionConfig {
@Autowired
Environment environment;
@Bean
public TextEncryptor textEncryptor() {
return Encryptors.queryableText(environment.getProperty("security.encryptPassword"),
environment.getProperty("security.encryptSalt"));
}
}
================================================
FILE: src/main/java/com/porterhead/rest/config/ApplicationStagingConfig.java
================================================
package com.porterhead.rest.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 21/09/2012
*/
@Configuration
@Profile(value="staging")
@PropertySource({"classpath:/properties/staging-app.properties"})
public class ApplicationStagingConfig {
@Autowired
Environment environment;
@Bean
public TextEncryptor textEncryptor() {
return Encryptors.queryableText(environment.getProperty("security.encryptPassword"),
environment.getProperty("security.encryptSalt"));
}
}
================================================
FILE: src/main/java/com/porterhead/rest/exception/ApplicationRuntimeException.java
================================================
package com.porterhead.rest.exception;
public class ApplicationRuntimeException extends BaseWebApplicationException {
public ApplicationRuntimeException(String applicationMessage) {
super(500, "50002", "Internal System error", applicationMessage);
}
}
================================================
FILE: src/main/java/com/porterhead/rest/exception/BaseWebApplicationException.java
================================================
package com.porterhead.rest.exception;
import com.porterhead.rest.api.ErrorResponse;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 19/10/2012
*/
public abstract class BaseWebApplicationException extends WebApplicationException {
private final int status;
private final String errorMessage;
private final String errorCode;
private final String developerMessage;
public BaseWebApplicationException(int httpStatus, String errorCode, String errorMessage, String developerMessage) {
this.status = httpStatus;
this.errorMessage = errorMessage;
this.errorCode = errorCode;
this.developerMessage = developerMessage;
}
@Override
public Response getResponse() {
return Response.status(status).type(MediaType.APPLICATION_JSON_TYPE).entity(getErrorResponse()).build();
}
public ErrorResponse getErrorResponse() {
ErrorResponse response = new ErrorResponse();
response.setErrorCode(errorCode);
response.setApplicationMessage(developerMessage);
response.setConsumerMessage(errorMessage);
return response;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/exception/NotFoundException.java
================================================
package com.porterhead.rest.exception;
import javax.ws.rs.WebApplicationException;
/**
* User: porter
* Date: 03/05/2012
* Time: 12:27
*/
public class NotFoundException extends WebApplicationException {
public NotFoundException() {
super(404);
}
}
================================================
FILE: src/main/java/com/porterhead/rest/exception/ValidationException.java
================================================
package com.porterhead.rest.exception;
import com.porterhead.rest.api.ErrorResponse;
import com.porterhead.rest.api.ValidationError;
import javax.validation.ConstraintViolation;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* User: porter
* Date: 03/05/2012
* Time: 21:43
*/
public class ValidationException extends WebApplicationException {
private final int status = 400;
private String errorMessage;
private String developerMessage;
private List<ValidationError> errors = new ArrayList<ValidationError>();
public ValidationException() {
errorMessage = "Validation Error";
developerMessage = "The data passed in the request was invalid. Please check and resubmit";
}
public ValidationException(String message) {
super();
errorMessage = message;
}
public ValidationException(Set<? extends ConstraintViolation<?>> violations) {
this();
for(ConstraintViolation<?> constraintViolation : violations) {
ValidationError error = new ValidationError();
error.setMessage(constraintViolation.getMessage());
error.setPropertyName(constraintViolation.getPropertyPath().toString());
error.setPropertyValue(constraintViolation.getInvalidValue() != null ? constraintViolation.getInvalidValue().toString() : null);
errors.add(error);
}
}
@Override
public Response getResponse() {
return Response.status(status).type(MediaType.APPLICATION_JSON_TYPE).entity(getErrorResponse()).build();
}
public ErrorResponse getErrorResponse() {
ErrorResponse response = new ErrorResponse();
response.setApplicationMessage(developerMessage);
response.setConsumerMessage(errorMessage);
response.setValidationErrors(errors);
return response;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/filter/ResourceFilterFactory.java
================================================
package com.porterhead.rest.filter;
import com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory;
import com.sun.jersey.api.model.AbstractMethod;
import com.sun.jersey.spi.container.ResourceFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.ws.rs.ext.Provider;
import java.util.ArrayList;
import java.util.List;
/**
* Add the SecurityContextFilter to the list of Filters to apply to requests
*
* This factory is registered with the Web Context:
*
* <code>
* <init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.porterhead.com.porterhead.rest.filter.ResourceFilterFactory</param-value>
</init-param>
* </code>
*
*
* @author: Iain Porter
*/
@Component
@Provider
public class ResourceFilterFactory extends RolesAllowedResourceFilterFactory {
@Autowired
private SecurityContextFilter securityContextFilter;
@Override
public List<ResourceFilter> create(AbstractMethod am) {
List<ResourceFilter> filters = super.create(am);
if (filters == null) {
filters = new ArrayList<ResourceFilter>();
}
List<ResourceFilter> securityFilters = new ArrayList<ResourceFilter>(filters);
//put the Security Filter first in line
securityFilters.add(0, securityContextFilter);
return securityFilters;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/filter/SecurityContextFilter.java
================================================
package com.porterhead.rest.filter;
import com.porterhead.rest.authorization.AuthorizationRequestContext;
import com.porterhead.rest.authorization.AuthorizationService;
import com.porterhead.rest.authorization.impl.RequestSigningAuthorizationService;
import com.porterhead.rest.authorization.impl.SecurityContextImpl;
import com.porterhead.rest.authorization.impl.SessionTokenAuthorizationService;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.user.UserRepository;
import com.porterhead.rest.user.UserService;
import com.porterhead.rest.user.api.ExternalUser;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.sun.jersey.spi.container.ResourceFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.ws.rs.ext.Provider;
/**
* A Servlet filter class for authorizing requests.
*
*
* The role of this filter class is to set a {@link javax.ws.rs.core.SecurityContext} in the {@link com.sun.jersey.spi.container.ContainerRequest}
*
* @see {@link com.porterhead.rest.authorization.impl.SecurityContextImpl}
*
* @author: Iain Porter
*/
@Component
@Provider
public class SecurityContextFilter implements ResourceFilter, ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(SecurityContextFilter.class);
protected static final String HEADER_AUTHORIZATION = "Authorization";
protected static final String HEADER_DATE = "x-java-rest-date";
protected static final String HEADER_NONCE = "nonce";
private AuthorizationService authorizationService;
ApplicationConfig config;
@Autowired
public SecurityContextFilter(UserRepository userRepository, UserService userService, ApplicationConfig config) {
delegateAuthorizationService(userRepository, userService, config);
this.config = config;
}
/**
* If there is an Authorisation header in the request extract the session token and retrieve the user
*
* Delegate to the AuthorizationService to validate the request
*
* If the request has a valid session token and the user is validated then a user object will be added to the security context
*
* Any Resource Controllers can assume the user has been validated and can merely authorize based on the role
*
* Resources with @PermitAll annotation do not require an Authorization header but will still be filtered
*
* @param request the ContainerRequest to filter
*
* @return the ContainerRequest with a SecurityContext added
*/
public ContainerRequest filter(ContainerRequest request) {
String authToken = request.getHeaderValue(HEADER_AUTHORIZATION);
String requestDateString = request.getHeaderValue(HEADER_DATE);
String nonce = request.getHeaderValue(HEADER_NONCE);
AuthorizationRequestContext context = new AuthorizationRequestContext(request.getPath(), request.getMethod(),
requestDateString, nonce, authToken);
ExternalUser externalUser = authorizationService.authorize(context);
request.setSecurityContext(new SecurityContextImpl(externalUser));
return request;
}
/**
* Specify the AuthorizationService that the application should use
*
* @param userRepository
* @param userService
* @param config
*/
private void delegateAuthorizationService(UserRepository userRepository, UserService userService, ApplicationConfig config) {
if(config.requireSignedRequests()) {
this.authorizationService = new RequestSigningAuthorizationService(userRepository, userService, config);
} else {
this.authorizationService = new SessionTokenAuthorizationService(userRepository);
}
}
public ContainerRequestFilter getRequestFilter() {
return this;
}
public ContainerResponseFilter getResponseFilter() {
return null;
}
@Autowired
public void setConfig(ApplicationConfig config) {
this.config = config;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/gateway/EmailServicesGateway.java
================================================
package com.porterhead.rest.gateway;
import com.porterhead.rest.user.EmailServiceTokenModel;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 11/09/2012
*/
public interface EmailServicesGateway {
public void sendVerificationToken(EmailServiceTokenModel model);
}
================================================
FILE: src/main/java/com/porterhead/rest/model/BaseEntity.java
================================================
package com.porterhead.rest.model;
import org.springframework.data.jpa.domain.AbstractPersistable;
import org.springframework.util.Assert;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import java.util.Date;
import java.util.UUID;
/**
* Base class for all JPA Entities
*
* @author : Iain Porter
*/
@MappedSuperclass
public abstract class BaseEntity extends AbstractPersistable<Long> {
@Version
private int version;
/**
* All objects will have a unique UUID which allows for the decoupling from DB generated ids
*
*/
@Column(length=36)
private String uuid;
private Date timeCreated;
public BaseEntity() {
this(UUID.randomUUID());
}
public BaseEntity(UUID guid) {
Assert.notNull(guid, "UUID is required");
setUuid(guid.toString());
this.timeCreated = new Date();
}
public UUID getUuid() {
return UUID.fromString(uuid);
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int hashCode() {
return getUuid().hashCode();
}
/**
* In most instances we can rely on the UUID to identify the object.
* Subclasses may want a user friendly identifier for constructing easy to read urls
*
* <code>
* /user/1883c578-76be-47fb-a5c1-7bbea3bf7fd0 using uuid as the identifier
*
* /user/jsmith using the username as the identifier
*
* </code>
*
* @return Object unique identifier for the object
*/
public Object getIdentifier() {
return getUuid().toString();
}
public int getVersion() {
return version;
}
public Date getTimeCreated() {
return timeCreated;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/resource/GenericExceptionMapper.java
================================================
package com.porterhead.rest.resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
/**
* User: porter
* Date: 22/03/2012
* Time: 15:56
*/
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
private static Logger LOG = LoggerFactory.getLogger(GenericExceptionMapper.class);
public Response toResponse(Exception exception) {
if (exception instanceof WebApplicationException) {
LOG.info("Web Application Exception: " + exception);
return ((WebApplicationException) exception).getResponse();
}
LOG.error("Internal Server Error: " + exception);
LOG.error("Internal Server Error: " + exception.getCause());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/resource/HealthCheckResource.java
================================================
package com.porterhead.rest.resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.security.PermitAll;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* User: porter
* Date: 11/04/2012
* Time: 15:21
*/
@Path("/healthcheck")
@Component
@Produces({MediaType.TEXT_PLAIN})
@PropertySource("classpath:properties/app.properties")
public class HealthCheckResource {
@Autowired
Environment env;
@PermitAll
@GET
public Response ping() {
return Response.ok().entity("Running version " + env.getProperty("application.version")).build();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/service/BaseService.java
================================================
package com.porterhead.rest.service;
import com.porterhead.rest.exception.ValidationException;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Set;
/**
* @version 1.0
* @author: Iain Porter
* @since 08/05/2013
*/
public abstract class BaseService {
private Validator validator;
public BaseService(Validator validator) {
this.validator = validator;
}
protected void validate(Object request) {
Set<? extends ConstraintViolation<?>> constraintViolations = validator.validate(request);
if (constraintViolations.size() > 0) {
throw new ValidationException(constraintViolations);
}
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/EmailServiceTokenModel.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.domain.User;
import com.porterhead.rest.user.domain.VerificationToken;
import org.apache.commons.codec.binary.Base64;
import java.io.Serializable;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 13/09/2012
*/
public class EmailServiceTokenModel implements Serializable {
private final String emailAddress;
private final String token;
private final VerificationToken.VerificationTokenType tokenType;
private final String hostNameUrl;
public EmailServiceTokenModel(User user, VerificationToken token, String hostNameUrl) {
this.emailAddress = user.getEmailAddress();
this.token = token.getToken();
this.tokenType = token.getTokenType();
this.hostNameUrl = hostNameUrl;
}
public String getEmailAddress() {
return emailAddress;
}
public String getEncodedToken() {
return new String(Base64.encodeBase64(token.getBytes()));
}
public String getToken() {
return token;
}
public VerificationToken.VerificationTokenType getTokenType() {
return tokenType;
}
public String getHostNameUrl() {
return hostNameUrl;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/SocialUserRepository.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.domain.SocialUser;
import com.porterhead.rest.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.util.MultiValueMap;
import java.util.List;
import java.util.Set;
/**
* User: porter
* Date: 15/05/2012
* Time: 16:35
*/
public interface SocialUserRepository extends JpaRepository<SocialUser, Long> {
List<SocialUser> findAllByUser(User user);
List<SocialUser> findByUserAndProviderId(User user, String providerId);
List<SocialUser> findByProviderIdAndProviderUserId(String providerId, String providerUserId);
//TODO will need a JPA Query here
List<SocialUser> findByUserAndProviderUserId(User user, MultiValueMap<String, String> providerUserIds);
@Query("Select userId from SocialUser where providerId = ? AND providerUserId in (?)")
Set<String> findByProviderIdAndProviderUserId(String providerId, Set<String> providerUserIds);
SocialUser findByUserAndProviderIdAndProviderUserId(User user, String providerId, String providerUserId);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/UserRepository.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.Date;
import java.util.List;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 12/04/2012
*/
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmailAddress(String emailAddress);
@Query("select u from User u where uuid = ?")
User findByUuid(String uuid);
@Query("select u from User u where u in (select user from AuthorizationToken where lastUpdated < ?)")
List<User> findByExpiredSession(Date lastUpdated);
@Query("select u from User u where u = (select user from AuthorizationToken where token = ?)")
User findBySession(String token);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/UserService.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.api.*;
import com.porterhead.rest.user.domain.AuthorizationToken;
import com.porterhead.rest.user.domain.Role;
import com.porterhead.rest.user.domain.User;
import org.springframework.social.connect.Connection;
/**
* @author: Iain Porter
*
* Service to manage users
*/
public interface UserService {
/**
* Create a new User with the given role
*
* @param request
* @param role
* @return AuthenticatedUserToken
*/
public AuthenticatedUserToken createUser(CreateUserRequest request, Role role);
/**
* Create a Default User with a given role
*
* @param role
* @return AuthenticatedUserToken
*/
public AuthenticatedUserToken createUser(Role role);
/**
* Login a User
*
* @param request
* @return AuthenticatedUserToken
*/
public AuthenticatedUserToken login(LoginRequest request);
/**
* Log in a User using Connection details from an authorized request from the User's supported Social provider
* encapsulated in the {@link org.springframework.social.connect.Connection} parameter
*
* @param connection containing the details of the authorized user account form the Social provider
* @return the User account linked to the {@link com.porterhead.rest.user.domain.SocialUser} account
*/
public AuthenticatedUserToken socialLogin(Connection<?> connection);
/**
* Get a User based on a unique identifier
*
* Identifiers supported are uuid, emailAddress
*
* @param userIdentifier
* @return User
*/
public ExternalUser getUser(ExternalUser requestingUser, String userIdentifier);
/**
* Delete user, only authenticated user accounts can be deleted
*
* @param userMakingRequest the user authorized to delete the user
* @param userId the id of the user to delete
*/
public void deleteUser(ExternalUser userMakingRequest, String userId);
/**
* Save User
*
* @param userId
* @param request
*/
public ExternalUser saveUser(String userId, UpdateUserRequest request);
/**
* Create an AuthorizationToken for the User
*
* @return
*/
public AuthorizationToken createAuthorizationToken(User user);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/UserServiceImpl.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.service.BaseService;
import com.porterhead.rest.user.api.*;
import com.porterhead.rest.user.domain.AuthorizationToken;
import com.porterhead.rest.user.domain.Role;
import com.porterhead.rest.user.domain.User;
import com.porterhead.rest.user.exception.AuthenticationException;
import com.porterhead.rest.user.exception.AuthorizationException;
import com.porterhead.rest.user.exception.DuplicateUserException;
import com.porterhead.rest.user.exception.UserNotFoundException;
import com.porterhead.rest.user.social.JpaUsersConnectionRepository;
import com.porterhead.rest.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.UserProfile;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.validation.Validator;
import java.util.List;
/**
* Service for managing User accounts
*
* @author: Iain Porter
*/
@Service("userService")
public class UserServiceImpl extends BaseService implements UserService {
/**
* For Social API handling
*/
private UsersConnectionRepository jpaUsersConnectionRepository;
private UserRepository userRepository;
private ApplicationConfig applicationConfig;
public UserServiceImpl(Validator validator) {
super(validator);
}
@Autowired
public UserServiceImpl(UsersConnectionRepository usersConnectionRepository,
Validator validator, ApplicationConfig applicationConfig) {
this(validator);
this.jpaUsersConnectionRepository = usersConnectionRepository;
((JpaUsersConnectionRepository)this.jpaUsersConnectionRepository).setUserService(this);
this.applicationConfig = applicationConfig;
}
private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);
/**
* {@inheritDoc}
*
* This method creates a User with the given Role. A check is made to see if the username already exists and a duplication
* check is made on the email address if it is present in the request.
* <P></P>
* The password is hashed and a AuthorizationToken generated for subsequent authorization of role-protected requests.
*
*/
@Transactional
public AuthenticatedUserToken createUser(CreateUserRequest request, Role role) {
validate(request);
User searchedForUser = userRepository.findByEmailAddress(request.getUser().getEmailAddress());
if (searchedForUser != null) {
throw new DuplicateUserException();
}
User newUser = createNewUser(request, role);
AuthenticatedUserToken token = new AuthenticatedUserToken(newUser.getUuid().toString(), createAuthorizationToken(newUser).getToken());
userRepository.save(newUser);
return token;
}
@Transactional
public AuthenticatedUserToken createUser(Role role) {
User user = new User();
user.setRole(role);
AuthenticatedUserToken token = new AuthenticatedUserToken(user.getUuid().toString(),
createAuthorizationToken(user).getToken());
userRepository.save(user);
return token;
}
/**
* {@inheritDoc}
*
* Login supports authentication against an email attribute.
* If a User is retrieved that matches, the password in the request is hashed
* and compared to the persisted password for the User account.
*/
@Transactional
public AuthenticatedUserToken login(LoginRequest request) {
validate(request);
User user = null;
user = userRepository.findByEmailAddress(request.getUsername());
if (user == null) {
throw new AuthenticationException();
}
String hashedPassword = null;
try {
hashedPassword = user.hashPassword(request.getPassword());
} catch (Exception e) {
throw new AuthenticationException();
}
if (hashedPassword.equals(user.getHashedPassword())) {
return new AuthenticatedUserToken(user.getUuid().toString(), createAuthorizationToken(user).getToken());
} else {
throw new AuthenticationException();
}
}
/**
* {@inheritDoc}
*
* Associate a Connection with a User account. If one does not exist a new User is created and linked to the
* {@link com.porterhead.rest.user.domain.SocialUser} represented in the Connection details.
*
* <P></P>
*
* A AuthorizationToken is generated and any Profile data that can be collected from the Social account is propagated to the User object.
*
*/
@Transactional
public AuthenticatedUserToken socialLogin(Connection<?> connection) {
List<String> userUuids = jpaUsersConnectionRepository.findUserIdsWithConnection(connection);
if(userUuids.size() == 0) {
throw new AuthenticationException();
}
User user = userRepository.findByUuid(userUuids.get(0)); //take the first one if there are multiple userIds for this provider Connection
if (user == null) {
throw new AuthenticationException();
}
updateUserFromProfile(connection, user);
return new AuthenticatedUserToken(user.getUuid().toString(), createAuthorizationToken(user).getToken());
}
/**
* Allow user to get their own profile or a user with administrator role to get any profile
*
* @param requestingUser
* @param userIdentifier
* @return user
*/
@Transactional
public ExternalUser getUser(ExternalUser requestingUser, String userIdentifier) {
Assert.notNull(requestingUser);
Assert.notNull(userIdentifier);
User user = ensureUserIsLoaded(userIdentifier);
if(!requestingUser.getId().equals(user.getUuid().toString()) && !requestingUser.getRole().equalsIgnoreCase(Role.administrator.toString())) {
throw new AuthorizationException("User not authorized to load profile");
}
return new ExternalUser(user);
}
@Transactional
public void deleteUser(ExternalUser userMakingRequest, String userId) {
Assert.notNull(userMakingRequest);
Assert.notNull(userId);
User userToDelete = ensureUserIsLoaded(userId);
if (userMakingRequest.getRole().equalsIgnoreCase(Role.administrator.toString()) && (userToDelete.hasRole(Role.anonymous) || userToDelete.hasRole(Role.authenticated))) {
userRepository.delete(userToDelete);
} else {
throw new AuthorizationException("User cannot be deleted. Only users with anonymous or authenticated role can be deleted.");
}
}
@Transactional
public ExternalUser saveUser(String userId, UpdateUserRequest request) {
validate(request);
User user = ensureUserIsLoaded(userId);
if(request.getFirstName() != null) {
user.setFirstName(request.getFirstName());
}
if(request.getLastName() != null) {
user.setLastName(request.getLastName());
}
if(request.getEmailAddress() != null) {
if(!request.getEmailAddress().equals(user.getEmailAddress())) {
user.setEmailAddress(request.getEmailAddress());
user.setVerified(false);
}
}
userRepository.save(user);
return new ExternalUser(user);
}
@Override
public AuthorizationToken createAuthorizationToken(User user) {
if(user.getAuthorizationToken() == null || user.getAuthorizationToken().hasExpired()) {
user.setAuthorizationToken(new AuthorizationToken(user, applicationConfig.getAuthorizationExpiryTimeInSeconds()));
userRepository.save(user);
}
return user.getAuthorizationToken();
}
private User createNewUser(CreateUserRequest request, Role role) {
User userToSave = new User(request.getUser());
try {
userToSave.setHashedPassword(userToSave.hashPassword(request.getPassword().getPassword()));
} catch (Exception e) {
throw new AuthenticationException();
}
userToSave.setRole(role);
return userToSave;
}
private void updateUserFromProfile(Connection<?> connection, User user) {
UserProfile profile = connection.fetchUserProfile();
user.setEmailAddress(profile.getEmail());
user.setFirstName(profile.getFirstName());
user.setLastName(profile.getLastName());
//users logging in from social network are already verified
user.setVerified(true);
if(user.hasRole(Role.anonymous)) {
user.setRole(Role.authenticated);
}
userRepository.save(user);
}
private User ensureUserIsLoaded(String userIdentifier) {
User user = null;
if (StringUtil.isValidUuid(userIdentifier)) {
user = userRepository.findByUuid(userIdentifier);
} else {
user = userRepository.findByEmailAddress(userIdentifier);
}
if (user == null) {
throw new UserNotFoundException();
}
return user;
}
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenRepository.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.domain.VerificationToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 14/09/2012
*/
public interface VerificationTokenRepository extends JpaRepository<VerificationToken, Long> {
@Query("select t from VerificationToken t where uuid = ?")
VerificationToken findByUuid(String uuid);
@Query("select t from VerificationToken t where token = ?")
VerificationToken findByToken(String token);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenService.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.user.api.LostPasswordRequest;
import com.porterhead.rest.user.api.PasswordRequest;
import com.porterhead.rest.user.domain.VerificationToken;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 10/09/2012
*/
public interface VerificationTokenService {
public VerificationToken sendEmailVerificationToken(String userId);
public VerificationToken sendEmailRegistrationToken(String userId);
public VerificationToken sendLostPasswordToken(LostPasswordRequest lostPasswordRequest);
public VerificationToken verify(String base64EncodedToken);
public VerificationToken generateEmailVerificationToken(String emailAddress);
public VerificationToken resetPassword(String base64EncodedToken, PasswordRequest passwordRequest);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenServiceImpl.java
================================================
package com.porterhead.rest.user;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.gateway.EmailServicesGateway;
import com.porterhead.rest.service.BaseService;
import com.porterhead.rest.user.api.LostPasswordRequest;
import com.porterhead.rest.user.api.PasswordRequest;
import com.porterhead.rest.user.domain.Role;
import com.porterhead.rest.user.domain.User;
import com.porterhead.rest.user.domain.VerificationToken;
import com.porterhead.rest.user.exception.*;
import com.porterhead.rest.util.StringUtil;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.validation.Validator;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 10/09/2012
*/
@Service("verificationTokenService")
public class VerificationTokenServiceImpl extends BaseService implements VerificationTokenService {
private VerificationTokenRepository tokenRepository;
private EmailServicesGateway emailServicesGateway;
private UserRepository userRepository;
ApplicationConfig config;
public VerificationTokenServiceImpl(Validator validator) {
super(validator);
}
@Autowired
public VerificationTokenServiceImpl(UserRepository userRepository, VerificationTokenRepository tokenRepository,
EmailServicesGateway emailServicesGateway, Validator validator) {
this(validator);
this.userRepository = userRepository;
this.tokenRepository = tokenRepository;
this.emailServicesGateway = emailServicesGateway;
}
@Transactional
public VerificationToken sendEmailVerificationToken(String userId) {
User user = ensureUserIsLoaded(userId);
return sendEmailVerificationToken(user);
}
private VerificationToken sendEmailVerificationToken(User user) {
VerificationToken token = new VerificationToken(user, VerificationToken.VerificationTokenType.emailVerification,
config.getEmailVerificationTokenExpiryTimeInMinutes());
user.addVerificationToken(token);
userRepository.save(user);
emailServicesGateway.sendVerificationToken(new EmailServiceTokenModel(user, token, getConfig().getHostNameUrl()));
return token;
}
@Transactional
public VerificationToken sendEmailRegistrationToken(String userId) {
User user = ensureUserIsLoaded(userId);
VerificationToken token = new VerificationToken(user,
VerificationToken.VerificationTokenType.emailRegistration,
config.getEmailRegistrationTokenExpiryTimeInMinutes());
user.addVerificationToken(token);
userRepository.save(user);
emailServicesGateway.sendVerificationToken(new EmailServiceTokenModel(user,
token, getConfig().getHostNameUrl()));
return token;
}
/**
* generate token if user found otherwise do nothing
*
* @param lostPasswordRequest
* @return a token or null if user not found
*/
@Transactional
public VerificationToken sendLostPasswordToken(LostPasswordRequest lostPasswordRequest) {
validate(lostPasswordRequest);
VerificationToken token = null;
User user = userRepository.findByEmailAddress(lostPasswordRequest.getEmailAddress());
if (user != null) {
token = user.getActiveLostPasswordToken();
if (token == null) {
token = new VerificationToken(user, VerificationToken.VerificationTokenType.lostPassword,
config.getLostPasswordTokenExpiryTimeInMinutes());
user.addVerificationToken(token);
userRepository.save(user);
}
emailServicesGateway.sendVerificationToken(new EmailServiceTokenModel(user, token, getConfig().getHostNameUrl()));
}
return token;
}
@Transactional
public VerificationToken verify(String base64EncodedToken) {
VerificationToken token = loadToken(base64EncodedToken);
if (token.isVerified() || token.getUser().isVerified()) {
throw new AlreadyVerifiedException();
}
token.setVerified(true);
token.getUser().setVerified(true);
userRepository.save(token.getUser());
return token;
}
@Transactional
public VerificationToken generateEmailVerificationToken(String emailAddress) {
Assert.notNull(emailAddress);
User user = userRepository.findByEmailAddress(emailAddress);
if (user == null) {
throw new UserNotFoundException();
}
if (user.isVerified()) {
throw new AlreadyVerifiedException();
}
//if token still active resend that
VerificationToken token = user.getActiveEmailVerificationToken();
if (token == null) {
token = sendEmailVerificationToken(user);
} else {
emailServicesGateway.sendVerificationToken(new EmailServiceTokenModel(user, token, getConfig().getHostNameUrl()));
}
return token;
}
@Transactional
public VerificationToken resetPassword(String base64EncodedToken, PasswordRequest passwordRequest) {
Assert.notNull(base64EncodedToken);
validate(passwordRequest);
VerificationToken token = loadToken(base64EncodedToken);
if (token.isVerified()) {
throw new AlreadyVerifiedException();
}
token.setVerified(true);
User user = token.getUser();
try {
user.setHashedPassword(user.hashPassword(passwordRequest.getPassword()));
} catch (Exception e) {
throw new AuthenticationException();
}
//set user to verified if not already and authenticated role
user.setVerified(true);
if (user.hasRole(Role.anonymous)) {
user.setRole(Role.authenticated);
}
userRepository.save(user);
return token;
}
private VerificationToken loadToken(String base64EncodedToken) {
Assert.notNull(base64EncodedToken);
String rawToken = new String(Base64.decodeBase64(base64EncodedToken));
VerificationToken token = tokenRepository.findByToken(rawToken);
if (token == null) {
throw new TokenNotFoundException();
}
if (token.hasExpired()) {
throw new TokenHasExpiredException();
}
return token;
}
@Autowired
public void setConfig(ApplicationConfig config) {
this.config = config;
}
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public ApplicationConfig getConfig() {
return this.config;
}
private User ensureUserIsLoaded(String userIdentifier) {
User user = null;
if (StringUtil.isValidUuid(userIdentifier)) {
user = userRepository.findByUuid(userIdentifier);
} else {
user = userRepository.findByEmailAddress(userIdentifier);
}
if (user == null) {
throw new UserNotFoundException();
}
return user;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/AuthenticatedUserToken.java
================================================
package com.porterhead.rest.user.api;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author: Iain Porter
*/
@XmlRootElement
public class AuthenticatedUserToken {
private String userId;
private String token;
public AuthenticatedUserToken(){}
public AuthenticatedUserToken(String userId, String sessionToken) {
this.userId = userId;
this.token = sessionToken;
}
public String getUserId() {
return userId;
}
public String getToken() {
return token;
}
public void setUserId(String userId) {
this.userId = userId;
}
public void setToken(String token) {
this.token = token;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/CreateUserRequest.java
================================================
package com.porterhead.rest.user.api;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author: Iain Porter
*/
@XmlRootElement
public class CreateUserRequest {
@NotNull
@Valid
private ExternalUser user;
@NotNull
@Valid
private PasswordRequest password;
public CreateUserRequest() {
}
public CreateUserRequest(final ExternalUser user, final PasswordRequest password) {
this.user = user;
this.password = password;
}
public ExternalUser getUser() {
return user;
}
public void setUser(ExternalUser user) {
this.user = user;
}
public PasswordRequest getPassword() {
return password;
}
public void setPassword(PasswordRequest password) {
this.password = password;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/EmailVerificationRequest.java
================================================
package com.porterhead.rest.user.api;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 15/09/2012
*/
@XmlRootElement
public class EmailVerificationRequest {
@NotNull
private String emailAddress;
public EmailVerificationRequest() {}
public EmailVerificationRequest(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/ExternalUser.java
================================================
package com.porterhead.rest.user.api;
import com.porterhead.rest.user.domain.AuthorizationToken;
import com.porterhead.rest.user.domain.SocialUser;
import com.porterhead.rest.user.domain.User;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author: Iain Porter
*/
@XmlRootElement
public class ExternalUser implements Principal {
private String id;
@Length(max=50)
private String firstName;
@Length(max=50)
private String lastName;
@NotNull
@Email
private String emailAddress;
private boolean isVerified;
@JsonIgnore
private String role;
private List<SocialProfile> socialProfiles = new ArrayList<SocialProfile>();
public ExternalUser() {}
public ExternalUser(String userId) {
this.id = userId;
}
public ExternalUser(User user) {
this.id = user.getUuid().toString();
this.emailAddress = user.getEmailAddress();
this.firstName = user.getFirstName();
this.lastName = user.getLastName();
this.isVerified = user.isVerified();
for(SocialUser socialUser: user.getSocialUsers()) {
SocialProfile profile = new SocialProfile();
profile.setDisplayName(socialUser.getDisplayName());
profile.setImageUrl(socialUser.getImageUrl());
profile.setProfileUrl(socialUser.getProfileUrl());
profile.setProvider(socialUser.getProviderId());
profile.setProviderUserId(socialUser.getProviderUserId());
socialProfiles.add(profile);
}
role = user.getRole().toString();
}
public ExternalUser(User user, AuthorizationToken activeSession) {
this(user);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public List<SocialProfile> getSocialProfiles() {
return socialProfiles;
}
public String getId() {
return id;
}
public boolean isVerified() {
return isVerified;
}
public String getName() {
return emailAddress;
}
public String getRole() {
return role;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/LoginRequest.java
================================================
package com.porterhead.rest.user.api;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author: Iain Porter
*/
@XmlRootElement
public class LoginRequest {
@NotNull
private String username;
@Length(min=8, max=30)
@NotNull
private String password;
public LoginRequest(){}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/LostPasswordRequest.java
================================================
package com.porterhead.rest.user.api;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 26/09/2012
*/
@XmlRootElement
public class LostPasswordRequest {
@NotNull
private String emailAddress;
public LostPasswordRequest() {}
public LostPasswordRequest(final String emailAddress) {
this.emailAddress = emailAddress;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/OAuth2Request.java
================================================
package com.porterhead.rest.user.api;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
* User: porter
* Date: 18/05/2012
* Time: 09:59
*/
@XmlRootElement
public class OAuth2Request {
private String accessToken;
@NotNull
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/PasswordRequest.java
================================================
package com.porterhead.rest.user.api;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 28/09/2012
*/
@XmlRootElement
public class PasswordRequest {
@Length(min=8, max=30)
@NotNull
private String password;
public PasswordRequest() {}
public PasswordRequest(final String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/SocialProfile.java
================================================
package com.porterhead.rest.user.api;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author: Iain Porter
*/
@XmlRootElement
public class SocialProfile {
String provider;
String providerUserId;
String profileUrl;
String imageUrl;
String displayName;
public SocialProfile() {}
public String getProvider() {
return provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public String getProviderUserId() {
return providerUserId;
}
public void setProviderUserId(String providerUserId) {
this.providerUserId = providerUserId;
}
public String getProfileUrl() {
return profileUrl;
}
public void setProfileUrl(String profileUrl) {
this.profileUrl = profileUrl;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/api/UpdateUserRequest.java
================================================
package com.porterhead.rest.user.api;
import org.hibernate.validator.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 05/10/2012
*/
@XmlRootElement
public class UpdateUserRequest {
private String firstName;
private String lastName;
@Email
@NotNull
private String emailAddress;
public UpdateUserRequest(){}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/AuthorizationToken.java
================================================
package com.porterhead.rest.user.domain;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.util.Date;
import java.util.UUID;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter
* @since 28/12/2012
*/
@Entity
@Table(name="rest_authorization_token")
public class AuthorizationToken extends AbstractPersistable<Long> {
private final static Integer DEFAULT_TIME_TO_LIVE_IN_SECONDS = (60 * 60 * 24 * 30); //30 Days
@Column(length=36)
private String token;
private Date timeCreated;
private Date expirationDate;
@JoinColumn(name = "user_id")
@OneToOne(fetch = FetchType.LAZY)
private User user;
public AuthorizationToken() {}
public AuthorizationToken(User user) {
this(user, DEFAULT_TIME_TO_LIVE_IN_SECONDS);
}
public AuthorizationToken(User user, Integer timeToLiveInSeconds) {
this.token = UUID.randomUUID().toString();
this.user = user;
this.timeCreated = new Date();
this.expirationDate = new Date(System.currentTimeMillis() + (timeToLiveInSeconds * 1000L));
}
public boolean hasExpired() {
return this.expirationDate != null && this.expirationDate.before(new Date());
}
public String getToken() {
return token;
}
public User getUser() {
return user;
}
public Date getTimeCreated() {
return timeCreated;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/Role.java
================================================
package com.porterhead.rest.user.domain;
/**
* User: porter
* Date: 03/04/2012
* Time: 13:17
*/
public enum Role {
authenticated, administrator, anonymous
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/SocialUser.java
================================================
package com.porterhead.rest.user.domain;
import com.porterhead.rest.model.BaseEntity;
import javax.persistence.*;
/**
* User: porter
* Date: 15/05/2012
* Time: 13:57
*/
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"userId", "providerId", "providerUserId"}),
@UniqueConstraint(columnNames = {"userId", "providerId", "rank"})})
public class SocialUser extends BaseEntity {
@ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "userId", nullable = false, updatable = false)
private User user;
private String providerId;
private String providerUserId;
private int rank;
private String displayName;
private String profileUrl;
private String imageUrl;
@Column(length = 500)
private String accessToken;
private String secret;
private String refreshToken;
private Long expireTime;
public String getProviderId() {
return providerId;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public String getProviderUserId() {
return providerUserId;
}
public void setProviderUserId(String providerUserId) {
this.providerUserId = providerUserId;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getProfileUrl() {
return profileUrl;
}
public void setProfileUrl(String profileUrl) {
this.profileUrl = profileUrl;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public Long getExpireTime() {
return expireTime;
}
public void setExpireTime(Long expireTime) {
this.expireTime = expireTime;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/SocialUserBuilder.java
================================================
package com.porterhead.rest.user.domain;
/**
* User: porter
* Date: 21/05/2012
* Time: 08:12
*/
public class SocialUserBuilder {
SocialUser user;
public static SocialUserBuilder create() {
return new SocialUserBuilder();
}
public SocialUserBuilder() {
user = new SocialUser();
}
public SocialUser build() {
return user;
}
public SocialUserBuilder withUser(User user) {
this.user.setUser(user);
return this;
}
public SocialUserBuilder withProviderId(String id) {
this.user.setProviderId(id);
return this;
}
public SocialUserBuilder withProviderUserId(String id) {
this.user.setProviderUserId(id);
return this;
}
public SocialUserBuilder withRank(int rank) {
this.user.setRank(rank);
return this;
}
public SocialUserBuilder withDisplayName(String name) {
this.user.setDisplayName(name);
return this;
}
public SocialUserBuilder withProfileUrl(String url) {
this.user.setProfileUrl(url);
return this;
}
public SocialUserBuilder withImageUrl(String url) {
this.user.setImageUrl(url);
return this;
}
public SocialUserBuilder withAccessToken(String token) {
this.user.setAccessToken(token);
return this;
}
public SocialUserBuilder withSecret(String secret) {
this.user.setSecret(secret);
return this;
}
public SocialUserBuilder withRefreshToken(String token) {
this.user.setRefreshToken(token);
return this;
}
public SocialUserBuilder withExpireTime(Long time) {
this.user.setExpireTime(time);
return this;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/User.java
================================================
package com.porterhead.rest.user.domain;
import com.porterhead.rest.model.BaseEntity;
import com.porterhead.rest.user.api.ExternalUser;
import com.porterhead.rest.util.HashUtil;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.springframework.util.StringUtils;
import javax.persistence.*;
import java.security.MessageDigest;
import java.util.*;
/**
* User: porter
* Date: 09/03/2012
* Time: 18:56
*/
@Entity
@Table(name="rest_user")
public class User extends BaseEntity {
/**
* Add additional salt to password hashing
*/
private static final String HASH_SALT = "d8a8e885-ecce-42bb-8332-894f20f0d8ed";
private static final int HASH_ITERATIONS = 1000;
private String firstName;
private String lastName;
private String emailAddress;
private String hashedPassword;
private boolean isVerified;
@Enumerated(EnumType.STRING)
private Role role;
@OneToMany(cascade={CascadeType.ALL}, mappedBy="user", fetch=FetchType.EAGER)
private Set<SocialUser> socialUsers = new HashSet<SocialUser>();
@OneToMany(mappedBy="user",
targetEntity=VerificationToken.class,
cascade= CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
private List<VerificationToken> verificationTokens = new ArrayList<VerificationToken>();
@OneToOne(fetch = FetchType.LAZY,
mappedBy = "user",
cascade = CascadeType.ALL)
private AuthorizationToken authorizationToken;
public User() {
this(UUID.randomUUID());
}
public User(UUID uuid) {
super(uuid);
setRole(Role.anonymous); //all users are anonymous until credentials are proved
}
public User(ExternalUser externalUser) {
this();
this.firstName = externalUser.getFirstName();
this.lastName = externalUser.getLastName();
this.emailAddress = externalUser.getEmailAddress();
}
public void setHashedPassword(String hashedPassword) {
this.hashedPassword = hashedPassword;
}
public String getHashedPassword() {
return this.hashedPassword;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public boolean hasRole(Role role) {
return role.equals(this.role);
}
public boolean equals(Object otherUser) {
boolean response = false;
if(otherUser == null) {
response = false;
}
else if(! (otherUser instanceof User)) {
response = false;
}
else {
if(((User)otherUser).getUuid().equals(this.getUuid())) {
response = true;
}
}
return response;
}
public int hashCode() {
return getUuid().hashCode();
}
public String getName() {
if(StringUtils.hasText(getFirstName())) {
return getFirstName() + " " + getLastName();
}
return "";
}
public Set<SocialUser> getSocialUsers() {
return socialUsers;
}
public void setSocialUsers(Set<SocialUser> socialUsers) {
this.socialUsers = socialUsers;
}
public void addSocialUser(SocialUser socialUser) {
getSocialUsers().add(socialUser);
}
public synchronized void addVerificationToken(VerificationToken token) {
verificationTokens.add(token);
}
public synchronized List<VerificationToken> getVerificationTokens() {
return Collections.unmodifiableList(this.verificationTokens);
}
public synchronized void setAuthorizationToken(AuthorizationToken token) {
this.authorizationToken = token;
}
public synchronized AuthorizationToken getAuthorizationToken() {
return authorizationToken;
}
/**
* If the user has a VerificationToken of type VerificationTokenType.lostPassword
* that is active return it otherwise return null
*
* @return verificationToken
*/
public VerificationToken getActiveLostPasswordToken() {
return getActiveToken(VerificationToken.VerificationTokenType.lostPassword);
}
/**
* If the user has a VerificationToken of type VerificationTokenType.emailVerification
* that is active return it otherwise return null
*
* @return verificationToken
*/
public VerificationToken getActiveEmailVerificationToken() {
return getActiveToken(VerificationToken.VerificationTokenType.emailVerification);
}
/**
* If the user has a VerificationToken of type VerificationTokenType.emailRegistration
* that is active return it otherwise return null
*
* @return verificationToken
*/
public VerificationToken getActiveEmailRegistrationToken() {
return getActiveToken(VerificationToken.VerificationTokenType.emailRegistration);
}
private VerificationToken getActiveToken(VerificationToken.VerificationTokenType tokenType) {
VerificationToken activeToken = null;
for (VerificationToken token : getVerificationTokens()) {
if (token.getTokenType().equals(tokenType)
&& !token.hasExpired() && !token.isVerified()) {
activeToken = token;
break;
}
}
return activeToken;
}
public boolean isVerified() {
return isVerified;
}
public void setVerified(boolean verified) {
isVerified = verified;
}
/**
* Hash the password using salt values
* See https://www.owasp.org/index.php/Hashing_Java
*
* @param passwordToHash
* @return hashed password
*/
public String hashPassword(String passwordToHash) throws Exception {
return hashToken(passwordToHash, getUuid().toString() + HASH_SALT );
}
private String hashToken(String token, String salt) throws Exception {
return HashUtil.byteToBase64(getHash(HASH_ITERATIONS, token, salt.getBytes()));
}
public byte[] getHash(int numberOfIterations, String password, byte[] salt) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.reset();
digest.update(salt);
byte[] input = digest.digest(password.getBytes("UTF-8"));
for (int i = 0; i < numberOfIterations; i++) {
digest.reset();
input = digest.digest(input);
}
return input;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/domain/VerificationToken.java
================================================
package com.porterhead.rest.user.domain;
import com.porterhead.rest.model.BaseEntity;
import org.joda.time.DateTime;
import javax.persistence.*;
import java.util.Date;
import java.util.UUID;
/**
* A token that gives the user permission to carry out a specific task once within a determined time period.
* An example would be a Lost Password token. The user receives the token embedded in a link.
* They send the token back to the server by clicking the link and the action is processed
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 10/09/2012
*/
@Entity
@Table(name = "rest_verification_token")
public class VerificationToken extends BaseEntity {
private static final int DEFAULT_EXPIRY_TIME_IN_MINS = 60 * 24; //24 hours
@Column(length=36)
private final String token;
private Date expiryDate;
@Enumerated(EnumType.STRING)
private VerificationTokenType tokenType;
private boolean verified;
@ManyToOne
@JoinColumn(name = "user_id")
User user;
public VerificationToken() {
super();
this.token = UUID.randomUUID().toString();
this.expiryDate = calculateExpiryDate(DEFAULT_EXPIRY_TIME_IN_MINS);
}
public VerificationToken(User user, VerificationTokenType tokenType, int expirationTimeInMinutes) {
this();
this.user = user;
this.tokenType = tokenType;
this.expiryDate = calculateExpiryDate(expirationTimeInMinutes);
}
public VerificationTokenType getTokenType() {
return tokenType;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Date getExpiryDate() {
return expiryDate;
}
public String getToken() {
return token;
}
private Date calculateExpiryDate(int expiryTimeInMinutes) {
DateTime now = new DateTime();
return now.plusMinutes(expiryTimeInMinutes).toDate();
}
public enum VerificationTokenType {
lostPassword, emailVerification, emailRegistration
}
public boolean hasExpired() {
DateTime tokenDate = new DateTime(getExpiryDate());
return tokenDate.isBeforeNow();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/AlreadyVerifiedException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 14/09/2012
*/
public class AlreadyVerifiedException extends BaseWebApplicationException {
public AlreadyVerifiedException() {
super(409, "40905", "Already verified", "The token has already been verified");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/AuthenticationException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
* User: porter
* Date: 13/03/2012
* Time: 08:58
*/
public class AuthenticationException extends BaseWebApplicationException {
public AuthenticationException() {
super(401, "40102", "Authentication Error", "Authentication Error. The username or password were incorrect");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/AuthorizationException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
* User: porter
* Date: 04/04/2012
* Time: 15:32
*/
public class AuthorizationException extends BaseWebApplicationException {
public AuthorizationException(String applicationMessage) {
super(403, "40301", "Not authorized", applicationMessage);
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/DuplicateUserException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
* User: porter
* Date: 12/03/2012
* Time: 15:10
*/
public class DuplicateUserException extends BaseWebApplicationException {
public DuplicateUserException() {
super(409, "40901", "User already exists", "An attempt was made to create a user that already exists");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/TokenHasExpiredException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 14/09/2012
*/
public class TokenHasExpiredException extends BaseWebApplicationException {
public TokenHasExpiredException() {
super(403, "40304", "Token has expired", "An attempt was made to load a token that has expired");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/TokenNotFoundException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 14/09/2012
*/
public class TokenNotFoundException extends BaseWebApplicationException {
public TokenNotFoundException() {
super(404, "40407", "Token Not Found", "No token could be found for that Id");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/exception/UserNotFoundException.java
================================================
package com.porterhead.rest.user.exception;
import com.porterhead.rest.exception.BaseWebApplicationException;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 12/09/2012
*/
public class UserNotFoundException extends BaseWebApplicationException {
public UserNotFoundException() {
super(404, "40402", "User Not Found", "No User could be found for that Id");
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/mail/MailSenderService.java
================================================
package com.porterhead.rest.user.mail;
import com.porterhead.rest.user.EmailServiceTokenModel;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 13/09/2012
*/
public interface MailSenderService {
public EmailServiceTokenModel sendVerificationEmail(EmailServiceTokenModel emailServiceTokenModel);
public EmailServiceTokenModel sendRegistrationEmail(EmailServiceTokenModel emailServiceTokenModel);
public EmailServiceTokenModel sendLostPasswordEmail(EmailServiceTokenModel emailServiceTokenModel);
}
================================================
FILE: src/main/java/com/porterhead/rest/user/mail/MockJavaMailSender.java
================================================
package com.porterhead.rest.user.mail;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* @author: Iain Porter
*/
public class MockJavaMailSender implements JavaMailSender {
List<MimeMessage> messages = new ArrayList<MimeMessage>();
public MimeMessage createMimeMessage() {
MimeMessage message = new MimeMessage(Session.getInstance(new Properties()));
return message;
}
public MimeMessage createMimeMessage(InputStream contentStream) throws MailException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void send(MimeMessage mimeMessage) throws MailException {
//To change body of implemented methods use File | Settings | File Templates.
}
public void send(MimeMessage[] mimeMessages) throws MailException {
//To change body of implemented methods use File | Settings | File Templates.
}
public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException {
try {
MimeMessage mimeMessage = createMimeMessage();
mimeMessagePreparator.prepare(mimeMessage);
messages.add(mimeMessage);
} catch(Exception e) {
System.out.println("Exception while preparing Mail Message" + e);
throw new RuntimeException(e);
}
}
public void send(MimeMessagePreparator[] mimeMessagePreparators) throws MailException {
//To change body of implemented methods use File | Settings | File Templates.
}
public void send(SimpleMailMessage simpleMessage) throws MailException {
//To change body of implemented methods use File | Settings | File Templates.
}
public void send(SimpleMailMessage[] simpleMessages) throws MailException {
//To change body of implemented methods use File | Settings | File Templates.
}
public List<MimeMessage> getMessages() {
return messages;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/mail/impl/MailSenderServiceImpl.java
================================================
package com.porterhead.rest.user.mail.impl;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.user.EmailServiceTokenModel;
import com.porterhead.rest.user.mail.*;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
import org.springframework.ui.velocity.VelocityEngineUtils;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.Map;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 13/09/2012
*/
@Service("mailSenderService")
public class MailSenderServiceImpl implements MailSenderService {
private static Logger LOG = LoggerFactory.getLogger(MailSenderServiceImpl.class);
private final JavaMailSender mailSender;
private final VelocityEngine velocityEngine;
private ApplicationConfig config;
@Autowired
public MailSenderServiceImpl(JavaMailSender mailSender, VelocityEngine velocityEngine) {
this.mailSender = mailSender;
this.velocityEngine = velocityEngine;
}
public EmailServiceTokenModel sendVerificationEmail(final EmailServiceTokenModel emailVerificationModel) {
Map<String, String> resources = new HashMap<String, String>();
return sendVerificationEmail(emailVerificationModel, config.getEmailVerificationSubjectText(),
"META-INF/velocity/VerifyEmail.vm", resources);
}
public EmailServiceTokenModel sendRegistrationEmail(final EmailServiceTokenModel emailVerificationModel) {
Map<String, String> resources = new HashMap<String, String>();
return sendVerificationEmail(emailVerificationModel, config.getEmailRegistrationSubjectText(),
"META-INF/velocity/RegistrationEmail.vm", resources);
}
public EmailServiceTokenModel sendLostPasswordEmail(final EmailServiceTokenModel emailServiceTokenModel) {
Map<String, String> resources = new HashMap<String, String>();
return sendVerificationEmail(emailServiceTokenModel, config.getLostPasswordSubjectText(),
"META-INF/velocity/LostPasswordEmail.vm", resources);
}
private void addInlineResource(MimeMessageHelper messageHelper, String resourcePath, String resourceIdentifier) throws MessagingException {
Resource resource = new ClassPathResource(resourcePath);
messageHelper.addInline(resourceIdentifier, resource);
}
private EmailServiceTokenModel sendVerificationEmail(final EmailServiceTokenModel emailVerificationModel, final String emailSubject,
final String velocityModel, final Map<String, String> resources) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, MimeMessageHelper.MULTIPART_MODE_RELATED, "UTF-8");
messageHelper.setTo(emailVerificationModel.getEmailAddress());
messageHelper.setFrom(config.getEmailFromAddress());
messageHelper.setReplyTo(config.getEmailReplyToAddress());
messageHelper.setSubject(emailSubject);
Map model = new HashMap();
model.put("model", emailVerificationModel);
String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, velocityModel, model);
messageHelper.setText(new String(text.getBytes(), "UTF-8"), true);
for(String resourceIdentifier: resources.keySet()) {
addInlineResource(messageHelper, resources.get(resourceIdentifier), resourceIdentifier);
}
}
};
LOG.debug("Sending {} token to : {}",emailVerificationModel.getTokenType().toString(), emailVerificationModel.getEmailAddress());
this.mailSender.send(preparator);
return emailVerificationModel;
}
@Autowired
public void setConfig(ApplicationConfig config) {
this.config = config;
}
public ApplicationConfig getConfig() {
return this.config;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/resource/PasswordResource.java
================================================
package com.porterhead.rest.user.resource;
import com.porterhead.rest.user.VerificationTokenService;
import com.porterhead.rest.user.api.LostPasswordRequest;
import com.porterhead.rest.user.api.PasswordRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.security.PermitAll;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
*
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 28/09/2012
*/
@Path("password")
@Component
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class PasswordResource {
@Autowired
protected VerificationTokenService verificationTokenService;
@PermitAll
@Path("tokens")
@POST
public Response sendEmailToken(LostPasswordRequest request) {
verificationTokenService.sendLostPasswordToken(request);
return Response.ok().build();
}
@PermitAll
@Path("tokens/{token}")
@POST
public Response resetPassword(@PathParam("token") String base64EncodedToken, PasswordRequest request) {
verificationTokenService.resetPassword(base64EncodedToken, request);
return Response.ok().build();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/resource/UserResource.java
================================================
package com.porterhead.rest.user.resource;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.gateway.EmailServicesGateway;
import com.porterhead.rest.user.UserService;
import com.porterhead.rest.user.VerificationTokenService;
import com.porterhead.rest.user.api.*;
import com.porterhead.rest.user.domain.Role;
import com.porterhead.rest.user.exception.AuthorizationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.net.URI;
/**
* User: porter
* Date: 12/03/2012
* Time: 18:57
*/
@Path("/user")
@Component
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class UserResource {
private ConnectionFactoryLocator connectionFactoryLocator;
@Autowired
protected UserService userService;
@Autowired
protected VerificationTokenService verificationTokenService;
@Autowired
protected EmailServicesGateway emailServicesGateway;
@Context
protected UriInfo uriInfo;
@Autowired
ApplicationConfig config;
@Autowired
public UserResource(ConnectionFactoryLocator connectionFactoryLocator) {
this.connectionFactoryLocator = connectionFactoryLocator;
}
@PermitAll
@POST
public Response signupUser(CreateUserRequest request) {
AuthenticatedUserToken token = userService.createUser(request, Role.authenticated);
verificationTokenService.sendEmailRegistrationToken(token.getUserId());
URI location = uriInfo.getAbsolutePathBuilder().path(token.getUserId()).build();
return Response.created(location).entity(token).build();
}
@RolesAllowed("admin")
@Path("{userId}")
@DELETE
public Response deleteUser(@Context SecurityContext sc, @PathParam("userId") String userId) {
ExternalUser userMakingRequest = (ExternalUser)sc.getUserPrincipal();
userService.deleteUser(userMakingRequest, userId);
return Response.ok().build();
}
@PermitAll
@Path("login")
@POST
public Response login(LoginRequest request) {
AuthenticatedUserToken token = userService.login(request);
return getLoginResponse(token);
}
@PermitAll
@Path("login/{providerId}")
@POST
public Response socialLogin(@PathParam("providerId") String providerId, OAuth2Request request) {
OAuth2ConnectionFactory<?> connectionFactory = (OAuth2ConnectionFactory<?>) connectionFactoryLocator.getConnectionFactory(providerId);
Connection<?> connection = connectionFactory.createConnection(new AccessGrant(request.getAccessToken()));
AuthenticatedUserToken token = userService.socialLogin(connection);
return getLoginResponse(token);
}
@RolesAllowed({"authenticated"})
@Path("{userId}")
@GET
public Response getUser(@Context SecurityContext sc, @PathParam("userId") String userId) {
ExternalUser userMakingRequest = (ExternalUser)sc.getUserPrincipal();
ExternalUser user = userService.getUser(userMakingRequest, userId);
return Response.ok().entity(user).build();
}
@RolesAllowed({"authenticated"})
@Path("{userId}")
@PUT
public Response updateUser(@Context SecurityContext sc, @PathParam("userId") String userId, UpdateUserRequest request) {
ExternalUser userMakingRequest = (ExternalUser)sc.getUserPrincipal();
if(!userMakingRequest.getId().equals(userId)) {
throw new AuthorizationException("User not authorized to modify this profile");
}
boolean sendVerificationToken = StringUtils.hasLength(request.getEmailAddress()) &&
!request.getEmailAddress().equals(userMakingRequest.getEmailAddress());
ExternalUser savedUser = userService.saveUser(userId, request);
if(sendVerificationToken) {
verificationTokenService.sendEmailVerificationToken(savedUser.getId());
}
return Response.ok().build();
}
private Response getLoginResponse(AuthenticatedUserToken token) {
URI location = UriBuilder.fromPath(uriInfo.getBaseUri() + "user/" + token.getUserId()).build();
return Response.ok().entity(token).contentLocation(location).build();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/resource/VerificationResource.java
================================================
package com.porterhead.rest.user.resource;
import com.porterhead.rest.user.VerificationTokenService;
import com.porterhead.rest.user.api.EmailVerificationRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.security.PermitAll;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* @version 1.0
* @author: Iain Porter iain.porter@porterhead.com
* @since 14/09/2012
*/
@Path("verify")
@Component
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class VerificationResource {
@Autowired
protected VerificationTokenService verificationTokenService;
@PermitAll
@Path("tokens/{token}")
@POST
public Response verifyToken(@PathParam("token") String token) {
verificationTokenService.verify(token);
return Response.ok().build();
}
@PermitAll
@Path("tokens")
@POST
public Response sendEmailToken(EmailVerificationRequest request) {
verificationTokenService.generateEmailVerificationToken(request.getEmailAddress());
return Response.ok().build();
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/social/JpaConnectionRepository.java
================================================
package com.porterhead.rest.user.social;
import com.porterhead.rest.user.SocialUserRepository;
import com.porterhead.rest.user.UserRepository;
import com.porterhead.rest.user.domain.SocialUser;
import com.porterhead.rest.user.domain.SocialUserBuilder;
import com.porterhead.rest.user.domain.User;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.social.connect.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.util.*;
/**
* User: porter
* Date: 15/05/2012
* Time: 16:13
*/
public class JpaConnectionRepository implements ConnectionRepository {
private final SocialUserRepository socialUserRepository;
private final UserRepository userRepository;
private final User user;
private final ConnectionFactoryLocator connectionFactoryLocator;
private final TextEncryptor textEncryptor;
public JpaConnectionRepository(SocialUserRepository socialUserRepository, UserRepository userRepository, User user, ConnectionFactoryLocator locator, TextEncryptor encryptor) {
this.socialUserRepository = socialUserRepository;
this.userRepository = userRepository;
this.user = user;
this.connectionFactoryLocator = locator;
this.textEncryptor = encryptor;
}
public MultiValueMap<String, Connection<?>> findAllConnections() {
List<Connection<?>> resultList = connectionMapper.mapEntities(socialUserRepository.findAllByUser(user));
MultiValueMap<String, Connection<?>> connections = new LinkedMultiValueMap<String, Connection<?>>();
Set<String> registeredProviderIds = connectionFactoryLocator.registeredProviderIds();
for (String registeredProviderId : registeredProviderIds) {
connections.put(registeredProviderId, Collections.<Connection<?>>emptyList());
}
for (Connection<?> connection : resultList) {
String providerId = connection.getKey().getProviderId();
if (connections.get(providerId).size() == 0) {
connections.put(providerId, new LinkedList<Connection<?>>());
}
connections.add(providerId, connection);
}
return connections;
}
public List<Connection<?>> findConnections(String providerId) {
return connectionMapper.mapEntities(socialUserRepository.findByUserAndProviderId(user, providerId));
}
@SuppressWarnings("unchecked")
public <A> List<Connection<A>> findConnections(Class<A> apiType) {
List<?> connections = findConnections(getProviderId(apiType));
return (List<Connection<A>>) connections;
}
public MultiValueMap<String, Connection<?>> findConnectionsToUsers(MultiValueMap<String, String> providerUsers) {
if (providerUsers.isEmpty()) {
throw new IllegalArgumentException("Unable to execute find: no providerUsers provided");
}
List<Connection<?>> resultList = connectionMapper.mapEntities(socialUserRepository.findByUserAndProviderUserId(user, providerUsers));
MultiValueMap<String, Connection<?>> connectionsForUsers = new LinkedMultiValueMap<String, Connection<?>>();
for (Connection<?> connection : resultList) {
String providerId = connection.getKey().getProviderId();
List<String> userIds = providerUsers.get(providerId);
List<Connection<?>> connections = connectionsForUsers.get(providerId);
if (connections == null) {
connections = new ArrayList<Connection<?>>(userIds.size());
for (int i = 0; i < userIds.size(); i++) {
connections.add(null);
}
connectionsForUsers.put(providerId, connections);
}
String providerUserId = connection.getKey().getProviderUserId();
int connectionIndex = userIds.indexOf(providerUserId);
connections.set(connectionIndex, connection);
}
return connectionsForUsers;
}
public Connection<?> getConnection(ConnectionKey connectionKey) {
try {
return connectionMapper.mapEntity(socialUserRepository.findByUserAndProviderIdAndProviderUserId(user, connectionKey.getProviderId(), connectionKey.getProviderUserId()));
} catch (EmptyResultDataAccessException e) {
throw new NoSuchConnectionException(connectionKey);
}
}
@SuppressWarnings("unchecked")
public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) {
String providerId = getProviderId(apiType);
return (Connection<A>) getConnection(new ConnectionKey(providerId, providerUserId));
}
@SuppressWarnings("unchecked")
public <A> Connection<A> getPrimaryConnection(Class<A> apiType) {
String providerId = getProviderId(apiType);
Connection<A> connection = (Connection<A>) findPrimaryConnection(providerId);
if (connection == null) {
throw new NotConnectedException(providerId);
}
return connection;
}
@SuppressWarnings("unchecked")
public <A> Connection<A> findPrimaryConnection(Class<A> apiType) {
String providerId = getProviderId(apiType);
return (Connection<A>) findPrimaryConnection(providerId);
}
@Transactional
public void addConnection(Connection<?> connection) {
try {
ConnectionData data = connection.createData();
//TODO: currently only support 1 connection per user per provider (rank = 1)
int rank = 1;
//create a SocialUser and call save
SocialUser socialUser = SocialUserBuilder.create().withUser(user).withProviderId(data.getProviderId())
.withProviderUserId(data.getProviderUserId()).withRank(rank).withDisplayName(data.getDisplayName())
.withProfileUrl(data.getProfileUrl()).withImageUrl(data.getImageUrl()).withAccessToken(encrypt(data.getAccessToken()))
.withSecret(encrypt(data.getSecret())).withRefreshToken(encrypt(data.getRefreshToken()))
.withExpireTime(data.getExpireTime()).build();
socialUserRepository.save(socialUser);
} catch (DuplicateKeyException e) {
throw new DuplicateConnectionException(connection.getKey());
}
}
public void updateConnection(Connection<?> connection) {
ConnectionData data = connection.createData();
SocialUser socialUser = socialUserRepository.findByUserAndProviderIdAndProviderUserId(user, data.getProviderId(), data.getProviderUserId());
if(socialUser != null){
socialUser.setDisplayName(data.getDisplayName());
socialUser.setProfileUrl(data.getProfileUrl());
socialUser.setImageUrl(data.getImageUrl());
socialUser.setAccessToken(encrypt(data.getAccessToken()));
socialUser.setSecret(encrypt(data.getSecret()));
socialUser.setRefreshToken(encrypt(data.getRefreshToken()));
socialUser.setExpireTime(data.getExpireTime());
socialUser = socialUserRepository.save(socialUser);
}
}
public void removeConnections(String providerId) {
List<SocialUser> users = socialUserRepository.findByUserAndProviderId(user, providerId);
socialUserRepository.delete(users);
}
public void removeConnection(ConnectionKey connectionKey) {
SocialUser socialUser = socialUserRepository.findByUserAndProviderIdAndProviderUserId(user, connectionKey.getProviderId(), connectionKey.getProviderUserId());
socialUserRepository.delete(socialUser);
}
private Connection<?> findPrimaryConnection(String providerId) {
List<Connection<?>> connections = connectionMapper.mapEntities(socialUserRepository.findByUserAndProviderId(user, providerId));
if (connections.size() > 0) {
return connections.get(0);
} else {
return null;
}
}
private final ServiceProviderConnectionMapper connectionMapper = new ServiceProviderConnectionMapper();
private final class ServiceProviderConnectionMapper {
public List<Connection<?>> mapEntities(List<SocialUser> socialUsers){
List<Connection<?>> result = new ArrayList<Connection<?>>();
for(SocialUser user : socialUsers){
result.add(mapEntity(user));
}
return result;
}
public Connection<?> mapEntity(SocialUser socialUser){
ConnectionData connectionData = mapConnectionData(socialUser);
ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(connectionData.getProviderId());
return connectionFactory.createConnection(connectionData);
}
private ConnectionData mapConnectionData(SocialUser socialUser){
return new ConnectionData(socialUser.getProviderId(), socialUser.getProviderUserId(), socialUser.getDisplayName(), socialUser.getProfileUrl(), socialUser.getImageUrl(),
decrypt(socialUser.getAccessToken()), decrypt(socialUser.getSecret()), decrypt(socialUser.getRefreshToken()), expireTime(socialUser.getExpireTime()));
}
private String decrypt(String encryptedText) {
return encryptedText != null ? textEncryptor.decrypt(encryptedText) : encryptedText;
}
private Long expireTime(Long expireTime) {
return expireTime == null || expireTime == 0 ? null : expireTime;
}
}
private <A> String getProviderId(Class<A> apiType) {
return connectionFactoryLocator.getConnectionFactory(apiType).getProviderId();
}
private String encrypt(String text) {
return text != null ? textEncryptor.encrypt(text) : text;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/social/JpaUsersConnectionRepository.java
================================================
package com.porterhead.rest.user.social;
import com.porterhead.rest.user.domain.Role;
import com.porterhead.rest.user.domain.SocialUser;
import com.porterhead.rest.user.SocialUserRepository;
import com.porterhead.rest.user.UserRepository;
import com.porterhead.rest.user.UserService;
import com.porterhead.rest.user.domain.User;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.social.connect.*;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* User: porter
* Date: 15/05/2012
* Time: 15:01
*/
public class JpaUsersConnectionRepository implements UsersConnectionRepository {
private SocialUserRepository socialUserRepository;
private UserService userService;
private UserRepository userRepository;
private final ConnectionFactoryLocator connectionFactoryLocator;
private final TextEncryptor textEncryptor;
public JpaUsersConnectionRepository(final SocialUserRepository repository, final UserRepository userRepository,
final ConnectionFactoryLocator connectionFactoryLocator,
final TextEncryptor textEncryptor) {
this.socialUserRepository = repository;
this.userRepository = userRepository;
this.connectionFactoryLocator = connectionFactoryLocator;
this.textEncryptor = textEncryptor;
}
/**
* Find User with the Connection profile (providerId and providerUserId)
* If this is the first connection attempt there will be nor User so create one and
* persist the Connection information
* In reality there will only be one User associated with the Connection
*
* @param connection
* @return List of User Ids (see User.getUuid())
*/
public List<String> findUserIdsWithConnection(Connection<?> connection) {
List<String> userIds = new ArrayList<String>();
ConnectionKey key = connection.getKey();
List<SocialUser> users = socialUserRepository.findByProviderIdAndProviderUserId(key.getProviderId(), key.getProviderUserId());
if (!users.isEmpty()) {
for (SocialUser user : users) {
userIds.add(user.getUser().getUuid().toString());
}
return userIds;
}
//First time connected so create a User account or find one that is already created with the email address
User user = findUserFromSocialProfile(connection);
String userId;
if(user == null) {
userId = userService.createUser(Role.authenticated).getUserId();
} else {
userId = user.getUuid().toString();
}
//persist the Connection
createConnectionRepository(userId).addConnection(connection);
userIds.add(userId);
return userIds;
}
public Set<String> findUserIdsConnectedTo(String providerId, Set<String> providerUserIds) {
return socialUserRepository.findByProviderIdAndProviderUserId(providerId, providerUserIds);
}
public ConnectionRepository createConnectionRepository(String userId) {
if (userId == null) {
throw new IllegalArgumentException("userId cannot be null");
}
User user = userRepository.findByUuid(userId);
if(user == null) {
throw new IllegalArgumentException("User not Found");
}
return new JpaConnectionRepository(socialUserRepository, userRepository, user, connectionFactoryLocator, textEncryptor);
}
private User findUserFromSocialProfile(Connection connection) {
User user = null;
UserProfile profile = connection.fetchUserProfile();
if(profile != null && StringUtils.hasText(profile.getEmail())) {
user = userRepository.findByEmailAddress(profile.getEmail());
}
return user;
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/user/social/SocialConfig.java
================================================
package com.porterhead.rest.user.social;
import com.porterhead.rest.config.ApplicationConfig;
import com.porterhead.rest.user.SocialUserRepository;
import com.porterhead.rest.user.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.support.ConnectionFactoryRegistry;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
/**
* User: porter
* Date: 13/03/2012
* Time: 17:39
*/
@Configuration
public class SocialConfig {
@Autowired
ApplicationConfig config;
@Autowired
SocialUserRepository socialUserRepository;
@Autowired
UserRepository userRepository;
@Autowired
TextEncryptor textEncryptor;
@Bean
public ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(
config.getFacebookClientId(),
config.getFacebookClientSecret()));
return registry;
}
@Bean
public UsersConnectionRepository usersConnectionRepository() {
JpaUsersConnectionRepository usersConnectionRepository = new JpaUsersConnectionRepository(socialUserRepository, userRepository,
connectionFactoryLocator(), textEncryptor);
return usersConnectionRepository;
}
}
================================================
FILE: src/main/java/com/porterhead/rest/util/DateUtil.java
================================================
package com.porterhead.rest.util;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.util.Date;
/**
* @author: Iain Porter
*/
public class DateUtil {
private static final DateTimeFormatter ISO8061_FORMATTER = ISODateTimeFormat.dateTimeNoMillis();
public static Date getDateFromIso8061DateString(String dateString) {
return ISO8061_FORMATTER.parseDateTime(dateString).toDate();
}
public static String getCurrentDateAsIso8061String() {
DateTime today = new DateTime();
return ISO8061_FORMATTER.print(today);
}
public static String getDateDateAsIso8061String(DateTime date) {
return ISO8061_FORMATTER.print(date);
}
}
================================================
FILE: src/main/java/com/porterhead/rest/util/HashUtil.java
================================================
package com.porterhead.rest.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.IOException;
public class HashUtil {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Enter a String to sign");
System.exit(-1);
}
System.out.println("Signed String: " + signString(args[0]));
}
/**
* From a base 64 representation, returns the corresponding byte[]
*
* @param data String The base64 representation
* @return byte[]
* @throws java.io.IOException
*/
public static byte[] base64ToByte(String data) throws IOException {
return Base64.decodeBase64(data);
}
/**
* From a byte[] returns a base 64 representation
*
* @param data byte[]
* @return String
* @throws IOException
*/
public static String byteToBase64(byte[] data) {
return new String(Base64.encodeBase64(data));
}
private static String signString(String request) {
byte[] digest = DigestUtils.sha256(request);
return new String(Base64.encodeBase64(digest));
}
}
================================================
FILE: src/main/java/com/porterhead/rest/util/StringUtil.java
================================================
package com.porterhead.rest.util;
import org.springframework.util.StringUtils;
import java.util.regex.Pattern;
import static org.springframework.util.Assert.hasText;
/**
* Author: Iain porter
*/
public class StringUtil {
private static final Pattern UUID_PATTERN = Pattern.compile("^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$");
public static void minLength(String str, int len) throws IllegalArgumentException {
hasText(str);
if (str.length() < len) {
throw new IllegalArgumentException();
}
}
public static void maxLength(String str, int len) throws IllegalArgumentException {
hasText(str);
if (str.length() > len) {
throw new IllegalArgumentException();
}
}
public static void validEmail(String email) throws IllegalArgumentException {
minLength(email, 4);
maxLength(email, 255);
if (!email.contains("@") || StringUtils.containsWhitespace(email)) {
throw new IllegalArgumentException();
}
}
public static boolean isValidUuid(String uuid) {
return UUID_PATTERN.matcher(uuid).matches();
}
}
================================================
FILE: src/main/resources/META-INF/persistence.xml
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="samplePersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.porterhead.rest.user.domain.User</class>
<class>com.porterhead.rest.user.domain.SocialUser</class>
<class>com.porterhead.rest.user.domain.AuthorizationToken</class>
<class>com.porterhead.rest.user.domain.VerificationToken</class>
<properties>
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<!--<property name="hbm2ddl.auto" value="validate"/>-->
<property name="show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
</properties>
</persistence-unit>
</persistence>
================================================
FILE: src/main/resources/META-INF/spring/component-scan-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.porterhead.rest.authorization"/>
<context:component-scan base-package="com.porterhead.rest.filter"/>
<context:component-scan base-package="com.porterhead.rest.config"/>
<context:component-scan base-package="com.porterhead.rest.resource"/>
<context:component-scan base-package="com.porterhead.rest.user"/>
</beans>
================================================
FILE: src/main/resources/META-INF/spring/data-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="samplePersistenceUnit"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<jpa:repositories base-package="com.porterhead.rest.user" />
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
</bean>
<tx:annotation-driven/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<constructor-arg ref="database"/>
</bean>
<beans profile="dev">
<bean id="database" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:restDB"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
</beans>
<beans profile="local">
<bean id="database" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/javarest"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="initialSize" value="10"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="50"/>
<property name="minIdle" value="10"/>
<property name="timeBetweenEvictionRunsMillis" value="30000"/>
<property name="minEvictableIdleTimeMillis" value="6000"/>
</bean>
</beans>
<beans profile="staging">
<!-- staging database-->
</beans>
<beans profile="production">
<!-- production database -->
</beans>
</beans>
================================================
FILE: src/main/resources/META-INF/spring/email-services-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:gateway id="emailServicesGateway" service-interface="com.porterhead.rest.gateway.EmailServicesGateway"
default-reply-timeout="3000">
<int:method name="sendVerificationToken" request-channel="emailVerificationRouterChannel"
request-timeout="3000"/>
</int:gateway>
<int:channel id="emailVerificationRouterChannel">
<int:queue capacity="1000" message-store="emailVerificationMessageStore"/>
</int:channel>
<int:router id="emailVerificationRouter" input-channel="emailVerificationRouterChannel"
expression="payload.getTokenType()">
<int:poller fixed-rate="2000">
<int:transactional/>
</int:poller>
<int:mapping value="emailVerification" channel="emailVerificationTokenSendChannel"/>
<int:mapping value="emailRegistration" channel="emailRegistrationTokenSendChannel"/>
<int:mapping value="lostPassword" channel="emailLostPasswordTokenSendChannel"/>
</int:router>
<int:channel id="emailRegistrationTokenSendChannel"/>
<int:service-activator id="emailVerficationMailSenderService" input-channel="emailVerificationTokenSendChannel"
output-channel="nullChannel" ref="mailSenderService"
method="sendVerificationEmail">
</int:service-activator>
<int:channel id="emailVerificationTokenSendChannel"/>
<int:service-activator id="emailRegistrationMailSenderService" input-channel="emailRegistrationTokenSendChannel"
output-channel="nullChannel" ref="mailSenderService"
method="sendRegistrationEmail">
</int:service-activator>
<int:channel id="emailLostPasswordTokenSendChannel"/>
<int:service-activator id="emailLostPasswordSenderService" input-channel="emailLostPasswordTokenSendChannel"
output-channel="nullChannel" ref="mailSenderService"
method="sendLostPasswordEmail">
</int:service-activator>
<int:logging-channel-adapter id="emailVerificationLoggingChannel" level="DEBUG">
</int:logging-channel-adapter>
<beans profile="dev, local">
<bean id="emailVerificationMessageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
</beans>
<beans profile="production, staging">
<int-jdbc:message-store id="emailVerificationMessageStore" data-source="dataSource" region="emailVerification"/>
</beans>
</beans>
================================================
FILE: src/main/resources/META-INF/spring/email-template-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
<beans profile="production, staging">
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<!-- Email provider here-->
<property name="host" value=""/>
<property name="port" value=""/>
<property name="username" value=""/>
<property name="password" value=""/>
<property name="javaMailProperties">
<props>
<prop key="mail.debug">false</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
</beans>
<beans profile="dev, local">
<bean id="mailSender" class="com.porterhead.rest.user.mail.MockJavaMailSender">
</bean>
</beans>
</beans>
================================================
FILE: src/main/resources/META-INF/spring/root-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<import resource="component-scan-context.xml"/>
<import resource="social-configuration-context.xml"/>
<import resource="email-services-context.xml"/>
<import resource="data-context.xml"/>
<import resource="email-template-context.xml"/>
<bean id="validatorFactory" class="javax.validation.Validation" factory-method="buildDefaultValidatorFactory"/>
<bean id="validator" factory-bean="validatorFactory" factory-method="getValidator"/>
</beans>
================================================
FILE: src/main/resources/META-INF/spring/social-configuration-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.porterhead.rest.user.social.SocialConfig"/>
</beans>
================================================
FILE: src/main/resources/META-INF/velocity/LostPasswordEmail.vm
================================================
<!DOCTYPE html>
<html>
<head>
<title>Sample Rest Application</title>
</head>
<body style="margin: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #333333; background-color: #481267;">
<center>
<table style="width: 100%; height: 100%; background-color: #481267;">
<tr><td style="width: 100%;">
<table style="background-color: #ffffff; border-radius: 10px; width: 935px;">
<tr>
<td style="padding-bottom: 20px; padding-top: 10px; padding-left: 10px;"></td>
<!-- HEADER MESSAGE -->
<td style="padding-left: 30px; padding-bottom: 20px; padding-top: 10px;"><h2>Reset Password</h2></td>
<td style="padding-bottom: 20px; padding-top: 10px; padding-left: 10px;">
</td>
</tr>
<tr>
<td style="text-align: center; padding-top: 20px;" valign="top">
</td>
<td colspan="2" style="padding-left: 30px; border-left: 2px solid #E7E7E8;">
<!-- MESSAGE -->
<p>A request was submitted to reset the password for your account. Click through on the link below to reset your password within the next 24 hours.</p>
<p><a href="${model.getHostNameUrl()}/reset_password.html?${model.getEncodedToken()}">Password Reset</a></p>
<!-- LEGALESE -->
<div style="font-size: 12px;">
<p>Please don't reply to this automatically generated email.</p>
<p>What is this doing in my mailbox?</p>
<p>If you did not intend to reset your password, you do not need to click through on the link in this email. If you did not request a link to reset your password, and are concerned that your account is at risk, then please contact us through customer support at http://XXXXXXXXXX.</p>
<p>Thanks for using the Sample java REST Application!</p>
</div>
</td>
</tr>
</table>
</td></tr>
</table>
</center>
</body>
</html>
================================================
FILE: src/main/resources/META-INF/velocity/RegistrationEmail.vm
================================================
<!DOCTYPE html>
<html>
<head>
<title>Sample Web</title>
</head>
<body style="margin: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #333333; background-color: #F2F2F2;">
<table style="width: 100%; background-color: #F2F2F2; height: 100%;">
<tr><td style="width: 100%;">
<table style="background-color: #ffffff; border-radius: 10px; width: 935px;">
<tr>
<!-- HEADER MESSAGE -->
<td style="padding-left: 30px; padding-bottom: 20px; padding-top: 10px;"><h2>Welcome to the java-rest project</h2></td>
</tr>
<tr>
<td style="padding-left: 30px; border-left: 2px solid #E7E7E8;">
<!-- MESSAGE -->
<p>Thanks for coming on board to the sample java-rest project. <br/>
Your registration is complete when you <a href="${model.getHostNameUrl()}/validate.html?${model.getEncodedToken()}">click here</a> to validate your email address.</p>
<br>
<br>
<br>
<!-- LEGALESE -->
<div style="font-size: 12px;">
<p>Please don't reply to this automatically generated email.</p>
<p>What is this doing in my mailbox?</p>
<p>If you do not wish to sign up for the java-rest project, you do not need to click through on the link above, and we will not contact you again unless you request it. As such, there is no need to unsubscribe.</p>
<p>Thanks for trying the java-rest project!</p>
</div>
</td>
</tr>
</table>
</td></tr>
</table>
</body>
</html>
================================================
FILE: src/main/resources/META-INF/velocity/VerifyEmail.vm
================================================
<!DOCTYPE html>
<html>
<head>
<title>Verify Your Email</title>
</head>
<body style="margin: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #333333; background-color: #F2F2F2;">
<center>
<table style="width: 100%; background-color: #F2F2F2; height: 100%;">
<tr><td style="width: 100%;">
<table style="background-color: #ffffff; border-radius: 10px; width: 935px;">
<tr>
<td style="padding-bottom: 20px; padding-top: 10px; padding-left: 10px;"></td>
<!-- HEADER MESSAGE -->
<td style="padding-left: 30px; padding-bottom: 20px; padding-top: 10px;"><h2>Email Verification</h2></td>
<td style="padding-bottom: 20px; padding-top: 10px; padding-left: 10px;">
</td>
</tr>
<tr>
<td style="text-align: center; padding-top: 20px;" valign="top">
</td>
<td colspan="2" style="padding-left: 30px; border-left: 2px solid #E7E7E8;">
<!-- MESSAGE -->
<p>
To verify your email address for your XXXXXXXXXXX account click through on the link below within the next 48 hours.
</p>
<p>
<a href="${model.getHostNameUrl()}/validate.html?${model.getEncodedToken()}">Verify my Email Address</a>
</p>
<p>
Thanks for using XXXXXXXXX!
</p>
<!-- LEGALESE -->
<div style="font-size: 12px;">
<p>Please don't reply to this automatically generated email.</p>
<p>What is this doing in my mailbox?</p>
<p>If you do not wish to sign up for XXXXXXXXX, you do not need to click through on the link above, and we will not contact you again unless you request it. As such, there is no need to unsubscribe.</p>
<p>Thanks for trying XXXXXXXXX!</p>
</div>
</td>
</tr>
</table>
</td></tr>
</table>
</center>
</body>
</html>
================================================
FILE: src/main/resources/logback.xml
================================================
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
logbak: %d{HH:mm:ss.SSS} %logger{36} - %msg%n
</Pattern>
</layout>
</appender>
<logger name="com.porterhead.rest" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
================================================
FILE: src/main/resources/properties/app.properties
================================================
#The Facebook app credentials for supporting Facebook login
facebook.clientId=133718006790561
facebook.clientSecret=2f489f0978614f958101b3d6b1776990
#encryption keys to use for encrypt/decrypt functions
security.encryptPassword=yoursecurepassword!!!
security.encryptSalt=45ea2b40ef910eef32
#if true all authorized requests will need to be signed and include the appropriate header fields.
#See com.porterheadead.rest.authorization.impl.RequestSigningAuthorizationService
security.authorization.requireSignedRequests=true
#How long in seconds before authorizationToken expires
authorization.timeToLive.inSeconds=2592000
#How long in minutes to allow the request timestamp to differ from the server time
session.date.offset.inMinutes=15
#How long in minutes that the email registration token should remain active
token.emailRegistration.timeToLive.inMinutes=1440
#How long in minutes that the email verification token should remain active
token.emailVerification.timeToLive.inMinutes=1440
#How long in minutes that the lost password token should remain active
token.lostPassword.timeToLive.inMinutes=30
#The address that mail sent to users will see as the from
email.services.fromAddress=foo@example.com
#The address that mail sent to users will see as the replyTo
email.services.replyTo=foo@example.com
#Email subject text for the various emails sent
email.services.emailVerificationSubjectText=[Java-REST sample application] Please verify your email Address
email.services.emailRegistrationSubjectText=Welcome to the Java-REST sample application
email.services.lostPasswordSubjectText=[Java-REST sample application] Reset Password
application.version=1.0.0
================================================
FILE: src/main/resources/properties/dev-app.properties
================================================
hostNameUrl=http://localhost:8080/java-rest
================================================
FILE: src/main/resources/properties/production-app.properties
================================================
hostNameUrl=http://localhost:8080/java-rest
================================================
FILE: src/main/resources/properties/staging-app.properties
================================================
hostNameUrl=http://localhost:8080/java-rest
================================================
FILE: src/main/resources/schema/indexes.sql
================================================
CREATE UNIQUE INDEX user_uuid_IDX ON rest_user ( uuid);
CREATE INDEX user_email_address_IDX on rest_user (email_address);
CREATE UNIQUE INDEX verification_token_uuid_IDX ON rest_verification_token (uuid);
CREATE UNIQUE INDEX verification_token_token_IDX ON rest_verification_token (token);
CREATE UNIQUE INDEX session_token_last_updated_IDX ON rest_session_token (last_updated);
CREATE UNIQUE INDEX session_token_token_IDX ON rest_session_token (token);
================================================
FILE: src/main/resources/schema/message_store.sql
================================================
CREATE TABLE INT_MESSAGE (
MESSAGE_ID CHAR(36) NOT NULL PRIMARY KEY,
REGION VARCHAR(100),
CREATED_DATE DATETIME NOT NULL,
MESSAGE_BYTES BLOB
) ENGINE=InnoDB;
CREATE INDEX INT_MESSAGE_IX1 ON INT_MESSAGE (CREATED_DATE);
CREATE TABLE INT_GROUP_TO_MESSAGE (
GROUP_KEY CHAR(36) NOT NULL,
MESSAGE_ID CHAR(36) NOT NULL,
constraint MESSAGE_GROUP_PK primary key (GROUP_KEY, MESSAGE_ID)
) ENGINE=InnoDB;
CREATE TABLE INT_MESSAGE_GROUP (
GROUP_KEY CHAR(36) NOT NULL PRIMARY KEY,
REGION VARCHAR(100),
MARKED BIGINT,
COMPLETE BIGINT,
LAST_RELEASED_SEQUENCE BIGINT,
CREATED_DATE DATETIME NOT NULL,
UPDATED_DATE DATETIME DEFAULT NULL
) ENGINE=InnoDB;
alter table INT_MESSAGE modify MESSAGE_BYTES MEDIUMBLOB;
================================================
FILE: src/main/resources/schema/truncate_data.sql
================================================
-- truncate all data
TRUNCATE table social_user;
TRUNCATE table rest_session_token;
TRUNCATE table rest_verification_token;
TRUNCATE table rest_user;
================================================
FILE: src/main/webapp/META-INF/MANIFEST.MF
================================================
Manifest-Version: 1.0
Class-Path:
================================================
FILE: src/main/webapp/WEB-INF/spring/appservlet/servlet-context.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<beans:import resource="classpath:META-INF/spring/root-context.xml" />
</beans:beans>
================================================
FILE: src/main/webapp/WEB-INF/web.xml
================================================
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Example Java REST Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appservlet/servlet-context.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter-mapping>
<filter-name>jersey-servlet</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>jersey-servlet</filter-name>
<filter-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.porterhead.rest.resource, com.porterhead.rest.user.resource</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.porterhead.rest.filter.ResourceFilterFactory</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/(.*\.jsp|.*\.css|.*\.png|.*\.js|.*\.gif|.*\.jpg|.*\.pdf|.*\.html|(WEB-INF/jsp))</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
================================================
FILE: src/main/webapp/css/styles.css
================================================
/*---------------Site styles------------*/
body {
background-color: #5087A3;
color: white;
font-family: helvetica;
margin: auto;
padding: 0;
-webkit-font-smoothing: antialiased;
}
/**** sections *****/
#container {
margin: 0 auto;
margin-top: 20px;
width: 310px;
padding: 5px;
}
#logo{
text-align: center;
margin-bottom: 40px;
}
#footer {
margin-top: 20px;
text-align: center;
font-size: 12px;
}
.section {
background-color: #D8E0E0;
border-radius: 4px;
width: 290px;
padding: 10px;
color: #333333;
margin-bottom: 40px;
}
.section a {
color: #DAFFFF;
}
/****Components ****/
a{
color: #fff;
cursor: pointer;
text-decoration: none;
}
a:hover{
color: #fff;
text-decoration: underline;
}
a img {
border: 0;
}
input[type="password"], input[type="text"], input[type="email"] {
width: 100%;
border-radius: 0px;
-webkit-appearance: none;
height: 45px;
padding: 0px;
text-indent: 10px;
box-shadow: inset 0px 1px 3px rgba(0,0,0,.5);
border: none;
margin-bottom: 15px;
font-size: 14px;
}
button {
font-size: 16px;
background-color: #E0F0FF;
border: none;
box-shadow: 0px 1px 3px rgba(0,0,0,.5);
height: 45px;
width: 100%;
margin-bottom: 15px;
color: #fff;
font-weight: bold;
cursor: pointer;
border-radius: 3px;
background: -webkit-gradient(linear, left top, left bottom, from(#91c814), to(#74a020));
background: -moz-linear-gradient(top, #91c814, #74a020);
}
button:active{
box-shadow: inset 0px 1px 3px rgba(0,0,0,.5);
}
button:hover{
background: -webkit-gradient(linear, left top, left bottom, from(#96d319), to(#79a525));
background: -moz-linear-gradient(top, #96d319, #79a525);
}
.small_button {
width: 38%;
}
.medium_button {
width: 50%;
}
.success, .error {
font-size: 1.250em;
font-weight: bold;
text-align: center;
}
#error_message {
background-color: #f22931;
border-radius: 0px;
padding: 10px;
color: #ffffff;
display: none;
margin-bottom: 15px;
box-shadow: 0px 1px 3px rgba(0,0,0,.5);
}
#success_message {
background-color: #77b300;
border-radius: 0px;
padding: 10px;
color: #ffffff;
display: none;
margin-bottom: 15px;
box-shadow: 0px 1px 3px rgba(0,0,0,.5);
}
dd {
font-size: 12px;
}
.margin_below {
margin-bottom:15px;
}
/*---------------Nav-----------*/
#nav {
margin-bottom: 40px;
}
.unselected_tab:hover{
background: -webkit-gradient(linear, left top, left bottom, from(#96d319), to(#79a525));
background: -moz-linear-gradient(top, #96d319, #79a525);
}
.selected_tab{
background-color: #271036;
color: #fff;
font-size: 16px;
box-shadow: inset 0px 1px 3px rgba(0,0,0,.5);
}
.unselected_tab:active{
box-shadow: inset 0px 1px 3px rgba(0,0,0,.5);
}
.unselected_tab{
color: #fff;
background-color: #77b300;
font-size: 16px;
background: -webkit-gradient(linear, left top, left bottom, from(#91c814), to(#74a020));
background: -moz-linear-gradient(top, #91c814, #74a020);
b
gitextract_6sr2pa59/
├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src/
├── main/
│ ├── config/
│ │ └── ci/
│ │ └── gradle.properties
│ ├── java/
│ │ └── com/
│ │ └── porterhead/
│ │ └── rest/
│ │ ├── api/
│ │ │ ├── ErrorResponse.java
│ │ │ ├── PagedQueryRequest.java
│ │ │ ├── PagedResponse.java
│ │ │ └── ValidationError.java
│ │ ├── authorization/
│ │ │ ├── AuthorizationRequestContext.java
│ │ │ ├── AuthorizationService.java
│ │ │ ├── exception/
│ │ │ │ └── InvalidAuthorizationHeaderException.java
│ │ │ └── impl/
│ │ │ ├── RequestSigningAuthorizationService.java
│ │ │ ├── SecurityContextImpl.java
│ │ │ └── SessionTokenAuthorizationService.java
│ │ ├── config/
│ │ │ ├── ApplicationConfig.java
│ │ │ ├── ApplicationDevConfig.java
│ │ │ ├── ApplicationProductionConfig.java
│ │ │ └── ApplicationStagingConfig.java
│ │ ├── exception/
│ │ │ ├── ApplicationRuntimeException.java
│ │ │ ├── BaseWebApplicationException.java
│ │ │ ├── NotFoundException.java
│ │ │ └── ValidationException.java
│ │ ├── filter/
│ │ │ ├── ResourceFilterFactory.java
│ │ │ └── SecurityContextFilter.java
│ │ ├── gateway/
│ │ │ └── EmailServicesGateway.java
│ │ ├── model/
│ │ │ └── BaseEntity.java
│ │ ├── resource/
│ │ │ ├── GenericExceptionMapper.java
│ │ │ └── HealthCheckResource.java
│ │ ├── service/
│ │ │ └── BaseService.java
│ │ ├── user/
│ │ │ ├── EmailServiceTokenModel.java
│ │ │ ├── SocialUserRepository.java
│ │ │ ├── UserRepository.java
│ │ │ ├── UserService.java
│ │ │ ├── UserServiceImpl.java
│ │ │ ├── VerificationTokenRepository.java
│ │ │ ├── VerificationTokenService.java
│ │ │ ├── VerificationTokenServiceImpl.java
│ │ │ ├── api/
│ │ │ │ ├── AuthenticatedUserToken.java
│ │ │ │ ├── CreateUserRequest.java
│ │ │ │ ├── EmailVerificationRequest.java
│ │ │ │ ├── ExternalUser.java
│ │ │ │ ├── LoginRequest.java
│ │ │ │ ├── LostPasswordRequest.java
│ │ │ │ ├── OAuth2Request.java
│ │ │ │ ├── PasswordRequest.java
│ │ │ │ ├── SocialProfile.java
│ │ │ │ └── UpdateUserRequest.java
│ │ │ ├── domain/
│ │ │ │ ├── AuthorizationToken.java
│ │ │ │ ├── Role.java
│ │ │ │ ├── SocialUser.java
│ │ │ │ ├── SocialUserBuilder.java
│ │ │ │ ├── User.java
│ │ │ │ └── VerificationToken.java
│ │ │ ├── exception/
│ │ │ │ ├── AlreadyVerifiedException.java
│ │ │ │ ├── AuthenticationException.java
│ │ │ │ ├── AuthorizationException.java
│ │ │ │ ├── DuplicateUserException.java
│ │ │ │ ├── TokenHasExpiredException.java
│ │ │ │ ├── TokenNotFoundException.java
│ │ │ │ └── UserNotFoundException.java
│ │ │ ├── mail/
│ │ │ │ ├── MailSenderService.java
│ │ │ │ ├── MockJavaMailSender.java
│ │ │ │ └── impl/
│ │ │ │ └── MailSenderServiceImpl.java
│ │ │ ├── resource/
│ │ │ │ ├── PasswordResource.java
│ │ │ │ ├── UserResource.java
│ │ │ │ └── VerificationResource.java
│ │ │ └── social/
│ │ │ ├── JpaConnectionRepository.java
│ │ │ ├── JpaUsersConnectionRepository.java
│ │ │ └── SocialConfig.java
│ │ └── util/
│ │ ├── DateUtil.java
│ │ ├── HashUtil.java
│ │ └── StringUtil.java
│ ├── resources/
│ │ ├── META-INF/
│ │ │ ├── persistence.xml
│ │ │ ├── spring/
│ │ │ │ ├── component-scan-context.xml
│ │ │ │ ├── data-context.xml
│ │ │ │ ├── email-services-context.xml
│ │ │ │ ├── email-template-context.xml
│ │ │ │ ├── root-context.xml
│ │ │ │ └── social-configuration-context.xml
│ │ │ └── velocity/
│ │ │ ├── LostPasswordEmail.vm
│ │ │ ├── RegistrationEmail.vm
│ │ │ └── VerifyEmail.vm
│ │ ├── logback.xml
│ │ ├── properties/
│ │ │ ├── app.properties
│ │ │ ├── dev-app.properties
│ │ │ ├── production-app.properties
│ │ │ └── staging-app.properties
│ │ └── schema/
│ │ ├── indexes.sql
│ │ ├── message_store.sql
│ │ └── truncate_data.sql
│ └── webapp/
│ ├── META-INF/
│ │ └── MANIFEST.MF
│ ├── WEB-INF/
│ │ ├── spring/
│ │ │ └── appservlet/
│ │ │ └── servlet-context.xml
│ │ └── web.xml
│ ├── css/
│ │ └── styles.css
│ ├── dashboard.html
│ ├── forgot_password.html
│ ├── index.html
│ ├── js/
│ │ ├── bootstrap.js
│ │ ├── cookie.js
│ │ ├── enc-base64-min.js
│ │ ├── grid.locale-en.js
│ │ ├── javarest.js
│ │ ├── jquery-full-house.js
│ │ ├── sha256.js
│ │ ├── store.js
│ │ ├── user.js
│ │ └── verify.js
│ ├── request_email.html
│ ├── reset_password.html
│ ├── signup.html
│ └── validate.html
└── test/
├── groovy/
│ ├── BaseIntegrationTst.groovy
│ └── UserIntegrationTest.groovy
├── java/
│ └── com/
│ └── porterhead/
│ └── rest/
│ ├── authorization/
│ │ ├── BaseAuthorizationTst.java
│ │ ├── RequestSigningAuthorizationServiceTest.java
│ │ ├── SecurityContextTest.java
│ │ └── SessionTokenAuthorizationServiceTest.java
│ ├── filter/
│ │ └── SecurityContextFilterTest.java
│ ├── mock/
│ │ └── AppMockConfiguration.java
│ ├── resource/
│ │ ├── BaseResourceTst.java
│ │ ├── ConsumerSimpleSecurityFilter.java
│ │ ├── HealthCheckResourceTest.java
│ │ └── SimpleSecurityFilter.java
│ └── user/
│ ├── BaseServiceTest.java
│ ├── MailSenderServiceTest.java
│ ├── UserServiceTest.java
│ ├── VerificationServiceTest.java
│ ├── api/
│ │ ├── CreateUserRequestTest.java
│ │ ├── LoginRequestTest.java
│ │ ├── PasswordRequestTest.java
│ │ └── ValidationTst.java
│ ├── builder/
│ │ └── ExternalUserBuilder.java
│ ├── resource/
│ │ ├── PasswordResourceTest.java
│ │ ├── UserResourceTest.java
│ │ └── VerificationResourceTest.java
│ └── social/
│ ├── AbstractSocialTst.java
│ ├── JpaConnectionRepositoryTest.java
│ └── JpaUsersConnectionRepositoryTest.java
└── resources/
├── integration-test-context.xml
└── social-test-context.xml
SYMBOL INDEX (665 symbols across 100 files)
FILE: src/main/java/com/porterhead/rest/api/ErrorResponse.java
class ErrorResponse (line 13) | @XmlRootElement
method getErrorCode (line 22) | public String getErrorCode() {
method setErrorCode (line 26) | public void setErrorCode(String errorCode) {
method getConsumerMessage (line 30) | public String getConsumerMessage() {
method setConsumerMessage (line 34) | public void setConsumerMessage(String consumerMessage) {
method getApplicationMessage (line 38) | public String getApplicationMessage() {
method setApplicationMessage (line 42) | public void setApplicationMessage(String applicationMessage) {
method getValidationErrors (line 46) | public List<ValidationError> getValidationErrors() {
method setValidationErrors (line 50) | public void setValidationErrors(List<ValidationError> validationErrors) {
FILE: src/main/java/com/porterhead/rest/api/PagedQueryRequest.java
class PagedQueryRequest (line 8) | public class PagedQueryRequest {
method PagedQueryRequest (line 21) | public PagedQueryRequest(){}
method PagedQueryRequest (line 23) | public PagedQueryRequest(int page, int pageSize) {
method getPage (line 28) | public int getPage() {
method setPage (line 32) | public void setPage(int page) {
method getPageSize (line 36) | public int getPageSize() {
method setPageSize (line 40) | public void setPageSize(int pageSize) {
method getSortProperty (line 44) | public String getSortProperty() {
method setSortProperty (line 48) | public void setSortProperty(String sortProperty) {
method getSortDirection (line 52) | public String getSortDirection() {
method setSortDirection (line 56) | public void setSortDirection(String sortDirection) {
method getSearchToken (line 60) | public String getSearchToken() {
method setSearchToken (line 64) | public void setSearchToken(String searchToken) {
FILE: src/main/java/com/porterhead/rest/api/PagedResponse.java
class PagedResponse (line 11) | @XmlRootElement
method PagedResponse (line 19) | public PagedResponse() {}
method getTotal (line 21) | public int getTotal() {
method setTotal (line 25) | public void setTotal(int total) {
method getPage (line 29) | public int getPage() {
method setPage (line 33) | public void setPage(int page) {
method getRecords (line 37) | public long getRecords() {
method setRecords (line 41) | public void setRecords(long records) {
method getRows (line 45) | public List<T> getRows() {
method setRows (line 49) | public void setRows(List<T> rows) {
FILE: src/main/java/com/porterhead/rest/api/ValidationError.java
class ValidationError (line 10) | @XmlRootElement
method getPropertyName (line 17) | public String getPropertyName() {
method setPropertyName (line 21) | public void setPropertyName(String propertyName) {
method getPropertyValue (line 25) | public String getPropertyValue() {
method setPropertyValue (line 29) | public void setPropertyValue(String propertyValue) {
method getMessage (line 33) | public String getMessage() {
method setMessage (line 37) | public void setMessage(String message) {
FILE: src/main/java/com/porterhead/rest/authorization/AuthorizationRequestContext.java
class AuthorizationRequestContext (line 9) | public class AuthorizationRequestContext {
method AuthorizationRequestContext (line 36) | public AuthorizationRequestContext(String requestUrl, String httpMetho...
method getRequestUrl (line 44) | public String getRequestUrl() {
method getHttpMethod (line 48) | public String getHttpMethod() {
method getRequestDateString (line 52) | public String getRequestDateString() {
method getNonceToken (line 56) | public String getNonceToken() {
method getAuthorizationToken (line 60) | public String getAuthorizationToken() {
FILE: src/main/java/com/porterhead/rest/authorization/AuthorizationService.java
type AuthorizationService (line 9) | public interface AuthorizationService {
method authorize (line 17) | public ExternalUser authorize(AuthorizationRequestContext authorizatio...
FILE: src/main/java/com/porterhead/rest/authorization/exception/InvalidAuthorizationHeaderException.java
class InvalidAuthorizationHeaderException (line 11) | public class InvalidAuthorizationHeaderException extends BaseWebApplicat...
method InvalidAuthorizationHeaderException (line 17) | public InvalidAuthorizationHeaderException() {
FILE: src/main/java/com/porterhead/rest/authorization/impl/RequestSigningAuthorizationService.java
class RequestSigningAuthorizationService (line 56) | public class RequestSigningAuthorizationService implements Authorization...
method RequestSigningAuthorizationService (line 93) | @Autowired
method initNonceCache (line 101) | private void initNonceCache() {
method authorize (line 121) | public ExternalUser authorize(AuthorizationRequestContext context) {
method isAuthorized (line 168) | private boolean isAuthorized(User user, AuthorizationRequestContext au...
method encodeAuthToken (line 188) | private String encodeAuthToken(String token, String unencodedRequest) {
method composeUnEncodedRequest (line 200) | private String composeUnEncodedRequest(AuthorizationRequestContext aut...
method validateRequestDate (line 216) | private void validateRequestDate(String requestDateString) {
method validateNonce (line 237) | private void validateNonce(String nonceValue) {
class Nonce (line 246) | private static class Nonce {
method Nonce (line 250) | Nonce(DateTime time, String nonce) {
FILE: src/main/java/com/porterhead/rest/authorization/impl/SecurityContextImpl.java
class SecurityContextImpl (line 17) | public class SecurityContextImpl implements SecurityContext {
method SecurityContextImpl (line 21) | public SecurityContextImpl(ExternalUser user) {
method getUserPrincipal (line 25) | public Principal getUserPrincipal() {
method isUserInRole (line 29) | public boolean isUserInRole(String role) {
method isSecure (line 39) | public boolean isSecure() {
method getAuthenticationScheme (line 43) | public String getAuthenticationScheme() {
FILE: src/main/java/com/porterhead/rest/authorization/impl/SessionTokenAuthorizationService.java
class SessionTokenAuthorizationService (line 22) | public class SessionTokenAuthorizationService implements AuthorizationSe...
method SessionTokenAuthorizationService (line 29) | public SessionTokenAuthorizationService(UserRepository repository) {
method authorize (line 33) | public ExternalUser authorize(AuthorizationRequestContext securityCont...
FILE: src/main/java/com/porterhead/rest/config/ApplicationConfig.java
class ApplicationConfig (line 13) | @Configuration
method getHostNameUrl (line 35) | public String getHostNameUrl() {
method getFacebookClientId (line 39) | public String getFacebookClientId() {
method getFacebookClientSecret (line 43) | public String getFacebookClientSecret() {
method getAuthorizationExpiryTimeInSeconds (line 47) | public int getAuthorizationExpiryTimeInSeconds() {
method getSessionDateOffsetInMinutes (line 51) | public int getSessionDateOffsetInMinutes() {
method getEmailRegistrationTokenExpiryTimeInMinutes (line 55) | public int getEmailRegistrationTokenExpiryTimeInMinutes() {
method getEmailVerificationTokenExpiryTimeInMinutes (line 59) | public int getEmailVerificationTokenExpiryTimeInMinutes() {
method getLostPasswordTokenExpiryTimeInMinutes (line 63) | public int getLostPasswordTokenExpiryTimeInMinutes() {
method getEmailVerificationSubjectText (line 67) | public String getEmailVerificationSubjectText() {
method getEmailRegistrationSubjectText (line 71) | public String getEmailRegistrationSubjectText() {
method getLostPasswordSubjectText (line 75) | public String getLostPasswordSubjectText() {
method getEmailFromAddress (line 79) | public String getEmailFromAddress() {
method getEmailReplyToAddress (line 83) | public String getEmailReplyToAddress() {
method requireSignedRequests (line 87) | public Boolean requireSignedRequests() {
FILE: src/main/java/com/porterhead/rest/config/ApplicationDevConfig.java
class ApplicationDevConfig (line 15) | @Configuration
method textEncryptor (line 20) | @Bean
FILE: src/main/java/com/porterhead/rest/config/ApplicationProductionConfig.java
class ApplicationProductionConfig (line 17) | @Configuration
method textEncryptor (line 25) | @Bean
FILE: src/main/java/com/porterhead/rest/config/ApplicationStagingConfig.java
class ApplicationStagingConfig (line 18) | @Configuration
method textEncryptor (line 26) | @Bean
FILE: src/main/java/com/porterhead/rest/exception/ApplicationRuntimeException.java
class ApplicationRuntimeException (line 4) | public class ApplicationRuntimeException extends BaseWebApplicationExcep...
method ApplicationRuntimeException (line 6) | public ApplicationRuntimeException(String applicationMessage) {
FILE: src/main/java/com/porterhead/rest/exception/BaseWebApplicationException.java
class BaseWebApplicationException (line 14) | public abstract class BaseWebApplicationException extends WebApplication...
method BaseWebApplicationException (line 21) | public BaseWebApplicationException(int httpStatus, String errorCode, S...
method getResponse (line 29) | @Override
method getErrorResponse (line 34) | public ErrorResponse getErrorResponse() {
FILE: src/main/java/com/porterhead/rest/exception/NotFoundException.java
class NotFoundException (line 10) | public class NotFoundException extends WebApplicationException {
method NotFoundException (line 12) | public NotFoundException() {
FILE: src/main/java/com/porterhead/rest/exception/ValidationException.java
class ValidationException (line 19) | public class ValidationException extends WebApplicationException {
method ValidationException (line 26) | public ValidationException() {
method ValidationException (line 31) | public ValidationException(String message) {
method ValidationException (line 36) | public ValidationException(Set<? extends ConstraintViolation<?>> viola...
method getResponse (line 47) | @Override
method getErrorResponse (line 52) | public ErrorResponse getErrorResponse() {
FILE: src/main/java/com/porterhead/rest/filter/ResourceFilterFactory.java
class ResourceFilterFactory (line 28) | @Component
method create (line 35) | @Override
FILE: src/main/java/com/porterhead/rest/filter/SecurityContextFilter.java
class SecurityContextFilter (line 33) | @Component
method SecurityContextFilter (line 49) | @Autowired
method filter (line 71) | public ContainerRequest filter(ContainerRequest request) {
method delegateAuthorizationService (line 89) | private void delegateAuthorizationService(UserRepository userRepositor...
method getRequestFilter (line 98) | public ContainerRequestFilter getRequestFilter() {
method getResponseFilter (line 102) | public ContainerResponseFilter getResponseFilter() {
method setConfig (line 106) | @Autowired
FILE: src/main/java/com/porterhead/rest/gateway/EmailServicesGateway.java
type EmailServicesGateway (line 11) | public interface EmailServicesGateway {
method sendVerificationToken (line 13) | public void sendVerificationToken(EmailServiceTokenModel model);
FILE: src/main/java/com/porterhead/rest/model/BaseEntity.java
class BaseEntity (line 17) | @MappedSuperclass
method BaseEntity (line 32) | public BaseEntity() {
method BaseEntity (line 36) | public BaseEntity(UUID guid) {
method getUuid (line 42) | public UUID getUuid() {
method setUuid (line 46) | public void setUuid(String uuid) {
method hashCode (line 50) | public int hashCode() {
method getIdentifier (line 67) | public Object getIdentifier() {
method getVersion (line 71) | public int getVersion() {
method getTimeCreated (line 75) | public Date getTimeCreated() {
FILE: src/main/java/com/porterhead/rest/resource/GenericExceptionMapper.java
class GenericExceptionMapper (line 16) | @Provider
method toResponse (line 21) | public Response toResponse(Exception exception) {
FILE: src/main/java/com/porterhead/rest/resource/HealthCheckResource.java
class HealthCheckResource (line 20) | @Path("/healthcheck")
method ping (line 29) | @PermitAll
FILE: src/main/java/com/porterhead/rest/service/BaseService.java
class BaseService (line 14) | public abstract class BaseService {
method BaseService (line 18) | public BaseService(Validator validator) {
method validate (line 22) | protected void validate(Object request) {
FILE: src/main/java/com/porterhead/rest/user/EmailServiceTokenModel.java
class EmailServiceTokenModel (line 15) | public class EmailServiceTokenModel implements Serializable {
method EmailServiceTokenModel (line 23) | public EmailServiceTokenModel(User user, VerificationToken token, Stri...
method getEmailAddress (line 30) | public String getEmailAddress() {
method getEncodedToken (line 34) | public String getEncodedToken() {
method getToken (line 38) | public String getToken() {
method getTokenType (line 42) | public VerificationToken.VerificationTokenType getTokenType() {
method getHostNameUrl (line 46) | public String getHostNameUrl() {
FILE: src/main/java/com/porterhead/rest/user/SocialUserRepository.java
type SocialUserRepository (line 17) | public interface SocialUserRepository extends JpaRepository<SocialUser, ...
method findAllByUser (line 19) | List<SocialUser> findAllByUser(User user);
method findByUserAndProviderId (line 21) | List<SocialUser> findByUserAndProviderId(User user, String providerId);
method findByProviderIdAndProviderUserId (line 23) | List<SocialUser> findByProviderIdAndProviderUserId(String providerId, ...
method findByUserAndProviderUserId (line 26) | List<SocialUser> findByUserAndProviderUserId(User user, MultiValueMap<...
method findByProviderIdAndProviderUserId (line 28) | @Query("Select userId from SocialUser where providerId = ? AND provide...
method findByUserAndProviderIdAndProviderUserId (line 31) | SocialUser findByUserAndProviderIdAndProviderUserId(User user, String ...
FILE: src/main/java/com/porterhead/rest/user/UserRepository.java
type UserRepository (line 16) | public interface UserRepository extends JpaRepository<User, Long> {
method findByEmailAddress (line 18) | User findByEmailAddress(String emailAddress);
method findByUuid (line 20) | @Query("select u from User u where uuid = ?")
method findByExpiredSession (line 23) | @Query("select u from User u where u in (select user from Authorizatio...
method findBySession (line 26) | @Query("select u from User u where u = (select user from Authorization...
FILE: src/main/java/com/porterhead/rest/user/UserService.java
type UserService (line 14) | public interface UserService {
method createUser (line 24) | public AuthenticatedUserToken createUser(CreateUserRequest request, Ro...
method createUser (line 33) | public AuthenticatedUserToken createUser(Role role);
method login (line 41) | public AuthenticatedUserToken login(LoginRequest request);
method socialLogin (line 50) | public AuthenticatedUserToken socialLogin(Connection<?> connection);
method getUser (line 60) | public ExternalUser getUser(ExternalUser requestingUser, String userId...
method deleteUser (line 68) | public void deleteUser(ExternalUser userMakingRequest, String userId);
method saveUser (line 76) | public ExternalUser saveUser(String userId, UpdateUserRequest request);
method createAuthorizationToken (line 83) | public AuthorizationToken createAuthorizationToken(User user);
FILE: src/main/java/com/porterhead/rest/user/UserServiceImpl.java
class UserServiceImpl (line 34) | @Service("userService")
method UserServiceImpl (line 46) | public UserServiceImpl(Validator validator) {
method UserServiceImpl (line 50) | @Autowired
method createUser (line 70) | @Transactional
method createUser (line 84) | @Transactional
method login (line 101) | @Transactional
method socialLogin (line 133) | @Transactional
method getUser (line 155) | @Transactional
method deleteUser (line 167) | @Transactional
method saveUser (line 179) | @Transactional
method createAuthorizationToken (line 199) | @Override
method createNewUser (line 208) | private User createNewUser(CreateUserRequest request, Role role) {
method updateUserFromProfile (line 219) | private void updateUserFromProfile(Connection<?> connection, User user) {
method ensureUserIsLoaded (line 232) | private User ensureUserIsLoaded(String userIdentifier) {
method setUserRepository (line 245) | @Autowired
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenRepository.java
type VerificationTokenRepository (line 12) | public interface VerificationTokenRepository extends JpaRepository<Verif...
method findByUuid (line 14) | @Query("select t from VerificationToken t where uuid = ?")
method findByToken (line 17) | @Query("select t from VerificationToken t where token = ?")
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenService.java
type VerificationTokenService (line 13) | public interface VerificationTokenService {
method sendEmailVerificationToken (line 15) | public VerificationToken sendEmailVerificationToken(String userId);
method sendEmailRegistrationToken (line 17) | public VerificationToken sendEmailRegistrationToken(String userId);
method sendLostPasswordToken (line 19) | public VerificationToken sendLostPasswordToken(LostPasswordRequest los...
method verify (line 21) | public VerificationToken verify(String base64EncodedToken);
method generateEmailVerificationToken (line 23) | public VerificationToken generateEmailVerificationToken(String emailAd...
method resetPassword (line 25) | public VerificationToken resetPassword(String base64EncodedToken, Pass...
FILE: src/main/java/com/porterhead/rest/user/VerificationTokenServiceImpl.java
class VerificationTokenServiceImpl (line 26) | @Service("verificationTokenService")
method VerificationTokenServiceImpl (line 37) | public VerificationTokenServiceImpl(Validator validator) {
method VerificationTokenServiceImpl (line 41) | @Autowired
method sendEmailVerificationToken (line 50) | @Transactional
method sendEmailVerificationToken (line 56) | private VerificationToken sendEmailVerificationToken(User user) {
method sendEmailRegistrationToken (line 65) | @Transactional
method sendLostPasswordToken (line 84) | @Transactional
method verify (line 103) | @Transactional
method generateEmailVerificationToken (line 115) | @Transactional
method resetPassword (line 135) | @Transactional
method loadToken (line 159) | private VerificationToken loadToken(String base64EncodedToken) {
method setConfig (line 172) | @Autowired
method setUserRepository (line 177) | @Autowired
method getConfig (line 182) | public ApplicationConfig getConfig() {
method ensureUserIsLoaded (line 186) | private User ensureUserIsLoaded(String userIdentifier) {
FILE: src/main/java/com/porterhead/rest/user/api/AuthenticatedUserToken.java
class AuthenticatedUserToken (line 8) | @XmlRootElement
method AuthenticatedUserToken (line 14) | public AuthenticatedUserToken(){}
method AuthenticatedUserToken (line 16) | public AuthenticatedUserToken(String userId, String sessionToken) {
method getUserId (line 21) | public String getUserId() {
method getToken (line 25) | public String getToken() {
method setUserId (line 29) | public void setUserId(String userId) {
method setToken (line 33) | public void setToken(String token) {
FILE: src/main/java/com/porterhead/rest/user/api/CreateUserRequest.java
class CreateUserRequest (line 10) | @XmlRootElement
method CreateUserRequest (line 22) | public CreateUserRequest() {
method CreateUserRequest (line 25) | public CreateUserRequest(final ExternalUser user, final PasswordReques...
method getUser (line 30) | public ExternalUser getUser() {
method setUser (line 34) | public void setUser(ExternalUser user) {
method getPassword (line 38) | public PasswordRequest getPassword() {
method setPassword (line 42) | public void setPassword(PasswordRequest password) {
FILE: src/main/java/com/porterhead/rest/user/api/EmailVerificationRequest.java
class EmailVerificationRequest (line 12) | @XmlRootElement
method EmailVerificationRequest (line 18) | public EmailVerificationRequest() {}
method EmailVerificationRequest (line 20) | public EmailVerificationRequest(String emailAddress) {
method getEmailAddress (line 24) | public String getEmailAddress() {
method setEmailAddress (line 28) | public void setEmailAddress(String emailAddress) {
FILE: src/main/java/com/porterhead/rest/user/api/ExternalUser.java
class ExternalUser (line 21) | @XmlRootElement
method ExternalUser (line 43) | public ExternalUser() {}
method ExternalUser (line 45) | public ExternalUser(String userId) {
method ExternalUser (line 49) | public ExternalUser(User user) {
method ExternalUser (line 67) | public ExternalUser(User user, AuthorizationToken activeSession) {
method getFirstName (line 71) | public String getFirstName() {
method setFirstName (line 75) | public void setFirstName(String firstName) {
method getLastName (line 79) | public String getLastName() {
method setLastName (line 83) | public void setLastName(String lastName) {
method getEmailAddress (line 87) | public String getEmailAddress() {
method setEmailAddress (line 91) | public void setEmailAddress(String emailAddress) {
method getSocialProfiles (line 95) | public List<SocialProfile> getSocialProfiles() {
method getId (line 99) | public String getId() {
method isVerified (line 103) | public boolean isVerified() {
method getName (line 107) | public String getName() {
method getRole (line 111) | public String getRole() {
FILE: src/main/java/com/porterhead/rest/user/api/LoginRequest.java
class LoginRequest (line 13) | @XmlRootElement
method LoginRequest (line 23) | public LoginRequest(){}
method getUsername (line 25) | public String getUsername() {
method setUsername (line 29) | public void setUsername(String username) {
method getPassword (line 33) | public String getPassword() {
method setPassword (line 37) | public void setPassword(String password) {
FILE: src/main/java/com/porterhead/rest/user/api/LostPasswordRequest.java
class LostPasswordRequest (line 12) | @XmlRootElement
method LostPasswordRequest (line 18) | public LostPasswordRequest() {}
method LostPasswordRequest (line 20) | public LostPasswordRequest(final String emailAddress) {
method getEmailAddress (line 24) | public String getEmailAddress() {
method setEmailAddress (line 28) | public void setEmailAddress(String emailAddress) {
FILE: src/main/java/com/porterhead/rest/user/api/OAuth2Request.java
class OAuth2Request (line 11) | @XmlRootElement
method getAccessToken (line 16) | @NotNull
method setAccessToken (line 21) | public void setAccessToken(String accessToken) {
FILE: src/main/java/com/porterhead/rest/user/api/PasswordRequest.java
class PasswordRequest (line 14) | @XmlRootElement
method PasswordRequest (line 21) | public PasswordRequest() {}
method PasswordRequest (line 23) | public PasswordRequest(final String password) {
method getPassword (line 27) | public String getPassword() {
method setPassword (line 31) | public void setPassword(String password) {
FILE: src/main/java/com/porterhead/rest/user/api/SocialProfile.java
class SocialProfile (line 8) | @XmlRootElement
method SocialProfile (line 17) | public SocialProfile() {}
method getProvider (line 19) | public String getProvider() {
method setProvider (line 23) | public void setProvider(String provider) {
method getProviderUserId (line 27) | public String getProviderUserId() {
method setProviderUserId (line 31) | public void setProviderUserId(String providerUserId) {
method getProfileUrl (line 35) | public String getProfileUrl() {
method setProfileUrl (line 39) | public void setProfileUrl(String profileUrl) {
method getImageUrl (line 43) | public String getImageUrl() {
method setImageUrl (line 47) | public void setImageUrl(String imageUrl) {
method getDisplayName (line 51) | public String getDisplayName() {
method setDisplayName (line 55) | public void setDisplayName(String displayName) {
FILE: src/main/java/com/porterhead/rest/user/api/UpdateUserRequest.java
class UpdateUserRequest (line 14) | @XmlRootElement
method UpdateUserRequest (line 24) | public UpdateUserRequest(){}
method getFirstName (line 26) | public String getFirstName() {
method setFirstName (line 30) | public void setFirstName(String firstName) {
method getLastName (line 34) | public String getLastName() {
method setLastName (line 38) | public void setLastName(String lastName) {
method getEmailAddress (line 42) | public String getEmailAddress() {
method setEmailAddress (line 46) | public void setEmailAddress(String emailAddress) {
FILE: src/main/java/com/porterhead/rest/user/domain/AuthorizationToken.java
class AuthorizationToken (line 15) | @Entity
method AuthorizationToken (line 32) | public AuthorizationToken() {}
method AuthorizationToken (line 34) | public AuthorizationToken(User user) {
method AuthorizationToken (line 38) | public AuthorizationToken(User user, Integer timeToLiveInSeconds) {
method hasExpired (line 45) | public boolean hasExpired() {
method getToken (line 49) | public String getToken() {
method getUser (line 53) | public User getUser() {
method getTimeCreated (line 57) | public Date getTimeCreated() {
FILE: src/main/java/com/porterhead/rest/user/domain/Role.java
type Role (line 8) | public enum Role {
FILE: src/main/java/com/porterhead/rest/user/domain/SocialUser.java
class SocialUser (line 12) | @Entity
method getProviderId (line 42) | public String getProviderId() {
method setProviderId (line 46) | public void setProviderId(String providerId) {
method getProviderUserId (line 50) | public String getProviderUserId() {
method setProviderUserId (line 54) | public void setProviderUserId(String providerUserId) {
method getRank (line 58) | public int getRank() {
method setRank (line 62) | public void setRank(int rank) {
method getDisplayName (line 66) | public String getDisplayName() {
method setDisplayName (line 70) | public void setDisplayName(String displayName) {
method getProfileUrl (line 74) | public String getProfileUrl() {
method setProfileUrl (line 78) | public void setProfileUrl(String profileUrl) {
method getImageUrl (line 82) | public String getImageUrl() {
method setImageUrl (line 86) | public void setImageUrl(String imageUrl) {
method getAccessToken (line 90) | public String getAccessToken() {
method setAccessToken (line 94) | public void setAccessToken(String accessToken) {
method getSecret (line 98) | public String getSecret() {
method setSecret (line 102) | public void setSecret(String secret) {
method getRefreshToken (line 106) | public String getRefreshToken() {
method setRefreshToken (line 110) | public void setRefreshToken(String refreshToken) {
method getExpireTime (line 114) | public Long getExpireTime() {
method setExpireTime (line 118) | public void setExpireTime(Long expireTime) {
method getUser (line 122) | public User getUser() {
method setUser (line 126) | public void setUser(User user) {
FILE: src/main/java/com/porterhead/rest/user/domain/SocialUserBuilder.java
class SocialUserBuilder (line 8) | public class SocialUserBuilder {
method create (line 12) | public static SocialUserBuilder create() {
method SocialUserBuilder (line 16) | public SocialUserBuilder() {
method build (line 20) | public SocialUser build() {
method withUser (line 24) | public SocialUserBuilder withUser(User user) {
method withProviderId (line 29) | public SocialUserBuilder withProviderId(String id) {
method withProviderUserId (line 34) | public SocialUserBuilder withProviderUserId(String id) {
method withRank (line 39) | public SocialUserBuilder withRank(int rank) {
method withDisplayName (line 44) | public SocialUserBuilder withDisplayName(String name) {
method withProfileUrl (line 49) | public SocialUserBuilder withProfileUrl(String url) {
method withImageUrl (line 54) | public SocialUserBuilder withImageUrl(String url) {
method withAccessToken (line 59) | public SocialUserBuilder withAccessToken(String token) {
method withSecret (line 64) | public SocialUserBuilder withSecret(String secret) {
method withRefreshToken (line 69) | public SocialUserBuilder withRefreshToken(String token) {
method withExpireTime (line 74) | public SocialUserBuilder withExpireTime(Long time) {
FILE: src/main/java/com/porterhead/rest/user/domain/User.java
class User (line 20) | @Entity
method User (line 54) | public User() {
method User (line 58) | public User(UUID uuid) {
method User (line 63) | public User(ExternalUser externalUser) {
method setHashedPassword (line 70) | public void setHashedPassword(String hashedPassword) {
method getHashedPassword (line 74) | public String getHashedPassword() {
method getFirstName (line 78) | public String getFirstName() {
method setFirstName (line 82) | public void setFirstName(String firstName) {
method getLastName (line 86) | public String getLastName() {
method setLastName (line 90) | public void setLastName(String lastName) {
method getEmailAddress (line 94) | public String getEmailAddress() {
method setEmailAddress (line 98) | public void setEmailAddress(String emailAddress) {
method getRole (line 102) | public Role getRole() {
method setRole (line 106) | public void setRole(Role role) {
method hasRole (line 110) | public boolean hasRole(Role role) {
method equals (line 115) | public boolean equals(Object otherUser) {
method hashCode (line 133) | public int hashCode() {
method getName (line 137) | public String getName() {
method getSocialUsers (line 144) | public Set<SocialUser> getSocialUsers() {
method setSocialUsers (line 149) | public void setSocialUsers(Set<SocialUser> socialUsers) {
method addSocialUser (line 153) | public void addSocialUser(SocialUser socialUser) {
method addVerificationToken (line 157) | public synchronized void addVerificationToken(VerificationToken token) {
method getVerificationTokens (line 161) | public synchronized List<VerificationToken> getVerificationTokens() {
method setAuthorizationToken (line 165) | public synchronized void setAuthorizationToken(AuthorizationToken toke...
method getAuthorizationToken (line 171) | public synchronized AuthorizationToken getAuthorizationToken() {
method getActiveLostPasswordToken (line 181) | public VerificationToken getActiveLostPasswordToken() {
method getActiveEmailVerificationToken (line 191) | public VerificationToken getActiveEmailVerificationToken() {
method getActiveEmailRegistrationToken (line 201) | public VerificationToken getActiveEmailRegistrationToken() {
method getActiveToken (line 205) | private VerificationToken getActiveToken(VerificationToken.Verificatio...
method isVerified (line 217) | public boolean isVerified() {
method setVerified (line 221) | public void setVerified(boolean verified) {
method hashPassword (line 232) | public String hashPassword(String passwordToHash) throws Exception {
method hashToken (line 237) | private String hashToken(String token, String salt) throws Exception {
method getHash (line 241) | public byte[] getHash(int numberOfIterations, String password, byte[] ...
FILE: src/main/java/com/porterhead/rest/user/domain/VerificationToken.java
class VerificationToken (line 19) | @Entity
method VerificationToken (line 39) | public VerificationToken() {
method VerificationToken (line 45) | public VerificationToken(User user, VerificationTokenType tokenType, i...
method getTokenType (line 52) | public VerificationTokenType getTokenType() {
method isVerified (line 56) | public boolean isVerified() {
method setVerified (line 60) | public void setVerified(boolean verified) {
method getUser (line 64) | public User getUser() {
method setUser (line 68) | public void setUser(User user) {
method getExpiryDate (line 72) | public Date getExpiryDate() {
method getToken (line 76) | public String getToken() {
method calculateExpiryDate (line 80) | private Date calculateExpiryDate(int expiryTimeInMinutes) {
type VerificationTokenType (line 85) | public enum VerificationTokenType {
method hasExpired (line 90) | public boolean hasExpired() {
FILE: src/main/java/com/porterhead/rest/user/exception/AlreadyVerifiedException.java
class AlreadyVerifiedException (line 11) | public class AlreadyVerifiedException extends BaseWebApplicationException {
method AlreadyVerifiedException (line 13) | public AlreadyVerifiedException() {
FILE: src/main/java/com/porterhead/rest/user/exception/AuthenticationException.java
class AuthenticationException (line 10) | public class AuthenticationException extends BaseWebApplicationException {
method AuthenticationException (line 12) | public AuthenticationException() {
FILE: src/main/java/com/porterhead/rest/user/exception/AuthorizationException.java
class AuthorizationException (line 11) | public class AuthorizationException extends BaseWebApplicationException {
method AuthorizationException (line 13) | public AuthorizationException(String applicationMessage) {
FILE: src/main/java/com/porterhead/rest/user/exception/DuplicateUserException.java
class DuplicateUserException (line 10) | public class DuplicateUserException extends BaseWebApplicationException {
method DuplicateUserException (line 12) | public DuplicateUserException() {
FILE: src/main/java/com/porterhead/rest/user/exception/TokenHasExpiredException.java
class TokenHasExpiredException (line 11) | public class TokenHasExpiredException extends BaseWebApplicationException {
method TokenHasExpiredException (line 13) | public TokenHasExpiredException() {
FILE: src/main/java/com/porterhead/rest/user/exception/TokenNotFoundException.java
class TokenNotFoundException (line 11) | public class TokenNotFoundException extends BaseWebApplicationException {
method TokenNotFoundException (line 13) | public TokenNotFoundException() {
FILE: src/main/java/com/porterhead/rest/user/exception/UserNotFoundException.java
class UserNotFoundException (line 11) | public class UserNotFoundException extends BaseWebApplicationException {
method UserNotFoundException (line 13) | public UserNotFoundException() {
FILE: src/main/java/com/porterhead/rest/user/mail/MailSenderService.java
type MailSenderService (line 11) | public interface MailSenderService {
method sendVerificationEmail (line 13) | public EmailServiceTokenModel sendVerificationEmail(EmailServiceTokenM...
method sendRegistrationEmail (line 15) | public EmailServiceTokenModel sendRegistrationEmail(EmailServiceTokenM...
method sendLostPasswordEmail (line 17) | public EmailServiceTokenModel sendLostPasswordEmail(EmailServiceTokenM...
FILE: src/main/java/com/porterhead/rest/user/mail/MockJavaMailSender.java
class MockJavaMailSender (line 18) | public class MockJavaMailSender implements JavaMailSender {
method createMimeMessage (line 22) | public MimeMessage createMimeMessage() {
method createMimeMessage (line 27) | public MimeMessage createMimeMessage(InputStream contentStream) throws...
method send (line 31) | public void send(MimeMessage mimeMessage) throws MailException {
method send (line 35) | public void send(MimeMessage[] mimeMessages) throws MailException {
method send (line 39) | public void send(MimeMessagePreparator mimeMessagePreparator) throws M...
method send (line 52) | public void send(MimeMessagePreparator[] mimeMessagePreparators) throw...
method send (line 56) | public void send(SimpleMailMessage simpleMessage) throws MailException {
method send (line 60) | public void send(SimpleMailMessage[] simpleMessages) throws MailExcept...
method getMessages (line 64) | public List<MimeMessage> getMessages() {
FILE: src/main/java/com/porterhead/rest/user/mail/impl/MailSenderServiceImpl.java
class MailSenderServiceImpl (line 29) | @Service("mailSenderService")
method MailSenderServiceImpl (line 38) | @Autowired
method sendVerificationEmail (line 45) | public EmailServiceTokenModel sendVerificationEmail(final EmailService...
method sendRegistrationEmail (line 51) | public EmailServiceTokenModel sendRegistrationEmail(final EmailService...
method sendLostPasswordEmail (line 57) | public EmailServiceTokenModel sendLostPasswordEmail(final EmailService...
method addInlineResource (line 64) | private void addInlineResource(MimeMessageHelper messageHelper, String...
method sendVerificationEmail (line 69) | private EmailServiceTokenModel sendVerificationEmail(final EmailServic...
method setConfig (line 92) | @Autowired
method getConfig (line 97) | public ApplicationConfig getConfig() {
FILE: src/main/java/com/porterhead/rest/user/resource/PasswordResource.java
class PasswordResource (line 20) | @Path("password")
method sendEmailToken (line 29) | @PermitAll
method resetPassword (line 37) | @PermitAll
FILE: src/main/java/com/porterhead/rest/user/resource/UserResource.java
class UserResource (line 29) | @Path("/user")
method UserResource (line 52) | @Autowired
method signupUser (line 58) | @PermitAll
method deleteUser (line 67) | @RolesAllowed("admin")
method login (line 76) | @PermitAll
method socialLogin (line 84) | @PermitAll
method getUser (line 94) | @RolesAllowed({"authenticated"})
method updateUser (line 103) | @RolesAllowed({"authenticated"})
method getLoginResponse (line 120) | private Response getLoginResponse(AuthenticatedUserToken token) {
FILE: src/main/java/com/porterhead/rest/user/resource/VerificationResource.java
class VerificationResource (line 18) | @Path("verify")
method verifyToken (line 27) | @PermitAll
method sendEmailToken (line 35) | @PermitAll
FILE: src/main/java/com/porterhead/rest/user/social/JpaConnectionRepository.java
class JpaConnectionRepository (line 23) | public class JpaConnectionRepository implements ConnectionRepository {
method JpaConnectionRepository (line 31) | public JpaConnectionRepository(SocialUserRepository socialUserReposito...
method findAllConnections (line 39) | public MultiValueMap<String, Connection<?>> findAllConnections() {
method findConnections (line 57) | public List<Connection<?>> findConnections(String providerId) {
method findConnections (line 61) | @SuppressWarnings("unchecked")
method findConnectionsToUsers (line 67) | public MultiValueMap<String, Connection<?>> findConnectionsToUsers(Mul...
method getConnection (line 93) | public Connection<?> getConnection(ConnectionKey connectionKey) {
method getConnection (line 101) | @SuppressWarnings("unchecked")
method getPrimaryConnection (line 107) | @SuppressWarnings("unchecked")
method findPrimaryConnection (line 117) | @SuppressWarnings("unchecked")
method addConnection (line 123) | @Transactional
method updateConnection (line 141) | public void updateConnection(Connection<?> connection) {
method removeConnections (line 158) | public void removeConnections(String providerId) {
method removeConnection (line 163) | public void removeConnection(ConnectionKey connectionKey) {
method findPrimaryConnection (line 168) | private Connection<?> findPrimaryConnection(String providerId) {
class ServiceProviderConnectionMapper (line 179) | private final class ServiceProviderConnectionMapper {
method mapEntities (line 181) | public List<Connection<?>> mapEntities(List<SocialUser> socialUsers){
method mapEntity (line 189) | public Connection<?> mapEntity(SocialUser socialUser){
method mapConnectionData (line 195) | private ConnectionData mapConnectionData(SocialUser socialUser){
method decrypt (line 200) | private String decrypt(String encryptedText) {
method expireTime (line 204) | private Long expireTime(Long expireTime) {
method getProviderId (line 210) | private <A> String getProviderId(Class<A> apiType) {
method encrypt (line 214) | private String encrypt(String text) {
FILE: src/main/java/com/porterhead/rest/user/social/JpaUsersConnectionRepository.java
class JpaUsersConnectionRepository (line 22) | public class JpaUsersConnectionRepository implements UsersConnectionRepo...
method JpaUsersConnectionRepository (line 34) | public JpaUsersConnectionRepository(final SocialUserRepository reposit...
method findUserIdsWithConnection (line 52) | public List<String> findUserIdsWithConnection(Connection<?> connection) {
method findUserIdsConnectedTo (line 77) | public Set<String> findUserIdsConnectedTo(String providerId, Set<Strin...
method createConnectionRepository (line 81) | public ConnectionRepository createConnectionRepository(String userId) {
method findUserFromSocialProfile (line 92) | private User findUserFromSocialProfile(Connection connection) {
method getUserService (line 101) | public UserService getUserService() {
method setUserService (line 105) | public void setUserService(UserService userService) {
FILE: src/main/java/com/porterhead/rest/user/social/SocialConfig.java
class SocialConfig (line 20) | @Configuration
method connectionFactoryLocator (line 35) | @Bean
method usersConnectionRepository (line 44) | @Bean
FILE: src/main/java/com/porterhead/rest/util/DateUtil.java
class DateUtil (line 12) | public class DateUtil {
method getDateFromIso8061DateString (line 16) | public static Date getDateFromIso8061DateString(String dateString) {
method getCurrentDateAsIso8061String (line 20) | public static String getCurrentDateAsIso8061String() {
method getDateDateAsIso8061String (line 25) | public static String getDateDateAsIso8061String(DateTime date) {
FILE: src/main/java/com/porterhead/rest/util/HashUtil.java
class HashUtil (line 9) | public class HashUtil {
method main (line 11) | public static void main(String[] args) {
method base64ToByte (line 26) | public static byte[] base64ToByte(String data) throws IOException {
method byteToBase64 (line 37) | public static String byteToBase64(byte[] data) {
method signString (line 41) | private static String signString(String request) {
FILE: src/main/java/com/porterhead/rest/util/StringUtil.java
class StringUtil (line 12) | public class StringUtil {
method minLength (line 16) | public static void minLength(String str, int len) throws IllegalArgume...
method maxLength (line 23) | public static void maxLength(String str, int len) throws IllegalArgume...
method validEmail (line 30) | public static void validEmail(String email) throws IllegalArgumentExce...
method isValidUuid (line 38) | public static boolean isValidUuid(String uuid) {
FILE: src/main/resources/schema/indexes.sql
type user_uuid_IDX (line 2) | CREATE UNIQUE INDEX user_uuid_IDX ON rest_user ( uuid)
type user_email_address_IDX (line 3) | CREATE INDEX user_email_address_IDX on rest_user (email_address)
type verification_token_uuid_IDX (line 4) | CREATE UNIQUE INDEX verification_token_uuid_IDX ON rest_verification_tok...
type verification_token_token_IDX (line 5) | CREATE UNIQUE INDEX verification_token_token_IDX ON rest_verification_to...
type session_token_last_updated_IDX (line 6) | CREATE UNIQUE INDEX session_token_last_updated_IDX ON rest_session_token...
type session_token_token_IDX (line 7) | CREATE UNIQUE INDEX session_token_token_IDX ON rest_session_token (token)
FILE: src/main/resources/schema/message_store.sql
type INT_MESSAGE (line 1) | CREATE TABLE INT_MESSAGE (
type INT_MESSAGE_IX1 (line 8) | CREATE INDEX INT_MESSAGE_IX1 ON INT_MESSAGE (CREATED_DATE)
type INT_GROUP_TO_MESSAGE (line 10) | CREATE TABLE INT_GROUP_TO_MESSAGE (
type INT_MESSAGE_GROUP (line 16) | CREATE TABLE INT_MESSAGE_GROUP (
FILE: src/main/webapp/js/bootstrap.js
function removeElement (line 115) | function removeElement() {
function clearMenus (line 677) | function clearMenus() {
function getParent (line 682) | function getParent($this) {
function removeWithAnimation (line 1129) | function removeWithAnimation() {
function ScrollSpy (line 1368) | function ScrollSpy(element, options) {
function next (line 1568) | function next() {
FILE: src/main/webapp/js/javarest.js
function javaRest (line 4) | function javaRest() {
function makeRandomString (line 36) | function makeRandomString() {
function pad (line 47) | function pad(n) {return n<10 ? '0'+n : n}
FILE: src/main/webapp/js/jquery-full-house.js
function get_initial_font_size (line 96) | function get_initial_font_size(container)
function find_max_font_size (line 108) | function find_max_font_size(container, options)
FILE: src/main/webapp/js/sha256.js
function a (line 7) | function a(){}
function f (line 13) | function f(a){for(var b=i.sqrt(a),d=2;d<=b;d++)if(!(a%d))return!1;return!0}
function g (line 13) | function g(a){return 4294967296*(a-(a|0))|0}
FILE: src/main/webapp/js/store.js
function h (line 2) | function h(){try{return d in b&&b[d]}catch(a){return!1}}
function i (line 2) | function i(){try{return e in b&&b[e]&&b[e][b.location.hostname]}catch(a)...
function m (line 2) | function m(b){return function(){var c=Array.prototype.slice.call(argumen...
function o (line 2) | function o(a){return a.replace(n,"___")}
FILE: src/test/java/com/porterhead/rest/authorization/BaseAuthorizationTst.java
class BaseAuthorizationTst (line 20) | public class BaseAuthorizationTst {
method setUp (line 33) | @Before
method getAuthorizationRequest (line 43) | protected AuthorizationRequestContext getAuthorizationRequest(String h...
method getAuthorizationRequest (line 47) | protected AuthorizationRequestContext getAuthorizationRequest(String h...
FILE: src/test/java/com/porterhead/rest/authorization/RequestSigningAuthorizationServiceTest.java
class RequestSigningAuthorizationServiceTest (line 25) | public class RequestSigningAuthorizationServiceTest extends BaseAuthoriz...
method setUp (line 30) | @Before
method authorizeUser (line 37) | @Test
method invalidUnEncodedRequest (line 45) | @Test (expected = AuthorizationException.class)
method invalidSessionToken (line 51) | @Test (expected = AuthorizationException.class)
method missingNonce (line 57) | @Test
method wrongNonce (line 64) | @Test (expected = AuthorizationException.class)
method dateOutOfRange (line 71) | @Test (expected = AuthorizationException.class)
method nullSessionToken (line 79) | @Test
FILE: src/test/java/com/porterhead/rest/authorization/SecurityContextTest.java
class SecurityContextTest (line 20) | public class SecurityContextTest {
method validRole (line 22) | @Test
method invalidRole (line 28) | @Test
method allowAnonymousRole (line 34) | @Test
method caseDoesNotMatter (line 40) | @Test
method authenticationFailure (line 46) | @Test(expected = InvalidAuthorizationHeaderException.class)
method nullSession (line 55) | @Test(expected = InvalidAuthorizationHeaderException.class)
method createSecurityContext (line 62) | private SecurityContext createSecurityContext(Role role) {
FILE: src/test/java/com/porterhead/rest/authorization/SessionTokenAuthorizationServiceTest.java
class SessionTokenAuthorizationServiceTest (line 18) | public class SessionTokenAuthorizationServiceTest extends BaseAuthorizat...
method setUp (line 21) | @Before
method authorizeUser (line 27) | @Test
method invalidSessionToken (line 33) | @Test (expected = AuthorizationException.class)
method noSessionToken (line 38) | @Test
FILE: src/test/java/com/porterhead/rest/filter/SecurityContextFilterTest.java
class SecurityContextFilterTest (line 29) | public class SecurityContextFilterTest {
method setUp (line 37) | @Before
method noHeadersInRequest (line 49) | @Test
method validAuthHeaders (line 57) | @Test
method setUpValidRequest (line 63) | private void setUpValidRequest() {
method dateHeaderIsOutOfRange (line 86) | @Test (expected = AuthorizationException.class)
method duplicateNonce (line 97) | @Test (expected = AuthorizationException.class)
FILE: src/test/java/com/porterhead/rest/mock/AppMockConfiguration.java
class AppMockConfiguration (line 21) | @Configuration
method environment (line 28) | public Environment environment() {
method userService (line 33) | @Bean
method verificationTokenService (line 39) | @Bean
method mailSenderService (line 45) | @Bean
method emailServicesGateway (line 51) | @Bean
method connectionFactoryLocator (line 57) | @Bean
FILE: src/test/java/com/porterhead/rest/resource/BaseResourceTst.java
class BaseResourceTst (line 29) | @ActiveProfiles(profiles = "dev")
method BaseResourceTst (line 32) | public BaseResourceTst(WebAppDescriptor descriptor) {
class ApplicationContextAccess (line 66) | public static class ApplicationContextAccess implements ApplicationCon...
method setApplicationContext (line 67) | public void setApplicationContext(ApplicationContext ctx) {
method setUpMocks (line 83) | @Before
method createSignupRequest (line 93) | protected CreateUserRequest createSignupRequest() {
method createLoginRequest (line 99) | protected LoginRequest createLoginRequest() {
method createUpdateUserRequest (line 106) | protected UpdateUserRequest createUpdateUserRequest(String emailAddres...
FILE: src/test/java/com/porterhead/rest/resource/ConsumerSimpleSecurityFilter.java
class ConsumerSimpleSecurityFilter (line 10) | public class ConsumerSimpleSecurityFilter extends SimpleSecurityFilter {
method getUser (line 12) | @Override
FILE: src/test/java/com/porterhead/rest/resource/HealthCheckResourceTest.java
class HealthCheckResourceTest (line 19) | public class HealthCheckResourceTest extends BaseResourceTst {
method HealthCheckResourceTest (line 21) | public HealthCheckResourceTest() {
method check (line 31) | @Test
FILE: src/test/java/com/porterhead/rest/resource/SimpleSecurityFilter.java
class SimpleSecurityFilter (line 14) | public abstract class SimpleSecurityFilter implements ContainerRequestFi...
method filter (line 16) | public ContainerRequest filter(ContainerRequest request) {
method getUser (line 22) | abstract User getUser();
FILE: src/test/java/com/porterhead/rest/user/BaseServiceTest.java
class BaseServiceTest (line 19) | public class BaseServiceTest {
method createUserWithRandomUserName (line 31) | protected AuthenticatedUserToken createUserWithRandomUserName(Role rol...
method getDefaultCreateUserRequest (line 36) | protected CreateUserRequest getDefaultCreateUserRequest() {
method getUser (line 43) | protected ExternalUser getUser() {
method createRandomEmailAddress (line 51) | protected String createRandomEmailAddress() {
FILE: src/test/java/com/porterhead/rest/user/MailSenderServiceTest.java
class MailSenderServiceTest (line 36) | @RunWith(SpringJUnit4ClassRunner.class)
method setUpServices (line 52) | @Before
method sendVerificationEmail (line 60) | @Test
method sendRegistrationEmail (line 70) | @Test
method sendLostPasswordEmail (line 80) | @Test
method assertOnMailResult (line 90) | private void assertOnMailResult(User user, VerificationToken token) th...
FILE: src/test/java/com/porterhead/rest/user/UserServiceTest.java
class UserServiceTest (line 31) | @RunWith(SpringJUnit4ClassRunner.class)
method createValidUser (line 38) | @Test
method createDefaultUser (line 45) | @Test
method duplicateUser (line 53) | @Test(expected = DuplicateUserException.class)
method nullPasswordRequest (line 62) | @Test(expected = ValidationException.class)
method badNameRequest (line 70) | @Test(expected = ValidationException.class)
method nullEmailAndUsernameRequest (line 80) | @Test(expected = ValidationException.class)
method validLoginWithEmailAddress (line 91) | @Test
method multipleLoginsGetSameAuthToken (line 108) | @Test
method invalidLoginRequestNullPassword (line 121) | @Test(expected = ValidationException.class)
method invalidLoginRequestNullEmailAddress (line 128) | @Test(expected = ValidationException.class)
method emailAddressAlreadyExists (line 135) | @Test(expected = DuplicateUserException.class)
method invalidPassword (line 142) | @Test(expected = AuthenticationException.class)
method userNotFound (line 153) | @Test(expected = AuthenticationException.class)
method userNotAuthorizedToDelete (line 162) | @Test (expected = AuthorizationException.class)
method getValidUser (line 171) | @Test
method getUserNotFound (line 179) | @Test (expected = UserNotFoundException.class)
method getUserByEmailAddress (line 184) | @Test
method updateUser (line 193) | @Test
method updateUserWithInvalidEmailAddress (line 207) | @Test (expected = ValidationException.class)
FILE: src/test/java/com/porterhead/rest/user/VerificationServiceTest.java
class VerificationServiceTest (line 34) | public class VerificationServiceTest {
method setUp (line 43) | @Before
method sendLostPasswordToken (line 68) | @Test
method sendLostPasswordTokenAgain (line 84) | @Test
method resetPassword (line 96) | @Test
method resetPasswordGetNewToken (line 112) | @Test
method sendEmailToken (line 125) | @Test
method sendRegistrationToken (line 139) | @Test
method verifyValidToken (line 153) | @Test
method tokenHasExpired (line 167) | @Test (expected = TokenHasExpiredException.class)
method tokenAlreadyVerified (line 180) | @Test (expected = AlreadyVerifiedException.class)
method userAlreadyVerified (line 194) | @Test (expected = AlreadyVerifiedException.class)
method tokenNotFound (line 209) | @Test (expected = TokenNotFoundException.class)
method generateEmailToken (line 217) | @Test
method generateTestUser (line 232) | private User generateTestUser() {
method generateEmailTokenAlreadyActive (line 238) | @Test
method generateEmailTokenAfterExpired (line 250) | @Test
method emailAddressNotFound (line 264) | @Test (expected = UserNotFoundException.class)
method generateEmailTokenAlreadyVerified (line 269) | @Test (expected = AlreadyVerifiedException.class)
FILE: src/test/java/com/porterhead/rest/user/api/CreateUserRequestTest.java
class CreateUserRequestTest (line 17) | public class CreateUserRequestTest extends ValidationTst {
method validRequest (line 20) | @Test
method nullUser (line 32) | @Test
method firstNameTooLong (line 40) | @Test
method lastNameTooLong (line 51) | @Test
FILE: src/test/java/com/porterhead/rest/user/api/LoginRequestTest.java
class LoginRequestTest (line 18) | public class LoginRequestTest extends ValidationTst {
method validRequest (line 20) | @Test
method invalidPassword (line 29) | @Test
FILE: src/test/java/com/porterhead/rest/user/api/PasswordRequestTest.java
class PasswordRequestTest (line 18) | public class PasswordRequestTest extends ValidationTst {
method validPassword (line 20) | @Test
method passwordTooShort (line 27) | public void passwordTooShort() {
method passwordTooLong (line 33) | public void passwordTooLong() {
FILE: src/test/java/com/porterhead/rest/user/api/ValidationTst.java
class ValidationTst (line 13) | public class ValidationTst {
method setUp (line 17) | @Before
FILE: src/test/java/com/porterhead/rest/user/builder/ExternalUserBuilder.java
class ExternalUserBuilder (line 10) | public class ExternalUserBuilder {
method create (line 12) | public static ExternalUserBuilder create() {
method ExternalUserBuilder (line 19) | public ExternalUserBuilder() {
method build (line 23) | public ExternalUser build() {
method withFirstName (line 27) | public ExternalUserBuilder withFirstName(String name) {
method withLastName (line 32) | public ExternalUserBuilder withLastName(String name) {
method withEmailAddress (line 37) | public ExternalUserBuilder withEmailAddress(String email) {
FILE: src/test/java/com/porterhead/rest/user/resource/PasswordResourceTest.java
class PasswordResourceTest (line 26) | public class PasswordResourceTest extends BaseResourceTst {
method PasswordResourceTest (line 28) | public PasswordResourceTest() {
method sendEmailToken (line 39) | @Test
method resetPassword (line 45) | @Test
method createLostPasswordRequest (line 51) | private LostPasswordRequest createLostPasswordRequest(String emailAddr...
method createPasswordRequest (line 57) | private PasswordRequest createPasswordRequest(String password) {
FILE: src/test/java/com/porterhead/rest/user/resource/UserResourceTest.java
class UserResourceTest (line 34) | public class UserResourceTest extends BaseResourceTst {
method UserResourceTest (line 36) | public UserResourceTest() {
method signUp (line 47) | @Test
method validationErrorOnCreateUser (line 60) | @Test
method duplicateUserOnCreateUser (line 68) | @Test
method login (line 76) | @Test
method socialLogin (line 87) | @Test
method validationErrorOnLogin (line 104) | @Test
method authenticationErrorOnLogin (line 111) | @Test
method getUser (line 118) | @Test
method deleteUser (line 130) | @Test
method updateUserWithNewEmailAddress (line 136) | @Test
method updateUserButNotEmailAddress (line 145) | @Test
method userTriesToModifyAnotherUserProfile (line 153) | @Test
method runtimeError (line 162) | @Test
FILE: src/test/java/com/porterhead/rest/user/resource/VerificationResourceTest.java
class VerificationResourceTest (line 28) | public class VerificationResourceTest extends BaseResourceTst {
method VerificationResourceTest (line 30) | public VerificationResourceTest() {
method verify (line 42) | @Test
method generateEmailToken (line 51) | @Test
FILE: src/test/java/com/porterhead/rest/user/social/AbstractSocialTst.java
class AbstractSocialTst (line 27) | public abstract class AbstractSocialTst {
method setMocks (line 44) | @Before
method setUpRepository (line 53) | public abstract void setUpRepository();
method mockUserRepository (line 55) | private void mockUserRepository() {
method mockSocialUsers (line 61) | private void mockSocialUsers() {
method mockConnectionData (line 75) | private void mockConnectionData() {
FILE: src/test/java/com/porterhead/rest/user/social/JpaConnectionRepositoryTest.java
class JpaConnectionRepositoryTest (line 17) | public class JpaConnectionRepositoryTest extends AbstractSocialTst {
method setUpRepository (line 21) | @Before
method findAllConnections (line 26) | @Test
FILE: src/test/java/com/porterhead/rest/user/social/JpaUsersConnectionRepositoryTest.java
class JpaUsersConnectionRepositoryTest (line 38) | public class JpaUsersConnectionRepositoryTest extends AbstractSocialTst {
method setUpRepository (line 45) | public void setUpRepository() {
method firstTimeConnected (line 60) | @Test
method alreadyRegistered (line 71) | @Test
method validSocialLogin (line 82) | @Test
method updateFromSocialLogin (line 99) | @Test
method loginWithEmailAddressThenSocialLogin (line 124) | @Test
method getCreateUserRequest (line 143) | private CreateUserRequest getCreateUserRequest(String emailAddress) {
Condensed preview — 146 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (405K chars).
[
{
"path": ".gitignore",
"chars": 146,
"preview": "\n.DS_Store\n\n.gradle/*\n\nbuild/*\n\nout/*\n\n*.iml\n\n*.ipr\n\n*.iws\n/build/\n/bin/\n\n# eclipse\n.settings/\n.project\n.classpath\n\n# In"
},
{
"path": "LICENSE.md",
"chars": 11325,
"preview": "Apache License\n Version 2.0, January 2004\n http://www.apache.org/licens"
},
{
"path": "README.md",
"chars": 2035,
"preview": "JAVA REST Application\r\n====================\r\n\r\nSimple and easily understandable web project that demonstrates the use of"
},
{
"path": "build.gradle",
"chars": 9350,
"preview": "apply plugin: 'idea'\napply plugin: 'java'\napply plugin: 'tomcat'\napply plugin: 'war'\napply plugin: 'groovy'\napply plugin"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 229,
"preview": "#Tue Jul 29 21:04:58 BST 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 66,
"preview": "systemProp.spring.profiles.active=dev\n\nplease accept pull request\n"
},
{
"path": "gradlew",
"chars": 5080,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2404,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
},
{
"path": "src/main/config/ci/gradle.properties",
"chars": 137,
"preview": "\ntomcatContainerId=tomcat6x\ntomcatPort=8080\ntomcatHostname=localhost\ntomcatUsername=admin\ntomcatPassword=admin\ntomcatCon"
},
{
"path": "src/main/java/com/porterhead/rest/api/ErrorResponse.java",
"chars": 1277,
"preview": "package com.porterhead.rest.api;\n\nimport javax.xml.bind.annotation.XmlRootElement;\nimport java.util.ArrayList;\nimport ja"
},
{
"path": "src/main/java/com/porterhead/rest/api/PagedQueryRequest.java",
"chars": 1554,
"preview": "package com.porterhead.rest.api;\n\n/**\n * @version 1.0\n * @author: Iain Porter\n * @since 28/02/2013\n */\npublic class Page"
},
{
"path": "src/main/java/com/porterhead/rest/api/PagedResponse.java",
"chars": 886,
"preview": "package com.porterhead.rest.api;\n\nimport javax.xml.bind.annotation.XmlRootElement;\nimport java.util.List;\n\n/**\n * @versi"
},
{
"path": "src/main/java/com/porterhead/rest/api/ValidationError.java",
"chars": 808,
"preview": "package com.porterhead.rest.api;\n\nimport javax.xml.bind.annotation.XmlRootElement;\n\n/**\n * @version 1.0\n * @author: Iain"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/AuthorizationRequestContext.java",
"chars": 1529,
"preview": "package com.porterhead.rest.authorization;\n\n/**\n *\n * @version 1.0\n * @author: Iain Porter\n * @since 28/01/2013\n */\npubl"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/AuthorizationService.java",
"chars": 498,
"preview": "package com.porterhead.rest.authorization;\n\nimport com.porterhead.rest.user.api.ExternalUser;\n\n/**\n *\n * @author: Iain P"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/exception/InvalidAuthorizationHeaderException.java",
"chars": 650,
"preview": "package com.porterhead.rest.authorization.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/impl/RequestSigningAuthorizationService.java",
"chars": 10055,
"preview": "package com.porterhead.rest.authorization.impl;\n\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.c"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/impl/SecurityContextImpl.java",
"chars": 1146,
"preview": "package com.porterhead.rest.authorization.impl;\n\nimport com.porterhead.rest.authorization.exception.InvalidAuthorization"
},
{
"path": "src/main/java/com/porterhead/rest/authorization/impl/SessionTokenAuthorizationService.java",
"chars": 1652,
"preview": "package com.porterhead.rest.authorization.impl;\n\nimport com.porterhead.rest.authorization.AuthorizationRequestContext;\ni"
},
{
"path": "src/main/java/com/porterhead/rest/config/ApplicationConfig.java",
"chars": 3743,
"preview": "package com.porterhead.rest.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springfra"
},
{
"path": "src/main/java/com/porterhead/rest/config/ApplicationDevConfig.java",
"chars": 740,
"preview": "package com.porterhead.rest.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.cont"
},
{
"path": "src/main/java/com/porterhead/rest/config/ApplicationProductionConfig.java",
"chars": 1045,
"preview": "package com.porterhead.rest.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springfra"
},
{
"path": "src/main/java/com/porterhead/rest/config/ApplicationStagingConfig.java",
"chars": 1047,
"preview": "package com.porterhead.rest.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springfra"
},
{
"path": "src/main/java/com/porterhead/rest/exception/ApplicationRuntimeException.java",
"chars": 271,
"preview": "package com.porterhead.rest.exception;\n\n\npublic class ApplicationRuntimeException extends BaseWebApplicationException {\n"
},
{
"path": "src/main/java/com/porterhead/rest/exception/BaseWebApplicationException.java",
"chars": 1277,
"preview": "package com.porterhead.rest.exception;\n\nimport com.porterhead.rest.api.ErrorResponse;\n\nimport javax.ws.rs.WebApplication"
},
{
"path": "src/main/java/com/porterhead/rest/exception/NotFoundException.java",
"chars": 271,
"preview": "package com.porterhead.rest.exception;\n\nimport javax.ws.rs.WebApplicationException;\n\n/**\n * User: porter\n * Date: 03/05/"
},
{
"path": "src/main/java/com/porterhead/rest/exception/ValidationException.java",
"chars": 1994,
"preview": "package com.porterhead.rest.exception;\n\nimport com.porterhead.rest.api.ErrorResponse;\nimport com.porterhead.rest.api.Val"
},
{
"path": "src/main/java/com/porterhead/rest/filter/ResourceFilterFactory.java",
"chars": 1465,
"preview": "package com.porterhead.rest.filter;\n\nimport com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory;\nimpor"
},
{
"path": "src/main/java/com/porterhead/rest/filter/SecurityContextFilter.java",
"chars": 4290,
"preview": "package com.porterhead.rest.filter;\n\nimport com.porterhead.rest.authorization.AuthorizationRequestContext;\nimport com.po"
},
{
"path": "src/main/java/com/porterhead/rest/gateway/EmailServicesGateway.java",
"chars": 306,
"preview": "package com.porterhead.rest.gateway;\n\nimport com.porterhead.rest.user.EmailServiceTokenModel;\n\n/**\n *\n * @version 1.0\n *"
},
{
"path": "src/main/java/com/porterhead/rest/model/BaseEntity.java",
"chars": 1790,
"preview": "package com.porterhead.rest.model;\n\nimport org.springframework.data.jpa.domain.AbstractPersistable;\nimport org.springfra"
},
{
"path": "src/main/java/com/porterhead/rest/resource/GenericExceptionMapper.java",
"chars": 958,
"preview": "package com.porterhead.rest.resource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.ws.rs.WebA"
},
{
"path": "src/main/java/com/porterhead/rest/resource/HealthCheckResource.java",
"chars": 877,
"preview": "package com.porterhead.rest.resource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springf"
},
{
"path": "src/main/java/com/porterhead/rest/service/BaseService.java",
"chars": 704,
"preview": "package com.porterhead.rest.service;\n\nimport com.porterhead.rest.exception.ValidationException;\n\nimport javax.validation"
},
{
"path": "src/main/java/com/porterhead/rest/user/EmailServiceTokenModel.java",
"chars": 1255,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.domain.User;\nimport com.porterhead.rest.user.domain.V"
},
{
"path": "src/main/java/com/porterhead/rest/user/SocialUserRepository.java",
"chars": 1156,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.domain.SocialUser;\nimport com.porterhead.rest.user.do"
},
{
"path": "src/main/java/com/porterhead/rest/user/UserRepository.java",
"chars": 851,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.domain.User;\nimport org.springframework.data.jpa.repo"
},
{
"path": "src/main/java/com/porterhead/rest/user/UserService.java",
"chars": 2341,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.api.*;\nimport com.porterhead.rest.user.domain.Authori"
},
{
"path": "src/main/java/com/porterhead/rest/user/UserServiceImpl.java",
"chars": 9659,
"preview": "package com.porterhead.rest.user;\n\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.serv"
},
{
"path": "src/main/java/com/porterhead/rest/user/VerificationTokenRepository.java",
"chars": 627,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.domain.VerificationToken;\nimport org.springframework."
},
{
"path": "src/main/java/com/porterhead/rest/user/VerificationTokenService.java",
"chars": 842,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.user.api.LostPasswordRequest;\nimport com.porterhead.rest.u"
},
{
"path": "src/main/java/com/porterhead/rest/user/VerificationTokenServiceImpl.java",
"chars": 7375,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.gatew"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/AuthenticatedUserToken.java",
"chars": 692,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.xml.bind.annotation.XmlRootElement;\n\n/**\n * @author: Iain Porter\n */"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/CreateUserRequest.java",
"chars": 878,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.validation.Valid;\nimport javax.validation.constraints.NotNull;\nimpor"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/EmailVerificationRequest.java",
"chars": 666,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.validation.constraints.NotNull;\nimport javax.xml.bind.annotation.Xml"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/ExternalUser.java",
"chars": 2802,
"preview": "package com.porterhead.rest.user.api;\n\nimport com.porterhead.rest.user.domain.AuthorizationToken;\nimport com.porterhead."
},
{
"path": "src/main/java/com/porterhead/rest/user/api/LoginRequest.java",
"chars": 718,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.hibernate.validator.constraints.Length;\n\nimport javax.validation.const"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/LostPasswordRequest.java",
"chars": 657,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.validation.constraints.NotNull;\nimport javax.xml.bind.annotation.Xml"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/OAuth2Request.java",
"chars": 458,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.validation.constraints.NotNull;\nimport javax.xml.bind.annotation.Xml"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/PasswordRequest.java",
"chars": 685,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.hibernate.validator.constraints.Length;\n\nimport javax.validation.const"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/SocialProfile.java",
"chars": 1152,
"preview": "package com.porterhead.rest.user.api;\n\nimport javax.xml.bind.annotation.XmlRootElement;\n\n/**\n * @author: Iain Porter\n */"
},
{
"path": "src/main/java/com/porterhead/rest/user/api/UpdateUserRequest.java",
"chars": 979,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.hibernate.validator.constraints.Email;\n\nimport javax.validation.constr"
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/AuthorizationToken.java",
"chars": 1441,
"preview": "package com.porterhead.rest.user.domain;\n\nimport org.springframework.data.jpa.domain.AbstractPersistable;\n\nimport javax."
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/Role.java",
"chars": 176,
"preview": "package com.porterhead.rest.user.domain;\n\n/**\n * User: porter\n * Date: 03/04/2012\n * Time: 13:17\n */\npublic enum Role {\n"
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/SocialUser.java",
"chars": 2656,
"preview": "package com.porterhead.rest.user.domain;\n\nimport com.porterhead.rest.model.BaseEntity;\n\nimport javax.persistence.*;\n\n/**"
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/SocialUserBuilder.java",
"chars": 1964,
"preview": "package com.porterhead.rest.user.domain;\n\n/**\n * User: porter\n * Date: 21/05/2012\n * Time: 08:12\n */\n public class So"
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/User.java",
"chars": 6966,
"preview": "package com.porterhead.rest.user.domain;\n\nimport com.porterhead.rest.model.BaseEntity;\nimport com.porterhead.rest.user.a"
},
{
"path": "src/main/java/com/porterhead/rest/user/domain/VerificationToken.java",
"chars": 2388,
"preview": "package com.porterhead.rest.user.domain;\n\nimport com.porterhead.rest.model.BaseEntity;\nimport org.joda.time.DateTime;\n\ni"
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/AlreadyVerifiedException.java",
"chars": 424,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n *\n "
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/AuthenticationException.java",
"chars": 414,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n * U"
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/AuthorizationException.java",
"chars": 386,
"preview": "package com.porterhead.rest.user.exception;\n\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n * "
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/DuplicateUserException.java",
"chars": 404,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n * U"
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/TokenHasExpiredException.java",
"chars": 442,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n *\n "
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/TokenNotFoundException.java",
"chars": 419,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n *\n "
},
{
"path": "src/main/java/com/porterhead/rest/user/exception/UserNotFoundException.java",
"chars": 415,
"preview": "package com.porterhead.rest.user.exception;\n\nimport com.porterhead.rest.exception.BaseWebApplicationException;\n\n/**\n *\n "
},
{
"path": "src/main/java/com/porterhead/rest/user/mail/MailSenderService.java",
"chars": 552,
"preview": "package com.porterhead.rest.user.mail;\n\nimport com.porterhead.rest.user.EmailServiceTokenModel;\n\n/**\n *\n * @version 1.0\n"
},
{
"path": "src/main/java/com/porterhead/rest/user/mail/MockJavaMailSender.java",
"chars": 2366,
"preview": "package com.porterhead.rest.user.mail;\n\nimport org.springframework.mail.MailException;\nimport org.springframework.mail.S"
},
{
"path": "src/main/java/com/porterhead/rest/user/mail/impl/MailSenderServiceImpl.java",
"chars": 4619,
"preview": "package com.porterhead.rest.user.mail.impl;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead."
},
{
"path": "src/main/java/com/porterhead/rest/user/resource/PasswordResource.java",
"chars": 1288,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.user.VerificationTokenService;\nimport com.porterh"
},
{
"path": "src/main/java/com/porterhead/rest/user/resource/UserResource.java",
"chars": 4700,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.r"
},
{
"path": "src/main/java/com/porterhead/rest/user/resource/VerificationResource.java",
"chars": 1203,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.user.VerificationTokenService;\nimport com.porterh"
},
{
"path": "src/main/java/com/porterhead/rest/user/social/JpaConnectionRepository.java",
"chars": 9153,
"preview": "package com.porterhead.rest.user.social;\n\nimport com.porterhead.rest.user.SocialUserRepository;\nimport com.porterhead.re"
},
{
"path": "src/main/java/com/porterhead/rest/user/social/JpaUsersConnectionRepository.java",
"chars": 4017,
"preview": "package com.porterhead.rest.user.social;\n\nimport com.porterhead.rest.user.domain.Role;\nimport com.porterhead.rest.user.d"
},
{
"path": "src/main/java/com/porterhead/rest/user/social/SocialConfig.java",
"chars": 1711,
"preview": "package com.porterhead.rest.user.social;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.res"
},
{
"path": "src/main/java/com/porterhead/rest/util/DateUtil.java",
"chars": 771,
"preview": "package com.porterhead.rest.util;\n\nimport org.joda.time.DateTime;\nimport org.joda.time.format.DateTimeFormatter;\nimport "
},
{
"path": "src/main/java/com/porterhead/rest/util/HashUtil.java",
"chars": 1203,
"preview": "package com.porterhead.rest.util;\n\nimport org.apache.commons.codec.binary.Base64;\nimport org.apache.commons.codec.digest"
},
{
"path": "src/main/java/com/porterhead/rest/util/StringUtil.java",
"chars": 1065,
"preview": "package com.porterhead.rest.util;\n\nimport org.springframework.util.StringUtils;\n\nimport java.util.regex.Pattern;\n\nimport"
},
{
"path": "src/main/resources/META-INF/persistence.xml",
"chars": 1529,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\n<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmln"
},
{
"path": "src/main/resources/META-INF/spring/component-scan-context.xml",
"chars": 857,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/spring/data-context.xml",
"chars": 3229,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/spring/email-services-context.xml",
"chars": 3234,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/spring/email-template-context.xml",
"chars": 1434,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/spring/root-context.xml",
"chars": 1124,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/spring/social-configuration-context.xml",
"chars": 368,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n xmlns:xsi=\"http"
},
{
"path": "src/main/resources/META-INF/velocity/LostPasswordEmail.vm",
"chars": 2063,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Sample Rest Application</title>\n </head>\n <body style=\"margin: 0px; font-fa"
},
{
"path": "src/main/resources/META-INF/velocity/RegistrationEmail.vm",
"chars": 1693,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Sample Web</title>\n </head>\n <body style=\"margin: 0px; font-family: 'Helvet"
},
{
"path": "src/main/resources/META-INF/velocity/VerifyEmail.vm",
"chars": 1982,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Verify Your Email</title>\n </head>\n <body style=\"margin: 0px; font-family: "
},
{
"path": "src/main/resources/logback.xml",
"chars": 437,
"preview": "<configuration>\n <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n <layout class=\"ch.qos.l"
},
{
"path": "src/main/resources/properties/app.properties",
"chars": 1668,
"preview": "#The Facebook app credentials for supporting Facebook login\nfacebook.clientId=133718006790561\nfacebook.clientSecret=2f48"
},
{
"path": "src/main/resources/properties/dev-app.properties",
"chars": 44,
"preview": "hostNameUrl=http://localhost:8080/java-rest\n"
},
{
"path": "src/main/resources/properties/production-app.properties",
"chars": 44,
"preview": "hostNameUrl=http://localhost:8080/java-rest\n"
},
{
"path": "src/main/resources/properties/staging-app.properties",
"chars": 44,
"preview": "hostNameUrl=http://localhost:8080/java-rest\n"
},
{
"path": "src/main/resources/schema/indexes.sql",
"chars": 455,
"preview": "\nCREATE UNIQUE INDEX user_uuid_IDX ON rest_user ( uuid);\nCREATE INDEX user_email_address_IDX on rest_user (email_address"
},
{
"path": "src/main/resources/schema/message_store.sql",
"chars": 716,
"preview": "CREATE TABLE INT_MESSAGE (\n\tMESSAGE_ID CHAR(36) NOT NULL PRIMARY KEY,\n\tREGION VARCHAR(100),\n\tCREATED_DATE DATETIME NOT "
},
{
"path": "src/main/resources/schema/truncate_data.sql",
"chars": 150,
"preview": "-- truncate all data\nTRUNCATE table social_user;\nTRUNCATE table rest_session_token;\nTRUNCATE table rest_verification_tok"
},
{
"path": "src/main/webapp/META-INF/MANIFEST.MF",
"chars": 39,
"preview": "Manifest-Version: 1.0\r\nClass-Path: \r\n\r\n"
},
{
"path": "src/main/webapp/WEB-INF/spring/appservlet/servlet-context.xml",
"chars": 388,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans:beans\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns:beans="
},
{
"path": "src/main/webapp/WEB-INF/web.xml",
"chars": 2553,
"preview": "<web-app id=\"WebApp_ID\" version=\"2.4\"\n\txmlns=\"http://java.sun.com/xml/ns/j2ee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSche"
},
{
"path": "src/main/webapp/css/styles.css",
"chars": 4554,
"preview": "/*---------------Site styles------------*/\n\nbody {\n background-color: #5087A3;\n color: white;\n font-family: helvetica"
},
{
"path": "src/main/webapp/dashboard.html",
"chars": 2023,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Java Rest sample application</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/forgot_password.html",
"chars": 1459,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Java REST Sample Application</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/index.html",
"chars": 3323,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Sample Java Rest Application</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/js/bootstrap.js",
"chars": 56264,
"preview": "/* ===================================================\n * bootstrap-transition.js v2.1.1\n * http://twitter.github.com/bo"
},
{
"path": "src/main/webapp/js/cookie.js",
"chars": 788,
"preview": "/**\n * Holds cookie methods\n */\njavaRest.cookie = {}\n\n/**\n * Get the value of a cookie.\n * @param {string}\n * @return {s"
},
{
"path": "src/main/webapp/js/enc-base64-min.js",
"chars": 891,
"preview": "/*\nCryptoJS v3.0.2\ncode.google.com/p/crypto-js\n(c) 2009-2012 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "src/main/webapp/js/grid.locale-en.js",
"chars": 3961,
"preview": ";(function($){\r\n/**\r\n * jqGrid English Translation\r\n * Tony Tomov tony@trirand.com\r\n * http://trirand.com/blog/ \r\n * Dua"
},
{
"path": "src/main/webapp/js/javarest.js",
"chars": 3696,
"preview": "/**\n * Singleton used for Namespace\n */\nfunction javaRest() {\n \n}\n\n/**\n * Wrap the API so we can proxy calls while test"
},
{
"path": "src/main/webapp/js/jquery-full-house.js",
"chars": 3878,
"preview": "/*\n Based on this script by Marcus Ekwall\n http://jsfiddle.net/mekwall/fNyHs/\n\n\tExamples, support and the newest v"
},
{
"path": "src/main/webapp/js/sha256.js",
"chars": 4419,
"preview": "/*\nCryptoJS v3.0.2\ncode.google.com/p/crypto-js\n(c) 2009-2012 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "src/main/webapp/js/store.js",
"chars": 2700,
"preview": "/* Copyright (c) 2010-2012 Marcus Westin */\n(function(){function h(){try{return d in b&&b[d]}catch(a){return!1}}function"
},
{
"path": "src/main/webapp/js/user.js",
"chars": 4466,
"preview": "javaRest.user = {}\n\n\n/**\n * Create a user\n *\n * @param {string}\n * @param {string}\n * @param {string}\n * @param {string}"
},
{
"path": "src/main/webapp/js/verify.js",
"chars": 621,
"preview": "javaRest.verify = {}\n\n/**\n * Sends an email to user for verification\n */\njavaRest.verify.request_email = function (email"
},
{
"path": "src/main/webapp/request_email.html",
"chars": 1360,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Sample Java REST applicaiton</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/reset_password.html",
"chars": 1757,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Java REST Sample Application</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/signup.html",
"chars": 3974,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Sample Java REST Application</title>\n <link href=\"css/styles.css\" rel=\"sty"
},
{
"path": "src/main/webapp/validate.html",
"chars": 1528,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <title>Email Validation</title>\n <link href=\"css/styles.css\" rel=\"stylesheet\">\n "
},
{
"path": "src/test/groovy/BaseIntegrationTst.groovy",
"chars": 3918,
"preview": "import groovyx.net.http.ContentType\nimport groovyx.net.http.RESTClient\nimport org.apache.commons.codec.binary.Base64\nimp"
},
{
"path": "src/test/groovy/UserIntegrationTest.groovy",
"chars": 5440,
"preview": "import groovyx.net.http.ContentType\nimport static org.hamcrest.Matchers.*\nimport static org.junit.Assert.assertThat\n\n/**"
},
{
"path": "src/test/java/com/porterhead/rest/authorization/BaseAuthorizationTst.java",
"chars": 2068,
"preview": "package com.porterhead.rest.authorization;\n\nimport com.porterhead.rest.authorization.impl.SessionTokenAuthorizationServi"
},
{
"path": "src/test/java/com/porterhead/rest/authorization/RequestSigningAuthorizationServiceTest.java",
"chars": 4053,
"preview": "package com.porterhead.rest.authorization;\n\nimport com.porterhead.rest.authorization.impl.RequestSigningAuthorizationSer"
},
{
"path": "src/test/java/com/porterhead/rest/authorization/SecurityContextTest.java",
"chars": 2289,
"preview": "package com.porterhead.rest.authorization;\n\nimport com.porterhead.rest.authorization.exception.InvalidAuthorizationHeade"
},
{
"path": "src/test/java/com/porterhead/rest/authorization/SessionTokenAuthorizationServiceTest.java",
"chars": 1364,
"preview": "package com.porterhead.rest.authorization;\n\nimport com.porterhead.rest.authorization.impl.SessionTokenAuthorizationServi"
},
{
"path": "src/test/java/com/porterhead/rest/filter/SecurityContextFilterTest.java",
"chars": 4915,
"preview": "package com.porterhead.rest.filter;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.use"
},
{
"path": "src/test/java/com/porterhead/rest/mock/AppMockConfiguration.java",
"chars": 1883,
"preview": "package com.porterhead.rest.mock;\n\nimport com.porterhead.rest.gateway.EmailServicesGateway;\nimport com.porterhead.rest.u"
},
{
"path": "src/test/java/com/porterhead/rest/resource/BaseResourceTst.java",
"chars": 4071,
"preview": "package com.porterhead.rest.resource;\n\nimport com.porterhead.rest.user.UserService;\nimport com.porterhead.rest.user.Veri"
},
{
"path": "src/test/java/com/porterhead/rest/resource/ConsumerSimpleSecurityFilter.java",
"chars": 303,
"preview": "package com.porterhead.rest.resource;\n\nimport com.porterhead.rest.user.domain.User;\n\n/**\n * User: porter\n * Date: 08/05/"
},
{
"path": "src/test/java/com/porterhead/rest/resource/HealthCheckResourceTest.java",
"chars": 1324,
"preview": "package com.porterhead.rest.resource;\n\nimport com.sun.jersey.api.client.ClientResponse;\nimport com.sun.jersey.spi.spring"
},
{
"path": "src/test/java/com/porterhead/rest/resource/SimpleSecurityFilter.java",
"chars": 720,
"preview": "package com.porterhead.rest.resource;\n\nimport com.porterhead.rest.user.api.ExternalUser;\nimport com.porterhead.rest.auth"
},
{
"path": "src/test/java/com/porterhead/rest/user/BaseServiceTest.java",
"chars": 1656,
"preview": "package com.porterhead.rest.user;\n\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.user"
},
{
"path": "src/test/java/com/porterhead/rest/user/MailSenderServiceTest.java",
"chars": 4144,
"preview": "package com.porterhead.rest.user;\n\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.user"
},
{
"path": "src/test/java/com/porterhead/rest/user/UserServiceTest.java",
"chars": 9055,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.exception.ValidationException;\nimport com.porterhead.rest."
},
{
"path": "src/test/java/com/porterhead/rest/user/VerificationServiceTest.java",
"chars": 13691,
"preview": "package com.porterhead.rest.user;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.rest.gatew"
},
{
"path": "src/test/java/com/porterhead/rest/user/api/CreateUserRequestTest.java",
"chars": 2634,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.apache.commons.lang.RandomStringUtils;\nimport org.junit.Test;\n\nimport "
},
{
"path": "src/test/java/com/porterhead/rest/user/api/LoginRequestTest.java",
"chars": 1211,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.apache.commons.lang.RandomStringUtils;\nimport org.junit.Test;\n\nimport "
},
{
"path": "src/test/java/com/porterhead/rest/user/api/PasswordRequestTest.java",
"chars": 1241,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.apache.commons.lang.RandomStringUtils;\nimport org.junit.Test;\n\nimport "
},
{
"path": "src/test/java/com/porterhead/rest/user/api/ValidationTst.java",
"chars": 397,
"preview": "package com.porterhead.rest.user.api;\n\nimport org.junit.Before;\n\nimport javax.validation.Validation;\nimport javax.valida"
},
{
"path": "src/test/java/com/porterhead/rest/user/builder/ExternalUserBuilder.java",
"chars": 839,
"preview": "package com.porterhead.rest.user.builder;\n\nimport com.porterhead.rest.user.api.ExternalUser;\n\n/**\n * User: porter\n * Dat"
},
{
"path": "src/test/java/com/porterhead/rest/user/resource/PasswordResourceTest.java",
"chars": 2549,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.resource.BaseResourceTst;\nimport com.porterhead.r"
},
{
"path": "src/test/java/com/porterhead/rest/user/resource/UserResourceTest.java",
"chars": 8916,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.resource.BaseResourceTst;\nimport com.porterhead.r"
},
{
"path": "src/test/java/com/porterhead/rest/user/resource/VerificationResourceTest.java",
"chars": 2676,
"preview": "package com.porterhead.rest.user.resource;\n\nimport com.porterhead.rest.resource.BaseResourceTst;\nimport com.porterhead.r"
},
{
"path": "src/test/java/com/porterhead/rest/user/social/AbstractSocialTst.java",
"chars": 3281,
"preview": "package com.porterhead.rest.user.social;\n\nimport com.porterhead.rest.user.SocialUserRepository;\nimport com.porterhead.re"
},
{
"path": "src/test/java/com/porterhead/rest/user/social/JpaConnectionRepositoryTest.java",
"chars": 995,
"preview": "package com.porterhead.rest.user.social;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.springframework.soc"
},
{
"path": "src/test/java/com/porterhead/rest/user/social/JpaUsersConnectionRepositoryTest.java",
"chars": 7684,
"preview": "package com.porterhead.rest.user.social;\n\nimport com.porterhead.rest.config.ApplicationConfig;\nimport com.porterhead.res"
},
{
"path": "src/test/resources/integration-test-context.xml",
"chars": 856,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\txmlns:xsi=\"http://www"
},
{
"path": "src/test/resources/social-test-context.xml",
"chars": 357,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\txmlns:xsi=\"http://www"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the iainporter/rest-java GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 146 files (368.0 KB), approximately 90.2k tokens, and a symbol index with 665 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.