LoginLogout

This commit is contained in:
Kilian Hofmann 2024-07-21 15:49:43 +02:00
parent 132e8790a3
commit 8d91e805dd
10 changed files with 293 additions and 51 deletions

View File

@ -2,11 +2,25 @@
namespace Api\Login;
use Exception;
use Khofmann\Input\Input;
class Login
{
public function post()
{
echo "LOGIN HANDLER post";
print_r(input()->all());
try {
$response = \Khofmann\Models\User\User::logIn(Input::post("email"), Input::post("password"));
return json_encode($response);
} catch (Exception $err) {
switch ($err->getMessage()) {
case "Failed":
throw new Exception("Login failed", 500);
case "NotFound":
throw new Exception("User not Found", 404);
case "Invalid":
throw new Exception("Invalid Username or Password", 401);
}
}
}
}

View File

@ -2,11 +2,13 @@
namespace Api\Logout;
use \Khofmann\Models\User\User;
class Logout
{
public function post()
{
echo "LOGOUT HANDLER post";
print_r(input()->all());
$token = request()->getHeader("token");
return json_decode(User::getByToken($token)->logOut($token));
}
}

View File

@ -28,7 +28,7 @@ paths:
Success:
value: true
401:
description: Failed
description: Invalid credentials
content:
application/json:
schema:
@ -37,7 +37,7 @@ paths:
Invalid Username or Password:
value: { "message": "Invalid Username or Password" }
404:
description: Failed
description: User not Found
content:
application/json:
schema:
@ -45,18 +45,23 @@ paths:
examples:
User not Found:
value: { "message": "User not Found" }
500:
description: Failed
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
Failed:
value: { "message": "Login failed" }
tags:
- Login/Logout
/logout:
post:
summary: Logout
description: Log out User
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LogoutRequest"
security:
- BasicAuth: []
responses:
200:
description: Success
@ -98,13 +103,6 @@ components:
type: string
password:
type: string
LogoutRequest:
type: object
required:
- token
properties:
token:
type: string
securitySchemes:
BasicAuth:
type: apiKey

View File

