Ports "تکمیل پروفایل" end to end (D22). API - POST customer/me/complete-profile — three required document ids, the customer taken from the token, verification step set to the reference's LIVE value (approved outright; its `= 1` line is commented out at :83 in favour of `= 2` at :85). Both SMS messages byte-identical and non-blocking per D20. - POST customer/me/documents — the reference let the app upload through the same file/create the admin used, inside its auth:api-customer group (routes/api.php:95); the target's copy is admin-guarded, so the page could not have uploaded at all. Reuses AdminUploadsService unchanged, so both paths share one size limit, MIME whitelist and naming scheme (UPL-01). - PROFILE_ADMIN_MOBILES replaces the reference's four hardcoded personal numbers; blank means nobody is notified and the upload still succeeds. Three reference behaviours deliberately NOT ported, all in ISSUES.md: - SEC-14: `$customer->update($request->all())` mass-assigned the whole request body, letting the app write its own credit limit, making charge, gold debt, active flag or mobile. Replaced with a three-field whitelist. - SEC-15: four real personal mobiles hardcoded in the source. - APP-03: refresh()'s unterminated setInterval page reload. Apps (both, template+script byte-identical, per-app styling only) - CompleteProfileView + SingleImageUploader - route /complete_profile, redirecting home once the documents are in, as the reference's guard did (router/index.ts:266) - the entry point on the profile screen, shown only while they are missing (profile.vue:96-102) Also (D23): JWT_CUSTOMER_SECRET now warns loudly at boot when unset. It falls back to JWT_SECRET, which signs app and admin tokens with the same key and leaves the `typ` check as the only barrier — and an expert's app token carries their AdminUser id in `sub`. Warn rather than refuse to boot (D19, lowest risk); DELIVERY.md lists it as the first pre-release step (REL-03). Verified: build 5/5 · jest 45/45 · complete-profile 38/38 (new) · expert login 36/36 · apps smoke 43/43 · admin smoke 43/43 · B2B scan 34 ok/0 broken · typecheck clean on all four apps. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 lines
5.0 KiB
JavaScript
2 lines
5.0 KiB
JavaScript
import{$ as O,a0 as T,a1 as I,C as S,a2 as U,a3 as V,k as l,a4 as j,d as $,i as _,c as m,e as z,b as c,I as B,t as x,f as w,g as d,q as D,_ as N,s as h,a5 as E,j as R,v as A,y as L}from"./index-0lMAZRQB.js";import{P as M}from"./PageBar-DP6LpIFv.js";import{a as q}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{s as W}from"./index-W8LzFWDq.js";import"./_commonjsHelpers-Cpj98o6Y.js";function X(){const e=S({show:!1}),o=a=>{e.show=a},s=a=>{I(e,a,{transitionAppear:!0}),o(!0)},u=()=>o(!1);return T({open:s,close:u,toggle:o}),{open:s,close:u,state:e,toggle:o}}function Y(e){const o=O(e),s=document.createElement("div");return document.body.appendChild(s),{instance:o.mount(s),unmount(){o.unmount(),document.body.removeChild(s)}}}let P,v;const F=e=>V(e)?e:{message:e};function G(){({instance:v}=Y({setup(){const{state:e,toggle:o}=X();return()=>l(W,j(e,{"onUpdate:show":o}),null)}}))}const H=()=>({type:"danger",color:void 0,message:"",onClose:void 0,onClick:void 0,onOpened:void 0,duration:3e3,position:void 0,className:"",lockScroll:!1,background:void 0});let J=H();const K=()=>{v&&v.toggle(!1)};function Q(e){if(U)return v||G(),e=I({},J,F(e)),v.open(e),clearTimeout(P),e.duration>0&&(P=setTimeout(K,e.duration)),v}const Z=["disabled"],ee=["src"],se={key:1,class:"siu__icon"},te={class:"siu__text"},oe={key:2,class:"siu__badge"},ne={key:0,class:"siu__error"},ae=8*1024*1024,ie=$({__name:"SingleImageUploader",props:{uploadText:{},purpose:{}},emits:["done"],setup(e,{emit:o}){const s=e,u=o,a=d(null),i=d(!1),r=d(null),p=d(null),g=d(null);async function t(y){var b;const n=y.target,f=(b=n.files)==null?void 0:b[0];if(n.value="",!!f){if(r.value=null,f.size>ae){r.value="حجم فایل بیش از حد مجاز است (۸ مگابایت)";return}i.value=!0;try{const C=await D.uploadDocument(f,s.purpose);p.value=C.id,g.value=f.type.startsWith("image/")?URL.createObjectURL(f):null,u("done",C.id)}catch{r.value="بارگذاری انجام نشد. دوباره تلاش کنید.",p.value=null,g.value=null}finally{i.value=!1}}}return(y,n)=>(_(),m("div",{class:z(["siu",{"is-done":!!p.value,"is-error":!!r.value}])},[c("input",{ref_key:"input",ref:a,type:"file",accept:"image/jpeg,image/png,image/webp,application/pdf",class:"siu__input",onChange:t},null,544),c("button",{type:"button",class:"siu__box",disabled:i.value,onClick:n[0]||(n[0]=f=>{var b;return(b=a.value)==null?void 0:b.click()})},[g.value?(_(),m("img",{key:0,src:g.value,class:"siu__preview",alt:""},null,8,ee)):(_(),m("span",se,[l(B,{icon:i.value?"vuesax-linear:refresh":"vuesax-linear:gallery-add",size:"26"},null,8,["icon"])])),c("span",te,x(i.value?"در حال بارگذاری…":p.value?"تغییر تصویر":e.uploadText),1),p.value&&!i.value?(_(),m("span",oe,[l(B,{icon:"vuesax-linear:tick-circle",size:"16"})])):w("",!0)],8,Z),r.value?(_(),m("p",ne,x(r.value),1)):w("",!0)],2))}}),k=N(ie,[["__scopeId","data-v-186945da"]]),le={class:"cpf"},ue={key:0,class:"cpf__error"},re=["disabled"],ce=$({__name:"CompleteProfileView",setup(e){const o=L(),s=S({business_license_image_id:null,shop_image_id:null,ncode_image_id:null}),u=d(!1),a=d(!1),i=d(null);async function r(){if(i.value=null,!s.business_license_image_id||!s.shop_image_id||!s.ncode_image_id){Q("لطفا تمامی عکس های خواسته شده را آپلود کنید");return}u.value=!0;try{await D.completeProfile({business_license_image_id:s.business_license_image_id,shop_image_id:s.shop_image_id,ncode_image_id:s.ncode_image_id}),a.value=!0}catch{i.value="ثبت اطلاعات انجام نشد. دوباره تلاش کنید."}finally{u.value=!1}}function p(){a.value=!1,o.push({name:"home"})}return(g,t)=>{const y=A("container");return _(),m("div",le,[l(M,{title:"تکمیل پروفایل","back-to":"userPage::hasSubRoute"}),l(q,{spinning:u.value,tip:"در حال ثبت اطلاعات"},{default:h(()=>[l(y,{class:"cpf__body"},{default:h(()=>[t[4]||(t[4]=c("p",{class:"cpf__lead"}," برای تکمیل پروفایل، سه مدرک زیر را بارگذاری کنید. ",-1)),c("form",{class:"cpf__form",onSubmit:R(r,["prevent"])},[l(k,{"upload-text":"بارگذاری عکس جواز کسب",purpose:"business-license",onDone:t[0]||(t[0]=n=>s.business_license_image_id=n)}),l(k,{"upload-text":"بارگذاری عکس سردر مغازه",purpose:"shop-image",onDone:t[1]||(t[1]=n=>s.shop_image_id=n)}),l(k,{"upload-text":"بارگذاری عکس کارت ملی",purpose:"national-card",onDone:t[2]||(t[2]=n=>s.ncode_image_id=n)}),i.value?(_(),m("p",ue,x(i.value),1)):w("",!0),c("button",{type:"submit",class:"cpf__submit",disabled:u.value}," بارگذاری اطلاعات ",8,re)],32)]),_:1})]),_:1},8,["spinning"]),l(E,{show:a.value,"onUpdate:show":t[3]||(t[3]=n=>a.value=n),"time-out":-1,"close-on-click-overlay":!1},{title:h(()=>[...t[5]||(t[5]=[c("div",{class:"cpf__dialogText"}," تکمیل اطلاعات شما با موفقیت انجام شد. ",-1)])]),button:h(()=>[c("div",{class:"cpf__dialogBtn",onClick:p},"متوجه شدم")]),_:1},8,["show"])])}}}),ve=N(ce,[["__scopeId","data-v-11de2b30"]]);export{ve as default};
|