@@ -18,27 +18,24 @@ You should have received a copy of the Affero GNU General Public License
1818*/
1919
2020using System ;
21- using System . Collections . Generic ;
2221using System . Linq ;
2322using System . Security . Claims ;
2423using System . Text . Json ;
2524using System . Threading . Tasks ;
2625using AngleSharp ;
27- using AngleSharp . Dom ;
2826using Microsoft . AspNetCore . Authorization ;
2927using Microsoft . AspNetCore . Http ;
3028using Microsoft . AspNetCore . Mvc ;
3129using Microsoft . Extensions . Logging ;
3230using MongoDB . Bson ;
3331using MongoDB . Driver ;
34- using Notesnook . API . Authorization ;
32+ using NanoidDotNet ;
3533using Notesnook . API . Models ;
3634using Notesnook . API . Services ;
3735using Streetwriters . Common ;
3836using Streetwriters . Common . Helpers ;
3937using Streetwriters . Common . Interfaces ;
4038using Streetwriters . Common . Messages ;
41- using Streetwriters . Data . Interfaces ;
4239using Streetwriters . Data . Repositories ;
4340
4441namespace Notesnook . API . Controllers
@@ -95,6 +92,22 @@ private async Task<Monograph> FindMonographAsync(string itemId)
9592 return await result . FirstOrDefaultAsync ( ) ;
9693 }
9794
95+ private async Task < Monograph > FindMonographBySlugAsync ( string slug )
96+ {
97+ var result = await monographs . Collection . FindAsync (
98+ Builders < Monograph > . Filter . Eq ( "Slug" , slug ) ,
99+ new FindOptions < Monograph >
100+ {
101+ Limit = 1
102+ } ) ;
103+ return await result . FirstOrDefaultAsync ( ) ;
104+ }
105+
106+ private static string GenerateSlug ( )
107+ {
108+ return Nanoid . Generate ( size : 24 ) ;
109+ }
110+
98111 [ HttpPost ]
99112 public async Task < IActionResult > PublishAsync ( [ FromQuery ] string ? deviceId , [ FromBody ] Monograph monograph )
100113 {
@@ -120,6 +133,7 @@ public async Task<IActionResult> PublishAsync([FromQuery] string? deviceId, [Fro
120133 }
121134 monograph . Deleted = false ;
122135 monograph . ViewCount = 0 ;
136+ monograph . Slug = GenerateSlug ( ) ;
123137 await monographs . Collection . ReplaceOneAsync (
124138 CreateMonographFilter ( userId , monograph ) ,
125139 monograph ,
@@ -131,7 +145,8 @@ await monographs.Collection.ReplaceOneAsync(
131145 return Ok ( new
132146 {
133147 id = monograph . ItemId ,
134- datePublished = monograph . DatePublished
148+ datePublished = monograph . DatePublished ,
149+ slug = monograph . Slug
135150 } ) ;
136151 }
137152 catch ( Exception e )
@@ -164,6 +179,7 @@ public async Task<IActionResult> UpdateAsync([FromQuery] string? deviceId, [From
164179 monograph . Content = null ;
165180
166181 monograph . DatePublished = DateTimeOffset . UtcNow . ToUnixTimeMilliseconds ( ) ;
182+ monograph . Slug = GenerateSlug ( ) ;
167183 var result = await monographs . Collection . UpdateOneAsync (
168184 CreateMonographFilter ( userId , monograph ) ,
169185 Builders < Monograph > . Update
@@ -172,6 +188,7 @@ public async Task<IActionResult> UpdateAsync([FromQuery] string? deviceId, [From
172188 . Set ( m => m . EncryptedContent , monograph . EncryptedContent )
173189 . Set ( m => m . SelfDestruct , monograph . SelfDestruct )
174190 . Set ( m => m . Title , monograph . Title )
191+ . Set ( m => m . Slug , monograph . Slug )
175192 . Set ( m => m . Password , monograph . Password )
176193 ) ;
177194 if ( ! result . IsAcknowledged ) return BadRequest ( ) ;
@@ -181,7 +198,8 @@ public async Task<IActionResult> UpdateAsync([FromQuery] string? deviceId, [From
181198 return Ok ( new
182199 {
183200 id = monograph . ItemId ,
184- datePublished = monograph . DatePublished
201+ datePublished = monograph . DatePublished ,
202+ slug = monograph . Slug
185203 } ) ;
186204 }
187205 catch ( Exception e )
@@ -208,11 +226,25 @@ public async Task<IActionResult> GetUserMonographsAsync()
208226 return Ok ( userMonographs . Select ( ( m ) => m . ItemId ?? m . Id ) ) ;
209227 }
210228
211- [ HttpGet ( "{id }" ) ]
229+ [ HttpGet ( "{slugOrId }" ) ]
212230 [ AllowAnonymous ]
213- public async Task < IActionResult > GetMonographAsync ( [ FromRoute ] string id )
231+ public async Task < IActionResult > GetMonographAsync ( [ FromRoute ] string slugOrId )
214232 {
215- var monograph = await FindMonographAsync ( id ) ;
233+ var monograph = await FindMonographBySlugAsync ( slugOrId ) ;
234+
235+ if ( monograph == null )
236+ {
237+ monograph = await FindMonographAsync ( slugOrId ) ;
238+ if ( ! string . IsNullOrEmpty ( monograph ? . Slug ) )
239+ {
240+ return NotFound ( new
241+ {
242+ error = "invalid_id" ,
243+ error_description = $ "No such monograph found."
244+ } ) ;
245+ }
246+ }
247+
216248 if ( monograph == null || monograph . Deleted )
217249 {
218250 return NotFound ( new
0 commit comments