• Как правильно реализовать сервис изменения баланса пользователю вместе с транзакциями?

    @Quty
    Почему начисление на баланс предшествует созданию транзакции? Что если при создании транзакции возникнет ошибка? Получается, баланс поменяется, а транзакции не будет. Если же на ошибку создания транзакции вызывать списание с баланса, то есть вероятность, что ошибка возникнет при списании.

    На мой взгляд баланс должен формироваться из транзакций. Из них всегда можно "построить" текущее состояние баланса пользователя, что-то вроде Event Source.

    По поводу валюты. Почему бы её просто не прокидывать в метод создания транзакции? Если на один счёт могут быть транзакции в разных валютах, то можно просто при расчёте баланса брать валюту из транзакции и умножать на курс этой валюты на момент создания транзакции.

    Само собой для каждого запроса баланса пользователя не нужно пересчитывать его с "самого начала". Можно кэшировать состояние баланса (создавать snapshot'ы) и при перерасчёте отталкиваться от него.

    Если ближе к сути вопроса, то как вариант можно ввести класс для хранения суммы и валюты, прокидывать во всюду его экземпляры вместо простых чисел (сумм). Этот класс (предположим, Money) нужен только для хранения валюты и суммы. А при изменении состояния баланса получать валюту счёта к которому относится транзакция и с помощью какого-нибудь CurrencyService переводить сумму в валюту счёта, после чего изменять остаток счёта.
    Ответ написан
    Комментировать
  • Где хранятся токены passport.js по умолчанию?

    @Quty
    На стороне сервера JWT нигде не хранится. В этом его суть. Конечно, иногда прибегают к хранения JWT в белом/чёрном списке токенов, но это уже детали.

    JWT в себе должен содержать достаточную информацию о пользователе для его аутентификации и авторизации.

    Если коротко, то JWT — это токен, содержащий JSON объект с полями, заложенными в этот объект при выдаче токена, и подписью. Подпись нужна для того, чтобы сервер (issuer, эмитент) мог удостовериться, что указанный при запросе клиента токен был действительно выдан этим (или доверенным) сервером (эмитентом).

    Например, если взять токен
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.6-NqQiSlSYgbZ-x31JH6g17DkFiTu04VM6CPiptriB0
    то можно заметить, что он состоит из трёх частей, разделенных точкой.
    Первая часть eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 — это заголовок. JSON-объект, закодированный в base64 строку, содержащий информацию о самом токене: тип и алгоритм шифрования, используемый для получения подписи. Если раскодировать строку, то получается {"alg":"HS256","typ":"JWT"}.
    Вторая часть
    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    — это полезная нагрузка. JSON-объект, который был сформирован сервером (эмитентом) при создании токена. Точно так же как и заголовок является base64 стрококой. Если раскодировать, то в данном примере получается
    {"sub":"1234567890","name":"John Doe","iat":1516239022}

    Третья часть 6-NqQiSlSYgbZ-x31JH6g17DkFiTu04VM6CPiptriB0 — это подпись. В данном примере подпись сформирована с помощью алгоритма HS256 (что указано в первой части токена) следующим образом:
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      jwt-secret
    )

    В данном случае секретом для подписания и валидации JWT является строка jwt-secret. Секретный ключ неизвестен клиенту, поэтому он не может сам сформировать JWT с любыми данными. Точнее может, но не может к этим данным сделать валидную подпись, так как не знает секрет. Сервер же секрет знает, поэтому может вычислить подпись из первых двух частей токена и сравнить её с третьей частью.

    Обычно во вторую часть токена (payload) помимо информации о пользователе попадает техническая информация о токене. Например, iat (issued at) — время, когда токен был выдан. Или exp (expiration time) — время, после наступления которого токен станет истёкшим. JWT библиотеки используют exp и при валидации токена выдают ошибку, если указанное время уже прошло.
    Ответ написан
    Комментировать
  • Как синхронизировать действия пользователей и данные в многопользовательской системе?

    @Quty
    Вероятно одним из решений будет внедрение возможности совместного редактирования документа. Посмотрите в сторону collaborative editors. Например, ProseMirror. Не могу сказать наверняка, что решение хорошее, но как вариант, думаю, рассмотреть стоит.
    Ответ написан
  • Где найти уроки по Ruby on Rails?

    @Quty
    Для работы с MySQL есть gem mysql2. Но в Rails Вам не надо работать с СУБД, Rails это делает за Вас. Конечно, можно и самому писать запросы, но в большинстве случаев этого не понадобится, благодаря гибкости моделей в RoR.
    К прочтению могу посоветовать:
    railstutorial.ru и www.rusrails.ru для начала.
    Ответ написан
    Комментировать
  • Как добавить статью с PHP кодом в БД MYSQL?

    @Quty
    403 Access denied - ошибка не PHP или MySQL, а веб-сервера. Скорее всего у Вас неверное сконфигурирован виртуальный хост, либо же недостаточно прав на каталог, в котором находятся скрипты.
    По поводу записи текста, то тут все в порядке, следующий код вполне успешно записывает строку, содержащую PHP код:
    $stmt = $mysqli->prepare("INSERT INTO code_examples(code_text) VALUES (?)") or die;  
    $stmt->bind_param("s", htmlspecialchars('<?php $i = 5; echo $i; ?>')) or die;
    $stmt->execute() or die;
    Ответ написан