Merge branch 'develop'

This commit is contained in:
x.yumoto.k 2023-10-26 16:15:28 +09:00
commit a354009346
47 changed files with 1738 additions and 133 deletions

View File

@ -49,7 +49,7 @@ jobs:
displayName: Deploy Frontend Files
variables:
storageAccountName: saomdspipeline
containerName: staging
environment: production
pool:
vmImage: ubuntu-latest
steps:
@ -65,7 +65,7 @@ jobs:
az storage blob download \
--auth-mode login \
--account-name $(storageAccountName) \
--container-name $(containerName) \
--container-name $(environment) \
--name $(Build.SourceVersion).zip \
--file $(Build.SourcesDirectory)/$(Build.SourceVersion).zip
- task: Bash@3

View File

@ -99,13 +99,13 @@ jobs:
azureContainerRegistry: '{"loginServer":"crodmsregistrymaintenance.azurecr.io", "id" : "/subscriptions/108fb131-cdca-4729-a2be-e5bd8c0b3ba7/resourceGroups/maintenance-rg/providers/Microsoft.ContainerRegistry/registries/crOdmsRegistryMaintenance"}'
action: Push an image
imageName: odmscloud/staging/dictation:$(Build.SourceVersion)
- job: frontend_build
- job: frontend_build_staging
dependsOn: backend_build
condition: succeeded('backend_build')
displayName: Build Frontend Files
displayName: Build Frontend Files(staging)
variables:
storageAccountName: saomdspipeline
containerName: staging
environment: staging
pool:
name: odms-deploy-pipeline
steps:
@ -122,7 +122,7 @@ jobs:
displayName: Bash Script
inputs:
targetType: inline
script: cd dictation_client && npm run build
script: cd dictation_client && cp -f .env.$(environment) .env && npm run build
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: dictation_client/build
@ -139,14 +139,59 @@ jobs:
az storage blob upload \
--auth-mode login \
--account-name $(storageAccountName) \
--container-name $(containerName) \
--container-name $(environment) \
--name $(Build.SourceVersion).zip \
--type block \
--overwrite \
--file $(Build.ArtifactStagingDirectory)/$(Build.SourceVersion).zip
- job: frontend_build_production
dependsOn: frontend_build_staging
condition: succeeded('frontend_build_staging')
displayName: Build Frontend Files(production)
variables:
storageAccountName: saomdspipeline
environment: production
pool:
name: odms-deploy-pipeline
steps:
- checkout: self
clean: true
fetchDepth: 1
- task: Npm@1
displayName: npm ci
inputs:
command: ci
workingDir: dictation_client
verbose: false
- task: Bash@3
displayName: Bash Script
inputs:
targetType: inline
script: cd dictation_client && cp -f .env.$(environment) .env && npm run build
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: dictation_client/build
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.SourceVersion).zip'
replaceExistingArchive: true
- task: AzureCLI@2
inputs:
azureSubscription: 'omds-service-connection-stg'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
az storage blob upload \
--auth-mode login \
--account-name $(storageAccountName) \
--container-name $(environment) \
--name $(Build.SourceVersion).zip \
--type block \
--overwrite \
--file $(Build.ArtifactStagingDirectory)/$(Build.SourceVersion).zip
- job: backend_deploy
dependsOn: frontend_build
condition: succeeded('frontend_build')
dependsOn: frontend_build_production
condition: succeeded('frontend_build_production')
displayName: Backend Deploy
pool:
name: odms-deploy-pipeline

View File

@ -0,0 +1,5 @@
VITE_STAGE=production
VITE_B2C_CLIENTID=b0ec473b-6b2b-4f12-adc6-39a24ebe6a3f
VITE_B2C_AUTHORITY=https://adb2codmsprod.b2clogin.com/adb2codmsprod.onmicrosoft.com/b2c_1_signin_prod
VITE_B2C_KNOWNAUTHORITIES=adb2codmsprod.b2clogin.com
VITE_DESK_TOP_APP_SCHEME=odms-desktopapp

View File

