@things-factory/integration-label-studio 9.1.19

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/EXTERNAL_DATA_SOURCING.md +484 -0
  3. package/IMPLEMENTATION_GUIDE.md +469 -0
  4. package/INTEGRATION.md +279 -0
  5. package/README.md +1014 -0
  6. package/SETUP_GUIDE.md +577 -0
  7. package/TEST_GUIDE.md +387 -0
  8. package/UI_CUSTOMIZATION.md +395 -0
  9. package/USER_SYNC_GUIDE.md +514 -0
  10. package/client/bootstrap.ts +1 -0
  11. package/client/index.ts +1 -0
  12. package/client/label-studio-label-page.ts +52 -0
  13. package/client/label-studio-project-create.ts +216 -0
  14. package/client/label-studio-project-list.ts +214 -0
  15. package/client/label-studio-wrapper.ts +294 -0
  16. package/client/route.ts +15 -0
  17. package/client/tsconfig.json +13 -0
  18. package/config/config.development.js +124 -0
  19. package/config/config.production.js +182 -0
  20. package/dist-client/bootstrap.d.ts +1 -0
  21. package/dist-client/bootstrap.js +2 -0
  22. package/dist-client/bootstrap.js.map +1 -0
  23. package/dist-client/index.d.ts +1 -0
  24. package/dist-client/index.js +2 -0
  25. package/dist-client/index.js.map +1 -0
  26. package/dist-client/label-studio-label-page.d.ts +8 -0
  27. package/dist-client/label-studio-label-page.js +54 -0
  28. package/dist-client/label-studio-label-page.js.map +1 -0
  29. package/dist-client/label-studio-project-create.d.ts +16 -0
  30. package/dist-client/label-studio-project-create.js +235 -0
  31. package/dist-client/label-studio-project-create.js.map +1 -0
  32. package/dist-client/label-studio-project-list.d.ts +16 -0
  33. package/dist-client/label-studio-project-list.js +222 -0
  34. package/dist-client/label-studio-project-list.js.map +1 -0
  35. package/dist-client/label-studio-wrapper.d.ts +57 -0
  36. package/dist-client/label-studio-wrapper.js +304 -0
  37. package/dist-client/label-studio-wrapper.js.map +1 -0
  38. package/dist-client/route.d.ts +1 -0
  39. package/dist-client/route.js +14 -0
  40. package/dist-client/route.js.map +1 -0
  41. package/dist-client/tsconfig.tsbuildinfo +1 -0
  42. package/dist-server/controller/label-studio-role-mapper.d.ts +35 -0
  43. package/dist-server/controller/label-studio-role-mapper.js +65 -0
  44. package/dist-server/controller/label-studio-role-mapper.js.map +1 -0
  45. package/dist-server/controller/user-provisioning-service.d.ts +66 -0
  46. package/dist-server/controller/user-provisioning-service.js +264 -0
  47. package/dist-server/controller/user-provisioning-service.js.map +1 -0
  48. package/dist-server/index.d.ts +7 -0
  49. package/dist-server/index.js +19 -0
  50. package/dist-server/index.js.map +1 -0
  51. package/dist-server/route/label-studio-sso.d.ts +2 -0
  52. package/dist-server/route/label-studio-sso.js +156 -0
  53. package/dist-server/route/label-studio-sso.js.map +1 -0
  54. package/dist-server/route/webhook.d.ts +65 -0
  55. package/dist-server/route/webhook.js +248 -0
  56. package/dist-server/route/webhook.js.map +1 -0
  57. package/dist-server/route.d.ts +1 -0
  58. package/dist-server/route.js +21 -0
  59. package/dist-server/route.js.map +1 -0
  60. package/dist-server/service/ai-prediction-service.d.ts +27 -0
  61. package/dist-server/service/ai-prediction-service.js +222 -0
  62. package/dist-server/service/ai-prediction-service.js.map +1 -0
  63. package/dist-server/service/dataset-labeling-integration.d.ts +44 -0
  64. package/dist-server/service/dataset-labeling-integration.js +512 -0
  65. package/dist-server/service/dataset-labeling-integration.js.map +1 -0
  66. package/dist-server/service/external-data-source-service.d.ts +78 -0
  67. package/dist-server/service/external-data-source-service.js +415 -0
  68. package/dist-server/service/external-data-source-service.js.map +1 -0
  69. package/dist-server/service/index.d.ts +12 -0
  70. package/dist-server/service/index.js +27 -0
  71. package/dist-server/service/index.js.map +1 -0
  72. package/dist-server/service/label-studio-sso-service.d.ts +38 -0
  73. package/dist-server/service/label-studio-sso-service.js +98 -0
  74. package/dist-server/service/label-studio-sso-service.js.map +1 -0
  75. package/dist-server/service/ml/ml-backend-service.d.ts +23 -0
  76. package/dist-server/service/ml/ml-backend-service.js +153 -0
  77. package/dist-server/service/ml/ml-backend-service.js.map +1 -0
  78. package/dist-server/service/prediction/prediction-management.d.ts +32 -0
  79. package/dist-server/service/prediction/prediction-management.js +299 -0
  80. package/dist-server/service/prediction/prediction-management.js.map +1 -0
  81. package/dist-server/service/project/project-management.d.ts +36 -0
  82. package/dist-server/service/project/project-management.js +309 -0
  83. package/dist-server/service/project/project-management.js.map +1 -0
  84. package/dist-server/service/task/task-management.d.ts +42 -0
  85. package/dist-server/service/task/task-management.js +372 -0
  86. package/dist-server/service/task/task-management.js.map +1 -0
  87. package/dist-server/service/user-provisioning/user-sync-mutation.d.ts +28 -0
  88. package/dist-server/service/user-provisioning/user-sync-mutation.js +111 -0
  89. package/dist-server/service/user-provisioning/user-sync-mutation.js.map +1 -0
  90. package/dist-server/service/webhook/webhook-management.d.ts +21 -0
  91. package/dist-server/service/webhook/webhook-management.js +134 -0
  92. package/dist-server/service/webhook/webhook-management.js.map +1 -0
  93. package/dist-server/tsconfig.tsbuildinfo +1 -0
  94. package/dist-server/types/dataset-labeling-types.d.ts +71 -0
  95. package/dist-server/types/dataset-labeling-types.js +259 -0
  96. package/dist-server/types/dataset-labeling-types.js.map +1 -0
  97. package/dist-server/types/label-studio-types.d.ts +128 -0
  98. package/dist-server/types/label-studio-types.js +494 -0
  99. package/dist-server/types/label-studio-types.js.map +1 -0
  100. package/dist-server/types/prediction-types.d.ts +39 -0
  101. package/dist-server/types/prediction-types.js +121 -0
  102. package/dist-server/types/prediction-types.js.map +1 -0
  103. package/dist-server/utils/annotation-exporter.d.ts +104 -0
  104. package/dist-server/utils/annotation-exporter.js +261 -0
  105. package/dist-server/utils/annotation-exporter.js.map +1 -0
  106. package/dist-server/utils/label-config-builder.d.ts +117 -0
  107. package/dist-server/utils/label-config-builder.js +286 -0
  108. package/dist-server/utils/label-config-builder.js.map +1 -0
  109. package/dist-server/utils/label-studio-api-client.d.ts +180 -0
  110. package/dist-server/utils/label-studio-api-client.js +401 -0
  111. package/dist-server/utils/label-studio-api-client.js.map +1 -0
  112. package/dist-server/utils/media-url-extractor.d.ts +45 -0
  113. package/dist-server/utils/media-url-extractor.js +152 -0
  114. package/dist-server/utils/media-url-extractor.js.map +1 -0
  115. package/dist-server/utils/task-transformer.d.ts +108 -0
  116. package/dist-server/utils/task-transformer.js +260 -0
  117. package/dist-server/utils/task-transformer.js.map +1 -0
  118. package/package.json +47 -0
  119. package/server/SERVER_STRUCTURE.md +351 -0
  120. package/server/controller/label-studio-role-mapper.ts +76 -0
  121. package/server/controller/user-provisioning-service.ts +340 -0
  122. package/server/index.ts +19 -0
  123. package/server/route/label-studio-sso.ts +194 -0
  124. package/server/route/webhook.ts +304 -0
  125. package/server/route.ts +35 -0
  126. package/server/service/ai-prediction-service.ts +239 -0
  127. package/server/service/dataset-labeling-integration.ts +590 -0
  128. package/server/service/external-data-source-service.ts +438 -0
  129. package/server/service/index.ts +24 -0
  130. package/server/service/label-studio-sso-service.ts +108 -0
  131. package/server/service/labeling-scenario-service.ts.deprecated +566 -0
  132. package/server/service/ml/ml-backend-service.ts +127 -0
  133. package/server/service/prediction/prediction-management.ts +281 -0
  134. package/server/service/project/project-management.ts +284 -0
  135. package/server/service/task/task-management.ts +363 -0
  136. package/server/service/user-provisioning/user-sync-mutation.ts +80 -0
  137. package/server/service/webhook/webhook-management.ts +109 -0
  138. package/server/tsconfig.json +11 -0
  139. package/server/types/dataset-labeling-types.ts +181 -0
  140. package/server/types/global.d.ts +23 -0
  141. package/server/types/label-studio-types.ts +346 -0
  142. package/server/types/prediction-types.ts +86 -0
  143. package/server/types/scenario-types.ts.deprecated +362 -0
  144. package/server/utils/annotation-exporter.ts +340 -0
  145. package/server/utils/label-config-builder.ts +340 -0
  146. package/server/utils/label-studio-api-client.ts +487 -0
  147. package/server/utils/media-url-extractor.ts +193 -0
  148. package/server/utils/task-transformer.ts +342 -0
  149. package/test-ai-prediction.js +268 -0
  150. package/test-dataset-integration.js +449 -0
  151. package/test-simple.js +89 -0
  152. package/things-factory.config.js +12 -0
