# # AnnotationAuthorityManager

在正式介绍如何使用 AnnotationAuthorityManager 工具类之前，我们先来了解一下注释权限类型及设置方式。

## # 注释权限类型

注释的权限类型有以下三种：

1. PDF 注释权限: PDF 文档本身对注释的操作限制， 可以使用 User_Permissions
   (opens new window) ( 全局) 或者 Annot_Flags
   (opens new window)（单个注释）来进行设置。PDF 注释权限的设置将被写入文档，从而改变文档。

2. 视图注释权限：视图层对注释的操作限制。视图注释权限的设置仅影响应用程序，并且不会写入文档，因此不会改变文档。

3. 交互注释权限：PDF 注释权限和视图注释权限的交集被称为交互式注释权限。在加载 PDF 文档后，用户对注释的操作将受到交互式注释权限的限制。

### # 注释权限的设置方式

Foxit PDF SDK for Web 提供了以下 4 种方式来设置注释权限，具体如下：

1. 通过 PDFViewer 构造函数设置视图注释权限。 比如，[options.customs.getDocPermissions=(doc:PDFDoc)=>-1]
   (opens new window) 和 [options.customs.getAnnotPermissions=(annot:Annot)=>Promise.resolve()]
   (opens new window)。

2. 通过 AnnotationAuthorityManager 工具类实时动态设置视图注释权限。如 setAnnotPermissionCallback
   (opens new window)。

3. 通过 PDFDoc::setPasswordAndPermission
   (opens new window) 全局设置 PDF 注释权限。

4. 通过 Annot:setFlags
   (opens new window) 设置 PDF 注释权限。

## # AnnotationAuthorityManager 的使用

您可以通过设置PDF注释权限或者视图注释权限来更新交互注释权限。在某些场景中，您可以并不想对原始文档进行修改，而只是想在应用层控制用户对 annotation 的操作权限。在这种情况下，您可以使用 AnnotationAuthorityManager 工具类来实时设置 annotation 的视图注释权限，然后更新交互注释权限即可实现。

备注: 当应用层对 annotation 交互注释权限更新时，Foxit PDF SDK for Web 会在内部将应用层设置的视图注释权限与PDF注释权限进行取交集，以确定用户可以对 annotation 操作的最终交互权限。

### # 交互注释权限更新时机

以下示例代码将展示用户如何被动或主动的更新交互注释权限。

1. 被动更新交互注释权限

在文档打开之前，用户可以通过 setAnnotPermissionCallback
(opens new window), [options.customs.getDocPermissions=(doc:PDFDoc)=>-1]
(opens new window), 和 [options.customs.getAnnotPermissions=(annot:Annot)=>Promise.resolve()]
(opens new window) 先设置权限。在文档打开后，SDK 会自动更新交互注释权限，用户无需另外设置。

备注：这里的 "被动更新" 是指 SDK 在打开文档后会自动完成交互注释权限的校验与更新，无需用户主动去调用接口来更新。

        // 在打开文档之前，设置视图注释权限有以下两种方法：

        // 第一种方法：构建 PDFViewer 对象时，根据 annotation 的信息设置视图注释权限
        const pdfui = new PDFUI({
            viewerOptions: {
                customs:{
                    // 设置视图注释权限
                    getAnnotPermissions:function(annot){
                        const ANNOTATION_PERMISSION = UIExtension.PDFViewCtrl.constants.ANNOTATION_PERMISSION
                        // 设置拥有所有的视图注释权限
                        return Promise.resolve([ANNOTATION_PERMISSION.fully]);
                    }
                }
            }
        })

        // 第二种方法：通过 AnnotationAuthorityManager 管理器，设置视图注释权限
        const pdfViewer = await pdfui.getPDFViewer();
        // 获取 AnnotationAuthorityManager 管理器
        const annotAuthMgr = pdfViewer.getAnnotAuthorityManager();
        // 设置视图注释权限
        annotAuthMgr.setAnnotPermissionCallback(function(annot) {
            // 设置没有任何操作权限
            return Promise.resolve([]);
        })

        // 打开 PDF 文档时，SDK 会读取设置的视图注释权限，然后自动更新交互注释权限
        pdfui.openPDFByHttpRangeRequest('http:xxx');

