Compare commits
5 Commits
refactor/w
...
fix/defaul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
850954efdf | ||
|
|
bf65654126 | ||
|
|
27ea170d85 | ||
|
|
6cf0c427a7 | ||
|
|
b7a3ae231b |
@@ -121,6 +121,7 @@ describe('AdminService', () => {
|
||||
NOT: {
|
||||
inviteeEmail: {
|
||||
in: [dbAdminUsers[0].email],
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -229,7 +230,10 @@ describe('AdminService', () => {
|
||||
|
||||
expect(mockPrisma.invitedUsers.deleteMany).toHaveBeenCalledWith({
|
||||
where: {
|
||||
inviteeEmail: { in: [invitedUsers[0].inviteeEmail] },
|
||||
inviteeEmail: {
|
||||
in: [invitedUsers[0].inviteeEmail],
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toEqualRight(true);
|
||||
|
||||
@@ -89,12 +89,17 @@ export class AdminService {
|
||||
adminEmail: string,
|
||||
inviteeEmail: string,
|
||||
) {
|
||||
if (inviteeEmail == adminEmail) return E.left(DUPLICATE_EMAIL);
|
||||
if (inviteeEmail.toLowerCase() == adminEmail.toLowerCase()) {
|
||||
return E.left(DUPLICATE_EMAIL);
|
||||
}
|
||||
if (!validateEmail(inviteeEmail)) return E.left(INVALID_EMAIL);
|
||||
|
||||
const alreadyInvitedUser = await this.prisma.invitedUsers.findFirst({
|
||||
where: {
|
||||
inviteeEmail: inviteeEmail,
|
||||
inviteeEmail: {
|
||||
equals: inviteeEmail,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
});
|
||||
if (alreadyInvitedUser != null) return E.left(USER_ALREADY_INVITED);
|
||||
@@ -159,7 +164,7 @@ export class AdminService {
|
||||
try {
|
||||
await this.prisma.invitedUsers.deleteMany({
|
||||
where: {
|
||||
inviteeEmail: { in: inviteeEmails },
|
||||
inviteeEmail: { in: inviteeEmails, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
return E.right(true);
|
||||
@@ -189,6 +194,7 @@ export class AdminService {
|
||||
NOT: {
|
||||
inviteeEmail: {
|
||||
in: userEmailObjs.map((user) => user.email),
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -299,7 +299,10 @@ export class ShortcodeService implements UserDataHandler, OnModuleInit {
|
||||
where: userEmail
|
||||
? {
|
||||
User: {
|
||||
email: userEmail,
|
||||
email: {
|
||||
equals: userEmail,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
|
||||
@@ -75,12 +75,13 @@ export class TeamInvitationService {
|
||||
if (!isEmailValid) return E.left(INVALID_EMAIL);
|
||||
|
||||
try {
|
||||
const teamInvite = await this.prisma.teamInvitation.findUniqueOrThrow({
|
||||
const teamInvite = await this.prisma.teamInvitation.findFirstOrThrow({
|
||||
where: {
|
||||
teamID_inviteeEmail: {
|
||||
inviteeEmail: inviteeEmail,
|
||||
teamID: teamID,
|
||||
inviteeEmail: {
|
||||
equals: inviteeEmail,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
teamID,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ beforeEach(() => {
|
||||
describe('UserService', () => {
|
||||
describe('findUserByEmail', () => {
|
||||
test('should successfully return a valid user given a valid email', async () => {
|
||||
mockPrisma.user.findUniqueOrThrow.mockResolvedValueOnce(user);
|
||||
mockPrisma.user.findFirst.mockResolvedValueOnce(user);
|
||||
|
||||
const result = await userService.findUserByEmail(
|
||||
'dwight@dundermifflin.com',
|
||||
@@ -158,7 +158,7 @@ describe('UserService', () => {
|
||||
});
|
||||
|
||||
test('should return a null user given a invalid email', async () => {
|
||||
mockPrisma.user.findUniqueOrThrow.mockRejectedValueOnce('NotFoundError');
|
||||
mockPrisma.user.findFirst.mockResolvedValueOnce(null);
|
||||
|
||||
const result = await userService.findUserByEmail('jim@dundermifflin.com');
|
||||
expect(result).resolves.toBeNone;
|
||||
|
||||
@@ -62,16 +62,16 @@ export class UserService {
|
||||
* @returns Option of found User
|
||||
*/
|
||||
async findUserByEmail(email: string): Promise<O.None | O.Some<AuthUser>> {
|
||||
try {
|
||||
const user = await this.prisma.user.findUniqueOrThrow({
|
||||
where: {
|
||||
email: email,
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: {
|
||||
email: {
|
||||
equals: email,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
});
|
||||
return O.some(user);
|
||||
} catch (error) {
|
||||
return O.none;
|
||||
}
|
||||
},
|
||||
});
|
||||
if (!user) return O.none;
|
||||
return O.some(user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div class="flex flex-col px-4 pt-2">
|
||||
<div v-if="isTooltipComponent" class="flex flex-col px-4 pt-2">
|
||||
<h2 class="inline-flex pb-1 font-semibold text-secondaryDark">
|
||||
{{ t("settings.interceptor") }}
|
||||
</h2>
|
||||
@@ -19,6 +19,9 @@
|
||||
:value="interceptor.interceptorID"
|
||||
:label="unref(interceptor.name(t))"
|
||||
:selected="interceptorSelection === interceptor.interceptorID"
|
||||
:class="{
|
||||
'!px-0 hover:bg-transparent': !isTooltipComponent,
|
||||
}"
|
||||
@change="interceptorSelection = interceptor.interceptorID"
|
||||
/>
|
||||
|
||||
@@ -39,6 +42,15 @@ import { InterceptorService } from "~/services/interceptor.service"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
isTooltipComponent?: boolean
|
||||
}>(),
|
||||
{
|
||||
isTooltipComponent: true,
|
||||
}
|
||||
)
|
||||
|
||||
const interceptorService = useService(InterceptorService)
|
||||
|
||||
const interceptorSelection =
|
||||
|
||||
@@ -36,16 +36,6 @@
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="space-y-4 py-4">
|
||||
<div class="flex items-center">
|
||||
<HoppSmartToggle
|
||||
:on="extensionEnabled"
|
||||
@change="extensionEnabled = !extensionEnabled"
|
||||
>
|
||||
{{ t("settings.extensions_use_toggle") }}
|
||||
</HoppSmartToggle>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -55,34 +45,12 @@ import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { ExtensionInterceptorService } from "~/platform/std/interceptors/extension"
|
||||
import { useService } from "dioc/vue"
|
||||
import { computed } from "vue"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const interceptorService = useService(InterceptorService)
|
||||
const extensionService = useService(ExtensionInterceptorService)
|
||||
|
||||
const extensionVersion = extensionService.extensionVersion
|
||||
const hasChromeExtInstalled = extensionService.chromeExtensionInstalled
|
||||
const hasFirefoxExtInstalled = extensionService.firefoxExtensionInstalled
|
||||
|
||||
const extensionEnabled = computed({
|
||||
get() {
|
||||
return (
|
||||
interceptorService.currentInterceptorID.value ===
|
||||
extensionService.interceptorID
|
||||
)
|
||||
},
|
||||
set(active) {
|
||||
if (active) {
|
||||
interceptorService.currentInterceptorID.value =
|
||||
extensionService.interceptorID
|
||||
} else {
|
||||
interceptorService.currentInterceptorID.value =
|
||||
platform.interceptors.default
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -8,16 +8,6 @@
|
||||
:label="t('app.proxy_privacy_policy')"
|
||||
/>.
|
||||
</div>
|
||||
<div class="space-y-4 py-4">
|
||||
<div class="flex items-center">
|
||||
<HoppSmartToggle
|
||||
:on="proxyEnabled"
|
||||
@change="proxyEnabled = !proxyEnabled"
|
||||
>
|
||||
{{ t("settings.proxy_use_toggle") }}
|
||||
</HoppSmartToggle>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2 py-4">
|
||||
<HoppSmartInput
|
||||
v-model="PROXY_URL"
|
||||
@@ -50,7 +40,6 @@ import { computed } from "vue"
|
||||
import { useService } from "dioc/vue"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { proxyInterceptor } from "~/platform/std/interceptors/proxy"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
@@ -59,23 +48,11 @@ const interceptorService = useService(InterceptorService)
|
||||
|
||||
const PROXY_URL = useSetting("PROXY_URL")
|
||||
|
||||
const proxyEnabled = computed({
|
||||
get() {
|
||||
return (
|
||||
interceptorService.currentInterceptorID.value ===
|
||||
proxyInterceptor.interceptorID
|
||||
)
|
||||
},
|
||||
set(active) {
|
||||
if (active) {
|
||||
interceptorService.currentInterceptorID.value =
|
||||
proxyInterceptor.interceptorID
|
||||
} else {
|
||||
interceptorService.currentInterceptorID.value =
|
||||
platform.interceptors.default
|
||||
}
|
||||
},
|
||||
})
|
||||
const proxyEnabled = computed(
|
||||
() =>
|
||||
interceptorService.currentInterceptorID.value ===
|
||||
proxyInterceptor.interceptorID
|
||||
)
|
||||
|
||||
const clearIcon = refAutoReset<typeof IconRotateCCW | typeof IconCheck>(
|
||||
IconRotateCCW,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { cloneDeep, defaultsDeep, has } from "lodash-es"
|
||||
import { Observable } from "rxjs"
|
||||
import { distinctUntilChanged, pluck } from "rxjs/operators"
|
||||
import { nextTick } from "vue"
|
||||
import { platform } from "~/platform"
|
||||
import type { KeysMatching } from "~/types/ts-utils"
|
||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||
|
||||
@@ -70,63 +68,52 @@ export type SettingsDef = {
|
||||
HAS_OPENED_SPOTLIGHT: boolean
|
||||
}
|
||||
|
||||
export const getDefaultSettings = (): SettingsDef => {
|
||||
const defaultSettings: SettingsDef = {
|
||||
syncCollections: true,
|
||||
syncHistory: true,
|
||||
syncEnvironments: true,
|
||||
export const getDefaultSettings = (): SettingsDef => ({
|
||||
syncCollections: true,
|
||||
syncHistory: true,
|
||||
syncEnvironments: true,
|
||||
|
||||
WRAP_LINES: {
|
||||
httpRequestBody: true,
|
||||
httpResponseBody: true,
|
||||
httpHeaders: true,
|
||||
httpParams: true,
|
||||
httpUrlEncoded: true,
|
||||
httpPreRequest: true,
|
||||
httpTest: true,
|
||||
httpRequestVariables: true,
|
||||
graphqlQuery: true,
|
||||
graphqlResponseBody: true,
|
||||
graphqlHeaders: false,
|
||||
graphqlVariables: false,
|
||||
graphqlSchema: true,
|
||||
importCurl: true,
|
||||
codeGen: true,
|
||||
cookie: true,
|
||||
},
|
||||
WRAP_LINES: {
|
||||
httpRequestBody: true,
|
||||
httpResponseBody: true,
|
||||
httpHeaders: true,
|
||||
httpParams: true,
|
||||
httpUrlEncoded: true,
|
||||
httpPreRequest: true,
|
||||
httpTest: true,
|
||||
httpRequestVariables: true,
|
||||
graphqlQuery: true,
|
||||
graphqlResponseBody: true,
|
||||
graphqlHeaders: false,
|
||||
graphqlVariables: false,
|
||||
graphqlSchema: true,
|
||||
importCurl: true,
|
||||
codeGen: true,
|
||||
cookie: true,
|
||||
},
|
||||
|
||||
CURRENT_INTERCEPTOR_ID: "",
|
||||
// Set empty because interceptor module will set the default value
|
||||
CURRENT_INTERCEPTOR_ID: "",
|
||||
|
||||
// TODO: Interceptor related settings should move under the interceptor systems
|
||||
PROXY_URL: "https://proxy.hoppscotch.io/",
|
||||
URL_EXCLUDES: {
|
||||
auth: true,
|
||||
httpUser: true,
|
||||
httpPassword: true,
|
||||
bearerToken: true,
|
||||
oauth2Token: true,
|
||||
},
|
||||
THEME_COLOR: "indigo",
|
||||
BG_COLOR: "system",
|
||||
TELEMETRY_ENABLED: true,
|
||||
EXPAND_NAVIGATION: false,
|
||||
SIDEBAR: true,
|
||||
SIDEBAR_ON_LEFT: false,
|
||||
COLUMN_LAYOUT: true,
|
||||
// TODO: Interceptor related settings should move under the interceptor systems
|
||||
PROXY_URL: "https://proxy.hoppscotch.io/",
|
||||
URL_EXCLUDES: {
|
||||
auth: true,
|
||||
httpUser: true,
|
||||
httpPassword: true,
|
||||
bearerToken: true,
|
||||
oauth2Token: true,
|
||||
},
|
||||
THEME_COLOR: "indigo",
|
||||
BG_COLOR: "system",
|
||||
TELEMETRY_ENABLED: true,
|
||||
EXPAND_NAVIGATION: false,
|
||||
SIDEBAR: true,
|
||||
SIDEBAR_ON_LEFT: false,
|
||||
COLUMN_LAYOUT: true,
|
||||
|
||||
HAS_OPENED_SPOTLIGHT: false,
|
||||
}
|
||||
|
||||
// Wait for platform to initialize before setting CURRENT_INTERCEPTOR_ID
|
||||
nextTick(() => {
|
||||
applySetting(
|
||||
"CURRENT_INTERCEPTOR_ID",
|
||||
platform?.interceptors.default || "browser"
|
||||
)
|
||||
})
|
||||
|
||||
return defaultSettings
|
||||
}
|
||||
HAS_OPENED_SPOTLIGHT: false,
|
||||
})
|
||||
|
||||
type ApplySettingPayload = {
|
||||
[K in keyof SettingsDef]: {
|
||||
|
||||
@@ -98,6 +98,12 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="space-y-8 p-8 md:col-span-2">
|
||||
<section class="flex flex-col space-y-2">
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t("settings.interceptor") }}
|
||||
</h4>
|
||||
<AppInterceptor :is-tooltip-component="false" />
|
||||
</section>
|
||||
<section v-for="[id, settings] in interceptorsWithSettings" :key="id">
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ settings.entryTitle(t) }}
|
||||
|
||||
Reference in New Issue
Block a user