React
- 5 ответов
- 0 вопросов
4
Вклад в тег
<style>
input + label {
color: #ff0000;
}
</style>
<input type="checkbox" id="checkbox" />
<label for="checkbox">чекбокс</label>
<style>
label > input {
outline-color: #ff0000;
outline-style: double;
}
</style>
<label>
<input type="checkbox" />
чекбокс
</label>
passport.use('byUsernameAndPassword', // я так назвал свою стратегию
new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
// passReqToCallback: true,
session: false,
}, (username, password, done) => {
User
.verifyByUsernameAndPassword(username, password) // примечание: это, конечно, не базовый метод, он написан "вручную"
.then(user => done(null, user))
.catch(error => done(error, false, error.message));
})
);
passport.use(
new JwtStrategy({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),// passport сам дешифрует токен и проверит его валидность, хотя это и не сложно сделать вручную, если решите passport не использовать
secretOrKey: process.env.ACCESS_SECRET,
session: false,
}, ({ username }, done) => {
// на самом деле можно и не доставать пользователя из базы, просто расшифровать jwt, как я уже писал.
// Доставать из базы можно только тогда, когда его нужно поменять (скажем, пользователю нужно добавить заказ в корзину)
// меньше запросов к БД - быстрее работает
User
.findOne({ phoneNumber: username })
.then(user => {
if (!user) return done(null, false, 'This user has been deleted or changed. Please, login again.');
return done(null, user);
})
.catch(err => done(err));
})
);
module.exports = passport;
const auth = require('../controller/auth');
const router = express.Router();
router.post('/login', passport.authenticate('byUsernameAndPassword'), auth.logIn);
const sessionRouter = express.Router();
// из Refresh-токена извлекаем собственно строку
function decodeRefreshStringFromToken(refreshToken, errorCallback) {
const decoded = require('jsonwebtoken').verify(refreshToken, process.env.REFRESH_SECRET, (error, decoded) => {
return error ? error : decoded;
});
if (decoded instanceof Error) // обработка ошибок
return decoded.refreshToken;
}
// для любой работы с сессией в теле запроса будем ожидать Refresh-токена
sessionRouter.use((req, res, next) => {
if (!req.body.refreshToken) return next(new RefreshTokenUnauthorizedError());
res.locals.refreshString = decodeRefreshStringFromToken(req.body.refreshToken, next);
return next();
});
// выход - удаление сессии из БД
sessionRouter.post('/logout', auth.logOut); // todo: jwtAuthMiddleware here&&
// сессия становится неактивной (пользователь закрыл приложение) - зачем нужен данный роут? В БД у сессии будем хранить поле isActive. Если пользователь сидит сразу с двух устройств - подозрительно)
sessionRouter.post('/interrupt', auth.interruptSession);
// обновляем сессию, когда время жизни Refresh-токена вышло
sessionRouter.post('/refresh', auth.refreshSession);
router.use('/session', sessionRouter);
module.exports = router;
module.exports.logIn = async (req, res, next) => {
req.user.installSession(req.useragent)
.then(newSessionData => {
res.json(newSessionData);
next();
});
};
userSchema.methods.installSession = async function(useragent) {
const newSession = this.createSession(useragent); // метод реализован ниже
if (this.sessions.length > 5) this.sessions = []; // допустим ограничение максимум в 5 сессий
if (this.sessions.find(session => session.isActive)) {// выходить из всех активных сессий, может даже удалять их}
this.sessions.push(newSession);
await this.save();
return this.makeSessionData(newSession.refreshToken);
};
userSchema.methods.createSession = function({ browser, os, platform }) {
return {
refreshString: this.generateRefreshString(),
browser,
os,
platform,
};
};
userSchema.methods.makeSessionData = function(refreshString) {
const {
id,
name,
phoneNumber,
role,
} = this;
const refreshToken = this.makeRefreshJwtToken(refreshString);
return ({ id, name, phoneNumber, role, refreshToken, accessToken: this.makeAccessJwtToken({ username: this.username }), tokenType: 'Bearer', expiresIn: process.env.ACCESS_EXPIRES_IN, });
};
userSchema.methods.makeRefreshJwtToken = function(refreshString) {
return jwt.sign(
{ refreshString },
REFRESH_SECRET,
{ expiresIn: REFRESH_EXPIRES_IN });
};
Достаточно ли просто создать div#catalog и рендерить в него компоненты реакта?
<html>
<head>
<title>PHP React Test</title>
<script src="https://unpkg.com/react@17/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<?php
$INIT_PARAMS = ['user' => 'Vasilij']; // данные из PHP
echo '<p>Hello React App</p>';
?>
<div id='react-app'></div>
// React-component. Конечно, лучше вынести в отдельный файл, если кода много.
// Еще лучше скомпилировать и подключить минифицированный бандл. Здесь - концептуальный пример.
<script type="text/babel">
'use strict';
const {useState} = React;
function App({user}) {
const [liked, setLiked] = useState(false);
return (
liked ? (`You (${user}) liked this.`) : (
<button onClick={() => setLiked(true)}>
Like
</button>
)
)
}
const domContainer = document.querySelector('#react-app');
ReactDOM.render(<App user={'<?=$INIT_PARAMS['user']?>'}/>, domContainer);
</script>
</body>
</html>
И как быть с SEO в таком случае?
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
class AdJob extends Component {
public $adJob;
public function mount($adJobId) {
$this->adJob = \App\Models\AdJob::find( $adJobId );
}
public function setReleaserForAdJob($releaserId) {
$this->adJob['releaser_id'] = $releaserId;
$this->adJob['status'] = 'in_progress';
$this->adJob->save();
}
public function setAdJobDone() {
$this->adJob['status'] = 'done';
$this->adJob->save();
}
public function render() {
return view('livewire.ad-job-with-reviews');
}
}
res.send(ReactDOMServer.renderToString(myElement))
- получаем нечто вроде создания "шаблона" (res.send - API express, остальное - react)const html = ReactDOMServer.renderToString(app);
Есть смысл сгенерировать картинку в формате строки base64 и потом JSON-ом передавать на бекенд?