mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Adding some css, fix message on log in failure
This commit is contained in:
@@ -22,10 +22,6 @@ export type AuthFailure = {
|
|||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MusicService {
|
|
||||||
generateToken(credentials: Credentials): Promise<AuthSuccess | AuthFailure>;
|
|
||||||
login(authToken: string): Promise<MusicLibrary>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Artist = {
|
export type Artist = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -64,6 +60,10 @@ export type ArtistQuery = Paging
|
|||||||
export type AlbumQuery = Paging & {
|
export type AlbumQuery = Paging & {
|
||||||
artistId?: string
|
artistId?: string
|
||||||
}
|
}
|
||||||
|
export interface MusicService {
|
||||||
|
generateToken(credentials: Credentials): Promise<AuthSuccess | AuthFailure>;
|
||||||
|
login(authToken: string): Promise<MusicLibrary>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MusicLibrary {
|
export interface MusicLibrary {
|
||||||
artists(q: ArtistQuery): Promise<Result<Artist>>;
|
artists(q: ArtistQuery): Promise<Result<Artist>>;
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import { Md5 } from "ts-md5/dist/md5";
|
import { Md5 } from "ts-md5/dist/md5";
|
||||||
import { Credentials, MusicService, Album, Artist, Result, slice2, asResult, AlbumQuery, ArtistQuery } from "./music_service";
|
import {
|
||||||
|
Credentials,
|
||||||
|
MusicService,
|
||||||
|
Album,
|
||||||
|
Artist,
|
||||||
|
Result,
|
||||||
|
slice2,
|
||||||
|
asResult,
|
||||||
|
AlbumQuery,
|
||||||
|
ArtistQuery,
|
||||||
|
} from "./music_service";
|
||||||
import X2JS from "x2js";
|
import X2JS from "x2js";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -85,7 +95,7 @@ export class Navidrome implements MusicService {
|
|||||||
).toString("base64"),
|
).toString("base64"),
|
||||||
userId: credentials.username,
|
userId: credentials.username,
|
||||||
nickname: credentials.username,
|
nickname: credentials.username,
|
||||||
}));
|
})).catch(e => ({ message: `${e}` }));
|
||||||
|
|
||||||
parseToken = (token: string): Credentials =>
|
parseToken = (token: string): Credentials =>
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
@@ -112,7 +122,7 @@ export class Navidrome implements MusicService {
|
|||||||
name: id,
|
name: id,
|
||||||
}),
|
}),
|
||||||
albums: (_: AlbumQuery): Promise<Result<Album>> => {
|
albums: (_: AlbumQuery): Promise<Result<Album>> => {
|
||||||
return Promise.resolve({ results: [], total: 0});
|
return Promise.resolve({ results: [], total: 0 });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,11 +83,11 @@ function server(
|
|||||||
if (isSuccess(authResult)) {
|
if (isSuccess(authResult)) {
|
||||||
linkCodes.associate(linkCode, authResult);
|
linkCodes.associate(linkCode, authResult);
|
||||||
res.render("success", {
|
res.render("success", {
|
||||||
message: `Login successful`,
|
message: `Login successful!`,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
res.status(403).render("failure", {
|
res.status(403).render("failure", {
|
||||||
message: `Login failed, ${authResult.message}!`,
|
message: `Login failed! ${authResult.message}!`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import axios from "axios";
|
|||||||
jest.mock("axios");
|
jest.mock("axios");
|
||||||
|
|
||||||
import randomString from "../src/random_string";
|
import randomString from "../src/random_string";
|
||||||
|
import { AuthSuccess } from "../src/music_service";
|
||||||
jest.mock("../src/random_string");
|
jest.mock("../src/random_string");
|
||||||
|
|
||||||
describe("t", () => {
|
describe("t", () => {
|
||||||
@@ -52,7 +53,7 @@ describe("navidrome", () => {
|
|||||||
</subsonic-response>`,
|
</subsonic-response>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const token = await navidrome.generateToken({ username, password });
|
const token = await navidrome.generateToken({ username, password }) as AuthSuccess;
|
||||||
|
|
||||||
expect(token.authToken).toBeDefined();
|
expect(token.authToken).toBeDefined();
|
||||||
expect(token.nickname).toEqual(username);
|
expect(token.nickname).toEqual(username);
|
||||||
@@ -73,9 +74,8 @@ describe("navidrome", () => {
|
|||||||
</subsonic-response>`,
|
</subsonic-response>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return expect(
|
const token = await navidrome.generateToken({ username, password });
|
||||||
navidrome.generateToken({ username, password })
|
expect(token).toEqual({ message: "Wrong username or password" })
|
||||||
).rejects.toMatch("Wrong username or password");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -101,10 +101,11 @@ describe("navidrome", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when no paging is ineffect", () => {
|
describe("when no paging is in effect", () => {
|
||||||
it("should return all the artists", async () => {
|
it("should return all the artists", async () => {
|
||||||
const artists = await navidrome
|
const artists = await navidrome
|
||||||
.generateToken({ username, password })
|
.generateToken({ username, password })
|
||||||
|
.then(it => it as AuthSuccess)
|
||||||
.then((it) => navidrome.login(it.authToken))
|
.then((it) => navidrome.login(it.authToken))
|
||||||
.then((it) => it.artists({ _index: 0, _count: 100 }));
|
.then((it) => it.artists({ _index: 0, _count: 100 }));
|
||||||
|
|
||||||
@@ -126,6 +127,7 @@ describe("navidrome", () => {
|
|||||||
it("should return only the correct page of artists", async () => {
|
it("should return only the correct page of artists", async () => {
|
||||||
const artists = await navidrome
|
const artists = await navidrome
|
||||||
.generateToken({ username, password })
|
.generateToken({ username, password })
|
||||||
|
.then(it => it as AuthSuccess)
|
||||||
.then((it) => navidrome.login(it.authToken))
|
.then((it) => navidrome.login(it.authToken))
|
||||||
.then((it) => it.artists({ _index: 1, _count: 2 }));
|
.then((it) => it.artists({ _index: 1, _count: 2 }));
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ describe("api", () => {
|
|||||||
.send({ username, password, linkCode })
|
.send({ username, password, linkCode })
|
||||||
.expect(403);
|
.expect(403);
|
||||||
|
|
||||||
expect(res.text).toContain(`Login failed, Invalid user:${username}`);
|
expect(res.text).toContain(`Login failed! Invalid user:${username}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% layout('./layout', { title: "Failure" }) %>
|
<% layout('./layout', { title: "Failure" }) %>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1><%= it.message %></h1>
|
<h1 class="failure"><%= it.message %></h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
<% layout('./layout') %>
|
<% layout('./layout') %>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1>bonob service</h1>
|
<h1><%= it.bonobService.name %> (<%= it.bonobService.sid %>)</h1>
|
||||||
<h2><%= it.bonobService.name %> (<%= it.bonobService.sid %>)
|
|
||||||
<h3>Expected config</h3>
|
<h3>Expected config</h3>
|
||||||
<div><%= JSON.stringify(it.bonobService) %></div>
|
<div><%= JSON.stringify(it.bonobService) %></div>
|
||||||
<% if(it.registeredBonobService) { %>
|
<% if(it.registeredBonobService) { %>
|
||||||
|
|||||||
@@ -2,6 +2,33 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title><%= it.title || "bonob" %></title>
|
<title><%= it.title || "bonob" %></title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#content {
|
||||||
|
margin: auto;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 700%;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 300%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 300%;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input#submit {
|
||||||
|
margin-top: 100px
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%~ it.body %>
|
<%~ it.body %>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<% layout('./layout', { title: "Login" }) %>
|
<% layout('./layout', { title: "Login" }) %>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1>Log in to <%= it.bonobService.name %></h1>
|
<h1 class="login">Log<br>in<br>to<br><%= it.bonobService.name %></h1>
|
||||||
<form action="<%= it.loginRoute %>" method="POST">
|
<form action="<%= it.loginRoute %>" method="POST">
|
||||||
<label for="username">Username:</label><input type="text" id="username" name="username"><br>
|
<label for="username">Username:</label><br>
|
||||||
<label for="password">Password:</label><input type="text" id="password" name="password"><br>
|
<input type="text" id="username" name="username"><br><br>
|
||||||
|
<label for="password">Password:</label><br>
|
||||||
|
<input type="password" id="password" name="password"><br>
|
||||||
<input type="hidden" name="linkCode" value="<%= it.linkCode %>">
|
<input type="hidden" name="linkCode" value="<%= it.linkCode %>">
|
||||||
<input type="submit" value="Login">
|
<input type="submit" value="Login" id="submit">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<% layout('./layout', { title: "Yippee" }) %>
|
<% layout('./layout', { title: "Yippee" }) %>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1><%= it.message %></h1>
|
<h1 class="success"><%= it.message %></h1>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user