MiraiForum

    • 注册
    • 登录
    • 搜索
    • 热门
    • 最新
    • 未解决
    • 标签
    • 群组
    • 友情链接

    已解决 把Permissions系统用于Command以外的权限控制,需要新的Permittee子类?

    开发交流
    2
    4
    807
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • H
      hundun000 ⭐2021⭐ 最后由 hundun000 编辑

      一般性的,一个插件除了Command为入口的功能,还可能包括其他途径触发的功能:

      • Event为入口的功能
      • 由定时器触发的功能

      这些其他途径触发的功能,如果需要做权限控制,或者说服务开关控制,一个方案是自行实现配置文件。如屏蔽消息的思路提到的关闭EventHandler对某个群的服务:

      // onGroupMessage(GroupMessageEvent event)
      if(this.main.getConfig().isBlackList(sender.getSenderID())) {
        return;
      }
      // do sth
      

      以及关闭定时器对某个群的服务:

      // on MyTimer run()
      bot.getGroups().foreach(group -> {
        if(timerConfig.isBlackList(group .getID())) {
          return;
        }
        // do sth
      })
      

      该方案的缺点是需要自行实现和维护多个XXXConfig,需要在文档多个地方说明,增加一个群时涉及多个配置文件……

      故考虑复用Permissions系统,用PermissionId对应EventHandler/Timer的开关,拥有权限则表示启用服务。这样把插件内所有的功能的权限控制/开关,都统一交给Permissions系统,用一份配置文件管理,可动态授权……

      // on init
      val PERMISSION_A = PermissionService.INSTANCE.register(permissionId("eventHandlerA"), "对应eventHandlerA开关");
      val PERMISSION_B = PermissionService.INSTANCE.register(permissionId("timerB"), "对应timerB开关");
      

      则PermissionService.yml会形如:

      grantedPermissionMap: 
        'myPlugin:eventHandlerA': 
          - 'g111111' # 表示只有111111群的群员可以使用eventHandlerA
        'myPlugin:timerB': 
          - 'g222222' # timerB只定时服务222222群
      

      EventHandler的判断变为:

      // onGroupMessage(GroupMessageEvent event)
      Permittee permittee  = permitteeFromGroupId(event.getGroupId());
      if(!permittee.hasPermission(PERMISSION_A) return;
      // do sth
      

      Timer的判断改变为:

      // on MyTimer run()
      bot.getGroups().foreach(group -> {
        Permittee permittee  = permitteeFromGroupId(group .getID());
        if(!permittee.hasPermission(PERMISSION_B) return;
        // do sth
      })
      

      目前的问题是:如何实现permitteeFromGroupId(),重点是返回哪个permittee子类?
      Command为入口已经有了CommandSender;我倾向于Event为入口,由Timer触发也分别有平级的一支子类,然而console文档指出注意:请不要自主实现 Permittee。虽然可以让他们也构造某个CommandSender子类,但毕竟这样的调用确实不是
      来自command,希望能有更合适的方式实现。

      1 条回复 最后回复 回复 引用 0
      • Karlatemp
        Karlatemp 最后由 Karlatemp 编辑

        https://github.com/mamoe/mirai-console/blob/master/backend/mirai-console/src/permission/PermitteeId.kt#L48

        https://github.com/mamoe/mirai-console/blob/53149d1d36cc2c091e738233c404cf747de05800/backend/mirai-console/src/permission/PermissionService.kt#L233

        H 1 条回复 最后回复 回复 引用 0
        • H
          hundun000 ⭐2021⭐ @Karlatemp 最后由 编辑

          @karlatemp 多谢,用起来了

          1 条回复 最后回复 回复 引用 0
          • H
            hundun000 ⭐2021⭐ 最后由 hundun000 编辑

            贴一下该设计在mirai-fleet-prinzeugen插件实际使用的例子。'hundun.fleet.prinzeugen.cos:INSTANCE'对应本帖讨论的自定义权限。

            授权后的config/Console/PermissionService.yml内容示例:

            grantedPermissionMap:
            'hundun.fleet.prinzeugen:*': # 常规Command权限
            - 'm111111.*' # 允许111111群的任意群员使用本插件的所有Command
            'hundun.fleet.prinzeugen.cos:INSTANCE': # 特殊权限,表示本插件(Event功能和定时器功能)的开关
            - m111111.222222 # bot账号222222在群1111111启用本插件

            注册特殊权限(源码简化后展示):

            // on init
            Permission characterCosPermission = registerCosPermission();
            
            protected Permission registerCosPermission() {
                    String newHost = "hundun.fleet.prinzeugen.cos";
                    String newName = "INSTANCE";
                    Permission newParent = Permission.getRootPermission();
                    try {
                        return PermissionService.Companion.getInstance().register(
                                new PermissionId(newHost, newName), 
                                "略", 
                                newParent
                                );
                    } catch (PermissionRegistryConflictException e) {
                        plugin.getLogger().error(e);
                        return null;
                    }
                }
            

            检查特殊权限(源码简化后展示):

            protected boolean checkCosPermission(Bot bot, Group group) {
                    Permission targetPermission = characterCosPermission;
                    ExactMember exactGroup = new ExactMember(group.getId(), bot.getId());
                    return PermissionService.testPermission(targetPermission, exactGroup);
                }
            
            1 条回复 最后回复 回复 引用 0
            • 1 / 1
            • First post
              Last post
            Powered by Mamoe Technologies & NodeBB | 友情链接 | 服务监控 | Contact