mirror of
https://github.com/lasthead0/yandex2mqtt.git
synced 2025-08-08 01:00:31 +03:00
Release
This commit is contained in:
13
routes/client.js
Normal file
13
routes/client.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const passport = require('passport');
|
||||
|
||||
module.exports.info = [
|
||||
passport.authenticate('bearer', { session: false }), (req, res) => {
|
||||
// request.authInfo is set using the `info` argument supplied by
|
||||
// `BearerStrategy`. It is typically used to indicate scope of the token,
|
||||
// and used in access control checks. For illustrative purposes, this
|
||||
// example simply returns the scope in the response.
|
||||
res.json({ client_id: req.user.id, name: req.user.name, scope: req.authInfo.scope });
|
||||
}
|
||||
];
|
13
routes/index.js
Normal file
13
routes/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const site = require('./site');
|
||||
const oauth2 = require('./oauth2');
|
||||
const user = require('./user');
|
||||
const client = require('./client');
|
||||
|
||||
module.exports = {
|
||||
site,
|
||||
oauth2,
|
||||
user,
|
||||
client,
|
||||
};
|
213
routes/oauth2.js
Normal file
213
routes/oauth2.js
Normal file
@@ -0,0 +1,213 @@
|
||||
'use strict';
|
||||
|
||||
const oauth2orize = require('@poziworld/oauth2orize');
|
||||
const passport = require('passport');
|
||||
const login = require('connect-ensure-login');
|
||||
const db = require('../db');
|
||||
const utils = require('../utils');
|
||||
|
||||
// Create OAuth 2.0 server
|
||||
const server = oauth2orize.createServer();
|
||||
|
||||
// Register serialization and deserialization functions.
|
||||
//
|
||||
// When a client redirects a user to user authorization endpoint, an
|
||||
// authorization transaction is initiated. To complete the transaction, the
|
||||
// user must authenticate and approve the authorization request. Because this
|
||||
// may involve multiple HTTP request/response exchanges, the transaction is
|
||||
// stored in the session.
|
||||
//
|
||||
// An application must supply serialization functions, which determine how the
|
||||
// client object is serialized into the session. Typically this will be a
|
||||
// simple matter of serializing the client's ID, and deserializing by finding
|
||||
// the client by ID from the database.
|
||||
|
||||
server.serializeClient((client, done) => done(null, client.id));
|
||||
|
||||
server.deserializeClient((id, done) => {
|
||||
db.clients.findById(id, (error, client) => {
|
||||
if (error) return done(error);
|
||||
return done(null, client);
|
||||
});
|
||||
});
|
||||
|
||||
// Register supported grant types.
|
||||
//
|
||||
// OAuth 2.0 specifies a framework that allows users to grant client
|
||||
// applications limited access to their protected resources. It does this
|
||||
// through a process of the user granting access, and the client exchanging
|
||||
// the grant for an access token.
|
||||
|
||||
// Grant authorization codes. The callback takes the `client` requesting
|
||||
// authorization, the `redirectUri` (which is used as a verifier in the
|
||||
// subsequent exchange), the authenticated `user` granting access, and
|
||||
// their response, which contains approved scope, duration, etc. as parsed by
|
||||
// the application. The application issues a code, which is bound to these
|
||||
// values, and will be exchanged for an access token.
|
||||
|
||||
server.grant(oauth2orize.grant.code((client, redirectUri, user, ares, done) => {
|
||||
const code = utils.getUid(16);
|
||||
db.authorizationCodes.save(code, client.id, redirectUri, user.id, user.username, (error) => {
|
||||
if (error) return done(error);
|
||||
return done(null, code);
|
||||
});
|
||||
}));
|
||||
|
||||
// Grant implicit authorization. The callback takes the `client` requesting
|
||||
// authorization, the authenticated `user` granting access, and
|
||||
// their response, which contains approved scope, duration, etc. as parsed by
|
||||
// the application. The application issues a token, which is bound to these
|
||||
// values.
|
||||
|
||||
server.grant(oauth2orize.grant.token((client, user, ares, done) => {
|
||||
const token = utils.getUid(256);
|
||||
db.accessTokens.save(token, user.id, client.clientId, (error) => {
|
||||
if (error) return done(error);
|
||||
return done(null, token);
|
||||
});
|
||||
}));
|
||||
|
||||
// Exchange authorization codes for access tokens. The callback accepts the
|
||||
// `client`, which is exchanging `code` and any `redirectUri` from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the user who authorized the
|
||||
// code. The issued access token response can include a refresh token and
|
||||
// custom parameters by adding these to the `done()` call
|
||||
|
||||
server.exchange(oauth2orize.exchange.code((client, code, redirectUri, done) => {
|
||||
db.authorizationCodes.find(code, (error, authCode) => {
|
||||
if (error) return done(error);
|
||||
if (client.id !== authCode.clientId) return done(null, false);
|
||||
if (redirectUri !== authCode.redirectUri) return done(null, false);
|
||||
|
||||
const token = utils.getUid(256);
|
||||
db.accessTokens.save(token, authCode.userId, authCode.clientId, (error) => {
|
||||
if (error) return done(error);
|
||||
// Add custom params, e.g. the username
|
||||
let params = { username: authCode.userName };
|
||||
// Call `done(err, accessToken, [refreshToken], [params])` to issue an access token
|
||||
return done(null, token, null, params);
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
// Exchange user id and password for access tokens. The callback accepts the
|
||||
// `client`, which is exchanging the user's name and password from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the user who authorized the code.
|
||||
|
||||
server.exchange(oauth2orize.exchange.password((client, username, password, scope, done) => {
|
||||
// Validate the client
|
||||
db.clients.findByClientId(client.clientId, (error, localClient) => {
|
||||
if (error) return done(error);
|
||||
if (!localClient) return done(null, false);
|
||||
if (localClient.clientSecret !== client.clientSecret) return done(null, false);
|
||||
// Validate the user
|
||||
db.users.findByUsername(username, (error, user) => {
|
||||
if (error) return done(error);
|
||||
if (!user) return done(null, false);
|
||||
if (password !== user.password) return done(null, false);
|
||||
// Everything validated, return the token
|
||||
const token = utils.getUid(256);
|
||||
db.accessTokens.save(token, user.id, client.clientId, (error) => {
|
||||
if (error) return done(error);
|
||||
// Call `done(err, accessToken, [refreshToken], [params])`, see oauth2orize.exchange.code
|
||||
return done(null, token);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
// Exchange the client id and password/secret for an access token. The callback accepts the
|
||||
// `client`, which is exchanging the client's id and password/secret from the
|
||||
// authorization request for verification. If these values are validated, the
|
||||
// application issues an access token on behalf of the client who authorized the code.
|
||||
|
||||
server.exchange(oauth2orize.exchange.clientCredentials((client, scope, done) => {
|
||||
// Validate the client
|
||||
db.clients.findByClientId(client.clientId, (error, localClient) => {
|
||||
if (error) return done(error);
|
||||
if (!localClient) return done(null, false);
|
||||
if (localClient.clientSecret !== client.clientSecret) return done(null, false);
|
||||
// Everything validated, return the token
|
||||
const token = utils.getUid(256);
|
||||
// Pass in a null for user id since there is no user with this grant type
|
||||
db.accessTokens.save(token, null, client.clientId, (error) => {
|
||||
if (error) return done(error);
|
||||
// Call `done(err, accessToken, [refreshToken], [params])`, see oauth2orize.exchange.code
|
||||
return done(null, token);
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
// User authorization endpoint.
|
||||
//
|
||||
// `authorization` middleware accepts a `validate` callback which is
|
||||
// responsible for validating the client making the authorization request. In
|
||||
// doing so, is recommended that the `redirectUri` be checked against a
|
||||
// registered value, although security requirements may vary across
|
||||
// implementations. Once validated, the `done` callback must be invoked with
|
||||
// a `client` instance, as well as the `redirectUri` to which the user will be
|
||||
// redirected after an authorization decision is obtained.
|
||||
//
|
||||
// This middleware simply initializes a new authorization transaction. It is
|
||||
// the application's responsibility to authenticate the user and render a dialog
|
||||
// to obtain their approval (displaying details about the client requesting
|
||||
// authorization). We accomplish that here by routing through `ensureLoggedIn()`
|
||||
// first, and rendering the `dialog` view.
|
||||
|
||||
module.exports.authorization = [
|
||||
login.ensureLoggedIn(),
|
||||
server.authorization((clientId, redirectUri, done) => {
|
||||
db.clients.findByClientId(clientId, (error, client) => {
|
||||
if (error) return done(error);
|
||||
// WARNING: For security purposes, it is highly advisable to check that
|
||||
// redirectUri provided by the client matches one registered with
|
||||
// the server. For simplicity, this example does not. You have
|
||||
// been warned.
|
||||
return done(null, client, redirectUri);
|
||||
});
|
||||
}, (client, user, done) => {
|
||||
// Check if grant request qualifies for immediate approval
|
||||
|
||||
// Auto-approve
|
||||
if (client.isTrusted) return done(null, true);
|
||||
|
||||
db.accessTokens.findByUserIdAndClientId(user.id, client.clientId, (error, token) => {
|
||||
// Auto-approve
|
||||
if (token) return done(null, true);
|
||||
|
||||
// Otherwise ask user
|
||||
return done(null, false);
|
||||
});
|
||||
}),
|
||||
(req, res) => {
|
||||
res.render('dialog', { transactionId: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });
|
||||
},
|
||||
];
|
||||
|
||||
// User decision endpoint.
|
||||
//
|
||||
// `decision` middleware processes a user's decision to allow or deny access
|
||||
// requested by a client application. Based on the grant type requested by the
|
||||
// client, the above grant middleware configured above will be invoked to send
|
||||
// a response.
|
||||
|
||||
module.exports.decision = [
|
||||
login.ensureLoggedIn(),
|
||||
server.decision(),
|
||||
];
|
||||
|
||||
|
||||
// Token endpoint.
|
||||
//
|
||||
// `token` middleware handles client requests to exchange authorization grants
|
||||
// for access tokens. Based on the grant type being exchanged, the above
|
||||
// exchange middleware will be invoked to handle the request. Clients must
|
||||
// authenticate when making requests to this endpoint.
|
||||
|
||||
module.exports.token = [
|
||||
passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
|
||||
server.token(),
|
||||
server.errorHandler(),
|
||||
];
|
19
routes/site.js
Normal file
19
routes/site.js
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const passport = require('passport');
|
||||
const login = require('connect-ensure-login');
|
||||
|
||||
module.exports.index = (req, res) => res.send('OAuth 2.0 Server');
|
||||
|
||||
module.exports.loginForm = (req, res) => res.render('login');
|
||||
|
||||
module.exports.login = passport.authenticate('local', {successReturnToOrRedirect: '/', failureRedirect: '/login'});
|
||||
|
||||
module.exports.logout = (req, res) => {
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
};
|
||||
|
||||
module.exports.account = [
|
||||
login.ensureLoggedIn(), (req, res) => res.render('account', {user: req.user}),
|
||||
];
|
92
routes/user.js
Normal file
92
routes/user.js
Normal file
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
|
||||
const passport = require('passport');
|
||||
|
||||
module.exports.info = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
const {user} = req;
|
||||
res.json({user_id: user.id, name: user.name, scope: req.authInfo.scope});
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.ping = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
res.status(200).send('OK');
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.devices = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
const reqId = req.get('X-Request-Id');
|
||||
const r = {
|
||||
request_id: reqId,
|
||||
payload: {
|
||||
user_id: "1",
|
||||
devices: []
|
||||
}
|
||||
};
|
||||
|
||||
for (const d of global.devices) {
|
||||
r.payload.devices.push(d.getInfo());
|
||||
};
|
||||
|
||||
res.status(200).send(r);
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.query = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
const reqId = req.get('X-Request-Id');
|
||||
const r = {
|
||||
request_id: reqId,
|
||||
payload: {
|
||||
devices: []
|
||||
}
|
||||
};
|
||||
|
||||
for (const d of req.body.devices) {
|
||||
const ldevice = global.devices.find(device => device.data.id == d.id);
|
||||
r.payload.devices.push(ldevice.getState());
|
||||
};
|
||||
|
||||
res.status(200).send(r);
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.action = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
const reqId = req.get('X-Request-Id');
|
||||
const r = {
|
||||
request_id: reqId,
|
||||
payload: {
|
||||
devices: []
|
||||
}
|
||||
};
|
||||
|
||||
for (const payloadDevice of req.body.payload.devices) {
|
||||
const {id} = payloadDevice;
|
||||
|
||||
const capabilities = [];
|
||||
const ldevice = global.devices.find(device => device.data.id == id);
|
||||
|
||||
for (const payloadCapability of payloadDevice.capabilities) {
|
||||
capabilities.push(ldevice.setCapabilityState(payloadCapability.state.value , payloadCapability.type, payloadCapability.state.instance));
|
||||
}
|
||||
|
||||
r.payload.devices.push({id, capabilities});
|
||||
};
|
||||
|
||||
res.status(200).send(r);
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.unlink = [
|
||||
passport.authenticate('bearer', {session: true}), (req, res) => {
|
||||
const reqId = req.get('X-Request-Id');
|
||||
const r = {
|
||||
request_id: reqId,
|
||||
}
|
||||
|
||||
res.status(200).send(r);
|
||||
}
|
||||
];
|
Reference in New Issue
Block a user