Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions directus-cms/utils/setup-local.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const ADMIN_EMAIL = process.env.ADMIN_EMAIL || 'admin@programmier.bar';
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || '123456';
const PROD_URL = 'https://admin.programmier.bar';
const PROD_API_TOKEN = process.env.PROD_API_TOKEN || '';
const DIRECTUS_LOCAL_ADMIN_TOKEN = 'random_SECRET_t0ken!';

// Collections that need public read access
const PUBLIC_COLLECTIONS = [
Expand Down Expand Up @@ -65,26 +66,42 @@ const PUBLIC_COLLECTIONS = [
'home_page_podcasts',
];

// Token management — Directus access tokens expire after 15 minutes by default.
// Long-running imports (especially file downloads) can exceed this, so we
// re-authenticate when the token is older than 10 minutes.
let _cachedToken = null;
let _tokenObtainedAt = 0;
const TOKEN_MAX_AGE_MS = 10 * 60 * 1000;

let _isTokenSet = false;
async function getToken() {
if (_cachedToken && (Date.now() - _tokenObtainedAt) < TOKEN_MAX_AGE_MS) {
return _cachedToken;
}
const res = await fetch(`${DIRECTUS_URL}/auth/login`, {
if (_isTokenSet) return DIRECTUS_LOCAL_ADMIN_TOKEN;

let res = await fetch(`${DIRECTUS_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: ADMIN_EMAIL, password: ADMIN_PASSWORD }),
});
const data = await res.json();
_cachedToken = data.data?.access_token;
_tokenObtainedAt = Date.now();
return _cachedToken;
let data = await res.json();
let tmpToken = data.data?.access_token;
res = await fetch(`${DIRECTUS_URL}/users/me`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${tmpToken}`,
}
});
data = await res.json();
let id = data.data?.id;
res = await fetch(`${DIRECTUS_URL}/users/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${tmpToken}`,
},
body: JSON.stringify({ token: DIRECTUS_LOCAL_ADMIN_TOKEN }),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict admin token rotation to local instances only

This line unconditionally sets the admin user's API token to a repo-known constant, but DIRECTUS_URL is environment-configurable, so running setup-local.mjs against a shared/staging URL will silently rotate that environment to a predictable admin credential. That is a security regression introduced by this commit: a mispointed run can both break existing admin auth flows and expose full admin API access to anyone who knows the checked-in token value.

Useful? React with 👍 / 👎.

});

if (!res.ok) {
throw new Error('Could not set admin user token.');
}

_isTokenSet = true;

return DIRECTUS_LOCAL_ADMIN_TOKEN
}

async function getOrCreatePublicPolicy(token) {
Expand Down
2 changes: 2 additions & 0 deletions nuxt-app/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ DIRECTUS_CMS_URL=http://localhost:8055
WEBSITE_URL=http://localhost:3000
NUXT_ENV=development

NUXT_DIRECTUS_API_TOKEN=random_SECRET_t0ken!

# Stripe (for ticket purchase testing)
# Get test keys from https://dashboard.stripe.com/test/apikeys
NUXT_STRIPE_SECRET_KEY=sk_test_...
Expand Down