Uwaga, aby artykuł nie miał setek stron, pominąłem dogłębne tłumaczenie kodu Javy/PHP/SQL. Co nie znaczy, że jeśli jesteś zaciekawionym tematem to nic nie zrozumiesz. Postarał się w miarę możliwości dobrze okomentować kod. W każdym razie czujcie się ostrzeżeni!
Z nielegalnym oprogramowaniem spotykamy się na co dzień – w Polsce jest ono dosyć popularne . Tworząc aplikację, którą chcemy sprzedać komuś, chcielibyśmy zadbać o to, żeby inni nie mieli do niej dostępu. Dlatego programiści starają się wymyślać coraz to nowsze zabezpieczenia przeciw piratom. Chciałbym pokazać jedną z prostych metod zabezpieczenia aplikacji.
Typowe zabezpieczenia:
Do każdego z tych punktów można dopisać jeszcze jedną wadę:
Żadne zabezpieczenie nie jest całkiem bezpieczne
Żadne z tych zabezpieczeń nie odeprze jednego: zmiany kodu programu. Dlatego warto jest korzystać z różnych zabezpieczeń, które modyfikują nam nazwy zmiennych/funkcji w kodzie, aby potem kod był trudny do rozczytania po dekompilacji.
Przed zastosowaniem zabezpieczenia warto przemyśleć, które warto wybrać. Jak każdy wie, stały wymóg połączenia internetowego może być denerwujący dla użytkownika. Jeżeli nie robicie aplikacji, która operuje na połączeniu internetowym, to nie zawsze warto wybierać to zabezpieczenie. Na dzień dzisiejszy najlepszym sposobem wydawać się może jednorazowa aktywacja – ma ją np. Windows, Steam. W tym artykule chciałbym zaprezentować mój sposób na system aktywacji, który przedstawiłem jako nr. 3 w liście wyżej; czyli – aktywacja urządzenia online.
Dlaczego akurat to wybrałem? Gdy myślałem o zastosowaniu mojej aplikacji, stwierdziłem, że zależy mi, aby nie była ona wykorzystywana przez jedną osobę na kilku urządzeniach. Dlatego aktywacja urządzenia wydaje się być rozsądnym wyborem.
Jak to wygląda?
Przy aktywacji urządzenia pierwszą rzeczą, jaka jest nam potrzebna, to pobranie jakiegoś identyfikatora urządzenia. I to jest drobny problem – co można wziąć? W większości przypadków znajdziecie na internecie wykorzystanie adresu MAC karty sieciowej, ale to rozwiązanie jest dosyć słabe – ponieważ w przypadku laptopów jest możliwość, iż aplikacja była instalowana gdy interfejs sieciowy WLAN był włączony, a potem wyłączony. Adres MAC w aplikacji zostanie zwrócony inny i aplikacja
przestanie
działać
. Dlatego polecam np. wykorzystać identyfikator BIOS’u. W Windowsie pobiera się go wpisując komendę w konsoli:
wmic bios get serialnumber
, w przypadku Linuxa sprawa jest nieco trudniejsza, ale i tak są pewne rozwiązania.
Okej – mamy już identyfikator sprzętowy – teraz przydałoby się go jakoś wysłać do serwera i odebrać plik weryfikacyjny. Tak to będzie wyglądać:
Ogólny schemat pierwszej aktywacji prezentuje się tak:
Schemat będzie się nieco
różnić
w przypadku, gdy klient aktywuje drugi raz aplikację na tym samym urządzeniu. Wtedy gdy serwer wykryje że klucz jest już użyty (czyli
used_num>=1
) to będzie sprawdzać tabelę
activations
i będzie próbował znaleźć
hardware_id
taki, jaki wysłał klient. Jeśli znajdzie takowy w tabeli, to oznacza, że klucz jest poprawny i odsyła klientowi klucz weryfikacyjny z kolumny
response_key
.
Przejdźmy do implementacji. Potrzebny nam serwer + baza danych na tym serwerze. Ja wybrałem bazę danych MySQL. Stworzyłem bazę danych o nazwie
Activation
, a w środku dwie tabele:
activation_keys
– w tej tabeli zawarte są wszystkie zaszyfrowane klucze programu i ich liczba użyć
CREATE TABLE activation_keys (id int PRIMARY KEY NOT NULL AUTO_INCREMENT, activation_key varchar(72) NOT NULL, used_num int);
activations
– w tej tabeli zwarte są wszystkie aktywacje, identyfikator sprzętowy i identyfikator klucza z tabeli activation_keys
CREATE TABLE activations (id int PRIMARY KEY NOT NULL AUTO_INCREMENT, id_key int NOT NULL, hardware_id varchar(64), response_key TEXT);
Identyfikator urządzenia będziemy pobierać, korzystając z wyżej wymienionego kodu + hashowania SHA-256.
Klucze będziemy szyfrować algorytmem BCrypt , który generuje maksymalnie 72-znakowy kod. Na obrazku obok jest pokazany schemat BCrypt. Jest to bardzo zalecane , gdyż mając atak hakerów na bazę danych, będą oni w stanie sprawdzić wszystkie dostępne klucze . Ogólnie, BCrypt zamienia klucz do formy zhashowanej. Ten proces trudno odwrócić, tzn.posiadając hash, trudno odnaleźć taki klucz, który po zhashowaniu będzie mieć taką samą formę jak zhashowany. BCrypt często wykorzystuje się do zapisywania haseł użytkowników na wielu stronach internetowych. Klient wysyła do serwera hasło w formie zahashowanej , a następnie jest sprawdzana jego poprawność. W przypadku ataku na bazę danych z hasłami, haker będzie mieć tylko tabelę z hasłami zahashowanymi oraz będzie mieć problem z odwróceniem procesu hashowania. Biblioteki BCrypt znajdziecie w Google.
Uwaga! Np. SHA-1, SHA-256 przestał być bezpiecznym algorytmem i dziś z dobrym komputerem nie ma większych problemów z inwersją. Jeżeli zależy wam na zabezpieczeniu przeciw dobrym hakerom, to polecam poszukać w Google nowych, skuteczniejszych zabezpieczeń. Jednak jeśli chcecie się obronić przed „Script kiddie”, to wystarczy nawet MD5. (nie warto też wrzucać tysięcy kluczy do tabeli, lecz dodawać nowe przy zakupie przez daną osobę)
Do tworzenia kluczy polecam stworzyć program. Ja uznałem że moje klucze będą 16 znakowe. Tak prezentuje się kod w Javie do wygenerowania losowego klucza i zhashowania go. Potrzebna jest też biblioteka BCrypt dla Javy: link .
BCrypt.gensalt(10)
– decyduje o złożoności hasła. Czym większa liczba w argumencie, tym trudniej będzie odszyfrować. Ale też sprawdzanie za pomocą serwera będzie dłuższe.
BCrypt.gensalt()
generuje optymalną wartość, wybraną przez twórcę biblioteki. Warto zauważyć, że duża wartość może być też problemem dla serwera przy sprawdzaniu poprawności klucza.
String AB
– w tym łańcuchu znaków znajdują się wszystkie znaki, które będą mogły znaleźć się w kluczu niezaszyfrowanym.
funkcja
randomString
– zwraca losowy łańcuch znaków o długości
len
, z wykorzystaniem znaków z łańcucha znaków
String AB
.
Dodajmy od razu testowy klucz
1234567890123456.
Aby taki zrobić wystarczy w kodzie zamiast
String key = randomString(16);
dać
String key = "1234567890123456";
Klucze w takiej formie będą przechowywane w tabeli do której nikt nie ma prawa mieć dostępu. Możecie zrobić bazę danych albo po prostu wklejać je do arkusza kalkulacyjnego. Otrzymujemy zaszyfrowany klucz –
$2a$10$SjT/4zh1LwNrsiKCvhUlzec4bAilAsvhw3xb2vpJkRK6eTacCTJFy.
Teraz wpisujemy go do tabeli na serwerze korzystając z komendy SQL
INSERT INTO
.
INSERT INTO `activation_keys`(`activation_key`,`used_num`) VALUES ("
$2a$10$SjT/4zh1LwNrsiKCvhUlzec4bAilAsvhw3xb2vpJkRK6eTacCTJFy
",0);
Czyli zhashowane klucze dodajemy do tabeli SQL, a klucz niezhashowany wysyłamy klientowi. Aplikacja będzie hashować klucz wpisany przez klienta, następnie wysyła go do serwera, który będzie porównywać wszystkie zhashowane klucze.
Okej, więc mamy bazę danych z kluczami gotową. Przejdźmy teraz do pliku weryfikującego licencję. Aby program zadziałał, w swojej lokalizacji musi mieć plik
activation.key
, który po odszyfrowaniu kluczem publicznym RSA wskaże
SHA-256 identyfikatora sprzętowego
urządzenia, na którym jest odpalany właśnie ten program. Ten plik
activation.key
będzie tworzony podczas pierwszej aktywacji (serwer wyśle odpowiedni kod dla klienta, który następnie zostanie zapisany w owym pliku). Trudno stworzyć taki klucz, żeby po odszyfrowaniu kluczem publicznych, dał SHA-256 identyfikatora, dlatego to zabezpieczenie jest w miarę bezpieczne. Serwer, posiadając klucz prywatny RSA może z łatwością stworzyć klucz weryfikacyjny. Rysunek pomoże dobrze zinterpretować to co napisałem:
Dla przypomnienia – schemat szyfrowania RSA . Wszystko pokazane na obrazku wyżej: kluczem publicznym szyfrujemy wiadomość; zaszyfrowanej wiadomości nie można rozszyfrować kluczem publicznym , potrzebny jest do tego klucz prywatny . Szyfrowanie to może też działać w drugą stronę – można szyfrować kluczem prywatnym, a odszyfrowywać publicznym, co dziś wykorzystamy. W naszym przypadku klucz weryfikacyjny będzie szyfrowany kluczem prywatnym na serwerze , a potem klucz będzie odszyfrowywany w aplikacji kluczem publicznym.
Jak stworzyć klucz
RSA
? Do jego stworzenia wykorzystam narzędzie
OpenSSL
, które można pobrać tu dla Windowsa:
http://gnuwins32.sourceforge.net/packages/openssl.htm
Program ten odpala się w trybie konsolowym. Potrzebne nam będzie parę komend:
openssl genrsa -out private_key.pem 2048
– tworzy 2048-bitowy klucz prywatny, o rozszerzeniu *.pem, które dobrze odczyta PHP. Jeśli chcecie lepszy poziom zabezpieczeń, to możecie użyć 3072 bitów.
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
– tworzy plik private_key.der w formacie PKCS#8, który lepiej jest odczytywany w Javie (bez kombinowania)
openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
– tworzy plik public_key.der, który łatwiej odczytać w Javie (bez tworzenia przeróżnych funkcji które zmieniają format klucza)
Są klucze, więc przyszła część na PHP, do którego będzie się zwracał klient. PHP będzie wypisywać proste komunikaty typu „ERROR”, „OK”, „WRONGKEY”, które następnie program wczyta i wskaże odpowiedni komunikat.
Klucz i identyfikator urządzenia będą wysyłane metodą POST. Wynik będzie wypisany funkcją echo, a oto lista możliwych wyników:
Po co te średniki w odpowiedziach? Są one po to aby wydzielić granice klucza weryfikacyjnego. Głębsze wyjaśnienie tego znajdziecie w dalszej części artykułu.
Program desktopowy będzie sprawdzać, jaki kod został otrzymany i wyświetli odpowiedni komunikat.
Na początku stworzyłem sobie dwie funkcje, które kończą wykonywanie pliku PHP i zwracają błąd:
Jeśli jakimś cudem nie ma parametrów HTTP POST lub identyfikator sprzętowy jest pusty to należy zakończyć działanie programu:
Klucz prywatny (private_key.pem) wrzucamy do poprzedniego katalogu niż jest plik PHP. Upewnijmy się, że prawa do pliku są tylko dla serwera i że nie można tego pliku otworzyć bezpośrednio z innego urządzenia.
Teraz należy pobrać klucz prywatny RSA z poprzedniego katalogu, który nie jest dostępny dla nikogo:
Połączenie się z bazą danych i ewentualne zwrócenie błędu:
Pobieramy rekordy z tabeli activation_keys i sprawdzamy, czy klucz jest dobry.
password_verify()
– sprawdza czy klucz w formie niezaszyfrowanej, jest odpowiednikiem zaszyfrowanego podanego w drugim argumencie (BCrypt)
trim()
– usuwa spacje na początku i końcu klucza. (zabezpieczenie, jeśli do bazy danych daliśmy zaszyfrowany klucz z niepotrzebną spacją – mi się to zdarzyło)
Jeżeli klucz nie został jeszcze użyty – czyli
$used
jest równe 0, to przygotujemy klucz weryfikacyjny dla klienta metodą
openssl_private_encrypt($informacja_do_zaszyfrowania, $zmienna_gdzie_zapisze_sie_zaszyfrowany_tekst, $klucz_prywatny_RSA);
Następnie należy powiększyć licznik użycia klucza i dodać identyfikator sprzętowy do tabeli
activations
. Na sam koniec wystarczy zwrócić klientowi klucz weryfikacyjny funkcją
echo
, który następnie klient zapisze do pliku.
Użyte jest to proste zabezpieczenie przed SQL Injection, więcej o tym możecie poczytać w innym artykule na tej stronie: Zabezpieczenia baz danych
Jeżeli klucz jest użyty to należy sprawdzić, czy urządzenie o identyfikatorze wysłanym w HTTP POST występuje w tabeli
activations
. Jeśli występuje to należy klucz weryfikujący wysłać klientowi.
Jeśli po zakończeniu pętli nie odnaleziono klucza, to należy zwrócić błąd – zły klucz.
Cały plik prezentuje się tak:
Możecie stworzyć też prosty plik HTML i porobić parę testów:
W tym fragmencie artykułu będę opisywał stworzenie aplikacji desktopowej Javie, co nie zmienia faktu, że tak samo da się zrobić w innych językach programowania.
Zacznijmy od stworzenia projektu i dodania biblioteki BCrypt. Link do biblioteki: http://www.mindrot.org/projects/jBCrypt/
Stwórzmy najpierw klasę pomocniczą
Activation.java
. Będzie ona pomagać w tworzeniu klucza identyfikatora urządzenia i do odszyfrowania klucza weryfikacyjnego:
Jak pewnie zauważyliście, do pobrania identyfikatora sprzętowego potrzebna jest magiczna klasa WindowsID. Wyżej napisałem, jak w przypadku systemu Windows pobierać identyfikator. Oto ta klasa:
W przypadku innych systemów też znajdziecie różne rozwiązania na pobranie identyfikatora sprzętowego.
Przejdźmy teraz do GUI aplikacji. Na początku można zrobić prosty layout w JavaFX (Java Scene Builder):
A tutaj przegląd obiektów, dla których przypisałem jakieś id. Jest to potrzebne po to, aby już w kodzie Javy móc pobrać te obiekty:
Do katalogu
resources
(jeśli nie wiecie jak dodawać to zapraszam tutaj:
link
) wrzucamy plik
public_key.der
. Startowy plik Javy wygląda tak:
OnActivationListener
zawiera funkcję, która zostanie aktywowana, jeśli aktywacja się powiedzie oraz funkcję pobrania klucza publicznego.
Teraz część kontrolera Aktywacji. W JavaFX, korzystając z kontrolera scen, można łatwo pobierać obiekty GUI dla których przypisaliśmy jakiś identyfikator. Wystarczy podać adnotację
@FXML
a następnie klasę obiektu i jego identyfikator. Bardzo ułatwia to pracę.
Po kliknięciu przycisku submitButton jest on wyłączany (na czas próby połączenia z serwerem) i są wykonywane czynności łączenia. Do funkcji
connectToServer
dodałem 3 argumenty:
keyInput.getText()
– klucz produktu
id
– identyfikator urządzenia
ActivationListener
– informuje o rezultacie połączenia / zwraca wynik wykonania PHP
Interfejs
ActivationListener
wygląda tak:
W odpowiedzi serwera musimy sprawdzić wszystkie przypadki, które wymieniłem wcześniej, czyli:
OK
,
OK_USED
,
WRONGKEY
,
WRONGHARDWARE
,
USED
,
ERROR
i jeszcze przypadek, jak coś innego zostało zwrócone (nieznany błąd). Gdy wystąpi błąd połączenia z serwerm (brak internetu lub serwer jest wyłączony) to zostanie wywołana funkcja z interfejsu
ActivationListener void error();
Błąd połączania wyskoczy jako wyjątek
IOException
, który łatwo wyłapać.
A tak wygląda sama funkcja łączenia z serwerem:
Warto zaznaczyć, że koniecznie trzeba tu użyć wątków. Bez nich aplikacja zacięłaby się na czas łączenia z serwerem.
Tak nie może być!
Dlatego też skorzystałem z prostego wątku
Thread.
Wracamy do interfejsu
ActivationListener
. Co jeśli jest błąd połączenia? Należy wyświetlić odpowiedni komunikat i ponownie włączyć przycisk
submitButton
(bo użytkownik ma prawo ponowić próbę).
Warto zauważyć, iż aktualizując elementy interfejsu z innego wątku, należy skorzystać z funkcji
Platform.runLater
, która aktualizuje GUI z wątku interfejsu graficznego. Bez tego nie da się aktualizować interfejsu.
Przejdźmy teraz do drugiej funkcji interfejsu
ActivationListener.
Serwer zwraca pewien ciąg bajtów, które można zamienić na łańcuch znaków:
String
responseString
=
new
String
(response);
Problem polega na tym, że PHP zwraca niepotrzebne spacje i nowe linie na końcu pliku, dlatego też użyłem średników do wyznaczania początku i końca klucza weryfikacyjnego. Do tego klucz weryfikacyjny jest zapisany w
formie bitów
i zawiera różne
znaki, które po przekształceniu do String’a,
zmienią
swój format. Dlatego, w przypadku zwróconego klucza weryfikacyjnego przez serwer, trzeba na nim operować jako na
tablicy bajtów
. Funkcja
trimKey
obcina tablicę bajtów do pierwszej znalezionej liczby podanej w argumencie 2 oraz obcina tablicę od końca to ostatniej znalezionej liczby podanej w argumencie 2. Średnik to w kodzie ASCII numer 59, dlatego też taki wpisałem do funkcji
trimKey
. Dobry klucz jest pobierany do zmiennej
goodKey
, a do zmiennej
keyFromServerDecrypted
przypisywany jest odszyfrowany klucz weryfikacyjny. Jeśli oba te zmienne mają takie same wartości (
contentEquals
), to należy zapisać klucz zaszyfrowany w pliku
activation.key
. Starałem się okomentować kod, aby był w miarę możliwości zrozumiały:
A funkcja
trimKey
prezentuje się tak:
Na sam koniec wystarczy jeszcze dopieszczyć plik startowy, aby program nie wyświetlał okna z aktywacją przy każdym uruchomieniu. Klucz będzie sprawdzany tak samo jak w przypadku aktywacji, więc nie tłumaczę już kodu. Poniżej fragment kodu z funkcji startowej JavaFX:
Nareszcie koniec ! Cieszę się, jeśli dotrwaliście do tego momentu. Od teraz możecie powiedzieć, że algorytm RSA nie taki straszny, a nasza aplikacja stała się w miarę bezpieczna! Jakbyście czegoś nie rozumieli to zapraszam do komentowania !
Tworząc aplikacje, które dotrą do wielkiej liczby użytkowników, nie jesteśmy w stanie całkiem przeciwdziałać ich niecnym zamiarom okradania nas. Jednakże systemy antypirackie takie jak aktywacja online pozwalają pozbyć się tego problemu nawet w większości przypadków. Warto łączyć różne systemy aktywacji, tworzyć własne, aby były trudniejsze do ogarnięcia .
W tym artykule przekazałem także informacje na temat szyfrowania – jest ono używane wszędzie: na stronach banku , sklepach, mediach społecznościowych. Dlatego kryptografia (utajnianie wiadomości) jest taka ważna. Korzystamy z niej na co dzień! Tworząc stronę internetową warto zadbać o to, aby hasła użytkowników nie były narażone na proste ataki hakerów. Zabezpieczenie haseł nie jest trudnym zajęciem, jednakże nadal sporo osób omija to szerokim łukiem lub używa przestarzałych algorytmów.
]]>
Hack Heroes to hackathon z okazji Code Weeka, czyli długiego tygodnia od 15. do 23. października. Więcej możecie o nim poczytać tutaj: http://apki.org/news/hack-heroes-wez-udzial-w-codeweekowym-hackathonie .
23:53
Już od początku doby, tj. od północy do jakiejś czwartej zabrałem się za rozpoczynanie projektu. Odpalenie phpStorma, załadowanie wszystkich zależności na composerze i npm-ie. Rozrysowanie na kartce czegoś, na czym będę mógł się opierać podczas pisania i kodowania frontendu i backendu. Obmyślałem podstawowe funkcjonalności aplikacji i zabrałem się za pisanie najprostszego szkieletu backendu, żeby móc się skupić na frontendzie. Dlaczego tak? Lubię widzieć do czego piszę backend, a taki gotowy frontend motywowałby mnie do dalszego pisania. Z racji czasu na backend wybrałem Slim-a , a na frontend nic, prócz frameworka Materialize.css (który swoją drogą jest dużo słabszy niż wygląda, przez jedną dobę zdążył mi już sprawić nie jedną bolączkę).
Sama aplikacja nazywa się Wakadog . Inspirowane lekko Wakatime. Czytane łakadog , wymową podobnie do walk a dog . Do tego właśnie służyć będzie moja aplikacja, do wyprowadzania psów. Mamy na mapie obszar z markerami, które oznaczają psy, których właściciele nie mają czasu lub nie mogą z nimi wyjść i potrzebują z tym pomocy. Porównałbym to do bazy ogłoszeń, jak OLX, z ogłoszeniami psów do wzięcia na spacer. Odpłatnie czy nie, to już kwestia leżąca poza odpowiedzialnością aplikacji. Potencjalny wyprowadzacz dostaje całkiem kompletny zbiór informacji o psie oraz numer telefonu do kontaktu. Po spacerze wyprowadzacz może wystawić psu ocenę, do pięciu gwiazdek. Na dzień dzisiejszy wygląda to tak:
Mój cel na nadchodzącą noc to dokończyć podstawowe widoki we froncie, żeby móc się skupić na backendzie.
01:53
Formularz dodawania psiaka ukończony, jednak nie jestem specjalnie zadowolony z jego aspektów wizualnych. Cóż, jak będzie czas to się coś wymyśli.
Naciśnięcie na mapę w dowolnym miejscu tworzy marker i wpisuje kordynaty do pola poniżej. UX tego rozwiązania jest zdecydowanie do poprawy. Nie podoba mi się rozkład poszczególnych pól. Te dwie sekcje można by jakoś sensownie pod względem wizualnym zgrupować.
Narazie zostawiam frontend i zaczynam klepać pehapa. Jakieś podstawowe encje i repozytoria, jednak najpierw, biorę kartkę i długopis i rozpiszę sobie bazę danych co by później nie mieć z zaprojektowaniem relacji problemów, w końcu jest coraz późniejsza godzina w nocy.
20:02
Oj ciężko w dni szkolne; zdecydowanie mniej czasu na to przeznaczam, co widać na WakaTime (screen obok).
Wczoraj siedziałem nad Wakadog tylko jakieś półtorej godziny. Trochę czasu zajęło mi za to przygotowywanie obrazu wirtualnej maszyny z linuksem skonfigurowanym do moich potrzeb, aby jutro móc w szkole kontynuować moją pracę. Nic prócz drobnej optymalizacji, dodaniu kontrolera od landing page oraz napisaniu dwóch widoków, formularza logowania i rejestracji nie zrobiłem. Obmyślałem za to sposób, w jaki będe w Wakadog uwierzytelniał i autoryzował użytkownika. Wszystko rozpisałem na kartce, trochę pogumkowałem, popoprawiałem i ostatecznie wyszło mi to, co widać na zdjęciu w tym issue na GitLabie .
Dzisiaj natomiast wcielam w kod (hmm, ciekawy zwrot) to, co rozpisałem na kartce. Planuję skontaktować się z jednym z mentorów w celu porozmawiania na temat bezpieczeństwa pewnego rozwiązania nad którym się zastanawiam. Tyle na teraz, lecę dalej pisać.
21:39
Minął dzień odkąd pisałem. Postaram się opisać co przez te dni robiłem.
Przedwczoraj udało mi się wcielić moje rozpiski w kod, z którego jestem na moment obecny zadowolony, a może i nawet dumny. Po hackathonie dopracuję go pod względem elastyczności, napiszę testy i opublikuję w oddzielnym repozytorium, żeby móc w przyszłości z niego korzystać.
Wczoraj z rana, w szkole, przez dwie lekcje implementowałem funkcjonalności formularza do logowania się. Swoją drogą pierwszy raz używałem linuksa jako systemu gościa do faktycznego developmentu i pracowało mi się całkiem przyjemnie. Postawiłem 64bitowego Debiana na Cinnamonie, jeżeli ktoś byłby ciekaw. Na iMacu 2015 27″ z przydzielonymi 4GB RAM działał bardzo dobrze.
Wieczorem zabrałem się za
obackendowywanie
formularza rejestracji, razem z tym doszedł też wybór walidatora. Wybór padł na
symfony/validator
jak niektórzy mogli się domyśleć. To, co popełniłem tamtego wieczoru było syfem i nie chcę o tym pamiętać. Cóż, teraz nie jest wspaniale, ale to za chwilę. Skończyłem wczoraj dosyć wcześnie, bo koło 22:00.
Przechodząc do dnia dzisiejszego, poprawiłem wczorajszy kod rejestracji na coś bardziej znośnego. Winę zwaliłem na
slim/flash
, który rozszerzyłem i zmodyfikowałem tak, aby akceptował coś innego niż tylko stringi. Możesz dowiedzieć się o co mi chodzi przeglądając commity z tego dnia. Dowiedziałem się telefonicznie, że termin oddawania prac został przesunięty o jedną dobę, a więc oddać projekt trzeba przed poniedziałkową północą.
Na ten moment udało mi się dodać dodawanie, usuwanie i moderację ocen. Lekko zmieniłem wygląd mapy, który będzie punktem wyjściowym nawigacji po stronie. Przede mną stoi obackendowanie dodawania psa. Gdy to zrobię, będę już na prostej do finiszu głównych funkcjonalności aplikacji i będę mógł się zabrać za drobne refaktoryzacje, optymalizacje czy poprawki wizualne.
12:17
Dzisiaj już nie wieczorem tylko z rana.
Wczoraj dodałem edycję oraz usuwanie psiaków. Walidacja tego wszystkiego to jest jeden wielki
syf
, na który nie mam pomysłu jak go ogarnąć. Jednak działa dobrze. Poprawiłem też pole
date
w psiakach, które nie ma teraz jakiejś dziwnej wartości, gdy wyborem jest
Kiedykolwiek
, a wynosi po prostu
null
. Dodałem ustawienia konta, w których można zmienić pola konta (aktualnie tylko widoczna nazwa), zmienić hasło lub bezpowrotnie usunąć konto.
Na mojej liście todo pozostał widok psów, których jesteśmy właścicielami oraz strona landing. Biorę się za pracę. A, i swoją drogą, podrzucam tydzień z WakaTime, ponieważ mam darmowe konto i statystyki mi zaczną już znikać.
01.11.2016 00:19
Projekt ukończyłem na przeddzień terminu, nie jestem specjalnie dumny z kodu w poszczególnych kontrolerach, mówiąc ściślej chodzi mi o ten, związany z walidacją. To jest porażka. Jednak cała aplikacja działa. Ma sporo dziur bardzo banalnych do odkrycia, o których pomyślałem już po terminie oddawania projektów. Na GitLabie pozostało parę issues otwartych i nieukończonych. Jednak jestem zadowolony z tego, że skończyłem ten projekt w terminie. Gdyby przysiąść do tego już na spokojnie, można by poprawić wszystkie niedociągnięcia i stworzyć całkiem udany produkt.
Na planowanie, programowanie oraz przeglądanie dokumentacji przeznaczyłem w 10 dni około 50 godzin, czyli średnio 5h dziennie, co jest przy takim okresie czasu moim osobistym rekordem. Na WakaTime załapałem się nawet do top100. Dzięki temu projektowi dowiedziałem się co to znaczy pracować z deadlinem .
Pojutrze (tj. 03.11.2016) rozpoczyna się głosowanie internetowe na najlepszy projekt. Na moment obecny pozostaje mi czekać na otwarcie głosowania oraz na oficjalne wyniki. Małe statystyki odnośnie hackathonu: udział wzięły 62 drużyny reprezentowane przez 193 zawodników, projekty końcowe złożyło finalnie 38 drużyn, czyli 61% drużyn złożyło ukończone projekty.
Na dole posta zdjęcie, które zrobiłem sobie podczas pisania. Bardzo mi się podoba.
Cały kod znajduje się na GitLabie pod tym linkiem . Wersja online będzie pod tym linkiem (jeżeli prowadzi do 404, już ją zdjąłem, jednak dodałem parę stron na https://archive.org/ ).
Cały hackathon został oficjalnie zakończony wręczeniem nagród w budynku Taurus w Warszawie na Mokotowie. Filmik (niestety ze słabym audio) możecie obejrzeć:
]]>