Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to reset own password #289

Merged
merged 12 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Fix dropdown clickable areas - #281 by @dominik-zeglen
- Use eslint - #285 by @dominik-zeglen
- Enforce using "name" property in style hooks - #288 by @dominik-zeglen
- Add ability to reset own password - #289 by @dominik-zeglen

## 2.0.0

Expand Down
58 changes: 57 additions & 1 deletion locale/messages.pot
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2019-11-26T14:34:48.426Z\n"
"POT-Creation-Date: 2019-12-04T10:13:32.661Z\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -1855,6 +1855,14 @@ msgctxt "description"
msgid "Category name"
msgstr ""

#: build/locale/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.json
#. [src.staff.components.StaffPasswordResetDialog.2521568990] - dialog header
#. defaultMessage is:
#. Change Password
msgctxt "dialog header"
msgid "Change Password"
msgstr ""

#: build/locale/src/staff/components/StaffProperties/StaffProperties.json
#. [src.staff.components.StaffProperties.2771097267] - button
#. defaultMessage is:
Expand All @@ -1863,6 +1871,14 @@ msgctxt "button"
msgid "Change photo"
msgstr ""

#: build/locale/src/staff/components/StaffPassword/StaffPassword.json
#. [src.staff.components.StaffPassword.1434811103] - utton
#. defaultMessage is:
#. Change your password
msgctxt " utton"
msgid "Change your password"
msgstr ""

#: build/locale/src/products/components/ProductPricing/ProductPricing.json
#. [src.products.components.ProductPricing.3015886868]
#. defaultMessage is:
Expand Down Expand Up @@ -4911,6 +4927,14 @@ msgctxt "description"
msgid "New Password"
msgstr ""

#: build/locale/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.json
#. [src.staff.components.StaffPasswordResetDialog.1254879564] - input label
#. defaultMessage is:
#. New Password
msgctxt "input label"
msgid "New Password"
msgstr ""

#: build/locale/src/products/views/ProductCreate.json
#. [src.products.views.1591632382] - page header
#. defaultMessage is:
Expand All @@ -4927,6 +4951,14 @@ msgctxt "variant name"
msgid "New Variant"
msgstr ""

#: build/locale/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.json
#. [src.staff.components.StaffPasswordResetDialog.1651415182]
#. defaultMessage is:
#. New password must be at least 8 characters long
msgctxt "description"
msgid "New password must be at least 8 characters long"
msgstr ""

#: build/locale/src/taxes/components/CountryTaxesPage/CountryTaxesPage.json
#. [src.taxes.components.CountryTaxesPage.1451721797] - tax rate
#. defaultMessage is:
Expand Down Expand Up @@ -5947,6 +5979,14 @@ msgctxt "description"
msgid "Password"
msgstr ""

#: build/locale/src/staff/components/StaffPassword/StaffPassword.json
#. [src.staff.components.StaffPassword.2237029987] - header
#. defaultMessage is:
#. Password
msgctxt "header"
msgid "Password"
msgstr ""

#: build/locale/src/auth/components/NewPasswordPage/NewPasswordPage.json
#. [src.auth.components.NewPasswordPage.4253911811]
#. defaultMessage is:
Expand Down Expand Up @@ -6215,6 +6255,14 @@ msgctxt "previous step, button"
msgid "Previous"
msgstr ""

#: build/locale/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.json
#. [src.staff.components.StaffPasswordResetDialog.53359254] - input label
#. defaultMessage is:
#. Previous Password
msgctxt "input label"
msgid "Previous Password"
msgstr ""

#: build/locale/src/categories/components/CategoryProductList/CategoryProductList.json
#. [src.categories.components.CategoryProductList.1134347598] - product price
#. defaultMessage is:
Expand Down Expand Up @@ -9667,6 +9715,14 @@ msgctxt "description"
msgid "Yes"
msgstr ""

#: build/locale/src/staff/components/StaffPassword/StaffPassword.json
#. [src.staff.components.StaffPassword.1274006906]
#. defaultMessage is:
#. You should change your password every month to avoid security issues.
msgctxt "description"
msgid "You should change your password every month to avoid security issues."
msgstr ""

