Skip to content
authdb.cpp 66.1 KiB
Newer Older
jan.koester's avatar
jan.koester committed
                        << "/editgroup/" << cruid << "\">Edit group</a></li>"
                        << "</ul></td></tr>";
jan.koester's avatar
jan.koester committed
                    }catch(AuthBackendError &e){
                        std::cerr << e.what() << std::endl;
                    }
                }
            }
jan.koester's avatar
jan.koester committed
            content->appendChild(domel);

jan.koester's avatar
jan.koester committed
            grouplist << "</table></div><div><ul class=\"grouptoolbar\" ><li><a class=\"button\" href=\"/settings/"<< cdid << "/creategroup\">CreateGroup</a></li></ul></div>";
jan.koester's avatar
jan.koester committed

            content->appendChild(grouplist.parse());

            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 createGroup(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args,const char *url){
jan.koester's avatar
jan.koester committed
            libhtmlpp::HtmlString form,out;

            libhtmlpp::HtmlElement root=_IndexElement,*content=root.getElementbyID("content");

            char cdid[255];
            uuid_t did;

            if(sscanf(curreq->getRequestURL(),"/settings/%[^/]",cdid)<0){
                throw AuthBackendError("createGroups: wrong url!");
            }

            DomainBackend dbackend(_AdminBackend);

            AuthBackend *backend=nullptr;

jan.koester's avatar
jan.koester committed
            if(strcmp(cdid,"admin") == 0 ){
                backend=&_AdminBackend;
            }else if(uuid_parse(cdid,did) == 0 ){
jan.koester's avatar
jan.koester committed
                backend=dbackend.data(did);
            }else{
jan.koester's avatar
jan.koester committed
                throw AuthBackendError("createGroups: could not parse uuid!");
jan.koester's avatar
jan.koester committed
            }

            if(!backend)
                throw AuthBackendError("createGroups: no backend seleted!");

            libhttppp::HttpForm curform;
            curform.parse(curreq);

            if (curform.getBoundary()) {
                size_t gcount=0;
                std::string gname;

                uuid_t gid;
                uuid_generate(gid);

jan.koester's avatar
jan.koester committed
                class GroupData grpdat(gid);

                struct GroupData::MemberUids member;
jan.koester's avatar
jan.koester committed

                for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData();
                     curformdat; curformdat = curformdat->nextData()) {

                    if(curformdat->Value.empty())
                        continue;


                    for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition();
                        curdispo; curdispo=curdispo->nextContentDisposition()
                    ){
                        std::string tmp=curdispo->getKey();

                        std::transform(tmp.begin(), tmp.end(), tmp.begin(),
                                       [](unsigned char c){ return std::tolower(c); });

                        if(tmp=="name" && strcmp(curdispo->getValue(),"members")==0){
                            ++gcount;
                        }

                        if(tmp=="name" && strcmp(curdispo->getValue(),"groupname")==0){
                            std::copy(curformdat->Value.begin(),curformdat->Value.end(),std::back_inserter(gname));
                        }

                    }
                }

                if(gname.empty())
                    throw AuthBackendError("createGroups: no doamin name given");

