diff --git a/frontend/public/image/png/Stroke.png b/frontend/public/image/png/Stroke.png new file mode 100644 index 00000000..c7985435 Binary files /dev/null and b/frontend/public/image/png/Stroke.png differ diff --git a/frontend/public/image/svg/LeftArrow.svg b/frontend/public/image/svg/LeftArrow.svg new file mode 100644 index 00000000..3c586ad8 --- /dev/null +++ b/frontend/public/image/svg/LeftArrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/public/image/svg/OptionBoxStroke.svg b/frontend/public/image/svg/OptionBoxStroke.svg new file mode 100644 index 00000000..44a2b0ff --- /dev/null +++ b/frontend/public/image/svg/OptionBoxStroke.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/frontend/public/image/svg/RightArrow.svg b/frontend/public/image/svg/RightArrow.svg new file mode 100644 index 00000000..4c98ff10 --- /dev/null +++ b/frontend/public/image/svg/RightArrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/public/image/svg/historyMyOptionLine.svg b/frontend/public/image/svg/historyMyOptionLine.svg new file mode 100644 index 00000000..07d73ade --- /dev/null +++ b/frontend/public/image/svg/historyMyOptionLine.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index bb4f2cf6..a4d1e2a8 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -10,6 +10,7 @@ import { BrowserRouter, Routes, Route } from "react-router-dom"; import Home from './pages/Home'; import Login from './pages/Login'; import User from './pages/User'; +import History from './pages/History'; function App() { return ( @@ -20,6 +21,7 @@ function App() { } /> } /> } /> + } /> diff --git a/frontend/src/css/History_style.css b/frontend/src/css/History_style.css new file mode 100644 index 00000000..8b833f6a --- /dev/null +++ b/frontend/src/css/History_style.css @@ -0,0 +1,1005 @@ +/** + * Copyright 2023 kyudori, Basaeng, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + + .history-send { + background-color: #ffffff; + display: flex; + flex-direction: row; + justify-content: center; + width: 100%; + position: relative; +} + +.history-send .div { + background-color: #ffffff; + border: 1px none; + height: 1080px; + position: relative; + width: 1920px; +} + +.history-send .overlap { + background-image: url(../../public/image/svg/OptionBoxStroke.svg); + background-size: 100% 100%; + height: 882px; + left: 34px; + position: absolute; + top: 133px; + width: 572px; + border-radius: 30px; + box-shadow: 0px 4px 4px #00000040, 2px 2px 2px 1px gray; + border: 1px solid gray; +} + +.history-send .option-menu { + height: 853px; + left: 41px; + position: relative; + top: 13px; + width: 482px; +} + +.history-send .button { + height: 773px; + left: 0; + position: absolute; + top: 80px; + width: 482px; +} + +.history-send .my-pull-request { + height: 255px; + left: 0; + position: absolute; + top: 0; + width: 484px; + cursor: pointer; + transition: background-color 0.3s; +} + +.history-send .my-pull-request:active, +.history-send .my-pull-request:focus { + background-color: #f0f0f0; + transform: translateY(4px) +} + +.history-send .overlap-group { + background-color: #ffffff; + border-radius: 30px; + box-shadow: 0px 4px 4px #00000040; + height: 255px; + position: relative; + width: 482px; + box-shadow: 0px 4px 4px #00000040, 2px 2px 2px 1px gray; + border: 1px solid gray; +} + +.history-send .text-wrapper { + color: black; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 84px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 104px; + white-space: nowrap; +} + +.history-send .text-wrapper-gray { + color: #0057B8; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 84px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 104px; + white-space: nowrap; +} + +.history-send .my-repo-pr-button { + height: 255px; + left: 0; + position: absolute; + top: 259px; + width: 484px; + cursor: pointer; + transition: background-color 0.3s; +} + +.history-send .my-repo-pr-button:active, +.history-send .my-repo-pr-button:focus { + background-color: #f0f0f0; + transform: translateY(4px) +} + +.history-send .my-repo-PR { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 121px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 107px; + white-space: nowrap; +} + +.history-send .my-repo-PR-gray { + color: #0057B8; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 121px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 107px; + white-space: nowrap; +} + +.history-send .my-org-PR-button { + height: 255px; + left: 0; + position: absolute; + top: 518px; + width: 484px; + cursor: pointer; + transition: background-color 0.3s +} + +.history-send .my-org-PR-button:active, +.history-send .my-org-PR-button:focus { + background-color: #f0f0f0; + transform: translateY(4px) +} + +.history-send .text-wrapper-2 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 140px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 97px; + white-space: nowrap; +} + +.history-send .text-wrapper-2-gray { + color: #0057B8; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 140px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 97px; + white-space: nowrap; +} + +.history-send .my-option-header { + height: 61px; + left: 0; + position: absolute; + top: 0; + width: 484px; +} + +.history-send .my-option-line { + left: 0; + position: absolute; + top: 58px; + width: 100%; +} + +.history-send .my-option-line svg { + width: 100%; + height: 2px; + display: block; +} + + +.history-send .text-wrapper-3 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 40px; + font-weight: 700; + left: 10px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 0; + white-space: nowrap; +} + +.history-send .page-move-tool-bar { + height: 30px; + left: 845px; + position: absolute; + top: 1027px; + width: 286px; +} + +.history-send .page-number { + align-items: flex-start; + display: inline-flex; + gap: 33px; + left: 35px; + position: absolute; + top: 0; +} + +.history-send .text-wrapper-4 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + letter-spacing: 0; + line-height: normal; + margin-top: -1px; + position: relative; + width: 13px; + cursor: pointer; +} + +.history-send .text-wrapper-4-blue { + color: #0057B8; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + letter-spacing: 0; + line-height: normal; + margin-top: -1px; + position: relative; + width: 13px; + cursor: pointer; +} + +.history-send .text-wrapper-5 { + color: #000000; + font-family: "Inter-SemiBold", Helvetica; + font-size: 25px; + font-weight: 600; + letter-spacing: 0; + line-height: normal; + margin-top: -1px; + position: relative; + width: 16px; + cursor: pointer; +} + +.history-send .text-wrapper-6 { + color: #000000; + font-family: "Inter-SemiBold", Helvetica; + font-size: 25px; + font-weight: 600; + letter-spacing: 0; + line-height: normal; + margin-top: -1px; + position: relative; + width: 17px; + cursor: pointer; +} + +.history-send .right-arrow { + height: 22px; + left: 275px; + position: absolute; + top: 4px; + width: 13px; + cursor: pointer; +} + +.history-send .left-arrow { + height: 22px; + left: -2px; + position: absolute; + top: 4px; + width: 13px; + cursor: pointer; +} + +.history-send .overlap-2 { + height: 882px; + left: 635px; + position: absolute; + top: 134px; + width: 1236px; +} + +.history-send .history-box { + height: 882px; + left: 0; + position: absolute; + top: 0; + width: 1236px; +} + +.history-send .history { + height: 158px; + left: 0; + position: absolute; + top: 724px; + width: 1242px; +} + +.history-send .overlap-3 { + background-image: url(../../public/image/png/Stroke.png); + background-size: 100% 100%; + height: 166px; + left: -4px; + position: relative; + width: 1244px; +} + +.history-send .text-wrapper-7 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: relative; + top: 15px; + display: inline-block; +} + +.text-wrapper-7-container { + position: relative; +} + +.history-send .text-wrapper-8 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 65px; + white-space: nowrap; + + +} + +.history-send .text-wrapper-8 ::after { + content: counter(name); +} + +.history-send .text-wrapper-9 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 105px; + white-space: nowrap; +} + +.history-send .prid { + height: 26px; + left: calc(100% + 20px); + position: absolute; + top: 4px; + width: 77px; +} + +.history-send .div-wrapper { + background-color: #d9d9d9; + border-radius: 15px; + height: 26px; + position: absolute; + left: 0px; + width: 75px; +} + +.history-send .text-wrapper-10 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 50%; + transform: translateX(-50%); + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; + white-space: nowrap; +} + +.history-send .status-scan-error { + height: 27px; + left: calc(100% + 20px); + position: absolute; + top: 1px; + width: 187px; +} + +.history-send .overlap-wrapper { + height: 158px; + left: 0; + position: absolute; + top: 543px; + width: 1242px; +} + +.history-send .overlap-4 { + background-image: url(../../public/image/png/Stroke.png); + background-size: 100% 100%; + height: 166px; + left: -4px; + position: relative; + width: 1244px; +} + +.history-send .text-wrapper-11 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: relative; + top: 15px; + display: inline-block; +} + +.history-send .p { + color: transparent; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 65px; + width: 1150px; + white-space: nowrap; +} + +.history-send .span { + color: #000000; +} + +.history-send .text-wrapper-12 { + color: #0057b8; +} + +.history-send .overlap-group-wrapper { + height: 26px; + left: calc(100% + 20px); + position: absolute; + top: 4px; + width: 77px; +} + +.history-send .text-wrapper-13 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; +} + +.history-send .status-issue { + height: 27px; + left: calc(100% + 20px); + position: absolute; + top: 0px; + width: 187px; +} + +.history-send .overlap-5 { + border-radius: 5px; + height: 27px; + position: relative; + width: 300px; +} + +.history-send .text-wrapper-14 { + color: #ff0000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 18px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 1px; + width: 100%; +} + +.history-send .history-2 { + height: 158px; + left: 0; + position: absolute; + top: 362px; + width: 1242px; +} + +.history-send .overlap-6 { + background-image: url(../../public/image/png/Stroke.png); + background-size: 100% 100%; + height: 166px; + left: -4px; + position: relative; + width: 1244px; +} + +.history-send .text-wrapper-15 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: relative; + top: 15px; + display: inline-block; +} + +.history-send .prid-2 { + height: 26px; + left: calc(100% + 20px); + position: absolute; + top: 4px; + width: 77px; +} + +.history-send .text-wrapper-16 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 50%; + transform: translateX(-50%); + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; + white-space: nowrap; +} + +.history-send .status-scan { + height: 27px; + left: calc(100% + 20px); + position: absolute; + top: 0px; + width: 187px; +} + +.history-send .issue-detected { + color: #0000ff; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 10px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 1px; + width: 161px; +} + +.history-send .history-3 { + height: 158px; + left: 0; + position: absolute; + top: 181px; + width: 1242px; +} + +.history-send .overlap-7 { + background-image: url(../../public/image/png/Stroke.png); + background-size: 100% 100%; + height: 166px; + left: -4px; + position: relative; + width: 1244px; +} + +.history-send .text-wrapper-17 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: relative; + top: 15px; + display: inline-block; +} + +.history-send .prid-3 { + height: 26px; + left: calc(100% + 20px); + position: absolute; + top: 4px; + width: 77px; +} + +.history-send .text-wrapper-18 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; +} + +.history-send .status-scan-2 { + height: 27px; + left: calc(100% + 20px); + position: absolute; + top: 0px; + width: 187px; +} + +.history-send .overlap-8 { + height: 28px; + position: relative; + width: 185px; +} + +.history-send .history-4 { + height: 158px; + left: 0; + position: absolute; + top: 0; + width: 1242px; +} + +.history-send .overlap-9 { + background-image: url(../../public/image/png/Stroke.png); + background-size: 100% 100%; + height: 166px; + left: -4px; + position: relative; + width: 1244px; +} + +.history-send .text-wrapper-19 { + color: #000000; + font-family: "Inter-Bold", Helvetica; + font-size: 25px; + font-weight: 700; + left: 29px; + letter-spacing: 0; + line-height: normal; + position: relative; + top: 16px; + display: inline-block; +} + +.history-send .https-github-com-kim { + color: transparent; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 28px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 65px; + width: 800px; +} + +.history-send .prid-4 { + height: 26px; + left: calc(100% + 20px); + position: absolute; + top: 4px; + width: 77px; +} + +.history-send .text-wrapper-20 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; +} + +.history-send .status-issue-2 { + height: 27px; + left: calc(100% + 20px); + position: absolute; + top: 0px; + width: 187px; +} + + +.history-send .text-wrapper-21 { + color: #d60000cf; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 44px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 2px; + white-space: nowrap; + width: 100% +} + +.history-send .menubar-top { + height: 101px; + left: 39px; + position: absolute; + top: 8px; + width: 1842px; +} + +.history-send .menu-line { + background-color: #000000; + height: 3px; + left: 0; + position: absolute; + top: 98px; + width: 1842px; +} + +.history-send .menu { + height: 96px; + left: 0; + position: absolute; + top: 0; + width: 1848px; +} + +.history-send .overlap-11 { + height: 43px; + left: 1572px; + position: absolute; + top: 37px; + width: 272px; +} + +.history-send .profile-border { + background-color: #d9d9d9; + height: 3px; + left: 104px; + position: absolute; + top: 20px; + transform: rotate(-90deg); + width: 40px; +} + +.history-send .text-wrapper-22 { + color: #000000; + font-family: "Inter-Regular", Helvetica; + font-size: 30px; + font-weight: 400; + left: 1590px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 40px; + width: 115px; +} + +.history-send .profile { + height: 43px; + left: 136px; + position: absolute; + top: 0; + width: 135px; +} + +.history-send .overlap-group-2 { + background-color: #d9d9d9; + border-radius: 50px; + height: 43px; + position: relative; + width: 133px; +} + +.history-send .image { + height: 31px; + left: 11px; + object-fit: cover; + position: absolute; + top: 6px; + width: 35px; +} + +.history-send .text-wrapper-23 { + color: #000000; + font-family: "Inter-SemiBold", Helvetica; + font-size: 20px; + font-weight: 600; + left: 56px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 10px; + white-space: nowrap; + width: 71px; +} + +.history-send .LPVS { + height: 96px; + left: 0; + object-fit: cover; + position: absolute; + top: 0; + width: 229px; +} + +.history-send .complete { + color: rgba(0, 0, 255, 1); + font-family: Tahoma, Geneva, sans-serif; + font-size: 20px; + font-weight: 500; + letter-spacing: 0; + line-height: normal; + top: 0px; + white-space: nowrap; + width: 100%; + margin-left: 10px; + position: static; + z-index: 1; +} + +.history-send .text-wrapper-998 { + color: #000000; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + letter-spacing: 0; + line-height: normal; + top: 0; + width: 100%; + margin-left: 10px; + position: static; + right: 0; +} + +.history-send .status-label { + background-color: #ff000054; + border: 1px solid; + border-color: #ff0000; + border-radius: 5px; + height: 27px; + left: 0; + position: absolute; + top: 0; + width: 185px; +} + +.history-send .status-label-2 { + background-color: #0000ff42; + border: 1px solid; + border-color: #0000ff; + border-radius: 5px; + height: 27px; + left: 0; + position: absolute; + top: 0; + width: 185px; +} + +.history-send .status-label-3 { + background-color: rgba(255, 245, 16, 0.5); + border: 1px solid; + border-color: #F9EF00; + border-radius: 5px; + height: 27px; + width: 185px; + z-index: 1; + position: relative; +} + + +.history-send .Issue-Detected { + background-color: #ff000054; + border: 2px solid; + border-color: #ff0000; + border-radius: 5px; + height: 27px; + left: 0; + position: absolute; + top: 0; + width: 185px; +} + +.history-send .Scan-completed { + background-color: #0000ff42; + border: 2px solid; + border-color: #0000ff; + border-radius: 5px; + height: 27px; + left: 0; + position: absolute; + top: 0; + width: 185px; +} + +.history-send .Scan-Error { + background-color: rgba(255, 245, 16, 0.5); + border: 2px solid; + border-color: #3F4311; + border-radius: 5px; + height: 27px; + left: 0; + top: 0; + width: 185px; + z-index: 1; +} + +.history-send .Scan-Error-text { + color: #ff0000 !important; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 45px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 3px; + width: 100%; +} + +.history-send .Scan-completed-text { + color: #0000ff !important; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 21px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 3px; + width: 161px; +} + +.history-send .Issue-Detected-text { + color: #ff0000 !important; + font-family: "Inter-Medium", Helvetica; + font-size: 20px; + font-weight: 500; + left: 26px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 3px; + width: 100%; +} diff --git a/frontend/src/css/Home_style.css b/frontend/src/css/Home_style.css index bff757a7..ab11e0a8 100644 --- a/frontend/src/css/Home_style.css +++ b/frontend/src/css/Home_style.css @@ -173,6 +173,30 @@ width: 71px; } +.home .text-wrapper-7 { + color: #000000; + font-family: "Inter-Regular", Helvetica; + font-size: 30px; + font-weight: 400; + left: 320px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 3px; + white-space: nowrap; + width: 104px; +} + +.home .profile-border { + background-color: #d9d9d9; + height: 3px; + left: 104px; + position: absolute; + top: 20px; + transform: rotate(-90deg); + width: 40px; +} + .home .LPVS { height: 96px; left: 0; diff --git a/frontend/src/css/User_style.css b/frontend/src/css/User_style.css index f2d7dbf6..0d7fe5e9 100644 --- a/frontend/src/css/User_style.css +++ b/frontend/src/css/User_style.css @@ -220,7 +220,6 @@ white-space: nowrap; } - .user .admit-rect-2 { border: 1px solid; border-color: #000000; @@ -377,8 +376,6 @@ /* click effect eliminate border */ } - - .user .github-ID-box { height: 50px; left: 0; @@ -535,6 +532,30 @@ width: 150px; } + .user .text-wrapper-18 { + color: #000000; + font-family: "Inter-Regular", Helvetica; + font-size: 30px; + font-weight: 400; + left: 320px; + letter-spacing: 0; + line-height: normal; + position: absolute; + top: 3px; + white-space: nowrap; + width: 104px; + } + + .user .profile-border { + background-color: #d9d9d9; + height: 3px; + left: 104px; + position: absolute; + top: 20px; + transform: rotate(-90deg); + width: 40px; + } + .user .LPVS { height: 96px; left: 0; diff --git a/frontend/src/pages/History.jsx b/frontend/src/pages/History.jsx new file mode 100644 index 00000000..8be2e77e --- /dev/null +++ b/frontend/src/pages/History.jsx @@ -0,0 +1,372 @@ +/** + * Copyright 2023 kyudori, Basaeng, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +import {React,useEffect, useState} from "react"; +import axios from 'axios'; +import { Link, useParams, useLocation } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; +import "../css/History_style.css"; + +export const History= () => { + + const { type, name } = useParams(); + const [ lpvsHistories, setlpvsHistories ] = useState(); + const navigate = useNavigate(); + + const location = useLocation(); + const queryParams = new URLSearchParams(location.search); + const page = queryParams.get('page') || 0; + + + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [username, setUsername] = useState(""); + + useEffect(() => { + axios.get("/login/check") + .then((loginresponse) => { + if (loginresponse.data.isLoggedIn) { + setIsLoggedIn(loginresponse.data.isLoggedIn); + axios.get("/user/info") + .then((userInfoResponse) => { + setUsername(userInfoResponse.data); + }) + .catch(function(error) { + console.log(error.toJSON()); + navigate("/login"); + }); + } else { + navigate("/login"); + } + }) + .catch(function(error) { + console.log(error.toJSON()); + navigate("/login"); + }); + }, []); + + useEffect(() => { + axios + .get(`/history/${type}/${name}?page=${page}`) + .then((response) => { + console.log(response.data) + setlpvsHistories(response.data); + }) + .catch(function(error) { + console.log(error.toJSON()); + const userChoice = window.confirm("Please enter the GitHub ID on the User page."); + if (userChoice) { + navigate('/user/setting'); + } else { + navigate(`/history/send/${username?.nickname}?page=0`); + } + }); + }, [type, name, page]); + + const handlePageChange = (pageNumber) => { + navigate(`/history/${type}/${name}?page=${pageNumber}`); + }; + + const [isHistoriesEmpty, setIsHistoriesEmpty] = useState(false); + console.log(lpvsHistories?.lpvsHistories?.length) + useEffect(() => { + if (lpvsHistories?.lpvsHistories?.length === 0) { + setIsHistoriesEmpty(true); + } else { + setIsHistoriesEmpty(false); + } + }, [lpvsHistories, page]); + + console.log(lpvsHistories) + + const navigateToOrg = () => { + if (!username?.organization || username?.organization.trim() === "") { + window.alert("Please enter the Organization information on the User page."); + } else { + navigate(`/history/org/${username?.organization}?page=0`); + } + }; + const navigateToOwn = () => { + navigate(`/history/own/${username?.nickname}?page=0`); + }; + const navigateToSend = () => { + navigate(`/history/send/${username?.nickname}?page=0`); + }; + + const [pageCount,setPageCount] = useState(1); + const [currentPage, setCurrentPage] = useState(1); + + useEffect(()=> { + setPageCount(Math.ceil(lpvsHistories?.count/5)) + }, [lpvsHistories?.count, currentPage]); + + console.log(pageCount); + + const check_page_plus =()=> { + if(currentPage <= pageCount) { + console.log(currentPage) + return setCurrentPage(currentPage+5); + } + else { + return + } + } + console.log(page); + console.log(currentPage); + const check_page_minus =(page)=> { + if(page <=4) { + return setCurrentPage(currentPage) + } + else { + return setCurrentPage(currentPage-5); + } + } + + const trueOrFalse =(a)=> { + if(a <= pageCount) { + return true; + } + else { + return false; + } + } + + const status_check=(a)=> { + if(a) { + return 'Issue-Detected'; + } + else { + return 'Scan-completed'; + } + } + console.log(lpvsHistories?.lpvsHistories[0]?.status) + + if (!lpvsHistories) { + return
Loading...
; + } + + const pageArrow=(page)=> { + if(page<=5) { + return false; + } + } + console.log(isHistoriesEmpty) + return ( +
+
+
+
+ +
+
+
+ {type === "send" ? +
My Pull Request
+ : +
My Pull Request
} +
+
+
+
+ {type === "own" ? +
My Repo PR
+ : +
My Repo PR
} +
+
+
+
+ {type === "org" ? +
My Org PR
+ : +
My Org PR
} +
+
+
+ +
+ My option line +
My Option
+
+
+
+
+
+ { + if (page > 4) { + check_page_minus(); + handlePageChange(currentPage - 2); + }}} style={{ cursor: "pointer" }} /> + {trueOrFalse(currentPage) &&
handlePageChange(currentPage-1)}>{currentPage}
} + {trueOrFalse(currentPage+1) &&
handlePageChange(currentPage)}>{currentPage+1}
} + {trueOrFalse(currentPage+2) &&
handlePageChange(currentPage+1)}>{currentPage+2}
} + {trueOrFalse(currentPage+3) &&
handlePageChange(currentPage+2)}>{currentPage+3}
} + {trueOrFalse(currentPage+4) &&
handlePageChange(currentPage+3)}>{currentPage+4}
} + {trueOrFalse(currentPage+5) ? {check_page_plus(); handlePageChange(currentPage + 4); }}style={{ cursor: "pointer" }}/> + : + } +
+
+
+
+ {lpvsHistories.lpvsHistories[4]?.status !== undefined ? ( + +
+
+ +
+ {lpvsHistories.lpvsHistories[4]?.repositoryName} +
+
+
+ {status_check(lpvsHistories.lpvsHistories[4]?.hasIssue)} +
+
+
+
+
{lpvsHistories.lpvsHistories[4]?.pullNumber}
+
+
+
+
+
+ +
{lpvsHistories.lpvsHistories[4]?.url}
+
{lpvsHistories.lpvsHistories[4]?.scanDate}
+
+
): null} + + {lpvsHistories.lpvsHistories[3]?.status !== undefined ? ( + +
+
+
+ {lpvsHistories.lpvsHistories[3]?.repositoryName} +
+
+
{status_check(lpvsHistories.lpvsHistories[3]?.hasIssue)}
+
+
+
+
+
{lpvsHistories.lpvsHistories[3]?.pullNumber}
+
+
+ +
+
+
{lpvsHistories.lpvsHistories[3]?.url}
+
{lpvsHistories.lpvsHistories[3]?.scanDate}
+
+
+ ): null} + + {lpvsHistories.lpvsHistories[2]?.status !== undefined ? ( + +
+
+
+ {lpvsHistories.lpvsHistories[2]?.repositoryName} +
+
+
{status_check(lpvsHistories.lpvsHistories[2]?.hasIssue)}
+
+
+
+
+
{lpvsHistories.lpvsHistories[2]?.pullNumber}
+
+
+
+
+
{lpvsHistories.lpvsHistories[2]?.url}
+
{lpvsHistories.lpvsHistories[2]?.scanDate}
+
+
+ + ): null} + + {lpvsHistories.lpvsHistories[1]?.status !== undefined ? ( + +
+
+
+ {lpvsHistories.lpvsHistories[1]?.repositoryName} +
+
+
{status_check(lpvsHistories.lpvsHistories[1]?.hasIssue)}
+
+
+
+
+
{lpvsHistories.lpvsHistories[1]?.pullNumber}
+
+
+
+
+
{lpvsHistories.lpvsHistories[1]?.url}
+
{lpvsHistories.lpvsHistories[1]?.scanDate}
+
+
+ + ) : null} + {lpvsHistories.lpvsHistories[0]?.status !== undefined ? ( + +
+
+
+ {lpvsHistories.lpvsHistories[0]?.repositoryName} +
+
+
{status_check(lpvsHistories.lpvsHistories[0]?.hasIssue)}
+
+
+
+
+
{lpvsHistories.lpvsHistories[0]?.pullNumber}
+
+
+
+
+
{lpvsHistories.lpvsHistories[0]?.url}
+
{lpvsHistories.lpvsHistories[0]?.scanDate}
+
+
+ + ): null} + +
+
+
+
+
+
+
+
+
+ Image +
{username.name}
+
+
+
+
+ History + +
+ + img + +
+
+
+
+ ); +}; + +export default History; diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index d68d2982..86e19771 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -11,120 +11,118 @@ import { Link } from "react-router-dom"; import "../css/Home_style.css"; export const LPVS_SERVER = process.env.REACT_APP_LPVS_SERVER; + export const Home = () => { - const [isLoggedIn, setIsLoggedIn] = useState(false); - const [username, setUsername] = useState(""); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [username, setUsername] = useState(""); - useEffect(() => { - axios.get("/login/check") - .then((loginresponse) => { - if (loginresponse.data.isLoggedIn) { - setIsLoggedIn(loginresponse.data.isLoggedIn); - axios.get("/user/info").then((userInfoResponse) => { - setUsername(userInfoResponse.data); - }); - } - }) - .catch(function(error) { - console.log(error.toJSON()); - }); - }, []); + useEffect(() => { + axios.get("/login/check") + .then((loginresponse) => { + if (loginresponse.data.isLoggedIn) { + setIsLoggedIn(loginresponse.data.isLoggedIn); + axios.get("/user/info").then((userInfoResponse) => { + setUsername(userInfoResponse.data); + }); + } + }) + .catch(function(error) { + console.log(error.toJSON()); + }); + }, []); - function truncateName(name) { - if (/[\u3131-\u314e\u314f-\u3163\uac00-\ud7a3]/g.test(name)) { - return name.length > 3 ? `${name.substring(0, 3)}.` : name; - } else { - return name.length > 5 ? `${name.substring(0, 5)}.` : name; + function truncateName(name) { + if (/[\u3131-\u314e\u314f-\u3163\uac00-\ud7a3]/g.test(name)) { + return name.length > 3 ? `${name.substring(0, 3)}.` : name; + } else { + return name.length > 5 ? `${name.substring(0, 5)}.` : name; + } } - } - return ( -
-
-
-
-
-

Welcome to the License Pre-Validation Service (LPVS).

-

Usage Procedure

-
    -
  1. Sign up and Login to the service.
  2. -
  3. Go to user information page, enter your GitHub ID (required) and Organization Name (optional), then click the "Admit" button.
  4. -
  5. Login to GitHub using the GitHub ID you entered in step 2.
  6. -
  7. To configure the repository for license validation, follow these steps:
  8. -
      -
    1. Go to the repository you want to validation.
    2. -
    3. Navigate to Settings -{">"} Webhooks -{">"} Add Webhooks.
    4. -
    5. Enter 'http://{"<"}IP where LPVS is running:7896/webhooks{">"}' in the Payload URL field.
    6. -
    7. Select 'application/json' for Content Type.
    8. -
    9. Enter 'LPVS' in the Secret field.
    10. -
    11. Under "Which events would you like to trigger this webhook?", select 'Let me select individual events.' and check only the 'Pull Request' option.
    12. -
    13. Click the green 'Add webhook' button.
    14. -
    -
  9. After completing the webhook setup for the repository, create a Pull Request on that repository to see the results of license validation.
  10. -
-

Important Notes

-
    -
  • If you enter a GitHub ID that is already used by someone else in your user information, it will not be reflected.
  • -
  • This service is only available for Public Repository.
  • -
  • Webhook settings are mandatory for using this service.
  • -
-
-
-
-
- - img - -
- License
- Pre
- Validation
- Service -
-
About
-
-
-
-
-
-
-
-
- img -
- {isLoggedIn ? ( - - - {username?.name ? ( -
{truncateName(username.name)}
- ) : ( -
Loading...
- )} - -
- ) : ( - - Login - - )} -
+ return ( +
+
+
+
+
+

Welcome to the License Pre-Validation Service (LPVS).

+

Usage Procedure

+
    +
  1. Sign up and Login to the service.
  2. +
  3. Go to user information page, enter your GitHub ID (required) and Organization Name (optional), then click the "Admit" button.
  4. +
  5. Login to GitHub using the GitHub ID you entered in step 2.
  6. +
  7. To configure the repository for license validation, follow these steps:
  8. +
      +
    1. Go to the repository you want to validation.
    2. +
    3. Navigate to Settings -{">"} Webhooks -{">"} Add Webhooks.
    4. +
    5. Enter 'http://{"<"}IP where LPVS is running:7896/webhooks{">"}' in the Payload URL field.
    6. +
    7. Select 'application/json' for Content Type.
    8. +
    9. Enter 'LPVS' in the Secret field.
    10. +
    11. Under "Which events would you like to trigger this webhook?", select 'Let me select individual events.' and check only the 'Pull Request' option.
    12. +
    13. Click the green 'Add webhook' button.
    14. +
    +
  9. After completing the webhook setup for the repository, create a Pull Request on that repository to see the results of license validation.
  10. +
+

Important Notes

+
    +
  • If you enter a GitHub ID that is already used by someone else in your user information, it will not be reflected.
  • +
  • This service is only available for Public Repository.
  • +
  • Webhook settings are mandatory for using this service.
  • +
+
+
+
+
+ + img + +
+ License
+ Pre
+ Validation
+ Service +
+
About
+
+
+
+
+
+ {isLoggedIn ?
: null} +
+
+ img +
+ {isLoggedIn ? ( + + + {username?.name ?
{truncateName(username.name)}
:
Loading...
} + +
+ ) : ( + + Login + + )} +
+
+
+
+
+ {isLoggedIn ? ( + + History + + ) : null} +
+
+ + img +
-
-
- - img -
-
-
- ); + ); }; export default Home; diff --git a/frontend/src/pages/User.jsx b/frontend/src/pages/User.jsx index c85b7f80..414e8c1c 100644 --- a/frontend/src/pages/User.jsx +++ b/frontend/src/pages/User.jsx @@ -109,6 +109,17 @@ export const User = () => { })); }; + const handleHistoryLinkClick = (event) => { + event.preventDefault(); + + if (!userInfo?.nickname) { + alert('To use service, You must enter a GitHub ID.'); + navigate('/user/setting'); + } else { + navigate(`/history/send/${userInfo.nickname}`); + } + }; + const handleLogoClick = (event) => { event.preventDefault(); @@ -255,6 +266,7 @@ export const User = () => {
+
Image @@ -275,6 +287,14 @@ export const User = () => {
+
+ + History + +
customAttribute = customAttribute(attributes, userNameAttributeName, memberProfile, registrationId); diff --git a/src/main/java/com/lpvs/controller/LPVSWebController.java b/src/main/java/com/lpvs/controller/LPVSWebController.java index 2e17b7c8..4de264ed 100644 --- a/src/main/java/com/lpvs/controller/LPVSWebController.java +++ b/src/main/java/com/lpvs/controller/LPVSWebController.java @@ -7,24 +7,39 @@ package com.lpvs.controller; -import com.lpvs.entity.LPVSLoginMember; -import com.lpvs.entity.LPVSMember; +import com.lpvs.entity.*; +import com.lpvs.entity.history.HistoryEntity; +import com.lpvs.entity.history.HistoryPageEntity; +import com.lpvs.entity.history.LPVSHistory; +import com.lpvs.entity.result.LPVSResult; +import com.lpvs.entity.result.LPVSResultFile; +import com.lpvs.entity.result.LPVSResultInfo; import com.lpvs.repository.LPVSDetectedLicenseRepository; import com.lpvs.repository.LPVSLicenseRepository; import com.lpvs.repository.LPVSMemberRepository; import com.lpvs.repository.LPVSPullRequestRepository; import com.lpvs.service.LPVSLoginCheckService; -import org.springframework.beans.factory.annotation.Value; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; @Controller +@Slf4j public class LPVSWebController implements ErrorController { private LPVSMemberRepository memberRepository; private LPVSDetectedLicenseRepository detectedLicenseRepository; @@ -54,7 +69,6 @@ public LPVSMember personalInfoSettings(Authentication authentication) { public LPVSLoginMember loginMember(Authentication authentication) { Map oauthLoginMemberMap = lpvsLoginCheckService.getOauthLoginMemberMap(authentication); boolean isLoggedIn = oauthLoginMemberMap == null || oauthLoginMemberMap.isEmpty(); - if (!isLoggedIn) { LPVSMember findMember = lpvsLoginCheckService.getMemberFromMemberMap(authentication); return new LPVSLoginMember(!isLoggedIn, findMember); @@ -77,6 +91,37 @@ public ResponseEntity postSettingTest(@RequestBody Map prPage = historyPageEntity.getPrPage(); + Long count = historyPageEntity.getCount(); + + List lpvsHistories = new ArrayList<>(); + List lpvsPullRequests = prPage.getContent(); + + for (LPVSPullRequest pr : lpvsPullRequests) { + String[] pullNumberTemp = pr.getPullRequestUrl().split("/"); + LocalDateTime localDateTime = new Timestamp(pr.getDate().getTime()).toLocalDateTime(); + String formattingDateTime = lpvsLoginCheckService.dateTimeFormatting(localDateTime); + + Boolean hasIssue = detectedLicenseRepository.existsIssue(pr); + + lpvsHistories.add(new LPVSHistory(formattingDateTime, pr.getRepositoryName(), pr.getId(), + pr.getPullRequestUrl(), pr.getStatus(), pr.getSender(), + pullNumberTemp[pullNumberTemp.length-2] + "/" + + pullNumberTemp[pullNumberTemp.length-1], hasIssue)); + } + + HistoryEntity historyEntity = new HistoryEntity(lpvsHistories, count); + return historyEntity; + } + @GetMapping("error") public String redirect(){ return "index.html"; diff --git a/src/main/java/com/lpvs/entity/LPVSMember.java b/src/main/java/com/lpvs/entity/LPVSMember.java index e4690ee6..68eab363 100644 --- a/src/main/java/com/lpvs/entity/LPVSMember.java +++ b/src/main/java/com/lpvs/entity/LPVSMember.java @@ -63,9 +63,4 @@ public void setOrganization(String organization) { this.organization = organization; } - public void setJoin(String name, String email, String provider) { - this.name = name; - this.email = email; - this.provider = provider; - } } diff --git a/src/main/java/com/lpvs/entity/LPVSPullRequest.java b/src/main/java/com/lpvs/entity/LPVSPullRequest.java index 39a98a3f..9179416c 100644 --- a/src/main/java/com/lpvs/entity/LPVSPullRequest.java +++ b/src/main/java/com/lpvs/entity/LPVSPullRequest.java @@ -45,6 +45,15 @@ public class LPVSPullRequest implements Serializable { @Column(name = "status") private String status; + @Column(name = "pull_request_head") + private String pullRequestHead; + + @Column(name = "pull_request_base") + private String pullRequestBase; + + @Column(name = "sender") + private String sender; + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/com/lpvs/entity/LPVSQueue.java b/src/main/java/com/lpvs/entity/LPVSQueue.java index abea0c4f..688e7b7c 100644 --- a/src/main/java/com/lpvs/entity/LPVSQueue.java +++ b/src/main/java/com/lpvs/entity/LPVSQueue.java @@ -57,6 +57,14 @@ public class LPVSQueue implements Serializable { @Column(name = "commit_sha", columnDefinition = "LONGTEXT") private String headCommitSHA; + @Column(name = "pull_request_head") + private String pullRequestHead; + + @Column(name = "pull_request_base") + private String pullRequestBase; + + @Column(name = "sender") + private String sender; @Transient private String repositoryLicense; diff --git a/src/main/java/com/lpvs/entity/history/HistoryEntity.java b/src/main/java/com/lpvs/entity/history/HistoryEntity.java new file mode 100644 index 00000000..312c6021 --- /dev/null +++ b/src/main/java/com/lpvs/entity/history/HistoryEntity.java @@ -0,0 +1,20 @@ +/** + * Copyright 2023 Basaeng, kyudori, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.history; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class HistoryEntity { + private List lpvsHistories; + private Long count; +} diff --git a/src/main/java/com/lpvs/entity/history/HistoryPageEntity.java b/src/main/java/com/lpvs/entity/history/HistoryPageEntity.java new file mode 100644 index 00000000..41c0335f --- /dev/null +++ b/src/main/java/com/lpvs/entity/history/HistoryPageEntity.java @@ -0,0 +1,19 @@ +/** + * Copyright 2023 Basaeng, kyudori, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.history; + +import com.lpvs.entity.LPVSPullRequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.data.domain.Page; + +@Getter @AllArgsConstructor +public class HistoryPageEntity { + private Page prPage; + private Long count; +} diff --git a/src/main/java/com/lpvs/entity/history/LPVSHistory.java b/src/main/java/com/lpvs/entity/history/LPVSHistory.java new file mode 100644 index 00000000..2014b3fc --- /dev/null +++ b/src/main/java/com/lpvs/entity/history/LPVSHistory.java @@ -0,0 +1,24 @@ +/** + * Copyright 2023 Basaeng, kyudori, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.history; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter @AllArgsConstructor +public class LPVSHistory { + private String scanDate; + private String repositoryName; + private Long pullRequestId; + private String url; + private String status; + private String sender; + private String pullNumber; // pull/number + private Boolean hasIssue; +} diff --git a/src/main/java/com/lpvs/entity/result/LPVSResult.java b/src/main/java/com/lpvs/entity/result/LPVSResult.java new file mode 100644 index 00000000..9656643b --- /dev/null +++ b/src/main/java/com/lpvs/entity/result/LPVSResult.java @@ -0,0 +1,23 @@ +package com.lpvs.entity.result; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +@Setter +@Getter +@AllArgsConstructor +public class LPVSResult { + private List lpvsResultFileList; + private LPVSResultInfo lpvsResultInfo; + private Long count; + + private Map licenseCountMap; + + private String pullNumber; + + private Boolean hasIssue; +} diff --git a/src/main/java/com/lpvs/entity/result/LPVSResultFile.java b/src/main/java/com/lpvs/entity/result/LPVSResultFile.java new file mode 100644 index 00000000..f93f4a85 --- /dev/null +++ b/src/main/java/com/lpvs/entity/result/LPVSResultFile.java @@ -0,0 +1,17 @@ +package com.lpvs.entity.result; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter @AllArgsConstructor +public class LPVSResultFile { + + private Long id; + private String path; + private String componentFileUrl; + private String matchLine; + private String matchValue; + + private String status; //license.licenseUsage + private String licenseSpdx; //license +} diff --git a/src/main/java/com/lpvs/entity/result/LPVSResultInfo.java b/src/main/java/com/lpvs/entity/result/LPVSResultInfo.java new file mode 100644 index 00000000..1380957c --- /dev/null +++ b/src/main/java/com/lpvs/entity/result/LPVSResultInfo.java @@ -0,0 +1,18 @@ +package com.lpvs.entity.result; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter @Setter @AllArgsConstructor +public class LPVSResultInfo { + + private Long id; + private Date scanDate; + private String repositoryName; + private String status; + private List detectedLicenses; +} diff --git a/src/main/java/com/lpvs/exception/PageControllerAdvice.java b/src/main/java/com/lpvs/exception/PageControllerAdvice.java index a97a365e..2010a19a 100644 --- a/src/main/java/com/lpvs/exception/PageControllerAdvice.java +++ b/src/main/java/com/lpvs/exception/PageControllerAdvice.java @@ -26,6 +26,13 @@ public ResponseEntity loginFailedHandle(LoginFailedException e) { return new ResponseEntity<>(errorResponse, HttpStatus.UNAUTHORIZED); } + @ExceptionHandler(WrongAccessException.class) + public ResponseEntity wrongAccessHandle(WrongAccessException e) { + log.error("wrongAccess"); + errorResponse = new ErrorResponse(e.getMessage(), HttpStatus.FORBIDDEN.name(), HttpStatus.FORBIDDEN.value()); + return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN); + } + @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleSQLException(IllegalArgumentException e) { log.error("duplicated key exception" + e.getMessage()); diff --git a/src/main/java/com/lpvs/exception/WrongAccessException.java b/src/main/java/com/lpvs/exception/WrongAccessException.java new file mode 100644 index 00000000..3044343f --- /dev/null +++ b/src/main/java/com/lpvs/exception/WrongAccessException.java @@ -0,0 +1,15 @@ +/** + * Copyright 2023 Basaeng, kyudori, hwan5180, quswjdgma83 + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.exception; + +public class WrongAccessException extends RuntimeException { + + public WrongAccessException(String message) { + super(message); + } +} diff --git a/src/main/java/com/lpvs/repository/LPVSDetectedLicenseRepository.java b/src/main/java/com/lpvs/repository/LPVSDetectedLicenseRepository.java index 3a9cdea6..da713c58 100644 --- a/src/main/java/com/lpvs/repository/LPVSDetectedLicenseRepository.java +++ b/src/main/java/com/lpvs/repository/LPVSDetectedLicenseRepository.java @@ -8,7 +8,25 @@ package com.lpvs.repository; import com.lpvs.entity.LPVSDetectedLicense; +import com.lpvs.entity.LPVSLicense; +import com.lpvs.entity.LPVSPullRequest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface LPVSDetectedLicenseRepository extends JpaRepository { + @Query(value = "select count(dl)>0 from LPVSDetectedLicense dl where dl.issue = True and dl.pullRequest = :pr") + Boolean existsIssue(@Param("pr") LPVSPullRequest pr); + + List findByPullRequest(LPVSPullRequest lpvsPullRequest); + Page findByPullRequest(LPVSPullRequest lpvsPullRequest, Pageable pageable); + + + @Query(value = "select count(*) from LPVSDetectedLicense dl where dl.pullRequest = :pr and dl.license is not null") + Long CountByDetectedLicenseWherePullRequestId(@Param("pr") LPVSPullRequest pr); + } diff --git a/src/main/java/com/lpvs/repository/LPVSLicenseRepository.java b/src/main/java/com/lpvs/repository/LPVSLicenseRepository.java index b99580e6..6f0680aa 100644 --- a/src/main/java/com/lpvs/repository/LPVSLicenseRepository.java +++ b/src/main/java/com/lpvs/repository/LPVSLicenseRepository.java @@ -26,4 +26,5 @@ public interface LPVSLicenseRepository extends CrudRepository @Query(value = "SELECT * FROM licenses WHERE licenses.license_alternative_names LIKE %:licenseName% ORDER BY id DESC LIMIT 1", nativeQuery = true) LPVSLicense searchByAlternativeLicenseNames(@Param("licenseName") String licenseName); + } diff --git a/src/main/java/com/lpvs/repository/LPVSPullRequestRepository.java b/src/main/java/com/lpvs/repository/LPVSPullRequestRepository.java index 56388514..d0b0c375 100644 --- a/src/main/java/com/lpvs/repository/LPVSPullRequestRepository.java +++ b/src/main/java/com/lpvs/repository/LPVSPullRequestRepository.java @@ -8,12 +8,41 @@ package com.lpvs.repository; import com.lpvs.entity.LPVSPullRequest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.Date; public interface LPVSPullRequestRepository extends JpaRepository { @Query(value = "SELECT now();", nativeQuery = true) Date getNow(); + + @Query(value = "select pr from LPVSPullRequest pr where pr.repositoryName like :name%") + Page findPullRequestByNameLike(@Param("name") String name, Pageable pageable); + + @Query(value = "select count(*) from LPVSPullRequest pr where pr.repositoryName like :name%") + Long CountByPullRequestWhereNameLike(@Param("name") String name); + + @Query(value = "select pr from LPVSPullRequest pr where pr.sender = :name") + Page findBySender(@Param("name") String name, Pageable pageable); + + @Query(value = "select count(*) from LPVSPullRequest pr where pr.sender = :name") + Long CountBySender(@Param("name") String name); + + @Query(value = "select pr from LPVSPullRequest pr where pr.pullRequestBase = :name") + Page findByPullRequestBase(@Param("name") String name, Pageable pageable); + + @Query(value = "select count(*) from LPVSPullRequest pr where pr.pullRequestBase = :name") + Long CountByPullRequestBase(@Param("name") String name); + + @Query(value = "select pr from LPVSPullRequest pr where pr.sender = :name or pr.pullRequestHead = :name") + Page findBySenderOrPullRequestHead(@Param("name") String name, Pageable pageable); + + @Query(value = "select count(*) from LPVSPullRequest pr where pr.sender = :name or pr.pullRequestHead = :name") + Long CountBySenderOrPullRequestHead(@Param("name") String name); + + } diff --git a/src/main/java/com/lpvs/service/LPVSLoginCheckService.java b/src/main/java/com/lpvs/service/LPVSLoginCheckService.java index bb6adab5..24a299db 100644 --- a/src/main/java/com/lpvs/service/LPVSLoginCheckService.java +++ b/src/main/java/com/lpvs/service/LPVSLoginCheckService.java @@ -8,16 +8,21 @@ package com.lpvs.service; import com.lpvs.entity.LPVSMember; +import com.lpvs.entity.LPVSPullRequest; +import com.lpvs.entity.history.HistoryPageEntity; import com.lpvs.exception.LoginFailedException; +import com.lpvs.exception.WrongAccessException; import com.lpvs.repository.LPVSMemberRepository; import com.lpvs.repository.LPVSPullRequestRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Map; -import java.util.Optional; @Service public class LPVSLoginCheckService { @@ -46,22 +51,41 @@ public void loginVerification(Authentication authentication) { } } - @Transactional public LPVSMember getMemberFromMemberMap(Authentication authentication) { Map memberMap = getOauthLoginMemberMap(authentication); - String name = (String) memberMap.get("name"); String email = (String) memberMap.get("email"); String provider = (String) memberMap.get("provider"); - Optional findMemberOptional = memberRepository.findByEmailAndProvider(email, provider); + LPVSMember findMember = memberRepository.findByEmailAndProvider(email, provider).get(); - if (findMemberOptional.isPresent()) { - return findMemberOptional.get(); + return findMember; + } + + public HistoryPageEntity pathCheck(String type, String name, + Pageable pageable, Authentication authentication) { + + loginVerification(authentication); + LPVSMember findMember = getMemberFromMemberMap(authentication); + String findNickName = findMember.getNickname(); + String findOrganization = findMember.getOrganization(); + Page prPage; + Long count; + + if ((type.equals("own") && findNickName.equals(name)) || + (type.equals("org") && findOrganization.equals(name))) { + prPage = lpvsPullRequestRepository.findByPullRequestBase(name, pageable); + count = lpvsPullRequestRepository.CountByPullRequestBase(name); + } else if (type.equals("send") && findNickName.equals(name)) { + prPage = lpvsPullRequestRepository.findBySenderOrPullRequestHead(name, pageable); + count = lpvsPullRequestRepository.CountBySenderOrPullRequestHead(name); } else { - LPVSMember newMember = new LPVSMember(); - newMember.setJoin(name, email, provider); - memberRepository.save(newMember); - return newMember; + throw new WrongAccessException("WrongAccessException"); } + + return new HistoryPageEntity(prPage, count); + } + + public String dateTimeFormatting(LocalDateTime localDateTime) { + return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } } diff --git a/src/main/java/com/lpvs/service/LPVSQueueService.java b/src/main/java/com/lpvs/service/LPVSQueueService.java index b1df41bd..c9c27661 100644 --- a/src/main/java/com/lpvs/service/LPVSQueueService.java +++ b/src/main/java/com/lpvs/service/LPVSQueueService.java @@ -97,6 +97,9 @@ public void checkForQueue() throws InterruptedException { pullRequest.setRepositoryName(LPVSWebhookUtil.getRepositoryOrganization(webhook) + "/" + LPVSWebhookUtil.getRepositoryName(webhook)); pullRequest.setDate(webhook.getDate()); pullRequest.setStatus(LPVSPullRequestStatus.NO_ACCESS.toString()); + pullRequest.setPullRequestHead(webhook.getPullRequestHead()); + pullRequest.setPullRequestBase(webhook.getPullRequestBase()); + pullRequest.setSender(webhook.getSender()); pullRequest = lpvsPullRequestRepository.saveAndFlush(pullRequest); if (webhook.getUserId().equals("GitHub hook")) { @@ -136,6 +139,9 @@ public void processWebHook(LPVSQueue webhookConfig) throws IOException { pullRequest.setRepositoryName(LPVSWebhookUtil.getRepositoryOrganization(webhookConfig) + "/" + LPVSWebhookUtil.getRepositoryName(webhookConfig)); pullRequest.setDate(webhookConfig.getDate()); pullRequest.setStatus(LPVSPullRequestStatus.SCANNING.toString()); + pullRequest.setPullRequestHead(webhookConfig.getPullRequestHead()); + pullRequest.setPullRequestBase(webhookConfig.getPullRequestBase()); + pullRequest.setSender(webhookConfig.getSender()); pullRequest = lpvsPullRequestRepository.saveAndFlush(pullRequest); log.debug("ID: " + pullRequest.getId() + " " + pullRequest.toString()); diff --git a/src/main/java/com/lpvs/util/LPVSWebhookUtil.java b/src/main/java/com/lpvs/util/LPVSWebhookUtil.java index d237b471..35451bc0 100644 --- a/src/main/java/com/lpvs/util/LPVSWebhookUtil.java +++ b/src/main/java/com/lpvs/util/LPVSWebhookUtil.java @@ -38,6 +38,10 @@ public static LPVSQueue getGitHubWebhookConfig(String payload) { webhookConfig.setHeadCommitSHA(json.getAsJsonObject("pull_request") .getAsJsonObject("head") .get("sha").getAsString()); + + webhookConfig.setPullRequestBase(json.getAsJsonObject("pull_request").getAsJsonObject("base").getAsJsonObject("repo").getAsJsonObject("owner").get("login").getAsString()); + webhookConfig.setPullRequestHead(json.getAsJsonObject("pull_request").getAsJsonObject("head").getAsJsonObject("repo").getAsJsonObject("owner").get("login").getAsString()); + webhookConfig.setSender(json.getAsJsonObject("sender").get("login").getAsString()); webhookConfig.setAttempts(0); return webhookConfig; } diff --git a/src/main/resources/database_dump.sql b/src/main/resources/database_dump.sql index f03ed74c..ad61453e 100644 --- a/src/main/resources/database_dump.sql +++ b/src/main/resources/database_dump.sql @@ -90,6 +90,9 @@ CREATE TABLE `pull_requests` ( `url` longtext NOT NULL, `diff_url` longtext, `status` varchar(255) DEFAULT NULL, + `pull_request_head` varchar(255) NOT NULL, + `pull_request_base` varchar(255) NOT NULL, + `sender` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java b/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java index 254a9e81..039981ab 100644 --- a/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java +++ b/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022, Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2023, Samsung Electronics Co., Ltd. All rights reserved. * * Use of this source code is governed by a MIT license that can be * found in the LICENSE file. @@ -76,8 +76,18 @@ public void okTest() { "}, " + "\"pull_request\": {" + "\"html_url\": \"https://github.com/Samsung/LPVS/pull/18\", " + + "\"base\": {" + + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"Samsung\"" + + "}" + + "}" + + "}," + "\"head\": {" + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"o-kopysov\"" + + "}," + "\"fork\": true, " + "\"html_url\": \"https://github.com/o-kopysov/LPVS/tree/utests\"" + "}, " + @@ -85,6 +95,9 @@ public void okTest() { "\"ref\": \"o-kopysov:utests\"" + "}, " + "\"url\": \"https://api.github.com/repos/Samsung/LPVS/pulls/18\"" + + "}," + + "\"sender\": {" + + "\"login\": \"o-kopysov\"" + "}" + "}"; diff --git a/src/test/java/com/lpvs/entity/LPVSPullRequestTest.java b/src/test/java/com/lpvs/entity/LPVSPullRequestTest.java index 0ee2feb0..a9fdf7e1 100644 --- a/src/test/java/com/lpvs/entity/LPVSPullRequestTest.java +++ b/src/test/java/com/lpvs/entity/LPVSPullRequestTest.java @@ -25,6 +25,10 @@ public class LPVSPullRequestTest { final String pullRequestUrl = "pulRequestUrl"; final String pullRequestFilesUrl = "pullRequestFileUrl"; final String status = "status"; + final String pullRequestBase = "user"; + final String pullRequestHead = "user"; + final String sender = "user"; + @BeforeEach void setUp() { @@ -34,7 +38,10 @@ void setUp() { repositoryName, pullRequestUrl, pullRequestFilesUrl, - status); + status, + pullRequestBase, + pullRequestHead, + sender); } @Test diff --git a/src/test/java/com/lpvs/util/WebHookUtilTest.java b/src/test/java/com/lpvs/util/WebHookUtilTest.java index 1cdfa3b0..6ce62140 100644 --- a/src/test/java/com/lpvs/util/WebHookUtilTest.java +++ b/src/test/java/com/lpvs/util/WebHookUtilTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022, Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2023, Samsung Electronics Co., Ltd. All rights reserved. * * Use of this source code is governed by a MIT license that can be * found in the LICENSE file. @@ -34,8 +34,18 @@ void setUp() { "}, " + "\"pull_request\": {" + "\"html_url\": \"https://github.com/Samsung/LPVS/pull/18\", " + + "\"base\": {" + + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"Samsung\"" + + "}" + + "}" + + "}, " + "\"head\": {" + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"o-kopysov\"" + + "}," + "\"fork\": true, " + "\"html_url\": \"https://github.com/o-kopysov/LPVS/tree/utests\"" + "}, " + @@ -43,6 +53,9 @@ void setUp() { "\"ref\": \"o-kopysov:utests\"" + "}, " + "\"url\": \"https://api.github.com/repos/Samsung/LPVS/pulls/18\"" + + "}," + + "\"sender\": {" + + "\"login\": \"o-kopysov\"" + "}" + "}"; @@ -53,6 +66,9 @@ void setUp() { expected.setPullRequestAPIUrl("https://api.github.com/repos/Samsung/LPVS/pulls/18"); expected.setRepositoryUrl("https://github.com/Samsung/LPVS"); expected.setUserId("GitHub hook"); + expected.setPullRequestBase("Samsung"); + expected.setPullRequestHead("o-kopysov"); + expected.setSender("o-kopysov"); expected.setHeadCommitSHA("edde69ecb8e8a88dde09fa9789e2c9cab7cf7cf9"); expected.setAttempts(0); } @@ -82,8 +98,18 @@ void setUp() { "}, " + "\"pull_request\": {" + "\"html_url\": \"https://github.com/Samsung/LPVS/pull/18\", " + + "\"base\": {" + + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"Samsung\"" + + "}" + + "}" + + "}, " + "\"head\": {" + "\"repo\": {" + + "\"owner\": {" + + "\"login\": \"o-kopysov\"" + + "}," + "\"fork\": false, " + "\"html_url\": \"https://github.com/o-kopysov/LPVS/tree/utests\"" + "}, " + @@ -91,6 +117,9 @@ void setUp() { "\"ref\": \"o-kopysov:utests\"" + "}, " + "\"url\": \"https://api.github.com/repos/Samsung/LPVS/pulls/18\"" + + "}," + + "\"sender\": {" + + "\"login\": \"o-kopysov\"" + "}" + "}"; @@ -101,6 +130,9 @@ void setUp() { expected.setPullRequestAPIUrl("https://api.github.com/repos/Samsung/LPVS/pulls/18"); expected.setRepositoryUrl("https://github.com/Samsung/LPVS"); expected.setUserId("GitHub hook"); + expected.setPullRequestBase("Samsung"); + expected.setPullRequestHead("o-kopysov"); + expected.setSender("o-kopysov"); expected.setHeadCommitSHA("edde69ecb8e8a88dde09fa9789e2c9cab7cf7cf9"); expected.setAttempts(0); }