feat(web): user profile (#1148)

* fix: allow updateUser for admin account

* feat: update user first/last name

* feat(web): change password
This commit is contained in:
Jason Rasmussen
2022-12-21 09:43:35 -05:00
committed by GitHub
parent 723a7c563f
commit 14db7a09e3
21 changed files with 615 additions and 22 deletions

View File

@@ -4,7 +4,7 @@
* Immich
* Immich API
*
* The version of the OpenAPI document: 1.38.2
* The version of the OpenAPI document: 1.39.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -481,6 +481,25 @@ export const AssetTypeEnum = {
export type AssetTypeEnum = typeof AssetTypeEnum[keyof typeof AssetTypeEnum];
/**
*
* @export
* @interface ChangePasswordDto
*/
export interface ChangePasswordDto {
/**
*
* @type {string}
* @memberof ChangePasswordDto
*/
'password': string;
/**
*
* @type {string}
* @memberof ChangePasswordDto
*/
'newPassword': string;
}
/**
*
* @export
@@ -4171,6 +4190,45 @@ export const AuthenticationApiAxiosParamCreator = function (configuration?: Conf
options: localVarRequestOptions,
};
},
/**
*
* @param {ChangePasswordDto} changePasswordDto
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
changePassword: async (changePasswordDto: ChangePasswordDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'changePasswordDto' is not null or undefined
assertParamExists('changePassword', 'changePasswordDto', changePasswordDto)
const localVarPath = `/auth/change-password`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication bearer required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(changePasswordDto, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @param {LoginCredentialDto} loginCredentialDto
@@ -4288,6 +4346,16 @@ export const AuthenticationApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.adminSignUp(signUpDto, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @param {ChangePasswordDto} changePasswordDto
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async changePassword(changePasswordDto: ChangePasswordDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.changePassword(changePasswordDto, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @param {LoginCredentialDto} loginCredentialDto
@@ -4335,6 +4403,15 @@ export const AuthenticationApiFactory = function (configuration?: Configuration,
adminSignUp(signUpDto: SignUpDto, options?: any): AxiosPromise<AdminSignupResponseDto> {
return localVarFp.adminSignUp(signUpDto, options).then((request) => request(axios, basePath));
},
/**
*
* @param {ChangePasswordDto} changePasswordDto
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
changePassword(changePasswordDto: ChangePasswordDto, options?: any): AxiosPromise<UserResponseDto> {
return localVarFp.changePassword(changePasswordDto, options).then((request) => request(axios, basePath));
},
/**
*
* @param {LoginCredentialDto} loginCredentialDto
@@ -4381,6 +4458,17 @@ export class AuthenticationApi extends BaseAPI {
return AuthenticationApiFp(this.configuration).adminSignUp(signUpDto, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @param {ChangePasswordDto} changePasswordDto
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AuthenticationApi
*/
public changePassword(changePasswordDto: ChangePasswordDto, options?: AxiosRequestConfig) {
return AuthenticationApiFp(this.configuration).changePassword(changePasswordDto, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @param {LoginCredentialDto} loginCredentialDto

View File

@@ -4,7 +4,7 @@
* Immich
* Immich API
*
* The version of the OpenAPI document: 1.38.2
* The version of the OpenAPI document: 1.39.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* Immich
* Immich API
*
* The version of the OpenAPI document: 1.38.2
* The version of the OpenAPI document: 1.39.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* Immich
* Immich API
*
* The version of the OpenAPI document: 1.38.2
* The version of the OpenAPI document: 1.39.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* Immich
* Immich API
*
* The version of the OpenAPI document: 1.38.2
* The version of the OpenAPI document: 1.39.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -1,27 +1,154 @@
<script lang="ts">
import { UserResponseDto } from '@api';
import {
notificationController,
NotificationType
} from '$lib/components/shared-components/notification/notification';
import { api, UserResponseDto } from '@api';
import { AxiosError } from 'axios';
import { fade } from 'svelte/transition';
import SettingAccordion from '../admin-page/settings/setting-accordion.svelte';
import SettingInputField, {
SettingInputFieldType
} from '../admin-page/settings/setting-input-field.svelte';
export let user: UserResponseDto;
const handleSaveProfile = async () => {
try {
const { data } = await api.userApi.updateUser({
id: user.id,
firstName: user.firstName,
lastName: user.lastName
});
Object.assign(user, data);
notificationController.show({
message: 'Saved profile',
type: NotificationType.Info
});
} catch (error) {
console.error('Error [user-profile] [updateProfile]', error);
notificationController.show({
message: 'Unable to save profile',
type: NotificationType.Error
});
}
};
let password = '';
let newPassword = '';
let confirmPassword = '';
const handleChangePassword = async () => {
try {
await api.authenticationApi.changePassword({
password,
newPassword
});
notificationController.show({
message: 'Updated password',
type: NotificationType.Info
});
password = '';
newPassword = '';
confirmPassword = '';
} catch (error: AxiosError | any) {
console.error('Error [user-profile] [changePassword]', error);
notificationController.show({
message: error?.response?.data?.message || 'Unable to change password',
type: NotificationType.Error
});
}
};
</script>
<SettingAccordion title="User profile" subtitle="Manage the user information">
<SettingAccordion title="User Profile" subtitle="View and manage your profile">
<section class="my-4">
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="First name"
bind:value={user.firstName}
required={true}
/>
<div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault>
<div class="flex flex-col gap-4 ml-4 mt-4">
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="User ID"
bind:value={user.id}
disabled={true}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="Last name"
bind:value={user.lastName}
required={true}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="Email"
bind:value={user.email}
disabled={true}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="First name"
bind:value={user.firstName}
required={true}
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label="Last name"
bind:value={user.lastName}
required={true}
/>
<div class="flex justify-end">
<button
type="submit"
on:click={() => handleSaveProfile()}
class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>Save
</button>
</div>
</div>
</form>
</div>
</section>
</SettingAccordion>
<SettingAccordion title="Password" subtitle="Change your password">
<section class="my-4">
<div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault>
<div class="flex flex-col gap-4 ml-4 mt-4">
<SettingInputField
inputType={SettingInputFieldType.PASSWORD}
label="Password"
bind:value={password}
required={true}
/>
<SettingInputField
inputType={SettingInputFieldType.PASSWORD}
label="New password"
bind:value={newPassword}
required={true}
/>
<SettingInputField
inputType={SettingInputFieldType.PASSWORD}
label="Confirm password"
bind:value={confirmPassword}
required={true}
/>
<div class="flex justify-end">
<button
type="submit"
disabled={!(password && newPassword && newPassword === confirmPassword)}
on:click={() => handleChangePassword()}
class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>Save
</button>
</div>
</div>
</form>
</div>
</section>
</SettingAccordion>