In 2021, the Wiki will add a number of tough features, including collaborative editing, page permissions, emojis, and more, that will make the user experience better. As a Wiki user and developer, today I would like to talk about the permissions of the page launched at the end of the year, and summarize the technologies involved in the development stage, the problems encountered and the solutions. I have written an article about permissions of Worktile before. Worktile privilege focuses on the design and implementation of RBAC (role-based privilege control scheme). This article is based on another mainstream privilege design scheme of Wiki page privilege selection: ACL.

This paper is roughly divided into three parts:

    1. The ACL is introduced
    1. Describe our permissions and why we chose them
    1. Designed and implemented

I. Introduction to ACLs

1. What is an ACL?

ACL: an Access Control List (ACL) is a permission Control scheme for files and directories. The famous Linux permission system, it is a typical case of ACL, I also received some inspiration in the development process of Linux permission design.

2. Application scenarios of acLs

The usage scenario can also be asked differently: Why use ACLs? Let’s also use Linux as an example: Linux itself only provides Owner, Group, and Others, meaning that other members or user groups cannot specify more granular permissions.

To better explain, let’s take a simple example (scenario) :

Have four members have A, B, C, D, A, B, C is A member of the group G, A member of the warehouse and the team development created A code code placed in the directory, which is mainly about the code of the group G, has nothing to do with other members, so A set file directory permissions, can read can write permissions are set, No one else has any access.

A is the Owner of the warehouse, G is the Group (including B and C), D is the members unrelated to the file, so it is Others. Now a user E is recruited. Since E is a newcomer, she does not want E to operate the code, but only allows him to view the familiar code.

Faced with this scenario, how to set corresponding permissions for member E? The answer is oh no, because E cannot be the Owner of group G or Others. Therefore, ACL can be used as a supplement to such weak permissions. ACL can support independent permissions for a certain user or user group, which perfectly solves similar scenarios.

PingCode Wiki permission architecture

OK, now that you know what acLs are and how to use them, let’s talk about the permission architecture of a Wiki. The basic architecture is shown in the figure below.

1. Basic permission RBAC — The permission corresponding to the role

1.1 Permission Configuration

1.2 Viewing Permissions

2. Page permissions ACL – Permissions for users and user groups

Page permissions are also used as a supplement to RBAC, which is a more fine-grained permission division, that is, assigning permissions to certain people or user groups.

2.1 Page Permission Settings

Top right menu — “More – Permission Settings”

2.2 Independent Rights and Share Rights

Independent Permissions — “Permissions Settings – Knowledge Base Members”Share Permissions – “Permission Settings – Non-Knowledge Base Members”From our requirements (for users and user group segments of the population) it is compatible with an ACL solution.

Iii. Design and implementation

The students here believe that they have had a general understanding of the Wiki permission function. Now I will introduce the design details, key points, difficulties and the selection and elimination of the scheme in detail.

1. Relational model and database design

After understanding the basic requirements, I made A simple preliminary plan based on my previous development experience, as shown in Plan A below. After adjusting some details according to the prototype and design drawing, PLAN B was produced, as shown in the following figure.

Plan A

Plan B (Final Plan)

Differences between the two schemes:

Scheme A is A common design of relational database, with user/ user group as the leading mapping module and permission, the corresponding relationship is: many-multiple users/user group — > Resource (pageId)

Scenario B, module-led mapping user/group, one-to-many: Resources (pageId) — > User/group (scopes)

Considering that permissions are fully saved, it is precisely because of this interaction that plan B is adjusted. Moreover, the server database is mongodb, which supports array features, which is very suitable.

2. Corresponding program implementation

Resource or module (pageId) — > User/user group (scopes), entity mapping

field type describe
scopes Array Permission Setting Details
permission_type Enum Permission types
principals ScopeDesignation[] Specify the detailed
type ScopeDesignationType Specify the type
id UID ID Unique identification of a person/user group/department
value number Permission values

The permission value calculation refers to Linux, using the bit operation: 1, 2, 4, 8…

  • The accumulated maximum mask value is: read only 1 + edit 2, final data inventory 3.
  • Check whether a permission value exists: Permission value & Expected permission value = Existing/expected permission value.

3. Agreement API

Again, the save interaction determines that add, modify, delete is an API.

  • Save (add/modify/Remove): {put} /api/wiki/spaces/:spaceId/pages/:pageId/permission$ 
  • Access to:{get} /api/wiki/spaces/:spaceId/pages/:pageId/permission/:scopeType$

4. Complex scenarios involved

There are a lot of complex scenarios involved in permissions. The discussion and decision of the following scenarios went through many twists and turns. Some functions were redone twice in the middle of the process, the iteration was postponed for a week, and two meetings lasted about two and a half hours in total.

4.1 Permission Inheritance (Complex Scenario)

The first point is difficult to handle permissions inheritance, it is round, believes that many products have met a similar scenario (what is here not here), I had reference from the Angle of technology and products the processing of Linux, but due to system level and the application is slightly different, made some adjustments, listed below are we have done.

First version: Child pages inherit completely from parent pages and cannot be changed

  • The parent page is not visible, and the child page is not
  • The parent page is read-only, the child page is edited, and the final child page is read-only
  • The parent page is edited, the child page is read only, and the final child page is edited

Unsatisfactory scenarios and logical conflict points:

  • The parent page is viewable, some child pages are expected to be viewable, and some child pages are not
  • The parent page is viewable but not editable, and some child pages are expected to have editable permissions
  • The parent page allows editing, but some child pages do not

