Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jh-boot
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jan Hrabal
jh-boot
Commits
6b52ff0f
Commit
6b52ff0f
authored
Nov 21, 2019
by
Jan Hrabal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
f94ac8fb
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
1939 additions
and
1 deletion
+1939
-1
pom.xml
pom.xml
+0
-1
JhBootApplication.java
src/main/java/com/jh/boot/JhBootApplication.java
+51
-0
AbstractHibernateAttachmentService.java
...h/boot/attachment/AbstractHibernateAttachmentService.java
+57
-0
Attachment.java
src/main/java/com/jh/boot/attachment/Attachment.java
+195
-0
AttachmentRepository.java
...ain/java/com/jh/boot/attachment/AttachmentRepository.java
+101
-0
AttachmentService.java
src/main/java/com/jh/boot/attachment/AttachmentService.java
+111
-0
FileBasedAttachmentService.java
...va/com/jh/boot/attachment/FileBasedAttachmentService.java
+69
-0
AppUserAuthentication.java
...main/java/com/jh/boot/security/AppUserAuthentication.java
+42
-0
AuthError.java
src/main/java/com/jh/boot/security/AuthError.java
+74
-0
AuthService.java
src/main/java/com/jh/boot/security/AuthService.java
+67
-0
AuthServiceAuthenticationProvider.java
...m/jh/boot/security/AuthServiceAuthenticationProvider.java
+56
-0
AuthServiceListener.java
src/main/java/com/jh/boot/security/AuthServiceListener.java
+24
-0
GrantedRole.java
src/main/java/com/jh/boot/security/GrantedRole.java
+21
-0
JhSecurityConfig.java
src/main/java/com/jh/boot/security/JhSecurityConfig.java
+102
-0
PasswordHash.java
src/main/java/com/jh/boot/security/PasswordHash.java
+82
-0
PasswordUtils.java
src/main/java/com/jh/boot/security/PasswordUtils.java
+117
-0
SecurityHelper.java
src/main/java/com/jh/boot/security/SecurityHelper.java
+49
-0
HibernateLoaderTemplateService.java
.../com/jh/boot/template/HibernateLoaderTemplateService.java
+75
-0
HibernateTemplateLoader.java
...in/java/com/jh/boot/template/HibernateTemplateLoader.java
+33
-0
HibernateTemplateRepository.java
...ava/com/jh/boot/template/HibernateTemplateRepository.java
+37
-0
Template.java
src/main/java/com/jh/boot/template/Template.java
+58
-0
TemplateEngine.java
src/main/java/com/jh/boot/template/TemplateEngine.java
+10
-0
TemplateLoader.java
src/main/java/com/jh/boot/template/TemplateLoader.java
+9
-0
TemplateService.java
src/main/java/com/jh/boot/template/TemplateService.java
+10
-0
TemplateValuesConfig.java
src/main/java/com/jh/boot/template/TemplateValuesConfig.java
+20
-0
Converter.java
src/main/java/com/jh/boot/web/Converter.java
+81
-0
FallbackLocaleResolver.java
src/main/java/com/jh/boot/web/FallbackLocaleResolver.java
+185
-0
GlobalControllerExceptionHandler.java
...ava/com/jh/boot/web/GlobalControllerExceptionHandler.java
+23
-0
IdNameDto.java
src/main/java/com/jh/boot/web/IdNameDto.java
+37
-0
JhWebConfig.java
src/main/java/com/jh/boot/web/JhWebConfig.java
+111
-0
LocalDateControllerAdvice.java
src/main/java/com/jh/boot/web/LocalDateControllerAdvice.java
+32
-0
No files found.
pom.xml
View file @
6b52ff0f
...
...
@@ -23,7 +23,6 @@
<maven.compiler.target>
1.8
</maven.compiler.target>
<project.build.date>
${maven.build.timestamp}
</project.build.date>
<java.version>
8
</java.version>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
...
...
src/main/java/com/jh/boot/JhBootApplication.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
;
import
com.jh.boot.template.*
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.context.annotation.Bean
;
import
com.jh.boot.email.LocalEmailService
;
import
com.jh.boot.security.utils.TemplateEmailAuthServiceListener
;
import
com.jh.boot.template.handlebars.HandlebarsTemplateEngine
;
public
class
JhBootApplication
{
@Bean
@ConditionalOnProperty
(
value
=
"email.local.enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
true
)
public
LocalEmailService
emailService
()
{
return
new
LocalEmailService
();
}
@Bean
@ConditionalOnProperty
(
value
=
"auth.listener.email.enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
true
)
public
TemplateEmailAuthServiceListener
authServiceListener
()
{
return
new
TemplateEmailAuthServiceListener
();
}
@Bean
@ConditionalOnMissingBean
(
TemplateEngine
.
class
)
public
TemplateEngine
templateEngine
()
{
return
new
HandlebarsTemplateEngine
();
}
@Bean
@ConditionalOnMissingBean
(
TemplateLoader
.
class
)
public
TemplateLoader
templateLoader
()
{
return
new
HibernateTemplateLoader
();
}
@Bean
@ConditionalOnMissingBean
(
TemplateService
.
class
)
public
TemplateService
templateService
()
{
return
new
HibernateLoaderTemplateService
();
}
@Bean
public
TemplateValuesConfig
templateValuesConfig
()
{
return
new
TemplateValuesConfig
();
}
}
src/main/java/com/jh/boot/attachment/AbstractHibernateAttachmentService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
attachment
;
import
java.io.InputStream
;
import
java.util.List
;
import
org.springframework.beans.factory.annotation.Autowired
;
public
abstract
class
AbstractHibernateAttachmentService
implements
AttachmentService
{
private
AttachmentRepository
repository
;
@Override
public
Attachment
saveAttachment
(
Attachment
attachment
,
InputStream
content
)
{
saveAttachment
(
attachment
);
saveData
(
attachment
,
content
);
return
attachment
;
}
protected
abstract
void
saveData
(
Attachment
attachment
,
InputStream
stream
);
@Override
public
Attachment
saveAttachment
(
Attachment
attachment
)
{
repository
.
save
(
attachment
);
return
attachment
;
}
@Override
public
List
<
Attachment
>
fetchAttachments
(
Long
unitId
,
String
objectType
,
Long
objectId
)
{
return
repository
.
findForUnitIdAndObject
(
unitId
,
objectType
,
objectId
);
}
@Override
public
Attachment
fetchAttachment
(
Long
attachmentId
)
{
return
repository
.
findById
(
attachmentId
);
}
@Override
public
void
deleteAttachment
(
Long
attachmentId
)
{
Attachment
a
=
repository
.
findById
(
attachmentId
);
if
(
a
!=
null
)
{
repository
.
delete
(
a
);
deleteData
(
a
);
}
}
protected
abstract
void
deleteData
(
Attachment
attachment
);
@Autowired
(
required
=
false
)
public
void
setRepository
(
AttachmentRepository
repository
)
{
this
.
repository
=
repository
;
}
}
src/main/java/com/jh/boot/attachment/Attachment.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
attachment
;
import
java.util.Date
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
import
com.jh.boot.jpa.AbstractIdEntity
;
/**
* The Class Attachment.
*/
@Entity
@Table
(
name
=
"ATTACHMENT"
)
public
class
Attachment
extends
AbstractIdEntity
{
/** The unit id. */
@Column
(
name
=
"UNIT_ID"
)
private
Long
unitId
;
/** The object type. */
@Column
(
name
=
"OBJECT_TYPE"
)
private
String
objectType
;
/** The object id. */
@Column
(
name
=
"OBJECT_ID"
)
private
Long
objectId
;
/** The name. */
private
String
name
;
/** The mime type. */
@Column
(
name
=
"MIME_TYPE"
)
private
String
mimeType
;
/** The size. */
@Column
(
name
=
"SIZE"
)
private
Long
size
;
/** The filename. */
@Column
(
name
=
"FILENAME"
)
private
String
filename
;
/** The uploaded. */
@Column
(
name
=
"UPLOADED"
)
private
Date
uploaded
;
/**
* Gets the unit id.
*
* @return the unit id
*/
public
Long
getUnitId
()
{
return
unitId
;
}
/**
* Sets the unit id.
*
* @param unitId the new unit id
*/
public
void
setUnitId
(
Long
unitId
)
{
this
.
unitId
=
unitId
;
}
/**
* Gets the object type.
*
* @return the object type
*/
public
String
getObjectType
()
{
return
objectType
;
}
/**
* Sets the object type.
*
* @param objectType the new object type
*/
public
void
setObjectType
(
String
objectType
)
{
this
.
objectType
=
objectType
;
}
/**
* Gets the object id.
*
* @return the object id
*/
public
Long
getObjectId
()
{
return
objectId
;
}
/**
* Sets the object id.
*
* @param objectId the new object id
*/
public
void
setObjectId
(
Long
objectId
)
{
this
.
objectId
=
objectId
;
}
/**
* Gets the name.
*
* @return the name
*/
public
String
getName
()
{
return
name
;
}
/**
* Sets the name.
*
* @param name the new name
*/
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
/**
* Gets the mime type.
*
* @return the mime type
*/
public
String
getMimeType
()
{
return
mimeType
;
}
/**
* Sets the mime type.
*
* @param mimeType the new mime type
*/
public
void
setMimeType
(
String
mimeType
)
{
this
.
mimeType
=
mimeType
;
}
/**
* Gets the size.
*
* @return the size
*/
public
Long
getSize
()
{
return
size
;
}
/**
* Sets the size.
*
* @param size the new size
*/
public
void
setSize
(
Long
size
)
{
this
.
size
=
size
;
}
/**
* Gets the filename.
*
* @return the filename
*/
public
String
getFilename
()
{
return
filename
;
}
/**
* Sets the filename.
*
* @param filename the new filename
*/
public
void
setFilename
(
String
filename
)
{
this
.
filename
=
filename
;
}
/**
* Gets the uploaded.
*
* @return the uploaded
*/
public
Date
getUploaded
()
{
return
uploaded
;
}
/**
* Sets the uploaded.
*
* @param uploaded the new uploaded
*/
public
void
setUploaded
(
Date
uploaded
)
{
this
.
uploaded
=
uploaded
;
}
}
src/main/java/com/jh/boot/attachment/AttachmentRepository.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
attachment
;
import
java.util.List
;
import
javax.persistence.TypedQuery
;
import
org.springframework.stereotype.Repository
;
import
com.jh.boot.jpa.AbstractHibernateRepository
;
import
com.jh.boot.web.list.Page
;
import
com.jh.boot.web.list.PagingInfo
;
/**
* The Class AttachmentRepository.
*/
@Repository
public
class
AttachmentRepository
extends
AbstractHibernateRepository
{
/**
* Find for unit id and object.
*
* @param unitId the unit id
* @param objectType the object type
* @param objectId the object id
* @param paging the paging
* @return the page
*/
public
Page
<
Attachment
>
findForUnitIdAndObject
(
Long
unitId
,
String
objectType
,
Long
objectId
,
PagingInfo
paging
)
{
TypedQuery
<
Attachment
>
query
=
getListQuery
(
unitId
,
objectType
,
objectId
);
query
.
setFirstResult
(
paging
.
getPage
()
*
paging
.
getPageSize
());
query
.
setMaxResults
(
paging
.
getPageSize
());
//return new Page<>(0, 0, 0, 0, null, objectType, null);
//FIXME
return
Page
.
empty
();
}
/**
* Find for unit id and object.
*
* @param unitId the unit id
* @param objectType the object type
* @param objectId the object id
* @return the list
*/
public
List
<
Attachment
>
findForUnitIdAndObject
(
Long
unitId
,
String
objectType
,
Long
objectId
)
{
TypedQuery
<
Attachment
>
query
=
getListQuery
(
unitId
,
objectType
,
objectId
);
return
query
.
getResultList
();
}
protected
TypedQuery
<
Attachment
>
getListQuery
(
Long
unitId
,
String
objectType
,
Long
objectId
)
{
String
hql
=
"select a from Attachment a"
;
if
(
unitId
!=
null
||
objectType
!=
null
||
objectId
!=
null
)
{
hql
+=
" where "
;
if
(
unitId
!=
null
)
{
hql
+=
" a.unitId = :unitId"
;
}
if
(
objectType
!=
null
)
{
hql
+=
" a.objectType = :objectType"
;
}
if
(
objectId
!=
null
)
{
hql
+=
" a.objectId = :objectId"
;
}
}
TypedQuery
<
Attachment
>
query
=
entityManager
.
createQuery
(
hql
,
Attachment
.
class
);
if
(
unitId
!=
null
)
{
query
.
setParameter
(
"unitId"
,
unitId
);
}
if
(
objectType
!=
null
)
{
query
.
setParameter
(
"objectType"
,
objectType
);
}
if
(
objectId
!=
null
)
{
query
.
setParameter
(
"objectId"
,
objectId
);
}
return
query
;
}
/**
* Rename.
*
* @param unitId the unit id
* @param objectType the object type
* @param objectId the object id
* @param attachmentId the attachment id
* @param name the name
*/
public
void
rename
(
Long
attachmentId
,
String
name
)
{
Attachment
a
=
findById
(
attachmentId
);
a
.
setName
(
name
);
}
public
Attachment
findById
(
Long
id
)
{
return
entityManager
.
find
(
Attachment
.
class
,
id
);
}
}
src/main/java/com/jh/boot/attachment/AttachmentService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
attachment
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
org.springframework.web.multipart.MultipartFile
;
public
interface
AttachmentService
{
Attachment
saveAttachment
(
Attachment
attachment
,
InputStream
content
);
Attachment
saveAttachment
(
Attachment
attachment
);
List
<
Attachment
>
fetchAttachments
(
Long
unitId
,
String
objectType
,
Long
objectId
);
Attachment
fetchAttachment
(
Long
attachmentId
);
InputStream
fetchAttachmentBody
(
Attachment
attachment
);
void
deleteAttachment
(
Long
attachmentId
);
// default methods
public
default
Attachment
addAttachment
(
String
objectType
,
Long
objectId
,
MultipartFile
file
)
{
return
addAttachment
(
null
,
objectType
,
objectId
,
file
);
}
public
default
Attachment
addAttachment
(
Long
unitId
,
String
objectType
,
Long
objectId
,
MultipartFile
file
)
{
Attachment
a
=
new
Attachment
();
a
.
setFilename
(
file
.
getOriginalFilename
());
a
.
setSize
(
file
.
getSize
());
a
.
setObjectId
(
objectId
);
a
.
setObjectType
(
objectType
);
try
{
saveAttachment
(
a
,
file
.
getInputStream
());
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Cannot upload attachment"
,
e
);
}
return
a
;
}
public
default
Attachment
syncAttachment
(
String
objectType
,
Long
objectId
,
Attachment
currentAttachment
,
Attachment
newAttachment
,
MultipartFile
file
)
{
return
syncAttachment
(
null
,
objectType
,
objectId
,
currentAttachment
,
newAttachment
,
file
);
}
public
default
Attachment
syncAttachment
(
Long
unitId
,
String
objectType
,
Long
objectId
,
Attachment
currentAttachment
,
Attachment
newAttachment
,
MultipartFile
file
)
{
Attachment
a
=
null
;
if
(
currentAttachment
!=
null
&&
newAttachment
==
null
)
{
//delete current attachment
deleteAttachment
(
currentAttachment
.
getId
());
}
if
(
file
!=
null
)
{
a
=
addAttachment
(
unitId
,
objectType
,
objectId
,
file
);
}
else
{
a
=
currentAttachment
;
}
return
a
;
}
public
default
<
C
extends
Collection
<
Attachment
>>
C
syncAttachments
(
String
objectType
,
Long
objectId
,
C
currentAttachments
,
C
newAttachments
,
MultipartFile
[]
files
,
Class
<
C
>
clazz
)
{
return
syncAttachments
(
null
,
objectType
,
objectId
,
currentAttachments
,
newAttachments
,
files
,
clazz
);
}
public
default
<
C
extends
Collection
<
Attachment
>>
C
syncAttachments
(
Long
unitId
,
String
objectType
,
Long
objectId
,
C
currentAttachments
,
C
newAttachments
,
MultipartFile
[]
files
,
Class
<
C
>
clazz
)
{
//decide whether Set or List
if
(
currentAttachments
==
null
)
{
if
(
Set
.
class
.
isAssignableFrom
(
clazz
))
{
currentAttachments
=
(
C
)
new
HashSet
<
Attachment
>();
}
else
if
(
List
.
class
.
isAssignableFrom
(
clazz
))
{
currentAttachments
=
(
C
)
new
ArrayList
<
Attachment
>();
}
else
{
throw
new
IllegalArgumentException
(
"Invalid collection type"
);
}
}
if
(
newAttachments
==
null
||
newAttachments
.
isEmpty
())
{
currentAttachments
.
clear
();
}
else
{
Iterator
<
Attachment
>
it
=
currentAttachments
.
iterator
();
while
(
it
.
hasNext
())
{
Attachment
a
=
it
.
next
();
if
(!
newAttachments
.
contains
(
a
))
{
it
.
remove
();
}
}
}
//TODO add attachments?
if
(
files
!=
null
&&
files
.
length
>
0
)
{
for
(
MultipartFile
f
:
files
)
{
currentAttachments
.
add
(
addAttachment
(
unitId
,
objectType
,
objectId
,
f
));
}
}
return
currentAttachments
;
}
}
src/main/java/com/jh/boot/attachment/FileBasedAttachmentService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
attachment
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.InputStream
;
import
java.nio.file.Paths
;
import
java.util.Objects
;
import
org.apache.tomcat.util.http.fileupload.IOUtils
;
import
org.springframework.beans.factory.annotation.Value
;
public
class
FileBasedAttachmentService
extends
AbstractHibernateAttachmentService
{
private
String
dataDirectory
;
@Override
public
InputStream
fetchAttachmentBody
(
Attachment
attachment
)
{
try
{
return
new
FileInputStream
(
file
(
attachment
));
}
catch
(
FileNotFoundException
e
)
{
throw
new
RuntimeException
(
"File not found"
,
e
);
}
}
@Override
protected
void
saveData
(
Attachment
attachment
,
InputStream
stream
)
{
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
file
(
attachment
)))
{
IOUtils
.
copy
(
stream
,
fos
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Cannot write data"
,
e
);
}
}
@Override
protected
void
deleteData
(
Attachment
attachment
)
{
File
file
=
file
(
attachment
);
if
(
file
.
exists
())
{
file
.
delete
();
file
=
file
.
getParentFile
();
if
(
file
.
listFiles
().
length
==
0
)
{
//delete ?
file
.
delete
();
}
}
}
protected
File
file
(
Attachment
attachment
)
{
Objects
.
requireNonNull
(
attachment
,
"Attachment must not be null"
);
File
file
=
Paths
.
get
(
dataDirectory
,
s
(
attachment
.
getUnitId
()),
attachment
.
getObjectType
(),
s
(
attachment
.
getObjectId
()),
attachment
.
getFilename
()).
toFile
();
file
.
getParentFile
().
mkdirs
();
return
file
;
}
protected
String
s
(
Number
n
)
{
return
n
==
null
?
"0"
:
String
.
valueOf
(
n
);
}
@Value
(
"${attachment.store.path:/var/data}"
)
public
void
setDataDirectory
(
String
dataDirectory
)
{
this
.
dataDirectory
=
dataDirectory
;
}
}
src/main/java/com/jh/boot/security/AppUserAuthentication.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
java.util.Collection
;
import
org.springframework.security.authentication.AbstractAuthenticationToken
;
import
org.springframework.security.core.GrantedAuthority
;
import
com.jh.boot.security.model.AppUser
;
public
class
AppUserAuthentication
extends
AbstractAuthenticationToken
{
private
static
final
long
serialVersionUID
=
1L
;
private
AppUser
user
;
public
AppUserAuthentication
(
AppUser
user
,
Collection
<?
extends
GrantedAuthority
>
authorities
)
{
super
(
authorities
);
this
.
user
=
user
;
}
@Override
public
Object
getCredentials
()
{
return
null
;
}
@Override
public
Object
getPrincipal
()
{
return
user
;
}
public
AppUser
getUser
()
{
return
user
;
}
@Override
public
boolean
isAuthenticated
()
{
return
true
;
}
}
src/main/java/com/jh/boot/security/AuthError.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
/**
* The Class AuthError.
*/
public
class
AuthError
{
/** The Constant USERNAME_FIELD. */
public
static
final
String
USERNAME_FIELD
=
"username"
;
/** The Constant PASSWORD_FIELD. */
public
static
final
String
PASSWORD_FIELD
=
"password"
;
/** The field. */
String
field
;
/** The code. */
String
code
;
/**
* Instantiates a new auth error.
*
* @param field the field
* @param error the error
*/
public
AuthError
(
String
field
,
String
error
)
{
super
();
this
.
field
=
field
;
this
.
code
=
error
;
}
/**
* Gets the field.
*
* @return the field
*/
public
String
getField
()
{
return
field
;
}
/**
* Gets the code.
*
* @return the code
*/
public
String
getCode
()
{
return
code
;
}
/**
* Username error.
*
* @param error the error
* @return the auth error
*/
public
static
AuthError
usernameError
(
String
error
)
{
return
new
AuthError
(
USERNAME_FIELD
,
error
);
}
/**
* Password error.
*
* @param error the error
* @return the auth error
*/
public
static
AuthError
passwordError
(
String
error
)
{
return
new
AuthError
(
PASSWORD_FIELD
,
error
);
}
}
src/main/java/com/jh/boot/security/AuthService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
java.util.Locale
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
com.jh.boot.security.model.AppUser
;
/**
* TODO.
*
* @author jh
*/
public
interface
AuthService
{
/**
* Authenticate.
*
* @param username the username
* @param password the password
* @return the authentication
* @throws BadCredentialsException the bad credentials exception
*/
Authentication
authenticate
(
String
username
,
String
password
)
throws
BadCredentialsException
;
/**
* Register.
* @param signup the signup
* @param email
* @param locale TODO
*/
void
register
(
String
login
,
String
email
,
String
password
,
Locale
locale
)
throws
AuthenticationException
;
/**
* This method is responsible for creating new reset password request
* for provided login (or should do nothing if the login is unknown).
*
* <p>The way of letting the user know the token is up to the implementation</p>
*
* @param login
*/
String
generateResetToken
(
String
login
);
/**
* TODO
* @param resetPassword
* @throws AuthenticationException TODO
*/
void
resetPassword
(
String
login
,
String
token
,
String
newPassword
)
throws
AuthenticationException
;
void
changePassword
(
String
login
,
String
currentPassword
,
String
newPassword
)
throws
AuthenticationException
;
/**
* TODO
*
* @param login
*/
void
delete
(
AppUser
login
);
}
src/main/java/com/jh/boot/security/AuthServiceAuthenticationProvider.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.authentication.AuthenticationProvider
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
/**
* The Class UserAuthenticationProvider.
*/
//TODO
public
class
AuthServiceAuthenticationProvider
implements
AuthenticationProvider
{
/** The auth service. */
private
AuthService
authService
;
/**
* Authenticate.
*
* @param authentication the authentication
* @return the authentication
* @throws AuthenticationException the authentication exception
* @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication)
*/
@Override
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
String
email
=
String
.
valueOf
(
authentication
.
getPrincipal
());
String
password
=
String
.
valueOf
(
authentication
.
getCredentials
());
//TODO refactor
return
authService
.
authenticate
(
email
,
password
);
}
/**
* Supports.
*
* @param authentication the authentication
* @return true, if successful
* @see org.springframework.security.authentication.AuthenticationProvider#supports(java.lang.Class)
*/
@Override
public
boolean
supports
(
Class
<?>
authentication
)
{
return
true
;
}
@Autowired
public
void
setAuthService
(
AuthService
authService
)
{
this
.
authService
=
authService
;
}
}
src/main/java/com/jh/boot/security/AuthServiceListener.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
com.jh.boot.security.model.AppUser
;
import
com.jh.boot.security.model.ResetPasswordToken
;
public
interface
AuthServiceListener
{
default
void
registerUser
(
AppUser
user
,
String
password
)
{
}
default
void
initializeUser
(
AppUser
user
)
{
}
default
void
generateResetToken
(
AppUser
user
,
ResetPasswordToken
token
)
{
}
default
void
deleteUser
(
AppUser
user
)
{
}
}
src/main/java/com/jh/boot/security/GrantedRole.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
org.springframework.security.core.GrantedAuthority
;
public
class
GrantedRole
implements
GrantedAuthority
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
role
;
public
GrantedRole
(
String
role
)
{
super
();
this
.
role
=
role
;
}
@Override
public
String
getAuthority
()
{
return
role
;
}
}
src/main/java/com/jh/boot/security/JhSecurityConfig.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
java.io.IOException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.security.authentication.AuthenticationProvider
;
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
;
import
org.springframework.security.config.http.SessionCreationPolicy
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.web.AuthenticationEntryPoint
;
import
com.jh.boot.security.repository.AppUserRepository
;
import
com.jh.boot.security.service.AppUserAuthService
;
/**
* The Class ReactApplicationSecurityContext.
*/
public
class
JhSecurityConfig
extends
WebSecurityConfigurerAdapter
{
/**
* @param http
* @throws Exception
* @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
*/
@Override
protected
void
configure
(
HttpSecurity
http
)
throws
Exception
{
HttpSecurity
cfg
=
http
.
authorizeRequests
()
.
antMatchers
(
"/auth/**"
).
permitAll
()
.
anyRequest
().
authenticated
()
.
and
()
.
logout
()
.
clearAuthentication
(
true
)
.
permitAll
()
.
and
();
cfg
.
httpBasic
();
http
.
csrf
().
disable
();
http
.
exceptionHandling
().
authenticationEntryPoint
(
authenticationEntryPoint
());
http
.
headers
().
frameOptions
().
disable
();
http
.
sessionManagement
().
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
);
}
/**
* @param auth
* @throws Exception
* @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder)
*/
@Override
protected
void
configure
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
.
authenticationProvider
(
authenticationProvider
());
}
/**
* Override this method to provide custom {@link AuthenticationEntryPoint}.
*
* It returns {@link RestAuthenticationEntryPoint} by default
*
* @return the authentication entry point
*/
protected
AuthenticationEntryPoint
authenticationEntryPoint
()
{
return
new
AuthenticationEntryPoint
()
{
@Override
public
final
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
authException
)
throws
IOException
{
response
.
sendError
(
HttpServletResponse
.
SC_UNAUTHORIZED
,
"Unauthorized"
);
}
};
}
@Bean
public
AuthenticationProvider
authenticationProvider
()
{
return
new
AuthServiceAuthenticationProvider
();
}
@Bean
public
AuthService
authService
()
{
AppUserAuthService
appUserAuthService
=
new
AppUserAuthService
();
appUserAuthService
.
setAppUserRepository
(
appUserRepository
());
return
appUserAuthService
;
}
@Bean
public
AppUserRepository
appUserRepository
()
{
return
new
AppUserRepository
();
}
// @Bean
// public GrantedAuthorityDefaults grantedAuthorityDefaults() {
// return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
// }
}
src/main/java/com/jh/boot/security/PasswordHash.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
/**
* The Class PasswordHash.
*/
public
class
PasswordHash
{
/** The hash. */
private
String
hash
;
/** The salt. */
private
String
salt
;
/** The iterations. */
private
int
iterations
;
/**
* Instantiates a new password hash.
*
* @param hash the hash
* @param salt the salt
*/
public
PasswordHash
(
String
hash
,
String
salt
)
{
this
(
hash
,
salt
,
1
);
}
/**
* Instantiates a new password hash.
*
* @param hash the hash
* @param salt the salt
* @param iterations the iterations
*/
public
PasswordHash
(
String
hash
,
String
salt
,
int
iterations
)
{
super
();
this
.
hash
=
hash
;
this
.
salt
=
salt
;
this
.
iterations
=
iterations
;
}
/**
* Gets the hash.
*
* @return the hash
*/
public
String
getHash
()
{
return
hash
;
}
/**
* Gets the salt.
*
* @return the salt
*/
public
String
getSalt
()
{
return
salt
;
}
/**
* Gets the iterations.
*
* @return the iterations
*/
public
int
getIterations
()
{
return
iterations
;
}
/**
* @return
* @see java.lang.Object#toString()
*/
@Override
public
String
toString
()
{
return
"PasswordHash [hash="
+
hash
+
", salt="
+
salt
+
", iterations="
+
iterations
+
"]"
;
}
}
src/main/java/com/jh/boot/security/PasswordUtils.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.SecureRandom
;
import
java.security.spec.InvalidKeySpecException
;
import
java.util.Base64
;
import
java.util.Base64.Decoder
;
import
java.util.Base64.Encoder
;
import
javax.crypto.SecretKeyFactory
;
import
javax.crypto.spec.PBEKeySpec
;
import
org.springframework.util.StringUtils
;
/**
* The Class PasswordSecurity.
*/
public
abstract
class
PasswordUtils
{
/** The Constant ITERATIONS. */
private
static
final
int
ITERATIONS
=
1
;
/** The b 64 encoder. */
private
static
Encoder
b64Encoder
=
Base64
.
getEncoder
();
/** The b 64 decoder. */
private
static
Decoder
b64Decoder
=
Base64
.
getDecoder
();
/**
* Hash password.
*
* @param password the password
* @return the password hash
*/
public
static
PasswordHash
hashPassword
(
String
password
)
{
try
{
byte
[]
salt
=
getSalt
();
String
hash
=
createHash
(
password
,
salt
);
String
salt64
=
new
String
(
b64Encoder
.
encode
(
salt
));
return
new
PasswordHash
(
hash
,
salt64
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
/**
* Check password.
*
* @param password the password
* @param storedHash the stored hash
* @param storedSalt the stored salt
* @return true, if successful
*/
public
static
boolean
checkPassword
(
String
password
,
String
storedHash
,
String
storedSalt
)
{
if
(
password
==
null
||
storedSalt
==
null
||
storedHash
==
null
)
{
return
false
;
}
byte
[]
salt
=
b64Decoder
.
decode
(
storedSalt
);
try
{
String
hash
=
createHash
(
password
,
salt
);
return
hash
.
equals
(
storedHash
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
/**
* Validate password.
*
* @param password the password
* @return true, if successful
*/
public
static
boolean
validatePassword
(
String
password
)
{
return
StringUtils
.
hasText
(
password
);
}
/**
* Creates the hash.
*
* @param password the password
* @param salt the salt
* @return the string
* @throws NoSuchAlgorithmException the no such algorithm exception
* @throws InvalidKeySpecException the invalid key spec exception
*/
protected
static
String
createHash
(
String
password
,
byte
[]
salt
)
throws
NoSuchAlgorithmException
,
InvalidKeySpecException
{
PBEKeySpec
spec
=
new
PBEKeySpec
(
password
.
toCharArray
(),
salt
,
ITERATIONS
,
2048
);
SecretKeyFactory
factory
=
SecretKeyFactory
.
getInstance
(
"PBKDF2WithHmacSHA512"
);
String
hash
=
new
String
(
b64Encoder
.
encode
(
factory
.
generateSecret
(
spec
).
getEncoded
()));
spec
.
clearPassword
();
return
hash
;
}
/**
* Gets the salt.
*
* @return the salt
* @throws NoSuchAlgorithmException the no such algorithm exception
*/
private
static
byte
[]
getSalt
()
throws
NoSuchAlgorithmException
{
//Always use a SecureRandom generator
SecureRandom
sr
=
SecureRandom
.
getInstance
(
"SHA1PRNG"
);
//Create array for salt
byte
[]
salt
=
new
byte
[
128
];
//Get a random salt
sr
.
nextBytes
(
salt
);
//return salt
return
salt
;
}
}
src/main/java/com/jh/boot/security/SecurityHelper.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
security
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
com.jh.boot.security.model.AppUser
;
public
class
SecurityHelper
{
private
SecurityHelper
()
{
}
public
static
AppUser
getUser
()
{
return
(
AppUser
)
SecurityContextHolder
.
getContext
().
getAuthentication
().
getPrincipal
();
}
public
static
AppUser
getUser
(
Authentication
auth
)
{
if
(
auth
==
null
)
{
return
null
;
}
return
(
AppUser
)
auth
.
getPrincipal
();
}
public
static
boolean
hasAnyRole
(
Authentication
auth
,
String
...
roles
)
{
AppUser
user
=
auth
instanceof
AppUserAuthentication
?
((
AppUserAuthentication
)
auth
).
getUser
()
:
null
;
return
hasAnyRole
(
user
,
roles
);
}
public
static
boolean
hasAnyRole
(
AppUser
user
,
String
...
roles
)
{
if
(
user
==
null
||
user
.
getRolesMap
()
==
null
||
roles
==
null
||
roles
.
length
==
0
)
{
return
false
;
}
for
(
String
role
:
roles
)
{
if
(
user
.
getRolesMap
().
containsKey
(
role
))
{
return
true
;
}
}
return
false
;
}
}
src/main/java/com/jh/boot/template/HibernateLoaderTemplateService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.io.StringWriter
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.Map
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
public
class
HibernateLoaderTemplateService
implements
TemplateService
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
HibernateLoaderTemplateService
.
class
);
private
TemplateLoader
loader
;
private
TemplateEngine
engine
;
private
TemplateValuesConfig
valuesConfig
;
@Override
@Transactional
public
String
evaluate
(
String
templateCode
,
Map
<
String
,
Object
>
data
,
Locale
locale
)
{
Template
t
=
loader
.
loadTemplate
(
templateCode
,
locale
);
if
(
t
==
null
)
{
LOG
.
warn
(
"Cannot find template {}"
,
templateCode
);
return
null
;
}
Map
<
String
,
Object
>
values
=
new
HashMap
<
String
,
Object
>();
if
(
valuesConfig
!=
null
)
{
values
.
putAll
(
valuesConfig
.
getValues
());
}
if
(
data
!=
null
)
{
values
.
putAll
(
data
);
}
String
content
=
t
.
getTemplate
();
StringWriter
sw
=
new
StringWriter
();
engine
.
evaluate
(
sw
,
content
,
values
);
content
=
sw
.
toString
();
if
(
t
.
getLayoutCode
()
!=
null
)
{
t
=
loader
.
loadTemplate
(
t
.
getLayoutCode
(),
locale
);
if
(
t
!=
null
)
{
values
.
put
(
"__layout_content__"
,
content
);
}
sw
=
new
StringWriter
();
engine
.
evaluate
(
sw
,
t
.
getTemplate
(),
values
);
content
=
sw
.
toString
();
}
return
content
;
}
@Autowired
public
void
setLoader
(
TemplateLoader
loader
)
{
this
.
loader
=
loader
;
}
@Autowired
public
void
setEngine
(
TemplateEngine
engine
)
{
this
.
engine
=
engine
;
}
@Autowired
public
void
setValuesConfig
(
TemplateValuesConfig
valuesConfig
)
{
this
.
valuesConfig
=
valuesConfig
;
}
}
src/main/java/com/jh/boot/template/HibernateTemplateLoader.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.util.Locale
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
public
class
HibernateTemplateLoader
implements
TemplateLoader
{
@Autowired
private
HibernateTemplateRepository
repository
;
@Override
@Transactional
public
Template
loadTemplate
(
String
code
,
Locale
locale
)
{
Template
t
=
null
;
if
(
locale
!=
null
)
{
if
(
StringUtils
.
hasText
(
locale
.
getCountry
()))
{
t
=
repository
.
loadTemplate
(
code
,
locale
.
getLanguage
()
+
"-"
+
locale
.
getCountry
());
}
if
(
t
==
null
)
{
t
=
repository
.
loadTemplate
(
code
,
locale
.
getLanguage
());
}
}
if
(
t
==
null
)
{
t
=
repository
.
loadTemplate
(
code
,
null
);
}
return
t
;
}
}
src/main/java/com/jh/boot/template/HibernateTemplateRepository.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.util.List
;
import
javax.persistence.TypedQuery
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.util.StringUtils
;
import
com.jh.boot.jpa.AbstractHibernateRepository
;
@Repository
public
class
HibernateTemplateRepository
extends
AbstractHibernateRepository
{
public
Template
loadTemplate
(
String
code
,
String
locale
)
{
if
(
code
==
null
)
{
return
null
;
}
String
hql
=
"select t from Template t where lower(code) = :code"
;
if
(
StringUtils
.
hasText
(
locale
))
{
hql
+=
" and lower(locale) = :locale"
;
}
else
{
hql
+=
" and locale is null"
;
}
TypedQuery
<
Template
>
q
=
entityManager
.
createQuery
(
hql
,
Template
.
class
);
q
.
setParameter
(
"code"
,
code
.
toLowerCase
());
if
(
StringUtils
.
hasText
(
locale
))
{
q
.
setParameter
(
"locale"
,
locale
.
toLowerCase
());
}
List
<
Template
>
list
=
q
.
getResultList
();
return
list
==
null
||
list
.
isEmpty
()
?
null
:
list
.
get
(
0
);
}
}
src/main/java/com/jh/boot/template/Template.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
import
com.jh.boot.jpa.AbstractIdEntity
;
@Entity
@Table
(
name
=
"TEMPLATE"
)
public
class
Template
extends
AbstractIdEntity
{
@Column
(
name
=
"CODE"
)
private
String
code
;
@Column
(
name
=
"LAYOUT_CODE"
)
private
String
layoutCode
;
@Column
(
name
=
"TEMPLATE"
)
private
String
template
;
@Column
(
name
=
"LOCALE"
)
private
String
locale
;
public
Template
()
{
super
();
}
public
Template
(
Long
templateId
)
{
super
();
setId
(
templateId
);
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getLayoutCode
()
{
return
layoutCode
;
}
public
void
setLayoutCode
(
String
name
)
{
this
.
layoutCode
=
name
;
}
public
String
getTemplate
()
{
return
template
;
}
public
void
setTemplate
(
String
template
)
{
this
.
template
=
template
;
}
}
src/main/java/com/jh/boot/template/TemplateEngine.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.io.Writer
;
import
java.util.Map
;
public
interface
TemplateEngine
{
void
evaluate
(
Writer
writer
,
String
templateContent
,
Map
<
String
,
Object
>
data
);
}
\ No newline at end of file
src/main/java/com/jh/boot/template/TemplateLoader.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.util.Locale
;
public
interface
TemplateLoader
{
Template
loadTemplate
(
String
code
,
Locale
locale
);
}
src/main/java/com/jh/boot/template/TemplateService.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.util.Locale
;
import
java.util.Map
;
public
interface
TemplateService
{
String
evaluate
(
String
templateCode
,
Map
<
String
,
Object
>
data
,
Locale
locale
);
}
src/main/java/com/jh/boot/template/TemplateValuesConfig.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
template
;
import
java.util.Map
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
@ConfigurationProperties
(
prefix
=
"template"
)
public
class
TemplateValuesConfig
{
private
Map
<
String
,
String
>
values
;
public
Map
<
String
,
String
>
getValues
()
{
return
values
;
}
public
void
setValues
(
Map
<
String
,
String
>
values
)
{
this
.
values
=
values
;
}
}
src/main/java/com/jh/boot/web/Converter.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
web
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
com.jh.boot.jpa.AbstractIdEntity
;
import
com.jh.boot.web.list.Page
;
import
com.jh.boot.web.list.SortTrend
;
public
class
Converter
{
private
Converter
()
{}
public
static
<
S
,
D
>
D
convert
(
S
source
,
Function
<
S
,
D
>
mappingFunction
)
{
if
(
source
==
null
||
mappingFunction
==
null
)
{
return
null
;
}
return
mappingFunction
.
apply
(
source
);
}
public
static
<
S
,
D
>
Set
<
D
>
convertSet
(
Collection
<
S
>
list
,
Function
<
S
,
D
>
mappingFunction
)
{
if
(
list
==
null
)
{
return
null
;
}
return
list
.
stream
().
map
(
mappingFunction
).
collect
(
Collectors
.
toSet
());
}
public
static
<
S
,
D
>
List
<
D
>
convertList
(
Collection
<
S
>
list
,
Function
<
S
,
D
>
mappingFunction
)
{
if
(
list
==
null
)
{
return
null
;
}
return
list
.
stream
().
map
(
mappingFunction
).
collect
(
Collectors
.
toList
());
}
public
static
<
S
,
D
>
Page
<
D
>
convertPage
(
Page
<
S
>
page
,
Function
<
S
,
D
>
mappingFunction
)
{
if
(
page
==
null
||
mappingFunction
==
null
)
{
return
null
;
}
List
<
D
>
content
=
new
ArrayList
<>();
if
(
page
.
getContent
()
!=
null
)
{
for
(
S
s
:
page
.
getContent
())
{
content
.
add
(
mappingFunction
.
apply
(
s
));
}
}
return
new
Page
<
D
>(
page
.
getPage
(),
page
.
getPagesCount
(),
page
.
getPageSize
(),
page
.
getTotalElements
(),
content
,
page
.
getSortBy
(),
SortTrend
.
parse
(
page
.
getTrend
()));
}
public
static
<
T
>
List
<
IdNameDto
>
mapToDtos
(
Collection
<
T
>
collection
,
Function
<
T
,
Long
>
getId
,
Function
<
T
,
String
>
getName
)
{
if
(
collection
==
null
||
collection
.
isEmpty
()
||
getId
==
null
||
getName
==
null
)
{
return
Collections
.
emptyList
();
}
List
<
IdNameDto
>
result
=
new
ArrayList
<
IdNameDto
>();
for
(
T
t
:
collection
)
{
result
.
add
(
new
IdNameDto
(
getId
.
apply
(
t
),
getName
.
apply
(
t
)));
}
return
result
;
}
//public static <T> T toEntity(IdNameDto )
/**
* Helper function to safely get id
*
* @param entity
* @return
*/
public
static
Long
getId
(
AbstractIdEntity
entity
)
{
return
entity
==
null
?
null
:
entity
.
getId
();
}
}
src/main/java/com/jh/boot/web/FallbackLocaleResolver.java
0 → 100644
View file @
6b52ff0f
/*
* Created on 29. 1. 2018 13:40:45
*
*/
package
com
.
jh
.
boot
.
web
;
import
java.util.LinkedHashSet
;
import
java.util.Locale
;
import
java.util.Set
;
import
javax.annotation.PostConstruct
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
;
import
org.springframework.web.util.WebUtils
;
/**
* The Class FallbackLocaleResolver.
*
* @author Jan Hrabal
*/
public
class
FallbackLocaleResolver
extends
AcceptHeaderLocaleResolver
/* LocaleResolver*/
{
/** The locales string. */
@Value
(
"${app.locales:en}"
)
private
String
localesString
;
/** The default locale. */
@Value
(
"${app.locale.default:en}"
)
private
String
defaultLocale
;
/** The default country. */
@Value
(
"${app.locale.defaultCountry:US}"
)
private
String
defaultCountry
;
/** The locales. */
private
Set
<
String
>
locales
;
/**
* Inits the.
*/
@PostConstruct
public
void
init
()
{
locales
=
new
LinkedHashSet
<>();
if
(
localesString
!=
null
)
{
String
[]
ls
=
localesString
.
split
(
"[\\s,;]"
);
for
(
String
s
:
ls
)
{
if
(
StringUtils
.
hasText
(
s
))
{
locales
.
add
(
s
.
trim
().
toLowerCase
());
}
}
}
else
{
locales
.
add
(
"en"
);
//TODO default config?
}
if
(
defaultLocale
==
null
)
{
defaultLocale
=
"en"
;
}
else
{
defaultLocale
=
defaultLocale
.
trim
().
toLowerCase
();
}
}
/**
* Resolve locale.
*
* @param httpRequest the http request
* @return the locale
* @see org.springframework.web.servlet.LocaleResolver#resolveLocale(javax.servlet.http.HttpServletRequest)
*/
@Override
public
Locale
resolveLocale
(
HttpServletRequest
httpRequest
)
{
String
code
=
null
;
//get param
String
lang
=
httpRequest
.
getParameter
(
"lang"
);
if
(
StringUtils
.
hasText
(
lang
))
{
if
(
locales
.
contains
(
langCode
(
lang
)))
{
code
=
lang
;
}
}
Cookie
c
=
WebUtils
.
getCookie
(
httpRequest
,
"lang"
);
if
(
c
!=
null
)
{
lang
=
c
.
getValue
();
if
(
StringUtils
.
hasText
(
lang
))
{
if
(
locales
.
contains
(
langCode
(
lang
)))
{
code
=
lang
;
}
}
}
if
(
code
==
null
)
{
String
acceptLanguage
=
httpRequest
.
getHeader
(
"Accept-Language"
);
if
(
StringUtils
.
hasText
(
acceptLanguage
))
{
String
[]
als
=
acceptLanguage
.
split
(
","
);
for
(
String
s
:
als
)
{
if
(
locales
.
contains
(
langCode
(
s
)))
{
code
=
s
;
break
;
}
}
}
}
String
country
=
null
;
if
(
code
==
null
)
{
code
=
defaultLocale
;
country
=
defaultCountry
;
}
else
{
country
=
countryCode
(
code
);
code
=
langCode
(
code
);
}
return
country
==
null
?
new
Locale
(
code
)
:
new
Locale
(
code
,
country
);
}
/**
* Sets the locale.
*
* @param arg0 the arg 0
* @param arg1 the arg 1
* @param arg2 the arg 2
* @see org.springframework.web.servlet.LocaleResolver#setLocale(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.util.Locale)
*/
@Override
public
void
setLocale
(
HttpServletRequest
arg0
,
HttpServletResponse
arg1
,
Locale
arg2
)
{
// TODO do nothing
}
/**
* Lang code.
*
* @param s the s
* @return the string
*/
protected
String
langCode
(
String
s
)
{
if
(
s
==
null
)
{
return
defaultLocale
;
}
s
=
s
.
trim
().
toLowerCase
();
if
(
s
.
length
()
>
2
)
{
return
s
.
substring
(
0
,
2
);
}
return
s
;
}
/**
* Lang name.
*
* @param s the s
* @return the string
*/
protected
String
langName
(
String
s
)
{
if
(
s
==
null
)
{
return
defaultLocale
;
}
return
s
.
trim
().
replace
(
"-"
,
"_"
);
}
/**
* Country code.
*
* @param s the s
* @return the string
*/
protected
String
countryCode
(
String
s
)
{
if
(
s
==
null
||
s
.
length
()
<
5
)
{
return
null
;
}
return
s
.
substring
(
3
);
}
}
src/main/java/com/jh/boot/web/GlobalControllerExceptionHandler.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
web
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException
;
import
org.springframework.web.bind.annotation.ControllerAdvice
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
/**
* The Class GlobalControllerExceptionHandler.
*/
@ControllerAdvice
class
GlobalControllerExceptionHandler
{
/**
* Handle conflict.
*/
@ResponseStatus
(
HttpStatus
.
CONFLICT
)
@ExceptionHandler
(
HibernateOptimisticLockingFailureException
.
class
)
public
void
handleConflict
()
{
}
}
\ No newline at end of file
src/main/java/com/jh/boot/web/IdNameDto.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
web
;
public
class
IdNameDto
{
private
Long
id
;
private
String
name
;
public
IdNameDto
()
{
}
public
IdNameDto
(
Long
id
,
String
name
)
{
super
();
this
.
id
=
id
;
this
.
name
=
name
;
}
public
Long
getId
()
{
return
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
}
src/main/java/com/jh/boot/web/JhWebConfig.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
web
;
import
java.util.List
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
import
org.springframework.web.servlet.LocaleResolver
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.PathMatchConfigurer
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
import
org.springframework.web.servlet.i18n.LocaleChangeInterceptor
;
import
com.fasterxml.jackson.annotation.JsonInclude.Include
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.SerializationFeature
;
import
com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module
;
import
com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module.Feature
;
import
com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
;
import
com.jh.boot.web.list.PagingArgumentResolver
;
import
com.jh.boot.web.list.SortingArgumentResolver
;
public
class
JhWebConfig
implements
WebMvcConfigurer
{
/**
* @param converters
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configureMessageConverters(java.util.List)
*/
@Override
public
void
configureMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
final
MappingJackson2HttpMessageConverter
converter
=
new
MappingJackson2HttpMessageConverter
();
converter
.
setObjectMapper
(
objectMapper
());
converters
.
add
(
converter
);
}
/**
* Object mapper.
*
* @return the object mapper
*/
@Bean
public
ObjectMapper
objectMapper
()
{
ObjectMapper
om
=
new
ObjectMapper
();
om
.
setSerializationInclusion
(
Include
.
NON_NULL
);
om
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
om
.
disable
(
SerializationFeature
.
WRITE_DATES_AS_TIMESTAMPS
);
om
.
registerModule
(
new
JavaTimeModule
());
Hibernate5Module
module
=
new
Hibernate5Module
();
module
.
disable
(
Feature
.
USE_TRANSIENT_ANNOTATION
);
module
.
enable
(
Feature
.
REPLACE_PERSISTENT_COLLECTIONS
);
om
.
registerModule
(
module
);
return
om
;
}
/**
* @param argumentResolvers
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addArgumentResolvers(java.util.List)
*/
@Override
public
void
addArgumentResolvers
(
List
<
HandlerMethodArgumentResolver
>
argumentResolvers
)
{
argumentResolvers
.
add
(
new
PagingArgumentResolver
());
argumentResolvers
.
add
(
new
SortingArgumentResolver
());
}
/**
* Locale resolver.
*
* @return the locale resolver
*/
@Bean
@Primary
public
LocaleResolver
localeResolver
()
{
return
new
FallbackLocaleResolver
();
}
@Bean
public
LocaleChangeInterceptor
localeChangeInterceptor
()
{
LocaleChangeInterceptor
lci
=
new
LocaleChangeInterceptor
();
lci
.
setParamName
(
"lang"
);
return
lci
;
}
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
registry
.
addInterceptor
(
localeChangeInterceptor
());
}
/**
* @param configurer
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configurePathMatch(org.springframework.web.servlet.config.annotation.PathMatchConfigurer)
*/
@Override
public
void
configurePathMatch
(
PathMatchConfigurer
configurer
)
{
configurer
.
setUseSuffixPatternMatch
(
false
);
// .setUseTrailingSlashMatch(false)
// .setUseRegisteredSuffixPatternMatch(true)
// .setPathMatcher(antPathMatcher())
// .setUrlPathHelper(urlPathHelper());
}
}
src/main/java/com/jh/boot/web/LocalDateControllerAdvice.java
0 → 100644
View file @
6b52ff0f
package
com
.
jh
.
boot
.
web
;
import
java.beans.PropertyEditorSupport
;
import
java.time.LocalDate
;
import
java.time.format.DateTimeFormatter
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.annotation.ControllerAdvice
;
import
org.springframework.web.bind.annotation.InitBinder
;
/**
* The Class LocalDateControllerAdvice.
*/
@ControllerAdvice
public
class
LocalDateControllerAdvice
{
/**
* Inits the binder.
*
* @param binder the binder
*/
@InitBinder
public
void
initBinder
(
WebDataBinder
binder
)
{
binder
.
registerCustomEditor
(
LocalDate
.
class
,
new
PropertyEditorSupport
()
{
@Override
public
void
setAsText
(
String
text
)
throws
IllegalArgumentException
{
setValue
(
LocalDate
.
parse
(
text
,
DateTimeFormatter
.
ISO_DATE
));
}
});
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment