211107 메인 화면 와이어프레임, 목업 개발
This commit is contained in:
@@ -2,8 +2,10 @@ package myblog.blog;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableJpaAuditing
|
||||
public class BlogApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package myblog.blog.article.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class ArticleController {
|
||||
|
||||
|
||||
}
|
||||
33
src/main/java/myblog/blog/article/domain/Article.java
Normal file
33
src/main/java/myblog/blog/article/domain/Article.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package myblog.blog.article.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import myblog.blog.member.doamin.Member;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@SequenceGenerator(
|
||||
name = "article_seq_generator",
|
||||
sequenceName = "article_seq",
|
||||
initialValue = 1, allocationSize = 50)
|
||||
public class Article {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "article_generator")
|
||||
@Column(name = "article_id")
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
@Column(nullable = false)
|
||||
private String content;
|
||||
private Long hit;
|
||||
private String toc;
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "member_id")
|
||||
private Member member;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package myblog.blog.article.repository;
|
||||
|
||||
import myblog.blog.article.domain.Article;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
public interface ArticleRepository extends JpaRepository<Article, Long> {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package myblog.blog.article.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.article.repository.ArticleRepository;
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleService {
|
||||
|
||||
private final ArticleRepository articleRepository;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public Long writeArticle(NewArticleDto newArticleDto){
|
||||
|
||||
Article article = modelMapper.map(newArticleDto, Article.class);
|
||||
|
||||
articleRepository.save(article);
|
||||
|
||||
return article.getId();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
18
src/main/java/myblog/blog/article/service/NewArticleDto.java
Normal file
18
src/main/java/myblog/blog/article/service/NewArticleDto.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package myblog.blog.article.service;
|
||||
|
||||
import myblog.blog.member.doamin.Member;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
public class NewArticleDto {
|
||||
|
||||
@NotBlank
|
||||
private String title;
|
||||
@NotBlank
|
||||
private String content;
|
||||
private String toc;
|
||||
@NotBlank
|
||||
private Long memberId;
|
||||
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
package myblog.blog.config;
|
||||
package myblog.blog.base.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.exception.LoginFailHandler;
|
||||
import myblog.blog.member.doamin.Role;
|
||||
import myblog.blog.member.service.Oauth2MemberService;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@@ -13,32 +17,40 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final Oauth2MemberService oauth2MemberService;
|
||||
private final LoginFailHandler loginFailHandler;
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web
|
||||
.ignoring()
|
||||
.antMatchers("/css/**", "/node_modules/**")
|
||||
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf().disable()
|
||||
|
||||
.authorizeRequests()
|
||||
.antMatchers("/user").authenticated()
|
||||
.antMatchers("/admin").access("hasRole('ROLE_ADMIN')")
|
||||
.anyRequest()
|
||||
.permitAll()
|
||||
.antMatchers("/admin").hasRole(Role.ADMIN.name())
|
||||
.anyRequest().permitAll()
|
||||
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/login")
|
||||
|
||||
.and()
|
||||
.logout()
|
||||
.logoutSuccessUrl("/")
|
||||
.deleteCookies("JSESSIONID","remember-me")
|
||||
|
||||
|
||||
.and()
|
||||
.oauth2Login()
|
||||
.loginPage("/login")
|
||||
.failureHandler(loginFailHandler)
|
||||
.userInfoEndpoint()
|
||||
.userService(oauth2MemberService)
|
||||
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
24
src/main/java/myblog/blog/base/domain/BasicEntity.java
Normal file
24
src/main/java/myblog/blog/base/domain/BasicEntity.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package myblog.blog.base.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@MappedSuperclass
|
||||
@Getter
|
||||
public abstract class BasicEntity {
|
||||
|
||||
@CreatedDate
|
||||
@Column(updatable = false)
|
||||
private LocalDateTime createdDate;
|
||||
@LastModifiedDate
|
||||
private LocalDateTime updatedDate;
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package myblog.blog.exception;
|
||||
|
||||
public class DuplicateEmailException extends RuntimeException {
|
||||
|
||||
public DuplicateEmailException() {
|
||||
super("이미 가입한 이메일입니다.");
|
||||
}
|
||||
|
||||
public DuplicateEmailException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DuplicateEmailException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DuplicateEmailException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
protected DuplicateEmailException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
23
src/main/java/myblog/blog/exception/ExceptionController.java
Normal file
23
src/main/java/myblog/blog/exception/ExceptionController.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package myblog.blog.exception;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
|
||||
@ControllerAdvice
|
||||
@Slf4j
|
||||
public class ExceptionController {
|
||||
|
||||
// @ExceptionHandler
|
||||
// public String handleRuntimeException(Principal principal, HttpServletRequest req, RuntimeException e) {
|
||||
// if (principal != null) {
|
||||
// log.info("'{}' requested '{}' ", principal.getName(), req.getRequestURI());
|
||||
// } else {
|
||||
// log.info("requested '{}'", req.getRequestURI());
|
||||
// }
|
||||
//
|
||||
// log.error("bad request", e);
|
||||
// return "";
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
34
src/main/java/myblog/blog/exception/LoginFailHandler.java
Normal file
34
src/main/java/myblog/blog/exception/LoginFailHandler.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package myblog.blog.exception;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LoginFailHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
|
||||
String errMsg = "error";
|
||||
|
||||
if(exception instanceof OAuth2AuthenticationException){
|
||||
errMsg = "duplicatedEmail";
|
||||
request.setAttribute("errMsg", errMsg);
|
||||
|
||||
}
|
||||
|
||||
setDefaultFailureUrl("/login?error="+errMsg);
|
||||
super.onAuthenticationFailure(request, response, exception);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
package myblog.blog;
|
||||
package myblog.blog.main;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class MainController {
|
||||
|
||||
|
||||
@GetMapping("/")
|
||||
public String main() {
|
||||
|
||||
return "index";
|
||||
return "main";
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,13 @@ package myblog.blog.member.auth;
|
||||
|
||||
|
||||
import myblog.blog.member.doamin.Member;
|
||||
import myblog.blog.member.doamin.Role;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -27,7 +31,9 @@ public class PrincipalDetails implements OAuth2User {
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return null;
|
||||
Collection<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.add(new SimpleGrantedAuthority(member.getRole().getValue()));
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package myblog.blog.member.auth;
|
||||
|
||||
import myblog.blog.member.auth.userinfo.*;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -19,7 +20,8 @@ public class UserInfoFactory {
|
||||
} else if (oAuth2UserRequest.getClientRegistration().getRegistrationId().equals("naver")) {
|
||||
return new NaverUserInfo(oAuth2User.getAttribute("response"));
|
||||
}
|
||||
else return null;
|
||||
else {
|
||||
throw new IllegalArgumentException("지원하지 않는 Oauth 인증 시도입니다");}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package myblog.blog.member.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
public class MemberController {
|
||||
|
||||
@GetMapping("/login")
|
||||
public String loginFrom(@RequestParam(value = "error",required = false) String error, Model model){
|
||||
|
||||
if(error!=null&&error.equals("duplicatedEmail")){
|
||||
model.addAttribute("errMsg","이미 가입된 이메일입니다.");
|
||||
}
|
||||
|
||||
return "login";
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -2,8 +2,11 @@ package myblog.blog.member.doamin;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.base.domain.BasicEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@SequenceGenerator(
|
||||
@@ -11,10 +14,11 @@ import javax.persistence.*;
|
||||
sequenceName = "MEMBER_SEQ",
|
||||
initialValue = 1, allocationSize = 50)
|
||||
@Getter
|
||||
public class Member {
|
||||
public class Member extends BasicEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
|
||||
@Column(name = "member_id")
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
@@ -23,7 +27,7 @@ public class Member {
|
||||
@Column(nullable = false)
|
||||
private String userId;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, unique = true)
|
||||
private String email;
|
||||
|
||||
private String picUrl;
|
||||
@@ -35,6 +39,9 @@ public class Member {
|
||||
|
||||
private String providerId;
|
||||
|
||||
@OneToMany(mappedBy = "member")
|
||||
private List<Article> articles;
|
||||
|
||||
protected Member() {
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package myblog.blog.member.doamin;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum Role {
|
||||
USER("ROLE_USER","일반사용자"),
|
||||
ADMIN("ROLE_ADMIN","관리자");
|
||||
USER("ROLE_USER"),
|
||||
ADMIN("ROLE_ADMIN");
|
||||
|
||||
private final String value;
|
||||
|
||||
private final String key;
|
||||
private final String title;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package myblog.blog.member.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.exception.DuplicateEmailException;
|
||||
import myblog.blog.member.auth.userinfo.Oauth2UserInfo;
|
||||
import myblog.blog.member.auth.UserInfoFactory;
|
||||
import myblog.blog.member.repository.MemberRepository;
|
||||
@@ -25,6 +24,7 @@ public class Oauth2MemberService extends DefaultOAuth2UserService {
|
||||
private final MemberRepository memberRepository;
|
||||
private final UserInfoFactory userInfoFactory;
|
||||
|
||||
// 앱 구동시 ADMIN 계정 Insert
|
||||
@Value("${admin.username}")
|
||||
private String adminUsername;
|
||||
@Value("${admin.picUrl}")
|
||||
@@ -37,6 +37,7 @@ public class Oauth2MemberService extends DefaultOAuth2UserService {
|
||||
private String adminProvider;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
|
||||
|
||||
Oauth2UserInfo userInfo =
|
||||
@@ -54,7 +55,7 @@ public class Oauth2MemberService extends DefaultOAuth2UserService {
|
||||
if(member == null) {
|
||||
|
||||
if(memberRepository.findByEmail(userInfo.getEmail()) != null)
|
||||
throw new DuplicateEmailException();
|
||||
throw new OAuth2AuthenticationException("duplicateEmail");
|
||||
|
||||
member = Member.builder()
|
||||
.username(userInfo.getUserName())
|
||||
|
||||
58
src/main/resources/static/css/login.css
Normal file
58
src/main/resources/static/css/login.css
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
button img{
|
||||
width: 200px;
|
||||
height:50px;
|
||||
}
|
||||
|
||||
/* Social Buttons Style */
|
||||
.btnCtm {
|
||||
background: none;
|
||||
border: none;
|
||||
background-position: 1em;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 2em;
|
||||
border-radius: 0.5em;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
line-height: 1em;
|
||||
padding: 0 2em 0 4em;
|
||||
text-decoration: none;
|
||||
transition: all 0.5s;
|
||||
height: 50px;
|
||||
width: 200px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.btn-google {
|
||||
background-color: #dd4b39;
|
||||
background-image: url("/img/google.svg");
|
||||
}
|
||||
.btn-google:hover {
|
||||
background-color: #e47365;
|
||||
}
|
||||
.btn-google:active {
|
||||
background-color: #c23321;
|
||||
}
|
||||
.btn-facebook {
|
||||
background-color: #3b5998;
|
||||
background-image: url("/img/facebook.svg");
|
||||
}
|
||||
.btn-facebook:hover {
|
||||
background-color: #4c70ba;
|
||||
}
|
||||
.btn-facebook:active {
|
||||
background-color: #2d4373;
|
||||
}
|
||||
|
||||
.btn-kakao{
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-naver{
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
}
|
||||
333
src/main/resources/static/css/mainCss.css
Normal file
333
src/main/resources/static/css/mainCss.css
Normal file
@@ -0,0 +1,333 @@
|
||||
@font-face {
|
||||
font-family: "IM_Hyemin-Bold";
|
||||
src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2106@1.1/IM_Hyemin-Bold.woff2")
|
||||
format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: rgb(65, 65, 65);
|
||||
}
|
||||
a:visited {
|
||||
text-decoration: none;
|
||||
color: rgb(65, 65, 65);
|
||||
}
|
||||
a:active {
|
||||
text-decoration: none;
|
||||
color: rgb(65, 65, 65);
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
color: rgb(65, 65, 65);
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #fcf6f5;
|
||||
font-family: "IM_Hyemin-Bold";
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(233, 224, 224);
|
||||
background-clip: padding-box;
|
||||
border: 4px solid transparent;
|
||||
border-top-left-radius: 100px;
|
||||
border-bottom-right-radius: 100px;
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar-track {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.offcanvas-body::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.offcanvas-body::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(233, 224, 224);
|
||||
background-clip: padding-box;
|
||||
border: 4px solid transparent;
|
||||
border-top-left-radius: 100px;
|
||||
border-bottom-right-radius: 100px;
|
||||
}
|
||||
|
||||
.offcanvas-body::-webkit-scrollbar-track {
|
||||
background-color: #fcf6f5;
|
||||
}
|
||||
|
||||
.btn-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
.btn-toggle:hover,
|
||||
.btn-toggle:focus {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
background-color: #d2f4ea;
|
||||
}
|
||||
|
||||
.btn-toggle::before {
|
||||
width: 1.25em;
|
||||
line-height: 0;
|
||||
content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
|
||||
transition: transform 0.35s ease;
|
||||
transform-origin: 0.5em 50%;
|
||||
}
|
||||
|
||||
.btn-toggle[aria-expanded="true"] {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
.btn-toggle[aria-expanded="true"]::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.btn-toggle-nav a {
|
||||
display: inline-flex;
|
||||
padding: 0.1875rem 0.5rem;
|
||||
margin-top: 0.125rem;
|
||||
margin-left: 1.25rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.btn-toggle-nav a:hover,
|
||||
.btn-toggle-nav a:focus {
|
||||
background-color: #d2f4ea;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
opacity: 0.98;
|
||||
}
|
||||
.navbar-toggler {
|
||||
border: whitesmoke;
|
||||
}
|
||||
.fa-address-card {
|
||||
font-size: 24px;
|
||||
color: rgb(119, 119, 119);
|
||||
}
|
||||
|
||||
.cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cards-container {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.popular-card {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-description {
|
||||
position: absolute;
|
||||
top: calc(100% - 50px);
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
|
||||
background: rgb(56, 55, 55);
|
||||
color: aliceblue;
|
||||
width: 100%;
|
||||
opacity: 0.8;
|
||||
|
||||
transition-property: all;
|
||||
transition-duration: 0.7s;
|
||||
}
|
||||
|
||||
.card-des-overlay {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
background: rgb(56, 55, 55);
|
||||
color: aliceblue;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 100%;
|
||||
opacity: 0.8;
|
||||
|
||||
transition-property: all;
|
||||
transition-duration: 0.7s;
|
||||
}
|
||||
|
||||
.popular-card:hover .card-des-overlay {
|
||||
top: 0%;
|
||||
}
|
||||
.popular-card:hover .card-description {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.recent-card-text {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
line-height: 1.2em;
|
||||
max-height: 3.6em;
|
||||
margin-right: -1em;
|
||||
}
|
||||
|
||||
.recent-card-text:before {
|
||||
content: "...";
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.recent-card-text:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
margin-top: 0.2em;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.recent-card {
|
||||
transition-property: all;
|
||||
transition-duration: 1s;
|
||||
}
|
||||
|
||||
.recent-card:hover {
|
||||
box-shadow: 0px 4px 8px rgba(38, 38, 38, 0.2);
|
||||
top: -4px;
|
||||
border: 1px solid #cccccc;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.arrow-up {
|
||||
position: fixed;
|
||||
bottom: 50px;
|
||||
right: 50px;
|
||||
font-size: 50px;
|
||||
border-radius: 100%;
|
||||
border: white;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
color: white;
|
||||
background-color: rgb(241, 226, 89);
|
||||
z-index: 5;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(233, 224, 224, 0.7);
|
||||
background-clip: padding-box;
|
||||
border: 4px solid transparent;
|
||||
border-top-left-radius: 100px;
|
||||
border-bottom-right-radius: 100px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
small {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.arrow-up {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 30px;
|
||||
line-height: 50px;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* list */
|
||||
.pagination-outer {
|
||||
text-align: center;
|
||||
}
|
||||
.pagination {
|
||||
display: inline-flex;
|
||||
}
|
||||
.pagination li {
|
||||
margin: 0 5px;
|
||||
}
|
||||
.pagination li a.page-link {
|
||||
color: #999;
|
||||
background: #e7e7e7;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.pagination li.active a.page-link,
|
||||
.pagination li a.page-link:hover,
|
||||
.pagination li.active a.page-link:hover,
|
||||
.pagination li a.page-link:focus {
|
||||
color: rgb(12, 11, 11);
|
||||
background: linear-gradient(#f0f5b0, #f8fae3);
|
||||
border: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.pagination {
|
||||
font-size: 0;
|
||||
display: block;
|
||||
}
|
||||
.pagination li {
|
||||
margin: 5px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.form-color {
|
||||
background-color: #e0dedd;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 25px;
|
||||
height: fit-content;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
color: #495057;
|
||||
background-color: #fcf6f5;
|
||||
border-color: #35b69f;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
text-indent: 10px;
|
||||
}
|
||||
|
||||
.comment-text {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.comment-reply {
|
||||
background-color: #e0dedd;
|
||||
}
|
||||
|
||||
.user-feed {
|
||||
font-size: 14px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
10
src/main/resources/static/img/facebook.svg
Normal file
10
src/main/resources/static/img/facebook.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="35px" height="35px" viewBox="0 0 300 300" enable-background="new 0 0 266.893 266.895"
|
||||
xml:space="preserve">
|
||||
<path id="f" fill="#FFFFFF" d="M182.409,262.307v-99.803h33.499l5.016-38.895h-38.515V98.777c0-11.261,3.127-18.935,19.275-18.935
|
||||
l20.596-0.009V45.045c-3.562-0.474-15.788-1.533-30.012-1.533c-29.695,0-50.025,18.126-50.025,51.413v28.684h-33.585v38.895h33.585
|
||||
v99.803H182.409z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 761 B |
23
src/main/resources/static/img/google.svg
Normal file
23
src/main/resources/static/img/google.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="35px" height="35px" viewBox="10 10 110.658 110.646" enable-background="new 0 0 134.658 131.646"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M70.479,71.845l-3.983-3.093c-1.213-1.006-2.872-2.334-2.872-4.765c0-2.441,1.659-3.993,3.099-5.43
|
||||
c4.64-3.652,9.276-7.539,9.276-15.73c0-8.423-5.3-12.854-7.84-14.956h6.849l7.189-4.517H60.418
|
||||
c-5.976,0-14.588,1.414-20.893,6.619c-4.752,4.1-7.07,9.753-7.07,14.842c0,8.639,6.633,17.396,18.346,17.396
|
||||
c1.106,0,2.316-0.109,3.534-0.222c-0.547,1.331-1.1,2.439-1.1,4.32c0,3.431,1.763,5.535,3.317,7.528
|
||||
c-4.977,0.342-14.268,0.893-21.117,5.103c-6.523,3.879-8.508,9.525-8.508,13.51c0,8.202,7.731,15.842,23.762,15.842
|
||||
c19.01,0,29.074-10.519,29.074-20.932C79.764,79.709,75.344,75.943,70.479,71.845z M56,59.107
|
||||
c-9.51,0-13.818-12.294-13.818-19.712c0-2.888,0.547-5.87,2.428-8.199c1.773-2.218,4.861-3.657,7.744-3.657
|
||||
c9.168,0,13.923,12.404,13.923,20.382c0,1.996-0.22,5.533-2.762,8.09C61.737,57.785,58.762,59.107,56,59.107z M56.109,103.65
|
||||
c-11.826,0-19.452-5.657-19.452-13.523c0-7.864,7.071-10.524,9.504-11.405c4.64-1.561,10.611-1.779,11.607-1.779
|
||||
c1.105,0,1.658,0,2.538,0.111c8.407,5.983,12.056,8.965,12.056,14.629C72.362,98.542,66.723,103.65,56.109,103.65z"/>
|
||||
<polygon fill="#FFFFFF" points="98.393,58.938 98.393,47.863 92.923,47.863 92.923,58.938 81.866,58.938 81.866,64.469
|
||||
92.923,64.469 92.923,75.612 98.393,75.612 98.393,64.469 109.506,64.469 109.506,58.938 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/main/resources/static/img/kakao.png
Normal file
BIN
src/main/resources/static/img/kakao.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/main/resources/static/img/naver.png
Normal file
BIN
src/main/resources/static/img/naver.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
ㅎㅇ
|
||||
|
||||
<div sec:authorize="isAuthenticated()">
|
||||
<div th:href="@{/profile/{userId}(userId=${#authentication.name})}" th:text="${#authentication.name} + '님'">
|
||||
아이디</div>
|
||||
</div>
|
||||
|
||||
|
||||
<a sec:authorize="!isAuthenticated()" href="/oauth2/authorization/google">구글 로그인</a>
|
||||
<a sec:authorize="!isAuthenticated()" href="/oauth2/authorization/facebook">페이스북 로그인</a>
|
||||
<a sec:authorize="!isAuthenticated()" href="/oauth2/authorization/naver">네이버 로그인</a>
|
||||
<a sec:authorize="!isAuthenticated()" href="/oauth2/authorization/kakao">카카오 로그인</a>
|
||||
<a sec:authorize="isAuthenticated()" href="/logout">로그아웃</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
294
src/main/resources/templates/layout/layout.html
Normal file
294
src/main/resources/templates/layout/layout.html
Normal file
@@ -0,0 +1,294 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:fragment="layout (title, content, style)"
|
||||
lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title th:replace="${title}">Jinia's Log</title>
|
||||
<!-- SEO -->
|
||||
<meta name="description" content=""/>
|
||||
<meta name="keyword" content=""/>
|
||||
<meta name="author" content="jinia"/>
|
||||
<meta name="viewport" content="width=device-width, user-scalable = no, initial-scale=1.0"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
|
||||
<!-- OPEN GRAPH(FACEBOOK, LINKEDIN) -->
|
||||
<meta property="og:type" content=""/>
|
||||
<meta property="og:description" content=""/>
|
||||
<meta property="og:title" content=""/>
|
||||
<meta property="og:image" content=""/>
|
||||
<meta property="og:url" content=""/>
|
||||
<meta property="og:site_name" content=""/>
|
||||
|
||||
<!-- twitter -->
|
||||
<meta property="twitter:card" content=""/>
|
||||
<meta property="twitter:title" content=""/>
|
||||
<meta property="twitter:description" content=""/>
|
||||
<meta property="twitter:image" content=""/>
|
||||
<meta property="twitter:url" content=""/>
|
||||
<meta property="twitter:creator" content=""/>
|
||||
|
||||
<link rel="icon" href=""/>
|
||||
<link rel="apple-touch-icon" href=""/>
|
||||
<link rel="short icon" type="image/x-icon" href=""/>
|
||||
|
||||
<!-- CSS RESET -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"/>
|
||||
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="/css/mainCss.css"/>
|
||||
<link th:replace="${style}">
|
||||
|
||||
<script src="https://kit.fontawesome.com/233840a552.js" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="fixed-top d-xxl-none p-0">
|
||||
<nav class="navbar navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasMenu"
|
||||
aria-controls="offcanvasMenu">
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<div id="nav-brand">
|
||||
<a href="#">
|
||||
<h4>Blog</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div id="nav-login" sec:authorize="!isAuthenticated()"><a th:href="@{/login}"><i
|
||||
class="far fa-address-card"></i></a></div>
|
||||
<div sec:authorize="isAuthenticated()">
|
||||
<span sec:authorize="isAuthenticated()" th:text="${#authentication.name} + '님'"></span>
|
||||
<a th:href="@{/article/write}"><span sec:authorize="hasRole('ADMIN')" style="font-size: 21px"><i class="fas fa-edit"></i></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- offcanvas s -->
|
||||
<aside class="offcanvas offcanvas-start " data-bs-scroll="true" style="max-width: 300px;" tabindex="-1"
|
||||
id="offcanvasMenu"
|
||||
aria-labelledby="offcanvasLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title">BLOG</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body bg-white">
|
||||
<div href="#" class="d-flex align-items-center pb-3 mb-3 link-dark border-bottom">
|
||||
<form class="d-flex">
|
||||
<input class="form-control me-2" type="search" placeholder="검색해" aria-label="Search">
|
||||
<button class="btn btn-outline-success" type="submit"><i class="fas fa-search"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<ul class="list-unstyled ps-0">
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#home-collapse" aria-expanded="true">
|
||||
Link
|
||||
</button>
|
||||
<div class="collapse show" id="home-collapse">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">
|
||||
<i class="fab fa-github" style="font-size: 20px;"></i>  Github
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse1" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse1">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse2" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse2">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse3" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse3">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="border-top my-3"></li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#account-collapse" aria-expanded="true">
|
||||
Account
|
||||
</button>
|
||||
<div class="collapse show" id="account-collapse">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li sec:authorize="!isAuthenticated()"><a href="#" th:href="@{/login}"
|
||||
class="link-dark rounded">로그인</a></li>
|
||||
<li sec:authorize="isAuthenticated()" th:text="${#authentication.name} + '님 환영합니다'"></li>
|
||||
<li sec:authorize="isAuthenticated()">
|
||||
<form method="post" id="logoutOC" name="logoutOC" th:action="@{/logout}">
|
||||
<a href="#" class="nav-link active" onclick="document.logout.submit()">로그아웃</a>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</aside>
|
||||
<!-- offcanvass e -->
|
||||
</header>
|
||||
|
||||
<!-- 실제 body s -->
|
||||
<section class="row g-0 row-cols-xxl-2 g-xxl-0 p-0 ">
|
||||
|
||||
<!-- sidebar-xxl -->
|
||||
<div class="bg-white sidebar col-xxl-2 d-none d-xxl-block p-0 overflow-auto">
|
||||
|
||||
<div class="p-4 sidebar-inner">
|
||||
|
||||
<div class="m-4 sidebar-header">
|
||||
<a href="#">
|
||||
<h5 class="text-black-50">BLOG</h5>
|
||||
</a>
|
||||
<a href="#">
|
||||
<h5 class="text-black-50">ABOUT ME</h5>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div href="#" class="d-flex align-items-center pb-3 mb-3 link-dark border-bottom">
|
||||
<form class="d-flex">
|
||||
<input class="form-control me-2" type="search" placeholder="검색해" aria-label="Search">
|
||||
<button class="btn btn-outline-success" type="submit"><i class="fas fa-search"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<ul class="list-unstyled ps-0">
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#home-collapse-xl" aria-expanded="true">
|
||||
Link
|
||||
</button>
|
||||
<div class="collapse show" id="home-collapse-xl">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">
|
||||
<i class="fab fa-github" style="font-size: 20px;"></i>  Github
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse1-xl" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse1-xl">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse2-xl" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse2-xl">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#dashboard-collapse3-xl" aria-expanded="true">
|
||||
카테고리
|
||||
</button>
|
||||
<div class="collapse show" id="dashboard-collapse3-xl">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">카테고리1</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리2</a></li>
|
||||
<li><a href="#" class="link-dark rounded">카테고리3</a></li>
|
||||
</div>
|
||||
</li>
|
||||
<li class="border-top my-3"></li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse"
|
||||
data-bs-target="#account-collapse-xl" aria-expanded="true">
|
||||
Account
|
||||
</button>
|
||||
<div class="collapse show" id="account-collapse-xl">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li sec:authorize="!isAuthenticated()"><a th:href="@{/login}"
|
||||
class="link-dark rounded">로그인</a></li>
|
||||
<li sec:authorize="isAuthenticated()" th:text="${#authentication.name} + '님 환영합니다'"></li>
|
||||
|
||||
<li sec:authorize="isAuthenticated()">
|
||||
<div class="link-dark rounded">
|
||||
<form method="post" id="logout" name="logout" th:action="@{/logout}">
|
||||
<a href="#" class="nav-link active" onclick="document.logout.submit()">로그아웃</a>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- sidebar e -->
|
||||
|
||||
|
||||
<!-- xxl dummy -->
|
||||
<div class="bg-white col-xxl-2 d-none d-xxl-block p-0">
|
||||
</div>
|
||||
<!-- -->
|
||||
|
||||
<!-- sections -->
|
||||
<div class="col-xxl-10 p-0 sections-container">
|
||||
|
||||
<section th:replace="${content}"></section>
|
||||
<!-- sections e -->
|
||||
|
||||
<footer class="footer bg-light">
|
||||
<div class="container text-center p-2">
|
||||
<h5><span class="text-muted">Copyright ©Jinia</span></h5>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
<!-- body e -->
|
||||
|
||||
|
||||
<button class="arrow-up">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
</button>
|
||||
|
||||
<!-- js -->
|
||||
<script src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- -->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
54
src/main/resources/templates/login.html
Normal file
54
src/main/resources/templates/login.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:replace="~{layout/layout.html :: layout(~{::title}, ~{::section}, ~{::link})}"
|
||||
lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5" xmlns="http://www.w3.org/1999/html">
|
||||
|
||||
<head>
|
||||
<title>Jinia's Log - 로그인</title>
|
||||
<link rel="stylesheet" href="/css/login.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section>
|
||||
|
||||
<div style="margin-bottom: 300px"></div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<P class="text-center field-error mt-3" id="capsAlert" th:text="${errMsg}">로그인 오류</P>
|
||||
|
||||
<div class="col">
|
||||
<a href="/oauth2/authorization/google">
|
||||
<button class="btnCtm btn-google">구글 로그인</button>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<a href="/oauth2/authorization/facebook">
|
||||
<button class="btnCtm btn-facebook">페이스북 로그인</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<a href="/oauth2/authorization/kakao">
|
||||
<button class="btn-kakao"><img src="/img/kakao.png"></button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<a href="/oauth2/authorization/naver">
|
||||
<button class="btn-naver"><img src="/img/naver.png"></button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 300px"></div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
332
src/main/resources/templates/main.html
Normal file
332
src/main/resources/templates/main.html
Normal file
@@ -0,0 +1,332 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:replace="~{layout/layout.html :: layout(~{::title}, ~{::section}, ~{::link})}"
|
||||
lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
|
||||
|
||||
<head>
|
||||
<title>Jinia's Log</title>
|
||||
<link rel="stylesheet" href=""/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section>
|
||||
<div class="main">
|
||||
|
||||
<div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel">
|
||||
|
||||
<div class="carousel-indicators">
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="0" class="active"
|
||||
aria-current="true" aria-label="Slide 0"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="1"
|
||||
aria-label="Slide 1"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="2"
|
||||
aria-label="Slide 2"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="3"
|
||||
aria-label="Slide 3"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="4"
|
||||
aria-label="Slide 4"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="5"
|
||||
aria-label="Slide 5"></button>
|
||||
</div>
|
||||
|
||||
<div class="carousel-inner">
|
||||
|
||||
<div class="carousel-item active">
|
||||
<a href="#">
|
||||
<img src="https://cdn.pixabay.com/photo/2020/11/08/13/28/tree-5723734_1280.jpg"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3 class="">첫번째 이미지</h3>
|
||||
<p class="text-truncate w-50">블로그 아티클 헤으응</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="#">
|
||||
<img src="https://cdn.pixabay.com/photo/2021/09/27/14/39/paris-6661136_1280.jpg"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3>두번째 이미지</h3>
|
||||
<p class="text-truncate w-50">블로그 아티클 헤으응2</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="#">
|
||||
<img src="https://cdn.pixabay.com/photo/2021/10/23/16/31/italy-6735340_1280.jpg"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3>세번째 이미지</h3>
|
||||
<p class="text-truncate w-50">블로그 아티클 헤으응3</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="#">
|
||||
<img src="https://cdn.pixabay.com/photo/2021/10/13/15/09/water-6706894_1280.jpg"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3>네번째 이미지</h3>
|
||||
<p class="text-truncate w-50">블로그 아티클
|
||||
헤으응31!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!헤으응31!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!헤으응31!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="#">
|
||||
<img
|
||||
src="https://media.istockphoto.com/photos/matrix-background-with-the-green-numbers-picture-id539244598"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3>다섯번째 이미지</h3>
|
||||
<p class="text-truncate w-50">블로그 아티클 헤으응3</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<a href="#">
|
||||
<img src="https://cdn.pixabay.com/photo/2021/01/01/21/31/halloween-5880068_1280.jpg"
|
||||
class="w-100 vh-100 cover" alt="...">
|
||||
<div class="card-img-overlay text-white text-center row justify-content-center align-content-center">
|
||||
<h3>여섯번째 이미지</h3>
|
||||
<p class="text-truncate">블로그 아티클 헤으응3</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions"
|
||||
data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions"
|
||||
data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-5 pt-2 popular-card-section">
|
||||
|
||||
<div class="cards-container container p-0">
|
||||
<div class=" row g-0 row-cols-2 row-cols-md-3">
|
||||
|
||||
<div class="col g-1 g-md-4 ">
|
||||
<a href="#">
|
||||
<div class=" card ratio ratio-1x1 popular-card " style="background-image: url(https://cdn.pixabay.com/photo/2020/11/08/13/28/tree-5723734_1280.jpg);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col g-1 g-md-4">
|
||||
<a href="#">
|
||||
<div class="card ratio ratio-1x1 popular-card " style="background-image: url(https://cdn.pixabay.com/photo/2021/09/27/14/39/paris-6661136_1280.jpg);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col g-1 g-md-4">
|
||||
<a href="#">
|
||||
<div class="card ratio ratio-1x1 popular-card " style="background-image: url(https://cdn.pixabay.com/photo/2021/10/23/16/31/italy-6735340_1280.jpg);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col g-1 g-md-4">
|
||||
<a href="#">
|
||||
<div class="card ratio ratio-1x1 popular-card " style="background-image: url(https://cdn.pixabay.com/photo/2021/10/13/15/09/water-6706894_1280.jpg);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col g-1 g-md-4">
|
||||
<a href="#">
|
||||
<div class="card ratio ratio-1x1 popular-card " style="background-image: url(https://media.istockphoto.com/photos/matrix-background-with-the-green-numbers-picture-id539244598);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col g-1 g-md-4">
|
||||
<a href="#">
|
||||
<div class="card ratio ratio-1x1 popular-card " style="background-image: url(https://cdn.pixabay.com/photo/2021/01/01/21/31/halloween-5880068_1280.jpg);
|
||||
background-size: cover;">
|
||||
<div class="card-description">
|
||||
<p>타이틀</p>
|
||||
</div>
|
||||
<div class="card-des-overlay">설명</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="py-1 mt-5" style="color: rgb(212, 200, 184);">
|
||||
|
||||
<div class="recent-cards mt-5">
|
||||
|
||||
<div class="cards-container container p-0">
|
||||
<h1 class="text-center">최신 포스팅</h1>
|
||||
<hr>
|
||||
|
||||
<div class="card mb-3 recent-card">
|
||||
<a href="#">
|
||||
<div class="row g-0">
|
||||
<div class="col-3">
|
||||
<div class="ratio ratio-1x1" style="background-image: url(https://cdn.pixabay.com/photo/2021/09/27/14/39/paris-6661136_1280.jpg);
|
||||
background-size: cover;"></div>
|
||||
</div>
|
||||
<div class="col-9 row row-cols-1 align-self-center">
|
||||
<h3 class="card-title col mb-3 text-truncate">글 제목</h3>
|
||||
<p class="d-none d-md-block col recent-card-text">대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충
|
||||
존나
|
||||
긴
|
||||
내용대충 존나 긴대충 긴대충 긴대충 긴대충 긴대충 긴대충 긴대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용</p>
|
||||
<p class="col mb-0"><small class="text-muted">Last updated 3 mins ago</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 recent-card">
|
||||
<a href="#">
|
||||
<div class="row g-0">
|
||||
<div class="col-3">
|
||||
<div class="ratio ratio-1x1" style="background-image: url(https://media.istockphoto.com/photos/matrix-background-with-the-green-numbers-picture-id539244598);
|
||||
background-size: cover;"></div>
|
||||
</div>
|
||||
<div class="col-9 row row-cols-1 align-self-center">
|
||||
<h3 class="card-title col mb-3 text-truncate">글 제목</h3>
|
||||
<p class="d-none d-md-block col recent-card-text">대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충
|
||||
존나
|
||||
긴
|
||||
내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충
|
||||
존나 긴 내용대충 존나 긴
|
||||
내용대충
|
||||
존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용
|
||||
</p>
|
||||
<p class="col mb-0"><small class="text-muted">Last updated 3 mins ago</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 recent-card">
|
||||
<a href="#">
|
||||
<div class="row g-0">
|
||||
<div class="col-3">
|
||||
<div class="ratio ratio-1x1" style="background-image: url(https://media.istockphoto.com/photos/matrix-background-with-the-green-numbers-picture-id539244598);
|
||||
background-size: cover;"></div>
|
||||
</div>
|
||||
<div class="col-9 row row-cols-1 align-self-center">
|
||||
<h3 class="card-title col mb-3 text-truncate">글 제목</h3>
|
||||
<p class="d-none d-md-block col recent-card-text">대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충
|
||||
존나
|
||||
긴
|
||||
내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충
|
||||
존나 긴 내용대충 존나 긴
|
||||
내용대충
|
||||
존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용
|
||||
</p>
|
||||
<p class="col mb-0"><small class="text-muted">Last updated 3 mins ago</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 recent-card">
|
||||
<a href="#">
|
||||
<div class="row g-0">
|
||||
<div class="col-3">
|
||||
<div class="ratio ratio-1x1" style="background-image: url(https://media.istockphoto.com/photos/matrix-background-with-the-green-numbers-picture-id539244598);
|
||||
background-size: cover;"></div>
|
||||
</div>
|
||||
<div class="col-9 row row-cols-1 align-self-center">
|
||||
<h3 class="card-title col mb-3 text-truncate">글 제목</h3>
|
||||
<p class="d-none d-md-block col recent-card-text">대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충
|
||||
존나
|
||||
긴
|
||||
내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충
|
||||
존나 긴 내용대충 존나 긴
|
||||
내용대충
|
||||
존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용
|
||||
</p>
|
||||
<p class="col mb-0"><small class="text-muted">Last updated 3 mins ago</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 recent-card">
|
||||
<a href="#">
|
||||
<div class="row g-0">
|
||||
<div class="col-3">
|
||||
<div class="ratio ratio-1x1" style="background-image: url(https://cdn.pixabay.com/photo/2021/01/01/21/31/halloween-5880068_1280.jpg);
|
||||
background-size: cover;"></div>
|
||||
</div>
|
||||
<div class="col-9 row row-cols-1 align-self-center">
|
||||
<h3 class="card-title col mb-3 text-truncate">글 제목</h3>
|
||||
<p class="d-none d-md-block col recent-card-text">대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충
|
||||
존나
|
||||
긴
|
||||
내용대충 존나 긴
|
||||
내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충
|
||||
존나 긴 내용대충 존나 긴
|
||||
내용대충
|
||||
존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴 내용대충 존나 긴
|
||||
내용대충 존나 긴 내용
|
||||
</p>
|
||||
<p class="col mb-0"><small class="text-muted update">Last updated 3 mins ago</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
33
src/test/java/myblog/blog/MainControllerTest.java
Normal file
33
src/test/java/myblog/blog/MainControllerTest.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package myblog.blog;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
class MainControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
@WithMockUser(roles = "ADMIN")
|
||||
public void 권한테스트() throws Exception {
|
||||
// given
|
||||
// when
|
||||
ResultActions admin = mockMvc.perform(get("/admin"));
|
||||
// then
|
||||
admin.andExpect(status().isOk());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package myblog.blog.member.service;
|
||||
|
||||
import myblog.blog.member.doamin.Member;
|
||||
import myblog.blog.member.doamin.Role;
|
||||
import myblog.blog.member.repository.MemberRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@SpringBootTest
|
||||
class Oauth2MemberServiceTest {
|
||||
|
||||
@Autowired
|
||||
Oauth2MemberService oauth2MemberService;
|
||||
|
||||
@Autowired
|
||||
MemberRepository memberRepository;
|
||||
|
||||
@Test
|
||||
public void 권한테스트() throws Exception {
|
||||
// given
|
||||
Optional<Member> byId = memberRepository.findById(1L);
|
||||
Member admin = byId.get();
|
||||
|
||||
|
||||
// when
|
||||
|
||||
// then
|
||||
assertThat(admin.getRole().toString()).isEqualTo(Role.ADMIN.toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user