koishi-plugin-new-auth 0.2.0 → 0.3.1
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.
- package/README.md +6 -1
- package/dist/index.js +1 -1
- package/dist/style.css +1 -1
- package/lib/index.d.ts +11 -0
- package/lib/index.js +47 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,6 +80,11 @@ The page provides:
|
|
|
80
80
|
- pending command review;
|
|
81
81
|
- legacy `authority` suggestions;
|
|
82
82
|
- AI-style automatic assignment for pending commands;
|
|
83
|
-
- command status and guild override toggles
|
|
83
|
+
- command status and guild override toggles;
|
|
84
|
+
- custom role creation and explicit member management;
|
|
85
|
+
- copying command policies from one role to another;
|
|
86
|
+
- batch assigning all commands from one plugin.
|
|
84
87
|
|
|
85
88
|
The automatic assignment advisor is conservative: dangerous instance-level commands are kept for `bot-admin`, group moderation commands go to `guild-admin` and `guild-owner`, normal user commands go to `guild-member` and above, and unclear commands fall back to the legacy authority suggestion.
|
|
89
|
+
|
|
90
|
+
Custom roles do not inherit from built-in roles. Use the WebUI copy action, or `newauth.role.copy`, to clone the current explicit policies from another role.
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineComponent as H,ref as v,computed as c,watch as J,openBlock as o,createElementBlock as a,createElementVNode as t,toDisplayString as s,withDirectives as y,Fragment as m,renderList as x,vModelSelect as U,normalizeClass as g,createCommentVNode as G,vModelCheckbox as K,createTextVNode as T,vModelText as D}from"vue";import{store as E,send as k}from"@koishijs/client";const Q={class:"new-auth-page"},W={class:"topbar"},X={class:"top-actions"},Y=["value"],Z=["disabled"],ee=["disabled"],te={class:"tabs"},le={key:0,class:"error"},ne={key:1,class:"role-layout"},se={class:"role-list"},oe=["onClick"],ae={key:0,class:"detail"},ie={class:"detail-head"},ue={class:"check"},de={class:"filters"},re={class:"command-list"},ce={class:"command-main"},ve={class:"state-buttons"},pe=["onClick"],ge=["onClick"],he=["onClick"],_e={key:2,class:"pending-grid"},fe={class:"row-actions"},be=["disabled","onClick"],ye=["disabled","onClick"],ke={key:0,class:"empty"},Ce={key:3,class:"commands-table"},we={class:"filters"},me={class:"command-main"},xe={class:"command-controls"},Ae={class:"check"},Ie=["checked","onChange"],Ve=["value","onChange"],$e=H({__name:"new-auth",setup(C){const i=v("roles"),u=v("global"),d=v(""),p=v(""),h=v("all"),$=v(false),_=v(false),A=v(""),w=c(()=>E.newauth||{roles:[],commands:[],policies:[],scopes:[{id:"global",name:"全局默认"}],pendingCount:0}),I=c(()=>w.value.roles),P=c(()=>w.value.commands),L=c(()=>w.value.policies),B=c(()=>{var n;return(n=w.value.scopes)!=null&&n.length?w.value.scopes:[{id:"global",name:"全局默认"}]}),V=c(()=>P.value.filter(n=>n.status==="pending")),f=c(()=>I.value.find(n=>n.id===d.value));J(I,n=>{!d.value&&n.length&&(d.value=n[0].id)},{immediate:true});const M=c(()=>{const n=p.value.toLowerCase();return P.value.filter(l=>h.value!=="all"&&l.status!==h.value?false:n?[l.id,l.name,l.commandPath,l.plugin,l.description].some(e=>e==null?void 0:e.toLowerCase().includes(n)):true)}),F=c(()=>f.value?M.value.filter(n=>{var l,e;return $.value||((l=f.value)==null?void 0:l.id)==="bot-admin"||((e=f.value)==null?void 0:e.scopeType)==="global"?true:n.allowGuildOverride}):[]);function S(n){const l=L.value.find(e=>e.scope===u.value&&e.roleId===d.value&&e.commandId===n);return(l==null?void 0:l.state)||"inherit"}async function b(n){_.value=true,A.value="";try{await n}catch(l){A.value=l instanceof Error?l.message:String(l)}finally{_.value=false}}async function R(){return b((async()=>{const n=await k("newauth/getData");E.newauth=n})())}function O(n,l){return b(k("newauth/setPolicy",{scope:u.value,roleId:d.value,commandId:n,state:l}))}function N(n,l){return b(k("newauth/applySuggestion",{commandId:n,scope:u.value,mode:l}))}function q(){return b(k("newauth/autoAssignPending",{scope:u.value,mode:"advisor"}))}function z(n,l){const e=l.target;return b(k("newauth/setGuildOverride",{commandId:n.id,allowGuildOverride:e.checked}))}function j(n,l){const e=l.target;return b(k("newauth/setCommandStatus",{commandId:n.id,status:e.value}))}return(n,l)=>(o(),a("main",Q,[t("header",W,[t("div",null,[l[9]||(l[9]=t("h1",null,"新权限",-1)),t("p",null,s(I.value.length)+" 个角色 / "+s(P.value.length)+" 个指令 / "+s(V.value.length)+" 个待配置",1)]),t("div",X,[y(t("select",{"onUpdate:modelValue":l[0]||(l[0]=e=>u.value=e),class:"scope-select"},[(o(true),a(m,null,x(B.value,e=>(o(),a("option",{key:e.id,value:e.id},s(e.name),9,Y))),128))],512),[[U,u.value]]),t("button",{class:"primary",disabled:_.value||!V.value.length,onClick:q}," AI 自动分配待配置 ",8,Z),t("button",{disabled:_.value,onClick:R},"刷新",8,ee)])]),t("nav",te,[t("button",{class:g({active:i.value==="roles"}),onClick:l[1]||(l[1]=e=>i.value="roles")},"角色",2),t("button",{class:g({active:i.value==="pending"}),onClick:l[2]||(l[2]=e=>i.value="pending")},"待配置",2),t("button",{class:g({active:i.value==="commands"}),onClick:l[3]||(l[3]=e=>i.value="commands")},"指令",2)]),A.value?(o(),a("p",le,s(A.value),1)):G("v-if",true),i.value==="roles"?(o(),a("section",ne,[t("aside",se,[(o(true),a(m,null,x(I.value,e=>(o(),a("button",{key:e.id,class:g(["role-item",{active:e.id===d.value}]),onClick:r=>d.value=e.id},[t("span",null,[t("strong",null,s(e.name),1),t("small",null,s(e.builtin?"内置角色":"自定义角色")+" / "+s(e.scopeType),1)]),t("em",null,s(e.allowCount),1)],10,oe))),128))]),f.value?(o(),a("section",ae,[t("div",ie,[t("div",null,[t("h2",null,s(f.value.name),1),t("p",null,s(f.value.id),1)]),t("label",ue,[y(t("input",{type:"checkbox","onUpdate:modelValue":l[4]||(l[4]=e=>$.value=e)},null,512),[[K,$.value]]),l[10]||(l[10]=T(" 审计模式 ",-1))])]),t("div",de,[y(t("input",{"onUpdate:modelValue":l[5]||(l[5]=e=>p.value=e),placeholder:"搜索指令、插件、描述"},null,512),[[D,p.value,void 0,{trim:true}]]),y(t("select",{"onUpdate:modelValue":l[6]||(l[6]=e=>h.value=e)},[...l[11]||(l[11]=[t("option",{value:"all"},"全部状态",-1),t("option",{value:"pending"},"待配置",-1),t("option",{value:"configured"},"已配置",-1),t("option",{value:"disabled"},"已禁用",-1)])],512),[[U,h.value]])]),t("div",re,[(o(true),a(m,null,x(F.value,e=>(o(),a("article",{key:e.id,class:"command-row"},[t("div",ce,[t("strong",null,s(e.name),1),t("span",null,s(e.commandPath),1),t("small",null,s(e.plugin)+" / legacy "+s(e.legacyAuthority)+" / "+s(e.suggestion.label),1)]),t("div",ve,[t("button",{class:g({active:S(e.id)==="inherit"}),onClick:r=>O(e.id,"inherit")}," 继承 ",10,pe),t("button",{class:g({active:S(e.id)==="allow"}),onClick:r=>O(e.id,"allow")}," 开 ",10,ge),t("button",{class:g({active:S(e.id)==="deny"}),onClick:r=>O(e.id,"deny")}," 关 ",10,he)])]))),128))])])):G("v-if",true)])):i.value==="pending"?(o(),a("section",_e,[(o(true),a(m,null,x(V.value,e=>(o(),a("article",{key:e.id,class:"pending-item"},[t("div",null,[t("strong",null,s(e.name),1),t("span",null,s(e.commandPath),1),t("small",null,s(e.plugin)+" / legacy "+s(e.legacyAuthority),1)]),t("dl",null,[l[12]||(l[12]=t("dt",null,"旧建议",-1)),t("dd",null,s(e.suggestion.label),1),l[13]||(l[13]=t("dt",null,"AI 建议",-1)),t("dd",null,s(e.autoAssign.label)+":"+s(e.autoAssign.reason),1)]),t("div",fe,[t("button",{disabled:_.value,onClick:r=>N(e.id,"legacy")},"采用旧建议",8,be),t("button",{class:"primary",disabled:_.value,onClick:r=>N(e.id,"advisor")},"采用 AI 建议",8,ye)])]))),128)),V.value.length?G("v-if",true):(o(),a("p",ke,"没有待配置指令。"))])):(o(),a("section",Ce,[t("div",we,[y(t("input",{"onUpdate:modelValue":l[7]||(l[7]=e=>p.value=e),placeholder:"搜索指令、插件、描述"},null,512),[[D,p.value,void 0,{trim:true}]]),y(t("select",{"onUpdate:modelValue":l[8]||(l[8]=e=>h.value=e)},[...l[14]||(l[14]=[t("option",{value:"all"},"全部状态",-1),t("option",{value:"pending"},"待配置",-1),t("option",{value:"configured"},"已配置",-1),t("option",{value:"disabled"},"已禁用",-1)])],512),[[U,h.value]])]),(o(true),a(m,null,x(M.value,e=>(o(),a("article",{key:e.id,class:"command-row"},[t("div",me,[t("strong",null,s(e.name),1),t("span",null,s(e.id),1),t("small",null,s(e.plugin)+" / "+s(e.commandPath)+" / "+s(e.autoAssign.label),1)]),t("div",xe,[t("label",Ae,[t("input",{type:"checkbox",checked:e.allowGuildOverride,onChange:r=>z(e,r)},null,40,Ie),l[15]||(l[15]=T(" 群内自治 ",-1))]),t("select",{value:e.status,onChange:r=>j(e,r)},[...l[16]||(l[16]=[t("option",{value:"pending"},"待配置",-1),t("option",{value:"configured"},"已配置",-1),t("option",{value:"disabled"},"已禁用",-1)])],40,Ve)])]))),128))]))]))}}),Pe=(C,i)=>{const u=C.__vccOpts||C;for(const[d,p]of i)u[d]=p;return u},Se=Pe($e,[["__scopeId","data-v-b49c6f52"]]),Ge=C=>{C.page({name:"新权限",path:"/new-auth",icon:"⌗",fields:["newauth"],authority:4,component:Se})};export{Ge as default};
|
|
1
|
+
import{defineComponent as ve,ref as i,computed as v,watch as H,openBlock as s,createElementBlock as u,createElementVNode as l,toDisplayString as o,withDirectives as c,Fragment as f,renderList as y,vModelSelect as _,normalizeClass as w,createCommentVNode as B,withModifiers as J,vModelText as x,vModelCheckbox as ce,createTextVNode as q}from"vue";import{store as Q,send as g}from"@koishijs/client";const pe={class:"new-auth-page"},ge={class:"topbar"},be={class:"top-actions"},me=["value"],fe=["disabled"],ye=["disabled"],ke={class:"tabs"},he={key:0,class:"error"},_e={key:1,class:"role-layout"},we={class:"role-list"},Ce=["onClick"],Ie=["disabled"],$e={key:0,class:"detail"},Ve={class:"detail-head"},Se={class:"detail-tools"},Ue=["value"],Pe=["disabled"],Re={class:"check"},xe={class:"member-panel"},Ae={class:"member-list"},Me=["disabled","onClick"],Oe=["value"],Te=["disabled"],Ge={class:"filters"},Ne={class:"command-list"},Be={class:"command-main"},De={class:"state-buttons"},Ee=["onClick"],Le=["onClick"],Fe=["onClick"],qe={key:2,class:"pending-grid"},ze={class:"row-actions"},Ke=["disabled","onClick"],je=["disabled","onClick"],He={key:0,class:"empty"},Je={key:3,class:"commands-table"},Qe={class:"filters"},We={class:"plugin-bulk"},Xe=["value"],Ye=["disabled"],Ze=["disabled"],el=["disabled"],ll=["disabled"],tl={class:"command-main"},nl={class:"command-controls"},ol={class:"check"},sl=["checked","onChange"],ul=["value","onChange"],al=ve({__name:"new-auth",setup(S){const b=i("roles"),a=i("global"),d=i(""),k=i(""),C=i("all"),D=i(false),r=i(false),A=i(""),I=i(""),U=i(""),E=i("guild"),P=i(""),M=i("global"),O=i(""),h=i(""),$=v(()=>Q.newauth||{roles:[],commands:[],policies:[],members:[],scopes:[{id:"global",name:"全局默认"}],pendingCount:0}),R=v(()=>$.value.roles),T=v(()=>$.value.commands),W=v(()=>$.value.policies),X=v(()=>$.value.members),Y=v(()=>{var n;return(n=$.value.scopes)!=null&&n.length?$.value.scopes:[{id:"global",name:"全局默认"}]}),G=v(()=>T.value.filter(n=>n.status==="pending")),V=v(()=>R.value.find(n=>n.id===d.value)),z=v(()=>X.value.filter(n=>n.roleId===d.value)),Z=v(()=>R.value.filter(n=>n.id!==d.value)),ee=v(()=>[...new Set(T.value.map(n=>n.plugin))].sort());H(R,n=>{!d.value&&n.length&&(d.value=n[0].id)},{immediate:true}),H(a,n=>{M.value=n==="global"?"global":n});const K=v(()=>{const n=k.value.toLowerCase();return T.value.filter(t=>C.value!=="all"&&t.status!==C.value?false:n?[t.id,t.name,t.commandPath,t.plugin,t.description].some(e=>e==null?void 0:e.toLowerCase().includes(n)):true)}),le=v(()=>V.value?K.value.filter(n=>{var t,e;return D.value||((t=V.value)==null?void 0:t.id)==="bot-admin"||((e=V.value)==null?void 0:e.scopeType)==="global"?true:n.allowGuildOverride}):[]);function L(n){const t=W.value.find(e=>e.scope===a.value&&e.roleId===d.value&&e.commandId===n);return(t==null?void 0:t.state)||"inherit"}async function p(n){r.value=true,A.value="";try{await n}catch(t){A.value=t instanceof Error?t.message:String(t)}finally{r.value=false}}async function te(){return p((async()=>{const n=await g("newauth/getData");Q.newauth=n})())}function F(n,t){return p(g("newauth/setPolicy",{scope:a.value,roleId:d.value,commandId:n,state:t}))}function j(n,t){return p(g("newauth/applySuggestion",{commandId:n,scope:a.value,mode:t}))}function ne(){return p(g("newauth/autoAssignPending",{scope:a.value,mode:"advisor"}))}function oe(n,t){const e=t.target;return p(g("newauth/setGuildOverride",{commandId:n.id,allowGuildOverride:e.checked}))}function se(n,t){const e=t.target;return p(g("newauth/setCommandStatus",{commandId:n.id,status:e.value}))}function ue(){return p((async()=>{await g("newauth/createRole",{id:I.value,name:U.value,scopeType:E.value}),d.value=I.value,I.value="",U.value=""})())}function ae(){return p((async()=>{await g("newauth/addMember",{roleId:d.value,uid:P.value,scope:M.value}),P.value=""})())}function ie(n){return p(g("newauth/removeMember",{roleId:n.roleId,uid:`${n.platform}:${n.userId}`,scope:n.scope}))}function de(){return p(g("newauth/copyRolePolicies",{sourceRoleId:O.value,targetRoleId:d.value,scope:a.value}))}function re(n){return`${n.roleId}:${n.platform}:${n.userId}:${n.scope}`}function N(n){return p(g("newauth/assignPluginCommands",{plugin:h.value,scope:a.value,target:n}))}return(n,t)=>(s(),u("main",pe,[l("header",ge,[l("div",null,[t[20]||(t[20]=l("h1",null,"新权限",-1)),l("p",null,o(R.value.length)+" 个角色 / "+o(T.value.length)+" 个指令 / "+o(G.value.length)+" 个待配置",1)]),l("div",be,[c(l("select",{"onUpdate:modelValue":t[0]||(t[0]=e=>a.value=e),class:"scope-select"},[(s(true),u(f,null,y(Y.value,e=>(s(),u("option",{key:e.id,value:e.id},o(e.name),9,me))),128))],512),[[_,a.value]]),l("button",{class:"primary",disabled:r.value||!G.value.length,onClick:ne}," AI 自动分配待配置 ",8,fe),l("button",{disabled:r.value,onClick:te},"刷新",8,ye)])]),l("nav",ke,[l("button",{class:w({active:b.value==="roles"}),onClick:t[1]||(t[1]=e=>b.value="roles")},"角色",2),l("button",{class:w({active:b.value==="pending"}),onClick:t[2]||(t[2]=e=>b.value="pending")},"待配置",2),l("button",{class:w({active:b.value==="commands"}),onClick:t[3]||(t[3]=e=>b.value="commands")},"指令",2)]),A.value?(s(),u("p",he,o(A.value),1)):B("v-if",true),b.value==="roles"?(s(),u("section",_e,[l("aside",we,[(s(true),u(f,null,y(R.value,e=>(s(),u("button",{key:e.id,class:w(["role-item",{active:e.id===d.value}]),onClick:m=>d.value=e.id},[l("span",null,[l("strong",null,o(e.name),1),l("small",null,o(e.builtin?"内置角色":"自定义角色")+" / "+o(e.scopeType),1)]),l("em",null,o(e.allowCount),1)],10,Ce))),128)),l("form",{class:"role-create",onSubmit:J(ue,["prevent"])},[c(l("input",{"onUpdate:modelValue":t[4]||(t[4]=e=>I.value=e),placeholder:"custom:music-admin"},null,512),[[x,I.value,void 0,{trim:true}]]),c(l("input",{"onUpdate:modelValue":t[5]||(t[5]=e=>U.value=e),placeholder:"角色名称"},null,512),[[x,U.value,void 0,{trim:true}]]),c(l("select",{"onUpdate:modelValue":t[6]||(t[6]=e=>E.value=e)},[...t[21]||(t[21]=[l("option",{value:"guild"},"群内角色",-1),l("option",{value:"global"},"全局角色",-1)])],512),[[_,E.value]]),l("button",{class:"primary",disabled:r.value||!I.value||!U.value},"创建角色",8,Ie)],32)]),V.value?(s(),u("section",$e,[l("div",Ve,[l("div",null,[l("h2",null,o(V.value.name),1),l("p",null,o(V.value.id),1)]),l("div",Se,[c(l("select",{"onUpdate:modelValue":t[7]||(t[7]=e=>O.value=e)},[t[22]||(t[22]=l("option",{disabled:"",value:""},"复制来源",-1)),(s(true),u(f,null,y(Z.value,e=>(s(),u("option",{key:e.id,value:e.id},o(e.name),9,Ue))),128))],512),[[_,O.value]]),l("button",{disabled:r.value||!O.value,onClick:de},"复制权限",8,Pe),l("label",Re,[c(l("input",{type:"checkbox","onUpdate:modelValue":t[8]||(t[8]=e=>D.value=e)},null,512),[[ce,D.value]]),t[23]||(t[23]=q(" 审计模式 ",-1))])])]),l("section",xe,[l("div",null,[t[24]||(t[24]=l("strong",null,"成员",-1)),l("small",null,o(z.value.length)+" 个显式成员",1)]),l("div",Ae,[(s(true),u(f,null,y(z.value,e=>(s(),u("span",{key:re(e),class:"member-chip"},[q(o(e.platform)+":"+o(e.userId)+" / "+o(e.scope)+" ",1),l("button",{disabled:r.value,onClick:m=>ie(e)},"移除",8,Me)]))),128))]),l("form",{class:"member-add",onSubmit:J(ae,["prevent"])},[c(l("input",{"onUpdate:modelValue":t[9]||(t[9]=e=>P.value=e),placeholder:"platform:userId"},null,512),[[x,P.value,void 0,{trim:true}]]),c(l("select",{"onUpdate:modelValue":t[10]||(t[10]=e=>M.value=e)},[t[25]||(t[25]=l("option",{value:"global"},"global",-1)),a.value!=="global"?(s(),u("option",{key:0,value:a.value},o(a.value),9,Oe)):B("v-if",true)],512),[[_,M.value]]),l("button",{class:"primary",disabled:r.value||!P.value},"添加成员",8,Te)],32)]),l("div",Ge,[c(l("input",{"onUpdate:modelValue":t[11]||(t[11]=e=>k.value=e),placeholder:"搜索指令、插件、描述"},null,512),[[x,k.value,void 0,{trim:true}]]),c(l("select",{"onUpdate:modelValue":t[12]||(t[12]=e=>C.value=e)},[...t[26]||(t[26]=[l("option",{value:"all"},"全部状态",-1),l("option",{value:"pending"},"待配置",-1),l("option",{value:"configured"},"已配置",-1),l("option",{value:"disabled"},"已禁用",-1)])],512),[[_,C.value]])]),l("div",Ne,[(s(true),u(f,null,y(le.value,e=>(s(),u("article",{key:e.id,class:"command-row"},[l("div",Be,[l("strong",null,o(e.name),1),l("span",null,o(e.commandPath),1),l("small",null,o(e.plugin)+" / legacy "+o(e.legacyAuthority)+" / "+o(e.suggestion.label),1)]),l("div",De,[l("button",{class:w({active:L(e.id)==="inherit"}),onClick:m=>F(e.id,"inherit")}," 继承 ",10,Ee),l("button",{class:w({active:L(e.id)==="allow"}),onClick:m=>F(e.id,"allow")}," 开 ",10,Le),l("button",{class:w({active:L(e.id)==="deny"}),onClick:m=>F(e.id,"deny")}," 关 ",10,Fe)])]))),128))])])):B("v-if",true)])):b.value==="pending"?(s(),u("section",qe,[(s(true),u(f,null,y(G.value,e=>(s(),u("article",{key:e.id,class:"pending-item"},[l("div",null,[l("strong",null,o(e.name),1),l("span",null,o(e.commandPath),1),l("small",null,o(e.plugin)+" / legacy "+o(e.legacyAuthority),1)]),l("dl",null,[t[27]||(t[27]=l("dt",null,"旧建议",-1)),l("dd",null,o(e.suggestion.label),1),t[28]||(t[28]=l("dt",null,"AI 建议",-1)),l("dd",null,o(e.autoAssign.label)+":"+o(e.autoAssign.reason),1)]),l("div",ze,[l("button",{disabled:r.value,onClick:m=>j(e.id,"legacy")},"采用旧建议",8,Ke),l("button",{class:"primary",disabled:r.value,onClick:m=>j(e.id,"advisor")},"采用 AI 建议",8,je)])]))),128)),G.value.length?B("v-if",true):(s(),u("p",He,"没有待配置指令。"))])):(s(),u("section",Je,[l("div",Qe,[c(l("input",{"onUpdate:modelValue":t[13]||(t[13]=e=>k.value=e),placeholder:"搜索指令、插件、描述"},null,512),[[x,k.value,void 0,{trim:true}]]),c(l("select",{"onUpdate:modelValue":t[14]||(t[14]=e=>C.value=e)},[...t[29]||(t[29]=[l("option",{value:"all"},"全部状态",-1),l("option",{value:"pending"},"待配置",-1),l("option",{value:"configured"},"已配置",-1),l("option",{value:"disabled"},"已禁用",-1)])],512),[[_,C.value]])]),l("div",We,[c(l("select",{"onUpdate:modelValue":t[15]||(t[15]=e=>h.value=e)},[t[30]||(t[30]=l("option",{disabled:"",value:""},"选择插件",-1)),(s(true),u(f,null,y(ee.value,e=>(s(),u("option",{key:e,value:e},o(e),9,Xe))),128))],512),[[_,h.value]]),l("button",{disabled:r.value||!h.value,onClick:t[16]||(t[16]=e=>N("legacy"))},"采用插件建议",8,Ye),l("button",{disabled:r.value||!h.value,onClick:t[17]||(t[17]=e=>N("guild-member"))},"给群成员",8,Ze),l("button",{disabled:r.value||!h.value,onClick:t[18]||(t[18]=e=>N("guild-admin"))},"给群管理员",8,el),l("button",{disabled:r.value||!h.value,onClick:t[19]||(t[19]=e=>N("bot-admin"))},"仅 Bot 管理员",8,ll)]),(s(true),u(f,null,y(K.value,e=>(s(),u("article",{key:e.id,class:"command-row"},[l("div",tl,[l("strong",null,o(e.name),1),l("span",null,o(e.id),1),l("small",null,o(e.plugin)+" / "+o(e.commandPath)+" / "+o(e.autoAssign.label),1)]),l("div",nl,[l("label",ol,[l("input",{type:"checkbox",checked:e.allowGuildOverride,onChange:m=>oe(e,m)},null,40,sl),t[31]||(t[31]=q(" 群内自治 ",-1))]),l("select",{value:e.status,onChange:m=>se(e,m)},[...t[32]||(t[32]=[l("option",{value:"pending"},"待配置",-1),l("option",{value:"configured"},"已配置",-1),l("option",{value:"disabled"},"已禁用",-1)])],40,ul)])]))),128))]))]))}}),il=(S,b)=>{const a=S.__vccOpts||S;for(const[d,k]of b)a[d]=k;return a},dl=il(al,[["__scopeId","data-v-755ad7c8"]]),cl=S=>{S.page({name:"新权限",path:"/new-auth",icon:"⌗",fields:["newauth"],authority:4,component:dl})};export{cl as default};
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.new-auth-page[data-v-
|
|
1
|
+
.new-auth-page[data-v-755ad7c8]{min-height:100vh;background:#f6f7f4;color:#1f2523;padding:20px}.topbar[data-v-755ad7c8],.detail-head[data-v-755ad7c8],.filters[data-v-755ad7c8],.row-actions[data-v-755ad7c8],.command-controls[data-v-755ad7c8],.top-actions[data-v-755ad7c8],.detail-tools[data-v-755ad7c8],.member-add[data-v-755ad7c8],.plugin-bulk[data-v-755ad7c8]{display:flex;align-items:center;gap:12px}.topbar[data-v-755ad7c8]{justify-content:space-between;border-bottom:1px solid #d9ded6;padding-bottom:16px}h1[data-v-755ad7c8],h2[data-v-755ad7c8],p[data-v-755ad7c8]{margin:0}h1[data-v-755ad7c8]{font-size:26px;line-height:1.2}h2[data-v-755ad7c8]{font-size:20px}p[data-v-755ad7c8],small[data-v-755ad7c8],span[data-v-755ad7c8],dd[data-v-755ad7c8],dt[data-v-755ad7c8]{color:#63706a}button[data-v-755ad7c8],select[data-v-755ad7c8],input[data-v-755ad7c8]{border:1px solid #c7cec8;border-radius:6px;background:#fff;color:#1f2523;min-height:34px;padding:0 10px;font:inherit}button[data-v-755ad7c8]{cursor:pointer}button[data-v-755ad7c8]:disabled{cursor:not-allowed;opacity:.55}.primary[data-v-755ad7c8]{background:#285e54;border-color:#285e54;color:#fff}.tabs[data-v-755ad7c8]{display:flex;gap:6px;margin:16px 0}.tabs button.active[data-v-755ad7c8],.state-buttons button.active[data-v-755ad7c8]{background:#25312d;border-color:#25312d;color:#fff}.role-layout[data-v-755ad7c8]{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:16px}.role-list[data-v-755ad7c8]{display:grid;gap:8px;align-content:start}.role-create[data-v-755ad7c8]{display:grid;gap:8px;border:1px solid #d9ded6;border-radius:8px;background:#fff;padding:10px}.role-item[data-v-755ad7c8]{display:flex;justify-content:space-between;align-items:center;min-height:58px;text-align:left}.role-item span[data-v-755ad7c8],.command-main[data-v-755ad7c8]{display:grid;gap:3px;min-width:0}.role-item.active[data-v-755ad7c8]{border-color:#285e54;box-shadow:inset 3px 0 #285e54}.role-item em[data-v-755ad7c8]{font-style:normal;color:#8b4a2f}.detail[data-v-755ad7c8]{min-width:0}.detail-head[data-v-755ad7c8]{justify-content:space-between;margin-bottom:12px}.detail-tools[data-v-755ad7c8]{flex-wrap:wrap;justify-content:flex-end}.member-panel[data-v-755ad7c8]{display:grid;gap:10px;border:1px solid #d9ded6;border-radius:8px;background:#fff;padding:12px;margin-bottom:12px}.member-panel>div[data-v-755ad7c8]:first-child{display:flex;justify-content:space-between;gap:12px}.member-list[data-v-755ad7c8]{display:flex;flex-wrap:wrap;gap:6px;min-height:28px}.member-chip[data-v-755ad7c8]{display:inline-flex;align-items:center;gap:6px;border:1px solid #c7cec8;border-radius:999px;background:#f6f7f4;padding:3px 4px 3px 10px}.member-chip button[data-v-755ad7c8]{min-height:24px;padding:0 8px;border-radius:999px}.filters[data-v-755ad7c8]{margin-bottom:12px}.plugin-bulk[data-v-755ad7c8]{flex-wrap:wrap;border:1px solid #d9ded6;border-radius:8px;background:#fff;padding:10px;margin-bottom:12px}.filters input[data-v-755ad7c8]{flex:1;min-width:180px}.command-list[data-v-755ad7c8],.pending-grid[data-v-755ad7c8],.commands-table[data-v-755ad7c8]{display:grid;gap:8px}.command-row[data-v-755ad7c8],.pending-item[data-v-755ad7c8]{background:#fff;border:1px solid #d9ded6;border-radius:8px;padding:12px}.command-row[data-v-755ad7c8]{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:center}.command-main strong[data-v-755ad7c8],.command-main span[data-v-755ad7c8],.command-main small[data-v-755ad7c8]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.state-buttons[data-v-755ad7c8]{display:grid;grid-template-columns:repeat(3,54px);gap:6px}.pending-grid[data-v-755ad7c8]{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}.pending-item[data-v-755ad7c8]{display:grid;gap:10px}dl[data-v-755ad7c8]{display:grid;grid-template-columns:58px 1fr;gap:4px 8px;margin:0}dd[data-v-755ad7c8]{margin:0}.check[data-v-755ad7c8]{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}.check input[data-v-755ad7c8]{min-height:0}.error[data-v-755ad7c8]{border:1px solid #d9a09a;background:#fff1ef;color:#8a2d22;border-radius:6px;padding:10px;margin-bottom:12px}.empty[data-v-755ad7c8]{padding:24px 0}@media (max-width: 760px){.new-auth-page[data-v-755ad7c8]{padding:12px}.topbar[data-v-755ad7c8],.detail-head[data-v-755ad7c8],.command-row[data-v-755ad7c8]{grid-template-columns:1fr;display:grid}.top-actions[data-v-755ad7c8],.filters[data-v-755ad7c8],.command-controls[data-v-755ad7c8],.detail-tools[data-v-755ad7c8],.member-add[data-v-755ad7c8],.plugin-bulk[data-v-755ad7c8]{flex-wrap:wrap}.role-layout[data-v-755ad7c8]{grid-template-columns:1fr}.state-buttons[data-v-755ad7c8]{grid-template-columns:repeat(3,minmax(0,1fr))}}
|
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ type ScopeType = 'global' | 'guild';
|
|
|
10
10
|
type CommandStatus = 'pending' | 'configured' | 'disabled';
|
|
11
11
|
type PolicyState = 'inherit' | 'allow' | 'deny';
|
|
12
12
|
type AutoAssignKind = 'public' | 'moderation' | 'owner' | 'admin' | 'legacy';
|
|
13
|
+
type PluginAssignTarget = 'legacy' | 'bot-admin' | 'guild-owner' | 'guild-admin' | 'guild-member';
|
|
13
14
|
export interface NewAuthCommandRecord {
|
|
14
15
|
id: string;
|
|
15
16
|
name: string;
|
|
@@ -94,6 +95,10 @@ declare module '@koishijs/plugin-console' {
|
|
|
94
95
|
success: true;
|
|
95
96
|
count: number;
|
|
96
97
|
}>;
|
|
98
|
+
'newauth/assignPluginCommands'(payload: AssignPluginCommandsPayload): Promise<{
|
|
99
|
+
success: true;
|
|
100
|
+
count: number;
|
|
101
|
+
}>;
|
|
97
102
|
}
|
|
98
103
|
}
|
|
99
104
|
export interface NewAuthConsoleData {
|
|
@@ -163,6 +168,11 @@ interface CopyRolePoliciesPayload {
|
|
|
163
168
|
targetRoleId: string;
|
|
164
169
|
scope: string;
|
|
165
170
|
}
|
|
171
|
+
interface AssignPluginCommandsPayload {
|
|
172
|
+
plugin: string;
|
|
173
|
+
scope: string;
|
|
174
|
+
target: PluginAssignTarget;
|
|
175
|
+
}
|
|
166
176
|
export interface Config {
|
|
167
177
|
botAdmins: string[];
|
|
168
178
|
trustLegacyAuthorityAsAdmin: boolean;
|
|
@@ -253,6 +263,7 @@ export declare class NewAuthService {
|
|
|
253
263
|
setCommandPolicy(scope: string, roleId: string, input: string, state: PolicyState): Promise<NewAuthCommandRecord>;
|
|
254
264
|
applySuggestedPolicy(input: string, scope?: string, mode?: 'legacy' | 'advisor'): Promise<NewAuthCommandRecord>;
|
|
255
265
|
autoAssignPending(scope?: string, mode?: 'legacy' | 'advisor'): Promise<number>;
|
|
266
|
+
assignPluginCommands(plugin: string, scope?: string, target?: PluginAssignTarget): Promise<number>;
|
|
256
267
|
getCommand(input: string): Promise<NewAuthCommandRecord>;
|
|
257
268
|
private ensureBuiltinRoles;
|
|
258
269
|
private applyRolesToCommand;
|
package/lib/index.js
CHANGED
|
@@ -379,7 +379,7 @@ class NewAuthService {
|
|
|
379
379
|
updatedAt: now,
|
|
380
380
|
};
|
|
381
381
|
if (existing) {
|
|
382
|
-
await this.ctx.database.set('new_auth_role', id, record);
|
|
382
|
+
await this.ctx.database.set('new_auth_role', id, omitPrimary(record, 'id'));
|
|
383
383
|
}
|
|
384
384
|
else {
|
|
385
385
|
await this.ctx.database.create('new_auth_role', record);
|
|
@@ -454,6 +454,22 @@ class NewAuthService {
|
|
|
454
454
|
}
|
|
455
455
|
return commands.length;
|
|
456
456
|
}
|
|
457
|
+
async assignPluginCommands(plugin, scope = 'global', target = 'legacy') {
|
|
458
|
+
const commands = (await this.listCommands({ all: true }))
|
|
459
|
+
.filter(command => command.plugin === plugin);
|
|
460
|
+
for (const command of commands) {
|
|
461
|
+
if (target === 'legacy') {
|
|
462
|
+
await this.applySuggestedPolicy(command.id, scope, 'legacy');
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
await this.applyRolesToCommand(scope, command.id, getAssignTargetRoles(target));
|
|
466
|
+
if (command.status === 'pending') {
|
|
467
|
+
await this.setCommandStatus(command.id, 'configured');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return commands.length;
|
|
472
|
+
}
|
|
457
473
|
async getCommand(input) {
|
|
458
474
|
const cached = this.commandCache.get(input);
|
|
459
475
|
if (cached)
|
|
@@ -474,7 +490,7 @@ class NewAuthService {
|
|
|
474
490
|
updatedAt: now,
|
|
475
491
|
};
|
|
476
492
|
if (existing) {
|
|
477
|
-
await this.ctx.database.set('new_auth_role', role.id, record);
|
|
493
|
+
await this.ctx.database.set('new_auth_role', role.id, omitPrimary(record, 'id'));
|
|
478
494
|
}
|
|
479
495
|
else {
|
|
480
496
|
await this.ctx.database.create('new_auth_role', record);
|
|
@@ -662,7 +678,7 @@ class NewAuthService {
|
|
|
662
678
|
}
|
|
663
679
|
}
|
|
664
680
|
exports.NewAuthService = NewAuthService;
|
|
665
|
-
function createConsoleServiceClass() {
|
|
681
|
+
function createConsoleServiceClass(service) {
|
|
666
682
|
const { DataService } = require('@koishijs/plugin-console');
|
|
667
683
|
return class NewAuthConsoleDataService extends DataService {
|
|
668
684
|
constructor(ctx) {
|
|
@@ -672,7 +688,7 @@ function createConsoleServiceClass() {
|
|
|
672
688
|
});
|
|
673
689
|
}
|
|
674
690
|
async get(_forced, _client) {
|
|
675
|
-
return
|
|
691
|
+
return service.getConsoleData();
|
|
676
692
|
}
|
|
677
693
|
};
|
|
678
694
|
}
|
|
@@ -681,7 +697,7 @@ function registerConsole(ctx, service) {
|
|
|
681
697
|
dev: (0, path_1.resolve)(__dirname, '../client/index.ts'),
|
|
682
698
|
prod: (0, path_1.resolve)(__dirname, '../dist'),
|
|
683
699
|
});
|
|
684
|
-
ctx.plugin(createConsoleServiceClass());
|
|
700
|
+
ctx.plugin(createConsoleServiceClass(service));
|
|
685
701
|
const ok = async (task) => {
|
|
686
702
|
await task;
|
|
687
703
|
ctx.console.refresh('newauth');
|
|
@@ -721,6 +737,11 @@ function registerConsole(ctx, service) {
|
|
|
721
737
|
ctx.console.refresh('newauth');
|
|
722
738
|
return { success: true, count };
|
|
723
739
|
}, { authority: 4 });
|
|
740
|
+
ctx.console.addListener('newauth/assignPluginCommands', async (payload) => {
|
|
741
|
+
const count = await service.assignPluginCommands(payload.plugin, payload.scope, payload.target);
|
|
742
|
+
ctx.console.refresh('newauth');
|
|
743
|
+
return { success: true, count };
|
|
744
|
+
}, { authority: 4 });
|
|
724
745
|
}
|
|
725
746
|
function registerManagementCommands(ctx, config, service) {
|
|
726
747
|
const authority = config.legacyAdminAuthority;
|
|
@@ -816,6 +837,14 @@ function registerManagementCommands(ctx, config, service) {
|
|
|
816
837
|
const count = await service.copyRolePolicies(sourceRoleId, targetRoleId, scope);
|
|
817
838
|
return `已复制 ${count} 条策略:${sourceRoleId} -> ${targetRoleId} (${scope})`;
|
|
818
839
|
});
|
|
840
|
+
ctx.command('newauth.plugin.assign <plugin> <target> [scope]', '批量配置插件指令', { authority })
|
|
841
|
+
.action(async (_, plugin, target, scope = 'global') => {
|
|
842
|
+
if (!['legacy', 'bot-admin', 'guild-owner', 'guild-admin', 'guild-member'].includes(target)) {
|
|
843
|
+
return 'target 只能是 legacy、bot-admin、guild-owner、guild-admin 或 guild-member。';
|
|
844
|
+
}
|
|
845
|
+
const count = await service.assignPluginCommands(plugin, scope, target);
|
|
846
|
+
return `已批量配置 ${count} 个指令:${plugin} -> ${target} (${scope})`;
|
|
847
|
+
});
|
|
819
848
|
}
|
|
820
849
|
function inferLegacyAuthority(command) {
|
|
821
850
|
if (typeof command.config.authority === 'number')
|
|
@@ -857,6 +886,19 @@ function getLegacySuggestion(authority) {
|
|
|
857
886
|
label: '仅 Bot 管理员',
|
|
858
887
|
};
|
|
859
888
|
}
|
|
889
|
+
function getAssignTargetRoles(target) {
|
|
890
|
+
if (target === 'guild-member')
|
|
891
|
+
return ['guild-member', 'guild-admin', 'guild-owner'];
|
|
892
|
+
if (target === 'guild-admin')
|
|
893
|
+
return ['guild-admin', 'guild-owner'];
|
|
894
|
+
if (target === 'guild-owner')
|
|
895
|
+
return ['guild-owner'];
|
|
896
|
+
return ['bot-admin'];
|
|
897
|
+
}
|
|
898
|
+
function omitPrimary(record, key) {
|
|
899
|
+
const { [key]: _value, ...rest } = record;
|
|
900
|
+
return rest;
|
|
901
|
+
}
|
|
860
902
|
function inferPlugin(command) {
|
|
861
903
|
const source = command.caller?.scope || command.ctx?.scope;
|
|
862
904
|
const plugin = source?.plugin?.name || source?.uid || source?.id || 'unknown';
|