Second edition: child pages allow independent permissions, inheriting parent permissions by default

Page inheritance logic: once the child page is set, the inheritance relationship with the parent page is interrupted, and the permission type can be changed after the interruption

  • After setting permissions on the parent page, the child page does not set permissions and inherits the parent page by default.
  • After setting permissions for a child page, it does not inherit the permissions of the parent page and forms its own page permissions

4.2 Middleware Logic

Middleware also involves many scenarios, such as single page detail view, drag and drop movement, cross-knowledge base movement, replication, deletion and so on. The core verification logic is shown in the figure below.

4.3 Page Tree Display and Permission Calculation (difficult points)

4.3.1 Displaying logic

At the meeting, the following options were discussed for displaying the page tree:

  • Display all levels of the page, according to the permissions of the visible content (there is a title privacy problem, after too many levels, you will see multiple invisible titles, discard)
  • Show only the pages that have permissions, bring out the child pages (hierarchy is out of whack, discard)
  • Landing scheme: only display pages with permissions. When the parent page is not visible and the child page is visible, the parent page will be displayed. If there are no visible child pages, the parent page will not be visible either (Scheme 2) — The title invisible to the parent page will be displayed in gray (click to retain the effect)
  • Directly hide the father and son (implemented scheme 1, can only be viewed by notice, less entrance, change the inheritance relationship, not applicable, abandoned)

If the child page has permissions, the parent page will be displayed to ensure the integrity of the tree structure. If neither the current page nor the child page has permissions, then the filter will be removed. The following figure

4.3.2 Permission Calculation (Technical difficulties)

Difficult points:

  1. Page trees involve inheritance
  2. Full calculation (do not need recursive processing), so the program computational complexity to consider
  3. Filter logic (children have access to view, the parent must show)

solution

  1. The database stores the parent and parent_ids fields. Parent_ids is ordered flatten by tree level, such as A->B->C, and parent_ids stores [A,B,C].
  2. Split the list data into two groups, one group is all pages, the other group is all as the parent page, the specific query just need to verify whether parent_id exists, belongs to the database operation.
  3. Transform the List data structure into a Map or Set, reducing the number of iterations to reduce complexity.

Concrete processing logic

Preparations:

  1. Retrieve the page list data of the current knowledge base and the corresponding ACL permission list from the database
  2. Flatten the page list to Map (to reduce complexity below)
  3. Convert permission list flat to Map (same purpose as above)
  4. Retrieve the knowledge base permission of RBAC
  5. A Set of parent pages that needs to be displayed (more on this below).
  6. Final page list (including permission values)

As shown below (serial numbers are specially marked for the convenience of subsequent explanation)

The processing process is as follows:

  1. List of iterated pages

  2. Take out a page and find the corresponding permission

  3. If the set corresponding permission is found, merge the RBAC permission into the final result set and execute the following logic if not found

    1. Iterates backwards through the parent_ids of the current page.
    2. If there is no parent or all the parents have no permission, continue the outermost iteration, instead, retrieve the most recent parent page, and put the page between the parent page and the current page into ⑥ (Set), for example: Suppose there are three pages, A, B, C, C’s parent is B, B’s parent is A, the current iteration is C, C has no permissions, B has no permissions, A has permissions, then finally push A and B into the Set, C also has permissions due to inheritance logic.
  4. Adds parent pages from the Set to the final result Set

  5. Continue iterating until the end

Finally, it is found that ⑥ is to supplement the missing part of the data: the child page is visible, the parent page is not visible, but the parent page is to be displayed.

You may have a question from the above session why merge RBAC knowledge base permissions, please read on.

4.4 Permission Related Special Handling

As mentioned above, page permissions have been verified, but knowledge base permissions have been merged because of the following product logic:

  1. Knowledge base does not have edit permission, page permission does, then finally have edit permission, so to override the knowledge base edit permission.
  2. Actions that cannot be performed by a member with read-only permission:
  • Cannot create child pages
  • The current page cannot be deleted
  • Cannot move current page
  • Cannot move under a read-only page (actually add page for the target page)
  • Unable to copy pages
  • Cannot copy to a read-only page
  • Unable to publish page
  • The page cannot be renamed
  • The edit page cannot be displayed

Be careful not to miss the scene.

4.4.1 Personal vision for the follow-up

For these special processing, personal feeling, after all, is not a solution, and the subsequent new add or remove permissions, much more consideration, technical Angle is difficult to maintain, it is easy to miss, so imagine pages also add more access points, and it takes for users to take the initiative to check the forbidden permissions, technically can unify a set of logic.

Write at the end

The above is just a list of common and slightly complex scenarios, but there are a lot of details in the actual development, so the development period was busy, experienced brainstorming, as well as the timely adjustment and reflection of mistakes, these are valuable experience.

Finally, some insights from development so far:

  • Timely communication between the team, full understanding of the needs, and the establishment of a unified understanding, to avoid the embarrassing incident of turning the chimney into a well, and to reduce the situation of blaming each other, have a good effect on the team. It is worth mentioning that the Wiki team inherits this good habit, which is in line with the values of the Wiki product.
  • Technical personnel should actively consider the needs, give priority to the perspective of users and products, then consider technology, do not be too dedicated to technology, but ignore the original intention of users and products.
  • Technical people are responsible for every line of code. Don’t leave technical debt to yourself or anyone else.
  • To do a good job of details, as or technology to do a good job of details, “just” to may be the details determine the success or failure.

That’s all. Thank you very much to everyone who has seen this. If you have any questions, welcome to discuss and exchange.