Jeg har i dag valgt at lancere det nye design af styrdindiabetes.dk.  Tag godt i mod det.

Godt nytår til jer alle.

Det er lang tid siden forrige indlæg, men der har været travlt med mange andre ting på arbejde og i fritiden.  Det er på tide at komme tilbage “on-track” med styrdindiabetes.dk.

Da jeg fornylig efter lang tids pause genoptog udvikling af styrdindiabetes.dk, virkede login med Facebook/Google/Microsoft pludselig ikke længere i Internet Explorer.  Årsagen er, at jeg i mellemtiden har opgraderet til fra Windows 8 til 8.1 med det resultat, IE er blevet opgraderet til version 11.

En spørgsmål på Mobile Services fora gav et svar fra en hjælpsom MSFT medarbejder: Jeg skulle opgradere Mobile Services JavaScript client library til nyeste version.

Mit forrige indlæg handlede om authorization via Windows Azure Mobile Services.  Authorization består af to elementer:

  1. Kun brugere, der er logget på, må kunne tilgå data.
  2. En bruger må kun kunne tilgå sit eget data.

Sidste gang diskuterede vi punkt 1 – denne gang bliver det punkt 2.

Udfordringen består i at forhindre, at en bruger læser eller redigerer i andre brugeres blodsukkermålinger.  Der er et hav af eksempler på, hvordan man sikrer, at en bruger ikke kan læse andre end sine egne data.  Det kræver blot følgende “where” clause i server-side node.js script for “Read”:

function read(query, user, request) {
    query.where({ userId: user.userId });
    request.execute();
}

Det kniber lidt mere med gode eksempler på, hvordan man f.eks. implementerer “Update” eller “Delete”.  For “Update” valgte jeg at benytte mig af det indbyggede MSSQL objekt, der kan bruges til at eksekvere rå SQL.  Som vi har talt om før, er data backend på Mobile Services blot en SQL Server:

   1:  function update(item, user, request) {
   2:      mssql.query('SELECT TOP 1 Id FROM Entries WHERE Id = ? AND userId = ?', [item.id, user.userId], {
   3:          success: function (results) {
   4:              if (results.length > 0) {
   5:                  item.userId = user.userId;
   6:                  request.execute();
   7:              }
   8:          }});
   9:  }

Idéen er, at jeg først checker, om der findes en entry med det pågældende id for den pågældende bruger.  Er det tilfældet, eksekverer jeg request’en. 

Linje 5 skal sikre, at brugeren ikke forsøger at putte en anden brugers ID på en blodsukkerregistrering.

“Delete” funktionen implementeres tilsvarende.

Vi er dermed klar til at slippe brugerne løs.  De kan logge ind med Facebook, Google eller en Microsoft konto, og de kan oprette blodsukkermålinger på livet løs uden at genere andre.

Authorization er den proces, der foregår, når man styre brugernes adgang til data.  På styrdindiabetes.dk skal det foregå på to niveauer:

  1. Kun brugere, der er logget på, må kunne tilgå data.
  2. En bruger må kun kunne tilgå sit eget data.

Det er punkt 1, vi skal se på i dette indlæg.

Vi har tidligere set på, hvordan Azure Mobile Services har authentication med Facebook o.a. indbygget.  Azure Mobile Services har også indbygget funktionalitet til at styre, hvem der må tilgå de databasetabeller, man opretter i backenden.  Det hele foregår i Azure Management portalen.

For hver tabel oprettet i Mobile Services, findes en Permissions side, hvor man kan angive, hvem der må udføre hver af de 4 CRUD operationer.  Man har følgende fire muligheder:

  • Everyone
  • Anybody with the Application Key
  • Only Authenticated Users
  • Only Scripts and Admins

image

Bemærk at for et website er der i praksis ingen forskel på “Everyone” og “Anybody with the Application Key”, da vores application key står frit tilgængelig i JavaScript’en, så enhver, der kender til højreklik og “Vis kilde” i browseren, kan få fat i nøglen.

Når en bruger via sitet forsøger at tilgå denne tabel vha. client.getTable("Entries"), vil Azure forhindre al tilgang for brugere, der ikke er logget på vha. Facebook eller andet.

