# 協作筆記 ─ 協作與權限 <!-- 標籤 --> ###### tags: `DocuSky暫存`, `工具`, `文件狀態:停止更新` <!-- 內文編輯更新資訊,若有更動此份文件內容,請更新此項資訊 --> > [name=Sih-Pin Lai, 彙整] > [time=Thu, Mar 18, 2021 4:35 PM] <!-- 摘要 --> :::success <!-- 當前負責人使用高亮標示,新接替維護人員請加在第一個 --> - **建立者**:陳柔安 - **維護者**:陳柔安 - [工具測試頁面](https://docusky.org.tw/DocuSky/WebApi/FUNCTEST-friendAccessibleDb.html) - [工作簡報](https://drive.google.com/drive/folders/1fwrI8JPNb2lkXQ_jOyiTYav4hC0LFnpI?usp=sharing) ::: <!-- 筆記正文開始 --> :::warning **原文件** * [協作筆記開發survey](/MzuW5qlFRkug-e07T00aZQ) * [1 月進度](/ghw5MOF2SvWvmUPDnV-PsA) * [2 月進度](/VlR_3KS-T2qy74NxDNygjQ) * [190312 meeting](/yjbe3wgXSLiHW_iNenxl8w) * [190318 meeting](/7rheN3g9THCDyonrQ88DiA) ::: ## 設計 ### 分享機制 * DocuXML分享 * 傳送到欲分享對象的雲端資料庫中 - 以widget直接傳送到對方的雲端中 * 讓欲分享對象瀏覽個人的雲端資料庫 - 讓欲對象有權限進到分享者的雲端中 ### 共同編輯機制 * 以「雲端資料庫」的共同編輯為預想 * 操作權限:可瀏覽、可修改、可新增刪除 * Coupus_level權限 - 整份文獻集的編輯 - 包含Metadata欄位及tag標籤種類的編輯 * Document_level權限 - 文獻集中的文件編輯 - 文件的全文、Metadata及tag的編輯 ### 編輯機制設計 * 編輯作業在server端的操作 * 編輯作業在client端的操作 * 編輯作業在server+client的操作 * 防呆與防護的設計 - 是否要有中介檢核 * 啟動共同編輯及執行共同編輯的介面及功能 ### 權限管理機制 * 群組模式 - 為共同作業群組 * 授權模式 - 由主控者授權給其他操作者 * 好友模式 - 將某些人設定為好友 ## 開發進度 ### 2019/03/18 * 權限規劃、Widget 接合 - [x] add item bug 修改 ==[是否開放此功能有待商榷]== - [x] 部分欄位(e.g.filename)鎖定不開放編輯 * 問題釐清: filename 可改但必須唯一 * 改為: 若改動到filename 則無法 save,且會跳出 error message 顯示 "filename should be unique" ==[之後一併改]== - [x] 與 widget 接合,可從 DocuSky 載入文庫文件 - [ ] ~~權限辨別 owner/others: Framework config 檔設定方式 study~~ - [x] [Port 管理群組安排](#Port-管理群組安排) - [x] [Backend Server 權限控管](#Backend-Server-權限控管) * 建立 token 認證協作文件的流程 - [ ] ~~上傳下載 local 端文件編輯功能~~ * next week: 與一梅學姊討論研討會協作編輯使用情境 ### 2019/03/12 * crossbar 協作筆記雛形 * [安裝 crossbar 套件](#Crossbar-安裝) * 角色設定與安排(傳輸方式) * 目前遇到狀況:pyro4 server 沒有能使用 web socket 與 web browser 相連接的 js library,僅提供 .NET 和 java 的 * 自己寫連接的 js library * 將 Pyro4 替換成其他可以的 websocket 套件(e.g. Crossbar..),程式重寫 :::info **[解決方向1]直接在原程式加入 Tornado Web Server** * [tornadoweb/tornado](https://github.com/tornadoweb/tornado) ``` C:\Users\RCDH\PycharmProjects\DocuPad>pip install tornado Collecting tornado Downloading https://files.pythonhosted.org/packages/d4/1b/191715afe5a4fbcb285e3292dfbe21f449f05b1edd85abc8c671bde5e9b1/tornado-5.1.1-cp37-cp37m-win32.whl (454kB) 100% |████████████████████████████████| 460kB 2.2MB/s Installing collected packages: tornado Successfully installed tornado-5.1.1 ``` * (concern) 這樣等於是用 http protocal 在做網頁的連接,與原先要求的使用 websocket 不同 <br> **[解決方向2] 參考 chatbot 範例實作方式** * 找到有寫 js library 的 chatbot 範例 * [arild/websocket_chat_server](https://github.com/arild/websocket_chat_server) * 應能解決 Pyro4 與 browser 連接那層不知道怎麼寫的問題 <br> **[解決方向3] 改用 crossbar 實作** ::: ### 2019/02/25 * [安裝 wxPython](#安裝-wxPython) * 依照 pypad 刻出 `client.py` `server.py` 架構 * [Pypad](https://github.com/stevenqzhang/PyPad) * 測試註冊功能正常 ### 2019/02/18 * 初步擬定架構 ![](https://i.imgur.com/3nYu3PO.png) * [Pyro4 tutorial & 修改](#Pyro4-tutorial-amp-修改) * meeting note :::info 可以不用 update queue server(pyro4) 怎麼得到最新狀態 - [x] client 透過 server 去拿 db 文件 - [x] 以一個client做master 第一個人上載 一點點不一致可以接受 doc_content 小心 tag 先識別到底是不是在編同一份文件 signature md file hashing function => 先把整份塞給大家 怎樣確認說亂掉之後 還可以回來 client 計算 signature 的能力 先假設 tag 都還在 xml 的那種環境 doc_content 的東西全顯示 pyro server 獨立出來 打好了之後再save?! client 決定要 update 時, 才跟 docusky 連 與docusky獨立 widget 和 pyro4 權限?! ::: ### 2019/01/28 * [安裝 python-socket.io](#安裝-python-socketio) * socket.io 教學 * [python-socketio](https://python-socketio.readthedocs.io/en/latest/intro.html) * [socketio/socket.io](https://github.com/socketio/socket.io) (written in js) * 參考 python collaborative editing * [ether/etherpad-lite](https://github.com/ether/etherpad-lite)(still written in js) * [stevenqzhang/PyPad](https://github.com/stevenqzhang/PyPad)(python) * other implementation for reference... * [stevenqzhang/PyPad](https://github.com/stevenqzhang/PyPad) 參考與實作 ([Detail](#stevenqzhangPyPad-參考與實作)) * 權限設計初步構想 ![](https://i.imgur.com/b3xv66r.jpg) * 問題釐清: 1. document_ID (or 文件本身) 在 owener 創建時,就以 “copy/丟出來共享” 的型式吐出?(或是 call on demend 的型式? 需要 owner 密碼?) 2. .json file/document 以何種型式儲存?儲存在哪? 3. 當 owner 將其他人加入 group 時需通知? or 待開啟協作筆記時直接出現? 4. 目前 docusky 的使用者階層均平行如何實踐 different level authorization? * 目前權限規劃: * owner 有刪除筆記&移除群組之權限 * group 僅有讀&編輯權限 * 任何人都有刪除其他群組成員的編輯內容的權限 ### 2019/01/14.21 * [開發前 Survey](#Survey) ### 2019/01/07 * Docusky 後續工具開發會議 ### 2019/01/02 * Docusky 後續網站修改安排會議 ## 開發筆記 ### Survey #### 背景知識 * [websocket 運作模式](http://www.cnblogs.com/lizhenghn/p/5155933.html) * [Example using C++/PHP/Python](https://github.com/lizhenghn123/zl_websocket) * [Real time collaborative editing - how does it work?](https://stackoverflow.com/questions/5086699/real-time-collaborative-editing-how-does-it-work) #### Resource * [Pusher-TextSync](https://pusher.com/textsync?doc=quxkz) * [pusher/textsync-server-node-example](https://github.com/pusher/textsync-server-node-example) * [https://github.com/pusher/textsync-server-node](https://github.com/pusher/textsync-server-node) * [Pushfyi Websocket Server](https://pushfyi.com/use-cases/real-time-collaboration/) * [Socket.io + Node.js](https://medium.com/front-end-weekly/build-a-collaborative-rich-text-editor-with-node-js-and-socket-io-38ee25b6e315) * [jalenjackson/realtime-froala-editor](https://github.com/jalenjackson/realtime-froala-editor) * [Redis + Node.js](http://www.laktek.com/2010/05/25/real-time-collaborative-editing-with-websockets-node-js-redis/) * Full project: [laktek/realie](https://github.com/laktek/realie) * [google/diff-match-patch](https://github.com/google/diff-match-patch) * Web Workers API in HTML5 * [ThisIsMissEm/node-websocket-server](https://github.com/ThisIsMissEm/node-websocket-server) * [redis.io](https://redis.io/): fast in-memory data access * [fictorial/redis-node-client](https://github.com/fictorial/redis-node-client) * [lambsteak/collab-ide](https://github.com/lambsteak/collab-ide) #### 基本流程 & authorization issues * In case if you wonder, this is how the real-time collaboration is done: 1. when one user makes a change; a diff will be created for his change and sent to server. 2. Then the server posts this diff to other connected collaborators of the pad. 3. When a user receives a diff, his content will be patched with the update. * backend: 1. HTTPS request 2. web socket request(node.js) * Mainly following messages needs to be sent: * When a user joins a pad * When a user leaves a pad * When a user sends a diff * When a user sends a chat message??? ### 安裝 python-socket.io #### python-socket.io ``` C:\Users\RCDH\PycharmProjects\webSocket>pip3 install C:\Users\RCDH\Downloads\python_socketio-3.1.1-py2.py3-none-any.whl Processing c:\users\rcdh\downloads\python_socketio-3.1.1-py2.py3-none-any.whl Collecting python-engineio>=3.2.0 (from python-socketio==3.1.1) Downloading https://files.pythonhosted.org/packages/60/f9/9a53733a18c34ed0f279654bca2de7729ba893dfb3c9ec134d7cab7cf614/python_engineio-3.2.3-py2.py3-none-any.whl (115kB) 100% |████████████████████████████████| 122kB 1.3MB/s Requirement already satisfied: six>=1.9.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from python-socketio==3.1.1) (1.12.0) Installing collected packages: python-engineio, python-socketio Successfully installed python-engineio-3.2.3 python-socketio-3.1.1 ``` #### urllib3 ``` C:\Users\RCDH\PycharmProjects\webSocket>pip3 install urllib3 Collecting urllib3 Downloading https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl (118kB) 100% |████████████████████████████████| 122kB 865kB/s Installing collected packages: urllib3 Successfully installed urllib3-1.24.1 ``` #### eventlet ``` C:\Users\RCDH\PycharmProjects\webSocket>pip3 install eventlet Collecting eventlet Downloading https://files.pythonhosted.org/packages/86/7e/96e1412f96eeb2f2eca9342dcc4d5bc9305880a448b603b0a8e54439b71c/eventlet-0.24.1-py2.py3-none-any.whl (219kB) 100% |████████████████████████████████| 225kB 2.1MB/s Collecting monotonic>=1.4 (from eventlet) Downloading https://files.pythonhosted.org/packages/ac/aa/063eca6a416f397bd99552c534c6d11d57f58f2e94c14780f3bbf818c4cf/monotonic-1.5-py2.py3-none-any.whl Requirement already satisfied: six>=1.10.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from eventlet) (1.12.0) Collecting greenlet>=0.3 (from eventlet) Downloading https://files.pythonhosted.org/packages/dc/b5/e5cef57068eb9916d3f3d3117ce4349409742f25323b4671531183c5a1c5/greenlet-0.4.15-cp37-cp37m-win32.whl Collecting dnspython>=1.15.0 (from eventlet) Downloading https://files.pythonhosted.org/packages/ec/d3/3aa0e7213ef72b8585747aa0e271a9523e713813b9a20177ebe1e939deb0/dnspython-1.16.0-py2.py3-none-any.whl (188kB) 100% |████████████████████████████████| 194kB 2.1MB/s Installing collected packages: monotonic, greenlet, dnspython, eventlet Successfully installed dnspython-1.16.0 eventlet-0.24.1 greenlet-0.4.15 monotonic-1.5 ``` ### stevenqzhang/PyPad 參考與實作 `ReomoteObject.py` #### 安裝 [Pyro](https://pyro4.readthedocs.io/en/stable/): distributed object middleware for Python (RPC) :::info RPC is the protocol. The socket provides access to the transport to implement that protocol. RPC is the service and protocol offered by the operating system to allow code to be triggered for running by a remote application. It has a defined protocol by which procedures or objects can be accessed by another device over a network. An implementation of RPC can be done over basically any network transport (e.g. TCP, UDP, cups with strings). The socket is just a programming abstraction such that the application can send and receive data with another device through a particular network transport. You implement protocols (such as RPC) on top of a transport (such as TCP) with a socket. ::: #### 安裝最新的 Pyro4 ``` C:\Users\RCDH\PycharmProjects\DocuPad>pip3 install Pyro4 Collecting Pyro4 Downloading https://files.pythonhosted.org/packages/15/93/219968d8bdc3eab73b8971b155b2006e11cf1e0b284d2e81611da8c3e7ca/Pyro4-4.75-py2.py3-none-any.whl (89kB) 100% |████████████████████████████████| 92kB 983kB/s Collecting serpent>=1.27 (from Pyro4) Downloading https://files.pythonhosted.org/packages/55/9f/8e6b4519af9eabde9fa29e6853b865e07d89e220035f34cca914507e17e7/serpent-1.27-py2.py3-none-any.whl Installing collected packages: serpent, Pyro4 Successfully installed Pyro4-4.75 serpent-1.27 ``` ### Pyro4 tutorial & 修改 #### 1. start a name server ``` C:\Users\RCDH\PycharmProjects\DocuPad>python -m Pyro4.naming Not starting broadcast server for localhost. NS running on localhost:9090 (127.0.0.1) Warning: HMAC key not set. Anyone can connect to this server! URI = PYRO:Pyro.NameServer@localhost:9090 ``` #### 2. interact with name server(name server control tool) ``` C:\Users\RCDH\PycharmProjects\DocuPad>python -m Pyro4.nsc list --------START LIST Pyro.NameServer --> PYRO:Pyro.NameServer@localhost:9090 metadata: ['class:Pyro4.naming.NameServer'] --------END LIST ``` `Pyro.NameServer` is registered to point to the URI #### 3. example - warehouse (`warehouse.py` 改為 Proxy) * `@Pyro4.expose`: tell Pyro it is allowed to access the class remotely. * `@Pyro4.behavior(instance_mode="single")`: it is required to properly have a persistent warehouse inventory. ```python= def main(): Pyro4.Daemon.serveSimple( { Warehouse: "example.warehouse" }, ns = False) if __name__=="__main__": main() ``` * 改好程式後,把 `warehouse.py` run 起來 ``` $ python warehouse.py Object <__main__.Warehouse object at 0x025F4FF0>: uri = PYRO:example.warehouse@localhost:51279 Pyro daemon running. ``` * `visit.py` 中,意即原本的 `warehouse = Warehouse()` 相當於: ``` # the location of the warehouse program 通常會讓人輸入剛剛得到的那個 uri uri="PYRO:example.warehouse@localhost:51279" warehouse = Pyro4.Proxy(uri) ``` * * (warehouse 現在是一個 proxy) * proxy? pyro object? pyro daemon(server)? * 改為最終 pyro 程式 * 上述缺點: 需每次重新加入URI => 加入 name server 來有效管理 * `warehouse.py` ```python= def main(): Pyro4.Daemon.serveSimple( { Warehouse: "example.warehouse" }, ns = True) # tell Pyro to use a name server to register the objects in if __name__=="__main__": main() ``` :::info [To start a name server] The `Pyro4.Daemon.serveSimple` is a very easy way to start a Pyro server but it provides very little control. [Oneliner Pyro object publishing: serveSimple()](https://pyro4.readthedocs.io/en/stable/servercode.html#server-servesimple) ::: * `visit.py` * 現在起,可以透過 name server 去 locate `warehouse.py` 的 URI (` warehouse = Pyro4.Proxy("PYRONAME:example.warehouse")`) * `sys.excepthook = Pyro4.util.excepthook`: install the `Pyro4.util.excepthook` as excepthook. You’ll soon see what this does to the exceptions and stack traces your program produces when something goes wrong with a Pyro object. * 測試 * run the name server ``` C:\Users\RCDH\Pyro4\examples\warehouse>python -m Pyro4.naming Not starting broadcast server for localhost. NS running on localhost:9090 (127.0.0.1) Warning: HMAC key not set. Anyone can connect to this server! URI = PYRO:Pyro.NameServer@localhost:9090 ``` * run `warehouse.py` ``` C:\Users\RCDH\Pyro4\examples\warehouse\phase3>python warehouse.py Object <class '__main__.Warehouse'>: uri = PYRO:obj_f8638adcb1024850a0a1f5d93c0f2a6e@localhost:60186 name = example.warehouse Pyro daemon running. ``` #### 4. stockmarket * `@property`: to access the name and symbols attributes of the class you have to turn them into real Python properties. * `stockmarket.py` ```python= nasdaq = StockMarket("NASDAQ", ["AAPL", "CSCO", "MSFT", "GOOG"]) newyork = StockMarket("NYSE", ["IBM", "HPQ", "BP"]) # for example purposes we will access the daemon and name server ourselves and not use serveSimple with Pyro4.Daemon() as daemon: nasdaq_uri = daemon.register(nasdaq) newyork_uri = daemon.register(newyork) with Pyro4.locateNS() as ns: ns.register("example.stockmarket.nasdaq", nasdaq_uri) ns.register("example.stockmarket.newyork", newyork_uri) print("Stockmarkets available.") daemon.requestLoop() ``` * `viewer.py` ```python= def find_stockmarkets(): # You can hardcode the stockmarket names for nasdaq and newyork, but it # is more flexible if we just look for every available stockmarket. markets = [] with Pyro4.locateNS() as ns: for market, market_uri in ns.list(prefix="example.stockmarket.").items(): print("found market", market) markets.append(Pyro4.Proxy(market_uri)) if not markets: raise ValueError("no markets found! (have you started the stock markets first?)") return markets ``` * run on different machine * start the name server in such a way that it is accessible from other machines: ` python -m Pyro4.naming -n your_hostname # i.e. your_hostname = “192.168.1.99”` or `pyro4-ns -n your_hostname` * 或者直接在 code 當中設定 ```python= Pyro4.Daemon.serveSimple( { Warehouse: "example.warehouse" }, host = 'your_hostname_here', ns = True) ``` * 或是直接在 create daemon 時設定 ```python with Pyro4.Daemon(host=HOST_IP, port=HOST_PORT) as daemon: ``` * To run the final stock quote system you need to do the following: * open a new console window and start the Pyro name server (`python -m Pyro4.naming`, or simply: `pyro4-ns`). * open another console window and start the stock market server * open another console window and start the viewer ### 安裝 wxPython ``` C:\Users\RCDH\PycharmProjects\DocuPad>pip install -U wxPython Collecting wxPython Downloading https://files.pythonhosted.org/packages/5b/1c/f1b46a9c79c572ab35276d6f07023a2794cc5b76a38723332ec653d365ff/wxPython-4.0.4-cp37-cp37m-win32.whl (14.0MB) 100% |████████████████████████████████| 14.0MB 2.2MB/s Collecting Pillow (from wxPython) Downloading https://files.pythonhosted.org/packages/d7/ea/46fd5bd57c5df5a2e79e508294acec4be0fcc2fb3ce95c2cf1038ebaa533/Pillow-5.4.1-cp37-cp37m-win32.whl (1.7MB) 100% |████████████████████████████████| 1.7MB 4.7MB/s Requirement already satisfied, skipping upgrade: six in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from wxPython) (1.12.0) Installing collected packages: Pillow, wxPython Successfully installed Pillow-5.4.1 wxPython-4.0.4 ``` ``` C:\Users\RCDH\PycharmProjects\DocuPad>python -m Pyro4.nsc list --------START LIST Pyro.NameServer --> PYRO:Pyro.NameServer@localhost:9090 metadata: ['class:Pyro4.naming.NameServer'] example.docupadclient.docupadserver_client_156 --> PYRO:obj_7b9ae9a16d4e490ea4567c0ae6d8e972@localhost:59551 example.docupadserver --> PYRO:obj_e67b4ff5d29842fc93ae2294f5a342b0@localhost:59546 --------END LIST ``` ### [Crossbar 安裝](https://crossbar.io/docs/Installation-on-Windows/) #### crossbar 以前開發筆記 for reference * [crossbar.io](https://crossbar.io/) * [carolc0708/pest_detection](https://github.com/carolc0708/pest_detection) * [170706 meeting](/H4y5XD-rThKQk9NdvKOmLg) * [170713 meeting](/gvJPJ_tRThyPhmFsGerCGg) * [170720 meeting](/5R9VJsGHR-CU-z5nDyX6Zg) * [170727 meeting](/NDuUydg0R1izXMfu2_fMYg) * [170803 meeting](/kM5WAyMZQcKM-WACqi1tvg) * [170810 meeting](/aKrtvmIxT4ynSzh6acpswQ) #### 安裝紀錄 * `pip install crossbar` 出現以下錯誤 * ~~需下載 [Microsoft Visual C++ Compiler for Python 2.7](https://www.microsoft.com/en-us/download/details.aspx?id=44266) (documentation)~~ ``` running build_ext building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/ ---------------------------------------- Command "c:\users\rcdh\appdata\local\programs\python\python37-32\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\RCDH\\AppData\\Local\\T emp\\pip-install-kjrujcwi\\twisted\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\RCDH\AppData\Local\Temp\pip-record-zo0jqkgw\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\RCDH\AppData\Local\Temp\pip-install-kjrujcwi\twisted\ ``` * 下載 [Visual C++ Build Tools](https://visualstudio.microsoft.com/zh-hant/visual-cpp-build-tools/?rr=https%3A%2F%2Fgithub.com%2Fbenfred%2Fimplicit%2Fissues%2F76) ``` C:\Users\RCDH\PycharmProjects\DocuPad>pip install crossbar Collecting crossbar Using cached https://files.pythonhosted.org/packages/65/74/a879b9e79d240661723db54fc07afd7890cd4386fca7437743dbd5fef6ae/crossbar-19.2.1-py2.py3-none-any.whl Collecting h2<4.0,>=3.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/a6/b2/0348a08cce9980b15ef8607adc7f0534193fe25b9269daa0c327dc74f026/h2-3.1.0-py2.py3-none-any.whl Collecting pyasn1-modules>=0.0.9 (from crossbar) Using cached https://files.pythonhosted.org/packages/da/98/8ddd9fa4d84065926832bcf2255a2b69f1d03330aa4d1c49cc7317ac888e/pyasn1_modules-0.2.4-py2.py3-none-any.whl Collecting mistune>=0.7.4 (from crossbar) Using cached https://files.pythonhosted.org/packages/09/ec/4b43dae793655b7d8a25f76119624350b4d65eb663459eb9603d7f1f0345/mistune-0.8.4-py2.py3-none-any.whl Collecting psutil>=5.2.2 (from crossbar) Using cached https://files.pythonhosted.org/packages/00/e6/561fed27453add44af41a52e13e1dfca4d1e35705d698769edea6292339a/psutil-5.5.1-cp37-cp37m-win32.whl Collecting pyasn1>=0.2.3 (from crossbar) Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl Requirement already satisfied: setuptools>=36.0.1 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (40.6.3) Collecting cbor>=1.0.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/9b/99/01c6a987c920500189eb74a291bd3a388e6c7cf85736bb6b066d9833315e/cbor-1.0.0.tar.gz Requirement already satisfied: attrs>=17.2.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (19.1.0) Collecting pyopenssl>=17.1.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/01/c8/ceb170d81bd3941cbeb9940fc6cc2ef2ca4288d0ca8929ea4db5905d904d/pyOpenSSL-19.0.0-py2.py3-none-any.whl Collecting txaio>=18.8.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/e9/6d/e1a6f7835cde86728e5bb1f577be9b2d7d273fdb33c286e70b087d418ded/txaio-18.8.1-py2.py3-none-any.whl Collecting setproctitle>=1.1.10 (from crossbar) Using cached https://files.pythonhosted.org/packages/5a/0d/dc0d2234aacba6cf1a729964383e3452c52096dc695581248b548786f2b3/setproctitle-1.1.10.tar.gz Requirement already satisfied: constantly>=15.1.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (15.1.0) Collecting priority>=1.3.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/de/96/2f4b8da7be255cd41e825c398efd11a6706ff86e66ae198f012204aa2a4f/priority-1.3.0-py2.py3-none-any.whl Collecting jinja2>=2.9.6 (from crossbar) Using cached https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl Collecting u-msgpack-python>=2.4.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/fa/41/4b831124d203fbb1be8e1b37f77ace336d9bb5661872885fa94ca98ebf06/u_msgpack_python-2.5.0-py2.py3-none-any.whl Collecting netaddr>=0.7.19 (from crossbar) Using cached https://files.pythonhosted.org/packages/ba/97/ce14451a9fd7bdb5a397abf99b24a1a6bb7a1a440b019bebd2e9a0dbec74/netaddr-0.7.19-py2.py3-none-any.whl Collecting service-identity>=17.0.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/e9/7c/2195b890023e098f9618d43ebc337d83c8b38d414326685339eb024db2f6/service_identity-18.1.0-py2.py3-none-any.whl Requirement already satisfied: idna<2.6,>=2.5 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (2.5) Collecting pyqrcode>=1.2.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/37/61/f07226075c347897937d4086ef8e55f0a62ae535e28069884ac68d979316/PyQRCode-1.2.1.tar.gz Requirement already satisfied: pygments>=2.2.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (2.3.1) Collecting passlib>=1.7.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/ee/a7/d6d238d927df355d4e4e000670342ca4705a72f0bf694027cf67d9bcf5af/passlib-1.7.1-py2.py3-none-any.whl Collecting pytrie>=0.3 (from crossbar) Using cached https://files.pythonhosted.org/packages/e1/eb/ae1f098969c9e9b81e821fb8e916cbf720b900ec1c0f3359e47a427395ec/PyTrie-0.3.1.tar.gz Requirement already satisfied: bitstring>=3.1.5 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (3.1.5) Collecting treq>=17.3.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/77/20/a938853f08d1b2ecb0bc161add2b41173d18a8f1756b3c3236e920a3e200/treq-18.6.0-py2.py3-none-any.whl Collecting lmdb>=0.92 (from crossbar) Using cached https://files.pythonhosted.org/packages/cb/31/5be8f436b56733d9e69c721c358502f4d77b627489a459978686be7db65f/lmdb-0.94.tar.gz Requirement already satisfied: incremental>=17.5.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (17.5.0) Collecting py-ubjson>=0.9.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/68/9c/a6c34e565351f0b04bcf6835e38bc4bd0647269dc48670e12eb99a3f5ef5/py-ubjson-0.12.0.tar.gz Collecting twisted>=18.9.0 (from crossbar) Using cached https://files.pythonhosted.org/packages/5d/0e/a72d85a55761c2c3ff1cb968143a2fd5f360220779ed90e0fadf4106d4f2/Twisted-18.9.0.tar.bz2 Requirement already satisfied: zope.interface>=4.4.2 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (4.6.0) Requirement already satisfied: pyyaml>=4.2b4 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (5.1b3) Requirement already satisfied: watchdog>=0.8.3 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (0.9.0) Collecting click>=6.7 (from crossbar) Using cached https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl Collecting cryptography>=1.9 (from crossbar) Using cached https://files.pythonhosted.org/packages/af/38/b53b461982d4c9fd9693beb7b6c6d77edd4fe7ceac7822aeb2a5754ccb15/cryptography-2.6.1-cp37-cp37m-win32.whl Collecting txtorcon>=0.19.3 (from crossbar) Using cached https://files.pythonhosted.org/packages/a2/88/f8b7f4ac3c82864e8b992a33a58cb40d7154c606e7b1e909a8de73dce780/txtorcon-19.0.0-py2.py3-none-any.whl Requirement already satisfied: pynacl>=1.1.2 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from crossbar) (1.3.0) Collecting autobahn>=19.2.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/d5/5d/49152a3ce88ad8f985a4f82ff9633a29f3ef2da050ae8aba8075142f5a61/autobahn-19.2.1-py2.py3-none-any.whl Collecting sdnotify>=0.3.1 (from crossbar) Using cached https://files.pythonhosted.org/packages/ce/d8/9fdc36b2a912bf78106de4b3f0de3891ff8f369e7a6f80be842b8b0b6bd5/sdnotify-0.3.2.tar.gz Collecting hpack<4,>=2.3 (from h2<4.0,>=3.0->crossbar) Using cached https://files.pythonhosted.org/packages/8a/cc/e53517f4a1e13f74776ca93271caef378dadec14d71c61c949d759d3db69/hpack-3.0.0-py2.py3-none-any.whl Collecting hyperframe<6,>=5.2.0 (from h2<4.0,>=3.0->crossbar) Using cached https://files.pythonhosted.org/packages/19/0c/bf88182bcb5dce3094e2f3e4fe20db28a9928cb7bd5b08024030e4b140db/hyperframe-5.2.0-py2.py3-none-any.whl Requirement already satisfied: six>=1.5.2 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from pyopenssl>=17.1.0->crossbar) (1.12.0) Collecting MarkupSafe>=0.23 (from jinja2>=2.9.6->crossbar) Using cached https://files.pythonhosted.org/packages/5b/d4/1deb3c5dc3714fb160c7e2116fc6dff36a063d9156a9328cce54ef35cc52/MarkupSafe-1.1.1-cp37-cp37m-win32.whl Collecting sortedcontainers (from pytrie>=0.3->crossbar) Using cached https://files.pythonhosted.org/packages/13/f3/cf85f7c3a2dbd1a515d51e1f1676d971abe41bba6f4ab5443240d9a78e5b/sortedcontainers-2.1.0-py2.py3-none-any.whl Requirement already satisfied: requests>=2.1.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from treq>=17.3.1->crossbar) (2.21.0) Requirement already satisfied: Automat>=0.3.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from twisted>=18.9.0->crossbar) (0.7.0) Requirement already satisfied: hyperlink>=17.1.1 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from twisted>=18.9.0->crossbar) (18.0.0) Requirement already satisfied: PyHamcrest>=1.9.0 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from twisted>=18.9.0->crossbar) (1.9.0) Requirement already satisfied: argh>=0.24.1 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from watchdog>=0.8.3->crossbar) (0.26.2) Requirement already satisfied: pathtools>=0.1.1 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from watchdog>=0.8.3->crossbar) (0.1.2) Requirement already satisfied: cffi!=1.11.3,>=1.8 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from cryptography>=1.9->crossbar) (1.12.2) Collecting asn1crypto>=0.21.0 (from cryptography>=1.9->crossbar) Using cached https://files.pythonhosted.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from requests>=2.1.0->treq>=17.3.1->crossbar) (3.0.4) Requirement already satisfied: certifi>=2017.4.17 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from requests>=2.1.0->treq>=17.3.1->crossbar) (2018.11.29) Requirement already satisfied: urllib3<1.25,>=1.21.1 in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from requests>=2.1.0->treq>=17.3.1->crossbar) (1.24.1) Requirement already satisfied: pycparser in c:\users\rcdh\appdata\local\programs\python\python37-32\lib\site-packages (from cffi!=1.11.3,>=1.8->cryptography>=1.9->crossbar) (2.19) Installing collected packages: hpack, hyperframe, h2, pyasn1, pyasn1-modules, mistune, psutil, cbor, asn1crypto, cryptography, pyopenssl, txaio, setproctitle, priority, MarkupSafe, jinja2, u-msgpack-python, netaddr, service-identity, p yqrcode, passlib, sortedcontainers, pytrie, twisted, treq, lmdb, py-ubjson, click, txtorcon, autobahn, sdnotify, crossbar Running setup.py install for cbor ... done Running setup.py install for setproctitle ... done Running setup.py install for pyqrcode ... done Running setup.py install for pytrie ... done Running setup.py install for twisted ... done Running setup.py install for lmdb ... done Running setup.py install for py-ubjson ... done Running setup.py install for sdnotify ... done Successfully installed MarkupSafe-1.1.1 asn1crypto-0.24.0 autobahn-19.2.1 cbor-1.0.0 click-7.0 crossbar-19.2.1 cryptography-2.6.1 h2-3.1.0 hpack-3.0.0 hyperframe-5.2.0 jinja2-2.10 lmdb-0.94 mistune-0.8.4 netaddr-0.7.19 passlib-1.7.1 pr iority-1.3.0 psutil-5.5.1 py-ubjson-0.12.0 pyasn1-0.4.5 pyasn1-modules-0.2.4 pyopenssl-19.0.0 pyqrcode-1.2.1 pytrie-0.3.1 sdnotify-0.3.2 service-identity-18.1.0 setproctitle-1.1.10 sortedcontainers-2.1.0 treq-18.6.0 twisted-18.9.0 txai o-18.8.1 txtorcon-19.0.0 u-msgpack-python-2.5.0 ``` * 下載 win32api ``` C:\Users\RCDH\PycharmProjects\DocuPad>pip install pypiwin32 Collecting pypiwin32 Downloading https://files.pythonhosted.org/packages/d0/1b/2f292bbd742e369a100c91faa0483172cd91a1a422a6692055ac920946c5/pypiwin32-223-py3-none-any.whl Collecting pywin32>=223 (from pypiwin32) Downloading https://files.pythonhosted.org/packages/8a/37/917c4020e93e0e854d4cbff1cbdf14ec45a6d1cedf52f8cafdea5b22451a/pywin32-224-cp37-cp37m-win32.whl (8.3MB) 100% |████████████████████████████████| 8.3MB 1.8MB/s Installing collected packages: pywin32, pypiwin32 Successfully installed pypiwin32-223 pywin32-224 ``` * 出現以下錯誤 * 解法:下載`python-snappy.whl`並安裝(直接用pip也會出現相同error) * 下載位置:https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-snappy * (Windows 64-bits, python 3.7) `python_snappy-0.5.4-cp37-cp37m-win32.whl` * `pip install python_snappy-0.5.4-cp37-cp37m-win32.whl` ```Unix ERROR: Complete output from command 'c:\users\admin\appdata\local\programs\python\python37-32\python.exe' -u -c 'import setuptools, tokenize;__file__='"'"'C:\\Users\\admin\\AppData\\Local\ \Temp\\pip-install-h6na8uee\\python-snappy\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, _ _file__, '"'"'exec'"'"'))' install --record 'C:\Users\admin\AppData\Local\Temp\pip-record-_i28yyn7\install-record.txt' --single-version-externally-managed --compile: ERROR: running install running build running build_py creating build creating build\lib.win32-3.7 creating build\lib.win32-3.7\snappy copying snappy\hadoop_snappy.py -> build\lib.win32-3.7\snappy copying snappy\snappy.py -> build\lib.win32-3.7\snappy copying snappy\snappy_cffi.py -> build\lib.win32-3.7\snappy copying snappy\snappy_cffi_builder.py -> build\lib.win32-3.7\snappy copying snappy\snappy_formats.py -> build\lib.win32-3.7\snappy copying snappy\__init__.py -> build\lib.win32-3.7\snappy copying snappy\__main__.py -> build\lib.win32-3.7\snappy running build_ext building 'snappy._snappy' extension creating build\temp.win32-3.7 creating build\temp.win32-3.7\Release creating build\temp.win32-3.7\Release\snappy C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\bin\HostX86\x86\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT -Ic:\users\admin\appdata\local\programs\p ython\python37-32\include -Ic:\users\admin\appdata\local\programs\python\python37-32\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\ATLMFC\i nclude" "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt" "-IC:\Program F iles (x86)\Windows Kits\10\include\10.0.17763.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt" /EHsc /Tpsnappy/snappymodule.cc /Fobuild\temp.win32-3.7\Release\snappy/snappymodule.obj snappymodule.cc snappy/snappymodule.cc(31): fatal error C1083: 無法開啟包含檔案: 'snappy-c.h': No such file or directory error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.21.27702\\bin\\HostX86\\x86\\cl.exe' failed with exit status 2 ---------------------------------------- ERROR: Command "'c:\users\admin\appdata\local\programs\python\python37-32\python.exe' -u -c 'import setuptools, tokenize;__file__='"'"'C:\\Users\\admin\\AppData\\Local\\Temp\\pip-install-h6na8 uee\\python-snappy\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"') )' install --record 'C:\Users\admin\AppData\Local\Temp\pip-record-_i28yyn7\install-record.txt' --single-version-externally-managed --compile" failed with error code 1 in C:\Users\admin\AppData \Local\Temp\pip-install-h6na8uee\python-snappy\ ``` * 測試是否安裝成功與版本 ``` C:\Users\RCDH\PycharmProjects\DocuPad>crossbar version ::::::::::::::::: ::::: _____ __ ::::: : ::::: / ___/____ ___ ___ ___ / / ___ _ ____ ::::::: ::::::: / /__ / __// _ \ (_-< (_-< / _ \/ _ `// __/ ::::: : ::::: \___//_/ \___//___//___//_.__/\_,_//_/ ::::: ::::::::::::::::: Crossbar v19.2.1 Copyright (c) 2013-2019 Crossbar.io Technologies GmbH, licensed under AGPL 3.0. Crossbar.io : 19.2.1 txaio : 18.8.1 Autobahn : 19.2.1 Twisted : 18.9.0-IOCPReactor LMDB : 0.94/lmdb-0.9.22 Python : 3.7.1/CPython Frozen executable : no Operating system : Windows-10-10.0.17763-SP0 Host machine : AMD64 Release key : RWR2yD4qEkDnHAOwcTx6qTqaTT55n+J5pWez5jXUFT89fwlfVO77nFaV ``` * (另一台電腦) ``` F:\DocuPad>crossbar version ::::::::::::::::: ::::: _____ __ ::::: : ::::: / ___/____ ___ ___ ___ / / ___ _ ____ ::::::: ::::::: / /__ / __// _ \ (_-< (_-< / _ \/ _ `// __/ ::::: : ::::: \___//_/ \___//___//___//_.__/\_,_//_/ ::::: ::::::::::::::::: Crossbar v19.2.1 Copyright (c) 2013-2019 Crossbar.io Technologies GmbH, licensed under AGPL 3.0. Crossbar.io : 19.2.1 txaio : 18.8.1 Autobahn : 19.2.1 Twisted : 18.9.0-IOCPReactor LMDB : 0.94/lmdb-0.9.22 Python : 3.6.5/CPython Frozen executable : no Operating system : Windows-10-10.0.17134-SP0 Host machine : AMD64 Release key : RWR2yD4qEkDnHAOwcTx6qTqaTT55n+J5pWez5jXUFT89fwlfVO77nFaV ``` * MAC OS 不好灌(需再研究看看) ### Port 管理群組安排 * 問題: 當多人同時使用協作筆記工具,編輯不同分文件時,port 如何管理與配給? * 方法1: 實作如chatbox範例(arild/websocket_chat_server)的load_balancer(),動態配給port給新進之使用者 * 杜博士建議: **<span style="color:RED">listening port 應只有一個</span>** * 方法2: 對使用者協作事件進行群組控管 * 於何處紀錄不同文件的使用者權限列表? (DocuXML 新增欄位? Local 端建置 buffer/DB?) * 以何種方式記錄文件的編輯權限? (參照linux權限設定方式? 自己定義?) * 問題: (先不考慮除了編輯以外的行為權限),誰來記錄不同文件開放給不同使用者的編輯的權限? * 文件本身? DocuXML新增欄位紀錄協作當中的編輯權限? * 杜博士建議不這樣做,因為其他使用者可直接透過編輯 .xml 檔案修改權限,除非額外設計加密程序 * 在 Local 端建置 DB 管理? 須寫死maximum參數? 額外的DB管理成本? * **<span style="color:RED">管理此權限的server暫時不需跟 docusky server 溝通</span>** * ~~DocuXML新增欄位紀錄權限metadata~~ * 何時新增? 第一次開啟時如何處之? 被指派權限但尚未開啟時如何知道自己有權限? * 修改權限時,未上線的使用者如何得知? * 如何分辨使用者在docusky上的身分?(和後續與docusky接合載入個人文庫功能有關) * 問題: (考慮除了編輯以外的行為權限),有哪些權限與該如何記錄? * 參考 linux: 分為 owner/group/others 與 read/write/execute (用三個數字紀錄之) * 自行界定? ### Backend Server 權限控管 在 backend server 進行權限控管 :::info * 處理情境: 1. user1 透過 widget 從 Docusky 取得文件 d 2. user1 在 backend server 上註冊,並將文件 d 的內容(完整內容或至少 hash signature) 傳給 backend server 3. user2 也透過 widget 取得文件 d 4. user2 在 backend server 上註冊,並將文件 d 的內容(完整內容或至少 hash signature) 傳給 backend server 5. 兩者對文件進行編輯,而 d 可利用 **owner+資料庫+文獻集+檔名** 來辨識,若 backend server 比對兩內容的 signature 發現有異,代表 user2 取得的內容已經和 user1 不同 6. 若 user2 從 docusky 取得的 d 內容和 backend server 保留的最新值不同,user2 須從 backend server 取得最新的 d 內容 7. 若 user3 加入,情況也類似 8. 若 user4 並沒有權限,因此無法從 Docusky 取得 d,但 user4 卻也透過工具連上 backend server 9. 這時 backend server 必須(例如要求 user4 提供特殊 token 之類) 拒絕 user4 ::: * 先以載入公開資料庫的情境來釐清問題 * owner ID 是以 docusky 身分或是動態配給的 node ID? * 以 docusky 身分: 限制了訪客編輯的可能性,協作共筆僅開放給 docusky 已註冊之會員 * node ID: 可供訪客編輯,但之後 backend server 在管理文件開放權限上會有問題,共同編輯行為變成一次性 * ==以 token 來識別不同的協作編輯事件(session)== * 無論是否有 docusky 帳號,無論文件是否公開,只要有 token 相當於獲得編輯邀請,可以進來編輯 * backend server 紀錄 token 和當前編輯文件的一對一 Table * 在多個共同編輯行為進行時,以 token 來區分群組,進行 real-time 的 publish/subscribe * 問題: * 何時終止這個 token & 釋放暫存資料? owner 上傳 docusky 文庫? owner 關閉協作? (因為 server 不可能無限讓它保存) :::info * 杜博士對共同編輯的想法: 1. 實現簡單情境的 co-edit 2. **<span style="color:RED">目前不打算讓使用者編輯公開資料庫</span>** 3. **<span style="color:RED">共同編輯發生在個人資料庫</span>**,因此須為此在 DocuSky 上準備基本的 access API (牽涉到 DB,杜博士還沒去實作) 4. 由於杜博士沒時間去設計實作 auth server 和對應的 api,因此上面提到的 **user4 部分需先留個(實際上還沒有作用的) token 欄位** 5. 這幾周就先在兩台電腦上用同個帳號 co-edit 某篇文件來進行開發測試 6. 杜博士會試著在這一兩個月把 "user1 允許 user2 存取某 DB/corpus A" 補上。完成後,user2 應可從 widget 取得 A 的文件(來進行共同編輯) 7. 5月底無法完成,則至少達成5. ::: * token 的產生方式(for 沒有權限的使用者) * 直接以"owner+資料庫+文獻集+檔名"這樣的字串來辨別文件d? * pros: 省空間 * cons: 易破解 * 以這串字串加密產生一串密碼? * pros: 較難破解 * cons: server 需額外程序解密取得文件 * 隨機產生一串密碼和文件紀錄在一起? * pros: 最難破解 * cons: server 儲存方式(密碼 + "owner+資料庫+文獻集+檔名" or 密碼 + 文件) * **<span style="color:RED">杜博士建議目前先隨便給個值(e.g. "Reserved"、隨便產生的亂數碼、當天日期)就好</span>** * 這個 **<span style="color:RED">後續要由 auth server 去發給</span>** * 目前為了完成兩人 co-edit 情境之下,backend server 能夠識別同一共同編輯事件,先以 `DB_TITLE` 作為 token 名稱以識別之 * 在 backend server 中以 token 識別一個協作編輯事件 * 杜博士: **backend server 中檢查 token 的程式,留一段註解提醒日後可加強** * 編輯文件的單位和層級(和 token 命名與記錄方式有關) * **一份 DocuXML 檔案** <- this * DocuXML 中的一個 xml 檔? * token 何時失效? backend 要存多久? * 目前是 set interval 隨時去檢查 connect 在 router 上的有幾個人,當人數為 0 時即釋放文件空間(& token 消失) * 協作文件 d 在 backend 的儲存方式為何? 編輯到一半要暫存在 backend? 還是直接存回 docusky? * 目前設計是以 page 的方式暫存,編輯完成後會輸出 backend 暫存內容 * 之後透過 widget 來更新 docusky 中的文件內容 (複寫) * backend 僅負責共同編輯的即時需求 * 以上是兩人編輯的情境/四人編輯的時候底下群組如何分配? * crossbar config 設定群組 * 必須每次有新群組都去重新更改 config 與重啟 router * 直接在 onXXX function 識別 token 決定要不要執行動作 * `if (kwargs.token !== docuSkyObj.db) return;` * `docuSkyObj.db` 待杜博士實作 auth server 後再改為吐回的 token attribute * 新增 backup 的 data structure * 必須進行上載(目前是輸出 `current data`) 才會將 `back data` 內容由原先 docusky 載入的原始文件內容改為 `current data` 內容 * 目的: 讓編輯者可以回復(reset)到尚未開始編輯的狀態 * 目前介面設計問題: 當載入文件頁數多時,在編輯P1的使用者,如何得知在編輯P20的使用者在做什麼改變,是否需要 alert? ## 討論 ### 2019/01/29 ==杜老大== 柔安的投影片,p2-p3 我看不懂 ==柔安== p2 主要是說我目前想的是所有使用者假設要使用協作平臺這個工具創造出來的一份筆記就會是一個.json file的形式當中記錄這份筆記的id使用者iddocument id(或是用其他型式儲存的使用者的document)再來是他的內容 p3 是說 協作平台後端會有一個 table 去記錄這些筆記id 與他的權限開給誰等等待不同使用者登入要去使用的時候根據他自己合法的權限可以看到那些它可以看的 並且去編輯 p4 是我現在大致想的介面 也是很不確定的地方就是不知道使用者想要用怎樣的方式去協作 想要編輯什麼文件 最後想要怎麼呈現覺得待這些釐清之後再下去想他背後怎麼設計 可能我也會比較清楚怎麼安排 現在先假設使用者是像word的註解方式進行筆記但不確定這跟杜博士當初想的有沒有出入(因為我從自己的角度很難想像這個上面會要編輯什麼 用什麼方式等等) ==一梅== 這部份我想像是是以現在的雲端資料庫做為共同編輯的項目,在項目中就有三個層次–資料庫、文獻集、文件,有些想法我已加在此文件的上面。 ==柔安== 一開始是有天馬行空想個可以讓使用者直接手寫(就是拿觸控筆直接在電腦螢幕或ipad上寫)主要是我參考的pypad就是有實踐這樣的功能但是這個真的是很後面的東西了光想到他的儲存形式就覺得一定很複雜 然後p4的地方可能會有點誤導但我的意思是說使用者要編輯當份文件的時候點開後系統會讓介面上顯示 那個筆記的json + 他原先編輯的document ==杜老大== 進度時程,最好先有整份(目前所設想)的規劃。例如,1月底前 survey,2月底前某某部份(功能)實作,3月底前某某其他部份,4月底前完成第一版(可測試的)prototype... 等 ==柔安== 好的 不好意思剛剛寫的有點趕 明天會補上完整的與詳細敘述。我將規劃加入新的版本了.34567月目前先空白主要希望先經過和杜博士、一梅學姊、其瑞學長討論過後確定我離開前要做好的部分跟具體做到的程度再作安排(基於我現在初步的構想下去討論)目前遇到的一些問題像是協作的使用者是要用怎樣的方式編輯 最後呈現會長什麼樣子 系統的哪些部分可以動到 哪些不能等等 都還需要詳細請教另外是個人因素可能三月開始比較能全心全力下去做因此接下來到二月底的四周 主要安排將想要參考的開源 project 基礎的三支程式重寫(投影片中有提到因為使用的套件有更新)、構通的middleware document study(有些網路的定義名詞我其實也沒有很了解 要看看example怎麼用才知道)若杜博士、一梅學姊、其瑞學長有覺得進度太慢或是任何不妥當的地方再麻煩和我說了 我再看看怎麼調整比較好~ ==一梅== 時程表其實是要提醒大家重要的時間點。妳可以用類似以下方式,先填入重要的時間點... 1. 將確定離開的時間,例如 7/31,填入 2. 以目前的經驗推估,離職前一個月就得把系統完成,因此就是 6/30 完成(包含基本測試) 3. 從現在到六月底有 5 個月(如果目前是訂在 7/1 離職,那就只有四個月),這五個月妳打算要做完哪些項目? 3.1 使用者資料庫的分享權限模型(有哪些角色、哪些分享權限等等) 3.2 使用者使用案例。例如某位研究者是 db owner,他可以開放該 db 的哪些權限(例如 read/insert/update/delete)給哪些人(透過帳號/群組?) 3.3 規劃從 db, api, 前端網頁,各需負責些什麼,才能達成 3.2 的工作。 從這些地方,可以看出至少需做什麼部件。筆記共享,只會是其中一種 use case。至少還會有「共同編輯文件」的需求。因此,需要有對應的 api,可以對應地更新資料庫內容(如果時間不夠,或許是先實作共同編輯文件)(筆記共享,是比較遠一些的應用)最好能儘早完成一個可以簡單玩玩(例如兩個人共同編輯一份簡單文件)的 prototype, 3.4 因此,若有五個月時間,希望前兩個月就能弄出一份簡單的雛型 4. 所以,三月底完成第一份 prototype。然後,要完成 prototype 需有哪些基本的 api,預計何時完成... 等等。依照目前的狀況,很可能會先採取簡單的共享模型。(因為大家在此似乎沒有足夠經驗,也沒時間 survey 出更合適的模型) 我們可以在年後再多討論,但之前妳應儘可能把問題釐清。這樣年後沒多久,就有機會進入實質的開發了。至於使用者之間的傳訊互通,雖很有趣,但或許也不是當前迫切的應用 ==柔安== 好的!我會根據杜博士給的建議在思考一下如何安排 (大概有抓到方向了)目前規劃上是以 “共同編輯” 在想架構。“筆記共享” 這個我比較不懂 我以為共同編輯就是在筆記上編輯 。所以使用者在共同編輯開放權限時 其實已經把筆記(文件)共享出去了(給其他有權限共同編輯的人)不知道這樣跟杜博士的理解有沒有什麼出入? ==杜老大== 也不算有什麼大出入,就是需釐清共同編輯的(單位)是什麼 然後,設想一下若這個單位(例如一篇文件)的資料頗大,處理的方式會是什麼 怎樣避免或處理 conflicts (例如,假如兩位使用者同時間了某個字 A,一位把它改成 B,另一位直接把 A 刪掉,系統會如何處理 不需把範圍擴大(做許多看起來很潮的功能),但要守住基本功能、並多考量後續的可維護(擴充)性 ### 2019/03/14 ==杜老大== 1. 在這半年內,其實沒辦法做好「希望有」的樣貌,只能算是起一個頭,實現簡單的情境下的 co-edit 2. 目前並沒有打算讓「使用者」編輯公開資料庫 3. 所以,共同編輯是發生個人資料庫,因此需為此在 DocuSky 上準備基本的 access API (牽涉到 db,api 我還沒去實作) 4. 由於我沒時間去設計實作 auth server 和對應的 api,因此早上講的 user4 部份可能就是請柔安留個 (實際上還沒有作用的) token 欄位 5. 在這幾個星期,就先在兩台電腦上,用同個帳號 co-edit 某篇文件來進行開發測試 6. 我會試著在這一兩個月把「user1 允許 user2 存取某 db/corpus A」補上。完成後 user2 應可從 widget 看到 user1 的 A,就可透過該 widget 取得 A 的文件(來進行共同編輯) 就算我在五月底來不及完成 6,柔安和欣烜也只要達到 5 即可 ==柔安== 您有提到4.先幫user4(沒有權限的使用者)留個token的欄位token是直接命名為 “owner+資料庫+文獻集+檔名”這樣的字串來辨別文件d?還是以這串字串加密產生一串密碼?還是隨機產生一串密碼和文件記錄在一起?另是想和您確認兩人 co-edit 文件的單位是一份docuXML? 還是 docuXML 中的一個 .xml檔?自己是覺得第三種最好backend server 在記錄密碼&“owner+資料庫+文獻集+檔名”的一對一對應好去locate文件。不知道這樣想有沒有什麼盲點?! 我們也有想到若使用者文件編輯到一半尚未儲存編輯到當前的檔案內容是要暫存在backend server還是要直接同步回 docusky 的文庫中?因為可能會牽涉到backend怎麼對編輯到一半的文件做處理 ==杜老大== - token 應該是由 auth server 所發給的,目前先隨便給個值(例如 "Reserved"、隨便產生的亂數碼、或者就那一天的日期)就好 - back-server 就留一段檢查 token 的程式碼,加一小段註解(提醒日後可加強)即可 - 至於編輯的內容,是一份文件,幾乎就是 DocuXml 中,以\<document\> 框住的部份,說「幾乎就是」是因為(透過 widget)從 DocuSky 取得的文件,會以 json 包裝該文件的 metadata 和內文 xml - 若使用者尚未儲存,就當作放棄修改內容(就像用 word 編輯一陣子後,不儲存就退出) - 目前 back-serer 就都是和使用者端溝通,由使用者端透過 widget 來更新文件在 DocuSky server 的內容 - 也就是說,使用者端的 co-edit 工具,透過 widget 存取 ds-server 文件,透過 back-server 處理共同編輯的即時需求 ==柔安== 編完的東西,我和欣烜會先實作「輸出backend 儲存內容」這個部分,而這個內容之後要供使用者下載到local端 或是 上傳至docusky複寫原本的檔案(因為杜博士這邊還沒開放) 就再看怎麼設計了