Skip to content
authdb.cpp 21.5 KiB
Newer Older
jan.koester's avatar
jan.koester committed
/*******************************************************************************
jan.koester's avatar
jan.koester committed
 * Copyright (c) 2025, Jan Koester jan.koester@gmx.net
jan.koester's avatar
jan.koester committed
 * 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 <organization> 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 <COPYRIGHT HOLDER> 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.
 *******************************************************************************/

jan.koester's avatar
jan.koester committed
#include <algorithm>
jan.koester's avatar
jan.koester committed
#include <iostream>
jan.koester's avatar
jan.koester committed
#include <cstring>
jan.koester's avatar
jan.koester committed
#include <sstream>
jan.koester's avatar
jan.koester committed
#include <mutex>
jan.koester's avatar
jan.koester committed
#include <map>
jan.koester's avatar
jan.koester committed
#include <fstream>
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
#include <uuid/uuid.h>
jan.koester's avatar
jan.koester committed
#include <cmdplus/cmdplus.h>
#include <confplus/conf.h>
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
#include <httppp/httpd.h>
jan.koester's avatar
jan.koester committed
#include <htmlpp/html.h>
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
#include "backend.h"
jan.koester's avatar
jan.koester committed
#include "authdb.h"
jan.koester's avatar
jan.koester committed
#include "user.h"
jan.koester's avatar
jan.koester committed
#include "domain.h"
jan.koester's avatar
jan.koester committed
#include "group.h"
jan.koester's avatar
jan.koester committed
#include "types.h"
jan.koester's avatar
jan.koester committed
#include "hash.h"
jan.koester's avatar
jan.koester committed
#include "hash/sha512.h"
#include "admin.h"
jan.koester's avatar
jan.koester committed
#include "api.h"
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
namespace authdb {
jan.koester's avatar
jan.koester committed

    std::mutex g_wizzard;

    bool initalized=true;
jan.koester's avatar
jan.koester committed

