Compare commits
No commits in common. "0faeb86ca7837f442dc8b20edf1a7442e4e06a5c" and "ca328724b37edfd2a5cfdf55199ec701e7756aa4" have entirely different histories.
0faeb86ca7
...
ca328724b3
11 changed files with 7 additions and 307 deletions
|
|
@ -1,70 +0,0 @@
|
||||||
describe('The admin nav link', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.exec('npm run db:seed')
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
cy.exec('npm run db:wipe')
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('when logged in as an admin', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.loginAsAdmin()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows the admin link on the home page', () => {
|
|
||||||
cy.visit('/home')
|
|
||||||
cy.get('#admin-link')
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.attr', 'href', '/admin')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows the admin link on the today page', () => {
|
|
||||||
cy.visit('/today')
|
|
||||||
cy.get('#admin-link')
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.attr', 'href', '/admin')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows the admin link on the user texts page', () => {
|
|
||||||
cy.visit('/texts')
|
|
||||||
cy.get('#admin-link')
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.attr', 'href', '/admin')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('navigates to the admin page when clicked', () => {
|
|
||||||
cy.visit('/home')
|
|
||||||
cy.get('#admin-link').click()
|
|
||||||
cy.url().should('include', '/admin')
|
|
||||||
cy.get('h1').should('contain', 'Admin')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('when logged in as a regular user', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.loginAsUser()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not show the admin link on the home page', () => {
|
|
||||||
cy.visit('/home')
|
|
||||||
cy.get('#admin-link').should('not.be.visible')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not show the admin link on the today page', () => {
|
|
||||||
cy.visit('/today')
|
|
||||||
cy.get('#admin-link').should('not.be.visible')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not show the admin link on the user texts page', () => {
|
|
||||||
cy.visit('/texts')
|
|
||||||
cy.get('#admin-link').should('not.be.visible')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('does not show the admin link on a user text page', () => {
|
|
||||||
cy.intercept('GET', '/api/texts/0').as('getText')
|
|
||||||
cy.visit('/texts/0')
|
|
||||||
cy.wait('@getText')
|
|
||||||
cy.get('#admin-link').should('not.be.visible')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
@ -69,60 +69,6 @@ describe('Authentication flows', () => {
|
||||||
cy.url().should('include', '/login')
|
cy.url().should('include', '/login')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logout button on today page works', () => {
|
|
||||||
cy.loginAsUser()
|
|
||||||
cy.visit('/today')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/today')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logout button on user texts list page works', () => {
|
|
||||||
cy.loginAsUser()
|
|
||||||
cy.visit('/texts')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/texts')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logout button on user specific text page works', () => {
|
|
||||||
cy.loginAsUser()
|
|
||||||
cy.visit('/texts/0')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/texts/0')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logout button on admin page works', () => {
|
|
||||||
cy.loginAsAdmin()
|
|
||||||
cy.visit('/admin')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/admin')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logout button on admin texts list page works', () => {
|
|
||||||
cy.loginAsAdmin()
|
|
||||||
cy.visit('/admin/texts')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/admin/texts')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logout button on admin specific text page works', () => {
|
|
||||||
cy.loginAsAdmin()
|
|
||||||
cy.visit('/admin/texts/0')
|
|
||||||
cy.get('#logout').click()
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
cy.visit('/admin/texts/0')
|
|
||||||
cy.url().should('include', '/login')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('non-admin user hitting /admin gets 403', () => {
|
it('non-admin user hitting /admin gets 403', () => {
|
||||||
cy.loginAsUser()
|
cy.loginAsUser()
|
||||||
cy.request({
|
cy.request({
|
||||||
|
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$texts = [
|
|
||||||
[
|
|
||||||
'id' => 0,
|
|
||||||
'name' => 'Tanach',
|
|
||||||
'userId' => 1,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$nodes = [
|
|
||||||
[
|
|
||||||
'id' => 0,
|
|
||||||
'title' => 'Tanach',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => null,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 1,
|
|
||||||
'title' => 'Torah',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 0,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 2,
|
|
||||||
'title' => 'Neviim',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 0,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 3,
|
|
||||||
'title' => 'Kesuvim',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 0,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 4,
|
|
||||||
'title' => 'Bereishis',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 1,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 5,
|
|
||||||
'title' => 'Shmos',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 1,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 6,
|
|
||||||
'title' => 'Vayikra',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 1,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 7,
|
|
||||||
'title' => 'Bamidbar',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 1,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 8,
|
|
||||||
'title' => 'Devarim',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 1,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 9,
|
|
||||||
'title' => 'Bereishis',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 4,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 10,
|
|
||||||
'title' => 'Noach',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 4,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 11,
|
|
||||||
'title' => 'Lech Lecha',
|
|
||||||
'textId' => 0,
|
|
||||||
'parentNodeId' => 4,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Default credentials:
|
|
||||||
// admin@example.com / admin1234 (admin)
|
|
||||||
// user@example.com / password1 (regular user)
|
|
||||||
// user2@example.com / password2 (second regular user, no texts seeded)
|
|
||||||
$users = [
|
|
||||||
[
|
|
||||||
'id' => 0,
|
|
||||||
'email' => 'admin@example.com',
|
|
||||||
'passwordHash' => password_hash('admin1234', PASSWORD_DEFAULT),
|
|
||||||
'isAdmin' => true,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 1,
|
|
||||||
'email' => 'user@example.com',
|
|
||||||
'passwordHash' => password_hash('password1', PASSWORD_DEFAULT),
|
|
||||||
'isAdmin' => false,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id' => 2,
|
|
||||||
'email' => 'user2@example.com',
|
|
||||||
'passwordHash' => password_hash('password2', PASSWORD_DEFAULT),
|
|
||||||
'isAdmin' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$plans = [];
|
|
||||||
$scheduledNodes = [];
|
|
||||||
$sessions = [];
|
|
||||||
|
|
||||||
$fileDataMap = [
|
|
||||||
'texts.json' => $texts,
|
|
||||||
'nodes.json' => $nodes,
|
|
||||||
'users.json' => $users,
|
|
||||||
'plans.json' => $plans,
|
|
||||||
'scheduledNodes.json' => $scheduledNodes,
|
|
||||||
'sessions.json' => $sessions,
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($fileDataMap as $file => $data) {
|
|
||||||
$path = __DIR__ . "/$file";
|
|
||||||
file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT));
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
|
||||||
const adminLink = document.getElementById('admin-link');
|
|
||||||
if (adminLink === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch('/api/auth/me', {
|
|
||||||
credentials: 'same-origin',
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = await response.json();
|
|
||||||
if (body.user && body.user.isAdmin === true) {
|
|
||||||
adminLink.hidden = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -32,15 +32,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
function fetchAndRenderNodes(textId) {
|
function fetchAndRenderNodes(textId) {
|
||||||
return fetch('/api/nodes/' + textId, { credentials: 'same-origin' })
|
return fetch('/api/nodes/' + textId, { credentials: 'same-origin' })
|
||||||
.then(function (response) {
|
.then(res => res.json())
|
||||||
if (!response.ok) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(nodes => {
|
.then(nodes => {
|
||||||
if (!Array.isArray(nodes)) return;
|
|
||||||
|
|
||||||
const existing = document.querySelector('#text-detail > ul');
|
const existing = document.querySelector('#text-detail > ul');
|
||||||
if (existing) existing.remove();
|
if (existing) existing.remove();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
<a class="btn btn-secondary" href="/today">
|
<a class="btn btn-secondary" href="/today">
|
||||||
Today's schedule
|
Today's schedule
|
||||||
</a>
|
</a>
|
||||||
<a id="admin-link" class="btn btn-secondary"
|
|
||||||
href="/admin" hidden>Admin</a>
|
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
<button id="logout" class="btn btn-danger">Logout</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -45,7 +43,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/js/auth.js"></script>
|
<script src="/js/auth.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/home.js"></script>
|
<script src="/js/home.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,14 @@
|
||||||
<body>
|
<body>
|
||||||
<header class="site-header">
|
<header class="site-header">
|
||||||
<div class="site-header-inner">
|
<div class="site-header-inner">
|
||||||
<div class="cluster">
|
|
||||||
<a class="btn btn-secondary" href="/admin/texts" id="back">
|
<a class="btn btn-secondary" href="/admin/texts" id="back">
|
||||||
Back to Texts
|
Back to Texts
|
||||||
</a>
|
</a>
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="container container-wide stack">
|
<main class="container container-wide stack">
|
||||||
<div id="text-detail" class="node-tree stack"></div>
|
<div id="text-detail" class="node-tree stack"></div>
|
||||||
</main>
|
</main>
|
||||||
<script src="/js/auth.js"></script>
|
|
||||||
<script src="/js/text.js"></script>
|
<script src="/js/text.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
<a class="btn btn-secondary" href="/admin" id="back">
|
<a class="btn btn-secondary" href="/admin" id="back">
|
||||||
Back to Admin
|
Back to Admin
|
||||||
</a>
|
</a>
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -32,7 +31,6 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
<script src="/js/auth.js"></script>
|
|
||||||
<script src="/js/texts.js"></script>
|
<script src="/js/texts.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,6 @@
|
||||||
<h1>Today</h1>
|
<h1>Today</h1>
|
||||||
<div class="cluster">
|
<div class="cluster">
|
||||||
<a class="btn btn-secondary" href="/home">Home</a>
|
<a class="btn btn-secondary" href="/home">Home</a>
|
||||||
<a id="admin-link" class="btn btn-secondary"
|
|
||||||
href="/admin" hidden>Admin</a>
|
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -25,7 +22,6 @@
|
||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
<script src="/js/auth.js"></script>
|
<script src="/js/auth.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/today.js"></script>
|
<script src="/js/today.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -9,22 +9,14 @@
|
||||||
<body>
|
<body>
|
||||||
<header class="site-header">
|
<header class="site-header">
|
||||||
<div class="site-header-inner">
|
<div class="site-header-inner">
|
||||||
<h1>Text</h1>
|
|
||||||
<div class="cluster">
|
|
||||||
<a class="btn btn-secondary" href="/texts" id="back">
|
<a class="btn btn-secondary" href="/texts" id="back">
|
||||||
My texts
|
Back to My Texts
|
||||||
</a>
|
</a>
|
||||||
<a id="admin-link" class="btn btn-secondary"
|
|
||||||
href="/admin" hidden>Admin</a>
|
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="container container-wide stack">
|
<main class="container container-wide stack">
|
||||||
<div id="text-detail" class="node-tree stack"></div>
|
<div id="text-detail" class="node-tree stack"></div>
|
||||||
</main>
|
</main>
|
||||||
<script src="/js/auth.js"></script>
|
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/text.js"></script>
|
<script src="/js/text.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@
|
||||||
<a class="btn btn-secondary" href="/home" id="back">
|
<a class="btn btn-secondary" href="/home" id="back">
|
||||||
Back to Home
|
Back to Home
|
||||||
</a>
|
</a>
|
||||||
<a id="admin-link" class="btn btn-secondary"
|
|
||||||
href="/admin" hidden>Admin</a>
|
|
||||||
<button id="logout" class="btn btn-danger">Logout</button>
|
<button id="logout" class="btn btn-danger">Logout</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -35,7 +33,6 @@
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
<script src="/js/auth.js"></script>
|
<script src="/js/auth.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/userTexts.js"></script>
|
<script src="/js/userTexts.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue