mirror of
https://github.com/strapi/strapi.git
synced 2025-09-07 15:49:24 +00:00
Add new user EE for SSO
Signed-off-by: HichamELBSI <elabbassih@gmail.com>
This commit is contained in:
parent
189740c92c
commit
3d2538d72e
@ -0,0 +1,47 @@
|
||||
// This component is a work in progress
|
||||
// It's made to be used when the users API is ready
|
||||
import React from 'react';
|
||||
import { Flex, Text } from '@buffetjs/core';
|
||||
import { Duplicate } from '@buffetjs/icons';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import IconWrapper from './IconWrapper';
|
||||
import Envelope from './Envelope';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const LinkNotification = ({ link, description }) => {
|
||||
const handleCopy = () => {
|
||||
strapi.notification.toggle({ type: 'info', message: { id: 'notification.link-copied' } });
|
||||
};
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<IconWrapper>
|
||||
<Envelope />
|
||||
</IconWrapper>
|
||||
<Flex flexDirection="column" justifyContent="center">
|
||||
<Text fontWeight="semiBold" color="black" fontSize="md" lineHeight="18px">
|
||||
{link}
|
||||
<CopyToClipboard onCopy={handleCopy} text={link}>
|
||||
<Duplicate fill="#8B91A0" className="icon-duplicate" />
|
||||
</CopyToClipboard>
|
||||
</Text>
|
||||
<Text fontWeight="regular" color="grey" fontSize="sm" lineHeight="18px">
|
||||
{description}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
LinkNotification.defaultProps = {
|
||||
link: '',
|
||||
description: '',
|
||||
};
|
||||
|
||||
LinkNotification.propTypes = {
|
||||
link: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
};
|
||||
|
||||
export default LinkNotification;
|
@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Padded } from '@buffetjs/core';
|
||||
import { Label, Description as BaseDescription } from '@buffetjs/styles';
|
||||
import { Col } from 'reactstrap';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import SelectRoles from '../SelectRoles';
|
||||
|
||||
const Description = styled(BaseDescription)`
|
||||
font-size: ${({ theme }) => theme.main.sizes.fonts.md};
|
||||
line-height: normal;
|
||||
`;
|
||||
|
||||
const RolesSelectComponent = ({ isDisabled, value, error, onChange }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<Col xs="6">
|
||||
<Padded bottom size="xs">
|
||||
<Label style={{ display: 'block' }} htmlFor="roles">
|
||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.roles' })}
|
||||
</Label>
|
||||
</Padded>
|
||||
<SelectRoles
|
||||
isDisabled={isDisabled}
|
||||
name="roles"
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
error={error}
|
||||
/>
|
||||
<Description>
|
||||
{formatMessage({
|
||||
id: 'app.components.Users.ModalCreateBody.block-title.roles.description',
|
||||
})}
|
||||
</Description>
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
RolesSelectComponent.defaultProps = {
|
||||
value: null,
|
||||
error: null,
|
||||
};
|
||||
RolesSelectComponent.propTypes = {
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
value: PropTypes.array,
|
||||
error: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default RolesSelectComponent;
|
@ -0,0 +1,74 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ModalSection } from 'strapi-helper-plugin';
|
||||
import { Padded } from '@buffetjs/core';
|
||||
import { Row } from 'reactstrap';
|
||||
import { useIntl } from 'react-intl';
|
||||
import loginSettingsForm from 'ee_else_ce/components/Users/ModalCreateBody/utils/loginSettingsForm';
|
||||
|
||||
import Input from '../../SizedInput';
|
||||
import Wrapper from '../ModalCreateBody/Wrapper';
|
||||
|
||||
const LoginModalSection = ({ isDisabled, modifiedData, onChange, formErrors }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<ModalSection>
|
||||
<Wrapper>
|
||||
<Padded top size="smd">
|
||||
<Row>
|
||||
{Object.keys(loginSettingsForm).map(inputName => {
|
||||
if (loginSettingsForm[inputName].Component) {
|
||||
const { Component } = loginSettingsForm[inputName];
|
||||
|
||||
return (
|
||||
<Component
|
||||
key={inputName}
|
||||
value={modifiedData[inputName]}
|
||||
onChange={onChange}
|
||||
error={formErrors[inputName]}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
{...loginSettingsForm[inputName]}
|
||||
key={inputName}
|
||||
description={formatMessage({ id: loginSettingsForm[inputName].description })}
|
||||
type={loginSettingsForm[inputName].type}
|
||||
disabled={isDisabled}
|
||||
name={inputName}
|
||||
onChange={onChange}
|
||||
value={modifiedData.useSSORegistration}
|
||||
error={formErrors.useSSORegistration}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</Padded>
|
||||
</Wrapper>
|
||||
</ModalSection>
|
||||
);
|
||||
};
|
||||
|
||||
LoginModalSection.defaultProps = {
|
||||
isDisabled: false,
|
||||
formErrors: {},
|
||||
};
|
||||
|
||||
LoginModalSection.propTypes = {
|
||||
isDisabled: PropTypes.bool,
|
||||
modifiedData: PropTypes.shape({
|
||||
roles: PropTypes.array,
|
||||
useSSORegistration: PropTypes.bool,
|
||||
}).isRequired,
|
||||
formErrors: PropTypes.shape({
|
||||
roles: PropTypes.array,
|
||||
useSSORegistration: PropTypes.bool,
|
||||
}),
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default LoginModalSection;
|
@ -1,50 +1,22 @@
|
||||
// This component is a work in progress
|
||||
// It's made to be used when the users API is ready
|
||||
import React from 'react';
|
||||
import { Flex, Text } from '@buffetjs/core';
|
||||
import { Duplicate } from '@buffetjs/icons';
|
||||
import { useIntl } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import LinkNotification from '../LinkNotification';
|
||||
import basename from '../../../utils/basename';
|
||||
import IconWrapper from './IconWrapper';
|
||||
import Envelope from './Envelope';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const MagicLink = ({ registrationToken }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const handleCopy = () => {
|
||||
strapi.notification.toggle({ type: 'info', message: { id: 'notification.link-copied' } });
|
||||
};
|
||||
|
||||
const MagicLink = ({ registrationToken, description }) => {
|
||||
const link = `${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<IconWrapper>
|
||||
<Envelope />
|
||||
</IconWrapper>
|
||||
<Flex flexDirection="column" justifyContent="center">
|
||||
<Text fontWeight="semiBold" color="black" fontSize="md" lineHeight="18px">
|
||||
{link}
|
||||
<CopyToClipboard onCopy={handleCopy} text={link}>
|
||||
<Duplicate fill="#8B91A0" className="icon-duplicate" />
|
||||
</CopyToClipboard>
|
||||
</Text>
|
||||
<Text fontWeight="regular" color="grey" fontSize="sm" lineHeight="18px">
|
||||
{formatMessage({ id: 'app.components.Users.MagicLink.connect' })}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Wrapper>
|
||||
);
|
||||
return <LinkNotification link={link} description={description} />;
|
||||
};
|
||||
|
||||
MagicLink.defaultProps = {
|
||||
registrationToken: '',
|
||||
description: '',
|
||||
};
|
||||
|
||||
MagicLink.propTypes = {
|
||||
registrationToken: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
};
|
||||
|
||||
export default MagicLink;
|
||||
|
@ -1,19 +1,20 @@
|
||||
import React, { forwardRef, useReducer, useImperativeHandle, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { BaselineAlignment, ModalSection, request } from 'strapi-helper-plugin';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { get } from 'lodash';
|
||||
import { Padded, Text } from '@buffetjs/core';
|
||||
import { Col, Row } from 'reactstrap';
|
||||
import { Row } from 'reactstrap';
|
||||
import MagicLink from 'ee_else_ce/components/Users/MagicLink';
|
||||
|
||||
import checkFormValidity from '../../../utils/checkFormValidity';
|
||||
import SelectRoles from '../SelectRoles';
|
||||
import form from './utils/form';
|
||||
import schema from './utils/schema';
|
||||
import { initialState, reducer } from './reducer';
|
||||
import init from './init';
|
||||
import Input from '../../SizedInput';
|
||||
import Wrapper from './Wrapper';
|
||||
import MagicLink from '../MagicLink';
|
||||
import LoginModalSection from '../LoginModalSection';
|
||||
|
||||
// This component accepts a ref so we can have access to the submit handler.
|
||||
const ModalCreateBody = forwardRef(
|
||||
@ -21,6 +22,7 @@ const ModalCreateBody = forwardRef(
|
||||
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
||||
const { formErrors, modifiedData } = reducerState;
|
||||
const buttonSubmitRef = useRef(null);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
submit: () => {
|
||||
@ -86,15 +88,13 @@ const ModalCreateBody = forwardRef(
|
||||
<ModalSection>
|
||||
<Padded top size="18px">
|
||||
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
|
||||
<FormattedMessage id="app.components.Users.ModalCreateBody.block-title.details">
|
||||
{txt => txt}
|
||||
</FormattedMessage>
|
||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.details' })}
|
||||
</Text>
|
||||
</Padded>
|
||||
</ModalSection>
|
||||
<ModalSection>
|
||||
<Wrapper>
|
||||
<Padded top size="20px">
|
||||
<Padded top size="smd">
|
||||
<Row>
|
||||
{Object.keys(form).map((inputName, i) => (
|
||||
<Input
|
||||
@ -115,29 +115,16 @@ const ModalCreateBody = forwardRef(
|
||||
<ModalSection>
|
||||
<Padded top size="3px">
|
||||
<Text fontSize="xs" color="grey" fontWeight="bold" textTransform="uppercase">
|
||||
<FormattedMessage id="app.components.Users.ModalCreateBody.block-title.roles">
|
||||
{txt => txt}
|
||||
</FormattedMessage>
|
||||
{formatMessage({ id: 'app.components.Users.ModalCreateBody.block-title.login' })}
|
||||
</Text>
|
||||
</Padded>
|
||||
</ModalSection>
|
||||
<ModalSection>
|
||||
<Wrapper>
|
||||
<Padded top size="12px">
|
||||
<Row>
|
||||
<Col xs="6">
|
||||
<SelectRoles
|
||||
isDisabled={isDisabled}
|
||||
name="roles"
|
||||
onChange={handleChange}
|
||||
value={modifiedData.roles}
|
||||
error={formErrors.roles}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Padded>
|
||||
</Wrapper>
|
||||
</ModalSection>
|
||||
<LoginModalSection
|
||||
modifiedData={modifiedData}
|
||||
onChange={handleChange}
|
||||
formErrors={formErrors}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
<button type="submit" style={{ display: 'none' }} ref={buttonSubmitRef}>
|
||||
hidden button to use the native form event
|
||||
</button>
|
||||
|
@ -1,18 +1,14 @@
|
||||
/* eslint-disable consistent-return */
|
||||
import produce from 'immer';
|
||||
import { set } from 'lodash';
|
||||
import formDataModel from 'ee_else_ce/components/Users/ModalCreateBody/utils/formDataModel';
|
||||
|
||||
const initialState = {
|
||||
formErrors: {},
|
||||
modifiedData: {
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
email: '',
|
||||
roles: [],
|
||||
},
|
||||
modifiedData: formDataModel,
|
||||
};
|
||||
|
||||
const reducer = (state, action) =>
|
||||
const reducer = (state = initialState, action) =>
|
||||
produce(state, draftState => {
|
||||
switch (action.type) {
|
||||
case 'ON_CHANGE': {
|
||||
|
@ -0,0 +1,8 @@
|
||||
const formDataModel = {
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
email: '',
|
||||
roles: [],
|
||||
};
|
||||
|
||||
export default formDataModel;
|
@ -0,0 +1,10 @@
|
||||
import RolesSelectComponent from '../../LoginModalSection/RolesSelectComponent';
|
||||
|
||||
const loginSettingsForm = {
|
||||
roles: {
|
||||
label: 'Settings.permissions.users.form.firstname',
|
||||
Component: RolesSelectComponent,
|
||||
},
|
||||
};
|
||||
|
||||
export default loginSettingsForm;
|
@ -19,6 +19,7 @@ const SelectRoles = ({ error, isDisabled, name, onChange, value }) => {
|
||||
return (
|
||||
<>
|
||||
<Select
|
||||
name={name}
|
||||
components={{
|
||||
ClearIndicator,
|
||||
DropdownIndicator,
|
||||
|
@ -32,15 +32,14 @@ const ModalForm = ({ isOpen, onClosed, onToggle }) => {
|
||||
};
|
||||
|
||||
const handleClosed = () => {
|
||||
setStep('create');
|
||||
|
||||
// Fetch data only if the user has submitted a new entry
|
||||
// We can use the registrationToken to know this
|
||||
if (registrationToken) {
|
||||
if (registrationToken || currentStep === 'magic-link') {
|
||||
onClosed();
|
||||
}
|
||||
|
||||
// Reset the state so we know that the user has created a new entry when there is a registrationToken
|
||||
setStep('create');
|
||||
setShowBody(false);
|
||||
setRegistrationToken(null);
|
||||
};
|
||||
|
@ -100,6 +100,8 @@
|
||||
"Settings.permissions.users.form.email": "Email",
|
||||
"Settings.permissions.users.form.firstname": "First name",
|
||||
"Settings.permissions.users.form.lastname": "Last name",
|
||||
"Settings.permissions.users.form.sso": "Connect with SSO",
|
||||
"Settings.permissions.users.form.sso.description": "When enabled (ON), users can login via SSO",
|
||||
"Settings.permissions.users.listview.header.description.plural": "{number} users found",
|
||||
"Settings.permissions.users.listview.header.description.singular": "{number} user found",
|
||||
"Settings.permissions.users.listview.header.title": "Users",
|
||||
@ -240,8 +242,11 @@
|
||||
"app.components.UpgradePlanModal.text-power": "Unlock the full power",
|
||||
"app.components.UpgradePlanModal.text-strapi": "of Strapi by upgrading your plan to the",
|
||||
"app.components.Users.MagicLink.connect": "Send this link to the user for them to connect.",
|
||||
"app.components.Users.MagicLink.connect.sso": "Send this link to the user, the first login can be mage via a SSO provider",
|
||||
"app.components.Users.ModalCreateBody.block-title.details": "Details",
|
||||
"app.components.Users.ModalCreateBody.block-title.roles": "User's roles",
|
||||
"app.components.Users.ModalCreateBody.block-title.roles.description": "Your user can have one or several roles",
|
||||
"app.components.Users.ModalCreateBody.block-title.login": "Login settings",
|
||||
"app.components.Users.SortPicker.button-label": "Sort by",
|
||||
"app.components.Users.SortPicker.sortby.email_asc": "Email (A to Z)",
|
||||
"app.components.Users.SortPicker.sortby.email_desc": "Email (Z to A)",
|
||||
@ -313,7 +318,7 @@
|
||||
"components.Input.error.validation.unique": "This value is already used.",
|
||||
"components.InputSelect.option.placeholder": "Choose here",
|
||||
"components.ListRow.empty": "There is no data to be shown.",
|
||||
"components.NotAllowedInput.text":"No permissions to see this field",
|
||||
"components.NotAllowedInput.text": "No permissions to see this field",
|
||||
"components.OverlayBlocker.description": "You're using a feature that needs the server to restart. Please wait until the server is up.",
|
||||
"components.OverlayBlocker.description.serverError": "The server should have restarted, please check your logs in the terminal.",
|
||||
"components.OverlayBlocker.title": "Waiting for restart...",
|
||||
|
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import LinkNotification from '../../../../../admin/src/components/Users/LinkNotification';
|
||||
import basename from '../../../../../admin/src/utils/basename';
|
||||
|
||||
const MagicLink = ({ registrationToken }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
if (registrationToken) {
|
||||
return (
|
||||
<LinkNotification
|
||||
link={`${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`}
|
||||
description={formatMessage({ id: 'app.components.Users.MagicLink.connect' })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<LinkNotification
|
||||
link={`${window.location.origin}${basename}`}
|
||||
description={formatMessage({ id: 'app.components.Users.MagicLink.connect.sso' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
MagicLink.defaultProps = {
|
||||
registrationToken: '',
|
||||
};
|
||||
|
||||
MagicLink.propTypes = {
|
||||
registrationToken: PropTypes.string,
|
||||
};
|
||||
|
||||
export default MagicLink;
|
@ -0,0 +1,14 @@
|
||||
import baseModel from '../../../../../../admin/src/components/Users/ModalCreateBody/utils/formDataModel';
|
||||
|
||||
const ssoInputsModel = ENABLED_EE_FEATURES.includes('sso')
|
||||
? {
|
||||
useSSORegistration: true,
|
||||
}
|
||||
: {};
|
||||
|
||||
const formDataModel = {
|
||||
...baseModel,
|
||||
...ssoInputsModel,
|
||||
};
|
||||
|
||||
export default formDataModel;
|
@ -0,0 +1,21 @@
|
||||
import baseForm from '../../../../../../admin/src/components/Users/ModalCreateBody/utils/loginSettingsForm';
|
||||
|
||||
const ssoInputs = ENABLED_EE_FEATURES.includes('sso')
|
||||
? {
|
||||
useSSORegistration: {
|
||||
label: 'Settings.permissions.users.form.sso',
|
||||
type: 'bool',
|
||||
validations: {
|
||||
required: true,
|
||||
},
|
||||
description: 'Settings.permissions.users.form.sso.description',
|
||||
},
|
||||
}
|
||||
: {};
|
||||
|
||||
const form = {
|
||||
...baseForm,
|
||||
...ssoInputs,
|
||||
};
|
||||
|
||||
export default form;
|
@ -15,7 +15,7 @@ module.exports = () => {
|
||||
const options = {
|
||||
backend: 'http://localhost:1337',
|
||||
publicPath: '/admin/',
|
||||
features: process.env.ENABLED_EE_FEATURES || [],
|
||||
features: process.env.ENABLED_EE_FEATURES || ['sso'],
|
||||
};
|
||||
|
||||
const args = {
|
||||
|
35
yarn.lock
35
yarn.lock
@ -4727,11 +4727,6 @@ base64-js@^1.0.2, base64-js@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
|
||||
base64url@3.x.x:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
|
||||
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
|
||||
|
||||
base@^0.11.1:
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
||||
@ -13928,11 +13923,6 @@ oauth-sign@^0.9.0, oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
oauth@0.9.x:
|
||||
version "0.9.15"
|
||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
||||
|
||||
object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
@ -14556,13 +14546,6 @@ pascalcase@^0.1.1:
|
||||
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
|
||||
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
|
||||
|
||||
passport-google-oauth2@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-google-oauth2/-/passport-google-oauth2-0.2.0.tgz#fc9ea59e7091f02e24fd16d6be9257ea982ebbc3"
|
||||
integrity sha512-62EdPtbfVdc55nIXi0p1WOa/fFMM8v/M8uQGnbcXA4OexZWCnfsEi3wo2buag+Is5oqpuHzOtI64JpHk0Xi5RQ==
|
||||
dependencies:
|
||||
passport-oauth2 "^1.1.2"
|
||||
|
||||
passport-local@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
|
||||
@ -14570,17 +14553,6 @@ passport-local@1.0.0:
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
|
||||
passport-oauth2@^1.1.2:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108"
|
||||
integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==
|
||||
dependencies:
|
||||
base64url "3.x.x"
|
||||
oauth "0.9.x"
|
||||
passport-strategy "1.x.x"
|
||||
uid2 "0.0.x"
|
||||
utils-merge "1.x.x"
|
||||
|
||||
passport-strategy@1.x.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
@ -19561,11 +19533,6 @@ uid-number@0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
|
||||
integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=
|
||||
|
||||
uid2@0.0.x:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
|
||||
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=
|
||||
|
||||
umask@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
|
||||
@ -19904,7 +19871,7 @@ utila@^0.4.0, utila@~0.4:
|
||||
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
|
||||
integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=
|
||||
|
||||
utils-merge@1.0.1, utils-merge@1.x.x:
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||
|
Loading…
x
Reference in New Issue
Block a user