Сиеста REST логин

Как перевести мой логин URLSession код в коде системы Сиеста? Моя текущая попытка не работает.

Я посмотрел на пример в GithubBrowser, но API у меня не работает так.

Проблема в том, что структура пользователя в некоторой степени разделена тем, как работает конечная точка в API, который я использую. Конечная точка http://server.com/api/key, Да, это действительно называется key и не user или же login, Это назвали авторы, потому что вы публикуете пару пользователь / пароль и получаете ключ назад. Таким образом, он принимает (через почту) структуру json, такую ​​как:

{"name": "bob", "password": "s3krit"}

и возвращает в качестве ответа:

{"token":"AEWasBDasd...AAsdga"}

у меня есть SessionUser структура:

struct SessionUser: Codable
{
    let name: String
    let password: String
    let token: String
}

... который инкапсулирует состояние ("S" в REST) ​​для пользователя. Проблема в том, что имя и пароль публикуются, а токен - это ответ.

Когда это состояние меняется, я делаю свое:

service.invalidateConfiguration()  // So requests get config change
service.wipeResources()            // Scrub all unauthenticated data

Экземпляр хранится в единственном экземпляре, который выбирается блоком настройки, так что токен от API помещается в заголовок для всех других запросов API:

    configure("**") {
        // This block ^ is run AGAIN when the configuration is invalidated
        // even if loadManifest is not called again.
        if let haveToken = SessionManager.shared.currentUser?.token
        {
            $0.headers["Authorization"] = haveToken
        }
    }

Кстати, эта часть для инъекции токена уже работает хорошо. Уу, сиеста!

Версия URLSession

Это раздутый по сравнению с Сиестой, и я сейчас не использую это, но вот то, что было раньше:

func login(user: SessionUser, endpoint: URL)
{
    DDLogInfo("Logging in: \(user.name) with \(user.password)")

    let json: [String: Any] = ["name": user.name, "password": user.password]
    let jsonData = try? JSONSerialization.data(withJSONObject: json)
    var request = URLRequest(url: endpoint)
    request.httpMethod = "POST"
    request.httpBody = jsonData
    _currentStatus = .Unknown

    weak var welf = self
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else {
            handleLogin(error: error, message: "No data from login attempt")
            return
        }
        let jsonData:Any
        do {
            jsonData = try JSONSerialization.jsonObject(with: data, options: [])
        }
        catch let jsonDecodeError {
            handleLogin(error: jsonDecodeError, message: "Could not get JSON from login response data")
            return
        }
        guard let jsonDecoded = jsonData as? [String: Any] else {
            handleLogin(error: error, message: "Could not decode JSON as dictionary")
            return
        }
        guard let token = jsonDecoded["token"] as? String else {
            handleLogin(error: error, message: "No auth token in login response")
            return
        }
        let newUser = SessionUser(name: user.name, password: "", token: token)
        welf?.currentUser = newUser
        welf?.saveCurrentSession()
        welf?._currentStatus = .LoggedIn
        DDLogInfo("User \(newUser.name) logged in")
        loginUpdate(user: newUser, status: .LoggedIn, message: nil, error: nil)
    }

    task.resume()
}

Сиеста Версия

Вот моя попытка прямо сейчас:

func login(user: String, pass: String, status: @escaping (String?) -> ())
{
    let json = [ "name": user, "password": pass]
    let req = ManifestCloud.shared.keys.request(.post, json: json)
    req.onSuccess { (tokenInfo) in
        if let token = tokenInfo.jsonDict["token"] as? String
        {
            let newUser = SessionUser(name: user, password: pass, token: token)
            self.currentUser = newUser
        }
        status("success")
    }
    req.onFailure { (error) in
        status(error.userMessage)
    }
    req.onCompletion { (response) in
        status(nil)
    }
}

Это своего рода работа, но учетные данные для входа в систему не сохраняются в Siesta, и мне пришлось настроить новую систему уведомлений для состояния входа в систему, что я надеялся, что Siesta сделает для меня.

Я хочу использовать кэширование Siesta, чтобы объект SessionUser кэшировался локально, и я могу использовать его для получения нового токена, при необходимости, с использованием кэшированных учетных данных. На данный момент у меня есть система с использованием жюри, использующая UserDefaults,

Любая помощь приветствуется!

1 ответ

Решение

Основная проблема здесь в том, что вы запрашиваете, но не загружаете ресурс. Сиеста проводит различие между этими двумя вещами: первое, по сути, причудливый запрос URLSession; второе означает, что Сиеста держится за какой-то штат и уведомляет об этом наблюдателей.

Забавно, я только что ответил на другой, но связанный с этим вопрос несколько минут назад! Вы можете найти этот ответ полезной отправной точкой.

В вашем случае проблема здесь:

let req = ManifestCloud.shared.keys.request(.post, json: json)

Тот .request(…) означает, что только ваш запрос перехватывает (onSuccess и т.д.) получите уведомление, когда ваш запрос POST завершится, и Siesta не будет следить за состоянием, чтобы другие могли его наблюдать.

Обычно вы выполняете это, используя .load(); однако это создает запрос GET, и вам нужен POST. Вы, вероятно, хотите рекламировать свой POST как запрос полной загрузки, например:

let keysResource = ManifestCloud.shared.keys
let req = keysResource.load(using:
    keysResource.request(.post, json: json))

Это возьмет все, что вернет POST-запрос, и сделает его (наблюдаемым) latestData из ManifestCloud.shared.keys, которая должна дать вам "систему уведомлений о состоянии входа", которую вы ищете.

Другие вопросы по тегам