@unchainedshop/api 2.3.5 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api-index.js.map +1 -1
- package/lib/errors.d.ts +1 -0
- package/lib/errors.js +1 -0
- package/lib/errors.js.map +1 -1
- package/lib/express/createBulkImportMiddleware.js +1 -1
- package/lib/express/createBulkImportMiddleware.js.map +1 -1
- package/lib/express/createERCMetadataMiddleware.d.ts +1 -1
- package/lib/express/createERCMetadataMiddleware.js +1 -1
- package/lib/express/createERCMetadataMiddleware.js.map +1 -1
- package/lib/express/createSingleSignOnMiddleware.d.ts +1 -1
- package/lib/express/createSingleSignOnMiddleware.js +0 -1
- package/lib/express/createSingleSignOnMiddleware.js.map +1 -1
- package/lib/loaders/index.d.ts +1 -1
- package/lib/loaders/index.js.map +1 -1
- package/lib/locale-context.d.ts +1 -1
- package/lib/resolvers/mutations/accounts/impersonate.js +3 -3
- package/lib/resolvers/mutations/accounts/impersonate.js.map +1 -1
- package/lib/resolvers/mutations/accounts/stopImpersonation.d.ts +6 -0
- package/lib/resolvers/mutations/accounts/stopImpersonation.js +21 -0
- package/lib/resolvers/mutations/accounts/stopImpersonation.js.map +1 -0
- package/lib/resolvers/mutations/index.d.ts +16 -37
- package/lib/resolvers/mutations/index.js +17 -15
- package/lib/resolvers/mutations/index.js.map +1 -1
- package/lib/resolvers/mutations/payment/removePaymentCredentials.js.map +1 -1
- package/lib/resolvers/queries/index.d.ts +2 -0
- package/lib/resolvers/queries/index.js +2 -0
- package/lib/resolvers/queries/index.js.map +1 -1
- package/lib/resolvers/queries/users/impersonator.d.ts +2 -0
- package/lib/resolvers/queries/users/impersonator.js +12 -0
- package/lib/resolvers/queries/users/impersonator.js.map +1 -0
- package/lib/resolvers/type/delivery-provider-types.js.map +1 -1
- package/lib/resolvers/type/dispatch-types.js.map +1 -1
- package/lib/resolvers/type/order/order-delivery-discount-types.js.map +1 -1
- package/lib/resolvers/type/order/order-item-discount-types.js.map +1 -1
- package/lib/resolvers/type/order/order-item-types.js.map +1 -1
- package/lib/resolvers/type/order/order-payment-discount-types.js.map +1 -1
- package/lib/resolvers/type/order/order-types.js.map +1 -1
- package/lib/resolvers/type/payment/payment-provider-types.js.map +1 -1
- package/lib/resolvers/type/product/product-discount.js.map +1 -1
- package/lib/resolvers/type/product/product-types.js +3 -0
- package/lib/resolvers/type/product/product-types.js.map +1 -1
- package/lib/resolvers/type/stock-types.js.map +1 -1
- package/lib/resolvers/type/user-types.d.ts +7 -0
- package/lib/resolvers/type/user-types.js +16 -1
- package/lib/resolvers/type/user-types.js.map +1 -1
- package/lib/roles/all.js +16 -0
- package/lib/roles/all.js.map +1 -1
- package/lib/roles/index.js +16 -0
- package/lib/roles/index.js.map +1 -1
- package/lib/roles/loggedIn.js +3 -0
- package/lib/roles/loggedIn.js.map +1 -1
- package/lib/schema/mutation.js +5 -0
- package/lib/schema/mutation.js.map +1 -1
- package/lib/schema/query.js +4 -0
- package/lib/schema/query.js.map +1 -1
- package/lib/schema/types/product/bundle-product.js +1 -0
- package/lib/schema/types/product/bundle-product.js.map +1 -1
- package/lib/schema/types/product/configurable-product.js +1 -0
- package/lib/schema/types/product/configurable-product.js.map +1 -1
- package/lib/schema/types/product/plan-product.js +1 -0
- package/lib/schema/types/product/plan-product.js.map +1 -1
- package/lib/schema/types/product/product.js +1 -0
- package/lib/schema/types/product/product.js.map +1 -1
- package/lib/schema/types/product/simple-product.js +1 -0
- package/lib/schema/types/product/simple-product.js.map +1 -1
- package/lib/schema/types/product/tokenized-product.js +1 -0
- package/lib/schema/types/product/tokenized-product.js.map +1 -1
- package/lib/schema/types/user.js +2 -0
- package/lib/schema/types/user.js.map +1 -1
- package/lib/user-context.d.ts +1 -1
- package/package.json +13 -13
- package/src/api-index.ts +2 -2
- package/src/errors.ts +5 -0
- package/src/express/createBulkImportMiddleware.ts +1 -1
- package/src/express/createERCMetadataMiddleware.ts +2 -2
- package/src/express/createSingleSignOnMiddleware.ts +1 -1
- package/src/express/index.ts +1 -1
- package/src/loaders/index.ts +1 -1
- package/src/locale-context.ts +1 -1
- package/src/resolvers/mutations/accounts/impersonate.ts +3 -3
- package/src/resolvers/mutations/accounts/stopImpersonation.ts +31 -0
- package/src/resolvers/mutations/index.ts +21 -15
- package/src/resolvers/mutations/payment/removePaymentCredentials.ts +2 -3
- package/src/resolvers/queries/index.ts +2 -0
- package/src/resolvers/queries/users/impersonator.ts +19 -0
- package/src/resolvers/type/delivery-provider-types.ts +1 -1
- package/src/resolvers/type/dispatch-types.ts +1 -1
- package/src/resolvers/type/order/order-delivery-discount-types.ts +1 -1
- package/src/resolvers/type/order/order-item-discount-types.ts +1 -1
- package/src/resolvers/type/order/order-item-types.ts +1 -1
- package/src/resolvers/type/order/order-payment-discount-types.ts +1 -1
- package/src/resolvers/type/order/order-types.ts +1 -1
- package/src/resolvers/type/payment/payment-provider-types.ts +1 -1
- package/src/resolvers/type/product/product-discount.ts +1 -1
- package/src/resolvers/type/product/product-types.ts +3 -0
- package/src/resolvers/type/stock-types.ts +1 -1
- package/src/resolvers/type/user-types.ts +26 -0
- package/src/roles/all.ts +16 -0
- package/src/roles/index.ts +17 -0
- package/src/roles/loggedIn.ts +3 -0
- package/src/schema/mutation.ts +5 -0
- package/src/schema/query.ts +4 -0
- package/src/schema/types/product/bundle-product.ts +1 -0
- package/src/schema/types/product/configurable-product.ts +1 -0
- package/src/schema/types/product/plan-product.ts +1 -0
- package/src/schema/types/product/product.ts +1 -0
- package/src/schema/types/product/simple-product.ts +1 -0
- package/src/schema/types/product/tokenized-product.ts +1 -0
- package/src/schema/types/user.ts +2 -0
- package/src/user-context.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { IncomingMessage } from 'http';
|
|
2
|
+
import path from 'path';
|
|
1
3
|
import { createLogger } from '@unchainedshop/logger';
|
|
2
4
|
import { UnchainedContextResolver } from '@unchainedshop/types/api.js';
|
|
3
5
|
import { systemLocale } from '@unchainedshop/utils';
|
|
4
|
-
import { IncomingMessage } from 'http';
|
|
5
6
|
import localePkg from 'locale';
|
|
6
|
-
import path from 'path';
|
|
7
7
|
|
|
8
8
|
const { Locale } = localePkg;
|
|
9
9
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
+
import { IncomingMessage } from 'http';
|
|
2
3
|
import { createLogger } from '@unchainedshop/logger';
|
|
3
4
|
import { UnchainedContextResolver } from '@unchainedshop/types/api.js';
|
|
4
5
|
import { UnchainedCore } from '@unchainedshop/types/core.js';
|
|
5
|
-
import { IncomingMessage } from 'http';
|
|
6
6
|
import cookie from 'cookie';
|
|
7
7
|
|
|
8
8
|
const { ROOT_URL, NODE_ENV, UNCHAINED_CLOUD_ENDPOINT } = process.env;
|
package/src/express/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { UnchainedCore } from '@unchainedshop/types/core.js';
|
|
2
1
|
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
2
|
+
import { UnchainedCore } from '@unchainedshop/types/core.js';
|
|
3
3
|
import { ApolloServer } from '@apollo/server';
|
|
4
4
|
import type e from 'express';
|
|
5
5
|
import { getCurrentContextResolver } from '../context.js';
|
package/src/loaders/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
1
2
|
import { UnchainedLoaders } from '@unchainedshop/types/api.js';
|
|
2
3
|
import DataLoader from 'dataloader';
|
|
3
|
-
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
4
4
|
import { systemLocale } from '@unchainedshop/utils';
|
|
5
5
|
import localePkg from 'locale';
|
|
6
6
|
import { Assortment, AssortmentText } from '@unchainedshop/types/assortments.js';
|
package/src/locale-context.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { UnchainedLocaleContext } from '@unchainedshop/types/api.js';
|
|
2
1
|
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
2
|
+
import { UnchainedLocaleContext } from '@unchainedshop/types/api.js';
|
|
3
3
|
import localePkg from 'locale';
|
|
4
4
|
import 'abort-controller/polyfill.js';
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { log } from '@unchainedshop/logger';
|
|
2
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ImpersonatingAdminUserError, UserNotFoundError } from '../../../errors.js';
|
|
4
4
|
|
|
5
5
|
const impersonate = async (root, { userId }, context: Context) => {
|
|
6
|
-
log(`mutation impersonate ${userId}
|
|
6
|
+
log(`mutation impersonate ${userId}`, { userId: context.userId });
|
|
7
7
|
|
|
8
8
|
const userToImpersonate = await context.modules.users.findUserById(userId);
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ const impersonate = async (root, { userId }, context: Context) => {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
if ((userToImpersonate.roles || []).includes('admin')) {
|
|
15
|
-
throw new
|
|
15
|
+
throw new ImpersonatingAdminUserError({ impersonatedUserId: userId, userId: context.userId });
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return context.modules.accounts.createImpersonationToken(userToImpersonate._id, context);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { UserNotFoundError } from '@unchainedshop/api/errors.js';
|
|
2
|
+
import { log } from '@unchainedshop/logger';
|
|
3
|
+
import { Context, Root } from '@unchainedshop/types/api.js';
|
|
4
|
+
|
|
5
|
+
export default async function stopImpersonation(root: Root, _, context: Context) {
|
|
6
|
+
const { userId, modules, loginToken } = context;
|
|
7
|
+
|
|
8
|
+
log(`mutation stopImpersonation for ${userId}`);
|
|
9
|
+
|
|
10
|
+
const impersonatedUser = await modules.users.findUserById(userId);
|
|
11
|
+
|
|
12
|
+
if (!impersonatedUser) throw new UserNotFoundError({ userId });
|
|
13
|
+
const impersonatedUserToken = impersonatedUser?.services?.resume?.loginTokens.find(
|
|
14
|
+
({ hashedToken, impersonatorId }) =>
|
|
15
|
+
hashedToken === modules.accounts.createHashLoginToken(loginToken) && impersonatorId,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
if (!impersonatedUserToken) throw new Error('Current session is not being impersonated');
|
|
19
|
+
|
|
20
|
+
await modules.accounts.logout({ loginToken }, context);
|
|
21
|
+
|
|
22
|
+
const accountsServer = modules.accounts.getAccountsServer();
|
|
23
|
+
|
|
24
|
+
const { token } = await accountsServer.loginWithUser(impersonatedUserToken.impersonatorId);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
id: impersonatedUserToken.impersonatorId,
|
|
28
|
+
token: token.token,
|
|
29
|
+
tokenExpires: token.when,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -3,6 +3,7 @@ import { checkResolver as acl } from '../../acl.js';
|
|
|
3
3
|
import loginWithPassword from './accounts/loginWithPassword.js';
|
|
4
4
|
import loginWithWebAuthn from './accounts/loginWithWebAuthn.js';
|
|
5
5
|
import impersonate from './accounts/impersonate.js';
|
|
6
|
+
import stopImpersonation from './accounts/stopImpersonation.js';
|
|
6
7
|
import loginAsGuest from './accounts/loginAsGuest.js';
|
|
7
8
|
import logout from './accounts/logout.js';
|
|
8
9
|
import logoutAllSessions from './accounts/logoutAllSessions.js';
|
|
@@ -162,11 +163,15 @@ import linkOAuthAccount from './accounts/linkOAuthAccount.js';
|
|
|
162
163
|
import unlinkOAuthAccount from './accounts/unlinkOAuthAccount.js';
|
|
163
164
|
|
|
164
165
|
export default {
|
|
165
|
-
logout,
|
|
166
|
-
logoutAllSessions,
|
|
167
|
-
loginAsGuest,
|
|
168
|
-
createWebAuthnCredentialCreationOptions
|
|
169
|
-
|
|
166
|
+
logout: acl(actions.logout)(logout),
|
|
167
|
+
logoutAllSessions: acl(actions.logoutAllSessions)(logoutAllSessions),
|
|
168
|
+
loginAsGuest: acl(actions.loginAsGuest)(loginAsGuest),
|
|
169
|
+
createWebAuthnCredentialCreationOptions: acl(actions.useWebAuthn)(
|
|
170
|
+
createWebAuthnCredentialCreationOptions,
|
|
171
|
+
),
|
|
172
|
+
createWebAuthnCredentialRequestOptions: acl(actions.useWebAuthn)(
|
|
173
|
+
createWebAuthnCredentialRequestOptions,
|
|
174
|
+
),
|
|
170
175
|
addPushSubscription: acl(actions.updateUser)(addPushSubscription),
|
|
171
176
|
removePushSubscription: acl(actions.updateUser)(removePushSubscription),
|
|
172
177
|
addWebAuthnCredentials: acl(actions.updateUser)(addWebAuthnCredentials),
|
|
@@ -176,22 +181,23 @@ export default {
|
|
|
176
181
|
verifyWeb3Address: acl(actions.updateUser)(verifyWeb3Address),
|
|
177
182
|
linkOAuthAccount: acl(actions.updateUser)(linkOAuthAccount),
|
|
178
183
|
unlinkOAuthAccount: acl(actions.updateUser)(unlinkOAuthAccount),
|
|
179
|
-
verifyEmail,
|
|
180
|
-
loginWithPassword,
|
|
181
|
-
loginWithWebAuthn,
|
|
182
|
-
loginWithOAuth,
|
|
184
|
+
verifyEmail: acl(actions.verifyEmail)(verifyEmail),
|
|
185
|
+
loginWithPassword: acl(actions.loginWithPassword)(loginWithPassword),
|
|
186
|
+
loginWithWebAuthn: acl(actions.loginWithWebAuthn)(loginWithWebAuthn),
|
|
187
|
+
loginWithOAuth: acl(actions.loginWithOAuth)(loginWithOAuth),
|
|
183
188
|
impersonate: acl(actions.impersonate)(impersonate),
|
|
189
|
+
stopImpersonation: acl(actions.stopImpersonation)(stopImpersonation),
|
|
184
190
|
buildSecretTOTPAuthURL: acl(actions.authTwoFactor)(buildSecretTOTPAuthURL),
|
|
185
191
|
enableTOTP: acl(actions.authTwoFactor)(enableTOTP),
|
|
186
192
|
disableTOTP: acl(actions.manageTwoFactor)(disableTOTP),
|
|
187
|
-
pageView,
|
|
188
|
-
createUser,
|
|
189
|
-
forgotPassword,
|
|
190
|
-
resetPassword,
|
|
193
|
+
pageView: acl(actions.pageView)(pageView),
|
|
194
|
+
createUser: acl(actions.createUser)(createUser),
|
|
195
|
+
forgotPassword: acl(actions.forgotPassword)(forgotPassword),
|
|
196
|
+
resetPassword: acl(actions.resetPassword)(resetPassword),
|
|
191
197
|
sendVerificationEmail: acl(actions.sendEmail)(sendVerificationEmail),
|
|
192
198
|
sendEnrollmentEmail: acl(actions.sendEmail)(sendEnrollmentEmail),
|
|
193
|
-
changePassword,
|
|
194
|
-
heartbeat,
|
|
199
|
+
changePassword: acl(actions.changePassword)(changePassword),
|
|
200
|
+
heartbeat: acl(actions.heartbeat)(heartbeat),
|
|
195
201
|
addEmail: acl(actions.updateUser)(addEmail),
|
|
196
202
|
removeEmail: acl(actions.updateUser)(removeEmail),
|
|
197
203
|
updateUserAvatar: acl(actions.updateUser)(updateUserAvatar),
|
|
@@ -10,9 +10,8 @@ export default async (
|
|
|
10
10
|
log(`mutation removePaymentCredentials ${paymentCredentialsId}`, { userId });
|
|
11
11
|
|
|
12
12
|
if (!paymentCredentialsId) throw new InvalidIdError({ paymentCredentialsId });
|
|
13
|
-
const removedCredentials =
|
|
14
|
-
paymentCredentialsId
|
|
15
|
-
);
|
|
13
|
+
const removedCredentials =
|
|
14
|
+
await modules.payment.paymentCredentials.removeCredentials(paymentCredentialsId);
|
|
16
15
|
if (!removedCredentials) throw new PaymentCredentialsNotFoundError({ paymentCredentialsId });
|
|
17
16
|
|
|
18
17
|
return removedCredentials;
|
|
@@ -65,9 +65,11 @@ import token from './warehousing/token.js';
|
|
|
65
65
|
import work from './worker/work.js';
|
|
66
66
|
import workQueue from './worker/workQueue.js';
|
|
67
67
|
import workQueueCount from './worker/workQueueCount.js';
|
|
68
|
+
import impersonator from './users/impersonator.js';
|
|
68
69
|
|
|
69
70
|
export default {
|
|
70
71
|
me,
|
|
72
|
+
impersonator,
|
|
71
73
|
user: acl(actions.viewUser)(user),
|
|
72
74
|
users: acl(actions.viewUsers)(users),
|
|
73
75
|
usersCount: acl(actions.viewUsers)(usersCount),
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { log } from '@unchainedshop/logger';
|
|
2
|
+
import { Context, Root } from '@unchainedshop/types/api.js';
|
|
3
|
+
|
|
4
|
+
export default async function impersonator(
|
|
5
|
+
root: Root,
|
|
6
|
+
params: any,
|
|
7
|
+
{ userId, user, remoteAddress, modules, loginToken }: Context,
|
|
8
|
+
) {
|
|
9
|
+
log(`query impersonator ${remoteAddress}`, { userId });
|
|
10
|
+
if (!user?.services || !user?.services?.resume || !user?.services?.resume?.loginTokens) return null;
|
|
11
|
+
|
|
12
|
+
const { loginTokens } = user.services.resume;
|
|
13
|
+
const impersonatedSession = loginTokens.find(
|
|
14
|
+
({ hashedToken, impersonatorId }) =>
|
|
15
|
+
hashedToken === modules.accounts.createHashLoginToken(loginToken) && impersonatorId,
|
|
16
|
+
);
|
|
17
|
+
if (!impersonatedSession) return null;
|
|
18
|
+
return modules.users.findUserById(impersonatedSession.impersonatorId);
|
|
19
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import {
|
|
3
4
|
DeliveryError,
|
|
4
5
|
DeliveryProvider as DeliveryProviderType,
|
|
5
6
|
} from '@unchainedshop/types/delivery.js';
|
|
6
|
-
import crypto from 'crypto';
|
|
7
7
|
import { DeliveryPricingDirector } from '@unchainedshop/core-delivery';
|
|
8
8
|
|
|
9
9
|
export type HelperType<P, T> = (provider: DeliveryProviderType, params: P, context: Context) => T;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { DeliveryProvider } from '@unchainedshop/types/delivery.js';
|
|
2
3
|
import { Product } from '@unchainedshop/types/products.js';
|
|
3
4
|
import { WarehousingProvider } from '@unchainedshop/types/warehousing.js';
|
|
4
|
-
import crypto from 'crypto';
|
|
5
5
|
|
|
6
6
|
export const Dispatch = {
|
|
7
7
|
_id: (params: {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { OrderDeliveryDiscount as OrderDeliveryDiscountType } from '@unchainedshop/types/orders.deliveries.js';
|
|
3
4
|
import { OrderDiscount } from '@unchainedshop/types/orders.discounts.js';
|
|
4
5
|
import { OrderPrice } from '@unchainedshop/types/orders.pricing.js';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
6
|
|
|
7
7
|
type HelperType<P, T> = (orderDelivery: OrderDeliveryDiscountType, params: P, context: Context) => T;
|
|
8
8
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { OrderDiscount } from '@unchainedshop/types/orders.discounts.js';
|
|
3
4
|
import { OrderPositionDiscount } from '@unchainedshop/types/orders.positions.js';
|
|
4
5
|
import { OrderPrice } from '@unchainedshop/types/orders.pricing.js';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
6
|
|
|
7
7
|
type HelperType<P, T> = (orderPositionDiscount: OrderPositionDiscount, params: P, context: Context) => T;
|
|
8
8
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { DeliveryProvider } from '@unchainedshop/types/delivery.js';
|
|
3
4
|
import { Order } from '@unchainedshop/types/orders.js';
|
|
@@ -6,7 +7,6 @@ import { OrderPrice } from '@unchainedshop/types/orders.pricing.js';
|
|
|
6
7
|
import { Product } from '@unchainedshop/types/products.js';
|
|
7
8
|
import { Quotation } from '@unchainedshop/types/quotations.js';
|
|
8
9
|
import { WarehousingProvider } from '@unchainedshop/types/warehousing.js';
|
|
9
|
-
import crypto from 'crypto';
|
|
10
10
|
|
|
11
11
|
type HelperType<P, T> = (orderPosition: OrderPosition, params: P, context: Context) => T;
|
|
12
12
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { OrderDiscount } from '@unchainedshop/types/orders.discounts.js';
|
|
3
4
|
import { OrderPayment } from '@unchainedshop/types/orders.payments.js';
|
|
4
5
|
import { OrderPrice } from '@unchainedshop/types/orders.pricing.js';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
6
|
|
|
7
7
|
type HelperType<P, T> = (
|
|
8
8
|
orderDelivery: OrderPrice & { discountId: string; item: OrderPayment },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { Country } from '@unchainedshop/types/countries.js';
|
|
3
4
|
import { Currency } from '@unchainedshop/types/currencies.js';
|
|
@@ -11,7 +12,6 @@ import { OrderPosition } from '@unchainedshop/types/orders.positions.js';
|
|
|
11
12
|
import { OrderPrice } from '@unchainedshop/types/orders.pricing.js';
|
|
12
13
|
import { PaymentProvider } from '@unchainedshop/types/payments.js';
|
|
13
14
|
import { User } from '@unchainedshop/types/user.js';
|
|
14
|
-
import crypto from 'crypto';
|
|
15
15
|
|
|
16
16
|
type HelperType<P, T> = (order: OrderType, params: P, context: Context) => T;
|
|
17
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { PaymentError, PaymentProvider as PaymentProviderType } from '@unchainedshop/types/payments.js';
|
|
3
|
-
import crypto from 'crypto';
|
|
4
4
|
import { PaymentPricingDirector } from '@unchainedshop/core-payment';
|
|
5
5
|
|
|
6
6
|
export interface PaymentProviderHelperTypes {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { Context } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { ProductDiscount as ProductDiscountType } from '@unchainedshop/types/products.js';
|
|
3
|
-
import crypto from 'crypto';
|
|
4
4
|
|
|
5
5
|
type HelperType<T> = (product: ProductDiscountType, _: never, context: Context) => T;
|
|
6
6
|
|
|
@@ -30,6 +30,9 @@ export const Product: ProductHelperTypes = {
|
|
|
30
30
|
queryString,
|
|
31
31
|
});
|
|
32
32
|
},
|
|
33
|
+
reviewsCount: async (obj, params, { modules }) => {
|
|
34
|
+
return modules.products.reviews.count({ ...params, productId: obj._id });
|
|
35
|
+
},
|
|
33
36
|
|
|
34
37
|
siblings: async (product, params, { modules }) => {
|
|
35
38
|
const { assortmentId, limit, offset, includeInactive = false } = params;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import { DeliveryProvider } from '@unchainedshop/types/delivery.js';
|
|
2
3
|
import { Product } from '@unchainedshop/types/products.js';
|
|
3
4
|
import { WarehousingProvider } from '@unchainedshop/types/warehousing.js';
|
|
4
|
-
import crypto from 'crypto';
|
|
5
5
|
|
|
6
6
|
export const Stock = {
|
|
7
7
|
_id: (params: {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import type { Locale } from 'locale';
|
|
21
21
|
import { TokenSurrogate } from '@unchainedshop/types/warehousing.js';
|
|
22
22
|
import { Roles, permissions } from '@unchainedshop/roles';
|
|
23
|
+
import { ProductReview } from '@unchainedshop/types/products.reviews.js';
|
|
23
24
|
import { checkAction, checkTypeResolver } from '../../acl.js';
|
|
24
25
|
import { actions } from '../../roles/index.js';
|
|
25
26
|
|
|
@@ -82,6 +83,15 @@ export interface UserHelperTypes {
|
|
|
82
83
|
username: HelperType<any, string>;
|
|
83
84
|
pushSubscriptions: HelperType<any, Array<PushSubscription>>;
|
|
84
85
|
oAuthAccounts: HelperType<any, Array<OAuthAccount>>;
|
|
86
|
+
reviews: HelperType<
|
|
87
|
+
{
|
|
88
|
+
sort?: Array<SortOption>;
|
|
89
|
+
limit?: number;
|
|
90
|
+
offset?: number;
|
|
91
|
+
},
|
|
92
|
+
Array<ProductReview>
|
|
93
|
+
>;
|
|
94
|
+
reviewsCount: HelperType<any, number>;
|
|
85
95
|
}
|
|
86
96
|
|
|
87
97
|
const {
|
|
@@ -90,6 +100,7 @@ const {
|
|
|
90
100
|
viewUserOrders,
|
|
91
101
|
viewUserEnrollments,
|
|
92
102
|
viewUserQuotations,
|
|
103
|
+
viewUserProductReviews,
|
|
93
104
|
} = actions as Record<string, string>;
|
|
94
105
|
|
|
95
106
|
const getPrimaryEmail = (user: UserType) => {
|
|
@@ -242,4 +253,19 @@ export const User: UserHelperTypes = {
|
|
|
242
253
|
}));
|
|
243
254
|
});
|
|
244
255
|
},
|
|
256
|
+
async reviews(user, params, context) {
|
|
257
|
+
const { modules } = context;
|
|
258
|
+
await checkAction(context, viewUserProductReviews, [user, params]);
|
|
259
|
+
return modules.products.reviews.findProductReviews({
|
|
260
|
+
...(params || {}),
|
|
261
|
+
authorId: user._id,
|
|
262
|
+
});
|
|
263
|
+
},
|
|
264
|
+
async reviewsCount(user, params, context) {
|
|
265
|
+
const { modules } = context;
|
|
266
|
+
await checkAction(context, viewUserProductReviews, [user, params]);
|
|
267
|
+
return modules.products.reviews.count({
|
|
268
|
+
authorId: user._id,
|
|
269
|
+
});
|
|
270
|
+
},
|
|
245
271
|
};
|
package/src/roles/all.ts
CHANGED
|
@@ -55,6 +55,7 @@ export const all = (role, actions) => {
|
|
|
55
55
|
role.allow(actions.viewUserQuotations, isInLoginMutationResponse);
|
|
56
56
|
role.allow(actions.viewUserPrivateInfos, isInLoginMutationResponse);
|
|
57
57
|
role.allow(actions.viewUserEnrollments, isInLoginMutationResponse);
|
|
58
|
+
role.allow(actions.viewUserProductReviews, isInLoginMutationResponse);
|
|
58
59
|
role.allow(actions.reviewProduct, () => false);
|
|
59
60
|
role.allow(actions.updateProductReview, () => false);
|
|
60
61
|
role.allow(actions.manageProductReviews, () => false);
|
|
@@ -79,6 +80,7 @@ export const all = (role, actions) => {
|
|
|
79
80
|
role.allow(actions.authTwoFactor, () => false);
|
|
80
81
|
role.allow(actions.manageTwoFactor, () => false);
|
|
81
82
|
role.allow(actions.impersonate, () => false);
|
|
83
|
+
role.allow(actions.stopImpersonation, () => false);
|
|
82
84
|
|
|
83
85
|
// only allow if query is not demanding for drafts
|
|
84
86
|
role.allow(actions.viewProducts, (root, { includeDrafts }) => !includeDrafts);
|
|
@@ -99,4 +101,18 @@ export const all = (role, actions) => {
|
|
|
99
101
|
role.allow(actions.viewFilters, () => true);
|
|
100
102
|
role.allow(actions.viewTranslations, () => true);
|
|
101
103
|
role.allow(actions.search, () => true);
|
|
104
|
+
role.allow(actions.logout, () => true);
|
|
105
|
+
role.allow(actions.logoutAllSessions, () => true);
|
|
106
|
+
role.allow(actions.loginAsGuest, () => true);
|
|
107
|
+
role.allow(actions.loginWithPassword, () => true);
|
|
108
|
+
role.allow(actions.loginWithWebAuthn, () => true);
|
|
109
|
+
role.allow(actions.loginWithOAuth, () => true);
|
|
110
|
+
role.allow(actions.verifyEmail, () => true);
|
|
111
|
+
role.allow(actions.useWebAuthn, () => true);
|
|
112
|
+
role.allow(actions.pageView, () => true);
|
|
113
|
+
role.allow(actions.createUser, () => true);
|
|
114
|
+
role.allow(actions.forgotPassword, () => true);
|
|
115
|
+
role.allow(actions.resetPassword, () => true);
|
|
116
|
+
role.allow(actions.changePassword, () => true);
|
|
117
|
+
role.allow(actions.heartbeat, () => true);
|
|
102
118
|
};
|
package/src/roles/index.ts
CHANGED
|
@@ -101,6 +101,22 @@ const actions: Record<string, string> = [
|
|
|
101
101
|
'authTwoFactor',
|
|
102
102
|
'manageTwoFactor',
|
|
103
103
|
'impersonate',
|
|
104
|
+
'stopImpersonation',
|
|
105
|
+
'logout',
|
|
106
|
+
'logoutAllSessions',
|
|
107
|
+
'loginAsGuest',
|
|
108
|
+
'loginWithPassword',
|
|
109
|
+
'loginWithWebAuthn',
|
|
110
|
+
'loginWithOAuth',
|
|
111
|
+
'verifyEmail',
|
|
112
|
+
'useWebAuthn',
|
|
113
|
+
'pageView',
|
|
114
|
+
'createUser',
|
|
115
|
+
'forgotPassword',
|
|
116
|
+
'resetPassword',
|
|
117
|
+
'changePassword',
|
|
118
|
+
'viewUserProductReviews',
|
|
119
|
+
'heartbeat',
|
|
104
120
|
].reduce((oldValue, actionValue) => {
|
|
105
121
|
const newValue = oldValue;
|
|
106
122
|
newValue[actionValue] = actionValue;
|
|
@@ -115,6 +131,7 @@ const configureRoles = ({ additionalRoles = {}, additionalActions = [] }) => {
|
|
|
115
131
|
allRoles[key] = new Role(key);
|
|
116
132
|
val(allRoles[key], actions);
|
|
117
133
|
});
|
|
134
|
+
|
|
118
135
|
all(allRoles.ALL, actions);
|
|
119
136
|
loggedIn(allRoles.LOGGEDIN, actions);
|
|
120
137
|
admin(allRoles.ADMIN, actions);
|
package/src/roles/loggedIn.ts
CHANGED
|
@@ -213,6 +213,7 @@ export const loggedIn = (role: any, actions: Record<string, string>) => {
|
|
|
213
213
|
role.allow(actions.viewUserQuotations, isMyself);
|
|
214
214
|
role.allow(actions.viewUserEnrollments, isMyself);
|
|
215
215
|
role.allow(actions.viewUserPrivateInfos, isMyself);
|
|
216
|
+
role.allow(actions.viewUserProductReviews, isMyself);
|
|
216
217
|
role.allow(actions.viewUserTokens, isMyself);
|
|
217
218
|
role.allow(actions.updateUser, isMyself);
|
|
218
219
|
role.allow(actions.authTwoFactor, isMyself);
|
|
@@ -241,4 +242,6 @@ export const loggedIn = (role: any, actions: Record<string, string>) => {
|
|
|
241
242
|
role.allow(actions.managePaymentCredentials, isOwnedPaymentCredential);
|
|
242
243
|
role.allow(actions.updateToken, isOwnedToken);
|
|
243
244
|
role.allow(actions.viewToken, isOwnedToken);
|
|
245
|
+
role.allow(actions.stopImpersonation, () => true);
|
|
246
|
+
role.allow(actions.impersonate, () => false);
|
|
244
247
|
};
|
package/src/schema/mutation.ts
CHANGED
|
@@ -449,6 +449,11 @@ export default [
|
|
|
449
449
|
"""
|
|
450
450
|
impersonate(userId: ID!): LoginMethodResponse!
|
|
451
451
|
|
|
452
|
+
"""
|
|
453
|
+
End customer impersonated user session and resume the impersonator session
|
|
454
|
+
"""
|
|
455
|
+
stopImpersonation: LoginMethodResponse!
|
|
456
|
+
|
|
452
457
|
"""
|
|
453
458
|
Reorder a media asset (first is primary)
|
|
454
459
|
"""
|
package/src/schema/query.ts
CHANGED
|
@@ -5,6 +5,10 @@ export default [
|
|
|
5
5
|
Currently logged in user
|
|
6
6
|
"""
|
|
7
7
|
me: User
|
|
8
|
+
"""
|
|
9
|
+
User impersonating current user session using the impersonate API
|
|
10
|
+
"""
|
|
11
|
+
impersonator: User
|
|
8
12
|
|
|
9
13
|
"""
|
|
10
14
|
Get list of users, by default sorted by creation date (ascending) unless a queryString is set
|
package/src/schema/types/user.ts
CHANGED
package/src/user-context.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
1
2
|
import { UnchainedUserContext } from '@unchainedshop/types/api.js';
|
|
2
3
|
import { UnchainedCore } from '@unchainedshop/types/core.js';
|
|
3
|
-
import { IncomingMessage, OutgoingMessage } from 'http';
|
|
4
4
|
import cookie from 'cookie';
|
|
5
5
|
|
|
6
6
|
function isString(input) {
|