I næste indlæg skal vi se på, hvordan vi sikrer, at brugerne kun kan tilgå deres eget data.

Som nævnt bruger Azure Mobile Services en SQL Server som backend database.  Det er ikke en normal SQL Server.  F.eks. findes begrebet foreign keys ikke, og Azure management konsollen giver ikke mulighed for at tilføje kolonner til tabeller som sådan.  I stedet bliver kolonner oprettet dynamisk ud fra det data, man sender til servicen.  Dette er en setting under “Configure” fanen for ens Mobile Service.

image

Husk at slå dynamic schema fra i produktion!

I første omgang har styrdindiabetes.dk behov for en enkelt tabel til at holde de indtastede blodsukkermåling.  En måling består bl.a. af en dato, typen (morgenmad, frokost, aftensmad eller sengetid) og blodsukker før og efter måltidet, hvor det giver mening.  Som JavaScript objekt kunne det se således ud i styrdindiabetes.dk (med lidt knockout.js blandet ind i det):

    var entry =
        {
            type: self.type(),
            beskrivelse: self.beskrivelse(),
            blodsukkerfoer: self.blodsukkerfoer(),
            blodsukkerefter: self.blodsukkerefter(),
            dato: dato,
            antalInsulinEnheder: self.antalInsulinEnheder(),
        };

CRUD operationer foregår vha. en REST API med POST, GET, PUT og DELETE.  Microsoft har heldigvis pakket REST API’en ind i en dejlig JavaScript API.  En CREATE/INSERT/POST operation kan f.eks. se således ud:

    client.getTable("Entries")
        .insert(entry)
        .done(function (result) {
            self.id(result.id);
            // ...
            }
        }, function (err) {
            self.root.errorMessage(err);
        });

JavaScript API’en opbygger HTTP kaldet for os.

Første gang vi laver ovenstående kald til “insert”, vil Mobile Service benytte dynamic schema og tilføje kolonner i Entries tabellen svarende til de properties, jeg definerede på entry objektet ovenfor.

Om  man kan lide dynamic schema er en smagssag.  Man kan godt frygte for integriteten i ens SQL Server database, og at der bliver givet køb på normalisering.  På den anden side øges produktiviteten betragteligt, fordi man kan koncentrere sig om at lave sin applikation og ikke om at designe database og lave datalag etc.  Jeg forestiller mig ikke, at Azure Mobile Services er beregnet til store datatunge projekter.

I næste indlæg skal vi se på, hvordan vi kan bruge login information til at styre adgang til data.

Som nævnt i forrige indlæg, får man authentication med Facebook, Twitter, Google og Microsoft med i Azure Mobile Services client API’en.  Det hele foregår i gennem det client objekt, vi fik fat i ved at inkludere Azure client JavaScript API’en. 

På min knockout.js viewmodel har jeg kode, der meget ligner følgende:

    self.login = function (providerName) {
        self.errorMessage('');
        client.login(providerName).then(self.afterLogin, function (error) {
            self.errorMessage(error);
        });
    } 

I HTML’en kalder jeg login funktion (gennem knockout.js bindings), hvor jeg angiver providernavnet (fremhævet):

    <ul class="dropdown-menu">
        <li><a data-bind="click: login.bind($data, 'facebook')" href="#">Facebook</a></li>
        <li><a data-bind="click: login.bind($data, 'microsoftaccount')" href="#">Microsoft</a></li>
        <li><a data-bind="click: login.bind($data, 'google')" href="#">Google</a></li>
    </ul>

Det vigtige her er kaldet til client.login(providerName). Det geniale er, at samme kode bruges til alle fire authentication providers: Facebook, Twitter, Google og Microsoft.  Jeg skal bare angive providername, som kan være “facebook”, “google”, “twitter” eller “microsoftaccount”. 

Bemærk at authentication kræver, at man først reigstrerer sig hos de fire udbydere, men det er ret nemt, og Microsoft har lavet en beskrivelse af processen.