#: build/locale/src/products/components/ProductVariantCreateDialog/ProductVariantCreateSummary.json
#. [src.products.components.ProductVariantCreateDialog.1009678918] - header
#. defaultMessage is:
Expand Down
9 changes: 9 additions & 0 deletions src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { PermissionEnum } from "../../../types/globalTypes";
import { StaffMemberDetails_user } from "../../types/StaffMemberDetails";
import StaffPreferences from "../StaffPreferences";
import StaffProperties from "../StaffProperties/StaffProperties";
import StaffPassword from "../StaffPassword/StaffPassword";

interface FormData {
hasFullAccess: boolean;
Expand All @@ -39,6 +40,7 @@ export interface StaffDetailsPageProps {
saveButtonBarState: ConfirmButtonTransitionState;
staffMember: StaffMemberDetails_user;
onBack: () => void;
onChangePassword: () => void;
onDelete: () => void;
onImageDelete: () => void;
onSubmit: (data: FormData) => void;
Expand All @@ -55,6 +57,7 @@ const StaffDetailsPage: React.FC<StaffDetailsPageProps> = ({
saveButtonBarState,
staffMember,
onBack,
onChangePassword,
onDelete,
onImageDelete,
onImageUpload,
Expand Down Expand Up @@ -100,6 +103,12 @@ const StaffDetailsPage: React.FC<StaffDetailsPageProps> = ({
onImageUpload={onImageUpload}
onImageDelete={onImageDelete}
/>
{canEditPreferences && (
<>
<CardSpacer />
<StaffPassword onChangePassword={onChangePassword} />
</>
)}
</div>
<div>
{canEditPreferences && (
Expand Down
43 changes: 43 additions & 0 deletions src/staff/components/StaffPassword/StaffPassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
import { FormattedMessage, useIntl } from "react-intl";

import CardTitle from "@saleor/components/CardTitle";

interface StaffPasswordProps {
onChangePassword: () => void;
}

const StaffPassword: React.FC<StaffPasswordProps> = ({ onChangePassword }) => {
const intl = useIntl();

return (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Password",
description: "header"
})}
toolbar={
<Button color="primary" onClick={onChangePassword}>
<FormattedMessage
defaultMessage="Change your password"
description=" utton"
dominik-zeglen marked this conversation as resolved.
Show resolved Hide resolved
/>
</Button>
}
/>
<CardContent>
<Typography>
<FormattedMessage defaultMessage="You should change your password every month to avoid security issues." />
</Typography>
</CardContent>
</Card>
);
};

StaffPassword.displayName = "StaffPassword";
export default StaffPassword;
2 changes: 2 additions & 0 deletions src/staff/components/StaffPassword/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./StaffPassword";
export * from "./StaffPassword";
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from "react";
import Button from "@material-ui/core/Button";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import TextField from "@material-ui/core/TextField";
import DialogTitle from "@material-ui/core/DialogTitle";
import { FormattedMessage, useIntl } from "react-intl";

import { DialogProps, UserError } from "@saleor/types";
import { buttonMessages } from "@saleor/intl";
import Form from "@saleor/components/Form";
import ConfirmButton, {
ConfirmButtonTransitionState
} from "@saleor/components/ConfirmButton";
import FormSpacer from "@saleor/components/FormSpacer";
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";

interface StaffPasswordResetDialogFormData {
newPassword: string;
oldPassword: string;
}
export interface StaffPasswordResetDialogProps extends DialogProps {
confirmButtonState: ConfirmButtonTransitionState;
errors: UserError[];
onSubmit: (data: StaffPasswordResetDialogFormData) => void;
}

const initialForm: StaffPasswordResetDialogFormData = {
newPassword: "",
oldPassword: ""
};

const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
confirmButtonState,
errors: apiErrors,
open,
onClose,
onSubmit
}) => {
const intl = useIntl();
const dialogErrors = useModalDialogErrors(apiErrors, open);

return (
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
<DialogTitle>
<FormattedMessage
defaultMessage="Change Password"
description="dialog header"
/>
</DialogTitle>
<Form errors={dialogErrors} initial={initialForm} onSubmit={onSubmit}>
{({ change, data, errors, submit }) => (
<>
<DialogContent>
<TextField
error={!!errors.oldPassword}
fullWidth
helperText={errors.oldPassword}
label={intl.formatMessage({
defaultMessage: "Previous Password",
description: "input label"
})}
name="oldPassword"
type="password"
onChange={change}
/>
<FormSpacer />
<TextField
error={!!errors.newPassword}
fullWidth
helperText={
errors.newPassword ||
intl.formatMessage({
defaultMessage:
"New password must be at least 8 characters long"
})
}
label={intl.formatMessage({
defaultMessage: "New Password",
description: "input label"
})}
name="newPassword"
type="password"
onChange={change}
/>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>
<FormattedMessage {...buttonMessages.back} />
</Button>
<ConfirmButton
disabled={!(data.newPassword.length >= 8)}
dominik-zeglen marked this conversation as resolved.
Show resolved Hide resolved
transitionState={confirmButtonState}
color="primary"
variant="contained"
type="submit"
onClick={submit}
>
<FormattedMessage {...buttonMessages.save} />
</ConfirmButton>
</DialogActions>
</>
)}
</Form>
</Dialog>
);
};

StaffPasswordResetDialog.displayName = "StaffPasswordResetDialog";
export default StaffPasswordResetDialog;
2 changes: 2 additions & 0 deletions src/staff/components/StaffPasswordResetDialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./StaffPasswordResetDialog";
export * from "./StaffPasswordResetDialog";
20 changes: 20 additions & 0 deletions src/staff/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import gql from "graphql-tag";

import makeMutation from "@saleor/hooks/makeMutation";
import { TypedMutation } from "../mutations";
import { staffMemberDetailsFragment } from "./queries";
import { StaffAvatarDelete } from "./types/StaffAvatarDelete";
Expand All @@ -19,6 +20,10 @@ import {
StaffMemberUpdate,
StaffMemberUpdateVariables
} from "./types/StaffMemberUpdate";
import {
ChangeStaffPassword,
ChangeStaffPasswordVariables
} from "./types/ChangeStaffPassword";

const staffMemberAddMutation = gql`
${staffMemberDetailsFragment}
Expand Down Expand Up @@ -114,3 +119,18 @@ export const TypedStaffAvatarDeleteMutation = TypedMutation<
StaffAvatarDelete,
StaffMemberDeleteVariables
>(staffAvatarDeleteMutation);

const changeStaffPassword = gql`
mutation ChangeStaffPassword($newPassword: String!, $oldPassword: String!) {
passwordChange(newPassword: $newPassword, oldPassword: $oldPassword) {
errors {
field
message
}
}
}
`;
export const useChangeStaffPassword = makeMutation<
ChangeStaffPassword,
ChangeStaffPasswordVariables
>(changeStaffPassword);
27 changes: 27 additions & 0 deletions src/staff/types/ChangeStaffPassword.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* tslint:disable */
/* eslint-disable */
// This file was automatically generated and should not be edited.

// ====================================================
// GraphQL mutation operation: ChangeStaffPassword
// ====================================================

export interface ChangeStaffPassword_passwordChange_errors {
__typename: "Error";
field: string | null;
message: string | null;
}

export interface ChangeStaffPassword_passwordChange {
__typename: "PasswordChange";
errors: ChangeStaffPassword_passwordChange_errors[] | null;
}

export interface ChangeStaffPassword {
passwordChange: ChangeStaffPassword_passwordChange | null;
}

export interface ChangeStaffPasswordVariables {
newPassword: string;
oldPassword: string;
}
5 changes: 4 additions & 1 deletion src/staff/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export const staffListUrl = (params?: StaffListUrlQueryParams) =>
staffListPath + "?" + stringifyQs(params);

export const staffMemberDetailsPath = (id: string) => urlJoin(staffSection, id);
export type StaffMemberDetailsUrlDialog = "remove" | "remove-avatar";
export type StaffMemberDetailsUrlDialog =
| "change-password"
| "remove"
| "remove-avatar";
export type StaffMemberDetailsUrlQueryParams = Dialog<
StaffMemberDetailsUrlDialog
>;
Expand Down
Loading