Miisiiks

From ICO wiki
Jump to navigationJump to search

Meeskond

  • Christo Aruste
  • Heleriin Malkov
  • Tõnis Prants

Analüüs

Idee

Juhutööde pakkumise ja otsimise veebiteenus ja veebikeskkond

Kirjeldus

Loome veebiteenuse ning veebikeskkonna, mille kaudu inimesed saavad vaadata ja lisada juhutöö otsimise ning pakkumise kuulutusi. Kuulutustel on võimalik ära märkida piirkond, kus otsitakse tööd/töötajat. Veebilehel on võimalik hinnata kasutajakontosid ja lisada kommentaare. Kuulutuse vastuvõtmisel saadetakse kuulutuse loojale teade kontaktandmetega. Kuulutuse lisamisel on võimalik märkida ära, kas antud töö eest pakutakse tasu või mitte.

Funktsionaalsus

Must have:

  • Kuulutuste vaatamine
  • Kuulutuste lisamine
  • Kuulutuste kustutamine
  • Kuulutuste otsimine
  • Kasutajate haldamine
  • Kasutajatele teadete saatmine
  • Teadete vaatamine

Nice to have:

  • Kasutajakontode hindamine
  • Kuulutuse aegumine
  • Kuulutuse sulgemine
  • Kasutajate kommenteerimine
  • Kuulutuse aadress
  • Kuulutuse asukoha kaugus sinu asukohast
  • Anonüümselt kuulutustele vastamine
  • Mitme kontaktandme valikuline sidumine kuulutusega

Veebiteenus

https://www.dropbox.com/s/e2vu3ukgckyc2x5/MiisiiksWS.zip?dl=0

Klientrakendus

https://www.dropbox.com/s/iwtheohp5mn0lek/MiisiiksC.zip?dl=0

XML