@@ -0,0 +1,351 @@
1
+ # Label Studio Integration - Server 모듈 구조
2
+
3
+ Things-Factory Label Studio 통합 서버 모듈의 최종 정리된 구조입니다.
4
+
5
+ ---
6
+
7
+ ## 📁 디렉토리 구조
8
+
9
+ ```
10
+ server/
11
+ ├── controller/ # 비즈니스 로직
12
+ │ └── label-studio-role-mapper.ts # 권한 매핑 로직
13
+ ├── service/ # GraphQL 서비스
14
+ │ ├── user-provisioning/
15
+ │ │ ├── user-provisioning-service.ts # 사용자 동기화 서비스
16
+ │ │ ├── user-sync-mutation.ts # GraphQL Mutation
17
+ │ │ └── index.ts
18
+ │ └── index.ts # 서비스 통합
19
+ ├── index.ts # 서버 모듈 진입점
20
+ └── route.ts # 메뉴 등록
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 📋 파일별 역할
26
+
27
+ ### 1. **controller/label-studio-role-mapper.ts**
28
+
29
+ Things-Factory 사용자 권한을 Label Studio 권한으로 매핑
30
+
31
+ **주요 기능**:
32
+
33
+ - `mapUserPermissions(domain, user)`: 권한 매핑
34
+ - `getPermissionsDescription(permissions)`: 권한 설명
35
+
36
+ **매핑 규칙**:
37
+
38
+ ```typescript
39
+ // 1. label-studio 카테고리 권한 있음 → Staff
40
+ // 2. user.owner === true → Admin
41
+ ```
42
+
43
+ **반환값**:
44
+
45
+ ```typescript
46
+ interface LabelStudioPermissions {
47
+ is_superuser: boolean // Admin 여부
48
+ is_staff: boolean // Django admin 접근
49
+ is_active: boolean // 활성화 여부
50
+ }
51
+ ```
52
+
53
+ ---
54
+
55
+ ### 2. **service/user-provisioning/user-provisioning-service.ts**
56
+
57
+ Label Studio API를 통한 사용자 동기화 서비스
58
+
59
+ **주요 메서드**:
60
+
61
+ #### `syncUser(domain, user): Promise<SyncResult>`
62
+
63
+ 개별 사용자를 Label Studio에 동기화
64
+
65
+ ```typescript
66
+ // 1. 권한 확인
67
+ const hasLSPrivilege = await User.hasPrivilege('label-studio', ...)
68
+
69
+ // 2. 권한 매핑
70
+ const lsPermissions = await LabelStudioRoleMapper.mapUserPermissions(domain, user)
71
+
72
+ // 3. Label Studio API 호출
73
+ const result = await createOrUpdateLabelStudioUser(...)
74
+ ```
75
+
76
+ #### `syncAllUsers(domain): Promise<SyncSummary>`
77
+
78
+ 도메인의 모든 사용자를 일괄 동기화
79
+
80
+ ```typescript
81
+ const users = await getDomainUsers(domain)
82
+ for (const user of users) {
83
+ await syncUser(domain, user)
84
+ }
85
+ ```
86
+
87
+ #### `getDomainUsers(domain): Promise<User[]>`
88
+
89
+ 도메인의 모든 사용자 조회 (users_domains 테이블 조인)
90
+
91
+ **Helper 메서드**:
92
+
93
+ - `createOrUpdateLabelStudioUser()`: 사용자 생성/수정
94
+ - `deactivateUser()`: 사용자 비활성화
95
+ - `buildApiUrl()`: API URL 생성
96
+ - `generateRandomPassword()`: 랜덤 패스워드 생성
97
+ - `sleep()`: Rate Limiting 방지
98
+
99
+ ---
100
+
101
+ ### 3. **service/user-provisioning/user-sync-mutation.ts**
102
+
103
+ GraphQL Mutation 정의
104
+
105
+ **Mutations**:
106
+
107
+ #### `syncMyUserToLabelStudio`
108
+
109
+ ```graphql
110
+ mutation {
111
+ syncMyUserToLabelStudio {
112
+ success
113
+ email
114
+ action
115
+ lsPermissions
116
+ }
117
+ }
118
+ ```
119
+
120
+ **권한**: `@privilege(category: "label-studio", privilege: "staff")`
121
+
122
+ #### `syncAllUsersToLabelStudio`
123
+
124
+ ```graphql
125
+ mutation {
126
+ syncAllUsersToLabelStudio {
127
+ total
128
+ created
129
+ updated
130
+ deactivated
131
+ skipped
132
+ errors
133
+ results {
134
+ email
135
+ action
136
+ lsPermissions
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ **권한**: `@privilege(category: "label-studio", privilege: "admin")`
143
+
144
+ ---
145
+
146
+ ### 4. **service/index.ts**
147
+
148
+ GraphQL 리졸버 통합
149
+
150
+ ```typescript
151
+ export const resolvers = [UserSyncMutation]
152
+ export * from './user-provisioning/index.js'
153
+ ```
154
+
155
+ ---
156
+
157
+ ### 5. **index.ts**
158
+
159
+ 서버 모듈 진입점
160
+
161
+ ```typescript
162
+ export * from './service/index.js'
163
+ import './route.js'
164
+ ```
165
+
166
+ ---
167
+
168
+ ## 🔄 데이터 흐름
169
+
170
+ ### 사용자 동기화 플로우
171
+
172
+ ```
173
+ 1. GraphQL Mutation 호출
174
+
175
+ 2. user-sync-mutation.ts
176
+ - 설정 검증 (apiToken 확인)
177
+
178
+ 3. user-provisioning-service.ts
179
+ - 권한 확인 (User.hasPrivilege)
180
+
181
+ 4. label-studio-role-mapper.ts
182
+ - 권한 매핑 (label-studio 카테고리 → Staff/Admin)
183
+
184
+ 5. Label Studio API 호출
185
+ - POST/PATCH /api/users
186
+ - is_superuser, is_staff, is_active 설정
187
+
188
+ 6. 결과 반환
189
+ - SyncResult / SyncSummary
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 🔧 설정
195
+
196
+ ### config/config.development.js
197
+
198
+ ```javascript
199
+ labelStudio: {
200
+ serverUrl: 'http://localhost:8080',
201
+ apiToken: '', // Label Studio API Token
202
+ interfaces: 'panel,controls,annotations:menu'
203
+ }
204
+ ```
205
+
206
+ ### 설정 사용
207
+
208
+ ```typescript
209
+ import { config } from '@things-factory/env'
210
+
211
+ const labelStudioConfig = config.get('labelStudio', {
212
+ serverUrl: '',
213
+ apiToken: '',
214
+ interfaces: 'panel,controls,annotations:menu'
215
+ })
216
+ ```
217
+
218
+ ---
219
+
220
+ ## 🗑️ 제거된 항목
221
+
222
+ ### 1. **LabelStudioConfig Entity**
223
+
224
+ - 엔티티 DB 저장 제거
225
+ - config 파일로 대체
226
+
227
+ ### 2. **label-studio-config 폴더**
228
+
229
+ - `label-studio-config.ts` (Entity)
230
+ - `label-studio-config-query.ts` (Query)
231
+ - `label-studio-config-mutation.ts` (Mutation)
232
+
233
+ ### 3. **role-mapping 폴더**
234
+
235
+ - `label-studio-role-mapper.ts` → controller로 이동
236
+
237
+ ### 4. **불필요한 메서드**
238
+
239
+ - `getOrganizationId()` - Community Edition 미사용
240
+ - `createOrganizationMembership()` - Community Edition 미사용
241
+ - `updateOrganizationMembership()` - Community Edition 미사용
242
+
243
+ ### 5. **entities 배열**
244
+
245
+ - `service/index.ts`의 빈 entities 배열 제거
246
+
247
+ ---
248
+
249
+ ## 📊 권한 체계
250
+
251
+ ### Things-Factory 권한
252
+
253
+ | Privilege Category | 설명 |
254
+ | ----------------------- | ---------------------- |
255
+ | `label-studio:query` | Label Studio 조회 권한 |
256
+ | `label-studio:mutation` | Label Studio 수정 권한 |
257
+ | `label-studio:staff` | Staff 전용 mutation |
258
+ | `label-studio:admin` | Admin 전용 mutation |
259
+
260
+ ### Label Studio 권한 (Community Edition)
261
+
262
+ | 플래그 | 설명 |
263
+ | --------------------- | ----------------- |
264
+ | `is_superuser: true` | Admin (모든 권한) |
265
+ | `is_superuser: false` | Staff (라벨링만) |
266
+ | `is_active: false` | 비활성화 |
267
+
268
+ ---
269
+
270
+ ## 🧪 테스트
271
+
272
+ ### 1. 개인 동기화
273
+
274
+ ```graphql
275
+ mutation {
276
+ syncMyUserToLabelStudio {
277
+ success
278
+ email
279
+ action
280
+ lsPermissions
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### 2. 전체 동기화
286
+
287
+ ```graphql
288
+ mutation {
289
+ syncAllUsersToLabelStudio {
290
+ total
291
+ created
292
+ updated
293
+ results {
294
+ email
295
+ lsPermissions
296
+ error
297
+ }
298
+ }
299
+ }
300
+ ```
301
+
302
+ ---
303
+
304
+ ## 📝 코드 규칙
305
+
306
+ ### 1. 권한 확인
307
+
308
+ ```typescript
309
+ // User.hasPrivilege 사용
310
+ const hasPrivilege = await User.hasPrivilege('label-studio', 'query', domain, user)
311
+ ```
312
+
313
+ ### 2. 설정 가져오기
314
+
315
+ ```typescript
316
+ // config.get 사용
317
+ const config = config.get('labelStudio', {
318
+ serverUrl: '',
319
+ apiToken: '',
320
+ interfaces: 'panel,controls,annotations:menu'
321
+ })
322
+ ```
323
+
324
+ ### 3. API 호출
325
+
326
+ ```typescript
327
+ // axios 사용
328
+ await axios.patch(`${apiUrl}/users/${id}/`, data, {
329
+ headers: {
330
+ Authorization: `Token ${config.apiToken}`,
331
+ 'Content-Type': 'application/json'
332
+ }
333
+ })
334
+ ```
335
+
336
+ ---
337
+
338
+ ## 🚀 향후 확장
339
+
340
+ ### 가능한 개선사항
341
+
342
+ 1. **Batch API 지원**: 여러 사용자 한 번에 동기화
343
+ 2. **Webhook 연동**: Label Studio → Things-Factory 이벤트
344
+ 3. **동기화 스케줄러**: 주기적 자동 동기화
345
+ 4. **에러 재시도 로직**: 실패 시 재시도
346
+
347
+ ---
348
+
349
+ **문서 버전**: 1.0
350
+ **작성일**: 2025-10-03
351
+ **정리 완료**: ✅
@@ -0,0 +1,76 @@
1
+ import { Domain } from '@things-factory/shell'
2
+ import { User } from '@things-factory/auth-base'
3
+ /**
4
+ * Label Studio Community Edition 권한
5
+ * Community Edition은 Django의 is_superuser 플래그만 사용
6
+ */
7
+ export interface LabelStudioPermissions {
8
+ is_superuser: boolean // true: 관리자, false: 일반 사용자
9
+ is_staff: boolean // Django admin 페이지 접근 (일반적으로 is_superuser와 동일)
10
+ is_active: boolean // 활성화 여부
11
+ }
12
+
13
+ /**
14
+ * Things-Factory Role → Label Studio Permissions 매핑
15
+ * Community Edition용 (2단계 권한)
16
+ */
17
+ export class LabelStudioRoleMapper {
18
+ /**
19
+ * Things-Factory 사용자의 권한을 분석하여 Label Studio 권한 결정
20
+ *
21
+ * 매핑 규칙:
22
+ * 1. privilege category에 'label-studio'가 포함되어 있으면 → Staff 권한
23
+ * 2. user.admin === true 이면 → Admin 권한
24
+ *
25
+ * @param user Things-Factory 사용자
26
+ * @returns Label Studio 권한 (is_superuser, is_staff, is_active)
27
+ */
28
+ static async mapUserPermissions(domain: Domain, user: User): Promise<LabelStudioPermissions> {
29
+ // 사용자의 권한 조회
30
+ // 1. Label Studio 관련 권한이 있는지 확인 (category에 'label-studio' 포함)
31
+ const hasLabelStudioPrivilege =
32
+ (await User.hasPrivilege('label-studio', 'query', domain, user)) ||
33
+ (await User.hasPrivilege('label-studio', 'mutation', domain, user))
34
+
35
+ // Label Studio 권한이 없으면 비활성화
36
+ if (!hasLabelStudioPrivilege) {
37
+ return {
38
+ is_superuser: false,
39
+ is_staff: false,
40
+ is_active: false
41
+ }
42
+ }
43
+
44
+ // 2. user.owner 플래그 확인
45
+ if (user.owner === true) {
46
+ return {
47
+ is_superuser: true,
48
+ is_staff: true,
49
+ is_active: true
50
+ }
51
+ }
52
+
53
+ // 3. Label Studio 권한은 있지만 owner가 아닌 경우 → Staff
54
+ return {
55
+ is_superuser: false,
56
+ is_staff: false,
57
+ is_active: true
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Label Studio 권한 설명 반환 (디버깅/로깅용)
63
+ *
64
+ * @param permissions Label Studio 권한
65
+ * @returns 권한 설명
66
+ */
67
+ static getPermissionsDescription(permissions: LabelStudioPermissions): string {
68
+ if (!permissions.is_active) {
69
+ return 'Inactive (No Label Studio access)'
70
+ }
71
+ if (permissions.is_superuser) {
72
+ return 'Admin (Full access)'
73
+ }
74
+ return 'Staff (Labeling only)'
75
+ }
76
+ }