Use passport authentication to standardize authentication in this application
This commit is contained in:
parent
2e5e6412b9
commit
c2cbd60f96
192
app.js
192
app.js
@ -1,19 +1,20 @@
|
|||||||
const connectSession = require('connect-redis')
|
const connectSession = require('connect-redis')
|
||||||
const session = require('express-session')
|
const session = require('express-session')
|
||||||
const bodyParser = require('body-parser')
|
const bodyParser = require('body-parser')
|
||||||
|
const nunjucks = require('nunjucks')
|
||||||
|
const passport = require('passport')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
const nunjucks = require('nunjucks')
|
|
||||||
const sqlite = require('sqlite')
|
const sqlite = require('sqlite')
|
||||||
const xml2js = require('xml2js')
|
const xml2js = require('xml2js')
|
||||||
const path = require('path')
|
|
||||||
const toml = require('toml')
|
|
||||||
const http = require('http')
|
|
||||||
const fs = require('fs')
|
|
||||||
const WebSocket = require('ws')
|
const WebSocket = require('ws')
|
||||||
const uuid = require('uuid/v4')
|
const uuid = require('uuid/v4')
|
||||||
const redis = require('redis')
|
const redis = require('redis')
|
||||||
|
const path = require('path')
|
||||||
|
const toml = require('toml')
|
||||||
|
const http = require('http')
|
||||||
const URL = require('url')
|
const URL = require('url')
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
require('express-async-errors')
|
require('express-async-errors')
|
||||||
|
|
||||||
@ -40,32 +41,26 @@ try {
|
|||||||
|
|
||||||
config = Object.assign({
|
config = Object.assign({
|
||||||
'Streaming': {
|
'Streaming': {
|
||||||
'Port': '9322',
|
'port': '9322',
|
||||||
'Database': 'streaming.db',
|
'database': 'streaming.db',
|
||||||
'StreamServer': 'https://tv.icynet.eu/live/',
|
'streamServer': 'https://tv.icynet.eu/live/',
|
||||||
'ServerHost': 'icynet.eu',
|
'serverHost': 'icynet.eu',
|
||||||
'PublishAddress': 'rtmp://{host}:1935/hls-live/{streamer}',
|
'publishAddress': 'rtmp://{host}:1935/hls-live/{streamer}',
|
||||||
'Secret': 'changeme'
|
'secret': 'changeme'
|
||||||
},
|
},
|
||||||
'Auth': {
|
'Auth': {
|
||||||
'Server': 'http://localhost:8282',
|
'strategy': 'passport-oauth2',
|
||||||
'Redirect': 'http://localhost:5000/auth/_callback/'
|
'callbackURL': 'http://localhost:5000/auth/_callback/',
|
||||||
},
|
'clientID': '1',
|
||||||
'OAuth2': {
|
'clientSecret': 'changeme'
|
||||||
'ClientID': '1',
|
|
||||||
'ClientSecret': 'changeme'
|
|
||||||
}
|
}
|
||||||
}, config)
|
}, config)
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const oauthAuth = '{server}/oauth2/authorize?response_type=code&state={state}&redirect_uri={redirect}&client_id={client}&scope=image'
|
const oauthAuth = '{server}/oauth2/authorize?response_type=code&state={state}&redirect_uri={redirect}&client_id={client}&scope=image'
|
||||||
const port = parseInt(config['Streaming']['Port'])
|
const port = parseInt(config['Streaming']['port'])
|
||||||
const streamServer = config['Streaming']['StreamServer']
|
const streamServer = config['Streaming']['streamServer']
|
||||||
const streamServerHost = config['Streaming']['ServerHost']
|
const streamServerHost = config['Streaming']['serverHost']
|
||||||
const authServer = config['Auth']['Server']
|
|
||||||
const oauthRedirect = config['Auth']['Redirect']
|
|
||||||
const oauthId = config['OAuth2']['ClientID'].toString()
|
|
||||||
const oauthSecret = config['OAuth2']['ClientSecret']
|
|
||||||
const streamAppName = streamServer.match(/\/([\w-_]+)\/$/)[1]
|
const streamAppName = streamServer.match(/\/([\w-_]+)\/$/)[1]
|
||||||
|
|
||||||
function teval (str, obj) {
|
function teval (str, obj) {
|
||||||
@ -79,7 +74,7 @@ function teval (str, obj) {
|
|||||||
|
|
||||||
// Database
|
// Database
|
||||||
const dbPromise = Promise.resolve()
|
const dbPromise = Promise.resolve()
|
||||||
.then(() => sqlite.open(path.join(process.cwd(), config['Streaming']['Database']), { Promise, cache: true }))
|
.then(() => sqlite.open(path.join(process.cwd(), config['Streaming']['database']), { Promise, cache: true }))
|
||||||
.then(db => db.migrate())
|
.then(db => db.migrate())
|
||||||
|
|
||||||
// Setup server
|
// Setup server
|
||||||
@ -87,6 +82,24 @@ const app = express()
|
|||||||
const server = http.createServer(app)
|
const server = http.createServer(app)
|
||||||
const wss = new WebSocket.Server({ clientTracking: false, noServer: true })
|
const wss = new WebSocket.Server({ clientTracking: false, noServer: true })
|
||||||
|
|
||||||
|
// Authentication
|
||||||
|
const Strategy = require(config['Auth']['strategy'])
|
||||||
|
const strategyConfig = Object.assign({}, config['Auth'])
|
||||||
|
if (!strategyConfig.provider) strategyConfig.provider = strategyConfig.strategy.replace('passport-', '')
|
||||||
|
passport.use(new Strategy(strategyConfig, function (accessToken, refreshToken, profile, done) {
|
||||||
|
process.nextTick(function() {
|
||||||
|
return done(null, profile)
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
passport.serializeUser(function (user, done) {
|
||||||
|
done(null, user)
|
||||||
|
})
|
||||||
|
|
||||||
|
passport.deserializeUser(function (user, done) {
|
||||||
|
done(null, user)
|
||||||
|
})
|
||||||
|
|
||||||
app.enable('trust proxy', 1)
|
app.enable('trust proxy', 1)
|
||||||
|
|
||||||
app.use(bodyParser.urlencoded({ extended: false }))
|
app.use(bodyParser.urlencoded({ extended: false }))
|
||||||
@ -101,7 +114,7 @@ nunjucks.configure('templates', {
|
|||||||
|
|
||||||
const sessionParser = session({
|
const sessionParser = session({
|
||||||
key: 'Streamserver Session',
|
key: 'Streamserver Session',
|
||||||
secret: config['Streaming']['Secret'],
|
secret: config['Streaming']['secret'],
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: true,
|
saveUninitialized: true,
|
||||||
store: new SessionStore({ client: redis.createClient() }),
|
store: new SessionStore({ client: redis.createClient() }),
|
||||||
@ -113,6 +126,9 @@ const sessionParser = session({
|
|||||||
|
|
||||||
app.use(sessionParser)
|
app.use(sessionParser)
|
||||||
|
|
||||||
|
app.use(passport.initialize())
|
||||||
|
app.use(passport.session())
|
||||||
|
|
||||||
// Parse stream metrics from the stat.xml file
|
// Parse stream metrics from the stat.xml file
|
||||||
async function pullMetrics (uuid) {
|
async function pullMetrics (uuid) {
|
||||||
let statPath = streamServer + 'stat'
|
let statPath = streamServer + 'stat'
|
||||||
@ -188,7 +204,7 @@ app.post('/publish', async (req, res) => {
|
|||||||
console.log('=> Streamer %s has started streaming!', streamer.name)
|
console.log('=> Streamer %s has started streaming!', streamer.name)
|
||||||
|
|
||||||
// Generate real publish address for the server
|
// Generate real publish address for the server
|
||||||
let publishAddress = config['Streaming']['PublishAddress']
|
let publishAddress = config['Streaming']['publishAddress']
|
||||||
.replace('{streamer}', streamer.name)
|
.replace('{streamer}', streamer.name)
|
||||||
.replace('{host}', '127.0.0.1')
|
.replace('{host}', '127.0.0.1')
|
||||||
|
|
||||||
@ -219,97 +235,50 @@ app.post('/publish_done', async (req, res) => {
|
|||||||
|
|
||||||
// Front-end server
|
// Front-end server
|
||||||
// OAuth2 authenticator
|
// OAuth2 authenticator
|
||||||
app.get('/login', async (req, res) => {
|
app.get('/login', passport.authenticate(strategyConfig.provider, Object.assign({}, strategyConfig.authOptions || {})))
|
||||||
if (req.session.user) return res.redirect('/')
|
|
||||||
req.session.state = uuid()
|
|
||||||
res.redirect(teval(oauthAuth, { state: req.session.state, redirect: oauthRedirect, client: oauthId, server: authServer }))
|
|
||||||
})
|
|
||||||
|
|
||||||
app.get('/auth/_callback', async (req, res) => {
|
|
||||||
let state = req.session.state
|
|
||||||
if (!state) throw new Error('Something went wrong!')
|
|
||||||
|
|
||||||
let code = req.query.code
|
|
||||||
let provState = req.query.state
|
|
||||||
if (!code || state !== provState) throw new Error('Something went wrong!')
|
|
||||||
delete req.session.state
|
|
||||||
|
|
||||||
// Aquire token
|
|
||||||
let { body } = await post(authServer + '/oauth2/token', {
|
|
||||||
form: {
|
|
||||||
grant_type: 'authorization_code',
|
|
||||||
code: code,
|
|
||||||
redirect_uri: oauthRedirect,
|
|
||||||
client_id: oauthId,
|
|
||||||
client_secret: oauthSecret
|
|
||||||
},
|
|
||||||
auth: {
|
|
||||||
user: oauthId,
|
|
||||||
pass: oauthSecret
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!body) throw new Error('Could not obtain access token!')
|
|
||||||
try {
|
|
||||||
body = JSON.parse(body)
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e, body)
|
|
||||||
throw new Error('Authorization server gave us an invalid response!')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body['error']) {
|
|
||||||
throw new Error(body['error'] + ': ' + body['error_description'])
|
|
||||||
}
|
|
||||||
|
|
||||||
let token = body.access_token
|
|
||||||
|
|
||||||
// Get user information
|
|
||||||
let { body: bodyNew } = await get(authServer + '/oauth2/user', { auth: { bearer: token } })
|
|
||||||
try {
|
|
||||||
bodyNew = JSON.parse(bodyNew)
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e, bodyNew)
|
|
||||||
throw new Error('Authorization server gave us an invalid response for user!')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
app.get('/auth/_callback', passport.authenticate(strategyConfig.provider, { failureRedirect: '/' }), async (req, res) => {
|
||||||
|
dev && console.log(req.user.username, 'logged in')
|
||||||
// Get user from database
|
// Get user from database
|
||||||
let db = await dbPromise
|
let db = await dbPromise
|
||||||
let user = await db.get('SELECT * FROM signed_users WHERE uuid=?', bodyNew.uuid)
|
let user = await db.get('SELECT * FROM signed_users WHERE uuid=?', req.user.uuid)
|
||||||
if (!user) {
|
if (!user) {
|
||||||
await db.run('INSERT INTO signed_users (uuid,name) VALUES (?,?)', bodyNew.uuid, bodyNew.username)
|
await db.run('INSERT INTO signed_users (uuid,name) VALUES (?,?)', req.user.uuid, req.user.username)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.session.login = bodyNew.uuid
|
|
||||||
req.session.username = bodyNew.username
|
|
||||||
|
|
||||||
// Lets see if this user is a streamer
|
// Lets see if this user is a streamer
|
||||||
let streamer = await db.get('SELECT * FROM channels WHERE user_uuid = ?', bodyNew.uuid)
|
let streamer = await db.get('SELECT * FROM channels WHERE user_uuid = ?', req.user.uuid)
|
||||||
if (streamer) cache.streamers[bodyNew.uuid] = streamer
|
if (streamer) cache.streamers[req.user.uuid] = streamer
|
||||||
|
|
||||||
res.redirect('/')
|
res.redirect('/')
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/logout', (req, res) => {
|
app.get('/logout', (req, res) => {
|
||||||
req.session.destroy()
|
req.logout()
|
||||||
res.redirect('/')
|
res.redirect('/')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function authed (req, res, next) {
|
||||||
|
if (req.isAuthenticated() && req.isStreamer) return next()
|
||||||
|
res.jsonp({ error: 'Unauthorized' })
|
||||||
|
}
|
||||||
|
|
||||||
// Views
|
// Views
|
||||||
|
|
||||||
app.use('/dist', express.static(path.join(__dirname, 'dist'), { maxAge: dev ? 0 : 2678400000 }))
|
app.use('/dist', express.static(path.join(__dirname, 'dist'), { maxAge: dev ? 0 : 2678400000 }))
|
||||||
app.use(async function (req, res, next) {
|
app.use(async function (req, res, next) {
|
||||||
req.isStreamer = false
|
req.isStreamer = false
|
||||||
if (!req.session.login) return next()
|
if (!req.isAuthenticated()) return next()
|
||||||
|
|
||||||
res.locals.session = { uuid: req.session.login, username: req.session.username }
|
res.locals.user = req.user
|
||||||
|
|
||||||
if (!cache.streamers[req.session.login]) {
|
if (!cache.streamers[req.user.uuid]) {
|
||||||
let db = await dbPromise
|
let db = await dbPromise
|
||||||
let streamer = await db.get('SELECT * FROM channels WHERE user_uuid = ?', req.session.login)
|
let streamer = await db.get('SELECT * FROM channels WHERE user_uuid = ?', req.user.uuid)
|
||||||
if (streamer) cache.streamers[req.session.login] = streamer
|
if (streamer) cache.streamers[req.user.uuid] = streamer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache.streamers[req.session.login]) {
|
if (cache.streamers[req.user.uuid]) {
|
||||||
req.isStreamer = true
|
req.isStreamer = true
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
@ -323,16 +292,14 @@ app.get('/', (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
app.get('/dashboard', (req, res, next) => {
|
app.get('/dashboard', authed, (req, res) => {
|
||||||
if (!req.isStreamer) return next(new Error('Unauthorized'))
|
let stream = cache.streamers[req.user.uuid]
|
||||||
let stream = cache.streamers[req.session.login]
|
|
||||||
res.render('dashboard.html', { stream: stream.key, server: 'rtmp://' + streamServerHost + '/live/' })
|
res.render('dashboard.html', { stream: stream.key, server: 'rtmp://' + streamServerHost + '/live/' })
|
||||||
})
|
})
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
app.get('/dashboard/stats', async (req, res) => {
|
app.get('/dashboard/stats', authed, async (req, res) => {
|
||||||
if (!req.isStreamer) return res.jsonp({ error: 'Unauthorized' })
|
let stream = cache.streamers[req.user.uuid]
|
||||||
let stream = cache.streamers[req.session.login]
|
|
||||||
let data
|
let data
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -346,9 +313,8 @@ app.get('/dashboard/stats', async (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
app.get('/dashboard/data', async (req, res) => {
|
app.get('/dashboard/data', authed, async (req, res) => {
|
||||||
if (!req.isStreamer) return res.jsonp({ error: 'Unauthorized' })
|
let stream = cache.streamers[req.user.uuid]
|
||||||
let stream = cache.streamers[req.session.login]
|
|
||||||
let data
|
let data
|
||||||
|
|
||||||
let db = await dbPromise
|
let db = await dbPromise
|
||||||
@ -364,7 +330,7 @@ app.get('/dashboard/data', async (req, res) => {
|
|||||||
res.jsonp({
|
res.jsonp({
|
||||||
'name': data.name,
|
'name': data.name,
|
||||||
'key': stream.key,
|
'key': stream.key,
|
||||||
'uuid': req.session.login,
|
'uuid': req.user.uuid,
|
||||||
'live': data.live_at != null,
|
'live': data.live_at != null,
|
||||||
'live_at': new Date(parseInt(data.live_at)),
|
'live_at': new Date(parseInt(data.live_at)),
|
||||||
'last_stream': new Date(parseInt(data.last_stream))
|
'last_stream': new Date(parseInt(data.last_stream))
|
||||||
@ -372,9 +338,8 @@ app.get('/dashboard/data', async (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Get links
|
// Get links
|
||||||
app.get('/dashboard/link', async (req, res) => {
|
app.get('/dashboard/link', authed, async (req, res) => {
|
||||||
if (!req.isStreamer) return res.jsonp({ error: 'Unauthorized' })
|
let user = req.user.uuid
|
||||||
let user = req.session.login
|
|
||||||
|
|
||||||
let db = await dbPromise
|
let db = await dbPromise
|
||||||
let links = await db.all('SELECT * FROM link WHERE uuid = ?', user)
|
let links = await db.all('SELECT * FROM link WHERE uuid = ?', user)
|
||||||
@ -383,9 +348,8 @@ app.get('/dashboard/link', async (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Add link URL
|
// Add link URL
|
||||||
app.post('/dashboard/link', async (req, res) => {
|
app.post('/dashboard/link', authed, async (req, res) => {
|
||||||
if (!req.isStreamer) return res.jsonp({ error: 'Unauthorized' })
|
let user = req.user.uuid
|
||||||
let user = req.session.login
|
|
||||||
let name = req.body.name
|
let name = req.body.name
|
||||||
let url = req.body.url
|
let url = req.body.url
|
||||||
|
|
||||||
@ -413,9 +377,8 @@ app.post('/dashboard/link', async (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Remove link URL
|
// Remove link URL
|
||||||
app.post('/dashboard/link/delete', async (req, res) => {
|
app.post('/dashboard/link/delete', authed, async (req, res) => {
|
||||||
if (!req.isStreamer) return res.jsonp({ error: 'Unauthorized' })
|
let user = req.user.uuid
|
||||||
let user = req.session.login
|
|
||||||
|
|
||||||
if (req.body.name == null && req.body.url == null) return res.jsonp({ error: 'Missing parameters!' })
|
if (req.body.name == null && req.body.url == null) return res.jsonp({ error: 'Missing parameters!' })
|
||||||
|
|
||||||
@ -469,8 +432,8 @@ app.use((error, req, res, next) => {
|
|||||||
|
|
||||||
// Socket Server
|
// Socket Server
|
||||||
wss.on('connection', (ws, request, client) => {
|
wss.on('connection', (ws, request, client) => {
|
||||||
const userId = request.session.login || request.session.id
|
const userId = request.user.uuid || request.session.id
|
||||||
const username = request.session.username
|
const username = request.user.username
|
||||||
let myChannels = []
|
let myChannels = []
|
||||||
|
|
||||||
dev && console.log(userId, 'connected')
|
dev && console.log(userId, 'connected')
|
||||||
@ -538,4 +501,5 @@ server.listen(port, host, () => {
|
|||||||
})().catch(e => console.error(e.stack))
|
})().catch(e => console.error(e.stack))
|
||||||
|
|
||||||
console.log('Listening on %s:%d', host, port)
|
console.log('Listening on %s:%d', host, port)
|
||||||
|
console.log('Authentication module: %s (%s)', strategyConfig.strategy, strategyConfig.provider)
|
||||||
})
|
})
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
[Streaming]
|
[Streaming]
|
||||||
Port = 5000
|
port = 5000
|
||||||
Database = "streaming.db"
|
database = "streaming.db"
|
||||||
StreamServer = "http://localhost:5000/live/"
|
streamServer = "http://localhost:5000/live/"
|
||||||
ServerHost = "localhost:1935"
|
serverHost = "localhost:1935"
|
||||||
PublishAddress = "rtmp://{host}:1935/hls-live/{streamer}"
|
publishAddress = "rtmp://{host}:1935/hls-live/{streamer}"
|
||||||
Secret = "changeme"
|
secret = "changeme"
|
||||||
|
|
||||||
[Auth]
|
[Auth]
|
||||||
Server = "http://localhost:8282"
|
provider = "oauth2"
|
||||||
Redirect = "http://localhost:5000/auth/_callback/"
|
strategy = "passport-oauth2"
|
||||||
|
callbackURL = "http://localhost:5000/auth/_callback/"
|
||||||
[OAuth2]
|
authorizationURL = "http://localhost/oauth2/authorize"
|
||||||
ClientID = 1
|
tokenURL = "http://localhost/oauth2/token"
|
||||||
ClientSecret = "hackme"
|
clientID = 1
|
||||||
|
clientSecret = "hackme"
|
||||||
|
21
package-lock.json
generated
21
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "icytv",
|
"name": "icytv",
|
||||||
"version": "2.0.0",
|
"version": "2.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -4570,6 +4570,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
|
||||||
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
|
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
|
||||||
},
|
},
|
||||||
|
"passport": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=",
|
||||||
|
"requires": {
|
||||||
|
"passport-strategy": "1.x.x",
|
||||||
|
"pause": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"passport-strategy": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
|
||||||
|
},
|
||||||
"path-browserify": {
|
"path-browserify": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
|
||||||
@ -4624,6 +4638,11 @@
|
|||||||
"pify": "^3.0.0"
|
"pify": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pause": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
|
||||||
|
},
|
||||||
"pbkdf2": {
|
"pbkdf2": {
|
||||||
"version": "3.0.16",
|
"version": "3.0.16",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"express-session": "^1.16.1",
|
"express-session": "^1.16.1",
|
||||||
"nunjucks": "^3.2.0",
|
"nunjucks": "^3.2.0",
|
||||||
|
"passport": "^0.4.0",
|
||||||
"redis": "^2.8.0",
|
"redis": "^2.8.0",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"sqlite": "^3.0.3",
|
"sqlite": "^3.0.3",
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
<h3 class="masthead-brand">IcyTV</h3>
|
<h3 class="masthead-brand">IcyTV</h3>
|
||||||
<nav class="nav nav-masthead justify-content-center">
|
<nav class="nav nav-masthead justify-content-center">
|
||||||
<a class="nav-link active" href="/">Home</a>
|
<a class="nav-link active" href="/">Home</a>
|
||||||
{% if session.uuid %}
|
{% if user.uuid %}
|
||||||
<a class="nav-link" href="/dashboard">{{ session.username }}</a>
|
<a class="nav-link" href="/dashboard">{{ user.username }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="nav-link" href="/login">Login</a>
|
<a class="nav-link" href="/login">Login</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<h1 class="cover-heading">IcyTV</h1>
|
<h1 class="cover-heading">IcyTV</h1>
|
||||||
<p class="lead">This is a private livestreaming server for Icy Network members.</p>
|
<p class="lead">This is a private livestreaming server for Icy Network members.</p>
|
||||||
{% if streamer %}
|
{% if streamer %}
|
||||||
<p class="lead">Welcome back, {{ session.username }}!</p>
|
<p class="lead">Welcome back, {{ user.username }}!</p>
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
<a href="/dashboard" class="btn btn-lg btn-secondary">My Dashboard</a>
|
<a href="/dashboard" class="btn btn-lg btn-secondary">My Dashboard</a>
|
||||||
</p>
|
</p>
|
||||||
|
Reference in New Issue
Block a user