@@ -12,47 +12,59 @@ const app = new Koa();
1212const db = new ShareDB ( ) ;
1313
1414db . use ( 'connect' , ( ctx , done ) => {
15- // use custom to store the allowed document ID
15+ // use custom to store the allowed document ID and readOnly setting
1616 ctx . agent . custom = ctx . req ;
1717 done ( ) ;
1818} ) ;
1919db . use ( 'submit' , ( ctx , done ) => {
20- const allowed = ctx . collection === COLLECTION_NAME && ctx . id === ctx . agent . custom ;
20+ const allowed =
21+ ctx . collection === COLLECTION_NAME &&
22+ ctx . id === ctx . agent . custom . docId &&
23+ ! ctx . agent . custom . readOnly ;
2124 done ( allowed ? undefined : 'Cannot write to this document' ) ;
2225} ) ;
2326db . use ( 'readSnapshots' , ( ctx , done ) => {
2427 const allowed =
2528 ctx . collection === COLLECTION_NAME &&
26- ! ctx . snapshots . find ( ( snapshot ) => snapshot . id !== ctx . agent . custom ) ;
29+ ! ctx . snapshots . find ( ( snapshot ) => snapshot . id !== ctx . agent . custom . docId ) ;
2730 done ( allowed ? undefined : 'Cannot read these document(s)' ) ;
2831} ) ;
2932
30- const documents = new Set ( ) ;
33+ const documents = new Map ( ) ;
3134
3235app . use ( cors ( ) ) ;
3336app . use ( websocket ( ) ) ;
3437app . use ( bodyParser ( { enableTypes : [ 'json' , 'text' ] , strict : false } ) ) ;
3538app . use ( async ( ctx ) => {
3639 if ( ctx . method === 'POST' && ctx . path === '/' ) {
37- const contents = isEmptyObject ( ctx . request . body ) ? '' : ctx . request . body ;
40+ const { contents } = ctx . request . body ;
41+
42+ // Creates various IDs
3843 const docId = uuid ( ) ;
39- const doc = db . connect ( undefined , docId ) . get ( COLLECTION_NAME , docId ) ;
44+ const sessionEditingId = generateShortId ( ) ;
45+ documents . set ( sessionEditingId , [ docId , false ] ) ;
46+ const sessionViewingId = generateShortId ( ) ;
47+ documents . set ( sessionViewingId , [ docId , true ] ) ;
48+
49+ const connection = db . connect ( undefined , { docId, readOnly : false } ) ;
50+ const doc = connection . get ( COLLECTION_NAME , docId ) ;
4051 await new Promise ( ( resolve , reject ) => {
41- doc . create ( contents , ( err ) => {
52+ doc . create ( { contents } , ( err ) => {
4253 if ( err ) {
4354 reject ( err ) ;
4455 } else {
4556 resolve ( ) ;
4657 }
4758 } ) ;
4859 } ) ;
49- documents . add ( docId ) ;
50- ctx . body = docId ;
60+ ctx . body = { docId, sessionEditingId, sessionViewingId } ;
5161 return ;
5262 }
5363
54- const docId = ctx . path . substr ( 1 ) ;
55- if ( ! documents . has ( docId ) ) {
64+ const sessionId = ctx . path . substr ( 1 ) ;
65+ const [ docId , readOnly ] = getSessionDetails ( sessionId ) ;
66+
67+ if ( docId === null ) {
5668 ctx . status = 404 ;
5769 return ;
5870 }
@@ -64,14 +76,24 @@ app.use(async (ctx) => {
6476
6577 if ( ctx . ws ) {
6678 const ws = new WebSocketJSONStream ( await ctx . ws ( ) ) ;
67- db . listen ( ws , docId ) ;
79+ db . listen ( ws , { docId, readOnly } ) ; // docId and readOnly is passed to 'connect' middleware as ctx.req
6880 } else {
69- ctx . body = 'Document exists.' ;
81+ ctx . body = { docId , readOnly } ;
7082 }
7183} ) ;
7284
7385app . listen ( process . env . PORT || 8080 ) ;
7486
75- function isEmptyObject ( obj ) {
76- return Object . keys ( obj ) . length === 0 && obj . constructor === Object ;
87+ function getSessionDetails ( sessionId ) {
88+ const sessionDetails = documents . get ( sessionId ) ;
89+ return sessionDetails === undefined ? [ null , null ] : sessionDetails ;
90+ }
91+
92+ function generateShortId ( ) {
93+ const id = uuid ( ) . slice ( 0 , 6 ) ;
94+ if ( documents . has ( id ) ) {
95+ return generateShortId ( ) ;
96+ } else {
97+ return id ;
98+ }
7799}
0 commit comments