diff --git a/app.go b/app.go index e950681..60c02b3 100644 --- a/app.go +++ b/app.go @@ -117,6 +117,12 @@ func (a *App) routeSignIn(c ufx.Context) { } user.PasswordDigest = "" + // must not blocked + if user.IsBlocked { + halt.String("blocked", halt.WithBadRequest()) + return + } + // delete history tokens rg.Must(db.Token.Where(db.Token.UserID.Eq(user.ID), db.Token.CreatedAt.Lte(time.Now().Add(-time.Hour*24*7))).Delete()) @@ -451,9 +457,34 @@ func (a *App) routeGrantedItems(c ufx.Context) { c.JSON(map[string]any{"granted_items": grantedItems}) } +func (a *App) routeUpdatePassword(c ufx.Context) { + _, u := a.requireUser(c) + + var data struct { + OldPassword string `json:"old_password" validate:"required"` + NewPassword string `json:"new_password" validate:"required,min=6"` + } + + c.Bind(&data) + + if !u.CheckPassword(data.OldPassword) { + halt.String("invalid old password", halt.WithBadRequest()) + return + } + + u.SetPassword(data.NewPassword) + + db := dao.Use(a.db) + + rg.Must(db.User.Where(db.User.ID.Eq(u.ID)).UpdateColumnSimple(db.User.PasswordDigest.Value(u.PasswordDigest))) + + c.JSON(map[string]any{}) +} + func InstallAppToRouter(a *App, ur ufx.Router) { ur.HandleFunc("/backend/sign_in", a.routeSignIn) ur.HandleFunc("/backend/sign_out", a.routeSignOut) + ur.HandleFunc("/backend/update_password", a.routeUpdatePassword) ur.HandleFunc("/backend/current_user", a.routeCurrentUser) ur.HandleFunc("/backend/granted_items", a.routeGrantedItems) ur.HandleFunc("/backend/keys", a.routeListKeys) diff --git a/ui/components/skeleton/dashboard.vue b/ui/components/skeleton/dashboard.vue index 8c2d723..ea53533 100644 --- a/ui/components/skeleton/dashboard.vue +++ b/ui/components/skeleton/dashboard.vue @@ -24,7 +24,7 @@ const links = [ to: { name: "dashboard-servers" }, }, { - label: "Users", + label: $t('users.title'), icon: "i-mdi-account-multiple", to: { name: "dashboard-users" }, }, @@ -33,12 +33,12 @@ const links = [ ], [ { - label: "SSH Keys", + label: $t('ssh_keys.title'), icon: "i-mdi-key-chain", to: { name: "dashboard-profile-keys" }, }, { - label: "Profile", + label: $t('profile.title'), icon: "i-mdi-account-circle", to: { name: "dashboard-profile" }, }, diff --git a/ui/pages/dashboard/index.vue b/ui/pages/dashboard/index.vue index 4b8eaf2..86f9b8e 100644 --- a/ui/pages/dashboard/index.vue +++ b/ui/pages/dashboard/index.vue @@ -37,7 +37,7 @@ function expandServerUser(s: string): string { diff --git a/ui/pages/dashboard/profile/index.vue b/ui/pages/dashboard/profile/index.vue index aa88c7f..bd61f8e 100644 --- a/ui/pages/dashboard/profile/index.vue +++ b/ui/pages/dashboard/profile/index.vue @@ -1,23 +1,27 @@ diff --git a/ui/pages/dashboard/profile/keys/index.vue b/ui/pages/dashboard/profile/keys/index.vue index d15ac90..f7b1cca 100644 --- a/ui/pages/dashboard/profile/keys/index.vue +++ b/ui/pages/dashboard/profile/keys/index.vue @@ -2,6 +2,8 @@ import type { FormError, FormSubmitEvent } from "#ui/types"; import { guardWorking } from "~/composables/error"; +const { $t } = useNuxtApp(); + definePageMeta({ middleware: ["auth"], }); @@ -9,11 +11,11 @@ definePageMeta({ const columns = [ { key: "display_name", - label: "Name", + label: $t('common.ssh_key_display_name'), }, { key: "id", - label: "Fingerprint", + label: $t('common.ssh_key_id'), }, { key: "actions", @@ -73,23 +75,24 @@ async function onSubmit(event: FormSubmitEvent) {