1import{_ as n,c as i,a,o as s}from"./app-B7HVJ7q3.js";const l={};function t(c,e){return s(),i("div",null,[...e[0]||(e[0]=[a(`<h1 id="åç«¯æ ¸å¿æ¨¡å详解" tabindex="-1"><a class="header-anchor" href="#åç«¯æ ¸å¿æ¨¡å详解"><span>åç«¯æ ¸å¿æ¨¡å详解</span></a></h1><p>æ¬ææ¡£æ·±å ¥åæ GoWind Admin å端åä¸ªæ ¸å¿ä¸å¡æ¨¡åç设计ä¸å®ç°ï¼æ¶µçè®¤è¯ææãç¨æ·ç®¡çãç§æ·ç®¡çãæéä½ç³»ãåå ¸ç®¡ççæ¨¡åã</p><h2 id="ä¸ã认è¯ä¸æææ¨¡å" tabindex="-1"><a class="header-anchor" href="#ä¸ã认è¯ä¸æææ¨¡å"><span>ä¸ã认è¯ä¸æææ¨¡å</span></a></h2><p>认è¯ï¼Authenticationï¼åææï¼Authorizationï¼æ¯å端å®å ¨ä½ç³»çæ ¸å¿ï¼GoWind Admin 卿¤æ¨¡ååäºå¤§é设计ã</p><h3 id="_1-è®¤è¯æå¡-authenticationservice" tabindex="-1"><a class="header-anchor" href="#_1-è®¤è¯æå¡-authenticationservice"><span>1. è®¤è¯æå¡ï¼AuthenticationServiceï¼</span></a></h3><p>è®¤è¯æå¡ä½äº <code>internal/service/authentication_service.go</code>ï¼è´è´£å¤çç¨æ·ç»å½ãç»åºã令çå·æ°ãéªè¯ç çæ ¸å¿æµç¨ã</p><h4 id="ç»å½æµç¨" tabindex="-1"><a class="header-anchor" href="#ç»å½æµç¨"><span>ç»å½æµç¨</span></a></h4><p>ç³»ç»æ¯æå¤ç§ OAuth 2.0 ææç±»åï¼Grant Typeï¼ï¼</p><table><thead><tr><th>Grant Type</th><th>说æ</th><th>å®ç°ç¶æ</th></tr></thead><tbody><tr><td><code>password</code></td><td>ç¨æ·åå¯ç ç»å½</td><td>â å·²å®ç°</td></tr><tr><td><code>refresh_token</code></td><td>å·æ°ä»¤ç</td><td>â å·²å®ç°</td></tr><tr><td><code>client_credentials</code></td><td>客æ·ç«¯åæ®</td><td>â é¢çæ¥å£</td></tr></tbody></table><p><strong>å¯ç ç»å½ç宿´æµç¨</strong>ï¼</p><ol><li>éªè¯éªè¯ç ï¼å¯éï¼</li><li>éè¿ <code>UserCredentialRepo</code> éªè¯ç¨æ·åè¯ï¼ç¨æ·å + å¯ç ï¼</li><li>è·åç¨æ·ä¿¡æ¯ï¼æ£æ¥ç¨æ·ç¶æ</li><li>è§£æç¨æ·æéä¿¡æ¯ï¼<code>resolveUserAuthority</code>ï¼ï¼ <ul><li>æ£æ¥ç¨æ·æ¯å¦è¢«ç¦ç¨</li><li>è·åç¨æ·è§è²å表</li><li>è·åè§è²å ³èçæéå表</li><li>éªè¯æ¯å¦æ¥æåå°è®¿é®æéï¼<code>SystemAccessBackendPermissionCode</code>ï¼</li></ul></li><li>çæ JWT Access Token å Refresh Token</li><li>è¿å令çä¿¡æ¯</li></ol><h4 id="éªè¯ç æºå¶" tabindex="-1"><a class="header-anchor" href="#éªè¯ç æºå¶"><span>éªè¯ç æºå¶</span></a></h4><p>ç³»ç»å ç½®éªè¯ç çæä¸éªè¯åè½ï¼æ¯æå¾å½¢éªè¯ç ï¼</p><ul><li><code>GenerateCaptcha</code>ï¼çæéªè¯ç å¾çï¼Base64 ç¼ç ï¼</li><li><code>VerifyCaptcha</code>ï¼éªè¯ç¨æ·è¾å ¥çéªè¯ç </li></ul><h4 id="令ç管ç" tabindex="-1"><a class="header-anchor" href="#令ç管ç"><span>令ç管ç</span></a></h4><ul><li><strong>Access Token</strong>ï¼ç¨äº API 请æ±è®¤è¯ï¼æææè¾ç</li><li><strong>Refresh Token</strong>ï¼ç¨äºå·æ° Access Tokenï¼æææè¾é¿</li><li>令çç¼åéè¿ <code>UserTokenCache</code> 管çï¼åºäº Redis å®ç°</li></ul><h3 id="_2-认è¯ä¸é´ä»¶" tabindex="-1"><a class="header-anchor" href="#_2-认è¯ä¸é´ä»¶"><span>2. 认è¯ä¸é´ä»¶</span></a></h3><p>认è¯ä¸é´ä»¶ä½äº <code>pkg/middleware/auth/</code>ï¼å¨ REST Server ä¸éè¿ Selector ä¸é´ä»¶æ¨¡å¼æ³¨å ¥ï¼</p><div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code><span class="line"><span class="token comment">// ç½ååæºå¶ï¼ä»¥ä¸æ¥å£ä¸éè¦è®¤è¯</span></span> 2<span class="line">rpc<span class="token punctuation">.</span><span class="token function">AddWhiteList</span><span class="token punctuation">(</span></span> 3<span class="line"> adminV1<span class="token punctuation">.</span>OperationAuthenticationServiceLogin<span class="token punctuation">,</span></span> 4<span class="line"> adminV1<span class="token punctuation">.</span>OperationAuthenticationServiceGenerateCaptcha<span class="token punctuation">,</span></span> 5<span class="line"> adminV1<span class="token punctuation">.</span>OperationAuthenticationServiceVerifyCaptcha<span class="token punctuation">,</span></span> 6<span class="line"><span class="token punctuation">)</span></span> 7<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>ä¸é´ä»¶æ ¸å¿åè½ï¼</p><ul><li>ä»è¯·æ± Header 䏿å JWT Token</li><li>éªè¯ Token æææ§</li><li>è§£æç¨æ·ä¿¡æ¯ï¼UserIdãTenantIdãRoles çï¼æ³¨å ¥å° Context</li><li>æ¯æ Ent Viewer ä¸ä¸ææ³¨å ¥ï¼å®ç°æ°æ®çº§å«çé离</li></ul><h3 id="_3-ææå¼æ" tabindex="-1"><a class="header-anchor" href="#_3-ææå¼æ"><span>3. ææå¼æ</span></a></h3><p>æææ¨¡åä½äº <code>pkg/authorizer/</code>ï¼å°è£ äºå¤ç§æéçç¥å¼æï¼</p><table><thead><tr><th>
7弿</th><th>é ç½®å¼</th><th>说æ</th></tr></thead><tbody><tr><td>Casbin</td><td><code>casbin</code></td><td>è½»é级æéæ§å¶ï¼æ¯æ ACLãRBAC çæ¨¡å</td></tr><tr><td>OPA</td><td><code>opa</code></td><td>Open Policy Agentï¼å¼ºå¤§ççç¥å¼æ</td></tr><tr><td>Zanzibar</td><td><code>zanzibar</code></td><td>Google Zanzibar 模åï¼æ¯æ Keto å OpenFGA</td></tr><tr><td>Noop</td><td><code>noop</code></td><td>空å®ç°ï¼ä¸è¿è¡æéæ ¡éª</td></tr></tbody></table><p>éè¿ <code>auth.yaml</code> é ç½®åæ¢ææå¼æï¼</p><div class="language-yaml line-numbers-mode" data-highlighter="prismjs" data-ext="yml"><pre><code><span class="line"><span class="token key atrule">authz</span><span class="token punctuation">:</span></span> 8<span class="line"> <span class="token key atrule">type</span><span class="token punctuation">:</span> <span class="token string">"noop"</span> <span class="token comment"># casbin, opa, zanzibar, noop</span></span> 9<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_4-审计æ¥å¿ä¸é´ä»¶" tabindex="-1"><a class="header-anchor" href="#_4-审计æ¥å¿ä¸é´ä»¶"><span>4. 审计æ¥å¿ä¸é´ä»¶</span></a></h3><p>审计æ¥å¿ä¸é´ä»¶ä½äº <code>pkg/middleware/logging/</code>ï¼èªå¨è®°å½ï¼</p><ul><li><strong>API 审计æ¥å¿</strong>ï¼è®°å½æ¯æ¬¡ API 请æ±ç详ç»ä¿¡æ¯</li><li><strong>ç»å½æ¥å¿</strong>ï¼è®°å½ç¨æ·ç»å½è¡ä¸ºï¼æå/失败ï¼</li></ul><p>ä¸é´ä»¶éè¿åè°å½æ°å°æ¥å¿åå ¥æ°æ®åºï¼</p><div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code><span class="line">applogging<span class="token punctuation">.</span><span class="token function">Server</span><span class="token punctuation">(</span></span> 10<span class="line"> applogging<span class="token punctuation">.</span><span class="token function">WithWriteApiLogFunc</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> data <span class="token operator">*</span>auditV1<span class="token punctuation">.</span>ApiAuditLog<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span></span> 11<span class="line"> <span class="token keyword">return</span> apiAuditLogRepo<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token operator">&</span>auditV1<span class="token punctuation">.</span>CreateApiAuditLogRequest<span class="token punctuation">{</span>Data<span class="token punctuation">:</span> data<span class="token punctuation">}</span><span class="token punctuation">)</span></span> 12<span class="line"> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span> 13<span class="line"> applogging<span class="token punctuation">.</span><span class="token function">WithWriteLoginLogFunc</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> data <span class="token operator">*</span>auditV1<span class="token punctuation">.</span>LoginAuditLog<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span></span> 14<span class="line"> <span class="token keyword">return</span> loginLogRepo<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token operator">&</span>auditV1<span class="token punctuation">.</span>CreateLoginAuditLogRequest<span class="token punctuation">{</span>Data<span class="token punctuation">:</span> data<span class="token punctuation">}</span><span class="token punctuation">)</span></span> 15<span class="line"> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span> 16<span class="line"><span class="token punctuation">)</span></span> 17<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="äºãç¨æ·ç®¡ç模å" tabindex="-1"><a class="header-anchor" href="#äºãç¨æ·ç®¡ç模å"><span>äºãç¨æ·ç®¡ç模å</span></a></h2><h3 id="_1-ç¨æ·æå¡-userservice" tabindex="-1"><a class="header-anchor" href="#_1-ç¨æ·æå¡-userservice"><span>1. ç¨æ·æå¡ï¼UserServiceï¼</span></a></h3><p>ä½äº <code>internal/service/user_service.go</code>ï¼æä¾å®æ´çç¨æ· CRUD 管çï¼</p><p><strong>æ ¸å¿åè½</strong>ï¼</p><ul><li>åå»ºç¨æ·ï¼æ¯æå¤è§è²ãå¤é¨é¨ã设置主管ï¼</li><li>æ´æ°ç¨æ·ä¿¡æ¯</li><li>å é¤ç¨æ·ï¼æ¯ææ¹éï¼</li><li>è·åç¨æ·è¯¦æ </li><li>å表æ¥è¯¢ï¼æ¯æå页ãé«çº§æ¥è¯¢ãæé¨é¨èå¨ï¼</li><li>ç¦ç¨/å¯ç¨ç¨æ·</li><li>设置/åæ¶ä¸»ç®¡</li><li>éç½®å¯ç </li><li>é ç½®å¤è§è²</li><li>é ç½®å¤é¨é¨</li><li>ä¸é®ç»å½æå®ç¨æ·</li></ul><h3 id="_2-ç¨æ·åè¯æå¡-usercredentialservice" tabindex="-1"><a class="header-anchor" href="#_2-ç¨æ·åè¯æå¡-usercredentialservice"><span>2. ç¨æ·åè¯æå¡ï¼UserCredentialServiceï¼</span></a></h3><p>ä½äº <code>internal/service/user_credential_service.go</code>ï¼ç®¡çç¨æ·è®¤è¯åè¯ï¼</p><ul><li>æ¯æå¤ç§åè¯ç±»åï¼ç¨æ·åå¯ç ãææºå·ãé®ç®±ç</li><li>å¯ç å å¯åå¨</li><li>åè¯éªè¯ï¼æ¯æå¯ç è§£å¯éªè¯ï¼</li></ul><h3 id="_3-ç¨æ·æ¡£æ¡æå¡-userprofileservice" tabindex="-1"><a class="header-anchor" href="#_3-ç¨æ·æ¡£æ¡æå¡-userprofileservice"><span>3. ç¨æ·æ¡£æ¡æå¡ï¼UserProfileServiceï¼</span></a></h3><p>ä½äº <code>internal/service/user_profile_service.go</code>ï¼ç®¡çç¨æ·ä¸ªäººèµæï¼</p><ul><li>æ¥ç/ä¿®æ¹ä¸ªäººä¿¡æ¯</li><li>æ¥çæåç»å½ä¿¡æ¯</li><li>ä¿®æ¹å¯ç </li></ul><h3 id="_4-æ°æ®å±" tabindex="-1"><a class="header-anchor" href="#_4-æ°æ®å±"><span>4. æ°æ®å±</span></a></h3><p>ç¨æ·æ°æ®å±ä½äº <code>internal/data/</code>ï¼æ ¸å¿ Repo å æ¬ï¼</p><table><thead><tr><th>
17Repo</th><th>æä»¶</th><th>说æ</th></tr></thead><tbody><tr><td><code>UserRepo</code></td><td><code>user_repo.go</code></td><td>ç¨æ·ä¸»è¡¨æä½</td></tr><tr><td><code>UserCredentialRepo</code></td><td><code>user_credential_repo.go</code></td><td>ç¨æ·åè¯æä½</td></tr><tr><td><code>UserRoleRepo</code></td><td><code>user_role_repo.go</code></td><td>ç¨æ·-è§è²å
³è</td></tr><tr><td><code>UserOrgUnitRepo</code></td><td><code>user_org_unit_repo.go</code></td><td>ç¨æ·-ç»ç»å
³è</td></tr><tr><td><code>UserPositionRepo</code></td><td><code>user_position_repo.go</code></td><td>ç¨æ·-èä½å
³è</td></tr><tr><td><code>UserTokenCache</code></td><td><code>user_token_cache.go</code></td><td>ç¨æ·ä»¤çç¼åï¼Redisï¼</td></tr></tbody></table><h2 id="ä¸ãç§æ·ç®¡ç模å" tabindex="-1"><a class="header-anchor" href="#ä¸ãç§æ·ç®¡ç模å"><span>ä¸ãç§æ·ç®¡ç模å</span></a></h2><h3 id="ç§æ·æå¡-tenantservice" tabindex="-1"><a class="header-anchor" href="#ç§æ·æå¡-tenantservice"><span>ç§æ·æå¡ï¼TenantServiceï¼</span></a></h3><p>ä½äº <code>internal/service/tenant_service.go</code>ï¼æä¾å¤ç§æ·ç®¡çè½åï¼</p><p><strong>æ ¸å¿åè½</strong>ï¼</p><ul><li>åå»ºç§æ·ï¼èªå¨åå§åç§æ·é¨é¨ãé»è®¤è§è²å管çåï¼</li><li>管çç§æ·å¥é¤</li><li>ç¦ç¨/å¯ç¨ç§æ·</li><li>ä¸é®ç»å½ç§æ·ç®¡çå</li></ul><p><strong>ç§æ·å建æµç¨</strong>ï¼</p><ol><li>åå»ºç§æ·è®°å½</li><li>èªå¨åå»ºç§æ·é»è®¤é¨é¨</li><li>åå»ºç§æ·é»è®¤è§è²</li><li>åå»ºç§æ·ç®¡çåè´¦å·</li><li>å°ç®¡çåå
³èå°è§è²åé¨é¨</li></ol><h3 id="å¤ç§æ·å
³ç³»æ¨¡å" tabindex="-1"><a class="header-anchor" href="#å¤ç§æ·å
³ç³»æ¨¡å"><span>å¤ç§æ·å
³ç³»æ¨¡å</span></a></h3><p>ç³»ç»æ¯æä¸¤ç§ç§æ·å
³ç³»æ¨¡åï¼éè¿ <code>constants.DefaultUserTenantRelationType</code> é
ç½®ï¼</p><p><strong>ä¸å¯¹ä¸æ¨¡å</strong>ï¼<code>UserTenantRelationOneToOne</code>ï¼ï¼</p><ul><li>ä¸ä¸ªç¨æ·åªå±äºä¸ä¸ªç§æ·</li><li>ç»å½æ¶ç´æ¥æ ¹æ®ç¨æ·ç <code>TenantId</code> è·åæé</li></ul><p><strong>ä¸å¯¹å¤æ¨¡å</strong>ï¼<code>UserTenantRelationOneToMany</code>ï¼ï¼</p><ul><li>ä¸ä¸ªç¨æ·å¯ä»¥å±äºå¤ä¸ªç§æ·</li><li>éè¿ <code>MembershipRepo</code> 管çå¤ç§æ·å
³ç³»</li><li>ç»å½æ¶éè¦éåæææ´»è·çæå身份ï¼åå¹¶æé</li></ul><h2 id="åãæéä½ç³»æ¨¡å" tabindex="-1"><a class="header-anchor" href="#åãæéä½ç³»æ¨¡å"><span>åãæéä½ç³»æ¨¡å</span></a></h2><p>GoWind Admin çæéä½ç³»å
å«èåæéãæ¥å£æéãæ°æ®æéä¸ä¸ªç»´åº¦ã</p><h3 id="_1-æéæå¡-permissionservice" tabindex="-1"><a class="header-anchor" href="#_1-æéæå¡-permissionservice"><span>1. æéæå¡ï¼PermissionServiceï¼</span></a></h3><p>ä½äº <code>internal/service/permission_service.go</code>ï¼ç®¡çæéç¹åæéåç»ï¼</p><ul><li>å建/æ´æ°/å 餿é</li><li>æéåç»ç®¡ç</li><li>æéä¸ API æ¥å£å
³è</li><li>æéä¸èåå
³è</li><li>æéçç¥ç®¡ç</li></ul><h3 id="_2-è§è²æå¡-roleservice" tabindex="-1"><a class="header-anchor" href="#_2-è§è²æå¡-roleservice"><span>2. è§è²æå¡ï¼RoleServiceï¼</span></a></h3><p>ä½äº <code>internal/service/role_service.go</code>ï¼ç®¡çè§è²åè§è²åç»ï¼</p><ul><li>å建/æ´æ°/å é¤è§è²</li><li>è§è²åç»ç®¡ç</li><li>è§è²å
³èæé</li><li>è§è²å
³èç¨æ·</li><li>æè§è²èå¨ç¨æ·</li><li>æ¹éæ·»å /ç§»é¤åå·¥</li></ul><h3 id="_3-èåæå¡-menuservice" tabindex="-1"><a class="header-anchor" href="#_3-èåæå¡-menuservice"><span>3. èåæå¡ï¼MenuServiceï¼</span></a></h3><p>ä½äº <code>internal/service/menu_service.go</code>ï¼ç®¡çç³»ç»èåï¼</p><ul><li>æ¯æä¸ç§èåç±»åï¼ç®å½ãèåãæé®</li><li>æ å½¢ç»æç®¡ç</li><li>èåå
³èæé</li></ul><h3 id="_4-api-æ¥å£æå¡-apiservice" tabindex="-1"><a class="header-anchor" href="#_4-api-æ¥å£æå¡-apiservice"><span>4. API æ¥å£æå¡ï¼ApiServiceï¼</span></a></h3><p>ä½äº <code>internal/service/api_service.go</code>ï¼ç®¡çå端 API æ¥å£ï¼</p><ul><li>æ¥å£æ³¨åä¸ç®¡ç</li><li>æ¥å£åæ¥åè½ï¼ä»è·¯ç±èªå¨åæ¥ï¼</li><li>æ¥å£å
³èæéç¹</li><li>æ¯ææ å½¢å表å±ç¤º</li><li>æä½æ¥å¿è¯·æ±åæ°åååºç»æé
ç½®</li></ul><h3 id="_5-æ°æ®æé" tabindex="-1"><a class="header-anchor" href="#_5-æ°æ®æé"><span>5. æ°æ®æé</span></a></h3><p>æ°æ®æééè¿è§è²é
ç½®ï¼æ¯æä»¥ä¸æ°æ®èå´ï¼</p><table><thead><tr><th>
17æ°æ®èå´</th><th>说æ</th></tr></thead><tbody><tr><td><code>SELF</code></td><td>ä» æ¬äººæ°æ®</td></tr><tr><td><code>UNIT_ONLY</code></td><td>æ¬é¨é¨æ°æ®</td></tr><tr><td><code>UNIT_AND_CHILD</code></td><td>æ¬é¨é¨åä¸çº§é¨é¨æ°æ®</td></tr><tr><td><code>SELECTED_UNITS</code></td><td>æå®é¨é¨æ°æ®</td></tr><tr><td><code>ALL</code></td><td>å ¨é¨æ°æ®</td></tr></tbody></table><p>æ°æ®æéä¼å 级ï¼<code>ALL > SELECTED_UNITS > UNIT_AND_CHILD > UNIT_ONLY > SELF</code></p><h2 id="äºãç»ç»æ¶ææ¨¡å" tabindex="-1"><a class="header-anchor" href="#äºãç»ç»æ¶ææ¨¡å"><span>äºãç»ç»æ¶ææ¨¡å</span></a></h2><h3 id="_1-ç»ç»ç®¡ç-orgunitservice" tabindex="-1"><a class="header-anchor" href="#_1-ç»ç»ç®¡ç-orgunitservice"><span>1. ç»ç»ç®¡çï¼OrgUnitServiceï¼</span></a></h3><p>ä½äº <code>internal/service/org_unit_service.go</code>ï¼ç®¡çç»ç»æ¶æï¼</p><ul><li>æ å½¢ç»æç»ç»ç®¡ç</li><li>æ¯æå¤çº§ç»ç»å±çº§</li><li>ç»ç»è·¯å¾èªå¨ç»´æ¤</li></ul><h3 id="_2-é¨é¨ç®¡ç" tabindex="-1"><a class="header-anchor" href="#_2-é¨é¨ç®¡ç"><span>2. é¨é¨ç®¡ç</span></a></h3><p>é¨é¨éè¿ç»ç»æ¶ææ¨¡åç»ä¸ç®¡çï¼æ¯æï¼</p><ul><li>æ å½¢å表å±ç¤º</li><li>æé¨é¨èå¨ç¨æ·</li><li>é¨é¨å ³èè§è²</li></ul><h3 id="_3-èä½ç®¡ç-positionservice" tabindex="-1"><a class="header-anchor" href="#_3-èä½ç®¡ç-positionservice"><span>3. èä½ç®¡çï¼PositionServiceï¼</span></a></h3><p>ä½äº <code>internal/service/position_service.go</code>ï¼ç®¡çç¨æ·èå¡ï¼</p><ul><li>èä½ä½ä¸ºç¨æ·çæ ç¾å±æ§</li><li>æ¯æç¨æ·å ³èå¤ä¸ªèä½</li></ul><h2 id="å ãåå ¸ç®¡çæ¨¡å" tabindex="-1"><a class="header-anchor" href="#å ãåå ¸ç®¡çæ¨¡å"><span>å ãåå ¸ç®¡çæ¨¡å</span></a></h2><h3 id="_1-åå ¸ç±»åæå¡-dicttypeservice" tabindex="-1"><a class="header-anchor" href="#_1-åå ¸ç±»åæå¡-dicttypeservice"><span>1. åå ¸ç±»åæå¡ï¼DictTypeServiceï¼</span></a></h3><p>ä½äº <code>internal/service/dict_type_service.go</code>ï¼ç®¡çæ°æ®åå ¸å¤§ç±»ï¼</p><ul><li>å建/æ´æ°/å é¤åå ¸å¤§ç±»</li><li>åå ¸å¤§ç±»ä¸åå ¸æ¡ç®èå¨</li></ul><h3 id="_2-åå ¸æ¡ç®æå¡-dictentryservice" tabindex="-1"><a class="header-anchor" href="#_2-åå ¸æ¡ç®æå¡-dictentryservice"><span>2. åå ¸æ¡ç®æå¡ï¼DictEntryServiceï¼</span></a></h3><p>ä½äº <code>internal/service/dict_entry_service.go</code>ï¼ç®¡çåå ¸å°ç±»/æ¡ç®ï¼</p><ul><li>æ¯ææåå ¸å¤§ç±»èå¨</li><li>æå¡ç«¯å¤åæåº</li><li>æ°æ®å¯¼å ¥å导åº</li><li>å½é 忝æï¼<code>DictEntryI18nRepo</code>ï¼</li></ul><h2 id="ä¸ãä»»å¡è°åº¦æ¨¡å" tabindex="-1"><a class="header-anchor" href="#ä¸ãä»»å¡è°åº¦æ¨¡å"><span>ä¸ãä»»å¡è°åº¦æ¨¡å</span></a></h2><h3 id="任塿å¡-taskservice" tabindex="-1"><a class="header-anchor" href="#任塿å¡-taskservice"><span>任塿å¡ï¼TaskServiceï¼</span></a></h3><p>ä½äº <code>internal/service/task_service.go</code>ï¼åºäº Asynq å®ç°åå¸å¼ä»»å¡è°åº¦ï¼</p><ul><li>任塿°å¢ãä¿®æ¹ãå é¤</li><li>ä»»å¡å¯å¨ãæå</li><li>ç«å³æ§è¡</li><li>æ¥çä»»å¡è¿è¡æ¥å¿</li></ul><p>Asynq Server é ç½®ï¼<code>server.yaml</code>ï¼ï¼</p><div class="language-yaml line-numbers-mode" data-highlighter="prismjs" data-ext="yml"><pre><code><span class="line"><span class="token key atrule">asynq</span><span class="token punctuation">:</span></span> 18<span class="line"> <span class="token key atrule">uri</span><span class="token punctuation">:</span> <span class="token string">"redis://:*Abcd123456@redis:6379/1"</span></span> 19<span class="line"> <span class="token key atrule">concurrency</span><span class="token punctuation">:</span> <span class="token number">10</span></span> 20<span class="line"> <span class="token key atrule">queues</span><span class="token punctuation">:</span></span> 21<span class="line"> <span class="token key atrule">critical</span><span class="token punctuation">:</span> <span class="token number">10</span></span> 22<span class="line"> <span class="token key atrule">default</span><span class="token punctuation">:</span> <span class="token number">5</span></span> 23<span class="line"> <span class="token key atrule">low</span><span class="token punctuation">:</span> <span class="token number">1</span></span> 24<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="å «ãæä»¶ç®¡ç模å" tabindex="-1"><a class="header-anchor" href="#å «ãæä»¶ç®¡ç模å"><span>å «ãæä»¶ç®¡ç模å</span></a></h2><h3 id="_1-æä»¶æå¡-fileservice" tabindex="-1"><a class="header-anchor" href="#_1-æä»¶æå¡-fileservice"><span>1. æä»¶æå¡ï¼FileServiceï¼</span></a></h3><p>ä½äº <code>internal/service/file_service.go</code>ï¼ç®¡çæä»¶å æ°æ®ï¼</p><ul><li>æä»¶æ¥è¯¢ãä¸è½½ãå é¤</li><li>å¤å¶æä»¶å°å</li><li>å¾ç大徿¥ç</li></ul><h3 id="_2-æä»¶ä¼ è¾æå¡-filetransferservice" tabindex="-1"><a class="header-anchor" href="#_2-æä»¶ä¼ è¾æå¡-filetransferservice"><span>2. æä»¶ä¼ è¾æå¡ï¼FileTransferServiceï¼</span></a></h3><p>ä½äº <code>internal/service/file_transfer_service.go</code>ï¼å¤çæä»¶ä¸ä¼ ä¸è½½ï¼</p><ul><li>æ¯æä¸ä¼ å° OSSï¼MinIOï¼ææ¬å°åå¨</li><li>æä»¶ä¸è½½</li><li>æä»¶ä¼ è¾è·¯ç±éè¦æå¨æ³¨åï¼ä¸è½ä½¿ç¨ä»£ç çæå¨ç Handlerï¼</li></ul><blockquote><p><strong>注æ</strong>ï¼æä»¶ä¼ è¾æå¡ç±äºæ¶å multipart form æ°æ®å¤çï¼æ æ³ä½¿ç¨ Protobuf èªå¨çæç Handlerï¼éè¦å¨ <code>rest_server.go</code> 䏿卿³¨åè·¯ç±ã</p></blockquote><h2 id="ä¹ãæ¶æ¯ç®¡ç模å" tabindex="-1"><a class="header-anchor" href="#ä¹ãæ¶æ¯ç®¡ç模å"><span>ä¹ãæ¶æ¯ç®¡ç模å</span></a></h2><h3 id="_1-ç«å ä¿¡æå¡-internalmessageservice" tabindex="-1"><a class="header-anchor" href="#_1-ç«å ä¿¡æå¡-internalmessageservice"><span>1. ç«å ä¿¡æå¡ï¼InternalMessageServiceï¼</span></a></h3><p>ä½äº <code>internal/service/internal_message_service.go</code>ï¼</p><ul><li>åéæ¶æ¯ç»æå®ç¨æ·</li><li>æ¥çç¨æ·å·²è¯»ç¶æå已读æ¶é´</li><li>æ¶æ¯è¯¦ç»æ¥çãå é¤</li><li>æ 为已读ãå ¨é¨å·²è¯»</li></ul><h3 id="_2-æ¶æ¯åç±»æå¡-internalmessagecategoryservice" tabindex="-1"><a class="header-anchor" href="#_2-æ¶æ¯åç±»æå¡-internalmessagecategoryservice"><span>2. æ¶æ¯åç±»æå¡ï¼InternalMessageCategoryServiceï¼</span></a></h3><p>ä½äº <code>internal/service/internal_message_category_service.go</code>ï¼</p><ul><li>æ¯æäºçº§èªå®ä¹æ¶æ¯åç±»</li><li>ç¨äºæ¶æ¯ç®¡çæ¶çåç±»éæ©</li></ul><h3 id="_3-æ¶æ¯æ¥æ¶è æå¡-internalmessagerecipientservice" tabindex="-1"><a class="header-anchor" href="#_3-æ¶æ¯æ¥æ¶è æå¡-internalmessagerecipientservice"><span>3. æ¶æ¯æ¥æ¶è æå¡ï¼InternalMessageRecipientServiceï¼</span></a></h3><p>ä½äº <code>internal/service/internal_message_recipient_service.go</code>ï¼</p><ul><li>ç®¡çæ¶æ¯æ¥æ¶è </li><li>æ¯ææå®ç¨æ·ãè§è²ãé¨é¨çå¤ç§æ¥æ¶èå´</li></ul><h2 id="åãæ¥å¿å®¡è®¡æ¨¡å" tabindex="-1"><a class="header-anchor" href="#åãæ¥å¿å®¡è®¡æ¨¡å"><span>åãæ¥å¿å®¡è®¡æ¨¡å</span></a></h2><h3 id="_1-ç»å½å®¡è®¡æ¥å¿-loginauditlogservice" tabindex="-1"><a class="header-anchor" href="#_1-ç»å½å®¡è®¡æ¥å¿-loginauditlogservice"><span>1. ç»å½å®¡è®¡æ¥å¿ï¼LoginAuditLogServiceï¼</span></a></h3><ul><li>è®°å½ç¨æ·ç»å½æåå失败æ¥å¿</li><li>æ¯æ IP å½å±å°è®°å½</li></ul><h3 id="_2-api-审计æ¥å¿-apiauditlogservice" tabindex="-1"><a class="header-anchor" href="#_2-api-审计æ¥å¿-apiauditlogservice"><span>2. API 审计æ¥å¿ï¼ApiAuditLogServiceï¼</span></a></h3><ul><li>è®°å½ API 请æ±ç详ç»ä¿¡æ¯</li><li>éè¿ä¸é´ä»¶èªå¨éé</li></ul><h3 id="_3-æä½å®¡è®¡æ¥å¿-operationauditlogservice" tabindex="-1"><a class="header-anchor" href="#_3-æä½å®¡è®¡æ¥å¿-operationauditlogservice"><span>3. æä½å®¡è®¡æ¥å¿ï¼OperationAuditLogServiceï¼</span></a></h3><ul><li>è®°å½ç¨æ·æä½æ¥å¿ï¼æ£å¸¸åå¼å¸¸ï¼</li><li>æ¯æ IP å½å±å°è®°å½</li><li>æ¥çæä½æ¥å¿è¯¦æ </li></ul><h3 id="_4-æ°æ®è®¿é®å®¡è®¡æ¥å¿-dataaccessauditlogservice" tabindex="-1"><a class="header-anchor" href="#_4-æ°æ®è®¿é®å®¡è®¡æ¥å¿-dataaccessauditlogservice"><span>4. æ°æ®è®¿é®å®¡è®¡æ¥å¿ï¼DataAccessAuditLogServiceï¼</span></a></h3><ul><li>è®°å½æ°æ®è®¿é®è¡ä¸º</li></ul><h3 id="_5-æé审计æ¥å¿-permissionauditlogservice" tabindex="-1"><a class="header-anchor" href="#_5-æé审计æ¥å¿-permissionauditlogservice"><span>5. æé审计æ¥å¿ï¼PermissionAuditLogServiceï¼</span></a></h3><ul><li>è®°å½æéåæ´æä½</li></ul><h3 id="_6-çç¥è¯ä¼°æ¥å¿-policyevaluationlogservice" tabindex="-1"><a class="header-anchor" href="#_6-çç¥è¯ä¼°æ¥å¿-policyevaluationlogservice"><span>6. çç¥è¯ä¼°æ¥å¿ï¼PolicyEvaluationLogServiceï¼</span></a></h3><ul><li>è®°å½æéçç¥è¯ä¼°è¿ç¨</li></ul><h2 id="åä¸ãç»å½çç¥æ¨¡å" tabindex="-1"><a class="header-anchor" href="#åä¸ãç»å½çç¥æ¨¡å"><span>åä¸ãç»å½çç¥æ¨¡å</span></a></h2><h3 id="ç»å½çç¥æå¡-loginpolicyservice" tabindex="-1"><a class="header-anchor" href="#ç»å½çç¥æå¡-loginpolicyservice"><span>ç»å½çç¥æå¡ï¼LoginPolicyServiceï¼</span></a></h3><p>ä½äº <code>internal/service/login_policy_service.go</code>ï¼</p><ul><li>管çç»å½çç¥è§å</li><li>å¯é ç½® IP ç½åå/é»åå</li><li>å¯é ç½®æ¶é´éå¶</li><li>å¯é ç½®ç»å½å¤±è´¥éå®çç¥</li></ul><h2 id="åäºãè¯è¨ç®¡ç模å" tabindex="-1"><a class="header-anchor" href="#åäºãè¯è¨ç®¡ç模å"><span>åäºãè¯è¨ç®¡ç模å</span></a></h2><h3 id="è¯è¨æå¡-languageservice" tabindex="-1"><a class="header-anchor" href="#è¯è¨æå¡-languageservice"><span>è¯è¨æå¡ï¼LanguageServiceï¼</span></a></h3><p>ä½äº <code>internal/service/language_service.go</code>ï¼</p><ul><li>管çç³»ç»æ¯æçè¯è¨å表</li><li>å½é åï¼i18nï¼åºç¡æ°æ®</li><li>ä¸åå ¸æ¡ç®å½é åèå¨</li></ul>`,138)])])}const o=n(l,[["render",t]]),d=JSON.parse('{"path":"/admin/backend-modules.html","title":"åç«¯æ ¸å¿æ¨¡å详解","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"ä¸ã认è¯ä¸æææ¨¡å","slug":"ä¸ã认è¯ä¸æææ¨¡å","link":"#ä¸ã认è¯ä¸æææ¨¡å","children":[{"level":3,"title":"1. è®¤è¯æå¡ï¼AuthenticationServiceï¼","slug":"_1-è®¤è¯æå¡-authenticationservice","link":"#_1-è®¤è¯æå¡-authenticationservice","children":[]},{"level":3,"title":"2. 认è¯ä¸é´ä»¶","slug":"_2-认è¯ä¸é´ä»¶","link":"#_2-认è¯ä¸é´ä»¶","children":[]},{"level":3,"title":"3. ææå¼æ","slug":"_3-ææå¼æ","link":"#_3-ææå¼æ","children":[]},{"level":3,"title":"4. 审计æ¥å¿ä¸é´ä»¶","slug":"_4-审计æ¥å¿ä¸é´ä»¶","link":"#_4-审计æ¥å¿ä¸é´ä»¶","children":[]}]},{"level":2,"title":"äºãç¨æ·ç®¡ç模å","slug":"äºãç¨æ·ç®¡ç模å","link":"#äºãç¨æ·ç®¡ç模å","children":[{"level":3,"title":"1. ç¨æ·æå¡ï¼UserServiceï¼","slug":"_1-ç¨æ·æå¡-userservice","link":"#_1-ç¨æ·æå¡-userservice","children":[]},{"level":3,"title":"2. ç¨æ·åè¯æå¡ï¼UserCredentialServiceï¼","slug":"_2-ç¨æ·åè¯æå¡-usercredentialservice","link":"#_2-ç¨æ·åè¯æå¡-usercredentialservice","children":[]},{"level":3,"title":"3. ç¨æ·æ¡£æ¡æå¡ï¼UserProfileServiceï¼","slug":"_3-ç¨æ·æ¡£æ¡æå¡-userprofileservice","link":"#_3-ç¨æ·æ¡£æ¡æå¡-userprofileservice","children":[]},{"level":3,"title":"4. æ°æ®å±","slug":"_4-æ°æ®å±","link":"#_4-æ°æ®å±","children":[]}]},{"level":2,"title":"ä¸ãç§æ·ç®¡ç模å","slug":"ä¸ãç§æ·ç®¡ç模å","link":"#ä¸ãç§æ·ç®¡ç模å","children":[{"level":3,"title":"ç§æ·æå¡ï¼TenantServiceï¼","slug":"ç§æ·æå¡-tenantservice","link":"#ç§æ·æå¡-tenantservice","children":[]},{"level":3,"title":"å¤ç§æ·å ³ç³»æ¨¡å","slug":"å¤ç§æ·å ³ç³»æ¨¡å","link":"#å¤ç§æ·å ³ç³»æ¨¡å","children":[]}]},{"level":2,"title":"åãæéä½ç³»æ¨¡å","slug":"åãæéä½ç³»æ¨¡å","link":"#åãæéä½ç³»æ¨¡å","children":[{"level":3,"title":"1. æéæå¡ï¼PermissionServiceï¼","slug":"_1-æéæå¡-permissionservice","link":"#_1-æéæå¡-permissionservice","children":[]},{"level":3,"title":"2. è§è²æå¡ï¼RoleServiceï¼","slug":"_2-è§è²æå¡-roleservice","link":"#_2-è§è²æå¡-roleservice","children":[]},{"level":3,"title":"3. èåæå¡ï¼MenuServiceï¼","slug":"_3-èåæå¡-menuservice","link":"#_3-èåæå¡-menuservice","children":[]},{"level":3,"title":"4. API æ¥å£æå¡ï¼ApiServiceï¼","slug":"_4-api-æ¥å£æå¡-apiservice","link":"#_4-api-æ¥å£æå¡-apiservice","children":[]},{"level":3,"title":"5. æ°æ®æé","slug":"_5-æ°æ®æé","link":"#_5-æ°æ®æé","children":[]}]},{"level":2,"title":"äºãç»ç»æ¶ææ¨¡å","slug":"äºãç»ç»æ¶ææ¨¡å","link":"#äºãç»ç»æ¶ææ¨¡å","children":[{"level":3,"title":"1. ç»ç»ç®¡çï¼OrgUnitServiceï¼","slug":"_1-ç»ç»ç®¡ç-orgunitservice","link":"#_1-ç
24»ç»ç®¡ç-orgunitservice","children":[]},{"level":3,"title":"2. é¨é¨ç®¡ç","slug":"_2-é¨é¨ç®¡ç","link":"#_2-é¨é¨ç®¡ç","children":[]},{"level":3,"title":"3. èä½ç®¡çï¼PositionServiceï¼","slug":"_3-èä½ç®¡ç-positionservice","link":"#_3-èä½ç®¡ç-positionservice","children":[]}]},{"level":2,"title":"å
ãåå
¸ç®¡ç模å","slug":"å
ãåå
¸ç®¡ç模å","link":"#å
ãåå
¸ç®¡ç模å","children":[{"level":3,"title":"1. åå
¸ç±»åæå¡ï¼DictTypeServiceï¼","slug":"_1-åå
¸ç±»åæå¡-dicttypeservice","link":"#_1-åå
¸ç±»åæå¡-dicttypeservice","children":[]},{"level":3,"title":"2. åå
¸æ¡ç®æå¡ï¼DictEntryServiceï¼","slug":"_2-åå
¸æ¡ç®æå¡-dictentryservice","link":"#_2-åå
¸æ¡ç®æå¡-dictentryservice","children":[]}]},{"level":2,"title":"ä¸ãä»»å¡è°åº¦æ¨¡å","slug":"ä¸ãä»»å¡è°åº¦æ¨¡å","link":"#ä¸ãä»»å¡è°åº¦æ¨¡å","children":[{"level":3,"title":"任塿å¡ï¼TaskServiceï¼","slug":"任塿å¡-taskservice","link":"#任塿å¡-taskservice","children":[]}]},{"level":2,"title":"å
«ãæä»¶ç®¡ç模å","slug":"å
«ãæä»¶ç®¡ç模å","link":"#å
«ãæä»¶ç®¡ç模å","children":[{"level":3,"title":"1. æä»¶æå¡ï¼FileServiceï¼","slug":"_1-æä»¶æå¡-fileservice","link":"#_1-æä»¶æå¡-fileservice","children":[]},{"level":3,"title":"2. æä»¶ä¼ è¾æå¡ï¼FileTransferServiceï¼","slug":"_2-æä»¶ä¼ è¾æå¡-filetransferservice","link":"#_2-æä»¶ä¼ è¾æå¡-filetransferservice","children":[]}]},{"level":2,"title":"ä¹ãæ¶æ¯ç®¡ç模å","slug":"ä¹ãæ¶æ¯ç®¡ç模å","link":"#ä¹ãæ¶æ¯ç®¡ç模å","children":[{"level":3,"title":"1. ç«å
ä¿¡æå¡ï¼InternalMessageServiceï¼","slug":"_1-ç«å
ä¿¡æå¡-internalmessageservice","link":"#_1-ç«å
ä¿¡æå¡-internalmessageservice","children":[]},{"level":3,"title":"2. æ¶æ¯åç±»æå¡ï¼InternalMessageCategoryServiceï¼","slug":"_2-æ¶æ¯åç±»æå¡-internalmessagecategoryservice","link":"#_2-æ¶æ¯åç±»æå¡-internalmessagecategoryservice","children":[]},{"level":3,"title":"3. æ¶æ¯æ¥æ¶è
æå¡ï¼InternalMessageRecipientServiceï¼","slug":"_3-æ¶æ¯æ¥æ¶è
æå¡-internalmessagerecipientservice","link":"#_3-æ¶æ¯æ¥æ¶è
æå¡-internalmessagerecipientservice","children":[]}]},{"level":2,"title":"åãæ¥å¿å®¡è®¡æ¨¡å","slug":"åãæ¥å¿å®¡è®¡æ¨¡å","link":"#åãæ¥å¿å®¡è®¡æ¨¡å","children":[{"level":3,"title":"1. ç»å½å®¡è®¡æ¥å¿ï¼LoginAuditLogServiceï¼","slug":"_1-ç»å½å®¡è®¡æ¥å¿-loginauditlogservice","link":"#_1-ç»å½å®¡è®¡æ¥å¿-loginauditlogservice","children":[]},{"level":3,"title":"2. API 审计æ¥å¿ï¼ApiAuditLogServiceï¼","slug":"_2-api-审计æ¥å¿-apiauditlogservice","link":"#_2-api-审计æ¥å¿-apiauditlogservice","children":[]},{"level":3,"title":"3. æä½å®¡è®¡æ¥å¿ï¼OperationAuditLogServiceï¼","slug":"_3-æä½å®¡è®¡æ¥å¿-operationauditlogservice","link":"#_3-æä½å®¡è®¡æ¥å¿-operationauditlogservice","children":[]},{"level":3,"title":"4. æ°æ®è®¿é®å®¡è®¡æ¥å¿ï¼DataAccessAuditLogServiceï¼","slug":"_4-æ°æ®è®¿é®å®¡è®¡æ¥å¿-dataaccessauditlogservice","link":"#_4-æ°æ®è®¿é®å®¡è®¡æ¥å¿-dataaccessauditlogservice","children":[]},{"level":3,"title":"5. æé审计æ¥å¿ï¼PermissionAuditLogServiceï¼","slug":"_5-æé审计æ¥å¿-permissionauditlogservice","link":"#_5-æé审计æ¥å¿-permissionauditlogservice","children":[]},{"level":3,"title":"6. çç¥è¯ä¼°æ¥å¿ï¼PolicyEvaluationLogServiceï¼","slug":"_6-çç¥è¯ä¼°æ¥å¿-policyevaluationlogservice","link":"#_6-çç¥è¯ä¼°æ¥å¿-policyevaluationlogservice","children":[]}]},{"level":2,"title":"åä¸ãç»å½çç¥æ¨¡å","slug":"åä¸ãç»å½çç¥æ¨¡å","link":"#åä¸ãç»å½çç¥æ¨¡å","children":[{"level":3,"title":"ç»å½çç¥æå¡ï¼LoginPolicyServiceï¼","slug":"ç»å½çç¥æå¡-loginpolicyservice","link":"#ç»å½çç¥æå¡-loginpolicyservice","children":[]}]},{"level":2,"title":"åäºãè¯è¨ç®¡ç模å","slug":"åäºãè¯è¨ç®¡ç模å","link":"#åäºãè¯è¨ç®¡ç模å","children":[{"level":3,"title":"è¯è¨æå¡ï¼LanguageServiceï¼","slug":"è¯è¨æå¡-languageservice","link":"#è¯è¨æå¡-languageservice","children":[]}]}
24],"git":{"updatedTime":1780586020000,"contributors":[{"name":"Bobo","username":"Bobo","email":"[email protected]","commits":1,"url":"https://github.com/Bobo"}],"changelog":[{"hash":"87b8f49b88e6ed7701d9d8014bef92cdc7df73f5","time":1780586020000,"email":"[email protected]","author":"Bobo","message":"docs(admin): æ·»å åç«¯ææ¡£å¹¶æ´æ°ä¾§è¾¹æ é
ç½®"}]},"filePathRelative":"admin/backend-modules.md"}');export{o as comp,d as data};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.