jan.koester's avatar
jan.koester committed
                Group grp;

                grpdat.setName(gname.c_str());

                member.count=gcount;
                member.uid = new uuid_t[gcount];
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
                size_t git=0;
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
                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()
                    ){
                        std::string tmp=curdispo->getKey();

                        std::transform(tmp.begin(), tmp.end(), tmp.begin(),
                                       [](unsigned char c){ return std::tolower(c); });

                        if(tmp=="name" && strcmp(curdispo->getValue(),"members")==0){
jan.koester's avatar
jan.koester committed
                            uuid_parse(curformdat->Value.data(),member.uid[git]);
jan.koester's avatar
jan.koester committed
                grpdat.addMember(member);

                grp.create(*backend,&grpdat);

                delete[] member.uid;
jan.koester's avatar
jan.koester committed
            }

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

            form  << "<form method=\"post\" enctype=\"multipart/form-data\">"
                  << "<table>"
                  << "<tr><th>Create Group:</th></tr>"
                  << "<tr><td><label for=\"groupname\">groupname:</label></td>"
                  << "<td><input type=\"text\" name=\"groupname\"></td></tr>"
                  << "<tr><td>Members:</td>"
                  << "<td><select name=\"members\" multiple>";
            while(rd<end){
                authdb::AuthData::Record cur;

                cur.type=EmptyData;

                backend->setPos(rd);
                backend->read((unsigned char*)&cur,sizeof(AuthData::Record));

                rd=backend->getPos()+cur.datasize;

                if(cur.type == UserData && strcmp(cur.fieldname,"username")==0){
                    cur.data=new char[cur.datasize];
                    backend->read((unsigned char*)cur.data,cur.datasize);
                    char cuid[255];
                    uuid_unparse(cur.uuid,cuid);
                    form << "<option value=\"" << cuid << "\">" << cur.data << "</option>";
                    delete[] cur.data;
                }

            }
            form  << "</select></td></tr>"
                  << "<tr><td></td><td><input type=\"submit\" value=\"Create group\"></td></tr>"
                  << "</table>"
                  << "</form";

            content->appendChild(form.parse());

            libhtmlpp::print(&root,out,true);

            libhttppp::HttpResponse rep;
            rep.setContentType("text/html");
            rep.setContentLength(out.size());
            rep.send(curreq,out.c_str(),out.size());
jan.koester's avatar
jan.koester committed
        }

jan.koester's avatar
jan.koester committed
        void removeGroup(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args,const char *url){
            char cdid[255],gid[255];
            uuid_t did;

            if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/removegroup/%s",cdid,gid)<0){
                throw AuthBackendError("removeGroup: wrong url!");
            }

            DomainBackend dbackend(_AdminBackend);

            AuthBackend *backend=nullptr;

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

            Group group;

            uuid_t uuid;

            uuid_parse(gid,uuid);

            group.remove(*backend,uuid);

            libhttppp::HttpResponse rep;
            rep.setState(HTTP307);
            rep.setVersion(HTTPVERSION(1.1));
            char rurl[255];
            snprintf(rurl,255,"/settings/%s/listgroups",cdid);
            rep.setHeaderData("Location")->push_back(rurl);
            rep.setContentType("text/html");
            rep.send(curreq,nullptr,0);
        }

