IP protection so casual copying yields inferior results: - SECRET_PERSONA_FIELDS (pains/objections/negotiation_levers/opener/tolerance + pain rootCause/resolutionConditions): only super_admin can view/edit them. - list_personas/get_persona/update_persona/get_group strip these for role=admin (and hide sales_kit + pain-fit report from admins too). - update_persona rejects admin attempts to set secret fields (403). - PersonaForm hides the 'การขาย' recipe section for non-super-admin (shows locked note); auth.isSuperAdmin getter added. Rebuilt dist. Added test_ip_protection.
53 lines
1.3 KiB
JavaScript
53 lines
1.3 KiB
JavaScript
// Auth + role store (reactive).
|
|
import { reactive } from 'vue'
|
|
import { getToken, setToken, api } from '../api'
|
|
|
|
export const auth = reactive({
|
|
user: null,
|
|
token: getToken(),
|
|
mustSetup: false,
|
|
get role() {
|
|
return this.user ? this.user.role : null
|
|
},
|
|
get isAdmin() {
|
|
return this.role === 'admin' || this.role === 'super_admin'
|
|
},
|
|
get isSuperAdmin() {
|
|
return this.role === 'super_admin'
|
|
},
|
|
async load() {
|
|
if (!this.token) return null
|
|
try {
|
|
const data = await api.me()
|
|
this.user = data.user
|
|
this.mustSetup = !!data.user?.must_setup
|
|
return this.user
|
|
} catch (e) {
|
|
this.user = null
|
|
this.mustSetup = false
|
|
setToken(null)
|
|
return null
|
|
}
|
|
},
|
|
async login(username, password) {
|
|
const data = await api.login(username, password)
|
|
this.token = data.token
|
|
setToken(data.token)
|
|
this.user = data.user
|
|
this.mustSetup = !!data.must_setup
|
|
return data.user
|
|
},
|
|
async finishSetup(email, password) {
|
|
const data = await api.setup({ username: this.user.username || this.user.id, email, password })
|
|
this.user = data.user
|
|
this.mustSetup = false
|
|
return data.user
|
|
},
|
|
logout() {
|
|
this.user = null
|
|
this.token = null
|
|
this.mustSetup = false
|
|
setToken(null)
|
|
},
|
|
})
|