    class AuthDB : public libhttppp::HttpEvent{
    public:
        AuthDB(authdb::AuthBackend &backend,netplus::socket *ssock) :
            HttpEvent(ssock),
            _AdminBackend(backend),
            _AdminInterface(backend,ssock){
jan.koester's avatar
jan.koester committed
            std::ifstream authfs(GETDATA(authdb.js), std::ios::ate);
jan.koester's avatar
jan.koester committed
            size_t asize = authfs.tellg();
            _AuthJs.resize(asize);
            authfs.seekg(0);
            authfs.read(_AuthJs.data(),asize);

jan.koester's avatar
jan.koester committed
            std::ifstream cssfs(GETDATA(style.css), std::ios::ate);
jan.koester's avatar
jan.koester committed
            size_t csssize = cssfs.tellg();
            _AuthCss.resize(csssize);
            cssfs.seekg(0);
            cssfs.read(_AuthCss.data(),csssize);
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        void WizzardEvent(libhttppp::HttpRequest * curreq, const int tid, ULONG_PTR args){
            std::lock_guard<std::mutex> wlock(g_wizzard);

            libhttppp::HttpForm form;

            form.parse(curreq);

            std::string username,password,pwhash;

            for(libhttppp::HttpForm::UrlcodedForm::Data *curformdat=form.UrlFormData.getFormData();
                curformdat; curformdat=curformdat->nextData()){
                if(strcmp(curformdat->getKey(),"username")==0)
                    username=curformdat->getValue();
                else if(strcmp(curformdat->getKey(),"password")==0)
                    password=curformdat->getValue();
                }

                if(!password.empty() && !username.empty()){
                    sha512 hash;
                    hash.hash(password,pwhash);

                    authdb::User user;

                    uuid_t adminid,admingid;

                    uuid_generate(adminid);

                    uuid_generate(admingid);

                    class authdb::UserData udat(adminid);

                    udat.setUserName(username.c_str());

                    authdb::sha512 sha;
                    sha.hash(password,pwhash);

                    udat.setPwHash(pwhash.c_str());

                    user.create(_AdminBackend,&udat);

                    authdb::Group group;

                    class authdb::GroupData gdat(admingid);

                    gdat.setName("SuperAdmin");

                    authdb::GroupData::MemberUids muid;

                    muid.count=1;
                    muid.uid=&adminid;

                    gdat.addMember(muid);

                    group.create(_AdminBackend,&gdat);

                    libhttppp::HTTPException exp;
                    exp[999] << "wizzard finished";
                    throw exp;
                }

                libhtmlpp::HtmlElement index;

                libhtmlpp::HtmlPage page;
                page.loadFile(index,GETDATA(wizzard.html));

                libhttppp::HttpResponse rep;

                libhtmlpp::HtmlString sendat;

                libhtmlpp::print((libhtmlpp::Element*)&index,sendat,false);

                rep.setState(HTTP200);
                rep.setVersion(HTTPVERSION(1.1));
                rep.setContentType("text/html");
                rep.send(curreq,sendat.c_str(),sendat.size());

        }

        void RequestEvent(libhttppp::HttpRequest * curreq, const int tid, ULONG_PTR args){
jan.koester's avatar
jan.koester committed
            if(strncmp("/authdb.js",curreq->getRequestURL(),9)==0){
                libhttppp::HttpResponse rep;
                rep.setState(HTTP200);
                rep.setContentType("text/javascript");
                rep.send(curreq,_AuthJs.data(),_AuthJs.size());
                return;
            }else if(strncmp("/style.css",curreq->getRequestURL(),9)==0){
                libhttppp::HttpResponse rep;
                rep.setState(HTTP200);
                rep.setContentType("text/css");
                rep.send(curreq,_AuthCss.data(),_AuthCss.size());
                return;
            }else if(_AdminBackend.end()<=sizeof(authdb::AuthHeader)){
jan.koester's avatar
jan.koester committed
                _AdminBackend.lock();
jan.koester's avatar
jan.koester committed
                try{
                    WizzardEvent(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                    _AdminBackend.unlock();
jan.koester's avatar
jan.koester committed
                    return;
                }catch(libhttppp::HTTPException &e){
jan.koester's avatar
jan.koester committed
                    if(e.getErrorType()!=999){
                        libhttppp::HttpResponse rep;
                        rep.setState(HTTP500);
                        rep.setContentType("text/html");
                        rep.send(curreq,e.what(),strlen(e.what()));
jan.koester's avatar
jan.koester committed
                        return;
jan.koester's avatar
jan.koester committed
                    }
jan.koester's avatar
jan.koester committed
                }
jan.koester's avatar
jan.koester committed
                _AdminBackend.unlock();
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
            }
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
            if(strncmp("/settings",curreq->getRequestURL(),9)==0){
                _AdminBackend.lock();
                try{
jan.koester's avatar
jan.koester committed
                    _AdminInterface.Request(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }catch(AuthBackendError &e){
                    libhttppp::HttpResponse rep;
                    rep.setState(HTTP500);
                    rep.setContentType("text/html");
                    rep.send(curreq,e.what(),strlen(e.what()));
                }
                _AdminBackend.unlock();
jan.koester's avatar
jan.koester committed
            }if(strncmp("/api",curreq->getRequestURL(),4)==0){
                _AdminBackend.lock();

                DomainBackend db(_AdminBackend);

                AuthBackend *apidb=nullptr;

                char domain[255];
                if(sscanf(curreq->getRequestURL(),"/api/%s",domain)<0)
                    return;

                uuid_t did;

                if(uuid_parse(domain,did) == 0 ){
                    apidb=db.data(did);
                }

                _AdminBackend.unlock();

                if(apidb){
                    apidb->lock();
                    try{
                        ApiController(*apidb,curreq,tid,args);
                    }catch(AuthBackendError &e){
                        libhttppp::HttpResponse rep;
                        rep.setState(HTTP500);
                        rep.setContentType("text/html");
                        rep.send(curreq,e.what(),strlen(e.what()));
                    }
                    apidb->unlock();
                }else{
                    libhttppp::HttpResponse rep;
                    rep.setState(HTTP404);
                    rep.setContentType("text/html");
                    rep.send(curreq,"uuid not found!",12);
                }
jan.koester's avatar
jan.koester committed
            }else if(strncmp("/getavatar",curreq->getRequestURL(),9)==0){
                _AdminBackend.lock();
                try{
jan.koester's avatar
jan.koester committed
                    getAvatar(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }catch(AuthBackendError &e){
                    libhttppp::HttpResponse rep;
                    rep.setState(HTTP500);
                    rep.setContentType("text/html");
                    rep.send(curreq,e.what(),strlen(e.what()));
                }
                _AdminBackend.unlock();
jan.koester's avatar
jan.koester committed
            }else{
jan.koester's avatar
jan.koester committed
                libhttppp::HttpResponse rep;
                rep.setState(HTTP307);
                rep.setVersion(HTTPVERSION(1.1));
                rep.setHeaderData("Location")->push_back("/settings/index");
                rep.setContentType("text/html");
                rep.send(curreq,nullptr,0);
                return;
jan.koester's avatar
jan.koester committed
            }
jan.koester's avatar
jan.koester committed
        void getAvatar(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){
            libhttppp::HttpResponse rep;

            DomainBackend dbackend(_AdminBackend);
            AuthBackend *backend=nullptr;

            char domain[255],cuid[255],ext[16];
            if(sscanf(curreq->getRequestURL(),"/getavatar/%[^/]/%[^.].%s",domain,cuid,ext)<0)
                return;

            uuid_t did;

            if(strcmp(domain,"admin") == 0 ){
                backend=&_AdminBackend;
            }else if(uuid_parse(domain,did) == 0 ){
                backend=dbackend.data(did);
            }else{
                throw AuthBackendError("createUser: could not parse uuid!");
            }

            uuid_t uid;
            uuid_parse(cuid,uid);

            size_t rd=sizeof(authdb::AuthHeader),end=backend->end();

            while(rd<end){
                authdb::AuthData::Record cur;
                backend->setPos(rd);
                backend->read((unsigned char*)&cur,sizeof(AuthData::Record));
                rd=backend->getPos()+cur.datasize;

                if(uuid_compare(cur.uuid,uid)==0 && strcmp(cur.fieldname,"avatar")==0){
                    cur.data = new char[cur.datasize];
                    backend->read((unsigned char*)cur.data,cur.datasize);
                    char ctype[255];
                    snprintf(ctype,255,"image/%s",ext);
                    rep.setContentType(ctype);
                    rep.send(curreq,cur.data,cur.datasize);
                    end=0;
                    delete[] cur.data;
                }
            }

            if(end!=0){
                rep.setState(HTTP404);
                rep.send(curreq,nullptr,0);
            }

        };

jan.koester's avatar
jan.koester committed
    private:
jan.koester's avatar
jan.koester committed
        AuthBackend       &_AdminBackend;
        AdminInterface     _AdminInterface;
        std::vector<char>  _AuthJs;
jan.koester's avatar
jan.koester committed
        std::vector<char>  _AuthCss;
jan.koester's avatar
jan.koester committed
    };

    int searchValue(authdb::AuthBackend &backend,const char*fieldname,const char *value){
jan.koester's avatar
jan.koester committed
        authdb::AuthData::Record *user=new AuthData::Record;
jan.koester's avatar
jan.koester committed
        int rd=sizeof(authdb::AuthHeader),brd=rd;
        while(rd>backend.end()){
jan.koester's avatar
jan.koester committed
            backend.setPos(rd);
            backend.read((unsigned char*)user,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
            rd=backend.getPos();
jan.koester's avatar
jan.koester committed
            if(strcmp(user->fieldname,fieldname) == 0){
jan.koester's avatar
jan.koester committed
                user->data = new char[user->datasize];
                backend.read((unsigned char*)user->data,user->datasize);
jan.koester's avatar
jan.koester committed
                if(strcmp(user->data,value) == 0){
                    delete[] user->data;
jan.koester's avatar
jan.koester committed
                    goto VALUEFOUND;
jan.koester's avatar
jan.koester committed
                }
jan.koester's avatar
jan.koester committed
                delete[] user->data;
jan.koester's avatar
jan.koester committed
            }
            brd=rd;
        }
jan.koester's avatar
jan.koester committed
VALUEFOUND:
        return brd;
    AuthData::AuthData(const uuid_t id){
jan.koester's avatar
jan.koester committed
         Data = std::make_shared<AuthData::Record>();
         memset(Data.get(),0,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
         uuid_copy(Data->uuid,id);
jan.koester's avatar
jan.koester committed
         Data->start=0xFE;
         Data->storage=EmptyStorage;
jan.koester's avatar
jan.koester committed
         Data->type=DataType::EmptyData;
         Data->fieldname[0]='\0';
         Data->data=nullptr;
         Data->datasize=0;
jan.koester's avatar
jan.koester committed
        _next=nullptr;
    }

jan.koester's avatar
jan.koester committed
    AuthData::AuthData(const AuthData &src) : AuthData(src.Data->uuid){
jan.koester's avatar
jan.koester committed
        std::shared_ptr<AuthData> dest(this);
jan.koester's avatar
jan.koester committed
        for(std::shared_ptr<AuthData> cursrc=std::make_shared<AuthData>(src); cursrc!=nullptr;
            cursrc=cursrc->_next){

            memcpy(dest->Data.get(),cursrc->Data.get(),sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
            dest->Data->datasize=cursrc->Data->datasize;
            dest->Data->data=new char[dest->Data->datasize];
            memcpy(dest->Data->data,cursrc->Data->data,cursrc->Data->datasize);
            if(cursrc->next()){
jan.koester's avatar
jan.koester committed
                dest->_next=std::make_shared<AuthData>(cursrc->Data->uuid);
                dest=dest->_next;
            }
        }
jan.koester's avatar
jan.koester committed
    AuthData::~AuthData(){
jan.koester's avatar
jan.koester committed
    std::shared_ptr<AuthData> AuthData::next() const{
jan.koester's avatar
jan.koester committed
        return _next;
jan.koester's avatar
jan.koester committed
    bool authdb::AuthData::empty(){
        if(!Data->data)
            return true;
        return false;
    };

jan.koester's avatar
jan.koester committed
    std::shared_ptr<AuthData> AuthData::append(const AuthData &src){
        std::shared_ptr<AuthData> curec(this),next(this);
jan.koester's avatar
jan.koester committed
        if(!curec->_next && curec->Data->datasize==0){
jan.koester's avatar
jan.koester committed
            for(std::shared_ptr<AuthData> cursrc=std::make_shared<AuthData>(src); cursrc; cursrc=cursrc->next()){
jan.koester's avatar
jan.koester committed
                next=next->append(*cursrc->Data);
jan.koester's avatar
jan.koester committed
            }
            return curec;
        }
jan.koester's avatar
jan.koester committed
        while(curec){
jan.koester's avatar
jan.koester committed
            if(!curec->_next){
jan.koester's avatar
jan.koester committed
                curec->_next= std::make_shared<AuthData>(src);
jan.koester's avatar
jan.koester committed
                curec=curec->_next;
                break;
            }
            curec=curec->_next;
jan.koester's avatar
jan.koester committed
        };
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        return curec;
    }

jan.koester's avatar
jan.koester committed
    std::shared_ptr<AuthData> AuthData::append(const AuthData::Record &src){
        std::shared_ptr<AuthData> curec(this);
jan.koester's avatar
jan.koester committed
        if(!curec->_next && curec->Data->datasize==0){
jan.koester's avatar
jan.koester committed
            memcpy(curec->Data.get(),&src,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
            curec->Data->data=new char[curec->Data->datasize];
            memcpy(curec->Data->data,src.data,curec->Data->datasize);
            return curec;
        }

        while(curec){
jan.koester's avatar
jan.koester committed
            if(!curec->_next){
jan.koester's avatar
jan.koester committed
                curec->_next=std::make_shared<AuthData>(Data->uuid);
jan.koester's avatar
jan.koester committed
                curec=curec->_next;
jan.koester's avatar
jan.koester committed
                curec->append(src);
jan.koester's avatar
jan.koester committed
                break;
            }
            curec=curec->_next;
jan.koester's avatar
jan.koester committed
        };
jan.koester's avatar
jan.koester committed

        return curec;
    }

    bool getRecord(authdb::AuthBackend &backend,AuthData &rec,int type){
jan.koester's avatar
jan.koester committed
        bool found=false;
        int rd=sizeof(authdb::AuthHeader),end=backend.end();

        while(rd<end){
jan.koester's avatar
jan.koester committed
            std::shared_ptr<AuthData::Record> cur(new AuthData::Record());
jan.koester's avatar
jan.koester committed
            backend.setPos(rd);
jan.koester's avatar
jan.koester committed
            backend.read(reinterpret_cast<unsigned char*>(cur.get()),sizeof(AuthData::Record));
            rd=backend.getPos()+cur->datasize;
            if(uuid_compare(cur->uuid,rec.Data->uuid) == 0 && cur->type == type){
                cur->data=new char[cur->datasize];
                backend.read((unsigned char*)cur->data,cur->datasize);
                rec.append(*cur);
jan.koester's avatar
jan.koester committed
                found=true;
jan.koester's avatar
jan.koester committed
            }
        }
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        return found;
    }
    bool editRecord(AuthBackend &backend,AuthData &rec,int type){
        AuthData old(rec.Data->uuid);
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        std::vector<std::shared_ptr<AuthData::Record>> changemap; //use fieldname;
        std::vector<std::shared_ptr<AuthData::Record>> newmap;
jan.koester's avatar
jan.koester committed

        getRecord(backend,old,type);
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        for(std::shared_ptr<AuthData> curdat=std::make_shared<AuthData>(rec); curdat; curdat=curdat->_next){
jan.koester's avatar
jan.koester committed
            bool newentry=true;
jan.koester's avatar
jan.koester committed
            if(rec.Data->datasize==0)
                continue;

jan.koester's avatar
jan.koester committed
            for(std::shared_ptr<AuthData> olddat=std::make_shared<AuthData>(old); olddat; olddat=olddat->_next){
                if(uuid_compare(olddat->Data->uuid,curdat->Data->uuid)==0
jan.koester's avatar
jan.koester committed
                    && strcmp(olddat->Data->fieldname,curdat->Data->fieldname)==0
                ){
                    size_t end = olddat->Data->datasize;
                    if(end!=curdat->Data->datasize){
jan.koester's avatar
jan.koester committed
                        changemap.emplace_back(curdat->Data);
jan.koester's avatar
jan.koester committed
                    }else{
                        for(size_t i=0; i<end; ++i){
                            if(olddat->Data->data[i]!=curdat->Data->data[i]){
jan.koester's avatar
jan.koester committed
                                changemap.emplace_back(curdat->Data);
jan.koester's avatar
jan.koester committed
                                break;
                            }
                        }
                    }
                    newentry=false;
                }
            }

            if(newentry){
jan.koester's avatar
jan.koester committed
                newmap.emplace_back(curdat->Data);
jan.koester's avatar
jan.koester committed
            }

        }

        for(auto newel : newmap){
            backend.setPos(backend.end());
jan.koester's avatar
jan.koester committed
            backend.write((unsigned char*)newel.get(),sizeof(AuthData::Record));;
jan.koester's avatar
jan.koester committed
            backend.write((unsigned char*)newel->data,newel->datasize);
jan.koester's avatar
jan.koester committed
        }

        const unsigned char zero = 0;


        for(auto chel : changemap){
            size_t rd=sizeof(authdb::AuthHeader),end=backend.end();
            while(rd<end){
jan.koester's avatar
jan.koester committed
                authdb::AuthData::Record *rdrec=new AuthData::Record;
                backend.setPos(rd);
                backend.read((unsigned char*)rdrec,sizeof(AuthData::Record));
                if(uuid_compare(rdrec->uuid,rec.Data->uuid)==0 && strcmp(rdrec->fieldname,chel->fieldname)==0){
jan.koester's avatar
jan.koester committed
                    backend.setPos(backend.end());
jan.koester's avatar
jan.koester committed
                    backend.write((const unsigned char*)chel.get(),sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
                    backend.write((const unsigned char*)chel->data,chel->datasize);
                    size_t dsize=rdrec->datasize;
jan.koester's avatar
jan.koester committed
                    memset(rdrec,0,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
                    rdrec->start = 0xFE;
jan.koester's avatar
jan.koester committed
                    rdrec->datasize=dsize;
jan.koester's avatar
jan.koester committed
                    backend.setPos(rd);
                    backend.write((const unsigned char*)rdrec,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
                    for(size_t i =0; i<rdrec->datasize; ++i){
                        backend.write(&zero,1);
                    }
                    rd=backend.getPos();
                }else{
                    rd=backend.getPos()+rdrec->datasize;
                }
                delete rdrec;
            }
        }

        if(!changemap.empty() || !newmap.empty())
            return true;
        return false;
    }

jan.koester's avatar
jan.koester committed
    void delRecord(AuthBackend &backend,const uuid_t uid,int type){
jan.koester's avatar
jan.koester committed
        size_t end=backend.end(),rd=sizeof(AuthHeader);

        if(!uid)
            throw AuthBackendError("user info uid required!");

        while(rd<end){
jan.koester's avatar
jan.koester committed
            authdb::AuthData::Record *cur=new AuthData::Record;
            backend.setPos(rd);
            size_t wr=backend.getPos();
jan.koester's avatar
jan.koester committed
            backend.read((unsigned char*)cur,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
            rd=backend.getPos()+cur->datasize;
jan.koester's avatar
jan.koester committed
            if(uuid_compare(uid,cur->uuid) == 0 && type == cur->type){
jan.koester's avatar
jan.koester committed
                size_t dsize=cur->datasize;
                memset(cur,0,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
                cur->start = 0xFE;
jan.koester's avatar
jan.koester committed
                cur->datasize=dsize;
jan.koester's avatar
jan.koester committed
                backend.setPos(wr);
                backend.write((unsigned char*)cur,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
                const unsigned char zero=0;
                for(size_t i=0; i<dsize; ++i){
                    backend.write(&zero,1);
                }
            }
            delete cur;
        }
    }

    DomainBackend::DomainBackend(authdb::AuthBackend &adminbck) : _adminbck(adminbck) {
        _domainbck=nullptr;
    }

    authdb::AuthBackend *DomainBackend::data(uuid_t did){
        size_t rd=sizeof(authdb::AuthHeader),end=_adminbck.end();

        while(rd<end){
            authdb::AuthData::Record cur;

            _adminbck.setPos(rd);
            _adminbck.read((unsigned char*)&cur,sizeof(AuthData::Record));

            rd=_adminbck.getPos()+cur.datasize;

            if(uuid_compare(cur.uuid,did) == 0 && cur.type == DataType::DomainData &&
jan.koester's avatar
jan.koester committed
                strcmp(cur.fieldname,"domainname")==0){

                class DomainData ddat(cur.uuid);

jan.koester's avatar
jan.koester committed
                size_t dpos=sizeof(authdb::AuthHeader);
jan.koester's avatar
jan.koester committed
                Domain domain;
                domain.info(_adminbck,ddat,dpos);
jan.koester's avatar
jan.koester committed
                _domainbck = new AuthBackend(ddat.getStorageType(),ddat.getStorageOptions(),ddat.getDomainName());
            }
        }
        return _domainbck;
    }

    DomainBackend::~DomainBackend(){
        delete _domainbck;
    }
jan.koester's avatar
jan.koester committed
};

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;
    }
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
    confplus::Config config(cmd.getCmdbyKey("config")->getValue());

    authdb::AuthBackend backend(authdb::AuthBackendType::File,
                                config.getValue(config.getKey("/AUTHDB/ADMINDB/PATH"),0),
                                "admin.local"
                                );
    try {
jan.koester's avatar
jan.koester committed
        libhttppp::HttpD httpd(
            config.getValue(config.getKey("/AUTHDB/BIND"),0),
jan.koester's avatar
jan.koester committed
                               config.getIntValue(config.getKey("/AUTHDB/PORT"),0),
                               config.getIntValue(config.getKey("/AUTHDB/MAXCONN"),0),
                               nullptr,
                               nullptr
jan.koester's avatar
jan.koester committed
        );
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
        authdb::AuthDB authdb(backend,httpd.getServerSocket());
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
      //  authdb.threads=2;
jan.koester's avatar
jan.koester committed
        authdb.runEventloop();
jan.koester's avatar
jan.koester committed
    }catch(authdb::AuthBackendError &e){
        std::cerr << e.what() << std::endl;
    }
jan.koester's avatar
jan.koester committed
}