2. 主动更新交互权限

在文档打开之后，用户可以动态设置权限，再通过 updateAll()
(opens new window) 或者 update()
(opens new window) 来主动更新交互注释权限。

        // 打开 PDF 文档
        pdfui.openPDFByHttpRangeRequest('http:xxx');

        // 通过 AnnotationAuthorityManager 管理器，设置视图注释权限
        const pdfViewer = await pdfui.getPDFViewer();
        // 获取 AnnotationAuthorityManager 管理器
        const annotAuthMgr = pdfViewer.getAnnotAuthorityManager();
        // 设置视图注释权限
        annotAuthMgr.setAnnotPermissionCallback(function(annot) {
            // 设置所有的 annotation 没有任何操作权限
            return Promise.resolve([]);
        })

        // 需要手动更新所有 annotation 的交互注释权限，否则设置的视图注释权限无法立即生效
        await annotAuthMgr.updateAll();

在实际项目中，用户可以使用 PDFViewer.getCurrentPDFDoc
(opens new window) 获取当前文档对象并验证当前文档是否已打开。如果值为 null，则表示文档未打开。

### # 视图注释权限使用场景

在实际场景中，可能需要设置不同的视图注释权限。目前主要有四种类型，以下示例是基于预先创建的 `AnnotationAuthorityManager` 实例。

1. 无权限

           // 设置视图注释权限
           annotAuthMgr.setAnnotPermissionCallback(function(annot) {
               // 设置所有的 annotation 没有任何操作权限
               return Promise.resolve([]);
           })

2. 组合权限

           const ANNOTATION_PERMISSION = UIExtension.PDFViewCtrl.constants.ANNOTATION_PERMISSION
           // 设置视图注释权限
           annotAuthMgr.setAnnotPermissionCallback(function(annot) {
               // 设置所有的 annotation 的权限为：可修改属性与行为，可删除/移动/旋转/缩放
               return Promise.resolve([ANNOTATION_PERMISSION.adjustable,ANNOTATION_PERMISSION.deletable,ANNOTATION_PERMISSION.modifiable]);
           })

3. 所有权限

           const ANNOTATION_PERMISSION = UIExtension.PDFViewCtrl.constants.ANNOTATION_PERMISSION
           // 设置视图注释权限
           annotAuthMgr.setAnnotPermissionCallback(function(annot) {
               // 设置拥有所有的视图注释权限
               return Promise.resolve([ANNOTATION_PERMISSION.fully]);
           })

4. 可忽略权限

           // 设置视图注释权限
           annotAuthMgr.setAnnotPermissionCallback(function(annot) {
               // 设置所有的 annotation 的权限为：忽略所有权限限制
               return null;
           })

### # 交互注释权限的使用场景

#### # 示例1：设置 Annotation 的视图权限，不允许删除指定的 annotation

        const pdfViewer = await pdfui.getPDFViewer();
        // 获取 AnnotationAuthorityManager 管理器
        const annotAuthMgr = pdfViewer.getAnnotAuthorityManager();
        // 获取指定页面的指定附件类型 annotationRender
        const fileAnnotRender = pdfViewer.getAnnotRender(0,'name');
        // 获取指定页面的指定附件类型 annotation
        const fileAnnot = fileAnnotRender.getAnnot();
        const ANNOTATION_PERMISSION = PDFViewCtrl.constants.ANNOTATION_PERMISSION
        // 设置视图注释权限
        annotAuthMgr.setAnnotPermissionCallback(function(annot) {
            // 设置指定的 fileAnnot 没有删除权限
            if(annot.getObjectNumber()=== fileAnnot.getObjectNumber()){
                return Promise.resolve(Object.keys(ANNOTATION_PERMISSION).filter(per=>per!==ANNOTATION_PERMISSION.deletable && per!==ANNOTATION_PERMISSION.fully));
            }
        })

        // 更新指定 annotation 的交互注释权限
        await annotAuthMgr.update(fileAnnot);