Desværre virker ovenstående login metode ikke på Windows Phone.  Det er uheldigt, da et af målene netop var at gøre styrdindiabetes.dk tilgængeligt på mobile platforme.  Problemet er, at IE på Windows Phone ikke understøtter popups, hvilket bruges i login processen.  Jeg har indtil videre valgt at Windows Phone må sejle sin egen sø.  Hvis tiden tillader det, kan der eventuelt komme en Windows Phone app til styrdindiabetes.dk.  Der er muligvis også et workaround på StackOverflow, men jeg har ikke prøvet det, og det løser kun problemet for Facebook.  I så fald skulle jeg lave tilsvarende workarounds for de andre udbydere.  Det er jeg ikke interesseret i at bruge tid på, og hele øvelsen med at bruge Azure Mobile Services skulle netop være at give høj produktivitet uden alt for meget fnidder.

Eftersom jeg har bestemt, at styrdindiabetes.dk skal være en Single Page Application, har jeg brug for en backend, hvor det er nemt at implementere en API, der er nemt at kalde fra JavaScript.  Her er REST med JSON et naturligt valg.

I ASP.NET MVC 4 er det nemt at opbygge en HTTP REST-ish API.  Formålet med relanceringen af styrdindiabetes.dk er dog ikke at opbygge en backend med en relationel database og en API ovenpå.  Det har jeg gjort før, og jeg keder mig allerede bare ved at skrive om det. 

Nej, formålet er at lære noget nyt, og det gjorde jeg heldigvis, da jeg i juni var til TechEd i Madrid.  Her så jeg en (ret poppet) session, hvor Steven Sanderson på 75 minutter bankede en SPA sammen med online booking af taxaer med kort og live pushbacks.  Det gjorde han vha. Windows Azure Mobile Services.

Azure Mobile Services har nogle interessante features.  Server-delen er baseret på node.js.  Databasen er SQL Server, men det er ikke muligt at lave relationer imellem tabeller.  Det kan føles som lidt en skuffelse, men på den anden side er Azure Mobile Services ikke bygget til store databasetunge projekter.  Tabellerne i databasen er dynamiske.  Det betyder, at kolonner dannes automatisk ud fra properties på de objekter, man sender fra klienten (det skal slås fra i produktion!).

Azure Mobile Servies har client API’er til Windows Phone, Android, iOS og ikke mindst til JavaScript.  API’en inkluderer authentication via FaceBook, Twitter, Google og Microsoft, hvilket skal bruges til styrdindiabetes.dk.

Platformen indeholder også andre ting som udsending af mails, push notifications og scheduled tasks.  Det er ikke noget, jeg regner med at få brug for, men man skal aldrig sige aldrig.

Priserne findes på Azure.  Som det fremgår får man 10 tjenester gratis med 20 MB SQL Server.  Det er nok til at lige at komme i gang.

Kode

Efter man har lavet sig en Azure Mobile Service, får man et client application id, som man skal bruge i sin JavaScript:

    <script src="https://styrdindiabetes.azure-mobile.net/client/MobileServices.Web-1.0.0.min.js"></script>

    <script>
        var client = new WindowsAzure.MobileServiceClient(
            "https://styrdindiabetes.azure-mobile.net/",
            "<Indsæt application id her"
        );
    </script>

Igennem client objektet har man nu adgang til hele API’en fra sin Azure Mobile Service, og så er det bare at gå i gang.

For at markere at vi nærmer os 4-årsdagen for diagnosticeringen af min type 1 diabetes, har jeg tænkt mig at relancere www.styrdindiabetes.dk.  Jeg startede det for 3½ år siden, men jeg blev aldrig rigtig selv tilfreds med hverken design eller funktionalitet, og et make-over er hårdt tiltrængt.

Baggrund

En type 1 diabetiker producerer ikke selv insulin.  Mange tror fejlagtigt, at insulin neutraliserer sukker, men insulin hjælper kulhydrater med at blive optaget i kroppens celler.  Når der ikke er noget insulin, kan en diabetiker ikke optage sukkerstoffer fra blodet, og blodsukkeret stiger.  Derfor skal diabetikere indsprøjte insulin i huden, for at hjælpe kroppen til at optage kulhydraterne. 

Indtager man for meget insulin ift., hvad man spiser af kulhydrater, får man for lavt blodsukker (hypoglykæmi), hvilket i løbet af få minutter kan forårsage ildebefindende (insulinchok), og - hvis det ikke behandles hurtigt - bevidstløshed og død.

