feat(auth): 后台登录、角色权限与会话访问策略
管理员与客服分角色登录,权限由后端判定;前端补齐登录、人员与组织管理页面。
This commit is contained in:
1 parent
5e0615f36d
commit
e24d3e2a65
123 files changed
+25293
No files matched your search
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
Copyright 2024-2026 ChatterMate
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import api from './api'
|
||||
import { apiPath } from '@/config/api'
|
||||
|
||||
/**
|
||||
* Check if Shopify is connected for the current organization
|
||||
*/
|
||||
export const checkShopifyConnection = async () => {
|
||||
try {
|
||||
// Gets the first connected shop to determine if Shopify is connected
|
||||
const response = await api.get('/shopify/shops?limit=1')
|
||||
const shops = response.data
|
||||
const isConnected = shops && shops.length > 0 && shops[0].is_installed
|
||||
|
||||
// Return connection status and shop domain if available
|
||||
return {
|
||||
connected: isConnected,
|
||||
shop_domain: isConnected ? shops[0].shop_domain : '',
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking Shopify connection:', error)
|
||||
return { connected: false }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Shopify authorization URL
|
||||
* User needs to provide their shop domain
|
||||
*/
|
||||
export const connectToShopify = (shopDomain: string) => {
|
||||
// Derive the store handle from the input (whether the user typed a bare
|
||||
// handle, a full *.myshopify.com host, or a URL) and rebuild the domain so
|
||||
// only a genuine <handle>.myshopify.com host can ever be used.
|
||||
const host = shopDomain.trim().toLowerCase().replace(/^https?:\/\//, '').split('/')[0]
|
||||
const handle = host.split('.')[0]
|
||||
shopDomain = `${handle}.myshopify.com`
|
||||
|
||||
// Reject anything that isn't a well-formed Shopify shop domain.
|
||||
if (!/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/.test(shopDomain)) {
|
||||
console.error('Invalid Shopify shop domain:', host)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect directly to the backend API for OAuth initiation
|
||||
// This bypasses the frontend router which requires authentication
|
||||
// apiPath() builds on the runtime API URL, which already includes /api/v1
|
||||
window.location.href = apiPath(`/shopify/auth?shop=${encodeURIComponent(shopDomain)}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect Shopify integration
|
||||
* This will remove all Shopify shops associated with the current organization
|
||||
*/
|
||||
export const disconnectShopify = async (shopId: string) => {
|
||||
try {
|
||||
// Assuming you'll create this endpoint
|
||||
const response = await api.delete(`/shopify/shops/${shopId}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error disconnecting Shopify:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all connected Shopify shops
|
||||
*/
|
||||
export const getShopifyShops = async () => {
|
||||
try {
|
||||
const response = await api.get('/shopify/shops')
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error getting Shopify shops:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save agent-to-Shopify configuration
|
||||
*/
|
||||
export const saveAgentShopifyConfig = async (agentId: string, config: {
|
||||
shop_id?: string;
|
||||
enabled: boolean;
|
||||
}) => {
|
||||
try {
|
||||
const response = await api.post(`/shopify/agent-config/${agentId}`, config)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error saving agent Shopify config:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get agent-to-Shopify configuration
|
||||
*/
|
||||
export const getAgentShopifyConfig = async (agentId: string) => {
|
||||
try {
|
||||
const response = await api.get(`/shopify/agent-config/${agentId}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error getting agent Shopify config:', error)
|
||||
return { enabled: false }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Shopify for multiple agents
|
||||
*/
|
||||
export const enableShopifyForAgents = async (agentIds: string[], shopId: string) => {
|
||||
try {
|
||||
const savePromises = agentIds.map(agentId =>
|
||||
saveAgentShopifyConfig(agentId, {
|
||||
shop_id: shopId,
|
||||
enabled: true
|
||||
})
|
||||
)
|
||||
|
||||
await Promise.all(savePromises)
|
||||
return { success: true, count: agentIds.length }
|
||||
} catch (error) {
|
||||
console.error('Error enabling Shopify for agents:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shop information from backend during auth flow
|
||||
*/
|
||||
export const getShopAuthInfo = async (shopDomain: string, embedded: boolean = true) => {
|
||||
try {
|
||||
const response = await api.get(`/shopify/auth?shop=${encodeURIComponent(shopDomain)}&embedded=${embedded ? 1 : 0}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error getting shop auth info:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shop configuration status (agents connected, widget ID, etc.)
|
||||
*/
|
||||
export const getShopConfigStatus = async (shopDomain: string, shopId?: string) => {
|
||||
try {
|
||||
const params = new URLSearchParams({ shop: shopDomain })
|
||||
if (shopId) {
|
||||
params.append('shop_id', shopId)
|
||||
}
|
||||
|
||||
const response = await api.get(`/shopify/shop-config-status?${params.toString()}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error('Error getting shop config status:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user