jan.koester's avatar
jan.koester committed
        void editGroup(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){
            char cdid[255],cgid[255];
            uuid_t did;

            if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/editgroup/%s",cdid,cgid)<0){
                throw AuthBackendError("listUsers: wrong url!");
            }

            DomainBackend dbackend(_AdminBackend);

            AuthBackend *backend=nullptr;

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


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

            uuid_t gid;
            uuid_parse(cgid,gid);

            AuthData editrec(gid);

            bool data = false;

            libhttppp::HttpForm curform;

            curform.parse(curreq);


            for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData();
                    curformdat; curformdat = curformdat->nextData()) {

                    AuthData curec(gid);

                    curec.Data->type=GroupData;
                    curec.Data->storage=EmptyStorage;

                    for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition();
                        curdispo; curdispo=curdispo->nextContentDisposition()
                    ){


                        if(curformdat->Value.empty() || !curdispo->getValue())
                            continue;

                        data = true;

                        std::string key;

                        if(curdispo->getKey())
                            key=curdispo->getKey();
                        else
                            continue;

                        std::transform(key.begin(), key.end(), key.begin(),
                                       [](unsigned char c){ return std::tolower(c); });

                        if(key=="name"){
                            strcpy(curec.Data->fieldname,curdispo->getValue());
                        }

                        if(key=="filename"){
                            curec.Data->storage=BinaryStorage;
                        }
                    }

                    if(curec.Data->storage==EmptyStorage){
                        bool numeric=true;

                        for(auto t : curformdat->Value){
                            if(!std::isdigit(t)){
                                numeric=false;
                                break;
                            }
                        }

                        if(numeric)
                            curec.Data->storage=IntStorage;
                        else
                            curec.Data->storage=TextStorage;
                    }



                    if(curec.Data->storage==TextStorage) {
                        curformdat->Value.push_back('\0');
                        curec.Data->datasize=curformdat->Value.size();
                        curec.Data->data=new char[curec.Data->datasize];
                        std::copy(curformdat->Value.begin(),
                                   curformdat->Value.end(),curec.Data->data);

                        editrec.append(curec);
                        delete[] curec.Data->data;
                    }else if(curec.Data->storage==BinaryStorage){
                        curec.Data->datasize=curformdat->Value.size();
                        curec.Data->data=new char[curec.Data->datasize];
                        memcpy(curec.Data->data,curformdat->Value.data(),
                               curformdat->Value.size());

                        editrec.append(curec);
                        delete[] curec.Data->data;
                    }else if(curec.Data->storage==IntStorage){
                        curformdat->Value.push_back('\0');

                        curec.Data->datasize=sizeof(int);
                        curec.Data->data=(char*)new int;
                        int val=atoi(curformdat->Value.data());
                        memcpy(curec.Data->data,&val,
                               curec.Data->datasize);

                        editrec.append(curec);
                        delete[] (int*)curec.Data->data;
                    }

            }

            if(data){
                editRecord(*backend,editrec,GroupData);
                libhttppp::HttpResponse rep;
                rep.setState(HTTP307);
                rep.setVersion(HTTPVERSION(1.1));
                char rurl[255];
                snprintf(rurl,255,"/settings/%s/listgroups",cdid);
                rep.setHeaderData("Location")->push_back(rurl);
                rep.setContentType("text/html");
                rep.send(curreq,nullptr,0);
                return;
            }
            libhtmlpp::HtmlPage page;

            libhtmlpp::HtmlString form,out;

            form  << "<form method=\"post\" enctype=\"multipart/form-data\">"
                  << "<table>";

            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,gid)==0 && cur.type==GroupData && cur.storage==TextStorage){
                    cur.data = new char[cur.datasize];
                    backend->read((unsigned char*)cur.data,cur.datasize);
                    try {
                        form  << "<tr><td><label for=\""<< cur.fieldname <<"\">" << cur.fieldname << "</label></td>"
                              << "<td><input type=\"text\" name=\"" << cur.fieldname << "\" value=\""
                              << cur.data <<"\"></td></tr>";
                    }catch(AuthBackendError &e){
                        std::cerr << e.what() << std::endl;
                    }
                    delete[] cur.data;
                } else if(uuid_compare(cur.uuid,gid)==0 && cur.type==GroupData && cur.storage==BinaryStorage
                    && strcmp(cur.fieldname ,"groupmembers")==0
                ){
                    cur.data = new char[cur.datasize];
                    backend->read((unsigned char*)cur.data,cur.datasize);

                    GroupData::MemberUids mrec;
                    memcpy(&mrec,cur.data,sizeof(GroupData::MemberUids));

                    mrec.uid=new uuid_t[mrec.count];
                    memcpy(mrec.uid,cur.data+sizeof(GroupData::MemberUids),
                           (sizeof(uuid_t)*mrec.count));

                    for(size_t i=0; i<mrec.count; ++i ){
                        size_t urd=sizeof(AuthHeader),uend=backend->end();
                        while(urd<uend){
                            authdb::AuthData::Record curu;
                            backend->setPos(urd);
                            backend->read((unsigned char*)&curu,sizeof(AuthData::Record));
                            urd=backend->getPos()+curu.datasize;

                            if(curu.type == UserData && uuid_compare(mrec.uid[i],curu.uuid) == 0 &&
                                curu.storage==TextStorage && strcmp(curu.fieldname,"username")==0){

                                curu.data = new char[curu.datasize];
                                backend->read((unsigned char*)curu.data,curu.datasize);
                                std::cout << curu.data << std::endl;
                                delete[] curu.data;
                                break;
                            }
                        }
                    }

                    delete[] mrec.uid;
                }

            }

            form  << "<tr><td></td><td><input type=\"submit\"></td></tr>"
                  << "</table>"
                  << "</form";

            libhtmlpp::HtmlElement root=_IndexElement;
            libhtmlpp::HtmlElement *content=root.getElementbyID("content");

            content->insertChild(form.parse());

            libhtmlpp::print(&root,out,true);

            libhttppp::HttpResponse rep;
            rep.setContentType("text/html");
            rep.setContentLength(out.size());
            rep.send(curreq,out.c_str(),out.size());
        }