@ -0,0 +1,36 @@
// 代行操作中に表示するコンポーネント
// ------------------------------------------------------
import React from "react";
import { useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import styles from "../../styles/app.module.scss";
import exit from "../../assets/images/exit.svg";
import reportWhite from "../../assets/images/report_white.svg";
import { getTranslationID } from "translation";
interface DelegationBarProps {
delegatedCompanyName: string;
}
export const DelegationBar: React.FC<DelegationBarProps> = (
porps
): JSX.Element => {
const { delegatedCompanyName } = porps;
const { t } = useTranslation();
return (
<div className={styles.manageInfo}>
<img src={reportWhite} className={styles.manageIcon} alt="report" />
<p className={styles.txNormal}>
{t(getTranslationID("common.label.operationInsteadOf"))}
<span>{delegatedCompanyName}</span>
</p>
<img
src={exit}
className={styles.manageIconClose}
alt="Exit"
title="Exit"
/>
</div>
);
};

View File

@ -14,6 +14,8 @@ const initialState: AuthState = {
configuration: initialConfig(),
accessToken: loadAccessToken(),
refreshToken: loadRefreshToken(),
delegatedAccessToken: null,
delegatedRefreshToken: null,
};
export const authSlice = createSlice({
@ -22,7 +24,12 @@ export const authSlice = createSlice({
reducers: {
setToken: (
state,
action: PayloadAction<Omit<AuthState, "configuration">>
action: PayloadAction<
Omit<
AuthState,
"configuration" | "delegatedAccessToken" | "delegatedRefreshToken"
>
>
) => {
const { accessToken, refreshToken } = action.payload;
if (accessToken && refreshToken) {

View File

@ -22,3 +22,7 @@ export const isTokenExpired = (state: RootState): boolean => {
}
return true;
};
// 代行操作用のトークンを取得する
export const selectDelegatedAccessToken = (state: RootState): string | null =>
state.auth.delegatedAccessToken;

View File

@ -4,4 +4,6 @@ export interface AuthState {
configuration: ConfigurationParameters;
accessToken: string | null;
refreshToken: string | null;
delegatedAccessToken: string | null;
delegatedRefreshToken: string | null;
}

View File

@ -30,6 +30,8 @@ import { selectSelectedRow } from "features/license/partnerLicense";
import undo from "../../assets/images/undo.svg";
import history from "../../assets/images/history.svg";
import progress_activit from "../../assets/images/progress_activit.svg";
import { selectDelegatedAccessToken } from "features/auth/selectors";
import { DelegationBar } from "components/delegate";
interface LicenseOrderHistoryProps {
onReturn: () => void;
@ -46,6 +48,8 @@ export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
const currentPage = useSelector(selectCurrentPage);
const isLoading = useSelector(selectIsLoading);
const selectedRow = useSelector(selectSelectedRow);
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
// Return押下時の処理
const returnGui = useCallback(() => {
@ -154,7 +158,14 @@ export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
}, [dispatch, currentPage]);
return (
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${delegatedAccessToken ? styles.manage : ""}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && <DelegationBar delegatedCompanyName="XXXXXX" />
}
<Header userName="XXXXXX" />
<UpdateTokenTimer />

View File

@ -22,6 +22,8 @@ import { LicenseOrderPopup } from "./licenseOrderPopup";
import { CardLicenseActivatePopup } from "./cardLicenseActivatePopup";
// eslint-disable-next-line import/no-named-as-default
import LicenseOrderHistory from "./licenseOrderHistory";
import { selectDelegatedAccessToken } from "features/auth/selectors";
import { DelegationBar } from "components/delegate";
interface LicenseSummaryProps {
onReturn?: () => void;
@ -33,6 +35,8 @@ export const LicenseSummary: React.FC<LicenseSummaryProps> = (
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
const selectedRow = useSelector(selectSelectedRow);
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
// popup制御関係
const [islicenseOrderPopupOpen, setIslicenseOrderPopupOpen] = useState(false);
@ -96,7 +100,18 @@ export const LicenseSummary: React.FC<LicenseSummaryProps> = (
/>
)}
{!islicenseOrderHistoryOpen && (
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXX" />
<UpdateTokenTimer />

View File

@ -15,10 +15,14 @@ import {
selectIsLoading,
} from "features/workflow/template";
import { AddTemplateFilePopup } from "./addTemplateFilePopup";
import { DelegationBar } from "components/delegate";
import { selectDelegatedAccessToken } from "features/auth/selectors";
export const TemplateFilePage: React.FC = () => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
// authStateに配置予定の代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
const templates = useSelector(selectTemplates);
const isLoading = useSelector(selectIsLoading);
@ -38,7 +42,18 @@ export const TemplateFilePage: React.FC = () => {
}}
/>
)}
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>

View File

@ -17,11 +17,14 @@ import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation";
import { AddTypistGroupPopup } from "./addTypistGroupPopup";
import { EditTypistGroupPopup } from "./editTypistGroupPopup";
import { selectDelegatedAccessToken } from "features/auth/selectors";
import { DelegationBar } from "components/delegate";
const TypistGroupSettingPage: React.FC = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
const isLoading = useSelector(selectIsLoading);
const typistGroup = useSelector(selectTypistGroups);
@ -60,7 +63,18 @@ const TypistGroupSettingPage: React.FC = (): JSX.Element => {
isOpen={isEditPopupOpen}
typistGroupId={editTypistGroupId}
/>
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>

View File

@ -28,10 +28,14 @@ import progress_activit from "../../assets/images/progress_activit.svg";
import { UserAddPopup } from "./popup";
import { UserUpdatePopup } from "./updatePopup";
import { AllocateLicensePopup } from "./allocateLicensePopup";
import { DelegationBar } from "components/delegate";
import { selectDelegatedAccessToken } from "features/auth/selectors";
const UserListPage: React.FC = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
const [isPopupOpen, setIsPopupOpen] = useState(false);
const [isUpdatePopupOpen, setIsUpdatePopupOpen] = useState(false);
@ -106,7 +110,18 @@ const UserListPage: React.FC = (): JSX.Element => {
setIsAllocateLicensePopupOpen(false);
}}
/>
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>

View File

@ -24,10 +24,14 @@ import { AppDispatch } from "app/store";
import { AddWorktypeIdPopup } from "./addWorktypeIdPopup";
import { EditWorktypeIdPopup } from "./editWorktypeIdPopup";
import { EditOptionItemsPopup } from "./editOptionItemsPopup";
import { selectDelegatedAccessToken } from "features/auth/selectors";
import { DelegationBar } from "components/delegate";
const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation();
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
const isLoading = useSelector(selectIsLoading);
const worktypes = useSelector(selectWorktypes);
const activeWorktypeId = useSelector(selectActiveWorktypeId);
@ -124,7 +128,18 @@ const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
}}
isOpen={isShowEditOptionItemPopup}
/>
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>

View File

@ -21,6 +21,8 @@ import progress_activit from "assets/images/progress_activit.svg";
import { getTranslationID } from "translation";
import { AddWorkflowPopup } from "./addworkflowPopup";
import { EditWorkflowPopup } from "./editworkflowPopup";
import { DelegationBar } from "components/delegate";
import { selectDelegatedAccessToken } from "features/auth/selectors";
const WorkflowPage: React.FC = (): JSX.Element => {
const dispatch: AppDispatch = useDispatch();
@ -29,7 +31,8 @@ const WorkflowPage: React.FC = (): JSX.Element => {
const [isShowAddPopup, setIsShowAddPopup] = useState<boolean>(false);
// 編集Popupの表示制御
const [isShowEditPopup, setIsShowEditPopup] = useState<boolean>(false);
// 代行操作用のトークンを取得する
const delegatedAccessToken = useSelector(selectDelegatedAccessToken);
const workflows = useSelector(selectWorkflows);
const isLoading = useSelector(selectIsLoading);
@ -70,7 +73,18 @@ const WorkflowPage: React.FC = (): JSX.Element => {
}}
/>
)}
<div className={styles.wrap}>
<div
className={`${styles.wrap} ${
delegatedAccessToken ? styles.manage : ""
}`}
>
{
// 代行操作中の場合は、代行操作バーを表示する
// TODO 代行操作中の会社名と、代行操作用のトークンを取得があれば表示するという風にする別タスクで
delegatedAccessToken && (
<DelegationBar delegatedCompanyName="XXXXXX" />
)
}
<Header userName="XXXXXX" />
<UpdateTokenTimer />
<main className={styles.main}>

View File

@ -16,6 +16,7 @@
"save": "Speichern",
"delete": "Löschen",
"return": "zurückkehren",
"operationInsteadOf": "(de)Operation instead of:",
"tier1": "(de)Admin",
"tier2": "(de)BC",
"tier3": "(de)Distributor",

View File

@ -16,6 +16,7 @@
"save": "Save",
"delete": "Delete",
"return": "Return",
"operationInsteadOf": "Operation instead of:",
"tier1": "Admin",
"tier2": "BC",
"tier3": "Distributor",

View File

@ -16,6 +16,7 @@
"save": "Ahorrar",
"delete": "Delete",
"return": "Devolver",
"operationInsteadOf": "(es)Operation instead of:",
"tier1": "(es)Admin",
"tier2": "(es)BC",
"tier3": "(es)Distributor",

View File

@ -16,6 +16,7 @@
"save": "Sauvegarder",
"delete": "Delete",
"return": "Retour",
"operationInsteadOf": "(fr)Operation instead of:",
"tier1": "(fr)Admin",
"tier2": "(fr)BC",
"tier3": "(fr)Distributor",

View File

@ -0,0 +1 @@
local.settings.json

View File

@ -0,0 +1,10 @@
*.js.map
*.ts
.git*
.vscode
local.settings.json
test
getting_started.md
node_modules/@types/
node_modules/azure-functions-core-tools/
node_modules/typescript/

48
dictation_function/.gitignore vendored Normal file
View File

@ -0,0 +1,48 @@
bin
obj
csx
.vs
edge
Publish
*.user
*.suo
*.cscfg
*.Cache
project.lock.json
/packages
/TestResults
/tools/NuGet.exe
/App_Data
/secrets
/data
.secrets
appsettings.json
local.settings.json
node_modules
dist
# Local python packages
.python_packages/
# Python Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Azurite artifacts
__blobstorage__
__queuestorage__
__azurite_db*__.json

View File

@ -0,0 +1,5 @@
{
"recommendations": [
"ms-azuretools.vscode-azurefunctions"
]
}

View File

@ -0,0 +1,21 @@
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/node:4-node18-appservice
FROM mcr.microsoft.com/azure-functions/node:4-node18
RUN /bin/cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo "Asia/Tokyo" > /etc/timezone
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
RUN apt-get -y update
RUN apt-get install -y \
curl \
gnupg
RUN apt-get install -y nodejs
WORKDIR /home/site/wwwroot
RUN cd /home/site/wwwroot
COPY ./ /home/site/wwwroot
RUN npm install -g npm

View File

@ -0,0 +1,20 @@
version: "3"
services:
dictation_function:
build: .
working_dir: /app/dictation_function
ports:
- "3001:3001"
- "6007:6007"
volumes:
- ../../:/app
- node_modules:/app/dictation_function/node_modules
expose:
- "8082"
environment:
- CHOKIDAR_USEPOLLING=true
# Data Volume として永続化する
volumes:
node_modules:

View File

@ -0,0 +1,15 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}

936
dictation_function/package-lock.json generated Normal file
View File

@ -0,0 +1,936 @@
{
"name": "dictation_function",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"dependencies": {
"@azure/functions": "^4.0.0-alpha.9"
},
"devDependencies": {
"@types/node": "18.x",
"azure-functions-core-tools": "^4.x",
"rimraf": "^5.0.0",
"typescript": "^4.0.0"
}
},
"node_modules/@azure/functions": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@azure/functions/-/functions-4.0.1.tgz",
"integrity": "sha512-Ol38b4XOlu6IDkLnO91HaYeo2utMixG0LIA1NR9Qehu17U/cGjNx+bAcOEdNlSJWNYh5ChhzjxA/uFB5dQJtmg==",
"dependencies": {
"long": "^4.0.0",
"undici": "^5.13.0"
},
"engines": {
"node": ">=18.0"
}
},
"node_modules/@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
"engines": {
"node": ">=14"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@types/node": {
"version": "18.18.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
"integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/azure-functions-core-tools": {
"version": "4.0.5413",
"resolved": "https://registry.npmjs.org/azure-functions-core-tools/-/azure-functions-core-tools-4.0.5413.tgz",
"integrity": "sha512-jHfw7JrfH5RZEQni098Bf1HZorIzLlQH8aoNNKYwmhF6mvh5J6aTqKyDSJKUbUN2/xqS9vxGYGpKzqv4US3dcA==",
"dev": true,
"hasInstallScript": true,
"hasShrinkwrap": true,
"os": [
"win32",
"darwin",
"linux"
],
"dependencies": {
"chalk": "3.0.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "5.0.0",
"progress": "2.0.3",
"rimraf": "3.0.2"
},
"bin": {
"azfun": "lib/main.js",
"azurefunctions": "lib/main.js",
"func": "lib/main.js"
},
"engines": {
"node": ">=6.9.1"
}
},
"node_modules/azure-functions-core-tools/node_modules/@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/@types/node": {
"version": "18.15.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz",
"integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==",
"dev": true,
"optional": true
},
"node_modules/azure-functions-core-tools/node_modules/@types/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
"dev": true,
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/azure-functions-core-tools/node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dev": true,
"dependencies": {
"debug": "4"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/ansi-styles": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz",
"integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==",
"dev": true,
"dependencies": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/azure-functions-core-tools/node_modules/balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/azure-functions-core-tools/node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"dev": true,
"engines": {
"node": "*"
}
},
"node_modules/azure-functions-core-tools/node_modules/chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/azure-functions-core-tools/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"dev": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/azure-functions-core-tools/node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/azure-functions-core-tools/node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dev": true,
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/azure-functions-core-tools/node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/azure-functions-core-tools/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/azure-functions-core-tools/node_modules/https-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
"dev": true,
"dependencies": {
"agent-base": "6",
"debug": "4"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/azure-functions-core-tools/node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/azure-functions-core-tools/node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/azure-functions-core-tools/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/azure-functions-core-tools/node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/azure-functions-core-tools/node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/azure-functions-core-tools/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/azure-functions-core-tools/node_modules/supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/azure-functions-core-tools/node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"node_modules/azure-functions-core-tools/node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dev": true,
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
},
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob": {
"version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.5",
"minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.10.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/jackspeak": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"node_modules/lru-cache": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
"integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/path-scurry": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"dev": true,
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
"integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
"dev": true,
"dependencies": {
"glob": "^10.3.7"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/string-width-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/undici": {
"version": "5.26.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.26.4.tgz",
"integrity": "sha512-OG+QOf0fTLtazL9P9X7yqWxQ+Z0395Wk6DSkyTxtaq3wQEjIroVe7Y4asCX/vcCxYpNGMnwz8F0qbRYUoaQVMw==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
}
}
}

View File

@ -0,0 +1,23 @@
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "dist/src/functions/*.js",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"clean": "rimraf dist",
"prestart": "npm run clean && npm run build",
"start": "func start",
"test": "echo \"No tests yet...\""
},
"dependencies": {
"@azure/functions": "^4.0.0-alpha.9"
},
"devDependencies": {
"azure-functions-core-tools": "^4.x",
"@types/node": "18.x",
"typescript": "^4.0.0",
"rimraf": "^5.0.0"
}
}

