mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-04-14 17:31:28 +03:00
jwt auth scaffolding
logging in now works UI login component created
This commit is contained in:
@@ -1629,9 +1629,14 @@ app.post('/api/fileStatusMp4', function(req, res) {
|
|||||||
|
|
||||||
// gets all download mp3s
|
// gets all download mp3s
|
||||||
app.get('/api/getMp3s', function(req, res) {
|
app.get('/api/getMp3s', function(req, res) {
|
||||||
|
const multiUserMode = config_api.getConfigItem('ytdl_multi_user_mode');
|
||||||
var mp3s = db.get('files.audio').value(); // getMp3s();
|
var mp3s = db.get('files.audio').value(); // getMp3s();
|
||||||
var playlists = db.get('playlists.audio').value();
|
var playlists = db.get('playlists.audio').value();
|
||||||
|
|
||||||
|
if (req.query.jwt && multiUserMode) {
|
||||||
|
// mp3s = db.get
|
||||||
|
}
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
mp3s: mp3s,
|
mp3s: mp3s,
|
||||||
playlists: playlists
|
playlists: playlists
|
||||||
@@ -2313,8 +2318,7 @@ app.get('/api/audio/:id', function(req , res){
|
|||||||
app.post('/api/auth/register'
|
app.post('/api/auth/register'
|
||||||
, auth.registerUser);
|
, auth.registerUser);
|
||||||
app.post('/api/auth/login'
|
app.post('/api/auth/login'
|
||||||
// , auth.passport.authenticate('basic',{session:false}) // causes challenge pop-up on 401
|
, auth.passport.authenticate('local', {})
|
||||||
, auth.authenticateViaPassport
|
|
||||||
, auth.generateJWT
|
, auth.generateJWT
|
||||||
, auth.returnAuthResponse
|
, auth.returnAuthResponse
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ db.defaults(
|
|||||||
}
|
}
|
||||||
).write();
|
).write();
|
||||||
|
|
||||||
|
var LocalStrategy = require('passport-local').Strategy;
|
||||||
|
var JwtStrategy = require('passport-jwt').Strategy,
|
||||||
|
ExtractJwt = require('passport-jwt').ExtractJwt;
|
||||||
|
var opts = {}
|
||||||
|
opts.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('jwt');
|
||||||
|
opts.secretOrKey = 'secret';
|
||||||
|
opts.issuer = 'example.com';
|
||||||
|
opts.audience = 'example.com';
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
* Authentication module
|
* Authentication module
|
||||||
************************/
|
************************/
|
||||||
@@ -23,11 +32,18 @@ const SERVER_SECRET = uuid();
|
|||||||
exports.passport = require('passport');
|
exports.passport = require('passport');
|
||||||
var BasicStrategy = require('passport-http').BasicStrategy;
|
var BasicStrategy = require('passport-http').BasicStrategy;
|
||||||
|
|
||||||
|
exports.passport.serializeUser(function(user, done) {
|
||||||
|
done(null, user);
|
||||||
|
});
|
||||||
|
|
||||||
|
exports.passport.deserializeUser(function(user, done) {
|
||||||
|
done(null, user);
|
||||||
|
});
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Register user with hashed password
|
* Register user with hashed password
|
||||||
**************************************/
|
**************************************/
|
||||||
exports.registerUser = function(req, res) {
|
exports.registerUser = function(req, res) {
|
||||||
console.log('got here');
|
|
||||||
var userid = req.body.userid;
|
var userid = req.body.userid;
|
||||||
var username = req.body.username;
|
var username = req.body.username;
|
||||||
var plaintextPassword = req.body.password;
|
var plaintextPassword = req.body.password;
|
||||||
@@ -76,10 +92,31 @@ exports.registerUser = function(req, res) {
|
|||||||
* This checks that the credentials are valid.
|
* This checks that the credentials are valid.
|
||||||
* If so, passes the user info to the next middleware.
|
* If so, passes the user info to the next middleware.
|
||||||
************************************************/
|
************************************************/
|
||||||
exports.passport.use(new BasicStrategy(
|
exports.passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
|
||||||
|
const user = db.get('users').find({uid: jwt_payload.sub}).value();
|
||||||
|
if (user) {
|
||||||
|
return done(null, user);
|
||||||
|
} else {
|
||||||
|
return done(null, false);
|
||||||
|
// or you could create a new account
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
exports.passport.use(new LocalStrategy({
|
||||||
|
usernameField: 'userid',
|
||||||
|
passwordField: 'password'},
|
||||||
|
function(username, password, done) {
|
||||||
|
const user = db.get('users').find({name: username}).value();
|
||||||
|
if (!user) { return done(null, false); }
|
||||||
|
if (user) {
|
||||||
|
return done(null, bcrypt.compareSync(password, user.passhash) ? user : false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
/*passport.use(new BasicStrategy(
|
||||||
function(userid, plainTextPassword, done) {
|
function(userid, plainTextPassword, done) {
|
||||||
// console.log('BasicStrategy: verifying credentials');
|
const user = db.get('users').find({name: userid}).value();
|
||||||
const user = db.get('users').find({uid: userid}).value();
|
|
||||||
if (user) {
|
if (user) {
|
||||||
var hashedPwd = user.passhash;
|
var hashedPwd = user.passhash;
|
||||||
return bcrypt.compare(plainTextPassword, hashedPwd);
|
return bcrypt.compare(plainTextPassword, hashedPwd);
|
||||||
@@ -88,6 +125,7 @@ exports.passport.use(new BasicStrategy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
*/
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* This is a wrapper for auth.passport.authenticate().
|
* This is a wrapper for auth.passport.authenticate().
|
||||||
@@ -96,6 +134,7 @@ exports.passport.use(new BasicStrategy(
|
|||||||
* Browser's will pop-up up dialog when status is 401 and
|
* Browser's will pop-up up dialog when status is 401 and
|
||||||
* "WWW-Authenticate:Basic..."
|
* "WWW-Authenticate:Basic..."
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
/*
|
||||||
exports.authenticateViaPassport = function(req, res, next) {
|
exports.authenticateViaPassport = function(req, res, next) {
|
||||||
exports.passport.authenticate('basic',{session:false},
|
exports.passport.authenticate('basic',{session:false},
|
||||||
function(err, user, info) {
|
function(err, user, info) {
|
||||||
@@ -109,6 +148,7 @@ exports.authenticateViaPassport = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
)(req, res, next);
|
)(req, res, next);
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* Generating/Signing a JWT token
|
* Generating/Signing a JWT token
|
||||||
@@ -158,6 +198,12 @@ exports.ensureAuthenticatedElseError = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// video stuff
|
||||||
|
|
||||||
|
exports.getUserVideos(type) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function getToken(queryParams) {
|
function getToken(queryParams) {
|
||||||
if (queryParams && queryParams.jwt) {
|
if (queryParams && queryParams.jwt) {
|
||||||
var parted = queryParams.jwt.split(' ');
|
var parted = queryParams.jwt.split(' ');
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import { MainComponent } from './main/main.component';
|
|||||||
import { PlayerComponent } from './player/player.component';
|
import { PlayerComponent } from './player/player.component';
|
||||||
import { SubscriptionsComponent } from './subscriptions/subscriptions.component';
|
import { SubscriptionsComponent } from './subscriptions/subscriptions.component';
|
||||||
import { SubscriptionComponent } from './subscription/subscription/subscription.component';
|
import { SubscriptionComponent } from './subscription/subscription/subscription.component';
|
||||||
|
import { PostsService } from './posts.services';
|
||||||
|
import { LoginComponent } from './components/login/login.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'home', component: MainComponent },
|
{ path: 'home', component: MainComponent, canActivate: [PostsService] },
|
||||||
{ path: 'player', component: PlayerComponent},
|
{ path: 'player', component: PlayerComponent, canActivate: [PostsService]},
|
||||||
{ path: 'subscriptions', component: SubscriptionsComponent },
|
{ path: 'subscriptions', component: SubscriptionsComponent, canActivate: [PostsService] },
|
||||||
{ path: 'subscription', component: SubscriptionComponent },
|
{ path: 'subscription', component: SubscriptionComponent, canActivate: [PostsService] },
|
||||||
|
{ path: 'login', component: LoginComponent },
|
||||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import { ArgModifierDialogComponent, HighlightPipe } from './dialogs/arg-modifie
|
|||||||
import { UpdaterComponent } from './updater/updater.component';
|
import { UpdaterComponent } from './updater/updater.component';
|
||||||
import { UpdateProgressDialogComponent } from './dialogs/update-progress-dialog/update-progress-dialog.component';
|
import { UpdateProgressDialogComponent } from './dialogs/update-progress-dialog/update-progress-dialog.component';
|
||||||
import { ShareMediaDialogComponent } from './dialogs/share-media-dialog/share-media-dialog.component';
|
import { ShareMediaDialogComponent } from './dialogs/share-media-dialog/share-media-dialog.component';
|
||||||
|
import { LoginComponent } from './components/login/login.component';
|
||||||
registerLocaleData(es, 'es');
|
registerLocaleData(es, 'es');
|
||||||
|
|
||||||
export function isVisible({ event, element, scrollContainer, offset }: IsVisibleProps<any>) {
|
export function isVisible({ event, element, scrollContainer, offset }: IsVisibleProps<any>) {
|
||||||
@@ -85,7 +86,8 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
|
|||||||
HighlightPipe,
|
HighlightPipe,
|
||||||
UpdaterComponent,
|
UpdaterComponent,
|
||||||
UpdateProgressDialogComponent,
|
UpdateProgressDialogComponent,
|
||||||
ShareMediaDialogComponent
|
ShareMediaDialogComponent,
|
||||||
|
LoginComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
22
src/app/components/login/login.component.html
Normal file
22
src/app/components/login/login.component.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<mat-card class="login-card">
|
||||||
|
<mat-tab-group>
|
||||||
|
<mat-tab label="Login">
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<mat-form-field>
|
||||||
|
<input [(ngModel)]="usernameInput" matInput placeholder="User name">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field>
|
||||||
|
<input [(ngModel)]="passwordInput" type="password" matInput placeholder="Password">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div style="margin-bottom: 10px; margin-top: 10px;">
|
||||||
|
<button [disabled]="loggingIn" color="primary" (click)="login()" mat-raised-button>Login</button>
|
||||||
|
</div>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab *ngIf="registrationEnabled" label="Register">
|
||||||
|
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
</mat-card>
|
||||||
6
src/app/components/login/login.component.scss
Normal file
6
src/app/components/login/login.component.scss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.login-card {
|
||||||
|
max-width: 600px;
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
25
src/app/components/login/login.component.spec.ts
Normal file
25
src/app/components/login/login.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginComponent } from './login.component';
|
||||||
|
|
||||||
|
describe('LoginComponent', () => {
|
||||||
|
let component: LoginComponent;
|
||||||
|
let fixture: ComponentFixture<LoginComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ LoginComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LoginComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
31
src/app/components/login/login.component.ts
Normal file
31
src/app/components/login/login.component.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { PostsService } from 'app/posts.services';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-login',
|
||||||
|
templateUrl: './login.component.html',
|
||||||
|
styleUrls: ['./login.component.scss']
|
||||||
|
})
|
||||||
|
export class LoginComponent implements OnInit {
|
||||||
|
|
||||||
|
usernameInput = '';
|
||||||
|
passwordInput = '';
|
||||||
|
registrationEnabled = true;
|
||||||
|
loggingIn = false;
|
||||||
|
|
||||||
|
constructor(private postsService: PostsService) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
login() {
|
||||||
|
this.loggingIn = true;
|
||||||
|
this.postsService.login(this.usernameInput, this.passwordInput).subscribe(res => {
|
||||||
|
this.loggingIn = false;
|
||||||
|
console.log(res);
|
||||||
|
}, err => {
|
||||||
|
this.loggingIn = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,12 +5,12 @@ import 'rxjs/add/operator/map';
|
|||||||
import 'rxjs/add/operator/catch';
|
import 'rxjs/add/operator/catch';
|
||||||
import 'rxjs/add/observable/throw';
|
import 'rxjs/add/observable/throw';
|
||||||
import { THEMES_CONFIG } from '../themes';
|
import { THEMES_CONFIG } from '../themes';
|
||||||
import { Router } from '@angular/router';
|
import { Router, CanActivate } from '@angular/router';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PostsService {
|
export class PostsService implements CanActivate {
|
||||||
path = '';
|
path = '';
|
||||||
audioFolder = '';
|
audioFolder = '';
|
||||||
videoFolder = '';
|
videoFolder = '';
|
||||||
@@ -24,6 +24,10 @@ export class PostsService {
|
|||||||
httpOptions = null;
|
httpOptions = null;
|
||||||
|
|
||||||
debugMode = false;
|
debugMode = false;
|
||||||
|
|
||||||
|
isLoggedIn = false;
|
||||||
|
token = null;
|
||||||
|
user = null;
|
||||||
constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document) {
|
constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document) {
|
||||||
console.log('PostsService Initialized...');
|
console.log('PostsService Initialized...');
|
||||||
// this.startPath = window.location.href + '/api/';
|
// this.startPath = window.location.href + '/api/';
|
||||||
@@ -41,6 +45,11 @@ export class PostsService {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
canActivate(route, state): boolean {
|
||||||
|
console.log(route);
|
||||||
|
return true;
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
setTheme(theme) {
|
setTheme(theme) {
|
||||||
this.theme = this.THEMES_CONFIG[theme];
|
this.theme = this.THEMES_CONFIG[theme];
|
||||||
@@ -233,4 +242,27 @@ export class PostsService {
|
|||||||
return this.http.get('https://api.github.com/repos/tzahi12345/youtubedl-material/releases');
|
return this.http.get('https://api.github.com/repos/tzahi12345/youtubedl-material/releases');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterLogin(user, token) {
|
||||||
|
this.isLoggedIn = true;
|
||||||
|
this.user = user;
|
||||||
|
this.token = token;
|
||||||
|
|
||||||
|
this.httpOptions = {
|
||||||
|
params: new HttpParams({
|
||||||
|
fromString: `apiKey=${this.auth_token}&jwt=${this.token}`
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// user methods
|
||||||
|
login(username, password) {
|
||||||
|
const call = this.http.post(this.path + 'auth/login', {userid: username, password: password}, this.httpOptions);
|
||||||
|
call.subscribe(res => {
|
||||||
|
if (res['token']) {
|
||||||
|
this.afterLogin(res['user'], res['token']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return call;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user