På den anden side kan for lidt insulin give for højt blodsukker (hyperglykæmi).  Har man for højt blodsukker over en længere periode, kan det give blindhed, fodsår som ikke kan hele (hvilket ofte ender i amputation), manglende følsomhed i fødderne, lever- og nyreskader, hjertekarsygdomme osv.  Listen er lang.  På kort sigt kan hyperglykæmi resultere i ketoacidose, som er en akut livstruende situation, hvor kroppens celler begynder at danne syre pga. manglende sukker.

Dagbog

Som det fremgår, er det yderst vigtigt for en diabetiker at have fuldstændig kontrol over blodsukkeret.  Det gør man ved flere gange dagligt at måle sit blodsukker.  Det gøres med specielle (og pænt dyre) apparater, som kan måle på blod presset ud gennem et hul, man prikker i sin finger eller i sit øre.  Personligt er jeg meget perfektionistisk mht. blodsukkermålinger, og jeg måler gerne op til 10 gange dagligt (det går naturligvis hårdt ud over mine fingre).

Behovet for insulin er indiviuelt og veksler meget fra person til person.  Desuden er der mange faktorer, der spiller ind: Kost, motion, stress, betændelsestilstand i kroppen, smerter (som f.eks. hovedpine), feber, søvn osv.  For at få en forståelse af ens eget insulinbehov, anbefales alle diabetiker i perioder af f.eks. en måneds længde at føre dagbog over blodsukkermålingerne.

Styrdindiabetes.dk

Det er her styrdindiabetes.dk kommer ind.  Styrdindiabetes.dk er en online dagbog for blodsukkermålinger.  Normalt fører man dagbog i en bog, men jeg synes, det er for besværligt, og der er sjældent plads til at gøre notater om motion og andre påvirkninger.  Derfor skal styrdindiabetes.dk være let at bruge og være tilgængeligt på alle platforme (mobil, tablet og desktop).

Min drøm er, at blodsukkerapparaterne bliver udstyret med et SIM-kort, så data automatisk overføres til en web service.  Men producenterne befinder sig stadig i forrige århundrede hvad angår design på apparaterne, så indtil da skal den manuelle registrering være så nem som muligt.

Mål

Jeg har følgende mål med relaceringen af styrdindiabetes.dk:

  1. Nyt og forbedret website hvad angår design og funktionalitet.
  2. Tilegnelse af kompetencer indenfor det nye “hotte” som Single Page Applications (SPAs) vha. Windows Azure Mobile Service, knockout.js, jQuery og Twitter Bootstrap.

Jeg betegner mig selv som nybegynder ud i kunsten af lave SPAs, så det bliver en spændende proces.  Jeg vil forsøge at beskrive, hvad jeg måtte møde af udfordringer her på dotninjas.dk.

Diabetikere bør (i hvert fald i perioder) føre dagbog over blodsukkermålinger som minimum foretaget før og efter hvert hovedmåltid og umiddelbart før sengetid.  Samtidig skal man tælle kulhydrater og løbende holde styr på sammenhængen mellem kulhydratindtaget og antallet af insulinenheder, man injicerer.

I anledning af halvårsdagen for konstateringen af min type 1 diabetes, har jeg arbejdet på et website til online registrering af blodsukkermålinger samt af indtag af insulin og kulhydrater.  Udover at give mig selv og andre diabetikere et centralt sted at føre dagbog, er det også mit første rigtige “live” ASP.NET MVC 2 og .NET 4.0 projekt.

Bayer Diabetes lever bl.a. af at lave blodsukkerapparater.  Hvert år udbyder de en sum penge til projekter, som på en eller anden måde gør livet nemmere for diabetikere, og mit website er blevet valgt som en af tre finalister til at modtage hjælp fra deres fond.  Den endelige vinder findes ved afstemning, hvor alle interesserede kan stemme.

Derfor beder jeg dig, kære læser, om at gå ind på og stemmemit bidrag.

Plz, plz, plz

P.S. Mit website er endnu ikke online, men du kan se et par skærmbilleder herunder.

simplewins1 simplewins2 simplewins3