-- ───────────────────────────────────────────────────────────────────────────── -- ic-web – Netzwerkereignisse, Exports, Konsolenbefehle -- -- Jedes Ereignis ist frei aufrufbar und deshalb gedrosselt. Rechte werden -- ausnahmslos serverseitig aus der Anmeldung abgeleitet; der Client erfaehrt -- nur das Ergebnis. -- ───────────────────────────────────────────────────────────────────────────── local S = ICWeb.Sites local D = ICWeb.Domains local M = ICWeb.Manage local A = ICWeb.Auth local DB = ICWeb.DB local FW = ICWeb.FW local function reply(src, reqId, ok, data, err) TriggerClientEvent('ic-web:client:response', src, reqId, { ok = ok == true, data = data, error = err }) end -- ── Anmeldung ──────────────────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:login', function(reqId, username, password) local src = source -- Eng gedrosselt: die Sperre je Benutzername greift erst nach fuenf -- Versuchen, diese hier bremst das Durchprobieren vieler Benutzernamen. if not ICWeb.ThrottleOk(src, 'login', 8, 60000) then return reply(src, reqId, false, nil, 'Zu viele Versuche, bitte kurz warten.') end local session, err = A.Login(src, username, password) reply(src, reqId, session ~= nil, session, err) end) RegisterNetEvent('ic-web:server:logout', function(reqId) local src = source A.Logout(src) reply(src, reqId, true) end) -- Wer bin ich gerade? Ohne Anmeldung: data = nil, aber ok = true. RegisterNetEvent('ic-web:server:session', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'session', 20, 10000) then return end reply(src, reqId, true, { session = A.Public(src), themes = Config.Themes, tlds = Config.Domain.allowedTlds, imageHosts = Config.ImageHosts, provider = Config.MainAdmin.providerName, selfService = Config.SelfRegistration.enabled, }) end) RegisterNetEvent('ic-web:server:changePassword', function(reqId, accountId, password) local src = source if not ICWeb.ThrottleOk(src, 'passwd', 5, 60000) then return end local ok, err = M.SetAccountPassword(src, accountId, password) if ok then FW.Notify(src, 'Passwort geändert.') end reply(src, reqId, ok, nil, err) end) -- ── Lesen: jeder darf ──────────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:getSite', function(reqId, domain, slug) local src = source if not ICWeb.ThrottleOk(src, 'get', 30, 10000) then return end local site, err = S.GetPublic(domain, slug) reply(src, reqId, site ~= nil, site, err) end) -- ── Eigene Domaenen ────────────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:listMine', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'listMine', 10, 10000) then return end reply(src, reqId, true, S.ListMine(src)) end) RegisterNetEvent('ic-web:server:getEditable', function(reqId, domain) local src = source if not ICWeb.ThrottleOk(src, 'getEditable', 20, 10000) then return end local site, err = S.GetForEditor(src, domain) reply(src, reqId, site ~= nil, site, err) end) -- ── Selbstanmeldung einer Domaene (nur wenn eingeschaltet) ─────────────────── RegisterNetEvent('ic-web:server:register', function(reqId, domain, title) local src = source if not ICWeb.ThrottleOk(src, 'register', 3, 60000) then return reply(src, reqId, false, nil, 'Zu viele Versuche, bitte kurz warten.') end local site, err, credentials = D.Register(src, domain, title) if not site then ICWeb.Log.Write(src, 'domain.rejected', { domain = tostring(domain), reason = err }, 'warn') return reply(src, reqId, false, nil, err) end FW.Notify(src, ('Domäne %s registriert.'):format(site.domain)) reply(src, reqId, true, { domain = site.domain, title = site.title, credentials = credentials, }) end) -- ── Bearbeiten ─────────────────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:savePage', function(reqId, domain, slug, title, blocks) local src = source if not ICWeb.ThrottleOk(src, 'save', 20, 60000) then return reply(src, reqId, false, nil, 'Zu viele Speichervorgänge, bitte kurz warten.') end local ok, err = S.SavePage(src, domain, slug, title, blocks) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:deletePage', function(reqId, domain, slug) local src = source if not ICWeb.ThrottleOk(src, 'delete', 10, 60000) then return end local ok, err = S.DeletePage(src, domain, slug) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:updateSite', function(reqId, domain, data) local src = source if not ICWeb.ThrottleOk(src, 'update', 20, 60000) then return end if type(data) ~= 'table' then return reply(src, reqId, false, nil, 'Ungültige Daten.') end local ok, err = S.UpdateSite(src, domain, data) reply(src, reqId, ok, nil, err) end) -- ── Melden ─────────────────────────────────────────────────────────────────── -- Ohne Anmeldung: jeder Spieler soll eine Seite melden koennen. RegisterNetEvent('ic-web:server:report', function(reqId, domain, slug, reason) local src = source if not ICWeb.ThrottleOk(src, 'report', 5, 60000) then return end local ok, err = S.Report(src, domain, slug, reason) if ok then FW.Notify(src, 'Meldung eingegangen. Danke.') end reply(src, reqId, ok, nil, err) end) -- ── Postfaecher im Mailclient ─────────────────────────────────────────────── -- Ein Postfach freischalten ist eine Passwortpruefung wie die Anmeldung und -- deshalb genauso eng gedrosselt. RegisterNetEvent('ic-web:server:openMailbox', function(reqId, username, password) local src = source if not ICWeb.ThrottleOk(src, 'openMailbox', 8, 60000) then return reply(src, reqId, false, nil, 'Zu viele Versuche, bitte kurz warten.') end local ok, err = A.OpenMailbox(src, username, password) if ok then FW.Notify(src, 'Postfach hinzugefügt.') end reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:closeMailbox', function(reqId, username) local src = source if not ICWeb.ThrottleOk(src, 'closeMailbox', 20, 60000) then return end local ok, err = A.CloseMailbox(src, username) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:listMailboxes', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'listMailboxes', 20, 10000) then return end reply(src, reqId, true, A.ListOpenMailboxes(src)) end) -- ── Zugaenge je Domaene ───────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:listAccounts', function(reqId, domain) local src = source if not ICWeb.ThrottleOk(src, 'accounts', 20, 10000) then return end local list, err = M.ListAccounts(src, domain) reply(src, reqId, list ~= nil, list, err) end) RegisterNetEvent('ic-web:server:createAccount', function(reqId, domain, username, password, role, displayName) local src = source if not ICWeb.ThrottleOk(src, 'createAccount', 10, 60000) then return end local account, err = M.CreateAccount(src, domain, username, password, role, displayName) reply(src, reqId, account ~= nil, account, err) end) RegisterNetEvent('ic-web:server:setAccountPassword', function(reqId, accountId, password) local src = source if not ICWeb.ThrottleOk(src, 'setPassword', 10, 60000) then return end local ok, err = M.SetAccountPassword(src, accountId, password) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:setAccountActive', function(reqId, accountId, active) local src = source if not ICWeb.ThrottleOk(src, 'setActive', 20, 60000) then return end local ok, err = M.SetAccountActive(src, accountId, active == true) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:setAccountRole', function(reqId, accountId, role) local src = source if not ICWeb.ThrottleOk(src, 'setRole', 20, 60000) then return end local ok, err = M.SetAccountRole(src, accountId, role) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:deleteAccount', function(reqId, accountId) local src = source if not ICWeb.ThrottleOk(src, 'deleteAccount', 10, 60000) then return end local ok, err = M.DeleteAccount(src, accountId) reply(src, reqId, ok, nil, err) end) -- ── Anbieterebene ─────────────────────────────────────────────────────────── RegisterNetEvent('ic-web:server:adminListSites', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'adminList', 20, 10000) then return end local list, err = M.AdminListSites(src) reply(src, reqId, list ~= nil, list, err) end) RegisterNetEvent('ic-web:server:adminListAccounts', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'adminAccounts', 20, 10000) then return end local list, err = M.AdminListAccounts(src) reply(src, reqId, list ~= nil, list, err) end) RegisterNetEvent('ic-web:server:adminListJobs', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'adminJobs', 10, 10000) then return end local list, err = M.AdminListJobs(src) reply(src, reqId, list ~= nil, list, err) end) RegisterNetEvent('ic-web:server:adminRegister', function(reqId, domain, title, ownerId, adminUser, adminPassword) local src = source if not ICWeb.ThrottleOk(src, 'adminRegister', 10, 60000) then return end local site, err, credentials = M.AdminRegister(src, domain, title, ownerId, adminUser, adminPassword) reply(src, reqId, site ~= nil, site and { domain = site.domain, credentials = credentials } or nil, err) end) RegisterNetEvent('ic-web:server:adminSetBlocked', function(reqId, domain, blocked) local src = source if not ICWeb.ThrottleOk(src, 'adminBlock', 20, 60000) then return end local ok, err = M.AdminSetBlocked(src, domain, blocked == true) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:adminSetOwner', function(reqId, domain, ownerId) local src = source if not ICWeb.ThrottleOk(src, 'adminOwner', 10, 60000) then return end local ok, err = M.AdminSetOwner(src, domain, ownerId) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:adminDeleteSite', function(reqId, domain) local src = source if not ICWeb.ThrottleOk(src, 'adminDelete', 5, 60000) then return end local ok, err = M.AdminDeleteSite(src, domain) reply(src, reqId, ok, nil, err) end) RegisterNetEvent('ic-web:server:adminListReports', function(reqId) local src = source if not ICWeb.ThrottleOk(src, 'adminReports', 20, 10000) then return end local list, err = M.AdminListReports(src) reply(src, reqId, list ~= nil, list, err) end) RegisterNetEvent('ic-web:server:adminSetReportStatus', function(reqId, id, status) local src = source if not ICWeb.ThrottleOk(src, 'adminReportStatus', 30, 60000) then return end local ok, err = M.AdminSetReportStatus(src, id, status) reply(src, reqId, ok, nil, err) end) -- ── Konsolenbefehle ───────────────────────────────────────────────────────── -- Kein IC-Weg, sondern die Notbremse des Serverbetreibers. Absichtlich nur in -- der Serverkonsole und fuer Serveradmins – nicht ueber die Anmeldung. local function consoleAllowed(src) if not src or src == 0 then return true end return FW.IsAdmin(src) end RegisterCommand('webpasswd', function(src, args) if not consoleAllowed(src) then return end local username = tostring(args[1] or ''):lower() local password = tostring(args[2] or '') if username == '' or password == '' then print('[ic-web] /webpasswd ') return end local account = DB.GetAccountByUsername(username) if not account then print('[ic-web] Zugang nicht gefunden.') return end local ok, err = A.SetPassword(account.id, password) print(ok and ('[ic-web] Passwort von %s geändert.'):format(username) or ('[ic-web] Fehlgeschlagen: %s'):format(tostring(err))) end, true) RegisterCommand('webaccounts', function(src) if not consoleAllowed(src) then return end local rows = DB.GetAllAccounts() print(('[ic-web] %d Zugänge:'):format(#rows)) for _, a in ipairs(rows) do print((' %-34s %-11s %-22s %s'):format( a.username, a.role, a.domain or '—', ICWeb.Bool(a.active) and 'aktiv' or 'gesperrt')) end end, true) RegisterCommand('webreports', function(src) if not consoleAllowed(src) then return end local reports = DB.GetOpenReports() if #reports == 0 then print('[ic-web] Keine offenen Meldungen.') return end print(('[ic-web] %d offene Meldungen:'):format(#reports)) for _, r in ipairs(reports) do print((' #%d %-24s %-10s %s'):format( r.id, r.domain, r.page_slug or '-', (r.reason or ''):sub(1, 60))) end print('[ic-web] Sperren mit /webblock , erledigen mit /webreport done ') end, true) RegisterCommand('webblock', function(src, args) if not consoleAllowed(src) then return end local domain = tostring(args[1] or ''):lower() local site = DB.GetSiteByDomain(domain) if not site then print('[ic-web] Domäne nicht gefunden.') return end local blocked = not ICWeb.Bool(site.blocked) DB.SetBlocked(site.id, blocked) ICWeb.Log.Write(src, blocked and 'site.blocked' or 'site.unblocked', { domain = domain }, 'warn') print(('[ic-web] %s ist jetzt %s.'):format(domain, blocked and 'gesperrt' or 'frei')) end, true) RegisterCommand('webreport', function(src, args) if not consoleAllowed(src) then return end local action = tostring(args[1] or '') local id = tonumber(args[2]) if (action ~= 'done' and action ~= 'dismiss') or not id then print('[ic-web] /webreport done oder /webreport dismiss ') return end DB.SetReportStatus(id, action == 'done' and 'reviewed' or 'dismissed') print(('[ic-web] Meldung #%d als %s markiert.'):format(id, action)) end, true) -- ── Exports fuer andere Resources ──────────────────────────────────────────── exports('GetSite', function(domain, slug) return S.GetPublic(domain, slug) end) exports('DomainExists', function(domain) return DB.GetSiteByDomain(tostring(domain or ''):lower()) ~= nil end) exports('GetSitesForJob', function(job) return DB.GetSitesForOwner('job', job) end) -- Wer ist an diesem Bildschirm angemeldet? pc-live nutzt das, um das Postfach -- des Zugangs zu oeffnen statt des persoenlichen. exports('GetSession', function(src) return A.Public(src) end) -- ── Start ──────────────────────────────────────────────────────────────────── AddEventHandler('onResourceStart', function(res) if res ~= GetCurrentResourceName() then return end if GetResourceState('ic-mail') ~= 'started' then print('[ic-web] ^3Hinweis^7: ic-mail läuft nicht – Domänen werden ohne Postfächer angelegt.') end A.EnsureMainAdmin() A.CleanupStaleMailAccess() DB.PruneLoginFails(86400) local sites = MySQL.single.await('SELECT COUNT(*) AS n FROM ic_web_sites') print(('[ic-web] bereit. %d Domänen registriert.'):format((sites and sites.n) or 0)) end)