Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
rijkvanzanten authored Aug 26, 2024
2 parents 5bb38c4 + 1458f41 commit bc4cce8
Show file tree
Hide file tree
Showing 20 changed files with 149 additions and 38 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-geckos-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@directus/app': minor
---

Added a system interface for showing a password field with visibility toggle
6 changes: 6 additions & 0 deletions .changeset/heavy-frogs-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@directus/env': patch
'@directus/api': patch
---

Fixed server address undefined for `graphql` and `websocket` logs
5 changes: 5 additions & 0 deletions .changeset/mighty-peaches-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'docs': patch
---

Fixed missing import in auth example
5 changes: 5 additions & 0 deletions .changeset/smooth-turkeys-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'directus': patch
---

Fixed a formatting warning in readme.md
4 changes: 2 additions & 2 deletions api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export async function startServer(): Promise<void> {

const host = env['HOST'] as string;
const path = env['UNIX_SOCKET_PATH'] as string | undefined;
const port = env['PORT'] as string | undefined;
const port = env['PORT'] as string;

let listenOptions: ListenOptions;

Expand All @@ -167,7 +167,7 @@ export async function startServer(): Promise<void> {
} else {
listenOptions = {
host,
port: parseInt(port || '8055'),
port: parseInt(port),
};
}

Expand Down
21 changes: 16 additions & 5 deletions api/src/utils/get-address.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, expect, test } from 'vitest';
import { getAddress } from './get-address.js';
import type { ListenOptions } from 'net';
import getPort from 'get-port';
import { randomAlpha } from '@directus/random';

