mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 21:45:25 +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
|
@ -3,117 +3,117 @@ export const LOCALES = [
|
|||
{
|
||||
name: "繁體中文 (Chinese traditional)",
|
||||
value: "zh-TW",
|
||||
progress: 26,
|
||||
progress: 28,
|
||||
},
|
||||
{
|
||||
name: "简体中文 (Chinese simplified)",
|
||||
value: "zh-CN",
|
||||
progress: 34,
|
||||
progress: 65,
|
||||
},
|
||||
{
|
||||
name: "Tiếng Việt (Vietnamese)",
|
||||
value: "vi-VN",
|
||||
progress: 0,
|
||||
progress: 2,
|
||||
},
|
||||
{
|
||||
name: "Українська (Ukrainian)",
|
||||
value: "uk-UA",
|
||||
progress: 100,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "Türkçe (Turkish)",
|
||||
value: "tr-TR",
|
||||
progress: 47,
|
||||
progress: 50,
|
||||
},
|
||||
{
|
||||
name: "Svenska (Swedish)",
|
||||
value: "sv-SE",
|
||||
progress: 60,
|
||||
progress: 71,
|
||||
},
|
||||
{
|
||||
name: "српски (Serbian)",
|
||||
value: "sr-SP",
|
||||
progress: 2,
|
||||
progress: 4,
|
||||
},
|
||||
{
|
||||
name: "Slovenian",
|
||||
value: "sl-SI",
|
||||
progress: 47,
|
||||
progress: 49,
|
||||
},
|
||||
{
|
||||
name: "Slovak",
|
||||
value: "sk-SK",
|
||||
progress: 99,
|
||||
progress: 97,
|
||||
},
|
||||
{
|
||||
name: "Pусский (Russian)",
|
||||
value: "ru-RU",
|
||||
progress: 31,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "Română (Romanian)",
|
||||
value: "ro-RO",
|
||||
progress: 12,
|
||||
progress: 32,
|
||||
},
|
||||
{
|
||||
name: "Português (Portuguese)",
|
||||
value: "pt-PT",
|
||||
progress: 69,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "Português do Brasil (Brazilian Portuguese)",
|
||||
value: "pt-BR",
|
||||
progress: 97,
|
||||
progress: 98,
|
||||
},
|
||||
{
|
||||
name: "Polski (Polish)",
|
||||
value: "pl-PL",
|
||||
progress: 99,
|
||||
progress: 97,
|
||||
},
|
||||
{
|
||||
name: "Norsk (Norwegian)",
|
||||
value: "no-NO",
|
||||
progress: 73,
|
||||
progress: 85,
|
||||
},
|
||||
{
|
||||
name: "Nederlands (Dutch)",
|
||||
value: "nl-NL",
|
||||
progress: 100,
|
||||
progress: 98,
|
||||
},
|
||||
{
|
||||
name: "Latvian",
|
||||
value: "lv-LV",
|
||||
progress: 0,
|
||||
progress: 1,
|
||||
},
|
||||
{
|
||||
name: "Lithuanian",
|
||||
value: "lt-LT",
|
||||
progress: 99,
|
||||
progress: 97,
|
||||
},
|
||||
{
|
||||
name: "한국어 (Korean)",
|
||||
value: "ko-KR",
|
||||
progress: 3,
|
||||
progress: 5,
|
||||
},
|
||||
{
|
||||
name: "日本語 (Japanese)",
|
||||
value: "ja-JP",
|
||||
progress: 9,
|
||||
progress: 11,
|
||||
},
|
||||
{
|
||||
name: "Italiano (Italian)",
|
||||
value: "it-IT",
|
||||
progress: 98,
|
||||
progress: 96,
|
||||
},
|
||||
{
|
||||
name: "Magyar (Hungarian)",
|
||||
value: "hu-HU",
|
||||
progress: 43,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "Croatian",
|
||||
value: "hr-HR",
|
||||
progress: 100,
|
||||
progress: 97,
|
||||
},
|
||||
{
|
||||
name: "עברית (Hebrew)",
|
||||
|
@ -123,27 +123,27 @@ export const LOCALES = [
|
|||
{
|
||||
name: "Galician",
|
||||
value: "gl-ES",
|
||||
progress: 0,
|
||||
progress: 1,
|
||||
},
|
||||
{
|
||||
name: "Français (French)",
|
||||
value: "fr-FR",
|
||||
progress: 100,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "French, Canada",
|
||||
value: "fr-CA",
|
||||
progress: 54,
|
||||
progress: 97,
|
||||
},
|
||||
{
|
||||
name: "Suomi (Finnish)",
|
||||
value: "fi-FI",
|
||||
progress: 31,
|
||||
progress: 95,
|
||||
},
|
||||
{
|
||||
name: "Español (Spanish)",
|
||||
value: "es-ES",
|
||||
progress: 59,
|
||||
progress: 76,
|
||||
},
|
||||
{
|
||||
name: "American English",
|
||||
|
@ -153,46 +153,46 @@ export const LOCALES = [
|
|||
{
|
||||
name: "British English",
|
||||
value: "en-GB",
|
||||
progress: 2,
|
||||
progress: 4,
|
||||
},
|
||||
{
|
||||
name: "Ελληνικά (Greek)",
|
||||
value: "el-GR",
|
||||
progress: 33,
|
||||
progress: 35,
|
||||
},
|
||||
{
|
||||
name: "Deutsch (German)",
|
||||
value: "de-DE",
|
||||
progress: 100,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "Dansk (Danish)",
|
||||
value: "da-DK",
|
||||
progress: 90,
|
||||
progress: 100,
|
||||
},
|
||||
{
|
||||
name: "Čeština (Czech)",
|
||||
value: "cs-CZ",
|
||||
progress: 60,
|
||||
progress: 66,
|
||||
},
|
||||
{
|
||||
name: "Català (Catalan)",
|
||||
value: "ca-ES",
|
||||
progress: 54,
|
||||
progress: 61,
|
||||
},
|
||||
{
|
||||
name: "Bulgarian",
|
||||
value: "bg-BG",
|
||||
progress: 13,
|
||||
progress: 99,
|
||||
},
|
||||
{
|
||||
name: "العربية (Arabic)",
|
||||
value: "ar-SA",
|
||||
progress: 7,
|
||||
progress: 16,
|
||||
},
|
||||
{
|
||||
name: "Afrikaans (Afrikaans)",
|
||||
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-manage-group": "User can manage group",
|
||||
"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": {
|
||||
"translated": "translated",
|
||||
|
|
|
@ -34,6 +34,9 @@ export interface AppInfo {
|
|||
demoStatus: boolean;
|
||||
allowSignup: boolean;
|
||||
}
|
||||
export interface AppStartupInfo {
|
||||
isFirstLogin: boolean;
|
||||
}
|
||||
export interface AppStatistics {
|
||||
totalRecipes: number;
|
||||
totalUsers: number;
|
||||
|
@ -41,6 +44,22 @@ export interface AppStatistics {
|
|||
uncategorizedRecipes: 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 {
|
||||
recipes?: boolean;
|
||||
settings?: boolean;
|
||||
|
|
|
@ -6,7 +6,14 @@
|
|||
*/
|
||||
|
||||
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 {
|
||||
privateGroup?: boolean;
|
||||
|
@ -263,39 +270,56 @@ export interface RecipeIngredient {
|
|||
}
|
||||
export interface IngredientUnit {
|
||||
name: string;
|
||||
pluralName?: string;
|
||||
description?: string;
|
||||
extras?: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
fraction?: boolean;
|
||||
abbreviation?: string;
|
||||
pluralAbbreviation?: string;
|
||||
useAbbreviation?: boolean;
|
||||
aliases?: IngredientUnitAlias[];
|
||||
id: string;
|
||||
createdAt?: string;
|
||||
updateAt?: string;
|
||||
}
|
||||
export interface IngredientUnitAlias {
|
||||
name: string;
|
||||
}
|
||||
export interface CreateIngredientUnit {
|
||||
name: string;
|
||||
pluralName?: string;
|
||||
description?: string;
|
||||
extras?: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
fraction?: boolean;
|
||||
abbreviation?: string;
|
||||
pluralAbbreviation?: string;
|
||||
useAbbreviation?: boolean;
|
||||
aliases?: CreateIngredientUnitAlias[];
|
||||
}
|
||||
export interface CreateIngredientUnitAlias {
|
||||
name: string;
|
||||
}
|
||||
export interface IngredientFood {
|
||||
name: string;
|
||||
pluralName?: string;
|
||||
description?: string;
|
||||
extras?: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
labelId?: string;
|
||||
aliases?: IngredientFoodAlias[];
|
||||
id: string;
|
||||
label?: MultiPurposeLabelSummary;
|
||||
createdAt?: string;
|
||||
updateAt?: string;
|
||||
}
|
||||
export interface IngredientFoodAlias {
|
||||
name: string;
|
||||
}
|
||||
export interface MultiPurposeLabelSummary {
|
||||
name: string;
|
||||
color?: string;
|
||||
|
@ -304,11 +328,16 @@ export interface MultiPurposeLabelSummary {
|
|||
}
|
||||
export interface CreateIngredientFood {
|
||||
name: string;
|
||||
pluralName?: string;
|
||||
description?: string;
|
||||
extras?: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
labelId?: string;
|
||||
aliases?: CreateIngredientFoodAlias[];
|
||||
}
|
||||
export interface CreateIngredientFoodAlias {
|
||||
name: string;
|
||||
}
|
||||
export interface ShoppingListCreate {
|
||||
name?: string;
|
||||
|
|
|
@ -465,7 +465,7 @@ export interface ScrapeRecipe {
|
|||
export interface ScrapeRecipeTest {
|
||||
url: string;
|
||||
}
|
||||
export interface SlugResponse { }
|
||||
export interface SlugResponse {}
|
||||
export interface TagIn {
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
/* 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 interface ErrorResponse {
|
||||
|
@ -19,6 +20,7 @@ export interface PaginationQuery {
|
|||
page?: number;
|
||||
perPage?: number;
|
||||
orderBy?: string;
|
||||
orderByNullPosition?: OrderByNullPosition;
|
||||
orderDirection?: OrderDirection & string;
|
||||
queryFilter?: string;
|
||||
paginationSeed?: string;
|
||||
|
|
|
@ -7,6 +7,18 @@
|
|||
'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-toolbar width="100%" color="primary" class="d-flex justify-center mb-4" dark>
|
||||
<v-toolbar-title class="headline text-h4"> Mealie </v-toolbar-title>
|
||||
|
@ -101,12 +113,14 @@
|
|||
</template>
|
||||
|
||||
<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 { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||
import { useAppInfo } from "~/composables/api";
|
||||
import { usePasswordField } from "~/composables/use-passwords";
|
||||
import { alert } from "~/composables/use-toast";
|
||||
import { useAsyncKey } from "~/composables/use-utils";
|
||||
import { AppStartupInfo } from "~/lib/api/types/admin";
|
||||
|
||||
export default defineComponent({
|
||||
layout: "blank",
|
||||
|
@ -115,7 +129,7 @@ export default defineComponent({
|
|||
const isDark = useDark();
|
||||
|
||||
const router = useRouter();
|
||||
const { $auth, i18n } = useContext();
|
||||
const { $auth, i18n, $axios } = useContext();
|
||||
const { loggedIn } = useLoggedInState();
|
||||
const groupSlug = computed(() => $auth.user?.groupSlug);
|
||||
|
||||
|
@ -133,6 +147,13 @@ export default defineComponent({
|
|||
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 appInfo = useAppInfo();
|
||||
|
@ -182,6 +203,7 @@ export default defineComponent({
|
|||
passwordIcon,
|
||||
inputType,
|
||||
togglePasswordShow,
|
||||
isFirstLogin
|
||||
};
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue