Евгений Колесников 3 жил өмнө
parent
commit
c827bf3e2e

+ 25 - 17
articles/f6_demo_1.md

@@ -118,16 +118,35 @@ https://www.figma.com/file/tD64TlCMQEqlr8OTv6bW2o/KOD1.4-Variant3?node-id=0%3A1
 Проект мобильного приложения успешно собирается | 0.1
 Иконка приложения соответствует Заданию | 0.2
 
+Все ресурсы нужно получать из "фигмы"
+
+**Как пользоваться "фигмой" для получения ресурсов:**
+
+![](../img/f6_011.png)
+
+1. Убедитесь, что смотрите правильный вариант вёрстки (нам нужен Андроид, Модуль 1)
+1. Экраны подписаны - нам нужен Icon-android (конкретно этот оказался не подписан)
+    Выбираем элемент, который хотим экспортировать, например, иконку
+1. В правой панели выберите закладку **Export**
+1. Нажмите символ `+`, чтобы открыть настройки экспорта
+1. Окройте **Preview** и убедитесь что элемент выбран весь целиком
+1. Если в **Preview** видна только часть элемента, то в левой панели можно выбрать элемент выше по иерархии
+1. Убедитесь, что формат для экспорта **PNG** и жмите **кнопку** Export
+
+Браузер сохранит файл с тем же названием, что и у элемента вёрстки, например `Icon-android 512.png`). Переименуйте его, убрав пробелы, чёрточки и любую другую фигню, которая может помешать воспринимать ресурс по имени (оставьте только латинские буквы и цифры). Ещё, как выяснилось на практике, ресурсы не могут быть в **CamelCase**, при именовании не используйте большие буквы.
+
 Про создание иконок смотри [первичную настройку приложения](./android_auth.md#первичная-настройка-приложения)
 
-В этом задании используется тёмная тема. Для переключения в ночной режим в конструктор каждого окна добавить код.
+В этом задании используется тёмная тема. Для переключения в ночной режим в файле разметки в режиме "дизайна" установите соответствующий параметр.
+
+![](../img/f6_012.png)
+
+или в коде принудительно переключитесь в ночной режим:
 
 ```kt
 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
 ```
 
-Все графические ресурсы для приложения вы должны загрузить из "фигмы", про неё расписано в разделе [Экран Launch Screen](#экран-launch-screen)
-
 ## Экран Launch Screen
 
 >2. Реализуйте экран Launch Screen согласно макету. Текст должен быть отдельным элементом. Логотип приложения должен быть расположен по центру экрана.
@@ -137,24 +156,13 @@ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
 Текст на Launch Screen является отдельным элементом | 0.1
 Логотип на Launch Screen отцентрирован | 0.1
 
-Как пользоваться "фигмой" для получения ресурсов:
-
-![figma](../img/f6_002.png)
-
-1. Убедитесь, что смотрите правильный вариант вёрстки (нам нужен Андроид, Модуль 1)
-2. Экраны подписаны - нам нужен Launch Screen
-3. Выбираем элемент, который хотим экспортировать, например, логотип
-4. В правой панели выберите закладку **Export**
-5. Окройте **Preview** и убедитесь что элемент выбран весь целиком
-6. Убедитесь, что формат для экспорта **PNG** и жмите **кнопку** Export
-
-Браузер сохранит файл с тем же названием, что и у элемента вёрстки (`video-camera 2.png`). Переименуйте его, убрав пробелы, чёрточки и любую другую фигню, которая может помешать воспринимать ресурс по имени (оставьте только латинские буквы и цифры). Ещё, как выяснилось на практике, ресурсы не могут быть в CamelCase, при именовании не используйте большие буквы.
+Экспортируйте необходимые файлы из "фигмы".
 
-Перенесите (drag-n-drop) полученный файл в ресурс drawable проекта
+Перенесите (drag-n-drop) полученные файлы в ресурс *drawable* проекта
 
 ![](../img/f6_004.png)
 
-в шаблон главного окна (`activity_main.xml`) добавьте элемент **ImageView** и отцентрируйте его горизонтально и вертикально (на этом окне можно не извращаться и не добавлять **LinearLayout**)
+в шаблон окна добавьте элемент **ImageView** и отцентрируйте его горизонтально и вертикально (на этом окне можно не извращаться и не добавлять **LinearLayout**)
 
 ![](../img/f6_003.png)
 

+ 0 - 19
cinema/api.rest

@@ -2,25 +2,6 @@
 
 # http://swagger.kolei.ru?url=http://cinema.kolei.ru/swagger/cinema.yml
 
-### Регистрация
-POST {{url}}/auth/register
-Content-Type: application/json
-
-{
-  "email": "kolei@yandex.ru",
-  "password": "123456",
-  "firstName": "Евгений",
-  "lastName": "Колесников"
-}
-
-### Аутентификация
-POST {{url}}/auth/login
-Content-Type: application/json
-
-{
-  "email": "kolei@yandex.ru",
-  "password": "123456"
-}
 
 ### Получение списка фильмов
 GET {{url}}/movies?filter=new

+ 42 - 35
cinema/index.js

@@ -18,7 +18,7 @@ const app = express()
 app.use( express.urlencoded() )
 app.use( express.json() )
 
-app.use('/up/images', express.static(__dirname +'/images') )
+app.use('/up/images', cors(), express.static(__dirname +'/images') )
 app.use('/swagger', cors(), express.static(__dirname +'/swagger') )
 
 // логгирую все входящие запросы
@@ -52,9 +52,6 @@ function findUserByToken(token) {
 app.options('/auth/register', cors())
 app.post('/auth/register', cors(), (req,res)=>{
   try {
-    // if(req.headers.token==undefined) 
-    //   throw new Error("В заголовке запроса нет токена")
-
     if(req.body.email==undefined) 
       throw new Error('Not found "email" param')
 
@@ -72,14 +69,21 @@ app.post('/auth/register', cors(), (req,res)=>{
       throw new Error('Param "email" don`t match template')
 
     let user = findUserByEmail(req.body.email)
-    if (user == null)
+    if (user == null) {
+      let user = null
+      let token = null
+      do {
+        token = Math.ceil(Math.random() * 999998)
+        user = findUserByToken(token)
+      } while (user != null);
       registeredUsers.push({
         email: req.body.email,
         password: req.body.password,
         firstName: req.body.firstName,
         lastName: req.body.lastName,
-        token: registeredUsers.length + 1
+        token: token
       })
+    }
 
     res.status(201)
   } catch (error) {
@@ -112,41 +116,44 @@ app.post('/auth/login', cors(), (req,res)=>{
   res.end()
 })
 
+function checkAuth(req){
+  if(req.headers.authorization==undefined) 
+    throw new Error('No Authorization header')
+
+  let parts = req.headers.authorization.split(' ')
+  if (parts.length == 2) {
+    if (parts[0] == 'Bearer') {
+      let user = findUserByToken(parts[1])
+      if (user == null)
+        throw new Error('User not found')
+    } else
+      throw new Error('Unsupported Authorization method')
+  } else
+    throw new Error('Bad Authorization content')
+}
+
 app.options('/movies', cors())
 app.get('/movies', cors(), (req,res)=>{
   try {
     if (typeof req.query.filter == 'undefined')
       throw new Error('Filter is required parameter')
 
-    if(req.headers.authorization==undefined) 
-      throw new Error('No Authorization header')
-
-    let parts = req.headers.authorization.split(' ')
-    if (parts.length == 2) {
-      if (parts[0] == 'Bearer') {
-        let user = findUserByToken(parts[1])
-        if (user == null)
-          throw new Error('User not found')
-        else {
-          let filtered = movies
-            .filter(m => m.filters.includes(req.query.filter))
-          let mapped = filtered.map(m => {
-            return {
-              movieId: m.movieId, 
-              name: m.name,
-              description: m.description,
-              age: m.age, 
-              images: m.images, 
-              poster: m.poster, 
-              tags: m.tags
-            }
-          })
-          res.json(mapped)
-        }
-      } else
-        throw new Error('Unsupported Authorization method')
-    } else
-      throw new Error('Bad Authorization content')
+    checkAuth(req)
+
+    let filtered = movies
+      .filter(m => m.filters.includes(req.query.filter))
+    let mapped = filtered.map(m => {
+      return {
+        movieId: m.movieId, 
+        name: m.name,
+        description: m.description,
+        age: m.age, 
+        images: m.images, 
+        poster: m.poster, 
+        tags: m.tags
+      }
+    })
+    res.json(mapped)
   } catch (error) {
     res.statusMessage = error.message
     res.status(400)

+ 80 - 3
cinema/swagger/cinema.yml

@@ -1,6 +1,6 @@
 openapi: 3.0.0
 info:
-  title: Попытка написать своё АПИ в Swagger
+  title: АПИ для демо-экзамена по компетенции Разработка мобильных приложений
   version: 0.0.1
   description: |
     API для мобильного приложения "WS-Cinema".
@@ -23,6 +23,8 @@ servers:
 tags:
   - name: auth
     description: Регистрация и авторизация (получение токена)
+  - name: movie
+    description: Информация о киноновинках
 
 paths:
   /auth/register:
@@ -69,7 +71,6 @@ paths:
       tags:
         - auth
       summary: Аутентификация в системе
-
       requestBody:
         required: true
         content:
@@ -100,5 +101,81 @@ paths:
                     type: integer
                     description: Токен доступа к серверу
                     example: 123456
+#          links:
+#            GetAuthToken:
+#              parameters:
+#                token: '$response.body#/token'
         '400':
-          description: Проблема аутентификации                    
+          description: Проблема аутентификации
+  /movies:
+    get:
+      tags:
+        - movie
+      summary: Получить список фильмов
+      description: Список фильмов для отображения на главном экране
+      parameters:
+        - name: filter
+          in: query
+          description: Фильтр для запроса
+          required: true
+          schema:
+            type: string
+            default: new
+            enum: [new, inTrend, forMe]
+      responses:
+        '200':
+          description: Массив фильмов
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ArrayOfMovies'
+        '400':
+          description: Проблемы при запросе
+components:
+  securitySchemes:
+    BearerAuth:
+      type: http
+      scheme: bearer
+  schemas:
+    ArrayOfMovies:
+      type: array
+      items:
+        type: object
+        properties:
+          movieId:
+            type: string
+            example: 1
+          name:
+            type: string
+            example: Название фильма
+          description:
+            type: string
+            example: Описание фильма
+          age:
+            type: string
+            enum: ['0','6','12','16','18']
+            description: Возрастные ограничения
+          images:
+            type: array
+            items: 
+              type: string
+          poster:
+            type: string
+            example: poster.png
+            description: Название картинки постера
+          tags:
+            $ref: '#/components/schemas/ArrayOfTags'
+        required:
+          - movieId
+    ArrayOfTags:
+      type: array
+      items:
+        type: object
+        properties:
+          idTags:
+            type: string
+            example: 13
+          tagName:
+            type: string
+            example: Комедия
+

BIN
img/f6_011.png


BIN
img/f6_012.png