feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
288
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/CliAuth.js
generated
vendored
Normal file
288
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/CliAuth.js
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
'use strict'
|
||||
|
||||
const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy')
|
||||
const querystring = require('querystring');
|
||||
|
||||
const http = require('http')
|
||||
const fs = require('fs')
|
||||
const url = require('url')
|
||||
const exec = require('child_process').exec
|
||||
const tryEach = require('async/tryEach')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const needle = require('needle')
|
||||
const chalk = require('chalk')
|
||||
const cst = require('../../../../constants.js')
|
||||
const promptly = require('promptly')
|
||||
|
||||
module.exports = class CliStrategy extends AuthStrategy {
|
||||
// the client will try to call this but we handle this part ourselves
|
||||
retrieveTokens (km, cb) {
|
||||
this.authenticated = false
|
||||
this.callback = cb
|
||||
this.km = km
|
||||
this.BASE_URI = 'https://id.keymetrics.io';
|
||||
}
|
||||
|
||||
// so the cli know if we need to tell user to login/register
|
||||
isAuthenticated () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.authenticated) return resolve(true)
|
||||
|
||||
let tokensPath = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.readFile(tokensPath, (err, tokens) => {
|
||||
if (err && err.code === 'ENOENT') return resolve(false)
|
||||
if (err) return reject(err)
|
||||
|
||||
// verify that the token is valid
|
||||
try {
|
||||
tokens = JSON.parse(tokens || '{}')
|
||||
} catch (err) {
|
||||
fs.unlinkSync(tokensPath)
|
||||
return resolve(false)
|
||||
}
|
||||
|
||||
// if the refresh tokens is here, the user could be automatically authenticated
|
||||
return resolve(typeof tokens.refresh_token === 'string')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
verifyToken (refresh) {
|
||||
return this.km.auth.retrieveToken({
|
||||
client_id: this.client_id,
|
||||
refresh_token: refresh
|
||||
})
|
||||
}
|
||||
|
||||
// called when we are sure the user asked to be logged in
|
||||
_retrieveTokens (optionalCallback) {
|
||||
const km = this.km
|
||||
const cb = this.callback
|
||||
|
||||
tryEach([
|
||||
// try to find the token via the environment
|
||||
(next) => {
|
||||
if (!process.env.PM2_IO_TOKEN) {
|
||||
return next(new Error('No token in env'))
|
||||
}
|
||||
this.verifyToken(process.env.PM2_IO_TOKEN)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(next)
|
||||
},
|
||||
// try to find it in the file system
|
||||
(next) => {
|
||||
fs.readFile(cst.PM2_IO_ACCESS_TOKEN, (err, tokens) => {
|
||||
if (err) return next(err)
|
||||
// verify that the token is valid
|
||||
tokens = JSON.parse(tokens || '{}')
|
||||
if (new Date(tokens.expire_at) > new Date(new Date().toISOString())) {
|
||||
return next(null, tokens)
|
||||
}
|
||||
|
||||
this.verifyToken(tokens.refresh_token)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(next)
|
||||
})
|
||||
},
|
||||
// otherwise make the whole flow
|
||||
(next) => {
|
||||
return this.authenticate((err, data) => {
|
||||
if (err instanceof Error) return next(err)
|
||||
// verify that the token is valid
|
||||
this.verifyToken(data.refresh_token)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(next)
|
||||
})
|
||||
}
|
||||
], (err, result) => {
|
||||
// if present run the optional callback
|
||||
if (typeof optionalCallback === 'function') {
|
||||
optionalCallback(err, result)
|
||||
}
|
||||
|
||||
if (result.refresh_token) {
|
||||
this.authenticated = true
|
||||
let file = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.writeFile(file, JSON.stringify(result), () => {
|
||||
return cb(err, result)
|
||||
})
|
||||
} else {
|
||||
return cb(err, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
authenticate (cb) {
|
||||
console.log(`${cst.PM2_IO_MSG} Using non-browser authentication.`)
|
||||
promptly.confirm(`${cst.PM2_IO_MSG} Do you have a pm2.io account? (y/n)`, (err, answer) => {
|
||||
// Either login or register
|
||||
return answer === true ? this.login(cb) : this.register(cb)
|
||||
})
|
||||
}
|
||||
|
||||
login (cb) {
|
||||
let retry = () => {
|
||||
promptly.prompt(`${cst.PM2_IO_MSG} Your username or email: `, (err, username) => {
|
||||
if (err) return retry();
|
||||
|
||||
promptly.password(`${cst.PM2_IO_MSG} Your password: `, { replace : '*' }, (err, password) => {
|
||||
if (err) return retry();
|
||||
|
||||
console.log(`${cst.PM2_IO_MSG} Authenticating ...`)
|
||||
this._loginUser({
|
||||
username: username,
|
||||
password: password
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
console.error(`${cst.PM2_IO_MSG_ERR} Failed to authenticate: ${err.message}`)
|
||||
return retry()
|
||||
}
|
||||
return cb(null, data)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
retry()
|
||||
}
|
||||
|
||||
register (cb) {
|
||||
console.log(`${cst.PM2_IO_MSG} No problem ! We just need few informations to create your account`)
|
||||
|
||||
var retry = () => {
|
||||
promptly.prompt(`${cst.PM2_IO_MSG} Please choose an username :`, {
|
||||
validator : this._validateUsername,
|
||||
retry : true
|
||||
}, (err, username) => {
|
||||
promptly.prompt(`${cst.PM2_IO_MSG} Please choose an email :`, {
|
||||
validator : this._validateEmail,
|
||||
retry : true
|
||||
},(err, email) => {
|
||||
promptly.password(`${cst.PM2_IO_MSG} Please choose a password :`, { replace : '*' }, (err, password) => {
|
||||
promptly.confirm(`${cst.PM2_IO_MSG} Do you accept the terms and privacy policy (https://pm2.io/legals/terms_conditions.pdf) ? (y/n)`, (err, answer) => {
|
||||
if (err) {
|
||||
console.error(chalk.bold.red(err));
|
||||
return retry()
|
||||
} else if (answer === false) {
|
||||
console.error(`${cst.PM2_IO_MSG_ERR} You must accept the terms and privacy policy to contiue.`)
|
||||
return retry()
|
||||
}
|
||||
|
||||
this._registerUser({
|
||||
email : email,
|
||||
password : password,
|
||||
username : username
|
||||
}, (err, data) => {
|
||||
console.log('\n')
|
||||
if (err) {
|
||||
console.error(`${cst.PM2_IO_MSG_ERR} Unexpect error: ${err.message}`)
|
||||
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
|
||||
return process.exit(1)
|
||||
}
|
||||
return cb(undefined, data)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
retry()
|
||||
}
|
||||
|
||||
/**
|
||||
* Register function
|
||||
* @param opts.username
|
||||
* @param opts.password
|
||||
* @param opts.email
|
||||
*/
|
||||
_registerUser (opts, cb) {
|
||||
const data = Object.assign(opts, {
|
||||
password_confirmation: opts.password,
|
||||
accept_terms: true
|
||||
})
|
||||
needle.post(this.BASE_URI + '/api/oauth/register', data, {
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Register-Provider': 'pm2-register',
|
||||
'x-client-id': this.client_id
|
||||
}
|
||||
}, function (err, res, body) {
|
||||
if (err) return cb(err)
|
||||
if (body.email && body.email.message) return cb(new Error(body.email.message))
|
||||
if (body.username && body.username.message) return cb(new Error(body.username.message))
|
||||
if (!body.access_token) return cb(new Error(body.msg))
|
||||
|
||||
return cb(null, {
|
||||
refresh_token : body.refresh_token.token,
|
||||
access_token : body.access_token.token
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
_loginUser (user_info, cb) {
|
||||
const URL_AUTH = '/api/oauth/authorize?response_type=token&scope=all&client_id=' +
|
||||
this.client_id + '&redirect_uri=http://localhost:43532';
|
||||
|
||||
needle.get(this.BASE_URI + URL_AUTH, (err, res) => {
|
||||
if (err) return cb(err);
|
||||
|
||||
var cookie = res.cookies;
|
||||
|
||||
needle.post(this.BASE_URI + '/api/oauth/login', user_info, {
|
||||
cookies : cookie
|
||||
}, (err, resp, body) => {
|
||||
if (err) return cb(err)
|
||||
if (resp.statusCode != 200) return cb('Wrong credentials')
|
||||
|
||||
var location = resp.headers['x-redirect']
|
||||
|
||||
needle.get(this.BASE_URI + location, {
|
||||
cookies : cookie
|
||||
}, (err, res) => {
|
||||
if (err) return cb(err);
|
||||
var refresh_token = querystring.parse(url.parse(res.headers.location).query).access_token;
|
||||
needle.post(this.BASE_URI + '/api/oauth/token', {
|
||||
client_id : this.client_id,
|
||||
grant_type : 'refresh_token',
|
||||
refresh_token : refresh_token,
|
||||
scope : 'all'
|
||||
}, (err, res, body) => {
|
||||
if (err) return cb(err)
|
||||
return cb(null, body)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
_validateEmail (email) {
|
||||
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
if (re.test(email) == false)
|
||||
throw new Error('Not an email');
|
||||
return email;
|
||||
}
|
||||
|
||||
_validateUsername (value) {
|
||||
if (value.length < 6) {
|
||||
throw new Error('Min length of 6');
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
deleteTokens (km) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// revoke the refreshToken
|
||||
km.auth.revoke()
|
||||
.then(res => {
|
||||
// remove the token from the filesystem
|
||||
let file = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.unlinkSync(file)
|
||||
return resolve(res)
|
||||
}).catch(reject)
|
||||
})
|
||||
}
|
||||
}
|
||||
187
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/WebAuth.js
generated
vendored
Normal file
187
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/WebAuth.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const cst = require('../../../../constants.js');
|
||||
|
||||
const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy')
|
||||
const http = require('http')
|
||||
const fs = require('fs')
|
||||
const url = require('url')
|
||||
const exec = require('child_process').exec
|
||||
const tryEach = require('async/tryEach');
|
||||
|
||||
module.exports = class WebStrategy extends AuthStrategy {
|
||||
// the client will try to call this but we handle this part ourselves
|
||||
retrieveTokens (km, cb) {
|
||||
this.authenticated = false
|
||||
this.callback = cb
|
||||
this.km = km
|
||||
}
|
||||
|
||||
// so the cli know if we need to tell user to login/register
|
||||
isAuthenticated () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.authenticated) return resolve(true)
|
||||
|
||||
let tokensPath = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.readFile(tokensPath, (err, tokens) => {
|
||||
if (err && err.code === 'ENOENT') return resolve(false)
|
||||
if (err) return reject(err)
|
||||
|
||||
// verify that the token is valid
|
||||
try {
|
||||
tokens = JSON.parse(tokens || '{}')
|
||||
} catch (err) {
|
||||
fs.unlinkSync(tokensPath)
|
||||
return resolve(false)
|
||||
}
|
||||
|
||||
// if the refresh tokens is here, the user could be automatically authenticated
|
||||
return resolve(typeof tokens.refresh_token === 'string')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// called when we are sure the user asked to be logged in
|
||||
_retrieveTokens (optionalCallback) {
|
||||
const km = this.km
|
||||
const cb = this.callback
|
||||
|
||||
let verifyToken = (refresh) => {
|
||||
return km.auth.retrieveToken({
|
||||
client_id: this.client_id,
|
||||
refresh_token: refresh
|
||||
})
|
||||
}
|
||||
tryEach([
|
||||
// try to find the token via the environment
|
||||
(next) => {
|
||||
if (!process.env.PM2_IO_TOKEN) {
|
||||
return next(new Error('No token in env'))
|
||||
}
|
||||
verifyToken(process.env.PM2_IO_TOKEN)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(next)
|
||||
},
|
||||
// try to find it in the file system
|
||||
(next) => {
|
||||
fs.readFile(cst.PM2_IO_ACCESS_TOKEN, (err, tokens) => {
|
||||
if (err) return next(err)
|
||||
// verify that the token is valid
|
||||
tokens = JSON.parse(tokens || '{}')
|
||||
if (new Date(tokens.expire_at) > new Date(new Date().toISOString())) {
|
||||
return next(null, tokens)
|
||||
}
|
||||
|
||||
verifyToken(tokens.refresh_token)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(next)
|
||||
})
|
||||
},
|
||||
// otherwise make the whole flow
|
||||
(next) => {
|
||||
return this.loginViaWeb((data) => {
|
||||
// verify that the token is valid
|
||||
verifyToken(data.access_token)
|
||||
.then((res) => {
|
||||
return next(null, res.data)
|
||||
}).catch(err => next(err))
|
||||
})
|
||||
}
|
||||
], (err, result) => {
|
||||
// if present run the optional callback
|
||||
if (typeof optionalCallback === 'function') {
|
||||
optionalCallback(err, result)
|
||||
}
|
||||
|
||||
if (result.refresh_token) {
|
||||
this.authenticated = true
|
||||
let file = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.writeFile(file, JSON.stringify(result), () => {
|
||||
return cb(err, result)
|
||||
})
|
||||
} else {
|
||||
return cb(err, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
loginViaWeb (cb) {
|
||||
const redirectURL = `${this.oauth_endpoint}${this.oauth_query}`
|
||||
|
||||
console.log(`${cst.PM2_IO_MSG} Please follow the popup or go to this URL :`, '\n', ' ', redirectURL)
|
||||
|
||||
let shutdown = false
|
||||
let server = http.createServer((req, res) => {
|
||||
// only handle one request
|
||||
if (shutdown === true) return res.end()
|
||||
shutdown = true
|
||||
|
||||
let query = url.parse(req.url, true).query
|
||||
|
||||
res.write(`
|
||||
<head>
|
||||
<script>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">
|
||||
You can go back to your terminal now :)
|
||||
</h2>
|
||||
</body>`)
|
||||
res.end()
|
||||
server.close()
|
||||
return cb(query)
|
||||
})
|
||||
server.listen(43532, () => {
|
||||
this.open(redirectURL)
|
||||
})
|
||||
}
|
||||
|
||||
deleteTokens (km) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// revoke the refreshToken
|
||||
km.auth.revoke()
|
||||
.then(res => {
|
||||
// remove the token from the filesystem
|
||||
let file = cst.PM2_IO_ACCESS_TOKEN
|
||||
fs.unlinkSync(file)
|
||||
return resolve(res)
|
||||
}).catch(reject)
|
||||
})
|
||||
}
|
||||
|
||||
open (target, appName, callback) {
|
||||
let opener
|
||||
const escape = function (s) {
|
||||
return s.replace(/"/g, '\\"')
|
||||
}
|
||||
|
||||
if (typeof (appName) === 'function') {
|
||||
callback = appName
|
||||
appName = null
|
||||
}
|
||||
|
||||
switch (process.platform) {
|
||||
case 'darwin': {
|
||||
opener = appName ? `open -a "${escape(appName)}"` : `open`
|
||||
break
|
||||
}
|
||||
case 'win32': {
|
||||
opener = appName ? `start "" ${escape(appName)}"` : `start ""`
|
||||
break
|
||||
}
|
||||
default: {
|
||||
opener = appName ? escape(appName) : `xdg-open`
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.SUDO_USER) {
|
||||
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener
|
||||
}
|
||||
return exec(`${opener} "${escape(target)}"`, callback)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user