Mobil applikáció, "teszt" és "éles" REST endpointokkal
2022-07-28T20:10:00+02:00
2022-08-02T12:20:15+02:00
2022-08-02T12:35:25+02:00
  • Szerintem túlagyalod ezt az egészet. Attól, hogy megpróbálsz máshova is loginolni minimálisat változik az alkalmazásod és az általad problémaként említett dolgok egyike sem szivárog át a kliensedbe. Ha ilyen van az inkább tervezési hiba.

    Bár részleteket nem osztottál meg, nem gondolom, hogy valami nagy multitenant, több szervizes dologról lenne szó, mert akkor eleve lenne gateway, ki lenne emelve az sts külön komponensbe, stb. Gondolom összesen van 2 db. url-ed, ahova kapcsolódni kell. Nyilván, majd ha lesz 10 az más kérdés, de akkor már más problémák is lesznek.

    Éppen ezért szerintem a faék tökéletes megoldás.

    Ha a prioritás a prod loginon van, akkor az általános felhasználók semmit sem vesznek észre. A review vagy teszt usernek lassab lesz a login, mert egyel több request. Nyilván sikeres login után el kell menteni valahova, hogy melyik apit használja a kliens és onnantól pont úgy működik minden, mint egyébként.
    Mutasd a teljes hozzászólást!
  • Miért nem próbálsz loginloni mindkét endpointra?Amelyiken a kérés sikeres azt használhatja a user azt jó.

    Igazából ~pár extra request-ért cserébe ezt az egész tesztuser->teszturl / produser->produrl dolgot eliminálni lehetne, nem is rossz ötlet.
    Mutasd a teljes hozzászólást!
  • Miért nem próbálsz loginloni mindkét endpointra?Amelyiken a kérés sikeres azt használhatja a user azt jó.

    Azért mert a kiszolgálónál lévő adatbázisok konfigurációjáról vagy arról, hogy melyik user konkrétan melyik táblában van tárolva, én nem akarok tudni semmit.

    Viszont így nekem kellene az applikációban olyan kódokat (prod-on, a review miatt) megvalósítanom, ami kb végig scanneli az endpoint-okat ennek kiderítésére, holott a "szerver" tudja, hogy melyik user melyik adatbázisban van.

    ...

    De köszönöm a javaslatot, felírtam a listára :)
    Mutasd a teljes hozzászólást!
  • Teljesen mindegy, hogy az a döntés, hogy melyik endpointra kell csatlakozni hol és mikor születik meg és mi alapján. Az egyetlen tényező a speciális userek száma és annak változása lehet. Ha sok usert érint, akkor már nem speciális, hanem általános eset, ezért érdemes a szerver oldalon, userhez kapcsoltan kezelni szerintem.

    Helytálló az az érvelés, hogy mivel a 'rest api server' két url-en keresztül érhető el ("api.valami.com" és "test.api.valami.com"), ezért ezt nem server oldalon kell lekezelni?

    Nem. Tök mindegy melyik és milyen komponens dönti el.

    készítsen egy "gateway.api.valami.com" url-t, én arra elküldöm a request-eket

    Ez értelmetlen, mert a bevezetése csak úgy, magától nem oldja meg a problémát, hiszent továbbra sincs eldöntve, hogy hova kell kapcsolódni az adott felhasználónak, ellenben növeli a bonyolultságot. Nyilván ennek a létjogosultságát ennyi információból nem lehet eldönteni.

    Miért nem próbálsz loginloni mindkét endpointra?
    Amelyiken a kérés sikeres azt használhatja a user azt jó.
    Mutasd a teljes hozzászólást!
  • De attól félek, hogy később lesz még N ilyen kérés és a végén az applikáció 10 féle szerverre fogja küldeni a requesteket a leglehetetlenebb feltételek alapján..

    Attól, hogy ezt a kérést most így oldod meg, nem kell letenned a nagyesküt, hogy minden más kérést is így fogsz megoldani.

    Tegyük fel, hogy később kell majd több szintű jogosultságkezelés.. Ha akkor is az lesz a javaslat, hogy pl az adminok az "1-es" szerveren vannak tárolva, a manager-ek a "2-esen", mindenki más a "3-ason" és így tovább..

    Ez meg különösen abszurdnak hangzik. Hány olyan login képernyőt láttál, ahol a rendszer a jogosultsági szintedet is megkérdezi, aztán "bemondásra" elhiszi neked? Az ilyesmi nyilván a backend rendszer dolga, mivel azt nem tudja manipulálni a felhasználó.
    Mutasd a teljes hozzászólást!
  • Azzal nincs probléma, hogy ez így implementálható.. De attól félek, hogy később lesz még N ilyen kérés és a végén az applikáció 10 féle szerverre fogja küldeni a requesteket a leglehetetlenebb feltételek alapján..

    Tegyük fel, hogy később kell majd több szintű jogosultságkezelés.. Ha akkor is az lesz a javaslat, hogy pl az adminok az "1-es" szerveren vannak tárolva, a manager-ek a "2-esen", mindenki más a "3-ason" és így tovább.. vagy ne adj isten ezek valamilyen kombinációja, úgy hogy még ezek is lehetnek teszt/demo/dev userek...
    Mutasd a teljes hozzászólást!
  • Ha jól értem, csak rajtad múlik, hogy a kliensen is minden információ a rendelkezésedre álljon. Ha a mohalaci által javasolt módszert használnád, amikor "jozsi@example.com" egy production user, "test#jozsi@example.com" egy test user és "dev#jozsi@example.com" egy dev user, akkor a szerver oldalnak nem kéne routingot megvalósítania (értsd: eggyel kevesebb network hop). Továbbá ha van olyan üzleti igény, hogy valami csak teszt usernek látszódjon, azt megint csak el tudod dönteni "ránézésre", a backend meghívása nélkül. Valamint nem kell a backend oldalon extra táblát és logikát implementálni, hogy bizonyos felhasználókat máshová proxyzzon.
    Mutasd a teljes hozzászólást!
  • Visszatérve az alapfelvetéshez, arra szeretnék választ kapni (durván absztrahálva), hogy ha van 2 'aktor' és ezeknek vannak saját állapotterei, és az egyik oldalon egy feltételrendszer kiértékelésére minden információ rendelkezésre áll, akkor milyen előnye van annak, hogy ne ott 'kalkuláljunk' ki egy eredményt, ahol arra lehetőségünk van?
    Mutasd a teljes hozzászólást!
  • Ha egy url van es a szerver mondjuk username alapjan donti el, hogy hova routolja a requestet, akkor az ugyanolyan, mintha hardcode-olnad a usert kliens oldalon.

    Az igaz, hogy tulajdonképpen lesz egy 'one-one' megfeleltetés egy username és a backend egyik user-e között (akármelyik 'environment'-ben is van), de szerintem azért nem ugyanolyan (mintha kliens oldalon beleégetnénk a user-t), mert ha egy url-ről lenne kiszolgálva minden kérés, a kliens "black-box"-ként kezelhetné a server-t, tehát semmit sem kellene tudnia annak működéséről (ahogyan arról sem, hogy XY user request-re mi alapján jönnek vissza az adatok). <- A jelenlegi javaslat szerint viszont pont hogy a kliensnek kellene eldöntenie, hogy a felhasználók közötti milyenség az konkrétan milyen feltételrendszer alapján történik. Viszont az egyik (applikáció/kliens) oldalon tulajdonképpen csak az adatok megjelenítése / absztrakciója történik, a másik oldalon ellenben minden információ rendelkezésre áll az ominózus "át-route-olás" elvégzéséhez. Az egyik 'oldal' változtatása több napos review folyamat (amire semmilyen ráhatásunk sincs), a server adatbázisa "on the fly" módosítható.

    Es ha ketto ilyen user is kell? Akkor szolsz a szervernek, megvarod mig megtortenik a deploy es utana tudsz dolgozni tovabb. Ez marha lassu folyamat.

    Ez szerintem implementálható úgy, hogy a server egyik 'admin' felületén kitöltenek egy html form-ot (aminek hatására létrejön egy új user), ami éppenhogy sokkal gyorsabb, mint egy új app-ot build-elni és elküldeni több napos review-ra.
    Mutasd a teljes hozzászólást!
  • Szerintem semmilyen extra implementacio nem kell kliens oldalon, csak annyi, hogy valami alapjan eldontsd melyik kornyezetbe kuldd a requesteket.

    Az adott usernek a jogosultsagait ugyis a szerveren kell ellenorizni.

    Nalunk van igazabol vagy 8 kornyezet, login kepernyon az email cim elotti prefix alapjan dol el, hogy melyik kornyezetbe akarunk menni. Semmilyen mas logika nincs kliens oldalon.

    Regisztralok a teszt kornyezetbe es mukodik minden feature, regisztralok a demo kornyezetbe es tudom ellenorizni, hogy a szerver oldal nem-e epp azon ugykodik, hogy teljesen eltori a mobil appot. A szerver fejlesztok ugyanugy tudjak ellenorzni a sajat munkajuk egy storebol letoltott appal es a dev kornyezetbe valo belepessel. A PO tudja csekkolni a szerveres modositasokat/javitasokat a storeban levo appal es nekem szerencsere meg se kell mozdulnom hozza :)

    Ha egy url van es a szerver mondjuk username alapjan donti el, hogy hova routolja a requestet, akkor az ugyanolyan, mintha hardcode-olnad a usert kliens oldalon. Es ha ketto ilyen user is kell? Akkor szolsz a szervernek, megvarod mig megtortenik a deploy es utana tudsz dolgozni tovabb. Ez marha lassu folyamat.
    Mutasd a teljes hozzászólást!
  • Nagyon szépen köszönök minden eddig érkezett választ!
    Mutasd a teljes hozzászólást!
  • Igen, de szerintem a 'hardcode-olt' user logika az általam felvázolt problémában pont hogy a kliens oldalán jelentkezik (a mobil applikációban), miszerint ott kellene implementálni, hogy melyik user milyen tulajdonságokkal bír (ki 'sima' user, ki 'review' user, ki 'demo' user), ráadásul a prod buildben.

    Mind a két alkalmazásboltban ~pár nap az átfutási idő, mielőtt kimegy 'élesbe'.

    Azok az előnyök, amiket felsoroltál az 'appban való megoldás mellett', mind megvalósíthatóak úgy is, ha az applikáció egyetlen url-re küldi az összes request-et, a felhasználónevek vagy akármi más alapján történő feltételrendszer nélküli 'endpoint választó' logika nélkül.

    Ha egyetlen url-en keresztül történne minden kommunikáció az applikáció és az 'api-server' között, úgy hogy ez az egész 'valódi user' / 'review user' / 'test user' elválasztás a kliens program számára teljesen transzparens lenne, az miért kevésbé optimális?
    Mutasd a teljes hozzászólást!
  • Demo feature nem kerul ki a storeba optimalis esetben.

    Csinalj egy kulon branchet (repo az felesleges) implementald a demo featuret, adjal ki egy betat es nyomhatjak vakulasig akik demozni akarnak. Ha a demo feature production ready, akkor mergeled a branchet es mehet storeba.
    Mutasd a teljes hozzászólást!
  • Ezt nem lehet csak igy megmondani, hogy kliens vagy szerver oldalon kell ezt megoldani.

    Ha mindenaron szerveroldalon akarod megoldani, akkor hardcodeolt userek alapjan tudsz csak eljutni bizonyos kornyezetekbe.
    Ha kliens oldalon oldod meg, akkor barmikor csinalhatsz barmelyik kornyezetben egy uj usert, akivel tesztelhetsz appon keresztul.

    Erveim az appban valo megoldas mellett:
    - barmelyik userrel elerheto lesz minden kornyezet
    - release appal tudod a szerveroldali modositasokat ellenorizni, hogy egy uj feature a szerveren, kinyirja ez appod
    - a fonoknek a demozni egyszerubb, mert mondhatod neki, hogy a storeban levo appal is meg tudja nezni, hogy az uj szerverrel is mukodik minden
    - a szerveren egy bugfixet meg teszt kornyezetben tudjatok ellenorizni a storeban levo appal
    - mivel nem hardcodeolt usert hasznalsz, ezert nagyon sok esetet tudsz tesztelni anelkul, hogy a db-ben a hardcodeolt user adatait/tevekenyseget kitorolned, mert eleg egy uj usert letrehozni es kesz is (raadasul ekozben a kollega epp mutogatja valakinek az appot a hardcodeolt userrel, kvazi kihuznad alola a szeket egy demo kozben, ha te meg kitorlod a user korabbi adatait)
    Mutasd a teljes hozzászólást!
  • A "demó-funkciók"-ra vonatkozó résszel kapcsolatban nem fogalmaztam egyértelműen. Az az egyik felmerült kérés, hogy (a google/apple review userek mellett) legyenek speciális user-ek, akiknél valamilyen funkció / felületi elem.. stb aktiválódjon vagy sem (az applikáción belül). Ezek ilyen, a 'valódi user'-ek esetén nem tapasztalható, "demó" dolgok.

    Ez egy általánosan használt módszer?
    Nem jobb ha a "demo" és a prod build teljesen (külön repo, külön track, külön api) elkülönül egymástól?
    Mások hogy csinálják?
    Mutasd a teljes hozzászólást!
  • 100%-ban egyetértek veled, én is hasonlóan érveltem.

    A probléma az, hogy azok a felhasználónév/jelszó párok, amiket az alkalmazásbolt review folyamatának elvégzésére generáltak és amikkel az alkalmazáson belül be is lehet jelentkezni, azok csak a teszt/dev url-en működnek. (ezen az API fejlesztője nem akar változtatni <- de azt is hozzá tenném, hogy ez a kolléga is a mi cégünkben dolgozik, tehát az elvi lehetősége meglenne rá).

    Ezeket meg kell adni az alkalmazásboltokban, vagy reject (hiszen nekik "végig kell tudniuk nyomogatni" az egészet, mintha valódi felhasználók lennének). Tehát nekem a valódi felhasználóknak szánt prod applikáció kódjába bele kell írnom azt a kivételt (akármilyen feltételrendszer alapján), hogy bizonyos felhasználók esetén a program a teszt/dev url-re küldje a kéréseket, vagy nem megy át az applikáció a review-on.

    Azért vagyok konfliktusban az API fejlesztőjével, mert úgy gondolom, ezt a kiszolgáló oldalán kellene implementálni. Erre vonatkozott a topic indító egyik kérdés is, hogy egy ilyen üzleti logikának a kliens kódban vagy a szerveren van e a helye (?). <- Úgy hogy mindkét kódbázis "in-house" (ez utóbbi új info).
    Mutasd a teljes hozzászólást!
  • ...lesz egy közös kódbázis amiben összekeverve lesz nem csak ez a "request url váltogató" logika hanem az összes olyan kivételes eset (demó funkciók) is, ami ezeknél a speciális usereknél megváltoztatja az applikáció működését

    Amit @mohalaci írt az egy valid megoldás, mi is hasonló módon járunk el mobil kliens alapú fejlesztéseknél. Vannak megkülönböztetett "demo" user-ek, sajátos usr/pwd-vel - egy ilyet kap a Google is, ezzel elvégezhetik a review-t.
    A szerver oldali kódbázisból csak egy van, ez lenne a prod, így a Google közvetlenül a prod-ot nézheti, csak az adatbázisban van néhány megkülönböztetett user, akivel külsőleg tesztelhető a prod rendszer. Illetve az ügyfeleink számára is vannak fenntartva demo user-ek, a prod rendszerben. A kódbázisban nincsenek olyan "speciális" elágazások, amelyek csak demo user-ek számára érhetőek el. Ez teljesen felesleges is lenne. Ezért nem értem az általad említett "demó funkciók"-at.
    Ez mellett, a dev-es teszt rendszer csak a fejlesztőknek van fenntartva, ahhoz semmi köze sincs a Google-nek, arról nem is tudnak. Az ügyfeleink számára itt is vannak demo user-ek fenntartva, de itt inkább csak a funkcionalítást tesztelik, a prod-ban meg a stabilitást és az integrációt.

    Ettől függetlenűl léteznek tisztán "enterprise" alkalmazások is, ahol a kliens program nem is lehet publikus, így nem is adjuk át a Google Play-nek, azokat mi telepítjuk közvetlenül a céges telefonokra. Ha ilyen megoldásról van szó, akkor lehetséges, hogy neked is felsleges a Google-al, meg az Apple-el ez miatt szívni.
    Mutasd a teljes hozzászólást!
  • Nem ertem az ervelesed. Miert is akarsz egy demo featuret kirakni productionbe? A prod szerveren csak az erheto el, ami production ready. A teszt szerveren az erheto el, ami tesztelesre alkalmas. A demo szerveren az erheto el, ami meg fejlesztes alatt all, de mar mutogathato.

    App oldalon pedig ami nem production ready azt nem toltod fel a storeba. Kit erdekel, hogy a szerver tud N darab uj endpointot, ami meg teszt/dev fazisban van? Az appod nem fogja meghivni egyik ilyen endpointot se, ha nem irod meg a kodot hozza az appodban.
    Mutasd a teljes hozzászólást!
  • Igen, de így ahelyett hogy lenne egy teszt kliens, ami egy teszt endpointra csatlakozik és egy 'valódi' usereknek szánt, ami pedig a prod endpointra, lesz egy közös kódbázis amiben összekeverve lesz nem csak ez a "request url váltogató" logika hanem az összes olyan kivételes eset (demó funkciók) is, ami ezeknél a speciális usereknél megváltoztatja az applikáció működését. Ezt azért nem akarom csinálni, mert az N-edik "demó" funkció implementálása után ember legyen a talpán, aki megmondja, hogy most egy kód egy demó funkcionalitásért felelős vagy az általános működésért.
    Mutasd a teljes hozzászólást!
  • Mi ezt ugy oldjuk meg, hogy bejelentkezeskor az email cim ele lehet rakni prefixet, pl: test#akarki@example.com

    es egy egyszeru logikaval el tudod donteni, hogy a tovabbiakban a prod vagy teszt kornyezetbe menjenek az api hivasok.
    Mutasd a teljes hozzászólást!
  • Helytálló az az érvelés, hogy mivel a 'rest api server' két url-en keresztül érhető el ("api.valami.com" és "test.api.valami.com"), ezért ezt nem server oldalon kell lekezelni?

    Szerintem ... welcome to the real world. Ha van valami REST-es függőséged és nem fizetsz érte, akkor alkalmazkodnod kell hozzá. Izgalmas lenne, ha te mondhatnád meg más fejlesztőknek, hogy mit csináljanak, ez a világban inkább csak akkor megy, ha szerződésed van velük.

    Gyárts egy saját "proxy" REST apit, ami mindig továbbítja a hívásokat a megfelelő helyre. Vagy valósítsd meg az API-t magad.
    Mutasd a teljes hozzászólást!
  • Ha az előnyöket nézed, akkor az így implementált api gateway többet tud, mint a mod_rewrite.
    Lesz egy layer7-es load balancered.

    Rakhatsz bele healthchecket, több targetet, központi logolást, token validációt, ...
    Az AWS ilyenekre használja most a Lambda@Edget.
    Mutasd a teljes hozzászólást!
  • Arra gondoltam, hogy készítek egy google cloud functions-t, amiben ezzel: http-proxy-middleware a 'login' endpoint request paramétereinek kiolvasásával elvégzem a "teszt"/"prod" átirányítást, utána hozzáfűzök egy extra header-t a válaszhoz, amit a (mobil app) kliens eltárol és hozzáfűz minden további (rest api) request-ig, amig nincs felhasználó váltás <- az egy use-case, hogy valaki ugyanarról az eszközről másik felhasználóval is beléphet.. De szerintem ez a megközelítés is csak a kikerülése egy olyan problémának, amit a 'rest api' kiszolgáló egy sima "mod-rewrite"-al meg tudna oldani (hiszen rendelkezésre áll az összes adat).
    Mutasd a teljes hozzászólást!
  • sajnos a 'rest api endpoint' kódbázisához semmilyen hozzáférésem sincsen, azt csak a másik fél tudja módosítani. Sem az 'endpoint' url-ek szintaktikáinak megváltoztatásához, sem pedig az adatbázisokhoz nincs hozzáférésem.
    Mutasd a teljes hozzászólást!
  • Eszembe jutott egy alternatív ötlet, ami bár technikailag kivitelezhető, de gányolás is szerintem, mert szennyezi a prod környezetet.

    Ha az alkalmazásod kezeli, megteheted azt is akár, hogy a prodon és a teszt környezeten egyaránt létrehozod a usert, de prodon AppStoreReview role-t rendelsz hozzá. AppStoreReview role esetében pedig a prodos szoftver login után ad egy HTTP 301 Moved Permanently üzenetet, redirect-elve a mobilapp-ot a tesztkörnyezetre. Ott megismétli a logint automatikusan és nyomkodhatják a szoftveredet.
    Mutasd a teljes hozzászólást!
  • Ez nagyon érdekes téma. Alig várom a hozzáértők véleményét, de addig is itt a sajátom.

    Ennek a review-nak elvileg az lenne a lényege, hogy a reviewer-ök ugyanazt a környezetet teszteljék, amit a felhasználók használni fognak (környezet == frontend + backend). Ebből a szempontból nézve rögtön eltört mindkét módszer, melyek szerint vagy legyen test user hardcode-olva és vagy mock-okkal, vagy pedig teszt backenddel kommunikáljon a mobilapp.

    A test backenddel egyébként is van egy másik probléma is. Írtad, hogy az egy dev környezet, ami sokkal instabilabb, mint a prod, de a legnagyobb problémája az, hogy nem is ugyanaz a verziójú kód, ami a prod.

    Van még egy sarkallatos pontja az app review-nak. A Google és az Apple neked untrusted ügyfelek. Mivel a review-hoz teljes funkcionalitást követelnek, te hogyan biztosítod azt, hogy ne éljenek vissza az általad adott credential-ökkel? Prodos accountot én biztos, hogy nem kockáztatnék meg.

    A helyes irány itt szerintem az általad említett gateway lenne, de szükséged lesz egy proddal verzió tekintetében ekvivalens környezetre is (vagy legalábbis ami stabil és a jövőben proddá válik... nevezhetjük talán staging-nek?). Igaz, ez sem ingyen van, hiszen némi plusz latency-t bevisz az igazi felhasználóidnak is. Ugyanakkor azt gondolom, hogy egy ilyen gateway a jövőben más célokra is hasznos lehet.
    Mutasd a teljes hozzászólást!
  • Van egy applikáció, ami egy http REST api endpoint-ról adatokat kérdez le, aztán megjelenít mindenfélét. Ennek a programnak a kezdőképernyője egy bejelentkező oldal, amit szintén a rest api validál (utána onnan visszajön egy bearer token.. a szokásos). Amikor én ezt az appot feltöltöm az android vagy az apple alkalmazásboltba, akkor mindkét platformon szükséges megadni egy olyan felhasználónév/jelszó párost, amivel ők át tudnak jutni a login képernyőn (máskülönben reject-elik). Ezzel eddig semmi probléma.

    Na de, a rest api server fejlesztője egyik nap két részre bontotta szét a saját kódbázisát, aminek az lett a következménye, hogy lett egy (prod) "api.valami.com" és egy (dev) "test.api.valami.com" url. Utána fogta az apple és android store review-t végző embereknek készített "demo" felhasználókat és azokat a prod adatbázisból kitörölte. Ezért az ezt követő review eredménye mindkét store-ban reject lett, mert a login oldalon nem jutottak túl (az app a 'prod' url-re küldte a kéréseket).

    Azt a javaslatot tettem az 'api server' programozójának, hogy készítsen egy "gateway.api.valami.com" url-t, én arra elküldöm a request-eket, aztán az üzleti logikát oldja meg, ahogy neki tetszik. Erre az a válasz érkezett, hogy inkább legyen egy üzleti logika a mobil app kliensbe implementálva, ami a (login) bejelentkezési oldalon a felhasználónév alapján, ami egy email cím, döntse el, hogy éppen a (dev) "test.api.valami.com" vagy a (prod) "api.valami.com" url-ekre kell küldeni a request-eket.

    A kérdéseim:
    - Valid igény, hogy a mobil app kliensben legyenek 'speciális' felhasználónevek hardcode-olva, amik nem X hanem Y endpoint-ra requestelnek (mert azok "teszt" felhasználók)?
    - Helytálló az az érvelés, hogy mivel a 'rest api server' két url-en keresztül érhető el ("api.valami.com" és "test.api.valami.com"), ezért ezt nem server oldalon kell lekezelni?

    (sajnos az a helyzet állt elő, hogy én nem akarok "spéci" felhasználókat és "teszt módot" beleprogramozni az applikációba, hiszen fejlesztés közben szabadon konfigurálható minden, DE a 'rest api endpoint' feljesztője nem hajlandó egy url alól kiszolgálni a kéréseket.. ami miatt mindkét alkalmazásbolt visszadobja a programot)

    Minden észrevételt / iránymutatást előre is megköszönnék.
    Mutasd a teljes hozzászólást!
Címkék
abcd