@ -52,7 +52,8 @@ data-styled.g14[id="sc-jCbFiK"]{content:"hSvuOo,"}/*!sc*/
.ezFOZv polygon{fill:#d41f1c;}/*!sc*/
.iMxoRf{height:20px;width:20px;min-width:20px;vertical-align:middle;float:right;transition:transform 0.2s ease-out;transform:rotateZ(0);}/*!sc*/
.iMxoRf polygon{fill:white;}/*!sc*/
data-styled.g15[id="sc-cBYhjr"]{content:"gUrACV,fqtTpb,ezFOZv,iMxoRf,"}/*!sc*/
.dJanPw{height:1.3em;width:1.3em;min-width:1.3em;vertical-align:middle;transition:transform 0.2s ease-out;transform:rotateZ(-90deg);}/*!sc*/
data-styled.g15[id="sc-cBYhjr"]{content:"gUrACV,fqtTpb,ezFOZv,iMxoRf,dJanPw,"}/*!sc*/
.gbdrVc{border-left:1px solid #7c7cbb;box-sizing:border-box;position:relative;padding:10px 10px 10px 0;}/*!sc*/
@media screen and (max-width: 50rem){.gbdrVc{display:block;overflow:hidden;}}/*!sc*/
tr:first-of-type>.gbdrVc,tr.last>.gbdrVc{border-left-width:0;background-position:top left;background-repeat:no-repeat;background-size:1px 100%;}/*!sc*/
@ -227,6 +228,29 @@ data-styled.g62[id="sc-hrDJJk"]{content:"gLEAmN,"}/*!sc*/
.dHStET a:visited{color:#32329f;}/*!sc*/
.dHStET a:hover{color:#6868cf;text-decoration:auto;}/*!sc*/
data-styled.g70[id="sc-iNJlaU"]{content:"dHStET,"}/*!sc*/
.fyveIh:after{content:' and ';font-weight:normal;}/*!sc*/
.fyveIh:last-child:after{content:none;}/*!sc*/
.fyveIh a{text-decoration:auto;color:#32329f;}/*!sc*/
.fyveIh a:visited{color:#32329f;}/*!sc*/
.fyveIh a:hover{color:#6868cf;text-decoration:auto;}/*!sc*/
data-styled.g80[id="sc-blcnQh"]{content:"fyveIh,"}/*!sc*/
.lkBZak{white-space:nowrap;}/*!sc*/
.lkBZak:after{content:' or ';white-space:pre;}/*!sc*/
.lkBZak:last-child:after,.lkBZak:only-child:after{content:none;}/*!sc*/
.lkBZak a{text-decoration:auto;color:#32329f;}/*!sc*/
.lkBZak a:visited{color:#32329f;}/*!sc*/
.lkBZak a:hover{color:#6868cf;text-decoration:auto;}/*!sc*/
data-styled.g81[id="sc-iHlJgr"]{content:"lkBZak,"}/*!sc*/
.febKCY{flex:1 1 auto;cursor:pointer;}/*!sc*/
data-styled.g82[id="sc-jHofgq"]{content:"febKCY,"}/*!sc*/
.juVMxG{width:75%;text-overflow:ellipsis;border-radius:4px;overflow:hidden;}/*!sc*/
@media screen and (max-width: 50rem){.juVMxG{margin-top:10px;}}/*!sc*/
data-styled.g83[id="sc-iRFtIJ"]{content:"juVMxG,"}/*!sc*/
.eGMvsx{display:inline-block;margin:0;}/*!sc*/
data-styled.g84[id="sc-jRHPII"]{content:"eGMvsx,"}/*!sc*/
.cCfxdS{width:100%;display:flex;margin:1em 0;flex-direction:row;}/*!sc*/
@media screen and (max-width: 50rem){.cCfxdS{flex-direction:column;}}/*!sc*/
data-styled.g85[id="sc-hWiVxH"]{content:"cCfxdS,"}/*!sc*/
.edbYXQ{margin-top:0;margin-bottom:0.5em;}/*!sc*/
data-styled.g91[id="sc-gjHHYa"]{content:"edbYXQ,"}/*!sc*/
.cwcfQE{border:1px solid #32329f;color:#32329f;font-weight:normal;margin-left:0.5em;padding:4px 8px 4px;display:inline-block;text-decoration:none;cursor:pointer;}/*!sc*/
@ -363,17 +387,19 @@ data-styled.g137[id="sc-kvXgyf"]{content:"fBvPoH,"}/*!sc*/
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"><p>Log in user</p>
</div></div><h5 class="sc-dkjaqt gwrByh">Request Body schema: <span class="sc-dwYcXH fafqZb">application/json</span><div class="sc-xuUkR sc-hrDJJk sc-kGqRax bJcEcT gLEAmN HCLfY">required</div></h5><div html="" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"></div><table class="sc-dENhDJ ceVHDP"><tbody><tr class=""><td kind="field" title="username" class="sc-tOkKi sc-epPVmt gbdrVc bUksBx"><span class="sc-hfvVTD hTjFRU"></span><span class="property-name">username</span><div class="sc-xuUkR sc-hrDJJk bJcEcT gLEAmN">required</div></td><td class="sc-fpSrms exGrJC"><div><div><span class="sc-xuUkR sc-cvzDha bJcEcT kDPMlG"></span><span class="sc-xuUkR sc-gKROGD bJcEcT etUsjc">string</span></div> <div><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div></div></div></td></tr><tr class="last "><td kind="field" title="password" class="sc-tOkKi sc-epPVmt gbdrVc bUksBx"><span class="sc-hfvVTD hTjFRU"></span><span class="property-name">password</span><div class="sc-xuUkR sc-hrDJJk bJcEcT gLEAmN">required</div></td><td class="sc-fpSrms exGrJC"><div><div><span class="sc-xuUkR sc-cvzDha bJcEcT kDPMlG"></span><span class="sc-xuUkR sc-gKROGD bJcEcT etUsjc">string</span></div> <div><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div></div></div></td></tr></tbody></table><div><h3 class="sc-eiLgtK dbBFCU">Responses</h3><div><button class="sc-giOWAb gcYfHW"><svg class="sc-cBYhjr fqtTpb" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">200<!-- --> </strong><div html="&lt;p&gt;Success&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>Success</p>
</div></button></div><div><button class="sc-giOWAb gbPhWg"><svg class="sc-cBYhjr ezFOZv" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">401<!-- --> </strong><div html="&lt;p&gt;Failed&lt;/p&gt;
</div></button></div><div><button class="sc-giOWAb gbPhWg"><svg class="sc-cBYhjr ezFOZv" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">401<!-- --> </strong><div html="&lt;p&gt;Invalid credentials&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>Invalid credentials</p>
</div></button></div><div><button class="sc-giOWAb gbPhWg"><svg class="sc-cBYhjr ezFOZv" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">404<!-- --> </strong><div html="&lt;p&gt;User not Found&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>User not Found</p>
</div></button></div><div><button class="sc-giOWAb gbPhWg"><svg class="sc-cBYhjr ezFOZv" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">500<!-- --> </strong><div html="&lt;p&gt;Failed&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>Failed</p>
</div></button></div><div><button class="sc-giOWAb gbPhWg"><svg class="sc-cBYhjr ezFOZv" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">404<!-- --> </strong><div html="&lt;p&gt;Failed&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>Failed</p>
</div></button></div></div></div><div class="sc-iKTcqh sc-gnpbhQ fTxZsC drGLlX"><div class="sc-dKsqdn dCbPd"><button class="sc-iAlELC gsBSOU"><span type="post" class="sc-oeqTF kpMtuJ http-verb post">post</span><span class="sc-eowDPD jcAXWA">/login</span><svg class="sc-cBYhjr iMxoRf" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-ezTrPE bFiOkX"><div class="sc-drnuxz hdRKqQ"><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div><div tabindex="0" role="button"><div class="sc-hDcvty jpmGrk"><span>https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api</span>/login</div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Request samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="react-tabs__tab react-tabs__tab--selected" role="tab" id="tab:R99cq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R99cq:0" tabindex="0" data-rttab="true">Payload</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R99cq:0" aria-labelledby="tab:R99cq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"username"</span>: <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"password"</span>: <span class="token string">&quot;string&quot;</span></div></li></ul><span class="token punctuation">}</span></code></div></div></div></div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Response samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="tab:R9pcq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R9pcq:0" tabindex="0" data-rttab="true">200</li><li class="tab-error" role="tab" id="tab:R9pcq:1" aria-selected="false" aria-disabled="false" aria-controls="panel:R9pcq:1" data-rttab="true">401</li><li class="tab-error" role="tab" id="tab:R9pcq:2" aria-selected="false" aria-disabled="false" aria-controls="panel:R9pcq:2" data-rttab="true">404</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R9pcq:0" aria-labelledby="tab:R9pcq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><span class="token boolean">true</span></code></div></div></div></div></div></div><div class="react-tabs__tab-panel" role="tabpanel" id="panel:R9pcq:1" aria-labelledby="tab:R9pcq:1"></div><div class="react-tabs__tab-panel" role="tabpanel" id="panel:R9pcq:2" aria-labelledby="tab:R9pcq:2"></div></div></div></div></div></div><div id="tag/LoginLogout/paths/~1logout/post" data-section-id="tag/LoginLogout/paths/~1logout/post" class="sc-dsLQwm kcRA-dj"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/LoginLogout/paths/~1logout/post" aria-label="tag/LoginLogout/paths/~1logout/post"></a>Logout<!-- --> </h2><div class="sc-fpJhiv cQxXyG"><div html="&lt;p&gt;Log out User&lt;/p&gt;
</div></button></div></div></div><div class="sc-iKTcqh sc-gnpbhQ fTxZsC drGLlX"><div class="sc-dKsqdn dCbPd"><button class="sc-iAlELC gsBSOU"><span type="post" class="sc-oeqTF kpMtuJ http-verb post">post</span><span class="sc-eowDPD jcAXWA">/login</span><svg class="sc-cBYhjr iMxoRf" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-ezTrPE bFiOkX"><div class="sc-drnuxz hdRKqQ"><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div><div tabindex="0" role="button"><div class="sc-hDcvty jpmGrk"><span>https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api</span>/login</div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Request samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="react-tabs__tab react-tabs__tab--selected" role="tab" id="tab:R99cq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R99cq:0" tabindex="0" data-rttab="true">Payload</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R99cq:0" aria-labelledby="tab:R99cq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"username"</span>: <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"password"</span>: <span class="token string">&quot;string&quot;</span></div></li></ul><span class="token punctuation">}</span></code></div></div></div></div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Response samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="tab:R9pcq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R9pcq:0" tabindex="0" data-rttab="true">200</li><li class="tab-error" role="tab" id="tab:R9pcq:1" aria-selected="false" aria-disabled="false" aria-controls="panel:R9pcq:1" data-rttab="true">401</li><li class="tab-error" role="tab" id="tab:R9pcq:2" aria-selected="false" aria-disabled="false" aria-controls="panel:R9pcq:2" data-rttab="true">404</li><li class="tab-error" role="tab" id="tab:R9pcq:3" aria-selected="false" aria-disabled="false" aria-controls="panel:R9pcq:3" data-rttab="true">500</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R9pcq:0" aria-labelledby="tab:R9pcq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><span class="token boolean">true</span></code></div></div></div></div></div></div><div class="react-tabs__tab-panel" role="tabpanel" id="panel:R9pcq:1" aria-labelledby="tab:R9pcq:1"></div><div class="react-tabs__tab-panel" role="tabpanel" id="panel:R9pcq:2" aria-labelledby="tab:R9pcq:2"></div><div class="react-tabs__tab-panel" role="tabpanel" id="panel:R9pcq:3" aria-labelledby="tab:R9pcq:3"></div></div></div></div></div></div><div id="tag/LoginLogout/paths/~1logout/post" data-section-id="tag/LoginLogout/paths/~1logout/post" class="sc-dsLQwm kcRA-dj"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/LoginLogout/paths/~1logout/post" aria-label="tag/LoginLogout/paths/~1logout/post"></a>Logout<!-- --> </h2><div class="sc-fpJhiv cQxXyG"><div html="&lt;p&gt;Log out User&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"><p>Log out User</p>
</div></div><h5 class="sc-dkjaqt gwrByh">Request Body schema: <span class="sc-dwYcXH fafqZb">application/json</span><div class="sc-xuUkR sc-hrDJJk sc-kGqRax bJcEcT gLEAmN HCLfY">required</div></h5><div html="" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"></div><table class="sc-dENhDJ ceVHDP"><tbody><tr class="last "><td kind="field" title="token" class="sc-tOkKi sc-epPVmt gbdrVc bUksBx"><span class="sc-hfvVTD hTjFRU"></span><span class="property-name">token</span><div class="sc-xuUkR sc-hrDJJk bJcEcT gLEAmN">required</div></td><td class="sc-fpSrms exGrJC"><div><div><span class="sc-xuUkR sc-cvzDha bJcEcT kDPMlG"></span><span class="sc-xuUkR sc-gKROGD bJcEcT etUsjc">string</span></div> <div><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div></div></div></td></tr></tbody></table><div><h3 class="sc-eiLgtK dbBFCU">Responses</h3><div><button class="sc-giOWAb gcYfHW"><svg class="sc-cBYhjr fqtTpb" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">200<!-- --> </strong><div html="&lt;p&gt;Success&lt;/p&gt;
</div></div><div class="sc-hWiVxH cCfxdS"><div class="sc-jHofgq febKCY"><h5 class="sc-dkjaqt sc-jRHPII gwrByh eGMvsx">Authorizations:</h5><svg class="sc-cBYhjr dJanPw" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></div><div class="sc-iRFtIJ juVMxG"><span class="sc-iHlJgr lkBZak"><span class="sc-blcnQh fyveIh"><i>BasicAuth</i></span></span></div></div><div><h3 class="sc-eiLgtK dbBFCU">Responses</h3><div><button class="sc-giOWAb gcYfHW"><svg class="sc-cBYhjr fqtTpb" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-catHVh gXPvFO">200<!-- --> </strong><div html="&lt;p&gt;Success&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww"><p>Success</p>
</div></button></div></div></div><div class="sc-iKTcqh sc-gnpbhQ fTxZsC drGLlX"><div class="sc-dKsqdn dCbPd"><button class="sc-iAlELC gsBSOU"><span type="post" class="sc-oeqTF kpMtuJ http-verb post">post</span><span class="sc-eowDPD jcAXWA">/logout</span><svg class="sc-cBYhjr iMxoRf" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-ezTrPE bFiOkX"><div class="sc-drnuxz hdRKqQ"><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div><div tabindex="0" role="button"><div class="sc-hDcvty jpmGrk"><span>https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api</span>/logout</div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Request samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="react-tabs__tab react-tabs__tab--selected" role="tab" id="tab:R99kq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R99kq:0" tabindex="0" data-rttab="true">Payload</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R99kq:0" aria-labelledby="tab:R99kq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"token"</span>: <span class="token string">&quot;string&quot;</span></div></li></ul><span class="token punctuation">}</span></code></div></div></div></div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Response samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="tab:R9pkq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R9pkq:0" tabindex="0" data-rttab="true">200</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R9pkq:0" aria-labelledby="tab:R9pkq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><span class="token boolean">true</span></code></div></div></div></div></div></div></div></div></div></div></div><div id="tag/Users" data-section-id="tag/Users" class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/Users" aria-label="tag/Users"></a>Users</h2></div></div></div><div id="tag/Posts" data-section-id="tag/Posts" class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/Posts" aria-label="tag/Posts"></a>Posts</h2></div></div></div></div><div class="sc-epzHnm bWkBKa"></div></div></div>
</div></button></div></div></div><div class="sc-iKTcqh sc-gnpbhQ fTxZsC drGLlX"><div class="sc-dKsqdn dCbPd"><button class="sc-iAlELC gsBSOU"><span type="post" class="sc-oeqTF kpMtuJ http-verb post">post</span><span class="sc-eowDPD jcAXWA">/logout</span><svg class="sc-cBYhjr iMxoRf" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-ezTrPE bFiOkX"><div class="sc-drnuxz hdRKqQ"><div html="" class="sc-euGpHm sc-exayXG fwfkcU jYGAQp"></div><div tabindex="0" role="button"><div class="sc-hDcvty jpmGrk"><span>https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api</span>/logout</div></div></div></div></div><div><h3 class="sc-kkmypM jKNCPF"> <!-- -->Response samples<!-- --> </h3><div class="sc-bSlUec jxQggo" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="tab:R9pkq:0" aria-selected="true" aria-disabled="false" aria-controls="panel:R9pkq:0" tabindex="0" data-rttab="true">200</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:R9pkq:0" aria-labelledby="tab:R9pkq:0"><div><div class="sc-WChnI iLXIA-d"><span class="sc-foMnoT dmNpjh">Content type</span><div class="sc-ZubPq KmnOC">application/json</div></div><div class="sc-AmOMz gDrQpr"><div class="sc-eTdEpr dgzSkD"><div class="sc-pFPEP bMXXJy"><button><div class="sc-eHujzY ecCAmX">Copy</div></button></div><div class="sc-euGpHm fwfkcU sc-fTgapq bDqsIm"><div class="redoc-json"><code><span class="token boolean">true</span></code></div></div></div></div></div></div></div></div></div></div></div><div id="tag/Users" data-section-id="tag/Users" class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/Users" aria-label="tag/Users"></a>Users</h2></div></div></div><div id="tag/Posts" data-section-id="tag/Posts" class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt"><h2 class="sc-knesRu cbpGTP"><a class="sc-jCbFiK hSvuOo" href="#tag/Posts" aria-label="tag/Posts"></a>Posts</h2></div></div></div></div><div class="sc-epzHnm bWkBKa"></div></div></div>
<script>
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"PHP Course Exam","version":"1.0.0","contact":{"name":"Kilian Kurt Hofmann","email":"khofmann@zedat.fu-berlin.de"},"description":"PHP Course (ABV FU Berlin) 2024 Exam"},"paths":{"/login":{"post":{"summary":"Login","description":"Log in user","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BooleanResponse"},"examples":{"Success":{"value":true}}}}},"401":{"description":"Failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"Invalid Username or Password":{"value":{"message":"Invalid Username or Password"}}}}}},"404":{"description":"Failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"User not Found":{"value":{"message":"User not Found"}}}}}}},"tags":["Login/Logout"]}},"/logout":{"post":{"summary":"Logout","description":"Log out User","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BooleanResponse"},"examples":{"Success":{"value":true}}}}}},"tags":["Login/Logout"]}}},"externalDocs":{"url":"https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/docs/"},"security":[],"servers":[{"url":"https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/","description":"","variables":{}}],"components":{"links":{},"callbacks":{},"schemas":{"BooleanResponse":{"type":"boolean"},"ErrorResponse":{"type":"object","properties":{"message":{"type":"string"}}},"LoginRequest":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}}},"LogoutRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}},"securitySchemes":{"BasicAuth":{"type":"apiKey","name":"token","in":"header"}}},"tags":[{"name":"Login/Logout"},{"name":"Users"},{"name":"Posts"}]}},"searchIndex":{"store":["tag/LoginLogout","tag/LoginLogout/paths/~1login/post","tag/LoginLogout/paths/~1logout/post","tag/Users","tag/Posts"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,1.386]],["description/0",[]],["title/1",[1,0.875]],["description/1",[1,0.597,2,0.597,3,0.367]],["title/2",[4,0.875]],["description/2",[2,0.497,3,0.306,4,0.497,5,0.788]],["title/3",[3,0.539]],["description/3",[]],["title/4",[6,1.386]],["description/4",[]]],"invertedIndex":[["log",{"_index":2,"title":{},"description":{"1":{},"2":{}}}],["login",{"_index":1,"title":{"1":{}},"description":{"1":{}}}],["login/logout",{"_index":0,"title":{"0":{}},"description":{}}],["logout",{"_index":4,"title":{"2":{}},"description":{"2":{}}}],["out",{"_index":5,"title":{},"description":{"2":{}}}],["post",{"_index":6,"title":{"4":{}},"description":{}}],["user",{"_index":3,"title":{"3":{}},"description":{"1":{},"2":{}}}]],"pipeline":[]}},"options":{}};
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"PHP Course Exam","version":"1.0.0","contact":{"name":"Kilian Kurt Hofmann","email":"khofmann@zedat.fu-berlin.de"},"description":"PHP Course (ABV FU Berlin) 2024 Exam"},"paths":{"/login":{"post":{"summary":"Login","description":"Log in user","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BooleanResponse"},"examples":{"Success":{"value":true}}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"Invalid Username or Password":{"value":{"message":"Invalid Username or Password"}}}}}},"404":{"description":"User not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"User not Found":{"value":{"message":"User not Found"}}}}}},"500":{"description":"Failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"Failed":{"value":{"message":"Login failed"}}}}}}},"tags":["Login/Logout"]}},"/logout":{"post":{"summary":"Logout","description":"Log out User","security":[{"BasicAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BooleanResponse"},"examples":{"Success":{"value":true}}}}}},"tags":["Login/Logout"]}}},"externalDocs":{"url":"https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/docs/"},"security":[],"servers":[{"url":"https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/","description":"","variables":{}}],"components":{"links":{},"callbacks":{},"schemas":{"BooleanResponse":{"type":"boolean"},"ErrorResponse":{"type":"object","properties":{"message":{"type":"string"}}},"LoginRequest":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}}}},"securitySchemes":{"BasicAuth":{"type":"apiKey","name":"token","in":"header"}}},"tags":[{"name":"Login/Logout"},{"name":"Users"},{"name":"Posts"}]}},"searchIndex":{"store":["tag/LoginLogout","tag/LoginLogout/paths/~1login/post","tag/LoginLogout/paths/~1logout/post","tag/Users","tag/Posts"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,1.386]],["description/0",[]],["title/1",[1,0.875]],["description/1",[1,0.597,2,0.597,3,0.367]],["title/2",[4,0.875]],["description/2",[2,0.497,3,0.306,4,0.497,5,0.788]],["title/3",[3,0.539]],["description/3",[]],["title/4",[6,1.386]],["description/4",[]]],"invertedIndex":[["log",{"_index":2,"title":{},"description":{"1":{},"2":{}}}],["login",{"_index":1,"title":{"1":{}},"description":{"1":{}}}],["login/logout",{"_index":0,"title":{"0":{}},"description":{}}],["logout",{"_index":4,"title":{"2":{}},"description":{"2":{}}}],["out",{"_index":5,"title":{},"description":{"2":{}}}],["post",{"_index":6,"title":{"4":{}},"description":{}}],["user",{"_index":3,"title":{"3":{}},"description":{"1":{},"2":{}}}]],"pipeline":[]}},"options":{}};
var container = document.getElementById('redoc');
Redoc.hydrate(__redoc_state, container);