<?xml version="1.0" encoding="utf-8" ?>
<ApplicationUsers>
  <ApplicationUserDTO UserId="296a7683-be8d-45e1-9b9d-6b7e1aa4657d">
    <UserName><![CDATA[workers@hotmail.com]]></UserName>
    <Advertisements>
      <AdvertisementDTO AdId="1">
        <AdName><![CDATA[Looking for a truck driver]]></AdName>
        <AdDescription><![CDATA[I am looking for a truck driver to help me move to another town. For more information send a message.]]></AdDescription>
        <UserName><![CDATA[workers@hotmail.com]]></UserName>
        <Location><![CDATA[Tallinn, Mustamäe]]></Location>
        <JobCategory> Driving </JobCategory>
        <CreationDate> 01.06.2018 </CreationDate>
        <AdvertisementPictureDTO PictureId="1">
          <Location><![CDATA[https://i1.wp.com/movingtips.wpengine.com/wp-content/uploads/2017/10/large-moving-truck.jpg?fit=1024%2C683&ssl=1]]></Location>
          <AdvertisementId> 1 </AdvertisementId>
        </AdvertisementPictureDTO>

        <AdvertisementPictureDTO PictureId="2">
          <Location><![CDATA[https://www.southernoak.com/v2/wp-content/uploads/2016/05/Moving-Day.jpg]]></Location>
          <AdvertisementId> 1 </AdvertisementId>
        </AdvertisementPictureDTO>
      </AdvertisementDTO>
    </Advertisements>
    <Contacts>
      <ContactDTO Id="1">
        <ContactValue><![CDATA[Miisiks]]></ContactValue>
        <UserName><![CDATA[workers@hotmail.com]]></UserName>
        <ContactTypeName> Skype </ContactTypeName>
      </ContactDTO>
    </Contacts>
  </ApplicationUserDTO>

  <ApplicationUserDTO UserId="2460d33a-3505-4844-b8c8-2b7e0ece6a70">
    <UserName><![CDATA[homeforyou@gmail.com]]></UserName>
    <Advertisements>
      <AdvertisementDTO AdId="3">
        <AdName><![CDATA[Need a home assistant]]></AdName>
        <AdDescription><![CDATA[Need help with a big spring cleaning at countryside house. There’s a lot to clean from inside the house to the garden. Please message for more information]]></AdDescription>
        <UserName><![CDATA[homeforyou@gmail.com]]></UserName>
        <Location><![CDATA[Pärnumaa, Sauga]]></Location>
        <JobCategory> Cleaning</JobCategory>
        <CreationDate> 12.02.2018 </CreationDate>
        <AdvertisementPictureDTO PictureId="3">
          <Location><![CDATA[https://s3-media4.fl.yelpcdn.com/bphoto/fWxU8tYpD3ddC7UtSKXA7A/o.jpg]]></Location>
          <AdvertisementId> 3 </AdvertisementId>
        </AdvertisementPictureDTO>

        <AdvertisementPictureDTO PictureId="4">
          <Location><![CDATA[http://whatdoimakenow.com/wp-content/uploads/2017/05/Messy-House-Project-Kitchen-Before-Stove-e1495030958246.jpg]]></Location>
          <AdvertisementId> 3 </AdvertisementId>
        </AdvertisementPictureDTO>

        <AdvertisementPictureDTO PictureId="5">
          <Location><![CDATA[http://www.gardenplansireland.com/forum/files/garden_123.jpg]]></Location>
          <AdvertisementId> 3 </AdvertisementId>
        </AdvertisementPictureDTO>

        <AdvertisementPictureDTO PictureId="6">
          <Location><![CDATA[https://wshg.net/wp-content/uploads/2014/05/GardenDilemmas_B_WHG13A.jpg]]></Location>
          <AdvertisementId> 3 </AdvertisementId>
        </AdvertisementPictureDTO>
      </AdvertisementDTO>
      <AdvertisementDTO AdId="4">
        <AdName><![CDATA[Fixing a roof]]></AdName>
        <AdDescription><![CDATA[Need help with fixing a roof. Please message for more information]]></AdDescription>
        <UserName><![CDATA[homeforyou@gmail.com]]></UserName>
        <Location><![CDATA[Pärnumaa, Sauga]]></Location>
        <JobCategory>Construction</JobCategory>
        <CreationDate> 01.06.2018 </CreationDate>
      </AdvertisementDTO>

    </Advertisements>
    <Contacts>
      <ContactDTO Id="2">
        <ContactValue><![CDATA[homeforyou]]></ContactValue>
        <UserName><![CDATA[homeforyou@gmail.com]]></UserName>
        <ContactTypeName> Skype </ContactTypeName>
      </ContactDTO>
    </Contacts>
  </ApplicationUserDTO>
</ApplicationUsers>

XML skeem

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="ApplicationUsers">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="ApplicationUserDTO">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="UserName" type="xs:string" />
              <xs:element name="Advertisements">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="AdvertisementDTO">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="AdName" type="xs:string" />
                          <xs:element name="AdDescription" type="xs:string" />
                          <xs:element name="UserName" type="xs:string" />
                          <xs:element name="Location" type="xs:string" />
                          <xs:element name="JobCategory" type="xs:string" />
                          <xs:element name="CreationDate" type="xs:string" />
                          <xs:element maxOccurs="unbounded" minOccurs="0" name="AdvertisementPictureDTO">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="Location" type="xs:string" />
                                <xs:element name="AdvertisementId" type="xs:int" />
                              </xs:sequence>
                              <xs:attribute name="PictureId" type="xs:int" />
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                        <xs:attribute name="AdId" type="xs:int" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="Contacts">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="ContactDTO">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="ContactValue" type="xs:string" />
                          <xs:element name="UserName" type="xs:string" />
                          <xs:element name="ContactTypeName" type="xs:string" />
                        </xs:sequence>
                        <xs:attribute name="Id" type="xs:int" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="UserId" type="xs:string" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XLS to HTML

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="html" indent="yes"/>
  <xsl:template match="/ApplicationUsers">
    <html>
      <head>
        <title>Miisiiks</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous"/>
      </head>
      <body>
        <h1>Advertisements</h1>
        <table border="1">
          <tr>
            <th>User</th>
            <th>Title</th>
            <th>Description</th>
            <th>Location</th>
            <th>Job Category</th>
            <th>Date Created</th>            
            <th>Pictures</th>
          </tr>
          <xsl:for-each select="ApplicationUserDTO/Advertisements/AdvertisementDTO">
            <tr>
              <td>
                <xsl:value-of select="UserName"/>
              </td>
              <td>
                <xsl:value-of select="AdName"/>
              </td>
              <td>
                <xsl:value-of select="AdDescription"/>
              </td>
              <td>
                <xsl:value-of select="Location"/>
              </td>
              <td>
                <xsl:value-of select="JobCategory"/>
              </td>
              <td>
                <xsl:value-of select="CreationDate"/>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="0 = count(AdvertisementPictureDTO)">
                    No pictures
                  </xsl:when>
                  <xsl:otherwise>
                    <img alt="Advertisement picture" height="50" width="60">
                      <xsl:attribute name="src">
                        <xsl:value-of select="AdvertisementPictureDTO/Location"/>
                      </xsl:attribute>
                    </img>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

XLS to XML

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:element name="ApplicationUsers">
      <xsl:for-each select="/ApplicationUsers/ApplicationUserDTO">
        <xsl:variable name="ApplicationUser" select="."/>
        <xsl:element name="ApplicationUser">
          <xsl:attribute name="UserId">
            <xsl:value-of select="@UserId"/>
          </xsl:attribute>
          <xsl:element name="UserName">
            <xsl:value-of select="UserName" />
          </xsl:element>
          <xsl:element name="Advertisements">
            <xsl:for-each select="$ApplicationUser/Advertisements/AdvertisementDTO">
              <xsl:variable name="AdvertisementDTO" select="."/>
              <xsl:element name="Advertisement">
                <xsl:attribute name="AdId">
                  <xsl:value-of select="@AdId"/>
                </xsl:attribute>
                <xsl:element name="AdName">
                  <xsl:value-of select="AdName"/>
                </xsl:element>
                <xsl:element name="AdDescription">
                  <xsl:value-of select="AdDescription"/>
                </xsl:element>
                <xsl:element name="UserName">
                  <xsl:value-of select="UserName"/>
                </xsl:element>
                <xsl:element name="Location">
                  <xsl:value-of select="Location"/>
                </xsl:element>
                <xsl:element name="JobCategory">
                  <xsl:value-of select="JobCategory"/>
                </xsl:element>
                <xsl:element name="CreationDate">
                  <xsl:value-of select="CreationDate"/>
                </xsl:element>
                <xsl:for-each select="$ApplicationUser/Advertisements/AdvertisementDTO/AdvertisementPictureDTO">
                  <xsl:variable name="Advertisement" select="."/>
                  <xsl:element name="Picture">
                    <xsl:attribute name="PictureId">
                      <xsl:value-of select="@PictureId"/>
                    </xsl:attribute>
                    <xsl:element name="Location">
                      <xsl:value-of select="Location"/>
                    </xsl:element>
                    <xsl:element name="AdvertisementId">
                      <xsl:value-of select="AdvertisementId"/>
                    </xsl:element>
                  </xsl:element>
                </xsl:for-each>
              </xsl:element>
            </xsl:for-each>
          </xsl:element>
          <xsl:element name="Contacts">
            <xsl:for-each select="$ApplicationUser/Contacts/ContactDTO">
              <xsl:variable name="Contact" select="."/>
              <xsl:element name="Contact">
                <xsl:attribute name="Id">
                  <xsl:value-of select="@Id"/>
                </xsl:attribute>

                <xsl:element name="ContactValue">
                  <xsl:value-of select="ContactValue" />
                </xsl:element>

                <xsl:element name="UserName">
                  <xsl:value-of select="UserName" />
                </xsl:element>

                <xsl:element name="ContactTypeName">
                  <xsl:value-of select="ContactTypeName" />
                </xsl:element>
              </xsl:element>
            </xsl:for-each>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>


Veebiteenuse retsensioon

Meeskonnale: Raavo V2™

Antud töö on ilusti kirjutatud ning ei oma suuremaid vigu ning kõik Must Have eesmärgid on edukalt saavutatud. Nice to Have eesmärgid on kahjuks kõik jäänud tegemata. Kogu projekt on ilusti kommenteeritud ning ei oma vigu, mis jäävad koheselt silma. Projekti struktuur on ilusti püsti pandud ning ükski klass ei ole suvalises kaustas. Projekti sees on tehtud eraldi lisaks WebAppile veel viis eraldi väiksemat projekti, kus hoitakse domeene, liideseid ning Entity Frameworkiga seostuvaid klasse.

Veebiteenuses on täidetud kõik nõuded peale kasutaja statistika. Seda nõuet saab küll täita mitut moodi ning kasutaja statistikat on ka võimalik võtta broneeringutest seega võib seda tehniliselt lugeda täidetuks.

Kõik klassid, millele on mõttekas luua liides, on see ka tehtud. Domeenidel on kõik vajalikud väljad piiratud ning on ära märgitud, mida on vaja ära täita, mis on välisvõti, mis on võti ning väljastatakse ka veateated, kui ületab limiiti.

Projektile on lisatud UnitOfWork meetod ning startupis on ka olemas vajalikud sisendid, et seda kasutada, kuid mitte kordagi ei ole seda projekti vältel kasutatud. UnitOfWork lisab antud projekti palju üleliigset koodi, ilma milleta saaks edukalt hakkama. UnitOfWorki on lisatud ka kõik domeenid seega mingiaeg on mõeldud selle kasutamise peale.

Kontrolleritele ei ole tehtud eraldi teenuseid, seega seda võib-olla hiljem keeruline muuta ja testida. Kõik kontrollerid nõuavad autoriseerimist seega ei tohiks keegi pääseda ligi informatsioonile, millele tal pole õigust. Kahjuks tundub, et autoriseerimine on mingilt maalt jäänud pooleli ning muutmise meetodid pole avatud tavakasutajale. Näiteks kui soovib kasutaja muuta auto informatsiooni, siis ta peab selle hoopis ära kustutama ja uuesti lisama, kuna PUT meetodile on lubatud ligipääs vaid administraatoril. API’de juures oleks võinud kommentaari „summary“ osasse panna täpsema info, et millega antud meetod tegeleb. Hetkel on seal lihtsalt kuidas meetodile ligi pääseda, mis oli automaatselt genereeritud. Igast kontrolleri meetodist ei tule ka tagasi IActionResult, mille tõttu võivad mõned meetodid tagastada vale koodi.

Antud töös ei ole kasutatud Data Transfer Objecteid (DTO’sid), seega kui kasutada API’t, siis saavad kasutajad palju informatsiooni tagasi, kui nemad peaksid saama. Kuna DTO puudub, siis võib ka läbi API saada ligi konfidentsiaalsele informatsioonile, kui ei ole ettevaatlik.

Kuigi kõik kontrollerid on ilusti ära kommenteeritud ning autorisatsioon on kõikidel meetoditel olemas, siis väga tihti on autoriseeritud roll ainult administraatoril, kuigi peaks olema ka teistel. Samuti on näiteks kasutaja lisamine läbi API lubatud ainult administraatoril ja seda tehakse valesti. Kasutaja informatsioon lisatakse otse andmebaasi läbi ApplicationDbContexti, paroole ei hashita ja informatsiooni üle ei kontrollita. Selle jaoks oleks võinud kasutada userManageri, kus on kõik vajalikud meetodid ja kontrollid juba sisse ehitatud.

Klientrakendus ja API ei ole ka väga kooskõlas. Näiteks saab klientrakenduses vahetada kasutajainformatsiooni ka kasutajana, kuid kui teha seda läbi API, siis peab olema administraator, et muuta kasutaja informatsiooni.

BookingArchive ei saa ka töötaja vaadata läbi API, see informatsioon peaks olema neile kindlasti ligipääsetav.

Kasutajatele ei ole kuidagi võimalik läbi API lisada kasutajarolle, rolle on küll ennast võimalik lisada, muuta ja kustutada, kuid nende ühendamist kasutajakontodega ei ole veel lisatud (läbi API).

Projekti käivitades luuakse andmebaasi kohe kolm erinevat rolli, Admin, worker ja User ning kõikidel neil on erinevad õigused teenuse kasutamisel. Ükski roll ei ole ülearu, kuid näiteks worker ei saa lisada teenuse tüüpe ja teenuseid seega mõndade rollide õigused tunduvad algselt poolikud. Kohe alguses luuakse ka administraator, mille parooli vahetamist peaks kasutajalt sisse logides nõudma, et muudaks. Selle jaoks võib ka teha teavituse ülesse serva, kui on algne parool, siis tuletaks meelde, et muutke ära. Igat kasutajat on ka võimalik deaktiveerida, sellehulgas ka administraatori oma. Administraatori kasutaja on ainuke, kelle oma ei tohiks deaktiveerida, kui ta on ainuke administraator. Ehk teha selle jaoks test, kui on ainult 1 isik administraatori rollidega, siis teda deaktiveerida ei saa.

Antud programm on hästi tehtud ning kommenteeritud. Kõik liidesed, mida oleks vaja on olemas, kuid puudavad Data Transfer Objekt klassid, mis ei ole küll nõutud, kuid API vastusteks sobiksid palju paremini. UnitOfWork tundub olevat antud projektis üleliigne ja API peale ei ole täielikult läbi mõeldud. Projektis ei esine ühtegi suuremat viga ning väärib kõrget punktisummat.