jan.koester's avatar
jan.koester committed
        void SettingsController(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){
jan.koester's avatar
jan.koester committed
            _AdminBackend.lock();

            char domain[255],url[255];

jan.koester's avatar
jan.koester committed
            if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/%s",domain,url)<0)
jan.koester's avatar
jan.koester committed
                throw AuthBackendError("wrong url!");

jan.koester's avatar
jan.koester committed
            try {
jan.koester's avatar
jan.koester committed
                if(strncmp(url,"listusers",9)==0){
jan.koester's avatar
jan.koester committed
                    listUsers(curreq,tid,args,"listusers");
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"createuser",10)==0){
jan.koester's avatar
jan.koester committed
                    createUser(curreq,tid,args,"createuser");
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"removeuser",10)==0){
jan.koester's avatar
jan.koester committed
                    removeuser(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"edituser",8)==0){
jan.koester's avatar
jan.koester committed
                    editUser(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"listdomains",11)==0){
jan.koester's avatar
jan.koester committed
                    listDomains(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"createdomain",11)==0){
jan.koester's avatar
jan.koester committed
                    createDomain(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"removedomain",11)==0){
jan.koester's avatar
jan.koester committed
                    removeDomain(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"listgroups",10)==0){
                    listGroups(curreq,tid,args,"listgroups");
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"creategroup",10)==0){
jan.koester's avatar
jan.koester committed
                    createGroup(curreq,tid,args,"creategroup");
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"removegroup",10)==0){
                    removeGroup(curreq,tid,args,"removegroup");
jan.koester's avatar
jan.koester committed
                }else if(strncmp(url,"editgroup",9)==0){
                    editGroup(curreq,tid,args);
jan.koester's avatar
jan.koester committed
                }else{
                    libhtmlpp::HtmlElement root=_IndexElement;
                    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());
                }
            }catch(AuthBackendError &e){
                    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
            }
jan.koester's avatar
jan.koester committed
            _AdminBackend.unlock();
jan.koester's avatar
jan.koester committed
        }

        void RequestEvent(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){
jan.koester's avatar
jan.koester committed
            if(strncmp(curreq->getRequestURL(),"/settings",9)==0){
                SettingsController(curreq,tid,args);
            }if(strncmp(curreq->getRequestURL(),"/getavatar/",11)==0){
                getAvatar(curreq,tid,args);
jan.koester's avatar
jan.koester committed
            }else if(strncmp(curreq->getRequestURL(),"/api",4)==0){

jan.koester's avatar
jan.koester committed
            }else if(strncmp(curreq->getRequestURL(),"/authdb.js",10)==0){
                libhttppp::HttpResponse rep;
                rep.setContentType("text/javascript");
                rep.send(curreq,_AuthJs.data(),_AuthJs.size());
jan.koester's avatar
jan.koester committed
            }else{
                libhttppp::HttpResponse rep;
                rep.setState(HTTP307);
                rep.setVersion(HTTPVERSION(1.1));
jan.koester's avatar
jan.koester committed
                rep.setHeaderData("Location")->push_back("/settings/admin/index");
jan.koester's avatar
jan.koester committed
                rep.setContentType("text/html");
                rep.send(curreq,nullptr,0);
jan.koester's avatar
jan.koester committed
            }
jan.koester's avatar
jan.koester committed
        };
    private:
