mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-02 20:15:24 +02:00
feat: auto detect first login (#2722)
* 'hide' default email and password env variables * first login API endpoint * run code-generators * frontend indicators for default username and pw * remove old env variables from docs * fix env set variable * remove password from tests
This commit is contained in:
parent
71f95ca3c6
commit
bc575ec5ae
22 changed files with 234 additions and 120 deletions
|
@ -4,19 +4,17 @@
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
|
||||||
| Variables | Default | Description |
|
| Variables | Default | Description |
|
||||||
| ---------------- | :-------------------: | ----------------------------------------------------------------------------------- |
|
| ------------- | :-------------------: | ----------------------------------------------------------------------------------- |
|
||||||
| PUID | 911 | UserID permissions between host OS and container |
|
| PUID | 911 | UserID permissions between host OS and container |
|
||||||
| PGID | 911 | GroupID permissions between host OS and container |
|
| PGID | 911 | GroupID permissions between host OS and container |
|
||||||
| DEFAULT_GROUP | Home | The default group for users |
|
| DEFAULT_GROUP | Home | The default group for users |
|
||||||
| DEFAULT_EMAIL | changeme@example.com | The default username for the superuser |
|
| BASE_URL | http://localhost:8080 | Used for Notifications |
|
||||||
| DEFAULT_PASSWORD | MyPassword | The default password for the superuser |
|
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid |
|
||||||
| BASE_URL | http://localhost:8080 | Used for Notifications |
|
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
|
||||||
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid |
|
| API_DOCS | True | Turns on/off access to the API documentation locally. |
|
||||||
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
|
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||||
| API_DOCS | True | Turns on/off access to the API documentation locally. |
|
| ALLOW_SIGNUP | true | Allow user sign-up without token |
|
||||||
| TZ | UTC | Must be set to get correct date/time on the server |
|
|
||||||
| ALLOW_SIGNUP | true | Allow user sign-up without token |
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
|
|
@ -3,117 +3,117 @@ export const LOCALES = [
|
||||||
{
|
{
|
||||||
name: "繁體中文 (Chinese traditional)",
|
name: "繁體中文 (Chinese traditional)",
|
||||||
value: "zh-TW",
|
value: "zh-TW",
|
||||||
progress: 26,
|
progress: 28,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "简体中文 (Chinese simplified)",
|
name: "简体中文 (Chinese simplified)",
|
||||||
value: "zh-CN",
|
value: "zh-CN",
|
||||||
progress: 34,
|
progress: 65,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Tiếng Việt (Vietnamese)",
|
name: "Tiếng Việt (Vietnamese)",
|
||||||
value: "vi-VN",
|
value: "vi-VN",
|
||||||
progress: 0,
|
progress: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Українська (Ukrainian)",
|
name: "Українська (Ukrainian)",
|
||||||
value: "uk-UA",
|
value: "uk-UA",
|
||||||
progress: 100,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Türkçe (Turkish)",
|
name: "Türkçe (Turkish)",
|
||||||
value: "tr-TR",
|
value: "tr-TR",
|
||||||
progress: 47,
|
progress: 50,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Svenska (Swedish)",
|
name: "Svenska (Swedish)",
|
||||||
value: "sv-SE",
|
value: "sv-SE",
|
||||||
progress: 60,
|
progress: 71,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "српски (Serbian)",
|
name: "српски (Serbian)",
|
||||||
value: "sr-SP",
|
value: "sr-SP",
|
||||||
progress: 2,
|
progress: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Slovenian",
|
name: "Slovenian",
|
||||||
value: "sl-SI",
|
value: "sl-SI",
|
||||||
progress: 47,
|
progress: 49,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Slovak",
|
name: "Slovak",
|
||||||
value: "sk-SK",
|
value: "sk-SK",
|
||||||
progress: 99,
|
progress: 97,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pусский (Russian)",
|
name: "Pусский (Russian)",
|
||||||
value: "ru-RU",
|
value: "ru-RU",
|
||||||
progress: 31,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Română (Romanian)",
|
name: "Română (Romanian)",
|
||||||
value: "ro-RO",
|
value: "ro-RO",
|
||||||
progress: 12,
|
progress: 32,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Português (Portuguese)",
|
name: "Português (Portuguese)",
|
||||||
value: "pt-PT",
|
value: "pt-PT",
|
||||||
progress: 69,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Português do Brasil (Brazilian Portuguese)",
|
name: "Português do Brasil (Brazilian Portuguese)",
|
||||||
value: "pt-BR",
|
value: "pt-BR",
|
||||||
progress: 97,
|
progress: 98,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Polski (Polish)",
|
name: "Polski (Polish)",
|
||||||
value: "pl-PL",
|
value: "pl-PL",
|
||||||
progress: 99,
|
progress: 97,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Norsk (Norwegian)",
|
name: "Norsk (Norwegian)",
|
||||||
value: "no-NO",
|
value: "no-NO",
|
||||||
progress: 73,
|
progress: 85,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Nederlands (Dutch)",
|
name: "Nederlands (Dutch)",
|
||||||
value: "nl-NL",
|
value: "nl-NL",
|
||||||
progress: 100,
|
progress: 98,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Latvian",
|
name: "Latvian",
|
||||||
value: "lv-LV",
|
value: "lv-LV",
|
||||||
progress: 0,
|
progress: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Lithuanian",
|
name: "Lithuanian",
|
||||||
value: "lt-LT",
|
value: "lt-LT",
|
||||||
progress: 99,
|
progress: 97,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "한국어 (Korean)",
|
name: "한국어 (Korean)",
|
||||||
value: "ko-KR",
|
value: "ko-KR",
|
||||||
progress: 3,
|
progress: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "日本語 (Japanese)",
|
name: "日本語 (Japanese)",
|
||||||
value: "ja-JP",
|
value: "ja-JP",
|
||||||
progress: 9,
|
progress: 11,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Italiano (Italian)",
|
name: "Italiano (Italian)",
|
||||||
value: "it-IT",
|
value: "it-IT",
|
||||||
progress: 98,
|
progress: 96,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Magyar (Hungarian)",
|
name: "Magyar (Hungarian)",
|
||||||
value: "hu-HU",
|
value: "hu-HU",
|
||||||
progress: 43,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Croatian",
|
name: "Croatian",
|
||||||
value: "hr-HR",
|
value: "hr-HR",
|
||||||
progress: 100,
|
progress: 97,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "עברית (Hebrew)",
|
name: "עברית (Hebrew)",
|
||||||
|
@ -123,27 +123,27 @@ export const LOCALES = [
|
||||||
{
|
{
|
||||||
name: "Galician",
|
name: "Galician",
|
||||||
value: "gl-ES",
|
value: "gl-ES",
|
||||||
progress: 0,
|
progress: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Français (French)",
|
name: "Français (French)",
|
||||||
value: "fr-FR",
|
value: "fr-FR",
|
||||||
progress: 100,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "French, Canada",
|
name: "French, Canada",
|
||||||
value: "fr-CA",
|
value: "fr-CA",
|
||||||
progress: 54,
|
progress: 97,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Suomi (Finnish)",
|
name: "Suomi (Finnish)",
|
||||||
value: "fi-FI",
|
value: "fi-FI",
|
||||||
progress: 31,
|
progress: 95,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Español (Spanish)",
|
name: "Español (Spanish)",
|
||||||
value: "es-ES",
|
value: "es-ES",
|
||||||
progress: 59,
|
progress: 76,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "American English",
|
name: "American English",
|
||||||
|
@ -153,46 +153,46 @@ export const LOCALES = [
|
||||||
{
|
{
|
||||||
name: "British English",
|
name: "British English",
|
||||||
value: "en-GB",
|
value: "en-GB",
|
||||||
progress: 2,
|
progress: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ελληνικά (Greek)",
|
name: "Ελληνικά (Greek)",
|
||||||
value: "el-GR",
|
value: "el-GR",
|
||||||
progress: 33,
|
progress: 35,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Deutsch (German)",
|
name: "Deutsch (German)",
|
||||||
value: "de-DE",
|
value: "de-DE",
|
||||||
progress: 100,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Dansk (Danish)",
|
name: "Dansk (Danish)",
|
||||||
value: "da-DK",
|
value: "da-DK",
|
||||||
progress: 90,
|
progress: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Čeština (Czech)",
|
name: "Čeština (Czech)",
|
||||||
value: "cs-CZ",
|
value: "cs-CZ",
|
||||||
progress: 60,
|
progress: 66,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Català (Catalan)",
|
name: "Català (Catalan)",
|
||||||
value: "ca-ES",
|
value: "ca-ES",
|
||||||
progress: 54,
|
progress: 61,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Bulgarian",
|
name: "Bulgarian",
|
||||||
value: "bg-BG",
|
value: "bg-BG",
|
||||||
progress: 13,
|
progress: 99,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "العربية (Arabic)",
|
name: "العربية (Arabic)",
|
||||||
value: "ar-SA",
|
value: "ar-SA",
|
||||||
progress: 7,
|
progress: 16,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Afrikaans (Afrikaans)",
|
name: "Afrikaans (Afrikaans)",
|
||||||
value: "af-ZA",
|
value: "af-ZA",
|
||||||
progress: 0,
|
progress: 96,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -868,7 +868,9 @@
|
||||||
"user-can-invite-other-to-group": "User can invite other to group",
|
"user-can-invite-other-to-group": "User can invite other to group",
|
||||||
"user-can-manage-group": "User can manage group",
|
"user-can-manage-group": "User can manage group",
|
||||||
"user-can-organize-group-data": "User can organize group data",
|
"user-can-organize-group-data": "User can organize group data",
|
||||||
"enable-advanced-features": "Enable advanced features"
|
"enable-advanced-features": "Enable advanced features",
|
||||||
|
"it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.",
|
||||||
|
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!"
|
||||||
},
|
},
|
||||||
"language-dialog": {
|
"language-dialog": {
|
||||||
"translated": "translated",
|
"translated": "translated",
|
||||||
|
|
|
@ -34,6 +34,9 @@ export interface AppInfo {
|
||||||
demoStatus: boolean;
|
demoStatus: boolean;
|
||||||
allowSignup: boolean;
|
allowSignup: boolean;
|
||||||
}
|
}
|
||||||
|
export interface AppStartupInfo {
|
||||||
|
isFirstLogin: boolean;
|
||||||
|
}
|
||||||
export interface AppStatistics {
|
export interface AppStatistics {
|
||||||
totalRecipes: number;
|
totalRecipes: number;
|
||||||
totalUsers: number;
|
totalUsers: number;
|
||||||
|
@ -41,6 +44,22 @@ export interface AppStatistics {
|
||||||
uncategorizedRecipes: number;
|
uncategorizedRecipes: number;
|
||||||
untaggedRecipes: number;
|
untaggedRecipes: number;
|
||||||
}
|
}
|
||||||
|
export interface AppTheme {
|
||||||
|
lightPrimary?: string;
|
||||||
|
lightAccent?: string;
|
||||||
|
lightSecondary?: string;
|
||||||
|
lightSuccess?: string;
|
||||||
|
lightInfo?: string;
|
||||||
|
lightWarning?: string;
|
||||||
|
lightError?: string;
|
||||||
|
darkPrimary?: string;
|
||||||
|
darkAccent?: string;
|
||||||
|
darkSecondary?: string;
|
||||||
|
darkSuccess?: string;
|
||||||
|
darkInfo?: string;
|
||||||
|
darkWarning?: string;
|
||||||
|
darkError?: string;
|
||||||
|
}
|
||||||
export interface BackupOptions {
|
export interface BackupOptions {
|
||||||
recipes?: boolean;
|
recipes?: boolean;
|
||||||
settings?: boolean;
|
settings?: boolean;
|
||||||
|
|
|
@ -6,7 +6,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type WebhookType = "mealplan";
|
export type WebhookType = "mealplan";
|
||||||
export type SupportedMigrations = "nextcloud" | "chowdown" | "copymethat" | "paprika" | "mealie_alpha" | "tandoor" | "plantoeat";
|
export type SupportedMigrations =
|
||||||
|
| "nextcloud"
|
||||||
|
| "chowdown"
|
||||||
|
| "copymethat"
|
||||||
|
| "paprika"
|
||||||
|
| "mealie_alpha"
|
||||||
|
| "tandoor"
|
||||||
|
| "plantoeat";
|
||||||
|
|
||||||
export interface CreateGroupPreferences {
|
export interface CreateGroupPreferences {
|
||||||
privateGroup?: boolean;
|
privateGroup?: boolean;
|
||||||
|
@ -263,39 +270,56 @@ export interface RecipeIngredient {
|
||||||
}
|
}
|
||||||
export interface IngredientUnit {
|
export interface IngredientUnit {
|
||||||
name: string;
|
name: string;
|
||||||
|
pluralName?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
extras?: {
|
extras?: {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
};
|
};
|
||||||
fraction?: boolean;
|
fraction?: boolean;
|
||||||
abbreviation?: string;
|
abbreviation?: string;
|
||||||
|
pluralAbbreviation?: string;
|
||||||
useAbbreviation?: boolean;
|
useAbbreviation?: boolean;
|
||||||
|
aliases?: IngredientUnitAlias[];
|
||||||
id: string;
|
id: string;
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
updateAt?: string;
|
updateAt?: string;
|
||||||
}
|
}
|
||||||
|
export interface IngredientUnitAlias {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
export interface CreateIngredientUnit {
|
export interface CreateIngredientUnit {
|
||||||
name: string;
|
name: string;
|
||||||
|
pluralName?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
extras?: {
|
extras?: {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
};
|
};
|
||||||
fraction?: boolean;
|
fraction?: boolean;
|
||||||
abbreviation?: string;
|
abbreviation?: string;
|
||||||
|
pluralAbbreviation?: string;
|
||||||
useAbbreviation?: boolean;
|
useAbbreviation?: boolean;
|
||||||
|
aliases?: CreateIngredientUnitAlias[];
|
||||||
|
}
|
||||||
|
export interface CreateIngredientUnitAlias {
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
export interface IngredientFood {
|
export interface IngredientFood {
|
||||||
name: string;
|
name: string;
|
||||||
|
pluralName?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
extras?: {
|
extras?: {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
};
|
};
|
||||||
labelId?: string;
|
labelId?: string;
|
||||||
|
aliases?: IngredientFoodAlias[];
|
||||||
id: string;
|
id: string;
|
||||||
label?: MultiPurposeLabelSummary;
|
label?: MultiPurposeLabelSummary;
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
updateAt?: string;
|
updateAt?: string;
|
||||||
}
|
}
|
||||||
|
export interface IngredientFoodAlias {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
export interface MultiPurposeLabelSummary {
|
export interface MultiPurposeLabelSummary {
|
||||||
name: string;
|
name: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
@ -304,11 +328,16 @@ export interface MultiPurposeLabelSummary {
|
||||||
}
|
}
|
||||||
export interface CreateIngredientFood {
|
export interface CreateIngredientFood {
|
||||||
name: string;
|
name: string;
|
||||||
|
pluralName?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
extras?: {
|
extras?: {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
};
|
};
|
||||||
labelId?: string;
|
labelId?: string;
|
||||||
|
aliases?: CreateIngredientFoodAlias[];
|
||||||
|
}
|
||||||
|
export interface CreateIngredientFoodAlias {
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
export interface ShoppingListCreate {
|
export interface ShoppingListCreate {
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
|
@ -465,7 +465,7 @@ export interface ScrapeRecipe {
|
||||||
export interface ScrapeRecipeTest {
|
export interface ScrapeRecipeTest {
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
export interface SlugResponse { }
|
export interface SlugResponse {}
|
||||||
export interface TagIn {
|
export interface TagIn {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export type OrderByNullPosition = "first" | "last";
|
||||||
export type OrderDirection = "asc" | "desc";
|
export type OrderDirection = "asc" | "desc";
|
||||||
|
|
||||||
export interface ErrorResponse {
|
export interface ErrorResponse {
|
||||||
|
@ -19,6 +20,7 @@ export interface PaginationQuery {
|
||||||
page?: number;
|
page?: number;
|
||||||
perPage?: number;
|
perPage?: number;
|
||||||
orderBy?: string;
|
orderBy?: string;
|
||||||
|
orderByNullPosition?: OrderByNullPosition;
|
||||||
orderDirection?: OrderDirection & string;
|
orderDirection?: OrderDirection & string;
|
||||||
queryFilter?: string;
|
queryFilter?: string;
|
||||||
paginationSeed?: string;
|
paginationSeed?: string;
|
||||||
|
|
|
@ -7,6 +7,18 @@
|
||||||
'bg-off-white': !$vuetify.theme.dark && !isDark,
|
'bg-off-white': !$vuetify.theme.dark && !isDark,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<v-alert v-if="isFirstLogin" class="my-4" type="info" icon="mdi-information">
|
||||||
|
<div>
|
||||||
|
<p class="mb-3">
|
||||||
|
{{ $tc('user.it-looks-like-this-is-your-first-time-logging-in')}}
|
||||||
|
</p>
|
||||||
|
<p class="mb-1"><strong>{{ $tc('user.username') }}:</strong> changeme@example.com</p>
|
||||||
|
<p class="mb-3"><strong>{{ $tc('user.password') }}:</strong> MyPassword</p>
|
||||||
|
<p>
|
||||||
|
{{ $tc('user.dont-want-to-see-this-anymore-be-sure-to-change-your-email') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</v-alert>
|
||||||
<v-card tag="section" class="d-flex flex-column align-center" width="600px">
|
<v-card tag="section" class="d-flex flex-column align-center" width="600px">
|
||||||
<v-toolbar width="100%" color="primary" class="d-flex justify-center mb-4" dark>
|
<v-toolbar width="100%" color="primary" class="d-flex justify-center mb-4" dark>
|
||||||
<v-toolbar-title class="headline text-h4"> Mealie </v-toolbar-title>
|
<v-toolbar-title class="headline text-h4"> Mealie </v-toolbar-title>
|
||||||
|
@ -101,12 +113,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, useContext, computed, reactive, useRouter } from "@nuxtjs/composition-api";
|
import { defineComponent, ref, useContext, computed, reactive, useRouter, useAsync } from "@nuxtjs/composition-api";
|
||||||
import { useDark, whenever } from "@vueuse/core";
|
import { useDark, whenever } from "@vueuse/core";
|
||||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||||
import { useAppInfo } from "~/composables/api";
|
import { useAppInfo } from "~/composables/api";
|
||||||
import { usePasswordField } from "~/composables/use-passwords";
|
import { usePasswordField } from "~/composables/use-passwords";
|
||||||
import { alert } from "~/composables/use-toast";
|
import { alert } from "~/composables/use-toast";
|
||||||
|
import { useAsyncKey } from "~/composables/use-utils";
|
||||||
|
import { AppStartupInfo } from "~/lib/api/types/admin";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
layout: "blank",
|
layout: "blank",
|
||||||
|
@ -115,7 +129,7 @@ export default defineComponent({
|
||||||
const isDark = useDark();
|
const isDark = useDark();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { $auth, i18n } = useContext();
|
const { $auth, i18n, $axios } = useContext();
|
||||||
const { loggedIn } = useLoggedInState();
|
const { loggedIn } = useLoggedInState();
|
||||||
const groupSlug = computed(() => $auth.user?.groupSlug);
|
const groupSlug = computed(() => $auth.user?.groupSlug);
|
||||||
|
|
||||||
|
@ -133,6 +147,13 @@ export default defineComponent({
|
||||||
remember: false,
|
remember: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isFirstLogin = ref(false)
|
||||||
|
|
||||||
|
useAsync(async () => {
|
||||||
|
const data = await $axios.get<AppStartupInfo>("/api/app/about/startup-info");
|
||||||
|
isFirstLogin.value = data.data.isFirstLogin;
|
||||||
|
}, useAsyncKey());
|
||||||
|
|
||||||
const loggingIn = ref(false);
|
const loggingIn = ref(false);
|
||||||
|
|
||||||
const appInfo = useAppInfo();
|
const appInfo = useAppInfo();
|
||||||
|
@ -182,6 +203,7 @@ export default defineComponent({
|
||||||
passwordIcon,
|
passwordIcon,
|
||||||
inputType,
|
inputType,
|
||||||
togglePasswordShow,
|
togglePasswordShow,
|
||||||
|
isFirstLogin
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,6 @@ async def system_startup():
|
||||||
indent=4,
|
indent=4,
|
||||||
exclude={
|
exclude={
|
||||||
"SECRET",
|
"SECRET",
|
||||||
"DEFAULT_PASSWORD",
|
|
||||||
"SFTP_PASSWORD",
|
"SFTP_PASSWORD",
|
||||||
"SFTP_USERNAME",
|
"SFTP_USERNAME",
|
||||||
"DB_URL", # replace by DB_URL_PUBLIC for logs
|
"DB_URL", # replace by DB_URL_PUBLIC for logs
|
||||||
|
|
|
@ -85,8 +85,17 @@ class AppSettings(BaseSettings):
|
||||||
return self.DB_PROVIDER.db_url_public if self.DB_PROVIDER else None
|
return self.DB_PROVIDER.db_url_public if self.DB_PROVIDER else None
|
||||||
|
|
||||||
DEFAULT_GROUP: str = "Home"
|
DEFAULT_GROUP: str = "Home"
|
||||||
DEFAULT_EMAIL: str = "changeme@example.com"
|
|
||||||
DEFAULT_PASSWORD: str = "MyPassword"
|
_DEFAULT_EMAIL: str = "changeme@example.com"
|
||||||
|
"""
|
||||||
|
This is the default email used for the first user created in the database. This is only used if no users
|
||||||
|
exist in the database. it should no longer be set by end users.
|
||||||
|
"""
|
||||||
|
_DEFAULT_PASSWORD: str = "MyPassword"
|
||||||
|
"""
|
||||||
|
This is the default password used for the first user created in the database. This is only used if no users
|
||||||
|
exist in the database. it should no longer be set by end users.
|
||||||
|
"""
|
||||||
|
|
||||||
# ===============================================
|
# ===============================================
|
||||||
# Email Configuration
|
# Email Configuration
|
||||||
|
|
|
@ -13,7 +13,7 @@ def dev_users() -> list[dict]:
|
||||||
"full_name": "Jason",
|
"full_name": "Jason",
|
||||||
"username": "jason",
|
"username": "jason",
|
||||||
"email": "jason@example.com",
|
"email": "jason@example.com",
|
||||||
"password": hash_password(settings.DEFAULT_PASSWORD),
|
"password": hash_password(settings._DEFAULT_PASSWORD),
|
||||||
"group": settings.DEFAULT_GROUP,
|
"group": settings.DEFAULT_GROUP,
|
||||||
"admin": False,
|
"admin": False,
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ def dev_users() -> list[dict]:
|
||||||
"full_name": "Bob",
|
"full_name": "Bob",
|
||||||
"username": "bob",
|
"username": "bob",
|
||||||
"email": "bob@example.com",
|
"email": "bob@example.com",
|
||||||
"password": hash_password(settings.DEFAULT_PASSWORD),
|
"password": hash_password(settings._DEFAULT_PASSWORD),
|
||||||
"group": settings.DEFAULT_GROUP,
|
"group": settings.DEFAULT_GROUP,
|
||||||
"admin": False,
|
"admin": False,
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,7 @@ def dev_users() -> list[dict]:
|
||||||
"full_name": "Sarah",
|
"full_name": "Sarah",
|
||||||
"username": "sarah",
|
"username": "sarah",
|
||||||
"email": "sarah@example.com",
|
"email": "sarah@example.com",
|
||||||
"password": hash_password(settings.DEFAULT_PASSWORD),
|
"password": hash_password(settings._DEFAULT_PASSWORD),
|
||||||
"group": settings.DEFAULT_GROUP,
|
"group": settings.DEFAULT_GROUP,
|
||||||
"admin": False,
|
"admin": False,
|
||||||
},
|
},
|
||||||
|
@ -37,7 +37,7 @@ def dev_users() -> list[dict]:
|
||||||
"full_name": "Sammy",
|
"full_name": "Sammy",
|
||||||
"username": "sammy",
|
"username": "sammy",
|
||||||
"email": "sammy@example.com",
|
"email": "sammy@example.com",
|
||||||
"password": hash_password(settings.DEFAULT_PASSWORD),
|
"password": hash_password(settings._DEFAULT_PASSWORD),
|
||||||
"group": settings.DEFAULT_GROUP,
|
"group": settings.DEFAULT_GROUP,
|
||||||
"admin": False,
|
"admin": False,
|
||||||
},
|
},
|
||||||
|
@ -48,8 +48,8 @@ def default_user_init(db: AllRepositories):
|
||||||
default_user = {
|
default_user = {
|
||||||
"full_name": "Change Me",
|
"full_name": "Change Me",
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
"email": settings.DEFAULT_EMAIL,
|
"email": settings._DEFAULT_EMAIL,
|
||||||
"password": hash_password(settings.DEFAULT_PASSWORD),
|
"password": hash_password(settings._DEFAULT_PASSWORD),
|
||||||
"group": settings.DEFAULT_GROUP,
|
"group": settings.DEFAULT_GROUP,
|
||||||
"admin": True,
|
"admin": True,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
from fastapi import APIRouter, Response
|
from fastapi import APIRouter, Depends, Response
|
||||||
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
from mealie.core.config import get_app_settings
|
from mealie.core.config import get_app_settings
|
||||||
from mealie.core.settings.static import APP_VERSION
|
from mealie.core.settings.static import APP_VERSION
|
||||||
from mealie.schema.admin.about import AppInfo, AppTheme
|
from mealie.db.db_setup import generate_session
|
||||||
|
from mealie.db.models.users.users import User
|
||||||
|
from mealie.schema.admin.about import AppInfo, AppStartupInfo, AppTheme
|
||||||
|
|
||||||
router = APIRouter(prefix="/about")
|
router = APIRouter(prefix="/about")
|
||||||
|
|
||||||
|
@ -20,6 +23,21 @@ def get_app_info():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/startup-info", response_model=AppStartupInfo)
|
||||||
|
def get_startup_info(session: Session = Depends(generate_session)):
|
||||||
|
"""returns helpful startup information"""
|
||||||
|
settings = get_app_settings()
|
||||||
|
|
||||||
|
is_first_login = False
|
||||||
|
with session as db:
|
||||||
|
if db.query(User).filter_by(email=settings._DEFAULT_EMAIL).count() > 0:
|
||||||
|
is_first_login = True
|
||||||
|
|
||||||
|
return AppStartupInfo(
|
||||||
|
is_first_login=is_first_login,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/theme", response_model=AppTheme)
|
@router.get("/theme", response_model=AppTheme)
|
||||||
def get_app_theme(resp: Response):
|
def get_app_theme(resp: Response):
|
||||||
"""Get's the current theme settings"""
|
"""Get's the current theme settings"""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# This file is auto-generated by gen_schema_exports.py
|
# This file is auto-generated by gen_schema_exports.py
|
||||||
from .about import AdminAboutInfo, AppInfo, AppStatistics, CheckAppConfig, DockerVolumeText
|
from .about import AdminAboutInfo, AppInfo, AppStartupInfo, AppStatistics, AppTheme, CheckAppConfig, DockerVolumeText
|
||||||
from .backup import AllBackups, BackupFile, BackupOptions, CreateBackup, ImportJob
|
from .backup import AllBackups, BackupFile, BackupOptions, CreateBackup, ImportJob
|
||||||
from .email import EmailReady, EmailSuccess, EmailTest
|
from .email import EmailReady, EmailSuccess, EmailTest
|
||||||
from .maintenance import MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary
|
from .maintenance import MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary
|
||||||
|
@ -27,7 +27,9 @@ __all__ = [
|
||||||
"MaintenanceSummary",
|
"MaintenanceSummary",
|
||||||
"AdminAboutInfo",
|
"AdminAboutInfo",
|
||||||
"AppInfo",
|
"AppInfo",
|
||||||
|
"AppStartupInfo",
|
||||||
"AppStatistics",
|
"AppStatistics",
|
||||||
|
"AppTheme",
|
||||||
"CheckAppConfig",
|
"CheckAppConfig",
|
||||||
"DockerVolumeText",
|
"DockerVolumeText",
|
||||||
"EmailReady",
|
"EmailReady",
|
||||||
|
|
|
@ -34,6 +34,15 @@ class AppTheme(MealieModel):
|
||||||
dark_error: str = "#EF5350"
|
dark_error: str = "#EF5350"
|
||||||
|
|
||||||
|
|
||||||
|
class AppStartupInfo(MealieModel):
|
||||||
|
is_first_login: bool
|
||||||
|
"""
|
||||||
|
The applications best guess that a user hasn't logged in. Currently, it really
|
||||||
|
on indicates that the 'changeme@example.com' user is still in the database. Once
|
||||||
|
it is removed, this will always return False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class AdminAboutInfo(AppInfo):
|
class AdminAboutInfo(AppInfo):
|
||||||
versionLatest: str
|
versionLatest: str
|
||||||
api_port: int
|
api_port: int
|
||||||
|
|
|
@ -92,6 +92,25 @@ __all__ = [
|
||||||
"RecipeToolOut",
|
"RecipeToolOut",
|
||||||
"RecipeToolResponse",
|
"RecipeToolResponse",
|
||||||
"RecipeToolSave",
|
"RecipeToolSave",
|
||||||
|
"RecipeTimelineEventCreate",
|
||||||
|
"RecipeTimelineEventIn",
|
||||||
|
"RecipeTimelineEventOut",
|
||||||
|
"RecipeTimelineEventPagination",
|
||||||
|
"RecipeTimelineEventUpdate",
|
||||||
|
"TimelineEventImage",
|
||||||
|
"TimelineEventType",
|
||||||
|
"RecipeAsset",
|
||||||
|
"RecipeSettings",
|
||||||
|
"RecipeShareToken",
|
||||||
|
"RecipeShareTokenCreate",
|
||||||
|
"RecipeShareTokenSave",
|
||||||
|
"RecipeShareTokenSummary",
|
||||||
|
"RecipeDuplicate",
|
||||||
|
"RecipeSlug",
|
||||||
|
"RecipeZipTokenResponse",
|
||||||
|
"SlugResponse",
|
||||||
|
"UpdateImageResponse",
|
||||||
|
"RecipeNote",
|
||||||
"CategoryBase",
|
"CategoryBase",
|
||||||
"CategoryIn",
|
"CategoryIn",
|
||||||
"CategoryOut",
|
"CategoryOut",
|
||||||
|
@ -102,6 +121,12 @@ __all__ = [
|
||||||
"TagIn",
|
"TagIn",
|
||||||
"TagOut",
|
"TagOut",
|
||||||
"TagSave",
|
"TagSave",
|
||||||
|
"RecipeCommentCreate",
|
||||||
|
"RecipeCommentOut",
|
||||||
|
"RecipeCommentPagination",
|
||||||
|
"RecipeCommentSave",
|
||||||
|
"RecipeCommentUpdate",
|
||||||
|
"UserBase",
|
||||||
"AssignCategories",
|
"AssignCategories",
|
||||||
"AssignSettings",
|
"AssignSettings",
|
||||||
"AssignTags",
|
"AssignTags",
|
||||||
|
@ -109,34 +134,10 @@ __all__ = [
|
||||||
"ExportBase",
|
"ExportBase",
|
||||||
"ExportRecipes",
|
"ExportRecipes",
|
||||||
"ExportTypes",
|
"ExportTypes",
|
||||||
"RecipeShareToken",
|
|
||||||
"RecipeShareTokenCreate",
|
|
||||||
"RecipeShareTokenSave",
|
|
||||||
"RecipeShareTokenSummary",
|
|
||||||
"ScrapeRecipe",
|
|
||||||
"ScrapeRecipeTest",
|
|
||||||
"RecipeCommentCreate",
|
|
||||||
"RecipeCommentOut",
|
|
||||||
"RecipeCommentPagination",
|
|
||||||
"RecipeCommentSave",
|
|
||||||
"RecipeCommentUpdate",
|
|
||||||
"UserBase",
|
|
||||||
"RecipeImageTypes",
|
|
||||||
"CreateRecipe",
|
|
||||||
"CreateRecipeBulk",
|
|
||||||
"CreateRecipeByUrlBulk",
|
|
||||||
"Recipe",
|
|
||||||
"RecipeCategory",
|
|
||||||
"RecipeCategoryPagination",
|
|
||||||
"RecipeLastMade",
|
|
||||||
"RecipePagination",
|
|
||||||
"RecipeSummary",
|
|
||||||
"RecipeTag",
|
|
||||||
"RecipeTagPagination",
|
|
||||||
"RecipeTool",
|
|
||||||
"RecipeToolPagination",
|
|
||||||
"IngredientReferences",
|
"IngredientReferences",
|
||||||
"RecipeStep",
|
"RecipeStep",
|
||||||
|
"RecipeImageTypes",
|
||||||
|
"Nutrition",
|
||||||
"CreateIngredientFood",
|
"CreateIngredientFood",
|
||||||
"CreateIngredientFoodAlias",
|
"CreateIngredientFoodAlias",
|
||||||
"CreateIngredientUnit",
|
"CreateIngredientUnit",
|
||||||
|
@ -159,20 +160,19 @@ __all__ = [
|
||||||
"SaveIngredientFood",
|
"SaveIngredientFood",
|
||||||
"SaveIngredientUnit",
|
"SaveIngredientUnit",
|
||||||
"UnitFoodBase",
|
"UnitFoodBase",
|
||||||
"RecipeAsset",
|
"CreateRecipe",
|
||||||
"RecipeTimelineEventCreate",
|
"CreateRecipeBulk",
|
||||||
"RecipeTimelineEventIn",
|
"CreateRecipeByUrlBulk",
|
||||||
"RecipeTimelineEventOut",
|
"Recipe",
|
||||||
"RecipeTimelineEventPagination",
|
"RecipeCategory",
|
||||||
"RecipeTimelineEventUpdate",
|
"RecipeCategoryPagination",
|
||||||
"TimelineEventImage",
|
"RecipeLastMade",
|
||||||
"TimelineEventType",
|
"RecipePagination",
|
||||||
"RecipeDuplicate",
|
"RecipeSummary",
|
||||||
"RecipeSlug",
|
"RecipeTag",
|
||||||
"RecipeZipTokenResponse",
|
"RecipeTagPagination",
|
||||||
"SlugResponse",
|
"RecipeTool",
|
||||||
"UpdateImageResponse",
|
"RecipeToolPagination",
|
||||||
"Nutrition",
|
"ScrapeRecipe",
|
||||||
"RecipeSettings",
|
"ScrapeRecipeTest",
|
||||||
"RecipeNote",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# This file is auto-generated by gen_schema_exports.py
|
# This file is auto-generated by gen_schema_exports.py
|
||||||
from .pagination import OrderDirection, PaginationBase, PaginationQuery, RecipeSearchQuery
|
from .pagination import OrderByNullPosition, OrderDirection, PaginationBase, PaginationQuery, RecipeSearchQuery
|
||||||
from .query_filter import LogicalOperator, QueryFilter, QueryFilterComponent, RelationalKeyword, RelationalOperator
|
from .query_filter import LogicalOperator, QueryFilter, QueryFilterComponent, RelationalKeyword, RelationalOperator
|
||||||
from .query_search import SearchFilter
|
from .query_search import SearchFilter
|
||||||
from .responses import ErrorResponse, FileTokenResponse, SuccessResponse
|
from .responses import ErrorResponse, FileTokenResponse, SuccessResponse
|
||||||
|
@ -15,6 +15,7 @@ __all__ = [
|
||||||
"QueryFilterComponent",
|
"QueryFilterComponent",
|
||||||
"RelationalKeyword",
|
"RelationalKeyword",
|
||||||
"RelationalOperator",
|
"RelationalOperator",
|
||||||
|
"OrderByNullPosition",
|
||||||
"OrderDirection",
|
"OrderDirection",
|
||||||
"PaginationBase",
|
"PaginationBase",
|
||||||
"PaginationQuery",
|
"PaginationQuery",
|
||||||
|
|
|
@ -116,7 +116,7 @@ class UserOut(UserBase):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_default_user(self) -> bool:
|
def is_default_user(self) -> bool:
|
||||||
return self.email == settings.DEFAULT_EMAIL.strip().lower()
|
return self.email == settings._DEFAULT_EMAIL.strip().lower()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loader_options(cls) -> list[LoaderOption]:
|
def loader_options(cls) -> list[LoaderOption]:
|
||||||
|
|
6
tests/fixtures/fixture_admin.py
vendored
6
tests/fixtures/fixture_admin.py
vendored
|
@ -10,7 +10,7 @@ from tests.utils import api_routes
|
||||||
def admin_token(api_client: TestClient):
|
def admin_token(api_client: TestClient):
|
||||||
settings = get_app_settings()
|
settings = get_app_settings()
|
||||||
|
|
||||||
form_data = {"username": settings.DEFAULT_EMAIL, "password": settings.DEFAULT_PASSWORD}
|
form_data = {"username": settings._DEFAULT_EMAIL, "password": settings._DEFAULT_PASSWORD}
|
||||||
return utils.login(form_data, api_client)
|
return utils.login(form_data, api_client)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def admin_token(api_client: TestClient):
|
||||||
def admin_user(api_client: TestClient):
|
def admin_user(api_client: TestClient):
|
||||||
settings = get_app_settings()
|
settings = get_app_settings()
|
||||||
|
|
||||||
form_data = {"username": settings.DEFAULT_EMAIL, "password": settings.DEFAULT_PASSWORD}
|
form_data = {"username": settings._DEFAULT_EMAIL, "password": settings._DEFAULT_PASSWORD}
|
||||||
|
|
||||||
token = utils.login(form_data, api_client)
|
token = utils.login(form_data, api_client)
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ def admin_user(api_client: TestClient):
|
||||||
yield utils.TestUser(
|
yield utils.TestUser(
|
||||||
_group_id=user_data.get("groupId"),
|
_group_id=user_data.get("groupId"),
|
||||||
user_id=user_data.get("id"),
|
user_id=user_data.get("id"),
|
||||||
password=settings.DEFAULT_PASSWORD,
|
password=settings._DEFAULT_PASSWORD,
|
||||||
username=user_data.get("username"),
|
username=user_data.get("username"),
|
||||||
email=user_data.get("email"),
|
email=user_data.get("email"),
|
||||||
token=token,
|
token=token,
|
||||||
|
|
|
@ -36,7 +36,7 @@ def test_init_superuser(api_client: TestClient, admin_user: TestUser):
|
||||||
assert admin_data["groupId"] == admin_user.group_id
|
assert admin_data["groupId"] == admin_user.group_id
|
||||||
|
|
||||||
assert admin_data["fullName"] == "Change Me"
|
assert admin_data["fullName"] == "Change Me"
|
||||||
assert admin_data["email"] == settings.DEFAULT_EMAIL
|
assert admin_data["email"] == settings._DEFAULT_EMAIL
|
||||||
|
|
||||||
|
|
||||||
def test_create_user(api_client: TestClient, admin_token):
|
def test_create_user(api_client: TestClient, admin_token):
|
||||||
|
@ -95,7 +95,7 @@ def test_update_other_user_as_not_admin(api_client: TestClient, unique_user: Tes
|
||||||
update_data = {
|
update_data = {
|
||||||
"id": unique_user.user_id,
|
"id": unique_user.user_id,
|
||||||
"fullName": "Updated Name",
|
"fullName": "Updated Name",
|
||||||
"email": settings.DEFAULT_EMAIL,
|
"email": settings._DEFAULT_EMAIL,
|
||||||
"group": "Home",
|
"group": "Home",
|
||||||
"admin": True,
|
"admin": True,
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ from tests.utils.fixture_schemas import TestUser
|
||||||
def test_failed_login(api_client: TestClient):
|
def test_failed_login(api_client: TestClient):
|
||||||
settings = get_app_settings()
|
settings = get_app_settings()
|
||||||
|
|
||||||
form_data = {"username": settings.DEFAULT_EMAIL, "password": "WRONG_PASSWORD"}
|
form_data = {"username": settings._DEFAULT_EMAIL, "password": "WRONG_PASSWORD"}
|
||||||
response = api_client.post(api_routes.auth_token, data=form_data)
|
response = api_client.post(api_routes.auth_token, data=form_data)
|
||||||
|
|
||||||
assert response.status_code == 401
|
assert response.status_code == 401
|
||||||
|
@ -23,7 +23,7 @@ def test_failed_login(api_client: TestClient):
|
||||||
def test_superuser_login(api_client: TestClient, admin_token):
|
def test_superuser_login(api_client: TestClient, admin_token):
|
||||||
settings = get_app_settings()
|
settings = get_app_settings()
|
||||||
|
|
||||||
form_data = {"username": settings.DEFAULT_EMAIL, "password": settings.DEFAULT_PASSWORD}
|
form_data = {"username": settings._DEFAULT_EMAIL, "password": settings._DEFAULT_PASSWORD}
|
||||||
response = api_client.post(api_routes.auth_token, data=form_data)
|
response = api_client.post(api_routes.auth_token, data=form_data)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
|
@ -9,7 +9,6 @@ from mealie.core.settings.settings import AppSettings
|
||||||
|
|
||||||
def test_non_default_settings(monkeypatch):
|
def test_non_default_settings(monkeypatch):
|
||||||
monkeypatch.setenv("DEFAULT_GROUP", "Test Group")
|
monkeypatch.setenv("DEFAULT_GROUP", "Test Group")
|
||||||
monkeypatch.setenv("DEFAULT_PASSWORD", "Test Password")
|
|
||||||
monkeypatch.setenv("API_PORT", "8000")
|
monkeypatch.setenv("API_PORT", "8000")
|
||||||
monkeypatch.setenv("API_DOCS", "False")
|
monkeypatch.setenv("API_DOCS", "False")
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ def test_non_default_settings(monkeypatch):
|
||||||
app_settings = get_app_settings()
|
app_settings = get_app_settings()
|
||||||
|
|
||||||
assert app_settings.DEFAULT_GROUP == "Test Group"
|
assert app_settings.DEFAULT_GROUP == "Test Group"
|
||||||
assert app_settings.DEFAULT_PASSWORD == "Test Password"
|
|
||||||
assert app_settings.API_PORT == 8000
|
assert app_settings.API_PORT == 8000
|
||||||
assert app_settings.API_DOCS is False
|
assert app_settings.API_DOCS is False
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,10 @@ admin_users_unlock = "/api/admin/users/unlock"
|
||||||
"""`/api/admin/users/unlock`"""
|
"""`/api/admin/users/unlock`"""
|
||||||
app_about = "/api/app/about"
|
app_about = "/api/app/about"
|
||||||
"""`/api/app/about`"""
|
"""`/api/app/about`"""
|
||||||
|
app_about_startup_info = "/api/app/about/startup-info"
|
||||||
|
"""`/api/app/about/startup-info`"""
|
||||||
|
app_about_theme = "/api/app/about/theme"
|
||||||
|
"""`/api/app/about/theme`"""
|
||||||
auth_refresh = "/api/auth/refresh"
|
auth_refresh = "/api/auth/refresh"
|
||||||
"""`/api/auth/refresh`"""
|
"""`/api/auth/refresh`"""
|
||||||
auth_token = "/api/auth/token"
|
auth_token = "/api/auth/token"
|
||||||
|
@ -183,6 +187,8 @@ users_reset_password = "/api/users/reset-password"
|
||||||
"""`/api/users/reset-password`"""
|
"""`/api/users/reset-password`"""
|
||||||
users_self = "/api/users/self"
|
users_self = "/api/users/self"
|
||||||
"""`/api/users/self`"""
|
"""`/api/users/self`"""
|
||||||
|
users_self_group = "/api/users/self/group"
|
||||||
|
"""`/api/users/self/group`"""
|
||||||
utils_download = "/api/utils/download"
|
utils_download = "/api/utils/download"
|
||||||
"""`/api/utils/download`"""
|
"""`/api/utils/download`"""
|
||||||
validators_group = "/api/validators/group"
|
validators_group = "/api/validators/group"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue