Commit 90b3d3d6 authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

admin page, oauth key 저장

parent 70eaef81
...@@ -16,10 +16,12 @@ import { ...@@ -16,10 +16,12 @@ import {
SurveyLayout, SurveyLayout,
SurveysLayout, SurveysLayout,
ResultLayout, ResultLayout,
AdminLayout,
} from "./layouts"; } from "./layouts";
import { Home } from "./home"; import { Home } from "./home";
import { OAuthRedirectHandler } from "./auth/OAuthRedirectHandler"; import { OAuthRedirectHandler } from "./auth/OAuthRedirectHandler";
import { LoginSuccess } from "./commons/LoginSuccess"; import { LoginSuccess } from "./commons/LoginSuccess";
import { Admin, SocialLogin } from "./admin";
export const MainRouter = () => { export const MainRouter = () => {
return ( return (
...@@ -35,6 +37,11 @@ export const MainRouter = () => { ...@@ -35,6 +37,11 @@ export const MainRouter = () => {
<Route path="/results/:surveyId" element={<ResultSurvey />} /> <Route path="/results/:surveyId" element={<ResultSurvey />} />
</Route> </Route>
<Route element={<AdminLayout />}>
<Route path="/admin" element={<Admin />}></Route>
<Route path="/admin/social-login" element={<SocialLogin />}></Route>
</Route>
<Route element={<AnswerLayout />}> <Route element={<AnswerLayout />}>
<Route path="/answers/:surveyId" element={<AnswerSurvey />} /> <Route path="/answers/:surveyId" element={<AnswerSurvey />} />
</Route> </Route>
......
import React from "react";
import { Link, Outlet } from "react-router-dom";
import { SideBar } from "./SideBar";
export const Admin = () => {
return <div className="flex"></div>;
};
import React from "react";
export const SideBar = () => {
return (
<aside className="w-48 h-screen" aria-label="Sidebar">
<div className="py-4 h-full px-3 bg-gray-50 rounded dark:bg-gray-800">
<ul className="flex flex-col items-center">
<li className="text-center font-bold p-2 border-b-2">ADMIN</li>
<div className="pt-2">
<li>
<a
href="#"
className="flex items-center p-2 text-base text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700"
>
<svg
aria-hidden="true"
className="w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M2 10a8 8 0 018-8v8h8a8 8 0 11-16 0z"></path>
<path d="M12 2.252A8.014 8.014 0 0117.748 8H12V2.252z"></path>
</svg>
<span className="ml-1">Dashboard</span>
</a>
</li>
<li>
<a
href="#"
className="flex items-center p-2 text-base text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700"
>
<svg
aria-hidden="true"
className="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5 3a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2V5a2 2 0 00-2-2H5zM5 11a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2v-2a2 2 0 00-2-2H5zM11 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V5zM11 13a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"></path>
</svg>
<span className="ml-1">Social</span>
</a>
</li>
<li>
<a
href="#"
className="flex items-center p-2 text-base text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700"
>
<svg
aria-hidden="true"
className="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clip-rule="evenodd"
></path>
</svg>
<span className="ml-1">Users</span>
</a>
</li>
<li>
<a
href="#"
className="flex items-center p-2 text-base text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700"
>
<svg
aria-hidden="true"
className="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M5 4a3 3 0 00-3 3v6a3 3 0 003 3h10a3 3 0 003-3V7a3 3 0 00-3-3H5zm-1 9v-1h5v2H5a1 1 0 01-1-1zm7 1h4a1 1 0 001-1v-1h-5v2zm0-4h5V8h-5v2zM9 8H4v2h5V8z"
clip-rule="evenodd"
></path>
</svg>
<span className="ml-1">Surveys</span>
</a>
</li>
</div>
</ul>
</div>
</aside>
);
};
import React, { useState, ChangeEvent, FormEvent } from "react";
import { authApi } from "../apis";
import { catchErrors } from "../helpers";
export const SocialLogin = () => {
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [keyInfo, setKeyInfo] = useState({
socialType: "kakao",
REST_API_KEY: "",
REDIRECT_URI: "",
CLIENT_SECRET_KEY: "",
});
const handleSubmit = async (e: FormEvent) => {
const { socialType, REST_API_KEY, REDIRECT_URI, CLIENT_SECRET_KEY } =
keyInfo;
try {
setLoading(true);
await authApi.saveOauthKeys(
socialType,
REST_API_KEY,
REDIRECT_URI,
CLIENT_SECRET_KEY
);
} catch (error) {
setLoading(false);
catchErrors(error, setError);
}
};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.currentTarget;
setKeyInfo({ ...keyInfo, [name]: value });
};
return (
<div className="flex flex-col w-full items-center">
<div className="text-slate-400 my-3">일단 카카오 로그인만 구현</div>
<form onSubmit={handleSubmit} className="flex flex-col mt-3 w-80">
<label className="block text-gray-700 text-sm font-bold mb-2 mt-3">
REST_API_KEY
</label>
<input
onChange={handleChange}
className="shadow appearance-none border rounded py-2 px-3 text-gray-70"
name="REST_API_KEY"
type="text"
placeholder="REST_API_KEY"
value={keyInfo.REST_API_KEY}
/>
<label className="block text-gray-700 text-sm font-bold mb-2 mt-3">
REDIRECT_URI
</label>
<input
onChange={handleChange}
className="shadow appearance-none border rounded py-2 px-3 text-gray-70"
name="REDIRECT_URI"
type="text"
placeholder="REDIRECT_URI"
value={keyInfo.REDIRECT_URI}
/>
<label className="block text-gray-700 text-sm font-bold mb-2 mt-3">
CLIENT_SECRET_KEY
</label>
<input
onChange={handleChange}
className="shadow appearance-none border rounded py-2 px-3 text-gray-70"
name="CLIENT_SECRET_KEY"
type="text"
placeholder="CLIENT_SECRET_KEY"
value={keyInfo.CLIENT_SECRET_KEY}
/>
<div className="flex justify-center items-center mt-3">
<button
type="submit"
className="bg-themeColor text-white border rounded w-full py-2 px-3"
>
저장하기
</button>
</div>
</form>
</div>
);
};
export { Admin } from "./Admin";
export { SideBar } from "./SideBar";
export { SocialLogin } from "./SocialLogin";
...@@ -27,3 +27,18 @@ export const getKakaoUserData = async (code: string) => { ...@@ -27,3 +27,18 @@ export const getKakaoUserData = async (code: string) => {
console.log("data=", data); console.log("data=", data);
return data.kakaoUserData; return data.kakaoUserData;
}; };
export const saveOauthKeys = async (
socialType: string,
REST_API_KEY: string,
REDIRECT_URI: string,
CLIENT_SECRET_KEY: string
) => {
const { data } = await axios.post(`${baseUrl}/auth/oauth`, {
socialType,
REST_API_KEY,
REDIRECT_URI,
CLIENT_SECRET_KEY,
});
return data;
};
import React from "react";
import { Outlet } from "react-router-dom";
import { SideBar } from "../admin/SideBar";
export const AdminLayout = () => {
return (
<div className="flex">
<SideBar />
<Outlet />
</div>
);
};
...@@ -3,3 +3,4 @@ export { BaseLayout } from "./BaseLayout"; ...@@ -3,3 +3,4 @@ export { BaseLayout } from "./BaseLayout";
export { SurveyLayout, useSurvey } from "./SurveyLayout"; export { SurveyLayout, useSurvey } from "./SurveyLayout";
export { SurveysLayout, useSurveys } from "./SurveysLayout"; export { SurveysLayout, useSurveys } from "./SurveysLayout";
export { ResultLayout } from "./ResultLayout"; export { ResultLayout } from "./ResultLayout";
export { AdminLayout } from "./AdminLayout";
...@@ -4,7 +4,7 @@ import jwt, { JwtPayload } from "jsonwebtoken"; ...@@ -4,7 +4,7 @@ import jwt, { JwtPayload } from "jsonwebtoken";
import isLength from "validator/lib/isLength"; import isLength from "validator/lib/isLength";
import isEmail from "validator/lib/isEmail"; import isEmail from "validator/lib/isEmail";
import { asyncWrap } from "../helpers"; import { asyncWrap } from "../helpers";
import { roleDb, userDb } from "../db"; import { roleDb, userDb, oauthDb } from "../db";
import { jwtCofig, envConfig, cookieConfig } from "../config"; import { jwtCofig, envConfig, cookieConfig } from "../config";
import axios from "axios"; import axios from "axios";
...@@ -183,3 +183,12 @@ export const kakaoAuthenticate = asyncWrap(async (req, res) => { ...@@ -183,3 +183,12 @@ export const kakaoAuthenticate = asyncWrap(async (req, res) => {
res.send("에러"); res.send("에러");
} }
}); });
export const saveOauthKeys = asyncWrap(async (req, res, next) => {
console.log(req.body);
try {
const oauth = await oauthDb.createSocialKey(req.body);
console.log(oauth);
return res.json(oauth);
} catch (error) {}
});
...@@ -4,3 +4,4 @@ export * as roleDb from "./role.db"; ...@@ -4,3 +4,4 @@ export * as roleDb from "./role.db";
export * as surveyDb from "./survey.db"; export * as surveyDb from "./survey.db";
export * as userDb from "./user.db"; export * as userDb from "./user.db";
export * as answerDb from "./answer.db"; export * as answerDb from "./answer.db";
export * as oauthDb from "./oauth.db";
import { Oauth, IOauth } from "../models";
export const createSocialKey = async (socialKeys: IOauth) => {
const newOauth = new Oauth({
socialType: socialKeys.socialType,
REST_API_KEY: socialKeys.REST_API_KEY,
REDIRECT_URI: socialKeys.REDIRECT_URI,
CLIENT_SECRET_KEY: socialKeys.CLIENT_SECRET_KEY,
});
const oauth = await newOauth.save();
return oauth;
};
...@@ -4,3 +4,4 @@ export { default as Role } from "./role.model"; ...@@ -4,3 +4,4 @@ export { default as Role } from "./role.model";
export { default as Survey, ISurvey } from "./survey.model"; export { default as Survey, ISurvey } from "./survey.model";
export { default as User, IUser } from "./user.model"; export { default as User, IUser } from "./user.model";
export { default as Answer, IAnswer } from "./answer.model"; export { default as Answer, IAnswer } from "./answer.model";
export { default as Oauth, IOauth } from "./oauth.model";
import { model, Schema } from "mongoose";
export interface IOauth {
socialType: string;
REST_API_KEY: string;
REDIRECT_URI: string;
CLIENT_SECRET_KEY: string;
}
const schema = new Schema<IOauth>(
{
socialType: { type: String, unique: true },
REST_API_KEY: { type: String },
REDIRECT_URI: { type: String },
CLIENT_SECRET_KEY: { type: String },
},
{ toJSON: { versionKey: false } }
);
export default model<IOauth>("Oauth", schema);
...@@ -5,9 +5,10 @@ const router = express.Router(); ...@@ -5,9 +5,10 @@ const router = express.Router();
router.route("/signup").post(authCtrl.signup); router.route("/signup").post(authCtrl.signup);
router.route("/login").post(authCtrl.login); router.route("/login").post(authCtrl.login);
// router.route("/login/kakao").get(authCtrl.kakaoLogin);
router.route("/logout").get(authCtrl.logout); router.route("/logout").get(authCtrl.logout);
router.route("/oauth").post(authCtrl.saveOauthKeys);
router.route("/oauth/kakao").post(authCtrl.kakaoAuthenticate); router.route("/oauth/kakao").post(authCtrl.kakaoAuthenticate);
export default router; export default router;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment