// -- Lisans Yonetim Paneli - UI --------------------------------------------------- // Uretici makinesinde: bagli fikocad'lari listele, aninda yetki/lisans ver, // uzaktan komut gonder, kilitle. Tum cihazlar TEK ekrandan yonetilir. // // Ag isleri lisans_yonetim_http.cpp'de; bu dosya yalniz CAZER. #include #include #include #include #include #include "lisans_yonetim.hpp" #include "fiko/core/gunluk.hpp" #include "fiko/ui/bilesen.hpp" #include "fiko/ui/bilesen_ek.hpp" #include "fiko/ui/tema.hpp" #include "imgui.h" #include "lisans_kimlikler.hpp" #include "lisans_uzaktan.hpp" // uzak kanal durumu + komut kayitlari namespace fiko { namespace { // -- Panel durumu (UI'a ozel; is mantigi degil) -------------------------------- struct UiDurum { char sunucu[128] = "https://fikoyt.com:9000"; char kullanici[64] = "admin"; char parola[64] = ""; char filtre[64] = ""; char komutMesaj[256] = ""; char ozelAnahtar[260] = ""; char yeniSeri[64] = ""; char yeniMusteri[128] = ""; char komutFiltre[64] = ""; int seciliCihaz = -1; int seciliKomut = 0; int yil = 0, ay = 0, gun = 0; bool suresiz = true; std::vector seciliKomutlar; // bilet icin secilen haklar bool ilkAcilis = true; i64 sonCevap = 0; }; UiDurum g_ui; std::vector g_cihazlar; // -- Yardimcilar --------------------------------------------------------------- std::string kucukHarf(const std::string& s) { std::string o = s; for (char& c : o) c = (char)std::tolower((unsigned char)c); return o; } // "2026-09-28T14:22:31..." -> "28.09 14:22" std::string kisaZaman(const std::string& iso) { if (iso.size() < 16) return iso; return iso.substr(8, 2) + "." + iso.substr(5, 2) + " " + iso.substr(11, 5); } ImVec4 durumRengi(const CihazOzet& c) { const ui::Tema& t = ui::tema(); if (c.kilitli) return t.hata; if (!c.cevrimici) return t.metinSoluk; if (c.seri.empty()) return t.uyari; return t.basari; } const char* durumEtiketi(const CihazOzet& c) { if (c.kilitli) return "KILITLI"; if (!c.cevrimici) return "cevrimdisi"; if (c.seri.empty()) return "LISANS YOK"; return "AKTIF"; } int durumLedKodu(const CihazOzet& c) { if (c.kilitli) return 3; if (!c.cevrimici) return 0; if (c.seri.empty()) return 2; return 1; } bool kucukHarfIcerir(const std::string& hay, const std::string& ara) { if (ara.empty()) return true; return kucukHarf(hay).find(kucukHarf(ara)) != std::string::npos; } } // namespace // ============================================================================== void lisansYonetimCiz(UygulamaBaglam& b, bool& acik) { if (!acik) return; const ui::Tema& t = ui::tema(); YonetimDurumu& durum = yonetimDurumu(); (void)b; ImGui::SetNextWindowSize(ImVec2(1220, 740), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(100, 70), ImGuiCond_FirstUseEver); bool gorunur = true; if (!ImGui::Begin("[SATICI] Lisans Yonetimi - Satici Konsolu", &gorunur, ImGuiWindowFlags_NoCollapse)) { ImGui::End(); if (!gorunur) acik = false; return; } if (!gorunur) { acik = false; ImGui::End(); return; } // ═══ UST SERIT: sunucu + oturum ═══════════════════════════════════════════ { ImGui::AlignTextToFramePadding(); ui::durumLed(durum.sunucuyaBagli ? 1 : 0, 6.0f); ImGui::SameLine(); ImGui::TextUnformatted("Sunucu"); ImGui::SameLine(); ImGui::SetNextItemWidth(230.0f); ImGui::InputText("##sunucu", g_ui.sunucu, sizeof g_ui.sunucu); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Lisans sunucusu adresi"); ImGui::SameLine(); ImGui::SetNextItemWidth(120.0f); ImGui::InputText("##kullanici", g_ui.kullanici, sizeof g_ui.kullanici); ImGui::SameLine(); ImGui::SetNextItemWidth(150.0f); ImGui::InputTextWithHint("##parola", "sifre", g_ui.parola, sizeof g_ui.parola, ImGuiInputTextFlags_Password); ImGui::SameLine(); if (durum.oturumAcik) { ui::rozet(durum.kullaniciAdi.c_str(), t.basari); ImGui::SameLine(); if (ui::buton("Cikis Yap", ImVec2(74, 0), ui::ButonTip::Ikincil)) { durum.oturumAcik = false; durum.kullaniciAdi.clear(); durum.sunucuyaBagli = false; g_cihazlar.clear(); ui::toastGoster("Oturum kapatildi", ui::ToastTip::Bilgi); } } else if (ui::buton("Baglan", ImVec2(96, 0), ui::ButonTip::Birincil)) { std::string hata; durum.yukleniyor = true; if (yonetimOturumAc(g_ui.sunucu, g_ui.kullanici, g_ui.parola, hata)) { ui::toastGoster("Sunucuya baglanildi", ui::ToastTip::Basari); } else { durum.cevapHatasi = hata; ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } durum.yukleniyor = false; std::memset(g_ui.parola, 0, sizeof g_ui.parola); } } if (!durum.cevapHatasi.empty()) { ImGui::Spacing(); ImGui::TextColored(t.hata, "[UYARI] %s", durum.cevapHatasi.c_str()); } // Bağlantı özeti: hangi sunucuya bağlı, kaç cihaz görülüyor (belirsizlik // bırakmaz — "0 cihaz" ile "yanlış sunucuya bağlı" karışmasın). { ImGui::Spacing(); const bool bagli = durum.oturumAcik && durum.sunucuyaBagli; ImGui::TextColored(bagli ? t.basari : t.metinSoluk, "%s Sunucu: %s", bagli ? "[BAGLI]" : "[KOPUK]", g_ui.sunucu); ImGui::SameLine(); ImGui::TextDisabled(" · %d cihaz listeleniyor · komut gonderilen: %d", (int)g_cihazlar.size(), durum.komutSayaci); } ImGui::Separator(); // ═══ ANA ICERIK: sol liste | sag detay ═════════════════════════════════════ const float solGenislik = 600.0f; ImGui::BeginChild("solpanel", ImVec2(solGenislik, 0), 0); ImGui::SetNextItemWidth(300.0f); ImGui::InputTextWithHint("##filtre", "[ARA] filtre (bilgisayar / seri / musteri)", g_ui.filtre, sizeof g_ui.filtre); ImGui::SameLine(); if (ui::buton("Yenile", ImVec2(100, 0), ui::ButonTip::Ikincil)) g_ui.ilkAcilis = true; ImGui::SameLine(); if (ui::buton("Temizle", ImVec2(74, 0), ui::ButonTip::Hayalet)) { std::memset(g_ui.filtre, 0, sizeof g_ui.filtre); } // Otomatik yenileme (3 sn) + ilk acilista hemen const float simdi = (float)ImGui::GetTime(); static float sonCekim = -99.0f; if (durum.oturumAcik && (g_ui.ilkAcilis || simdi - sonCekim > 3.0f)) { g_ui.ilkAcilis = false; sonCekim = simdi; std::string hata; if (yonetimCihazlariYenile(g_cihazlar, hata)) { durum.sunucuyaBagli = true; durum.cevapHatasi.clear(); } else { durum.cevapHatasi = hata; } } ImGui::Spacing(); ImGui::TextDisabled("%d cihaz | gonderilen komut: %d", (int)g_cihazlar.size(), durum.komutSayaci); if (g_cihazlar.empty()) { ImGui::Spacing(); ImGui::Separator(); if (durum.oturumAcik) { ImGui::TextDisabled("Henuz cihaz gorunmuyor."); ImGui::TextDisabled("Fikocad acildiginda burada belirir."); } else { ImGui::TextDisabled("Once sunucuya baglanin (ust satir)."); } } if (ImGui::BeginTable("cihaztablo", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, ImGui::GetContentRegionAvail().y - 10.0f))) { ImGui::TableSetupColumn("Bilgisayar", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Seri", ImGuiTableColumnFlags_WidthFixed, 105.0f); ImGui::TableSetupColumn("IP", ImGuiTableColumnFlags_WidthFixed, 92.0f); ImGui::TableSetupColumn("Son", ImGuiTableColumnFlags_WidthFixed, 78.0f); ImGui::TableSetupColumn("Durum", ImGuiTableColumnFlags_WidthFixed, 96.0f); ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableHeadersRow(); for (int i = 0; i < (int)g_cihazlar.size(); ++i) { const CihazOzet& c = g_cihazlar[(size_t)i]; if (!kucukHarfIcerir(c.bilgisayar + " " + c.seri + " " + c.musteri + " " + c.ip, g_ui.filtre)) continue; ImGui::PushID(i); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ui::durumLed(durumLedKodu(c), 4.0f); ImGui::SameLine(); if (ImGui::Selectable(c.bilgisayar.c_str(), g_ui.seciliCihaz == i, 0, ImVec2(ImGui::GetContentRegionAvail().x, 0))) g_ui.seciliCihaz = i; if (ImGui::IsItemHovered() && ImGui::BeginTooltip()) { ImGui::Text("Cihaz: %s", c.cihazKimlik.c_str()); ImGui::Text("Musteri: %s", c.musteri.empty() ? "-" : c.musteri.c_str()); ImGui::Text("Surum: %s", c.surum.empty() ? "-" : c.surum.c_str()); ImGui::TextDisabled("Sol tikla: yonet"); ImGui::EndTooltip(); } ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(c.seri.empty() ? "-" : c.seri.c_str()); ImGui::TableSetColumnIndex(2); ImGui::TextUnformatted(c.ip.empty() ? "-" : c.ip.c_str()); ImGui::TableSetColumnIndex(3); ImGui::TextDisabled("%s", kisaZaman(c.sonBaglanma).c_str()); ImGui::TableSetColumnIndex(4); ImGui::TextColored(durumRengi(c), "%s", durumEtiketi(c)); ImGui::PopID(); } ImGui::EndTable(); } ImGui::EndChild(); // ═══ SAG PANEL ══════════════════════════════════════════════════════════════ ImGui::SameLine(); ImGui::BeginChild("sagpanel", ImVec2(0, 0), 0); if (g_ui.seciliCihaz < 0 || g_ui.seciliCihaz >= (int)g_cihazlar.size()) { ImGui::TextDisabled("Soldaki listeden bir cihaz secin."); ImGui::EndChild(); ImGui::End(); return; } CihazOzet& c = g_cihazlar[(size_t)g_ui.seciliCihaz]; ui::baslikSeridi("[CIHAZ]", c.bilgisayar.c_str()); ImGui::SameLine(); ui::rozet(durumEtiketi(c), durumRengi(c)); ui::neonAyrac(); // -- Cihaz bilgisi ---------------------------------------------------------- if (ImGui::CollapsingHeader("Cihaz bilgisi", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Text("Cihaz kimligi : %s", c.cihazKimlik.c_str()); ImGui::Text("Seri : %s", c.seri.empty() ? "(lisanssiz)" : c.seri.c_str()); ImGui::Text("Musteri : %s", c.musteri.empty() ? "-" : c.musteri.c_str()); ImGui::Text("IP : %s", c.ip.empty() ? "-" : c.ip.c_str()); ImGui::Text("Surum : %s", c.surum.empty() ? "-" : c.surum.c_str()); ImGui::Text("Son baglanma : %s", kisaZaman(c.sonBaglanma).c_str()); ImGui::Spacing(); } // -- EYLEM 1: Uzaktan komut ------------------------------------------------- if (ImGui::CollapsingHeader("Uzaktan komut gonder", ImGuiTreeNodeFlags_DefaultOpen)) { const std::vector& bl = yonetimBeyazListe(); if (g_ui.seciliKomut >= (int)bl.size()) g_ui.seciliKomut = 0; ImGui::SetNextItemWidth(300.0f); if (ImGui::BeginCombo("##komutsec", bl[(size_t)g_ui.seciliKomut].c_str())) { for (int i = 0; i < (int)bl.size(); ++i) if (ImGui::Selectable(bl[(size_t)i].c_str(), g_ui.seciliKomut == i)) g_ui.seciliKomut = i; ImGui::EndCombo(); } if (ImGui::IsItemHovered()) ImGui::SetTooltip("Beyaz listedeki komutlar. Fikocad ayrica imza + gate dener."); ImGui::SetNextItemWidth(240.0f); ImGui::InputTextWithHint("##komutmesaj", "mesaj (opsiyonel)", g_ui.komutMesaj, sizeof g_ui.komutMesaj); ImGui::SameLine(); if (ui::buton("Gonder", ImVec2(110, 0), ui::ButonTip::Birincil)) { std::string hata; if (yonetimKomutGonder(c, bl[(size_t)g_ui.seciliKomut], g_ui.komutMesaj, hata)) { ui::toastGoster(("Gonderildi: " + bl[(size_t)g_ui.seciliKomut]).c_str(), ui::ToastTip::Basari); std::memset(g_ui.komutMesaj, 0, sizeof g_ui.komutMesaj); } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } } ImGui::Spacing(); } // -- EYLEM 2: Lisans / komut yetkilendir ----------------------------------- if (ImGui::CollapsingHeader("Lisans ver / komut yetkilendir", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::TextDisabled("Satilan komutlari sec -> bilet imzalanir -> cihaza aninda gider."); ImGui::SetNextItemWidth(220.0f); ImGui::InputTextWithHint("##yseri", "seri no (FKC-2026-0001)", g_ui.yeniSeri, sizeof g_ui.yeniSeri); ImGui::SameLine(); ImGui::SetNextItemWidth(260.0f); ImGui::InputTextWithHint("##ymusteri", "musteri adi", g_ui.yeniMusteri, sizeof g_ui.yeniMusteri); // Komut katalogu ImGui::Spacing(); ImGui::SetNextItemWidth(280.0f); ImGui::InputTextWithHint("##komutfiltre", "[ARA] komut filtresi", g_ui.komutFiltre, sizeof g_ui.komutFiltre); ImGui::SameLine(); ImGui::TextDisabled("%d kayit", lisansKimlikSayisi()); if (!g_ui.seciliKomutlar.empty()) { ImGui::SameLine(); if (ui::buton("Secimi temizle", ImVec2(120, 0), ui::ButonTip::Hayalet)) g_ui.seciliKomutlar.clear(); } if (ImGui::BeginChild("katalog", ImVec2(0, 190.0f), ImGuiChildFlags_Borders)) { const int toplam = lisansKimlikSayisi(); for (int i = 0; i < toplam; ++i) { const char* g = nullptr; const char* ad = nullptr; const char* kim = nullptr; if (!lisansKimlikKaydi(i, g, ad, kim)) continue; if (!kucukHarfIcerir(std::string(g) + " " + ad + " " + kim, g_ui.komutFiltre)) continue; const std::string k(kim); bool sec = std::find(g_ui.seciliKomutlar.begin(), g_ui.seciliKomutlar.end(), k) != g_ui.seciliKomutlar.end(); ImGui::PushID(i); const std::string etiket = std::string(g) + " > " + ad; if (ImGui::Checkbox(etiket.c_str(), &sec)) { if (sec) g_ui.seciliKomutlar.push_back(k); else g_ui.seciliKomutlar.erase( std::remove(g_ui.seciliKomutlar.begin(), g_ui.seciliKomutlar.end(), k), g_ui.seciliKomutlar.end()); } if (ImGui::IsItemHovered()) ImGui::SetTooltip("Kimlik: %s", kim); ImGui::SameLine(); ImGui::TextDisabled("(%s)", kim); ImGui::PopID(); } ImGui::EndChild(); } // Anahtar ImGui::Spacing(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 110.0f); ImGui::InputTextWithHint("##anahtaryolu", "ozel anahtar dosyasi (.key)", g_ui.ozelAnahtar, sizeof g_ui.ozelAnahtar); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Uretici makinesindeki ozel imza anahtari.\n" "Bileti o imzalar; musteride bu dosya ASLA bulunmaz."); ImGui::SameLine(); if (ui::buton("Sec", ImVec2(74, 0), ui::ButonTip::Ikincil)) { // varsayilan yol onerisi const char* up = std::getenv("USERPROFILE"); if (up) std::snprintf(g_ui.ozelAnahtar, sizeof g_ui.ozelAnahtar, "%s\\.fikoyt\\lisans_ozel.key", up); } // Bitis ImGui::Spacing(); if (ui::anahtar("Suresiz", &g_ui.suresiz)) { /* aninda yansitir */ } if (!g_ui.suresiz) { ImGui::SameLine(); ImGui::SetNextItemWidth(70.0f); ImGui::InputInt("##gun", &g_ui.gun); ImGui::SameLine(); ImGui::TextUnformatted("gun"); ImGui::SameLine(); ImGui::SetNextItemWidth(70.0f); ImGui::InputInt("##ay", &g_ui.ay); ImGui::SameLine(); ImGui::TextUnformatted("ay"); ImGui::SameLine(); ImGui::SetNextItemWidth(70.0f); ImGui::InputInt("##yil", &g_ui.yil); } // Ozet + gonder ImGui::Spacing(); const bool hazir = !g_ui.seciliKomutlar.empty() && g_ui.ozelAnahtar[0] && (g_ui.suresiz || (g_ui.yil > 2000 && g_ui.ay > 0 && g_ui.gun > 0)); ImGui::Text("%d komut secildi", (int)g_ui.seciliKomutlar.size()); if (!g_ui.suresiz && g_ui.yil > 2000 && g_ui.ay > 0 && g_ui.gun > 0) { ImGui::SameLine(); ImGui::TextDisabled("| bitis: %02d.%02d.%04d", g_ui.gun, g_ui.ay, g_ui.yil); } ImGui::BeginDisabled(!hazir); if (ui::buton("LISANSI YAZ ve aninda gonder", ImVec2(-1, 34.0f), ui::ButonTip::Birincil)) { // Bitis hesapla (gece yarisi -> 23:59:59) i64 bitis = 0; if (!g_ui.suresiz) { std::tm tm{}; tm.tm_mday = g_ui.gun; tm.tm_mon = g_ui.ay - 1; tm.tm_year = g_ui.yil - 1900; tm.tm_hour = 23; tm.tm_min = 59; tm.tm_sec = 59; tm.tm_isdst = -1; const time_t tt = mktime(&tm); bitis = (i64)tt; } std::string hata; if (yonetimLisansYaz(g_ui.ozelAnahtar, c, g_ui.yeniMusteri, g_ui.yeniSeri, g_ui.seciliKomutlar, bitis, hata)) { ui::toastGoster("Lisans yazildi ve cihaza gonderildi", ui::ToastTip::Basari, 5.0f); } else { ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 8.0f); } } ImGui::EndDisabled(); if (!hazir) { ImGui::TextDisabled("[OK] komut sec | [OK] anahtar yolu | [OK] gecerli bitis tarihi"); } ImGui::Spacing(); } // -- KANAL DURUMU + KOMUT GECMISI (musteri tarafi) --------------------------- if (ImGui::CollapsingHeader("Uzak kanal durumu", ImGuiTreeNodeFlags_DefaultOpen)) { const UzakKanalDurum kd = uzakKanalDurumu(); ImGui::Text("Kanal: %s", uzakKanalDurumAdi(kd)); ImGui::SameLine(); ImGui::TextDisabled("| %s", uzakKanalOzet().c_str()); ImGui::Spacing(); ImGui::TextDisabled("Bu kanal URETICI tarafindan gelen komutlari karsilar " "(Engelle / Lisans yenile / Komut yetkilendir)."); if (!uzakKomutKayitlari().empty()) { ImGui::SameLine(); if (ui::buton("Gecmisi temizle", ImVec2(120, 0), ui::ButonTip::Hayalet)) uzakKomutKayitTemizle(); } } if (ImGui::CollapsingHeader("Son komutlar (bu makine)")) { if (uzakKomutKayitlari().empty()) { ImGui::TextDisabled("Henuz uzaktan komut calismadi."); } else if (ImGui::BeginTable("gecmis", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 160.0f))) { ImGui::TableSetupColumn("Saat", ImGuiTableColumnFlags_WidthFixed, 60.0f); ImGui::TableSetupColumn("Komut", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Sonuc", ImGuiTableColumnFlags_WidthFixed, 70.0f); ImGui::TableSetupColumn("Detay", ImGuiTableColumnFlags_WidthStretch); ImGui::TableHeadersRow(); for (const UzaktanKomutKaydi& k : uzakKomutKayitlari()) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::TextDisabled("%s", k.zaman.c_str()); ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(k.komutKodu.c_str()); ImGui::TableSetColumnIndex(2); ImGui::TextColored(k.basarili ? t.basari : t.hata, "%s", k.basarili ? "OK" : "RED"); ImGui::TableSetColumnIndex(3); ImGui::TextDisabled("%s", k.sonucMesaji.c_str()); } ImGui::EndTable(); } } // -- EYLEM 3: Kilitle ------------------------------------------------------- if (ImGui::CollapsingHeader("Kilit / kilit ac")) { ImGui::TextDisabled("Kilitle: tum komutlar kapanir (gorsuntuleyici kipi)."); if (ui::buton(c.kilitli ? "KILIT ACI" : "KILITLE", ImVec2(150, 0), c.kilitli ? ui::ButonTip::Birincil : ui::ButonTip::Tehlike)) { std::string hata; if (yonetimKilitle(c, !c.kilitli, "", hata)) ui::toastGoster(c.kilitli ? "Kilit acma gonderildi" : "Kilitleme gonderildi", ui::ToastTip::Basari); else ui::toastGoster(hata.c_str(), ui::ToastTip::Hata, 7.0f); } } ImGui::EndChild(); ImGui::End(); } } // namespace fiko