View File

@ -2,8 +2,10 @@
namespace Khofmann\Auth;
use Exception;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use Khofmann\Models\User\User;
class Auth implements IMiddleware
{
@ -11,10 +13,15 @@ class Auth implements IMiddleware
{
$token = $request->getHeader("token");
//TODO: Auth user with token
// No token
if ($token === null) {
response()->httpCode(401)->json(["message" => "Not Authorized"]);
}
// If authentication failed
if ($request->token === null) {
try {
User::getByToken($token);
} catch (Exception $err) {
// No user with this token exists
response()->httpCode(401)->json(["message" => "Not Authorized"]);
}
}

View File

@ -2,9 +2,9 @@
namespace Khofmann\Database;
use \PDO;
use PDO;
class Database extends
class Database extends PDO
{
private static array $instances = [];
@ -17,7 +17,7 @@ class Database extends
{
$cls = static::class;
if (!isset(self::$instances[$cls])) {
$dataAccess = Config\Config::getDatabase();
$dataAccess = \Config\Config::getDatabase();
self::$instances[$cls] = new static(
"mysql:host={$dataAccess["host"]};dbname={$dataAccess["database"]};charset={$dataAccess["charset"]}",
$dataAccess["user"],

View File

@ -0,0 +1,20 @@
<?php
namespace Khofmann\Input;
class Input
{
private static function input($index = null, $defaultValue = null, ...$methods)
{
if ($index !== null) {
return request()->getInputHandler()->value($index, $defaultValue, ...$methods);
}
return request()->getInputHandler();
}
public static function post($index, $defaultValue = null)
{
return input()->post($index, $defaultValue);
}
}

View File

@ -0,0 +1,188 @@
<?php
namespace Khofmann\Models\User;
use Exception;
use PDO;
use Khofmann\Database\Database;
use JsonSerializable;
class User implements JsonSerializable
{
private int $id;
private string $username;
private int $status;
private string $email;
private ?string $image;
private bool $isAdmin;
protected function __construct(int $id, string $username, int $status, string $email, string $image = null, bool $isAdmin = false)
{
$this->id = $id;
$this->username = $username;
$this->status = $status;
$this->email = $email;
$this->image = $image;
$this->isAdmin = $isAdmin;
}
/*
* Statics
*/
public static function getByID(int $id): User
{
$db = Database::getInstance();
$stmt = $db->prepare(
"SELECT benutzer, status, email, image, isadmin FROM egb_benutzer WHERE id = :ID"
);
$stmt->bindValue(":ID", $id);
$stmt->execute();
$data = $stmt->fetch();
if (!$data)
throw new Exception("No user found");
return new User($id, $data["benutzer"], $data["status"], $data["email"], $data["image"], $data["isadmin"] === 1);
}
public static function getByEmail(string $email): User
{
$db = Database::getInstance();
$stmt = $db->prepare(
"SELECT id, benutzer, status, image, isadmin FROM egb_benutzer WHERE email = :EMAIL"
);
$stmt->bindValue(":EMAIL", $email);
$stmt->execute();
$data = $stmt->fetch();
if (!$data)
throw new Exception("No user found");
return new User($data["id"], $data["benutzer"], $data["status"], $email, $data["image"], $data["isadmin"] === 1);
}
public static function getByToken(string $token): User
{
$db = Database::getInstance();
$stmt = $db->prepare(
"SELECT id, benutzer, status, email, image, isadmin FROM egb_benutzer WHERE token = :TOKEN"
);
$stmt->bindValue(":TOKEN", $token);
$stmt->execute();
$data = $stmt->fetch();
if (!$data)
throw new Exception("No user found");
return new User($data["id"], $data["benutzer"], $data["status"], $data["email"], $data["image"], $data["isadmin"] === 1);
}
public static function logIn(string $email, string $password): array
{
$db = Database::getInstance();
// Get user data
$stmt = $db->prepare("SELECT * FROM egb_benutzer WHERE email LIKE :EMAIL AND status = 1");
$stmt->bindValue(":EMAIL", $email);
$stmt->execute();
$data = $stmt->fetch();
if ($data) {
$user = new User($data["id"], $data["benutzer"], $data["status"], $email, $data["image"], $data["isadmin"] === 1);
if (password_verify($password, $data["passwort"])) {
// REHASH for safety should it somehow change
if (password_needs_rehash($data["passwort"], PASSWORD_DEFAULT)) {
$newHash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE egb_benutzer SET passwort = :PAS WHERE id = :ID");
$stmt->bindValue(":PAS", $newHash);
$stmt->bindValue(":ID", $user->getID());
$stmt->execute();
}
// Generate token
$stmt = $db->prepare("UPDATE egb_benutzer SET token = UUID() WHERE id = :ID");
$stmt->bindValue(":ID", $user->getID());
$stmt->execute();
// Get token
$stmt = $db->prepare("SELECT token FROM egb_benutzer WHERE id = :ID");
$stmt->bindValue(":ID", $user->getID());
$stmt->execute();
$token = $stmt->fetch(PDO::FETCH_COLUMN, 0);
// Return user and token
if ($token) {
return ["user" => $user, "token" => $token];
}
// Token generation failed
throw new Exception("Failed");
} else {
// PW wrong
throw new Exception("Invalid");
}
} else {
// User does not exist
throw new Exception("NotFound");
}
}
/*
* Members
*/
public function logOut(string $token): bool
{
$db = Database::getInstance();
// Get user data
$stmt = $db->prepare("UPDATE egb_benutzer SET token = NULL WHERE id = :ID");
$stmt->bindValue(":ID", $this->id);
return $stmt->execute();
}
/*
* Getters
*/
public function getID(): int
{
return $this->id;
}
public function getUsername(): string
{
return $this->username;
}
public function getStatus(): int
{
return $this->status;
}
public function getEmail(): string
{
return $this->email;
}
public function getImage(): string
{
return $this->image;
}
public function getIsAdmin(): bool
{
return $this->isAdmin;
}
/*
* JSON
*/
public function jsonSerialize(): array
{
return [
'id' => $this->getId(),
'username' => $this->getUsername(),
'status' => $this->getStatus(),
'email' => $this->getEmail(),
'image' => $this->getImage(),
'isAdmin' => $this->getIsAdmin()
];
}
}

View File

@ -4,7 +4,8 @@ use Pecee\SimpleRouter\SimpleRouter;
use Pecee\Http\Request;
// Error handling
SimpleRouter::error(function (Request $request, \Exception $exception) {
response()->httpCode($exception->getCode())->json(["message" => $exception->getMessage()]);
$code = $exception->getCode();
response()->httpCode(is_int($code) ? $code : 500)->json(["message" => $exception->getMessage()]);
});
// Index
SimpleRouter::all("/", function () {
@ -12,7 +13,9 @@ SimpleRouter::all("/", function () {
});
// Login/Logout
SimpleRouter::post("/login", [Api\Login\Login::class, "post"]);
SimpleRouter::group(["middleware" => \Khofmann\Auth\Auth::class], function () {
SimpleRouter::post("/logout", [Api\Logout\Logout::class, "post"]);
});
// User
SimpleRouter::group(["middleware" => \Khofmann\Auth\Auth::class], function () {
SimpleRouter::get("/user/{id}", function ($userID) {

View File

@ -44,22 +44,6 @@ function request(): Request
return Router::request();
}
/**
* Get input class
* @param string|null $index Parameter index name
* @param string|mixed|null $defaultValue Default return value
* @param array ...$methods Default methods
* @return \Pecee\Http\Input\InputHandler|array|string|null
*/
function input($index = null, $defaultValue = null, ...$methods)
{
if ($index !== null) {
return request()->getInputHandler()->value($index, $defaultValue, ...$methods);
}
return request()->getInputHandler();
}
/**
* @param string $url
* @param int|null $code