package com.app.admin.framework.system.permission.shiro.realm;

import cn.hutool.extra.spring.SpringUtil;
import com.app.admin.framework.system.administrator.model.SysAdministrator;
import com.app.admin.framework.system.administrator.service.SysAdministratorService;
import com.app.admin.framework.system.module.model.SysModule;
import com.app.admin.framework.system.organization.model.SysOrganization;
import com.app.admin.framework.system.organization.service.SysOrganizationService;
import com.app.admin.framework.system.permission.authorization.service.SysAuthorityService;
import com.app.admin.framework.system.permission.shiro.matcher.PwdCredentialsMatcher;
import com.app.framework.core.support.enums.common.StateEnum;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.Iterator;
import java.util.List;

public class ShiroRealm extends AuthorizingRealm {

    public ShiroRealm() {
        this.setCredentialsMatcher(new PwdCredentialsMatcher());
    }

    private SysAdministratorService getSysAdministratorService() {
        return SpringUtil.getBean(SysAdministratorService.class);
    }

    private SysOrganizationService getSysOrganizationService() {
        return SpringUtil.getBean(SysOrganizationService.class);
    }

    private SysAuthorityService getSysAuthorityService() {
        return SpringUtil.getBean(SysAuthorityService.class);
    }

    /**
     * 权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SysAdministrator loginUser = (SysAdministrator) principalCollection.getPrimaryPrincipal();//获取登录的用户
        if (loginUser != null) {
            //权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            //用户的角色对应的所有权限，如果只使用角色定义访问权限，下面的四行可以不要
            List<SysModule> listFuncBtn = getSysAuthorityService().getLoginUserModule(loginUser, 2);
            for (Iterator<SysModule> iterator = listFuncBtn.iterator(); iterator.hasNext(); ) {
                SysModule m = iterator.next();
                info.addStringPermission(m.getMark());
            }
            return info;
        }
        return null;
    }

    /**
     * 登录认证;
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String) authenticationToken.getPrincipal();
        SysAdministrator loginUser = getSysAdministratorService().findByUsername(username);
        if (loginUser == null) {
            throw new UnknownAccountException();//没找到帐号
        }
        if (StateEnum.DISABLE.equalValue(loginUser.getState())) {
            throw new DisabledAccountException(); //帐号禁用
        }
        //判断组织机构状态
        if (loginUser.getOrganizationId() > 0) {
            SysOrganization organization = getSysOrganizationService().getById(loginUser.getOrganizationId());
            if (organization == null || StateEnum.DELETE.equalValue(organization.getState())) {
                throw new UnknownAccountException("账号所属机构已被删除"); //组织机构不在
            } else if (StateEnum.DISABLE.equalValue(organization.getState())) {
                throw new UnknownAccountException("账号所属机构已被禁用"); //组织机构禁用
            }
        }
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以在此判断或自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                loginUser, //用户
                loginUser.getPassword(), //密码
                ByteSource.Util.bytes(loginUser.getUsername()),//salt=username+salt
                loginUser.getUsername()  //realm name
        );
        return authenticationInfo;
    }
}