View File

@ -0,0 +1,15 @@
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
export async function HttpExample(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || await request.text() || 'world';
return { body: `Hello, ${name}!` };
};
app.http('HttpExample', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: HttpExample
});

View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false
}
}

View File

@ -0,0 +1,8 @@
-- +migrate Up
delete from terms where terms.document_type = 'EURA' and terms.version = 'V0.1';
insert into terms(terms.document_type, terms.version) values('EULA', 'V0.1');
commit;
-- +migrate Down
delete from terms where terms.document_type = 'EULA' and terms.version = 'V0.1';
commit;

View File

@ -88,6 +88,100 @@
"security": [{ "bearer": [] }]
}
},
"/auth/delegation/token": {
"post": {
"operationId": "delegationToken",
"summary": "",
"description": "代行操作用のリフレッシュトークン・アクセストークンを生成します",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DelegationTokenRequest"
}
}
}
},
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DelegationTokenResponse"
}
}
}
},
"400": {
"description": "指定したアカウントが代行操作を許可していない場合",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
}
}
},
"401": {
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
}
}
},
"500": {
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
}
}
}
},
"tags": ["auth"],
"security": [{ "bearer": [] }]
}
},
"/auth/delegation/access-token": {
"post": {
"operationId": "delegationAccessToken",
"summary": "",
"description": "代行操作用のアクセストークンを再生成します",
"parameters": [],
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DelegationAccessTokenResponse"
}
}
}
},
"401": {
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
}
}
},
"500": {
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
}
}
}
},
"tags": ["auth"],
"security": [{ "bearer": [] }]
}
},
"/accounts": {
"post": {
"operationId": "createAccount",
@ -3399,6 +3493,40 @@
"properties": { "accessToken": { "type": "string" } },
"required": ["accessToken"]
},
"DelegationTokenRequest": {
"type": "object",
"properties": {
"delegatedAccountId": {
"type": "number",
"description": "代行操作対象のアカウントID"
}
},
"required": ["delegatedAccountId"]
},
"DelegationTokenResponse": {
"type": "object",
"properties": {
"refreshToken": {
"type": "string",
"description": "代行操作用のリフレッシュトークン"
},
"accessToken": {
"type": "string",
"description": "代行操作用のアクセストークン"
}
},
"required": ["refreshToken", "accessToken"]
},
"DelegationAccessTokenResponse": {
"type": "object",
"properties": {
"accessToken": {
"type": "string",
"description": "代行操作用のアクセストークン"
}
},
"required": ["accessToken"]
},
"CreateAccountRequest": {
"type": "object",
"properties": {
@ -3680,13 +3808,7 @@
"poNumber": { "type": "string", "description": "POナンバー" },
"status": { "type": "string", "description": "注文状態" }
},
"required": [
"orderDate",
"issueDate",
"numberOfOrder",
"poNumber",
"status"
]
"required": ["orderDate", "numberOfOrder", "poNumber", "status"]
},
"GetOrderHistoriesResponse": {
"type": "object",

View File

@ -200,7 +200,7 @@ export class AccountsController {
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('me')
async getMyAccount(@Req() req: Request): Promise<GetMyAccountResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -249,7 +249,7 @@ export class AccountsController {
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('authors')
async getAuthors(@Req() req: Request): Promise<GetAuthorsResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -295,7 +295,7 @@ export class AccountsController {
@UseGuards(AuthGuard)
@Get('typists')
async getTypists(@Req() req: Request): Promise<GetTypistsResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -340,7 +340,7 @@ export class AccountsController {
@UseGuards(AuthGuard)
@Get('typist-groups')
async getTypistGroups(@Req() req: Request): Promise<GetTypistGroupsResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -398,7 +398,7 @@ export class AccountsController {
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -461,7 +461,7 @@ export class AccountsController {
const { typistGroupName, typistIds } = body;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -525,7 +525,7 @@ export class AccountsController {
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -590,7 +590,7 @@ export class AccountsController {
): Promise<CreatePartnerAccountResponse> {
const { companyName, country, email, adminName } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -731,7 +731,7 @@ export class AccountsController {
): Promise<IssueLicenseResponse> {
const { orderedAccountId, poNumber } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -812,7 +812,7 @@ export class AccountsController {
@Req() req: Request,
@Body() body: CancelIssueRequest,
): Promise<CancelIssueResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -860,7 +860,7 @@ export class AccountsController {
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async getWorktypes(@Req() req: Request): Promise<GetWorktypesResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -913,7 +913,7 @@ export class AccountsController {
): Promise<CreateWorktypeResponse> {
const { worktypeId, description } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -973,7 +973,7 @@ export class AccountsController {
const { worktypeId, description } = body;
const { id } = param;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1033,7 +1033,7 @@ export class AccountsController {
): Promise<DeleteWorktypeResponse> {
const { id } = param;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1086,7 +1086,7 @@ export class AccountsController {
): Promise<GetOptionItemsResponse> {
const { id } = param;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1146,7 +1146,7 @@ export class AccountsController {
const { optionItems } = body;
const { id } = param;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1205,7 +1205,7 @@ export class AccountsController {
): Promise<PostActiveWorktypeResponse> {
const { id } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1263,7 +1263,7 @@ export class AccountsController {
): Promise<GetPartnersResponse> {
const { limit, offset } = query;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1330,7 +1330,7 @@ export class AccountsController {
secondryAdminUserId,
} = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -1390,7 +1390,7 @@ export class AccountsController {
): Promise<DeleteAccountResponse> {
const { accountId } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),

View File

@ -34,7 +34,7 @@ export class CreateAccountRequest {
@ApiProperty({ required: false })
@IsInt()
@IsOptional()
dealerAccountId?: number | undefined;
dealerAccountId?: number;
@ApiProperty()
adminName: string;
@ApiProperty()
@ -116,19 +116,19 @@ export class Account {
country: string;
@ApiProperty({ required: false })
parentAccountId?: number | undefined;
parentAccountId?: number;
@ApiProperty()
delegationPermission: boolean;
@ApiProperty({ required: false })
primaryAdminUserId?: number | undefined;
primaryAdminUserId?: number;
@ApiProperty({ required: false })
secondryAdminUserId?: number | undefined;
secondryAdminUserId?: number;
@ApiProperty({ required: false })
parentAccountName?: string | undefined;
parentAccountName?: string;
}
export class GetMyAccountResponse {
@ -394,7 +394,7 @@ export class GetWorktypesResponse {
required: false,
description: 'Active WorktypeIDに設定されているWorkTypeの内部ID',
})
active?: number | undefined;
active?: number;
}
export class CreateWorktypesRequest {
@ -516,7 +516,7 @@ export class PostActiveWorktypeRequest {
@Type(() => Number)
@IsInt()
@Min(0)
id?: number | undefined;
id?: number;
}
export class PostActiveWorktypeResponse {}
@ -571,14 +571,14 @@ export type PartnerInfoFromDb = {
export class UpdateAccountInfoRequest {
@ApiProperty({ description: '親アカウントのID', required: false })
@IsOptional()
parentAccountId?: number | undefined;
parentAccountId?: number;
@ApiProperty({ description: '代行操作許可' })
delegationPermission: boolean;
@ApiProperty({ description: 'プライマリ管理者ID' })
primaryAdminUserId: number;
@ApiProperty({ description: 'セカンダリ管理者ID', required: false })
@IsOptional()
secondryAdminUserId?: number | undefined;
secondryAdminUserId?: number;
}
export class UpdateAccountInfoResponse {}

View File

@ -5,6 +5,7 @@ import {
HttpStatus,
Post,
Req,
UseGuards,
} from '@nestjs/common';
import {
ApiResponse,
@ -19,10 +20,17 @@ import {
AccessTokenResponse,
TokenRequest,
TokenResponse,
DelegationTokenRequest,
DelegationTokenResponse,
DelegationAccessTokenResponse,
} from './types/types';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { makeContext } from '../../common/log';
import { v4 as uuidv4 } from 'uuid';
import { Request } from 'express';
import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { ADMIN_ROLES, TIERS } from '../../constants';
@ApiTags('auth')
@Controller('auth')
@ -117,7 +125,7 @@ export class AuthController {
operationId: 'accessToken',
description: 'リフレッシュトークンを元にアクセストークンを再生成します',
})
async accessToken(@Req() req): Promise<AccessTokenResponse> {
async accessToken(@Req() req: Request): Promise<AccessTokenResponse> {
const refreshToken = retrieveAuthorizationToken(req);
if (!refreshToken) {
@ -135,4 +143,95 @@ export class AuthController {
);
return { accessToken };
}
@Post('delegation/token')
@ApiBearerAuth()
@ApiResponse({
status: HttpStatus.OK,
type: DelegationTokenResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '指定したアカウントが代行操作を許可していない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'delegationToken',
description:
'代行操作用のリフレッシュトークン・アクセストークンを生成します',
})
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER4],
}),
)
async delegationToken(
@Req() req: Request,
@Body() body: DelegationTokenRequest,
): Promise<DelegationTokenResponse> {
const { delegatedAccountId } = body;
const refreshToken = retrieveAuthorizationToken(req);
if (!refreshToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const context = makeContext(uuidv4());
return { accessToken: '', refreshToken: '' };
}
@Post('delegation/access-token')
@ApiBearerAuth()
@ApiResponse({
status: HttpStatus.OK,
type: DelegationAccessTokenResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'delegationAccessToken',
description: '代行操作用のアクセストークンを再生成します',
})
async delegationAccessToken(
@Req() req: Request,
): Promise<DelegationAccessTokenResponse> {
const refreshToken = retrieveAuthorizationToken(req);
if (!refreshToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const context = makeContext(uuidv4());
return { accessToken: '' };
}
}

View File

@ -142,8 +142,8 @@ export class AuthService {
{
//ユーザーの属しているアカウントの管理者にユーザーが設定されていればadminをセットする
role: `${role} ${
user.account.primary_admin_user_id == user.id ||
user.account.secondary_admin_user_id == user.id
user.account.primary_admin_user_id === user.id ||
user.account.secondary_admin_user_id === user.id
? ADMIN_ROLES.ADMIN
: ADMIN_ROLES.STANDARD
}`,

View File

@ -25,3 +25,19 @@ export type TermsCheckInfo = {
latestEulaVersion: string;
latestDpaVersion: string;
};
export class DelegationTokenRequest {
@ApiProperty({ description: '代行操作対象のアカウントID' })
delegatedAccountId: number;
}
export class DelegationTokenResponse {
@ApiProperty({ description: '代行操作用のリフレッシュトークン' })
refreshToken: string;
@ApiProperty({ description: '代行操作用のアクセストークン' })
accessToken: string;
}
export class DelegationAccessTokenResponse {
@ApiProperty({ description: '代行操作用のアクセストークン' })
accessToken: string;
}

View File

@ -182,7 +182,7 @@ export class FilesController {
const context = makeContext(userId);
const url = await this.filesService.publishUploadSas(context, accessToken);
const url = await this.filesService.publishUploadSas(context, userId);
return { url };
}

View File

@ -210,49 +210,25 @@ export class FilesService {
externalId: string,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishUploadSas.name}`,
`[IN] [${context.trackingId}] ${this.publishUploadSas.name} | params: { externalId: ${externalId} };`,
);
//DBから国情報とアカウントIDを取得する
let accountId: number;
let country: string;
try {
const user = await this.usersRepository.findUserByExternalId(externalId);
if (!user.account) {
throw new AccountNotFoundError('account not found.');
}
accountId = user.account_id;
country = user.account.country;
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const accountId = user.account_id;
const country = user.account.country;
try {
// 国に応じたリージョンのBlobストレージにコンテナが存在するか確認
await this.blobStorageService.containerExists(
context,
accountId,
country,
);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
try {
// SASトークン発行
const url = await this.blobStorageService.publishUploadSas(
context,

View File

@ -75,7 +75,7 @@ export class LicensesController {
@Req() req: Request,
@Body() body: CreateOrdersRequest,
): Promise<CreateOrdersResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -126,7 +126,7 @@ export class LicensesController {
@Req() req: Request,
@Body() body: IssueCardLicensesRequest,
): Promise<IssueCardLicensesResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -182,7 +182,7 @@ export class LicensesController {
@Req() req: Request,
@Body() body: ActivateCardLicensesRequest,
): Promise<ActivateCardLicensesResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -235,7 +235,7 @@ export class LicensesController {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@Req() req: Request,
): Promise<GetAllocatableLicensesResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -296,7 +296,7 @@ export class LicensesController {
@Req() req: Request,
@Body() body: CancelOrderRequest,
): Promise<CancelOrderResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),

View File

@ -84,7 +84,7 @@ export class TasksController {
@Req() req,
@Query() body: TasksRequest,
): Promise<TasksResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -204,7 +204,7 @@ export class TasksController {
): Promise<ChangeStatusResponse> {
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -274,7 +274,7 @@ export class TasksController {
const { audioFileId } = params;
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -341,7 +341,7 @@ export class TasksController {
const { audioFileId } = params;
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -410,7 +410,7 @@ export class TasksController {
const { audioFileId } = params;
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -560,7 +560,7 @@ export class TasksController {
): Promise<PostCheckoutPermissionResponse> {
const { assignees } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),

View File

@ -77,7 +77,7 @@ export class Assignee {
@IsInt()
@Min(1)
@IsOptional()
typistUserId?: number | undefined;
typistUserId?: number;
@ApiProperty({
required: false,
description: 'TypistGroupIDTypistGroupIDかTypistIDのどちらかに値が入る',
@ -85,7 +85,7 @@ export class Assignee {
@IsInt()
@Min(1)
@IsOptional()
typistGroupId?: number | undefined;
typistGroupId?: number;
@ApiProperty({ description: 'Typist名 / TypistGroup名' })
typistName: string;
}
@ -143,7 +143,7 @@ export class Task {
required: false,
description: '割り当てられたユーザー',
})
typist?: Typist | undefined;
typist?: Typist;
@ApiProperty({
type: [Assignee],
description:
@ -159,12 +159,12 @@ export class Task {
required: false,
description: '文字起こし開始日時yyyy-mm-ddThh:mm:ss.sss',
})
transcriptionStartedDate?: string | undefined;
transcriptionStartedDate?: string;
@ApiProperty({
required: false,
description: '文字起こし終了日時yyyy-mm-ddThh:mm:ss.sss',
})
transcriptionFinishedDate?: string | undefined;
transcriptionFinishedDate?: string;
}
export class TasksResponse {
@ -198,7 +198,7 @@ export class AudioNextResponse {
required: false,
description: 'ODMS Cloud上の次の音声ファイルID存在しなければundefind',
})
nextFileId?: number | undefined;
nextFileId?: number;
}
export class ChangeStatusRequest {

View File

@ -30,7 +30,7 @@ export class User {
role: string;
@ApiProperty({ required: false })
authorId?: string | undefined;
authorId?: string;
@ApiProperty()
typistGroupName: string[];
@ -57,10 +57,10 @@ export class User {
prompt: boolean;
@ApiProperty({ required: false })
expiration?: string | undefined;
expiration?: string;
@ApiProperty({ required: false })
remaining?: number | undefined;
remaining?: number;
@ApiProperty({
description: `${Object.values(USER_LICENSE_STATUS).join('/')}`,
@ -86,7 +86,7 @@ export class SignupRequest {
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
authorId?: string | undefined;
authorId?: string;
@ApiProperty()
email: string;
@ -102,16 +102,16 @@ export class SignupRequest {
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
encryption?: boolean | undefined;
encryption?: boolean;
@ApiProperty({ required: false })
@IsPasswordvalid()
@IsEncryptionPasswordPresent()
encryptionPassword?: string | undefined;
encryptionPassword?: string;
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
prompt?: boolean | undefined;
prompt?: boolean;
}
export class SignupResponse {}
@ -162,7 +162,7 @@ export class GetRelationsResponse {
description: 'ユーザーが暗号化を掛ける場合のパスワード',
required: false,
})
encryptionPassword?: string | undefined;
encryptionPassword?: string;
@ApiProperty({
description:
'アカウントがデフォルトで利用するWorkTypeIDアカウントに紐づくWorkTypeIDから一つ指定。activeWorktypeがなければ空文字を返却する',
@ -215,7 +215,7 @@ export class PostUpdateUserRequest {
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
authorId?: string | undefined;
authorId?: string;
@ApiProperty()
autoRenew: boolean;
@ -228,15 +228,15 @@ export class PostUpdateUserRequest {
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
encryption?: boolean | undefined;
encryption?: boolean;
@ApiProperty({ required: false })
@IsPasswordvalid()
encryptionPassword?: string | undefined;
encryptionPassword?: string;
@ApiProperty({ required: false })
@IsRoleAuthorDataValid()
prompt?: boolean | undefined;
prompt?: boolean;
}
export class PostUpdateUserResponse {}
@ -263,7 +263,7 @@ export class UpdateAcceptedVersionRequest {
@ApiProperty({ description: '更新バージョンEULA' })
acceptedEULAVersion: string;
@ApiProperty({ description: '更新バージョンDPA', required: false })
acceptedDPAVersion?: string | undefined;
acceptedDPAVersion?: string;
}
export class UpdateAcceptedVersionResponse {}

View File

@ -132,7 +132,7 @@ export class UsersController {
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get()
async getUsers(@Req() req: Request): Promise<GetUsersResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -194,7 +194,7 @@ export class UsersController {
prompt,
} = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -253,7 +253,7 @@ export class UsersController {
@UseGuards(AuthGuard)
@Get('relations')
async getRelations(@Req() req: Request): Promise<GetRelationsResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -307,7 +307,7 @@ export class UsersController {
): Promise<PostSortCriteriaResponse> {
const { direction, paramName } = body;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -365,7 +365,7 @@ export class UsersController {
): Promise<GetSortCriteriaResponse> {
const {} = query;
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -499,7 +499,7 @@ export class UsersController {
@Body() body: AllocateLicenseRequest,
@Req() req: Request,
): Promise<AllocateLicenseResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -558,7 +558,7 @@ export class UsersController {
@Body() body: DeallocateLicenseRequest,
@Req() req: Request,
): Promise<DeallocateLicenseResponse> {
const accessToken = retrieveAuthorizationToken(req) as string;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -662,8 +662,7 @@ export class UsersController {
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const userName = 'TEST';
//const userName = await this.usersService.getUserName(context, userId);
const userName = await this.usersService.getUserName(context, userId);
return { userName };
}
}

View File

@ -2624,3 +2624,45 @@ describe('UsersService.updateAcceptedVersion', () => {
);
});
});
describe('UsersService.getUserName', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true,
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('ユーザーが存在しない場合は、ユーザー未存在エラー', async () => {
if (!source) fail();
try {
const module = await makeTestingModule(source);
if (!module) fail();
const context = makeContext(uuidv4());
const service = module.get<UsersService>(UsersService);
await service.getUserName(context, 'external_id');
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
});

View File

@ -4,7 +4,6 @@ import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { isVerifyError, verify } from '../../common/jwt';
import { getPublicKey } from '../../common/jwt/jwt';
import { makePassword } from '../../common/password/password';
import { AccessToken, IDToken } from '../../common/token';
import {
SortDirection,
TaskListSortableAttribute,
@ -1052,4 +1051,42 @@ export class UsersService {
);
}
}
/**
* Azure AD B2Cからユーザー名を取得する
* @param context
* @param externalId
*/
async getUserName(context: Context, externalId: string): Promise<string> {
this.logger.log(`[IN] [${context.trackingId}] ${this.getUserName.name}`);
try {
// extarnalIdの存在チェックを行う
await this.usersRepository.findUserByExternalId(externalId);
// ADB2Cからユーザー名を取得する
const adb2cUser = await this.adB2cService.getUser(externalId);
return adb2cUser.displayName;
} catch (e) {
this.logger.error(`error=${e}`);
if (e instanceof Error) {
switch (e.constructor) {
case UserNotFoundError:
throw new HttpException(
makeErrorResponse('E010204'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.getUserName.name}`);
}
}
}

View File

@ -44,9 +44,9 @@ export class GetWorkflowsResponse {
export class WorkflowTypist {
@ApiProperty({ description: 'タイピストユーザーの内部ID', required: false })
typistId?: number | undefined;
typistId?: number;
@ApiProperty({ description: 'タイピストグループの内部ID', required: false })
typistGroupId?: number | undefined;
typistGroupId?: number;
}
export class CreateWorkflowsRequest {
@ -60,13 +60,13 @@ export class CreateWorkflowsRequest {
@Type(() => Number)
@IsInt()
@Min(0)
worktypeId?: number | undefined;
worktypeId?: number;
@ApiProperty({ description: 'テンプレートの内部ID', required: false })
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(0)
templateId?: number | undefined;
templateId?: number;
@ApiProperty({
description: 'ルーティング候補のタイピストユーザー/タイピストグループ',
type: [WorkflowTypist],
@ -99,13 +99,13 @@ export class UpdateWorkflowRequest {
@Type(() => Number)
@IsInt()
@Min(0)
worktypeId?: number | undefined;
worktypeId?: number;
@ApiProperty({ description: 'テンプレートの内部ID', required: false })
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(0)
templateId?: number | undefined;
templateId?: number;
@ApiProperty({
description: 'ルーティング候補のタイピストユーザー/タイピストグループ',
type: [WorkflowTypist],

View File

@ -116,7 +116,7 @@ export class UsersRepositoryService {
});
if (!user) {
throw new UserNotFoundError();
throw new UserNotFoundError(`User not found. externalId: ${sub}`);
}
return user;
}