Skip to content
This repository has been archived by the owner on Oct 22, 2020. It is now read-only.

Commit

Permalink
[MERGE #170] from milzipmoza-developers/feature/ZENHUB-163
Browse files Browse the repository at this point in the history
[#163] 어드민의 유저 관리 기능을 구현한다.
  • Loading branch information
TheDevLuffy authored May 22, 2020
2 parents dfc5caf + b23d3ae commit 3369bfc
Show file tree
Hide file tree
Showing 15 changed files with 491 additions and 5 deletions.
15 changes: 15 additions & 0 deletions tecobrary-admin/src/front/src/api/admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import request from '@/utils/request'

export const getAdmin = (query) => request({
url: '/api/admin',
method: 'get',
params: Object.assign(query, {
page: query.page
})
})

export const createAdmin = (data) => request({
url: '/api/admin',
method: 'post',
data: data
})
167 changes: 164 additions & 3 deletions tecobrary-admin/src/front/src/views/user/admin.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,166 @@
<template>
<div>
어드민 관리
<div class="app-container">
<el-form :inline="true" :model="queryForm">
<el-form-item label="검색할 이메일 주소">
<el-input v-model="queryForm.email"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSearchRequest">검색</el-button>
<el-button type="success" @click="onAddBtnClickHandler">새로 등록하기</el-button>
</el-form-item>
</el-form>

<el-table
empty-text="해당하는 어드민 유저가 없습니다"
:data="adminUser.content"
style="width: 100%; min-height: 400px;"
highlight-current-row
fit
>
<el-table-column align="center" label="번호" width="100">
<span slot-scope="scope">{{ scope.row.id }}</span>
</el-table-column>
<el-table-column align="center" label="이메일">
<span slot-scope="scope" class="link-type">{{ scope.row.email }}</span>
</el-table-column>
<el-table-column align="center" label="이름">
<span slot-scope="scope">{{ scope.row.name }}</span>
</el-table-column>
<el-table-column align="center" label="권한">
<span slot-scope="scope">{{ scope.row.role }}</span>
</el-table-column>
</el-table>

<!-- 페이지네이션 -->
<div class="block" style="margin: 16px;">
<el-pagination
:current-page="queryForm.page"
:page-sizes="[10, 20]"
:page-size="queryForm.size"
layout="total, sizes, prev, pager, next, jumper"
:total="adminUser.totalElements"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>

<el-dialog title="새로운 어드민 정보" :visible.sync="newAdmin.visible">
<el-form :model="newAdmin" :rules="newAdmin.rules" ref="newAdmin">
<el-form-item label="등록할 이메일 주소" prop="email">
<el-input v-model="newAdmin.email"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="newAdmin.visible = false">닫기</el-button>
<el-button type="warning" @click="onAdminEnrollRequest">등록하기</el-button>
</span>
</el-dialog>
</div>
</template>
</template>

<script>
import {getAdmin, createAdmin} from "@/api/admin";
export default {
data: () => {
const validEmail = (email) => {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
const checkMailForm = (rule, value, callback) => {
if (value === '') {
callback(new Error("어드민으로 등록할 이메일을 입력해주세요."))
} else if (!validEmail(value)) {
callback(new Error("이메일 주소를 입력해주세요."))
} else {
callback()
}
}
return {
queryForm: {
email: '',
page: 0,
size: 10
},
adminUser: {
totalElements: 1,
totalPages: 1,
number: 10,
content: []
},
newAdmin: {
visible: false,
rules: {
email: [
{validator: checkMailForm, trigger: 'blur'}
]
},
email: ''
}
}
},
async beforeMount() {
this.getAdmins()
},
methods: {
async getAdmins() {
try {
const response = await getAdmin(this.queryForm)
const {content, totalElements, totalPages, number} = response
this.adminUser.content = content
this.adminUser.totalElements = totalElements
this.adminUser.totalPages = totalPages
this.adminUser.number = number
} catch (e) {
console.log(e)
}
},
onSearchRequest() {
console.log("search")
},
onAddBtnClickHandler() {
this.newAdmin.email = ''
this.newAdmin.visible = true
},
onAdminEnrollRequest() {
this.$refs["newAdmin"].validate(async (valid) => {
if (valid) {
try {
const response = await createAdmin({email: this.newAdmin.email})
console.log(response)
this.getAdmins()
} catch (e) {
console.log(e)
}
this.newAdmin.visible = false
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
handleSizeChange(size) {
this.queryForm.size = size
},
handleCurrentChange(page) {
this.queryForm.page = page
}
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers("/", "/login", "/oauth2/authorization/**", "/static/**").permitAll()

.antMatchers("/api/librarybook/**").hasAuthority(AdminRole.ROLE_ADMIN.name())
.antMatchers("/api/admin/**").hasAuthority(AdminRole.ROLE_ADMIN.name())

.anyRequest().authenticated()
.and().logout().logoutSuccessUrl("/").invalidateHttpSession(true)
.and().oauth2Login().userInfoEndpoint().userService(userSecurityService);

if (environment.acceptsProfiles(Profiles.of("local"))) {
if (environment.acceptsProfiles(Profiles.of("local"))
|| environment.acceptsProfiles(Profiles.of("localdev"))) {
http.oauth2Login()
.defaultSuccessUrl(DEVELOP_ORIGIN)
.loginPage(DEVELOP_ORIGIN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ public Admin extract(OAuth2User oAuth2User) {
Admin admin = adminRepository.findByEmail(email)
.orElseThrow(() -> new IllegalArgumentException("등록된 유저가 아닙니다."));

return admin.updateUserInfo(name, picture);
return adminRepository.save(admin.updateUserInfo(name, picture));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.woowacourse.tecobrary.admin.web.admin;

import com.woowacourse.tecobrary.admin.web.admin.dto.AdminCreateRequest;
import com.woowacourse.tecobrary.admin.web.admin.dto.AdminCreateResponse;
import com.woowacourse.tecobrary.admin.web.admin.dto.AdminSearchRequest;
import com.woowacourse.tecobrary.admin.web.admin.dto.AdminSearchResponse;
import com.woowacourse.tecobrary.admin.web.admin.service.AdminFacade;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/admin")
public class AdminController {

private final AdminFacade adminFacade;

@GetMapping
public Page<AdminSearchResponse> searchAdmin(@PageableDefault Pageable pageable,
@Valid AdminSearchRequest request) {
return adminFacade.searchAdmin(pageable, request);
}

@PostMapping
public AdminCreateResponse createAdmin(@RequestBody AdminCreateRequest request) {
return adminFacade.createAdmin(request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.woowacourse.tecobrary.admin.web.admin.converter;

import com.woowacourse.tecobrary.admin.web.admin.dto.AdminCreateResponse;
import com.woowacourse.tecobrary.admin.web.admin.dto.AdminSearchResponse;
import com.woowacourse.tecobrary.domain.admin.entity.Admin;
import org.springframework.stereotype.Component;

@Component
public class AdminConverter {

public AdminSearchResponse convertToSearchResponse(Admin admin) {
return AdminSearchResponse.builder()
.id(admin.getId())
.email(admin.getEmail())
.name(admin.getName())
.role(admin.getRole().name())
.build();
}

public AdminCreateResponse convertToCreateResponse(Admin admin) {
return AdminCreateResponse.builder()
.id(admin.getId())
.email(admin.getEmail())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.woowacourse.tecobrary.admin.web.admin.dto;


import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public class AdminCreateRequest {

private String email;

public AdminCreateRequest(String email) {
this.email = email;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.woowacourse.tecobrary.admin.web.admin.dto;


import lombok.*;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public class AdminCreateResponse {

private Long id;
private String email;

@Builder
public AdminCreateResponse(Long id, String email) {
this.id = id;
this.email = email;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.woowacourse.tecobrary.admin.web.admin.dto;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public class AdminSearchRequest {

private String email;
private String name;

public AdminSearchRequest(String email, String name) {
this.email = email;
this.name = name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.woowacourse.tecobrary.admin.web.admin.dto;

import lombok.*;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public class AdminSearchResponse {

private Long id;
private String email;
private String name;
private String role;

@Builder
public AdminSearchResponse(Long id, String email, String name, String role) {
this.id = id;
this.email = email;
this.name = name;
this.role = role;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.woowacourse.tecobrary.admin.web.admin.repository;

import com.querydsl.core.QueryResults;
import com.querydsl.jpa.JPQLQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.woowacourse.tecobrary.domain.admin.entity.Admin;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;

import static com.woowacourse.tecobrary.domain.admin.entity.QAdmin.admin;

@Repository
public class AdminManageRepository extends QuerydslRepositorySupport {

private final JPAQueryFactory jpaQueryFactory;

public AdminManageRepository(JPAQueryFactory jpaQueryFactory) {
super(Admin.class);
this.jpaQueryFactory = jpaQueryFactory;
}

public Page<Admin> searchAdmin(Pageable pageable, AdminSearchClause clause) {
JPQLQuery<Admin> jpqlQuery = jpaQueryFactory.selectFrom(admin)
.where(clause.where())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(admin.id.asc());

QueryResults<Admin> queryResults = jpqlQuery.fetchResults();

return new PageImpl<>(queryResults.getResults(), pageable, queryResults.getTotal());
}
}
Loading

0 comments on commit 3369bfc

Please sign in to comment.