jan.koester's avatar
jan.koester committed
        authdb::AuthBackend     _AdminBackend;
jan.koester's avatar
jan.koester committed
        libhtmlpp::HtmlElement  _IndexElement;
        libhtmlpp::HtmlPage     _Indexpage;
jan.koester's avatar
jan.koester committed
        std::vector<char>       _AuthJs;
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:
jan.koester's avatar
jan.koester committed
        delete user;
jan.koester's avatar
jan.koester committed
        return brd;
    AuthData::AuthData(const uuid_t id){
jan.koester's avatar
jan.koester committed
         Data = new struct AuthData::Record;
jan.koester's avatar
jan.koester committed
         memset(Data,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){
        AuthData *dest=this;

        for(const AuthData *cursrc=&src; cursrc; cursrc=cursrc->next()){
            memcpy(dest->Data,cursrc->Data,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=new AuthData(cursrc->Data->uuid);
                dest=dest->_next;
            }
        }
jan.koester's avatar
jan.koester committed
    AuthData::~AuthData(){
jan.koester's avatar
jan.koester committed
        delete Data;
jan.koester's avatar
jan.koester committed
    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
    AuthData *AuthData::append(const AuthData &src){
jan.koester's avatar
jan.koester committed
        AuthData *curec=this,*next=this;
        if(!curec->_next && curec->Data->datasize==0){
            for(const AuthData *cursrc=&src; cursrc; cursrc=cursrc->next()){
                next->append(*src.Data);
                if(cursrc->next()){
                    next->_next=new AuthData(Data->uuid);
                    next=next->_next;
                }
            }
            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=new 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;
    }

    AuthData *AuthData::append(const AuthData::Record &src){
        AuthData *curec=this;
jan.koester's avatar
jan.koester committed
        if(!curec->_next && curec->Data->datasize==0){
            memcpy(curec->Data,&src,sizeof(AuthData::Record));
            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){
                curec->_next=new 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();
jan.koester's avatar
jan.koester committed
        AuthData *curec=&rec;
jan.koester's avatar
jan.koester committed

        while(rd<end){
            AuthData::Record cur;
            memset(&cur,0,sizeof(AuthData::Record));
jan.koester's avatar
jan.koester committed
            backend.setPos(rd);
            backend.read((unsigned char*)&cur,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);
                delete[] cur.data;
jan.koester's avatar
jan.koester committed
                found=true;
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
        std::vector<AuthData::Record*> changemap; //use fieldname;
        std::vector<AuthData::Record*> newmap;
        getRecord(backend,old,type);
jan.koester's avatar
jan.koester committed
        for(const AuthData *curdat=&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(const AuthData *olddat=&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){
                        changemap.push_back(curdat->Data);
                    }else{
                        for(size_t i=0; i<end; ++i){
                            if(olddat->Data->data[i]!=curdat->Data->data[i]){
                                changemap.push_back(curdat->Data);
                                break;
                            }
                        }
                    }
                    newentry=false;
                }
            }

            if(newentry){
                newmap.push_back(curdat->Data);
            }

        }

        for(auto newel : newmap){
            backend.setPos(backend.end());
jan.koester's avatar
jan.koester committed
            backend.write((unsigned char*)newel,sizeof(AuthData::Record));;
            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());
                    backend.write((const unsigned char*)chel,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;
        }
    }

jan.koester's avatar
jan.koester committed
int main(int argc, char *argv[]){
    cmdplus::CmdController &cmd=cmdplus::CmdController::getInstance();
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
    cmd.registerCmd("config",'c',true,nullptr,"Config Path");
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
    cmd.parseCmd(argc,argv);
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
    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"
                                );
jan.koester's avatar
jan.koester committed
    try {
jan.koester's avatar
jan.koester committed
        if(backend.end()<=sizeof(authdb::AuthHeader)){
jan.koester's avatar
jan.koester committed
            authdb::initalized=false;
jan.koester's avatar
jan.koester committed
        }

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