以上代码执行后，用户就无法删除指定 name 的 annotation。

#### # 示例2：设置 Annotation 的视图注释权限，允许编辑 callout 内容

        const pdfViewer = await pdfui.getPDFViewer();
        // 获取 AnnotationAuthorityManager 管理器
        const annotAuthMgr = pdfViewer.getAnnotAuthorityManager();
        const ANNOTATION_PERMISSION = PDFViewCtrl.constants.ANNOTATION_PERMISSION
        // 设置视图注释权限
        annotAuthMgr.setAnnotPermissionCallback(function(annot) {
            // 设置 callout 类型的 annotation 具有编辑权限
            if(annot.getIntent()=== 'FreeTextCallout'){
                return Promise.resolve([ANNOTATION_PERMISSION.editable]);
            }
        })

        // 更新所有 annotation 的交互注释权限
        await annotAuthMgr.updateAll();

以上代码执行后，用户就可以编辑 FreeText 对象为 callout 的 annotation。

#### # 示例3： 在自定义组件上校验 PDF 注释权限和视图注释权限

以下代码将演示如何在新添加的自定义组件上验证注释权限。

        var pdfui = new PDFUI({
            // 自定义新增一个删除 annotation 的组件
            fragments: [{
                target: 'hand-tool',
                template: '<xbutton class="fv__ui-toolbar-show-text-button" name="cus-delete-button">button behind of hand-tool</xbutton>',
                action: UIExtension.UIConsts.FRAGMENT_ACTION.AFTER,
                config: [{
                    target: 'cus-delete-button',
                    callback: PDFViewCtrl.shared.createClass({
                        mounted: function() {
                            this.permissionHandler();
                        },
                        permissionHandler(){
                            const Events = UIExtension.UIEvents;
                            let permissionHandler = async ()=>{
                                const docRender = await pdfui.getPDFDocRender()
                                // 获取 PDF 注释权限
                                const userPermission = docRender.getUserPermission().getValue();
                                const {AnnotForm} = UIExtension.PDFViewCtrl.Consts.PDFDocPermission;
                                this.hasAnnotForm = (userPermission & AnnotForm) === AnnotForm;
                                // 是否禁用此组件
                                this.component[this.hasAnnotForm?'enable':'disable']();
                            }
                            this.addDestroyHook(
                                pdfui.addViewerEventListener(Events.openFileSuccess,permissionHandler)
                                pdfui.addViewerEventListener(Events.permissionChanged,permissionHandler)
                                pdfui.addViewerEventListener(Events.activeAnnotation,async annotRender=>{
                                    // 获取激活的 annotation
                                    const annot = annotRender.getAnnot();
                                    const pdfViewer = await pdfui.getPDFViewer();
                                    // 获取 AnnotationAuthorityManager 管理器
                                    const annotAuthMgr = pdfViewer.getAnnotAuthorityManager();
                                    // 获取指定 annotation 的视图注释权限
                                    const annotPermission = await annotAuthMgr.getPermission(annot);
                                    // 是否可以删除 annot
                                    const isDeleteAble = annotPermission.isDeletable();
                                    // 是否禁用此组件
                                    this.component[isDeleteAble&&this.hasAnnotForm?'enable':'disable']();
                                })
                            );
                        }
                    }, UIExtension.Controller)
                }]
            }]
        });

### # 视图注释权限的限制

目前视图注释权限的限制范围：

1. Redaction Apply 功能不支持设置交互权限。
2. 目前 AnnotationAuthorityManager 不支持 Form Widget。