function createServer(listenOptions?: ListenOptions) {
return new Promise<http.Server>((resolve, reject) => {
Expand All @@ -20,16 +21,26 @@ function createServer(listenOptions?: ListenOptions) {
}

describe('getAddress', async () => {
test('Should return undefined before server is listening', async () => {
const server = await createServer();
test('Should return unix socket before server is listening when path is provided', async () => {
const serverSocket = `/tmp/server${randomAlpha(5)}.sock`;
const server = await createServer({ path: serverSocket });

expect(getAddress(server)).toBe(undefined);
expect(getAddress(server)).toBe(serverSocket);
server.close();
});

test('Should return host + port before server is listening when path is undefined', async () => {
const serverPort = await getPort();
const server = await createServer({ host: '0.0.0.0', port: serverPort });

expect(getAddress(server)).toBe(`0.0.0.0:${serverPort}`);
});

test('Should return unix socket when path is provided', async () => {
const server = await createServer({ path: '/tmp/server.sock' });
const serverSocket = `/tmp/server${randomAlpha(5)}.sock`;
const server = await createServer({ path: serverSocket });

expect(getAddress(server)).toBe('/tmp/server.sock');
expect(getAddress(server)).toBe(serverSocket);
});

test('Should return host + port when path is undefined', async () => {
Expand Down
9 changes: 8 additions & 1 deletion api/src/utils/get-address.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import * as http from 'http';
import { useEnv } from '@directus/env';

export function getAddress(server: http.Server) {
const env = useEnv();
const address = server.address();

if (address === null) {
// Before the 'listening' event has been emitted or after calling server.close()
return;

if (env['UNIX_SOCKET_PATH']) {
return env['UNIX_SOCKET_PATH'];
}

return `${env['HOST']}:${env['PORT']}`;
}

if (typeof address === 'string') {
Expand Down
3 changes: 2 additions & 1 deletion api/src/websocket/controllers/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export class GraphQLSubscriptionController extends SocketController {
});

bindPubSub();
logger.info(`GraphQL Subscriptions started at ws://${getAddress(httpServer)}${this.endpoint}`);

logger.info(`GraphQL Subscriptions started at ${getAddress(httpServer)}${this.endpoint}`);
}

private bindEvents(client: WebSocketClient) {
Expand Down
2 changes: 1 addition & 1 deletion api/src/websocket/controllers/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class WebSocketController extends SocketController {
this.bindEvents(this.createClient(ws, auth));
});

logger.info(`WebSocket Server started at ws://${getAddress(httpServer)}${this.endpoint}`);
logger.info(`WebSocket Server started at ${getAddress(httpServer)}${this.endpoint}`);
}

private bindEvents(client: WebSocketClient) {
Expand Down
27 changes: 27 additions & 0 deletions app/src/interfaces/_system/system-input-password/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { defineInterface } from '@directus/extensions';
import InputPassword from './input-password.vue';

export default defineInterface({
id: 'system-input-password',
name: '$t:interfaces.input-password.input-password',
description: '$t:interfaces.input-password.description',
icon: 'visibility',
component: InputPassword,
system: true,
types: ['string', 'text'],
group: 'standard',
options: [
{
field: 'placeholder',
name: '$t:placeholder',
type: 'string',
meta: {
width: 'half',
interface: 'input',
options: {
placeholder: '$t:enter_a_placeholder',
},
},
},
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
withDefaults(
defineProps<{
value?: string | null;
autofocus?: boolean;
autocomplete?: string | null;
placeholder?: string;
disabled?: boolean;
}>(),
{
value: null,
autofocus: false,
autocomplete: 'new-password',
disabled: false,
},
);
const emit = defineEmits<{
input: [value: string];
}>();
const { t } = useI18n();
const hidden = ref<boolean>(true);
function toggleHidePassword() {
hidden.value = !hidden.value;
}
</script>

<template>
<v-input
:model-value="value"
:type="hidden ? 'password' : 'text'"
:autocomplete="autocomplete"
:autofocus="autofocus"
:placeholder="placeholder ?? t('password')"
:disabled="disabled"
@update:model-value="emit('input', $event)"
>
<template #append>
<v-icon
v-tooltip="hidden ? t('show_password') : t('hide_password')"
:name="hidden ? 'visibility' : 'visibility_off'"
clickable
@click="toggleHidePassword"
/>
</template>
</v-input>
</template>
5 changes: 5 additions & 0 deletions app/src/lang/translations/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,9 @@ interfaces:
system-raw-editor:
system-raw-editor: Raw Editor
description: Allow entering of raw or mustache templating values
input-password:
input-password: Input Password
description: Password input with toggle to hide value
displays:
translations:
translations: Translations
Expand Down Expand Up @@ -2537,3 +2540,5 @@ duplicate_dashboard: Duplicate Dashboard
search_dashboard: Search Dashboard...
search_flow: Search Flow...
percent: Percent
show_password: Show password
hide_password: Hide password
2 changes: 1 addition & 1 deletion app/src/routes/login/components/login-form/login-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async function onSubmit() {
<template>
<form novalidate @submit.prevent="onSubmit">
<v-input v-model="email" autofocus autocomplete="username" type="email" :placeholder="t('email')" />
<v-input v-model="password" type="password" autocomplete="current-password" :placeholder="t('password')" />
<interface-system-input-password :value="password" autocomplete="current-password" @input="password = $event" />

<transition-expand>
<v-input
Expand Down
24 changes: 2 additions & 22 deletions app/src/routes/register/register-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ const { t } = useI18n();
const isLoading = ref(false);
const email = ref<string | null>(null);
const password = ref<string | null>(null);
const passwordVerification = ref<string | null>(null);
const error = ref<RequestError | string | null>(null);
const passwordsMatch = computed(() => password.value === passwordVerification.value);
const emit = defineEmits<{
wasSuccessful: [boolean];
Expand All @@ -39,12 +37,7 @@ async function onSubmit() {
// Simple RegEx, not for validation, but to prevent unnecessary login requests when the value is clearly invalid
const emailRegex = /^\S+@\S+$/;
if (
email.value === null ||
!emailRegex.test(email.value) ||
password.value === null ||
passwordsMatch.value === false
) {
if (email.value === null || !emailRegex.test(email.value) || password.value === null) {
error.value = ErrorCode.InvalidPayload;
return;
}
Expand Down Expand Up @@ -79,20 +72,7 @@ async function onSubmit() {
:placeholder="t('email')"
:disabled="isLoading"
/>
<v-input
v-model="password"
type="password"
autocomplete="new-password"
:placeholder="t('password')"
:disabled="isLoading"
/>
<v-input
v-model="passwordVerification"
type="password"
autocomplete="new-password"
:placeholder="t('confirm_password')"
:disabled="isLoading"
/>
<interface-system-input-password :value="password" :disabled="isLoading" @input="password = $event" />

<v-notice v-if="error" type="warning">
{{ errorFormatted }}
Expand Down
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@
- maxsteinwand
- FatumaA
- keesvanbemmel
- HZooly
3 changes: 2 additions & 1 deletion directus/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Directus is a real-time API and App dashboard for managing SQL database content.

## 🚀 Directus Cloud

[Directus Cloud](https://directus.io/pricing) allows you to create projects, hosted by the Directus team, from $15/month.
[Directus Cloud](https://directus.io/pricing) allows you to create projects, hosted by the Directus team, from
$15/month.

- A self-service dashboard to create and monitor all your projects in one place.
- Everything you need: Directus, database, storage, auto-scaling, and a global CDN.
Expand Down
7 changes: 5 additions & 2 deletions docs/contributing/codebase-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ The various sub-packages of the platform. Including the file-storage adapters, s
| [@directus/composables](/packages/@directus/composables/) | Shared Vue composables for Directus use |
| [@directus/constants](/packages/@directus/constants/) | Shared constants for Directus |
| [create-directus-extension](https://github.com/directus/directus/tree/main/packages/create-directus-extension) | A small util that will scaffold a Directus extension |
| [@directus/data-driver-postgres](https://github.com/directus/directus/tree/main/packages/data-driver-postgres) | Data abstraction for Postgres |
| [@directus/data](https://github.com/directus/directus/tree/main/packages/data) | Data abstraction for Directus |
| [create-directus-project](https://github.com/directus/directus/tree/main/packages/create-directus-project) | A small installer util that will create a directory, add boilerplate folders, and install Directus through npm |
| [@directus/env](/packages/@directus/env/) | Environment variable configuration extraction for Directus |
| [@directus/errors](/packages/@directus/errors/) | Utility functions to help creating and checking against Directus errors |
| [@directus/extensions-registry](/packages/@directus/extensions-registry/) | Abstraction for exploring Directus extensions on a package registry |
| [@directus/extensions-sdk](/packages/@directus/extensions-sdk/) | A toolkit to develop extensions to extend Directus |
| [@directus/extensions](/packages/@directus/extensions/) | Shared utilities, types and constants related to Directus extensions |
| [@directus/format-title](/packages/@directus/format-title/) | Custom formatter that converts any string into Title Case |
| [@directus/memory](/packages/@directus/memory/) | Memory / Redis abstraction for Directus |
| [@directus/pressure](/packages/@directus/pressure/) | Pressure based rate limiter |
Expand All @@ -100,6 +102,7 @@ The various sub-packages of the platform. Including the file-storage adapters, s
| [@directus/storage-driver-gcs](https://github.com/directus/directus/tree/main/packages/storage-driver-gcs) | GCS file storage abstraction for `@directus/storage` |
| [@directus/storage-driver-local](https://github.com/directus/directus/tree/main/packages/storage-driver-local) | Local file storage abstraction for `@directus/storage` |
| [@directus/storage-driver-s3](https://github.com/directus/directus/tree/main/packages/storage-driver-s3) | S3 file storage abstraction for `@directus/storage` |
| [@directus/storage-driver-supabase](https://github.com/directus/directus/tree/main/packages/storage-driver-supabase) | Supabase file storage driver for `@directus/storage` |
| [@directus/storage](https://github.com/directus/directus/tree/main/packages/storage) | Object storage abstraction layer for Directus |
| [@directus/stores](/packages/@directus/stores/) | Shared Directus Studio state for use in components, extensions, and the `@directus/app` routes. Stores are [Pinia](https://www.npmjs.com/package/pinia)-based stores. |
| [@directus/system-data](/packages/@directus/system-data/) | Definitions and types for Directus system collections |
Expand Down
1 change: 1 addition & 0 deletions docs/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ Corepack
CORS
CPUs?
create-directus-extension
create-directus-project
cron
Cron
CRON
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ const item = await client.request(
<template #authentication>

```js
import { createDirectus, rest, createUser } from '@directus/sdk';
const client = createDirectus('https://xyz.directus.app').with(rest());
import { createDirectus, rest, createUser, authentication } from '@directus/sdk';
const client = createDirectus('https://xyz.directus.app').with(rest()).with(authentication());

const newUser = await client.request(
createUser({
Expand Down
1 change: 1 addition & 0 deletions packages/env/src/constants/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const DEFAULTS = {
CONFIG_PATH: resolve(cwd(), '.env'),

HOST: '0.0.0.0',
PORT: 8055,
PUBLIC_URL: '/',
MAX_PAYLOAD_SIZE: '1mb',
MAX_RELATIONAL_DEPTH: 10,
Expand Down

0 comments on commit bc4cce8

Please sign in to comment.