/******************************************************************************* * Copyright (c) 2025, Jan Koester jan.koester@gmx.net * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ #include #include #include #include #include #include #include #include #include "backend.h" #include "authdb.h" #include "user.h" #include "types.h" namespace authdb { bool initalized=true; class AuthDB : public libhttppp::HttpEvent{ public: AuthDB(authdb::AuthBackend &backend,netplus::socket *ssock) : HttpEvent(ssock), _Backend(backend){ }; void listUsers(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ _Backend.lock(); authdb::AuthData *cur=new AuthData; size_t rd=sizeof(authdb::AuthHeader),end=_Backend.end(); _Backend.setPos(rd); libhtmlpp::HtmlElement root; libhtmlpp::HtmlPage page; page.loadFile(root,"../data/index.html"); libhtmlpp::HtmlString userlist,out; libhtmlpp::HtmlElement *content=root.getElementbyID("content"); userlist <<"

UserList:

"; while(rdfieldname,"username")==0){ AuthDataRecord *rec=new AuthDataRecord; uuid_t uid; uuid_parse(cur->uuid,uid); _Backend.setPos(sizeof(AuthHeader)); getRecord(_Backend,rec,uid,DataType::UserData); userlist+="User: "; std::copy(cur->data,cur->data+cur->datasize,std::back_inserter(userlist)); userlist+=" UID: "; userlist+= cur->uuid; userlist+= "
"; for(AuthDataRecord *curec=rec; curec; curec=curec->next()){ if(strcmp(curec->Data->fieldname,"username")!=0 && curec->Data->data){ userlist+=" "; userlist+=curec->Data->fieldname; userlist+=": "; std::copy(curec->Data->data,curec->Data->data+curec->Data->datasize, std::back_inserter(userlist)); userlist+= "
"; } } delete rec; } } userlist << "
"; delete cur; _Backend.unlock(); content->insertChild(userlist.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.send(curreq,out.c_str(),out.size()); } void createUser(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ libhttppp::HttpResponse rep; libhttppp::HttpForm curform; curform.parse(curreq); if (curform.getBoundary()) { uuid_t uid; uuid_generate(uid); class UserData udat(uid); for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData(); curformdat; curformdat = curformdat->nextData()) { for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition(); curdispo; curdispo=curdispo->nextContentDisposition() ){ if(curformdat->Value.empty() || !curdispo->getValue()) continue; std::vector tmp; if(strcmp(curdispo->getValue(),"avatar")!=0){ std:copy(curformdat->Value.begin(),curformdat->Value.end(),std::back_inserter(tmp)); tmp.push_back('\0'); } if(strcmp(curdispo->getValue(),"username")==0){ udat.setUserName(tmp.data()); }else if(strcmp(curdispo->getValue(),"firstname")==0){ udat.setFirstName(tmp.data()); }else if(strcmp(curdispo->getValue(),"lastname")==0){ udat.setLastName(tmp.data()); }else if(strcmp(curdispo->getValue(),"mail")==0){ udat.setMail(tmp.data()); }else if(strcmp(curdispo->getValue(),"avatar")==0 && !curformdat->Value.empty()){ udat.setAvatar(curformdat->Value); } } } User user; user.create(_Backend,&udat); std::cout << "user created!" << std::endl; } libhtmlpp::HtmlElement root; libhtmlpp::HtmlPage page; page.loadFile(root,"../data/index.html"); libhtmlpp::HtmlString form,out; form << "
" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "
" << "insertChild(form.parse()); libhtmlpp::print(&root,out,true); rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } void AdminController(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ if(strncmp(curreq->getRequestURL(),"/admin/listusers",16)==0){ listUsers(curreq,tid,args); }else if(strncmp(curreq->getRequestURL(),"/admin/createuser",17)==0){ createUser(curreq,tid,args); }else{ libhtmlpp::HtmlElement root; libhtmlpp::HtmlPage page; page.loadFile(root,"../data/index.html"); libhtmlpp::HtmlString out; libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } } void RequestEvent(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ if(strncmp(curreq->getRequestURL(),"/admin",6)==0){ AdminController(curreq,tid,args); }else if(strncmp(curreq->getRequestURL(),"/api",4)==0){ }else{ libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); rep.setHeaderData("Location")->push_back("/admin"); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); } }; private: authdb::AuthBackend &_Backend; }; int searchValue(authdb::AuthBackend &backend,const char*fieldname,const char *value){ authdb::AuthData *user=new AuthData; int rd=sizeof(authdb::AuthHeader),brd=rd; while(rd>backend.end()){ backend.ReadAuthData(user,rd); rd=backend.getPos(); if(strcmp(user->fieldname,fieldname) == 0){ if(strcmp(user->data,value) == 0){ delete[] user->data; delete user; return brd; } } brd=rd; delete[] user->data; } delete user; return -1; } AuthDataRecord::AuthDataRecord(){ Data = new AuthData; memset((void*)Data,0,sizeof(AuthData)); Data->start=0xFE; Data->end=0xFF; _next=nullptr; } AuthDataRecord::AuthDataRecord(const AuthDataRecord &src){ Data = new AuthData; memcpy(&Data,&src.Data,sizeof(src.Data)); memcpy(Data->data,src.Data->data,src.Data->datasize); _next=nullptr; } AuthDataRecord::~AuthDataRecord(){ delete Data; } AuthDataRecord *AuthDataRecord::next(){ return _next; }; bool getRecord(authdb::AuthBackend &backend,AuthDataRecord *dest,uuid_t id,int type){ bool found=false; AuthData *cur=new AuthData; int rd=sizeof(authdb::AuthHeader),end=backend.end(); char plainid[255]; uuid_unparse(id,plainid); AuthDataRecord *curec=dest; while(rduuid,plainid) == 0 && cur->type == type){ memcpy(curec->Data,cur,sizeof(*cur)); if(rd_next=new AuthDataRecord; curec=curec->_next; } found=true; } } delete cur; return found; } }; int main(int argc, char *argv[]){ cmdplus::CmdController &cmd=cmdplus::CmdController::getInstance(); cmd.registerCmd("config",'c',true,nullptr,"Config Path"); cmd.parseCmd(argc,argv); if(!cmd.checkRequired()){ std::cerr << "Config Path required !" << std::endl; cmd.printHelp(); return -1; } confplus::Config config(cmd.getCmdbyKey("config")->getValue()); authdb::AuthBackend backend(authdb::AuthBackendType::File, config.getValue(config.getKey("/AUTHDB/ADMINDB/PATH"),0), "admin.local" ); try { if(backend.end()<=sizeof(authdb::AuthHeader)){ authdb::initalized=false; } libhttppp::HttpD httpd( config.getValue(config.getKey("/AUTHDB/BIND"),0), config.getIntValue(config.getKey("/AUTHDB/PORT"),0), config.getIntValue(config.getKey("/AUTHDB/MAXCONN"),0), nullptr, nullptr ); authdb::AuthDB authdb(backend,httpd.getServerSocket()); authdb.runEventloop(); }catch(authdb::AuthBackendError &e){ std::cerr << e.what() << std::endl; } }