From 44b410f359f64e6cb69d506b5689d2b3df715c74 Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 19 Aug 2020 21:54:35 +0800 Subject: Upgrade packages. --- Timeline.Tests/Timeline.Tests.csproj | 10 +- Timeline.Tests/packages.lock.json | 354 +++++++++++++++--------------- Timeline/Timeline.csproj | 20 +- Timeline/packages.lock.json | 405 ++++++++++++++--------------------- 4 files changed, 347 insertions(+), 442 deletions(-) diff --git a/Timeline.Tests/Timeline.Tests.csproj b/Timeline.Tests/Timeline.Tests.csproj index fc1a6ca4..ca207f00 100644 --- a/Timeline.Tests/Timeline.Tests.csproj +++ b/Timeline.Tests/Timeline.Tests.csproj @@ -14,15 +14,15 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + all runtime; build; native; contentfiles; analyzers diff --git a/Timeline.Tests/packages.lock.json b/Timeline.Tests/packages.lock.json index c2cfec72..c01f13c8 100644 --- a/Timeline.Tests/packages.lock.json +++ b/Timeline.Tests/packages.lock.json @@ -35,40 +35,40 @@ }, "Microsoft.AspNetCore.TestHost": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "o08GfbTytPirpwlNe/mIaGv7yyM+Qf0Ig0dM4Dxmzee4rPRXQl3QlhFGVW8WbtVamUXlskbTloi7lmUVwAihPw==", + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "NyYXhaKwMDFYhTCwuRC9uFTK1lHH2lbjSBSY0ZbmOkM6xk3CIyZggTS+tIB3235GcqmWXt5NIdGveKanMflAxQ==", "dependencies": { "System.IO.Pipelines": "4.7.1" } }, "Microsoft.CodeAnalysis.FxCopAnalyzers": { "type": "Direct", - "requested": "[3.0.0, )", - "resolved": "3.0.0", - "contentHash": "ea8bbNa4fzS/s55AUCAvYjb6Y3lFysFVfEwt9zIwR/NeFpOcUluIleOXSUPAyUtwBFugn01aWvNfMVmIwnvgqQ==", + "requested": "[3.3.0, )", + "resolved": "3.3.0", + "contentHash": "k3Icqx8kc+NrHImuiB8Jc/wd32Xeyd2B/7HOR5Qu9pyKzXQ4ikPeBAwzG2FSTuYhyIuNWvwL5k9yYBbbVz6w9w==", "dependencies": { - "Microsoft.CodeAnalysis.VersionCheckAnalyzer": "[3.0.0]", - "Microsoft.CodeQuality.Analyzers": "[3.0.0]", - "Microsoft.NetCore.Analyzers": "[3.0.0]", - "Microsoft.NetFramework.Analyzers": "[3.0.0]" + "Microsoft.CodeAnalysis.VersionCheckAnalyzer": "[3.3.0]", + "Microsoft.CodeQuality.Analyzers": "[3.3.0]", + "Microsoft.NetCore.Analyzers": "[3.3.0]", + "Microsoft.NetFramework.Analyzers": "[3.3.0]" } }, "Microsoft.NET.Test.Sdk": { "type": "Direct", - "requested": "[16.6.1, )", - "resolved": "16.6.1", - "contentHash": "zYAjfWzpxKb64P9ntReT1Xr8HdONZnpLVs12HIjXWo+UOCDpevP1UWRoaAgNysaD1/l3teBKvgbSeG9bRssfOQ==", + "requested": "[16.7.0, )", + "resolved": "16.7.0", + "contentHash": "sF0iQqII3WEOdcDwM+bNog2zrRM48MHtKP3T3scfZmlh5IvFIBRfS0kGH9AGOMpTqmpkTYuMkEUkSaz94aWYkA==", "dependencies": { - "Microsoft.CodeCoverage": "16.6.1", - "Microsoft.TestPlatform.TestHost": "16.6.1" + "Microsoft.CodeCoverage": "16.7.0", + "Microsoft.TestPlatform.TestHost": "16.7.0" } }, "Moq": { "type": "Direct", - "requested": "[4.14.1, )", - "resolved": "4.14.1", - "contentHash": "yRrU+cLNBtZpL9eLVyicOENMPUx7DjOOB+VPgDhrXaCjhfob661d4HJ82YJpPUBmlYoivNA8F4R+NIMfoKbD7g==", + "requested": "[4.14.5, )", + "resolved": "4.14.5", + "contentHash": "g/TLN+z6Fjd1E3DAUDbBI3nZcNDUXGKGEmImYqJdZ9TzvjME9KkE4BfV4vsKSXm3Of/C0y+rQKW3/5QSCeTUPA==", "dependencies": { "Castle.Core": "4.4.0", "System.Threading.Tasks.Extensions": "4.5.1" @@ -87,26 +87,27 @@ }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.4.2, )", - "resolved": "2.4.2", - "contentHash": "Trt9multph2KE3U0p9oBt0k4Fq6lUv4btUcONaQEeuFnMCak2k/b7PAArbLtMFW7HO1jxlBHUgIPKEqci3Y1dg==" + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" }, "AutoMapper": { "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "xCqvoxT4HIrNY/xlXG9W+BA/awdrhWvMTKTK/igkGSRbhOhpl3Q8O8Gxlhzjc9JsYqE7sS6AxgyuUUvZ6R5/Bw==", + "resolved": "10.0.0", + "contentHash": "T09NoqMZBqw0/JEauXulxnmmerl0Zj03e0r6VCcJ0LURWBIaYxZPPoiDv8bHf5Y4x2xcXJp4JPXoCaeOMJfHEA==", "dependencies": { - "Microsoft.CSharp": "4.5.0", - "System.Reflection.Emit": "4.3.0" + "Microsoft.CSharp": "4.7.0", + "System.Reflection.Emit": "4.7.0" } }, "AutoMapper.Extensions.Microsoft.DependencyInjection": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "szI4yeRIM7GWe9JyekW0dKYehPB0t6M+I55fPeCebN6PhS7zQZa0eG3bgOnOx+eP3caSNoE7KEJs2rk7MLsh8w==", + "resolved": "8.0.1", + "contentHash": "hhUzmc8Ld7wCuVHJFodsxtPmFqBAhB6nUNQUgaMF3uamQdxOLxntG0dwv+5ApC67GABa8Oay8MEYGg5IgVZP1Q==", "dependencies": { - "AutoMapper": "9.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0" + "AutoMapper": "[10.0.0, 11.0.0)", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.0.0", + "Microsoft.Extensions.Options": "3.0.0" } }, "Castle.Core": { @@ -128,28 +129,28 @@ }, "Microsoft.AspNetCore.NodeServices": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "WpDoV45BhN0mhc1+5+k29AKzn6suYfm3HynIYngdgBaS2pdXWZPNY/73m7btxbwqaQHup35oqNBVUGNWK2NMWg==", + "resolved": "3.1.7", + "contentHash": "JrDTykwIAdQBbakPMHbbyh6tPJdcQmza+RBKrCK6Dtyk3HL6lqcLIL739WVqrwU21Py3WZtqYwNmn+5yvrYung==", "dependencies": { - "Microsoft.Extensions.Logging.Console": "3.1.5", + "Microsoft.Extensions.Logging.Console": "3.1.7", "Newtonsoft.Json": "12.0.2" } }, "Microsoft.AspNetCore.SpaServices": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "DE34f2Ne92p++7vnONcz869p+yKuHjWjBzfZj7ny2wFSwABzpb98l/x41MYB3zndQW322C5wPmnJbh3P2+AhRg==", + "resolved": "3.1.7", + "contentHash": "BOkdx8FChFq9l3ZJqSirp6iuhtTeKjCYcvxFT32lQGeNOU594NnV8XU3f13aSGUhI/6AsqMPwuliWlUA2RpSSg==", "dependencies": { - "Microsoft.AspNetCore.NodeServices": "3.1.5" + "Microsoft.AspNetCore.NodeServices": "3.1.7" } }, "Microsoft.AspNetCore.SpaServices.Extensions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "mWRSFYK+AxBMuB+PMIMaB9E2QaXaaiwMYhfavPLPZ8VolKIEeJsfcrBhtgAKroaLblkJL7zQJFIEZL0KGoWaYw==", + "resolved": "3.1.7", + "contentHash": "avSGyrRPLaRbVdbEKDANRw7KGwZ2g8r/lWSlhELeGlWhuz99LMet8cpsXJeqq2hWcwJ2ZmnL7StNn6tCGJtukA==", "dependencies": { - "Microsoft.AspNetCore.SpaServices": "3.1.5", - "Microsoft.Extensions.FileProviders.Physical": "3.1.5" + "Microsoft.AspNetCore.SpaServices": "3.1.7", + "Microsoft.Extensions.FileProviders.Physical": "3.1.7" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -164,49 +165,49 @@ }, "Microsoft.CodeAnalysis.VersionCheckAnalyzer": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "RL9OdvWLhtQXcvxK2EPbXM9LandLcDG14Ndz5baVH2aiyvEB11VrHfrzLNoEE5B2/zhRGqN+BHsBg21f75wG9g==" + "resolved": "3.3.0", + "contentHash": "xjLM3DRFZMan3nQyBQEM1mBw6VqQybi4iMJhMFW6Ic1E1GCvqJR3ABOwEL7WtQjDUzxyrGld9bASnAos7G/Xyg==" }, "Microsoft.CodeCoverage": { "type": "Transitive", - "resolved": "16.6.1", - "contentHash": "nBYXDgAZCfjsOVzlhMB5olGvX4dTDWB/gWaYS/MhgXBcCz8XJuVGqkfK8LmwlBR/eeUPE9Q/NFZNwlJyMZf0vg==" + "resolved": "16.7.0", + "contentHash": "przIisHDudyAtmh0hx8GCW8lOlJ7Zi0OX8LVrLlyFvaIPl6shGVhcPFjwAtY8cuSEpjc/Rpu9+BuJcphcXpyrA==" }, "Microsoft.CodeQuality.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "pOROTgdPa+15sYfEMvDlWlDEedCO1SuRLrRjX36Ltli3SmhZawC2Vgws4crz1XMs9WRzBo8WIJM5WRzGNsOSmQ==" + "resolved": "3.3.0", + "contentHash": "zZ3miq6u22UFQKhfJyLnVEJ+DgeOopLh3eKJnKAcOetPP2hiv3wa7kHZlBDeTvtqJQiAQhAVbttket8XxjN1zw==" }, "Microsoft.CSharp": { "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ==" + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" }, "Microsoft.Data.Sqlite.Core": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "97AVbafsZQVale8l04QmrOa1fEo8eCQ4oMK1XxdKc8JVYY4r9nMiYZiNwEDa9VHVY/Hug9YIawghzg6o+0E+fw==", + "resolved": "3.1.7", + "contentHash": "NpX0Ni0ZYxbWXtTxVfFnHR7i/+dCX+BayFSPjH8rCEv5NZXtndKyR0Gh3xl5jpuhv4m1eZr8njq+sV2fNREPjw==", "dependencies": { "SQLitePCLRaw.core": "2.0.2" } }, "Microsoft.DotNet.PlatformAbstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2jxam7bgOxELzk8m8iwRg+e42x7G6WigtWCk6d9MXQEiZSl5FZMGpEk/8AXvl4ybogu1OgBkT5G+g94O9/lelQ==" + "resolved": "3.1.3", + "contentHash": "bwD01wYeN+g+Yib7XXahbRdvh5lj6PJ0si6TO6kP7n+fQsBxGy18ewJLjTZUxCwWJqX39WfQHM6idtE4QuVaiw==" }, "Microsoft.EntityFrameworkCore": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "1jYVmK8dMKGhtMMrtw0hicRjAJq8hnFSuXHdJTIGa04UVWFvsMFwWsdO3Y1ziCLgR2xM7u5AgUcFLGbV0t9cOg==", + "resolved": "3.1.7", + "contentHash": "u0MXvEkUwXd/JPzuWcSn4Bvx65FrDsn0GJV/tN4kjoZdVcKkXgbDG+RZM9BMGgK77NXmhx9Osy35fujmS3otyA==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "1.1.1", "Microsoft.Bcl.HashCode": "1.1.0", - "Microsoft.EntityFrameworkCore.Abstractions": "3.1.5", - "Microsoft.EntityFrameworkCore.Analyzers": "3.1.5", - "Microsoft.Extensions.Caching.Memory": "3.1.5", - "Microsoft.Extensions.DependencyInjection": "3.1.5", - "Microsoft.Extensions.Logging": "3.1.5", + "Microsoft.EntityFrameworkCore.Abstractions": "3.1.7", + "Microsoft.EntityFrameworkCore.Analyzers": "3.1.7", + "Microsoft.Extensions.Caching.Memory": "3.1.7", + "Microsoft.Extensions.DependencyInjection": "3.1.7", + "Microsoft.Extensions.Logging": "3.1.7", "System.Collections.Immutable": "1.7.1", "System.ComponentModel.Annotations": "4.7.0", "System.Diagnostics.DiagnosticSource": "4.7.1" @@ -214,215 +215,215 @@ }, "Microsoft.EntityFrameworkCore.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "xZ3mUVu22p2h0ZKTWgoyK9YjA2H11cJcZssDcZYs8iLUVHPxMcb+ITOKpMdnV6SkEiQQ5pvjPXQ5J7VxiGSwDw==" + "resolved": "3.1.7", + "contentHash": "Dx2aGjTKPq49nMYl8t9Lq9XgZJOSIsIQE7lOCThVyHHAYgZrkc8NRgzE/PLGfUO4tfyNSImkXlyF98DBAXI5fw==" }, "Microsoft.EntityFrameworkCore.Analyzers": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "NhxlI6Qj/QUt79ApeBrpKo+a5TGt/UCddxd9rLHD7Zd6yLyfkDOMiyu4oPqhnMhpqmzo/gd79tW7BMwIxgEZCw==" + "resolved": "3.1.7", + "contentHash": "zSh3QF/Kz8fdVgyStQ1HYUGFDRqFbUR1UBpfa8tUuB0OutYab9R4aYdjkD8i9w9P5VZyHXqQNglh2cQHBFLtjg==" }, "Microsoft.EntityFrameworkCore.Relational": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "MNWF77Ekiu7Fe9BhgpwNft6MW0x5T+r7B43A/jtnEH+fQTjrfJrjBDgm+klxrQhha/8Jr/GxkRHmptXws0AAfA==", + "resolved": "3.1.7", + "contentHash": "XLzwdgHPq5QgcmPZkkAso+SSW/tQqPD/iGaZv+fhl7lCb7VTPsjGE0BiPG9xiUP7OR+tlKNDffSzKimElZMaqA==", "dependencies": { - "Microsoft.EntityFrameworkCore": "3.1.5" + "Microsoft.EntityFrameworkCore": "3.1.7" } }, "Microsoft.EntityFrameworkCore.Sqlite": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "HZn8UjdzfrvAK3xoqj65PZKprMXXev6NVNDEe/PAU6dcW1KXuSxU8cg2LB68ltEI1dLx8JaiKF/yWAq7H4pUQQ==", + "resolved": "3.1.7", + "contentHash": "ZLBVThJ/EBAlqXTOb665GeXglEjkZhxikd+FwseNR1B8GuzowrC+cX2TAVd1ryhnpG/4g+RNOajTPDk5dBta7Q==", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite.Core": "3.1.5", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "3.1.7", "SQLitePCLRaw.bundle_e_sqlite3": "2.0.2" } }, "Microsoft.EntityFrameworkCore.Sqlite.Core": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "Rb9It33lD2x6ODF4i0M3quadEPJOEHsANSNqctBnUnLbZX8HshGmEml3jQZELpJ1lhV0aEuATrFLDWT8EUdbiQ==", + "resolved": "3.1.7", + "contentHash": "jOViumARQZ84Ya/j+gKgtjwBa9D5iKsbPWuLy2Z/fVvkpfuTwfiRjIoxe0y+ta8iec9FpEQ+Q2r13hzSdXSfEQ==", "dependencies": { - "Microsoft.Data.Sqlite.Core": "3.1.5", - "Microsoft.DotNet.PlatformAbstractions": "3.1.5", - "Microsoft.EntityFrameworkCore.Relational": "3.1.5", - "Microsoft.Extensions.DependencyModel": "3.1.5" + "Microsoft.Data.Sqlite.Core": "3.1.7", + "Microsoft.DotNet.PlatformAbstractions": "3.1.3", + "Microsoft.EntityFrameworkCore.Relational": "3.1.7", + "Microsoft.Extensions.DependencyModel": "3.1.3" } }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "1HWdvlBNI4laVkx5oglv3Oaz5s8dO/dpkOep8FLv7+QAK2rm3ofBVv49aiDnijnwO+ZPJ/0iNctZWP0W2S07Rw==", + "resolved": "3.1.7", + "contentHash": "Uj/0fmq7FWi7B7RfLkn2UJE1SThJ60mOlChx9P5nRjP/EbeYNm+LoyiOr6yPhDsArwHttKyun18TXXJ2C9EE/g==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Caching.Memory": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "tqnVZ/tyXiBAEeLtcTvyb/poVp/gn6bbpdr12SAbO4TcfNkd1eNCEbyyABo0qhiQh6vVwba41aixklElx4grdw==", + "resolved": "3.1.7", + "contentHash": "EvNcJWk0KKSqyXefiUTgF5D94r40rmmtAvo5/yhy7u5/CtRjqyN7wQBSKz2ezWlu5vbuMGyaMktANgkk4kEkaw==", "dependencies": { - "Microsoft.Extensions.Caching.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Caching.Abstractions": "3.1.7", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Logging.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Configuration": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LZfdAP8flK4hkaniUv6TlstDX9FXLmJMX1A4mpLghAsZxTaJIgf+nzBNiPRdy/B5Vrs74gRONX3JrIUJQrebmA==", + "resolved": "3.1.7", + "contentHash": "JCVsQYNZNGeLXWMw6tkCZ8Wa2IQKF9AiLKeq9Ff2XvGJTMzhYEHAzF/FvHdeBBhPiOf+Kl1t6mdcHL93kUz6MA==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7" } }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", + "resolved": "3.1.7", + "contentHash": "WJEbrrIgly95D9rM8Gwr4w8sbYla6/iOcCZ0UE7+Qg/Q8NnQJwAJ60Lq1A26zbNE8Fm1fkbGU90LDl8e+BoRSQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZR/zjBxkvdnnWhRoBHDT95uz1ZgJFhv1QazmKCIcDqy/RXqi+6dJ/PfxDhEnzPvk9HbkcGfFsPEu1vSIyxDqBQ==", + "resolved": "3.1.7", + "contentHash": "FYQ64i7DwYO6XDdOFi+VkoRDDzel570I+X/vTYt6mVJWNj1SAstXwZ71P5d6P2Cei+cT950NiScOwj4F8EUeTA==", "dependencies": { - "Microsoft.Extensions.Configuration": "3.1.5" + "Microsoft.Extensions.Configuration": "3.1.7" } }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+RTJQi7TtenIHZqL2zr6523PYXfL88Ruu4UIVmspIxdw14GHd8zZ+2dGLSdwX7fn41Hth4d42S1e1iHWVOJyQ==", + "resolved": "3.1.7", + "contentHash": "yp38AFc5tJQZkjINjXBcxq+dANU06lo27D84duitZthtRPsgKJL87uf9RWRsDdRsWd+kXflmdMWFLKFjyKx6Pw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" + "resolved": "3.1.7", + "contentHash": "oKL2yNtTN1/cOp+cbdyv5TeLzO+GkO9B3fvbcPzKWTNCkDoH3ccYS3FWC1p4KSYe9frW4WsyfSTeM8X+xftOig==" }, "Microsoft.Extensions.DependencyModel": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "u1RWQS0ym1USOoRji6MKcka/F/Br18/+1kiUvAcqWeG7v95SejSBXWRuS5eFfk6gCr3ppRxYyfnwUpmXa91ZsA==", + "resolved": "3.1.3", + "contentHash": "NrcgRhryflmjz16bwr2krbQyhMstOhRi6dD39KEhUGRKVdXEKOppVVOOelxchIFVfNUGs5SEvcAm+binU09S3g==", "dependencies": { - "System.Text.Json": "4.7.2" + "System.Text.Json": "4.7.1" } }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", + "resolved": "3.1.7", + "contentHash": "nasMSdDlIIBcKgGVHoZdFSmfUY1bI0zkvfZTsWLlEFcMCVD0fzcgsVlkeZTzPLJV0w7Uwq3okOgMWpU1nFEhxg==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "JemaaSSQosZ59flEfNzqvQRHDt1u4aEwV/pR4eFQEXpaX7lHI13gSbQbQ7TMGDdmY9F2t2+6RPp44Mmf9O1DsQ==", + "resolved": "3.1.7", + "contentHash": "mo21yJfL3oGCjC/rcwdbs2z4KGL9R5BvTfwYR31ueyg3l77i9oPCryMtlSZ4TvpI5duENNEpZyzcpaycqERdZQ==", "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.FileSystemGlobbing": "3.1.5" + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.7", + "Microsoft.Extensions.FileSystemGlobbing": "3.1.7" } }, "Microsoft.Extensions.FileSystemGlobbing": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ObdbZ/L3X89KOHI0K/zlwufnlHESYSp2L/Z1XgYp3Odekmzevl06iffrtIBP9Qgw2RxBVAyTEVNrIouCuik6yg==" + "resolved": "3.1.7", + "contentHash": "Cenv9mtZdSZ9u09rGYl3ejMB19gIOdRryXk/rYEzQsyrBTTuNzmRHwtHdy640P08DL1Rdu+0z/s2lpvFbZV8Hw==" }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "C85NYDym6xy03o70vxX+VQ4ZEjj5Eg5t5QoGW0t100vG5MmPL6+G3XXcQjIIn1WRQrjzGWzQwuKf38fxXEWIWA==", + "resolved": "3.1.7", + "contentHash": "p68Hvr8S+t+bGUeXRX6wcjlkK961w0YRXWy8O6pkTsucdNpnzB8mwLIgcnQ7oj0biw8S1Ftv4PREzPIwo1UwpA==", "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "3.1.5", - "Microsoft.Extensions.DependencyInjection": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Configuration.Binder": "3.1.7", + "Microsoft.Extensions.DependencyInjection": "3.1.7", + "Microsoft.Extensions.Logging.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" + "resolved": "3.1.7", + "contentHash": "oD7LQbMuaqq/yAz8PKX0hl4+H/vDFTQHo8rxbKB36P1/bG8FG7JUVKBoHkSt1MaJUtgyiHrH1AlAhaucKUKyEg==" }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+9jx/A9cLdkTmynKMa2oR4rYAfe3n2F/wNVvKxwIk2J33paEU13Se08Q5xvQisqfbumaRUNF7BWHr63JzuuRw==", + "resolved": "3.1.7", + "contentHash": "lfV0JUsVb/AyYWoZpsn2vmJe+C1hO34FlPh1YDNIpgHbpmK4IbQpGkcjQ2MPyFohJUHmscB9tST5J3xfTYIQEQ==", "dependencies": { - "Microsoft.Extensions.Logging": "3.1.5", - "Microsoft.Extensions.Options.ConfigurationExtensions": "3.1.5" + "Microsoft.Extensions.Logging": "3.1.7", + "Microsoft.Extensions.Options.ConfigurationExtensions": "3.1.7" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "c/W7d9sjgyU0/3txj/i6pC+8f25Jbua7zKhHVHidC5hHL4OX8fAxSGPBWYOsRN4tXqpd5VphNmIFUWyT12fMoA==", + "resolved": "3.1.7", + "contentHash": "rbFWSXzxP9eMzEiFJsOgxc7I8Wy+gJjkl2ROR3KHD0mCQzBjnJ1VR4Dsu5k1AIThwPbC+WoOzMjqNe0Jwxvwpg==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging": "3.1.5", - "Microsoft.Extensions.Logging.Configuration": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7", + "Microsoft.Extensions.Logging": "3.1.7", + "Microsoft.Extensions.Logging.Configuration": "3.1.7" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", + "resolved": "3.1.7", + "contentHash": "O5TXu1D79hbaZuKCIK4mswSP86MtmiIQjuOZnVhPdbjOVILsoQwZUtnmU2xRfX1E0QWuFEI0umhw3mDDn6dNHw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Options.ConfigurationExtensions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "mgM+JHFeRg3zSRjScVADU/mohY8s0czKRTNT9oszWgX1mlw419yqP6ITCXovPopMXiqzRdkZ7AEuErX9K+ROww==", + "resolved": "3.1.7", + "contentHash": "VYW5bmNoNM852QmWvlPS1iktEZ4loGCfcoP0/UASpsjOZejGAvk0XTRdwh1DFv6AvWT0NYitdbx4y3Sqigr42g==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.Configuration.Binder": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7", + "Microsoft.Extensions.Configuration.Binder": "3.1.7", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" + "resolved": "3.1.7", + "contentHash": "sa17s3vDAXTuIVGxuJcK713i0B0iaUoiwY4Sl2SLHhMqM8snznn0YVGiZAVkoKEUFWjvIg1Z/JNmAicBamI4mg==" }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "ZhzG2+nxbGDJ67vY0e9kuJEtPpA53EhkhXpLWlBOUzEGd085ojJT3XPLK74mC+mjsXpZqWj5pHtgbB77gSqJeg==", + "resolved": "6.7.1", + "contentHash": "q/Ii8ILV8cM1X49gnl12cJK+0KWiI1xUeiLYiE9+uRonJLaHWB0l8t89rGnZTEGthGKItyikKSB38LQpfy/zBw==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "6.6.0" + "Microsoft.IdentityModel.Tokens": "6.7.1" } }, "Microsoft.IdentityModel.Logging": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "OWfHX7bXKTEBXcD9b+0Tx7dWBaqF4wht7RmS6q+9vAXHiNpRG/wkoFKhOp1Yus0Xd1xAXXHSkAKxgmn/SRD1KA==" + "resolved": "6.7.1", + "contentHash": "WGtTiTy2ZikOz/I5GxCGbNPLOpyI9fPyuyG4Q5rfkhACK+Q0Ad6U8XajYZ2cJ2cFKse0IvHwm15HVrfwrX/89g==" }, "Microsoft.IdentityModel.Tokens": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "fNfhlY7AEB9y/jooK6xI1vH+7rmq7c2kTEk7j/5SSy25iHRB1twrG8+He9sHxBQqIXhrQliMEwi4GXZInzO4ww==", + "resolved": "6.7.1", + "contentHash": "Td9Vn9d/0eM1zlUUvaVQzjqdBkBLJ2oGtGL/LYPuiCUAALMeAHVDtpXGk8eYI8Gbduz5n+o7ifldsCIca4MWew==", "dependencies": { "Microsoft.CSharp": "4.5.0", - "Microsoft.IdentityModel.Logging": "6.6.0", + "Microsoft.IdentityModel.Logging": "6.7.1", "System.Security.Cryptography.Cng": "4.5.0" } }, "Microsoft.NetCore.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "JdjhkobYjmQAu4JpsEALDAr7xig2pzXMsXGilHJ2gvmUaUSBjYObw53CBaIkRXmPu0DaDPN8ze9LCtsRd1R8UA==" + "resolved": "3.3.0", + "contentHash": "6qptTHUu1Wfszuf83NhU0IoAb4j7YWOpJs6oc6S4G/nI6aGGWKH/Xi5Vs9L/8lrI74ijEEzPcIwafSQW5ASHtA==" }, "Microsoft.NETCore.Platforms": { "type": "Transitive", @@ -436,23 +437,23 @@ }, "Microsoft.NetFramework.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "Q0sB3JYld9JMa9/HKtioIxhqmOohEku1FkfSC/uf0usGcCIhm6GYWU565klP64jC2kzmjFIu/6fkHEIYRqZCQQ==" + "resolved": "3.3.0", + "contentHash": "JTfMic5fEFWICePbr7GXOGPranqS9Qxu2U/BZEcnnGbK1SFW8TxRyGp6O1L52xsbfOdqmzjc0t5ubhDrjj+Xpg==" }, "Microsoft.TestPlatform.ObjectModel": { "type": "Transitive", - "resolved": "16.6.1", - "contentHash": "QFD1oT7Rn8Pv6z8L95gDXHsgRSsQmvMrIIhSrUqsEuKwsKg4HAqlOhWRwR0/UEkFMl9NdWt2w+OH01ttcDTtkg==", + "resolved": "16.7.0", + "contentHash": "1/49rMeZXCdlAd0bCBcL6zicQm+lCNOW5N0d7DdNUdtFASCWTQ2u8MauoFT3zwYsZDcC/3q6zLnt723EGeQwZg==", "dependencies": { "NuGet.Frameworks": "5.0.0" } }, "Microsoft.TestPlatform.TestHost": { "type": "Transitive", - "resolved": "16.6.1", - "contentHash": "zPDuoodyqh99TReaEE7ea7nXmNTvQ7oclK/yng/r6DrOUDP1E7a5sW6x3fkb0CqEmb2YNUwH9QgmiVmouv/wIw==", + "resolved": "16.7.0", + "contentHash": "5yWCRl3oI6Hj9ikgthc/QoyvwUD7CbWnZZjgm8jqZ4HZawAEDNpXLRjYkhWAtZ/sOfbC7lFSV1Pmk87FmNxuSA==", "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "16.6.1", + "Microsoft.TestPlatform.ObjectModel": "16.7.0", "Newtonsoft.Json": "9.0.1" } }, @@ -645,8 +646,8 @@ }, "SixLabors.ImageSharp": { "type": "Transitive", - "resolved": "1.0.0-rc0001", - "contentHash": "lxQYvAv8vTp0QD1MafqUP1t8kbwy/2wolqHwymCMeozcfGNnYKNXlLSzwVQRoGXBOVRWgvU4f07hXCNmCLN4Ug==" + "resolved": "1.0.0", + "contentHash": "8amvsk8NXnCxZV0lvJppAZJknViWgBOO/2V59IGR6DVoD13mSmG+/Z9eg5IwrHQuRHp5RD9lfXBXDZyk8rTKDg==" }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", @@ -931,11 +932,11 @@ }, "System.IdentityModel.Tokens.Jwt": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "irSFzRuejokJUb0z/tkHq1x0WCCuk8wtJ85Sql7YaUqSQXPLmKi7zFjVI1UAUX+yANmD673VwN+n64lEq/vW6Q==", + "resolved": "6.7.1", + "contentHash": "sPnRn9dUMYARQC3mAKWpig/7rlrruqJvopKXmGoYAQ1A+xQsT3q5LiwsArkV8Oz/hfiRCLkV9vgi3FQg/mYfrw==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "6.6.0", - "Microsoft.IdentityModel.Tokens": "6.6.0" + "Microsoft.IdentityModel.JsonWebTokens": "6.7.1", + "Microsoft.IdentityModel.Tokens": "6.7.1" } }, "System.IO": { @@ -1140,15 +1141,8 @@ }, "System.Reflection.Emit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.0", + "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" }, "System.Reflection.Emit.ILGeneration": { "type": "Transitive", @@ -1439,8 +1433,8 @@ }, "System.Text.Json": { "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "TcMd95wcrubm9nHvJEQs70rC0H/8omiSGGpU4FQ/ZA1URIqD4pjmFJh2Mfv1yH1eHgJDWTi2hMDXwTET+zOOyg==" + "resolved": "4.7.1", + "contentHash": "XwzMbct3iNepJaFylN1+l8weWlFburEzXidqleSsLvSXdHSIJHEKtRVKHPlpWcFmJX6k3goPFfVgUfp40RR+bg==" }, "System.Text.RegularExpressions": { "type": "Transitive", @@ -1590,14 +1584,14 @@ "timeline": { "type": "Project", "dependencies": { - "AutoMapper": "9.0.0", - "AutoMapper.Extensions.Microsoft.DependencyInjection": "7.0.0", - "Microsoft.AspNetCore.SpaServices.Extensions": "3.1.5", - "Microsoft.EntityFrameworkCore": "3.1.5", - "Microsoft.EntityFrameworkCore.Analyzers": "3.1.5", - "Microsoft.EntityFrameworkCore.Sqlite": "3.1.5", - "SixLabors.ImageSharp": "1.0.0-rc0001", - "System.IdentityModel.Tokens.Jwt": "6.6.0", + "AutoMapper": "10.0.0", + "AutoMapper.Extensions.Microsoft.DependencyInjection": "8.0.1", + "Microsoft.AspNetCore.SpaServices.Extensions": "3.1.7", + "Microsoft.EntityFrameworkCore": "3.1.7", + "Microsoft.EntityFrameworkCore.Analyzers": "3.1.7", + "Microsoft.EntityFrameworkCore.Sqlite": "3.1.7", + "SixLabors.ImageSharp": "1.0.0", + "System.IdentityModel.Tokens.Jwt": "6.7.1", "Timeline.ErrorCodes": "1.0.0" } }, diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 50458c4b..cdd5f1f2 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -26,22 +26,22 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/Timeline/packages.lock.json b/Timeline/packages.lock.json index ad9a3a73..24fd30ff 100644 --- a/Timeline/packages.lock.json +++ b/Timeline/packages.lock.json @@ -4,59 +4,60 @@ ".NETCoreApp,Version=v3.1": { "AutoMapper": { "type": "Direct", - "requested": "[9.0.0, )", - "resolved": "9.0.0", - "contentHash": "xCqvoxT4HIrNY/xlXG9W+BA/awdrhWvMTKTK/igkGSRbhOhpl3Q8O8Gxlhzjc9JsYqE7sS6AxgyuUUvZ6R5/Bw==", + "requested": "[10.0.0, )", + "resolved": "10.0.0", + "contentHash": "T09NoqMZBqw0/JEauXulxnmmerl0Zj03e0r6VCcJ0LURWBIaYxZPPoiDv8bHf5Y4x2xcXJp4JPXoCaeOMJfHEA==", "dependencies": { - "Microsoft.CSharp": "4.5.0", - "System.Reflection.Emit": "4.3.0" + "Microsoft.CSharp": "4.7.0", + "System.Reflection.Emit": "4.7.0" } }, "AutoMapper.Extensions.Microsoft.DependencyInjection": { "type": "Direct", - "requested": "[7.0.0, )", - "resolved": "7.0.0", - "contentHash": "szI4yeRIM7GWe9JyekW0dKYehPB0t6M+I55fPeCebN6PhS7zQZa0eG3bgOnOx+eP3caSNoE7KEJs2rk7MLsh8w==", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "hhUzmc8Ld7wCuVHJFodsxtPmFqBAhB6nUNQUgaMF3uamQdxOLxntG0dwv+5ApC67GABa8Oay8MEYGg5IgVZP1Q==", "dependencies": { - "AutoMapper": "9.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0" + "AutoMapper": "[10.0.0, 11.0.0)", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.0.0", + "Microsoft.Extensions.Options": "3.0.0" } }, "Microsoft.AspNetCore.SpaServices.Extensions": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "mWRSFYK+AxBMuB+PMIMaB9E2QaXaaiwMYhfavPLPZ8VolKIEeJsfcrBhtgAKroaLblkJL7zQJFIEZL0KGoWaYw==", + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "avSGyrRPLaRbVdbEKDANRw7KGwZ2g8r/lWSlhELeGlWhuz99LMet8cpsXJeqq2hWcwJ2ZmnL7StNn6tCGJtukA==", "dependencies": { - "Microsoft.AspNetCore.SpaServices": "3.1.5", - "Microsoft.Extensions.FileProviders.Physical": "3.1.5" + "Microsoft.AspNetCore.SpaServices": "3.1.7", + "Microsoft.Extensions.FileProviders.Physical": "3.1.7" } }, "Microsoft.CodeAnalysis.FxCopAnalyzers": { "type": "Direct", - "requested": "[3.0.0, )", - "resolved": "3.0.0", - "contentHash": "ea8bbNa4fzS/s55AUCAvYjb6Y3lFysFVfEwt9zIwR/NeFpOcUluIleOXSUPAyUtwBFugn01aWvNfMVmIwnvgqQ==", + "requested": "[3.3.0, )", + "resolved": "3.3.0", + "contentHash": "k3Icqx8kc+NrHImuiB8Jc/wd32Xeyd2B/7HOR5Qu9pyKzXQ4ikPeBAwzG2FSTuYhyIuNWvwL5k9yYBbbVz6w9w==", "dependencies": { - "Microsoft.CodeAnalysis.VersionCheckAnalyzer": "[3.0.0]", - "Microsoft.CodeQuality.Analyzers": "[3.0.0]", - "Microsoft.NetCore.Analyzers": "[3.0.0]", - "Microsoft.NetFramework.Analyzers": "[3.0.0]" + "Microsoft.CodeAnalysis.VersionCheckAnalyzer": "[3.3.0]", + "Microsoft.CodeQuality.Analyzers": "[3.3.0]", + "Microsoft.NetCore.Analyzers": "[3.3.0]", + "Microsoft.NetFramework.Analyzers": "[3.3.0]" } }, "Microsoft.EntityFrameworkCore": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "1jYVmK8dMKGhtMMrtw0hicRjAJq8hnFSuXHdJTIGa04UVWFvsMFwWsdO3Y1ziCLgR2xM7u5AgUcFLGbV0t9cOg==", + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "u0MXvEkUwXd/JPzuWcSn4Bvx65FrDsn0GJV/tN4kjoZdVcKkXgbDG+RZM9BMGgK77NXmhx9Osy35fujmS3otyA==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "1.1.1", "Microsoft.Bcl.HashCode": "1.1.0", - "Microsoft.EntityFrameworkCore.Abstractions": "3.1.5", - "Microsoft.EntityFrameworkCore.Analyzers": "3.1.5", - "Microsoft.Extensions.Caching.Memory": "3.1.5", - "Microsoft.Extensions.DependencyInjection": "3.1.5", - "Microsoft.Extensions.Logging": "3.1.5", + "Microsoft.EntityFrameworkCore.Abstractions": "3.1.7", + "Microsoft.EntityFrameworkCore.Analyzers": "3.1.7", + "Microsoft.Extensions.Caching.Memory": "3.1.7", + "Microsoft.Extensions.DependencyInjection": "3.1.7", + "Microsoft.Extensions.Logging": "3.1.7", "System.Collections.Immutable": "1.7.1", "System.ComponentModel.Annotations": "4.7.0", "System.Diagnostics.DiagnosticSource": "4.7.1" @@ -64,60 +65,60 @@ }, "Microsoft.EntityFrameworkCore.Analyzers": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "NhxlI6Qj/QUt79ApeBrpKo+a5TGt/UCddxd9rLHD7Zd6yLyfkDOMiyu4oPqhnMhpqmzo/gd79tW7BMwIxgEZCw==" + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "zSh3QF/Kz8fdVgyStQ1HYUGFDRqFbUR1UBpfa8tUuB0OutYab9R4aYdjkD8i9w9P5VZyHXqQNglh2cQHBFLtjg==" }, "Microsoft.EntityFrameworkCore.Sqlite": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "HZn8UjdzfrvAK3xoqj65PZKprMXXev6NVNDEe/PAU6dcW1KXuSxU8cg2LB68ltEI1dLx8JaiKF/yWAq7H4pUQQ==", + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "ZLBVThJ/EBAlqXTOb665GeXglEjkZhxikd+FwseNR1B8GuzowrC+cX2TAVd1ryhnpG/4g+RNOajTPDk5dBta7Q==", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite.Core": "3.1.5", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "3.1.7", "SQLitePCLRaw.bundle_e_sqlite3": "2.0.2" } }, "Microsoft.EntityFrameworkCore.Tools": { "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "8vv6M1/HyoQuuvPZ9aL0HycCJdxEWLULMxFA9oRjRLBg70oo4Y2lKt7VpZT/zIOi/BFyq+H25JFT6+S7vYxakQ==", + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "Cc1OQP/mVUAmH3JGeFuhAdtJ7J33Q4U/MvLAh7Of7e+5XUdHb7tJxobjVyr6nxJDZlJvZ38af9xPGzwwSswASw==", "dependencies": { - "Microsoft.EntityFrameworkCore.Design": "3.1.5" + "Microsoft.EntityFrameworkCore.Design": "3.1.7" } }, "SixLabors.ImageSharp": { "type": "Direct", - "requested": "[1.0.0-rc0001, )", - "resolved": "1.0.0-rc0001", - "contentHash": "lxQYvAv8vTp0QD1MafqUP1t8kbwy/2wolqHwymCMeozcfGNnYKNXlLSzwVQRoGXBOVRWgvU4f07hXCNmCLN4Ug==" + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "8amvsk8NXnCxZV0lvJppAZJknViWgBOO/2V59IGR6DVoD13mSmG+/Z9eg5IwrHQuRHp5RD9lfXBXDZyk8rTKDg==" }, "System.IdentityModel.Tokens.Jwt": { "type": "Direct", - "requested": "[6.6.0, )", - "resolved": "6.6.0", - "contentHash": "irSFzRuejokJUb0z/tkHq1x0WCCuk8wtJ85Sql7YaUqSQXPLmKi7zFjVI1UAUX+yANmD673VwN+n64lEq/vW6Q==", + "requested": "[6.7.1, )", + "resolved": "6.7.1", + "contentHash": "sPnRn9dUMYARQC3mAKWpig/7rlrruqJvopKXmGoYAQ1A+xQsT3q5LiwsArkV8Oz/hfiRCLkV9vgi3FQg/mYfrw==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "6.6.0", - "Microsoft.IdentityModel.Tokens": "6.6.0" + "Microsoft.IdentityModel.JsonWebTokens": "6.7.1", + "Microsoft.IdentityModel.Tokens": "6.7.1" } }, "Microsoft.AspNetCore.NodeServices": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "WpDoV45BhN0mhc1+5+k29AKzn6suYfm3HynIYngdgBaS2pdXWZPNY/73m7btxbwqaQHup35oqNBVUGNWK2NMWg==", + "resolved": "3.1.7", + "contentHash": "JrDTykwIAdQBbakPMHbbyh6tPJdcQmza+RBKrCK6Dtyk3HL6lqcLIL739WVqrwU21Py3WZtqYwNmn+5yvrYung==", "dependencies": { - "Microsoft.Extensions.Logging.Console": "3.1.5", + "Microsoft.Extensions.Logging.Console": "3.1.7", "Newtonsoft.Json": "12.0.2" } }, "Microsoft.AspNetCore.SpaServices": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "DE34f2Ne92p++7vnONcz869p+yKuHjWjBzfZj7ny2wFSwABzpb98l/x41MYB3zndQW322C5wPmnJbh3P2+AhRg==", + "resolved": "3.1.7", + "contentHash": "BOkdx8FChFq9l3ZJqSirp6iuhtTeKjCYcvxFT32lQGeNOU594NnV8XU3f13aSGUhI/6AsqMPwuliWlUA2RpSSg==", "dependencies": { - "Microsoft.AspNetCore.NodeServices": "3.1.5" + "Microsoft.AspNetCore.NodeServices": "3.1.7" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -132,13 +133,13 @@ }, "Microsoft.CodeAnalysis.VersionCheckAnalyzer": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "RL9OdvWLhtQXcvxK2EPbXM9LandLcDG14Ndz5baVH2aiyvEB11VrHfrzLNoEE5B2/zhRGqN+BHsBg21f75wG9g==" + "resolved": "3.3.0", + "contentHash": "xjLM3DRFZMan3nQyBQEM1mBw6VqQybi4iMJhMFW6Ic1E1GCvqJR3ABOwEL7WtQjDUzxyrGld9bASnAos7G/Xyg==" }, "Microsoft.CodeQuality.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "pOROTgdPa+15sYfEMvDlWlDEedCO1SuRLrRjX36Ltli3SmhZawC2Vgws4crz1XMs9WRzBo8WIJM5WRzGNsOSmQ==" + "resolved": "3.3.0", + "contentHash": "zZ3miq6u22UFQKhfJyLnVEJ+DgeOopLh3eKJnKAcOetPP2hiv3wa7kHZlBDeTvtqJQiAQhAVbttket8XxjN1zw==" }, "Microsoft.CSharp": { "type": "Transitive", @@ -147,238 +148,228 @@ }, "Microsoft.Data.Sqlite.Core": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "97AVbafsZQVale8l04QmrOa1fEo8eCQ4oMK1XxdKc8JVYY4r9nMiYZiNwEDa9VHVY/Hug9YIawghzg6o+0E+fw==", + "resolved": "3.1.7", + "contentHash": "NpX0Ni0ZYxbWXtTxVfFnHR7i/+dCX+BayFSPjH8rCEv5NZXtndKyR0Gh3xl5jpuhv4m1eZr8njq+sV2fNREPjw==", "dependencies": { "SQLitePCLRaw.core": "2.0.2" } }, "Microsoft.DotNet.PlatformAbstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2jxam7bgOxELzk8m8iwRg+e42x7G6WigtWCk6d9MXQEiZSl5FZMGpEk/8AXvl4ybogu1OgBkT5G+g94O9/lelQ==" + "resolved": "3.1.3", + "contentHash": "bwD01wYeN+g+Yib7XXahbRdvh5lj6PJ0si6TO6kP7n+fQsBxGy18ewJLjTZUxCwWJqX39WfQHM6idtE4QuVaiw==" }, "Microsoft.EntityFrameworkCore.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "xZ3mUVu22p2h0ZKTWgoyK9YjA2H11cJcZssDcZYs8iLUVHPxMcb+ITOKpMdnV6SkEiQQ5pvjPXQ5J7VxiGSwDw==" + "resolved": "3.1.7", + "contentHash": "Dx2aGjTKPq49nMYl8t9Lq9XgZJOSIsIQE7lOCThVyHHAYgZrkc8NRgzE/PLGfUO4tfyNSImkXlyF98DBAXI5fw==" }, "Microsoft.EntityFrameworkCore.Design": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "Bo5IVeCueESgeADKth/w9+IIwhMb1FgNrgB/egnHoTudnoZFffxPo/HVp8R5uyDIkBkEkfD7pTLy5szMyc8c1w==", + "resolved": "3.1.7", + "contentHash": "gSRNa758T3dCqg5JUvOMMfDxx1Y8oFipf6t2bMg8KDpNyzVfp2YmjUsdQHDDIjiG4X8m3jkkykQPqBS0GsJD/A==", "dependencies": { "Microsoft.CSharp": "4.7.0", - "Microsoft.EntityFrameworkCore.Relational": "3.1.5" + "Microsoft.EntityFrameworkCore.Relational": "3.1.7" } }, "Microsoft.EntityFrameworkCore.Relational": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "MNWF77Ekiu7Fe9BhgpwNft6MW0x5T+r7B43A/jtnEH+fQTjrfJrjBDgm+klxrQhha/8Jr/GxkRHmptXws0AAfA==", + "resolved": "3.1.7", + "contentHash": "XLzwdgHPq5QgcmPZkkAso+SSW/tQqPD/iGaZv+fhl7lCb7VTPsjGE0BiPG9xiUP7OR+tlKNDffSzKimElZMaqA==", "dependencies": { - "Microsoft.EntityFrameworkCore": "3.1.5" + "Microsoft.EntityFrameworkCore": "3.1.7" } }, "Microsoft.EntityFrameworkCore.Sqlite.Core": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "Rb9It33lD2x6ODF4i0M3quadEPJOEHsANSNqctBnUnLbZX8HshGmEml3jQZELpJ1lhV0aEuATrFLDWT8EUdbiQ==", + "resolved": "3.1.7", + "contentHash": "jOViumARQZ84Ya/j+gKgtjwBa9D5iKsbPWuLy2Z/fVvkpfuTwfiRjIoxe0y+ta8iec9FpEQ+Q2r13hzSdXSfEQ==", "dependencies": { - "Microsoft.Data.Sqlite.Core": "3.1.5", - "Microsoft.DotNet.PlatformAbstractions": "3.1.5", - "Microsoft.EntityFrameworkCore.Relational": "3.1.5", - "Microsoft.Extensions.DependencyModel": "3.1.5" + "Microsoft.Data.Sqlite.Core": "3.1.7", + "Microsoft.DotNet.PlatformAbstractions": "3.1.3", + "Microsoft.EntityFrameworkCore.Relational": "3.1.7", + "Microsoft.Extensions.DependencyModel": "3.1.3" } }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "1HWdvlBNI4laVkx5oglv3Oaz5s8dO/dpkOep8FLv7+QAK2rm3ofBVv49aiDnijnwO+ZPJ/0iNctZWP0W2S07Rw==", + "resolved": "3.1.7", + "contentHash": "Uj/0fmq7FWi7B7RfLkn2UJE1SThJ60mOlChx9P5nRjP/EbeYNm+LoyiOr6yPhDsArwHttKyun18TXXJ2C9EE/g==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Caching.Memory": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "tqnVZ/tyXiBAEeLtcTvyb/poVp/gn6bbpdr12SAbO4TcfNkd1eNCEbyyABo0qhiQh6vVwba41aixklElx4grdw==", + "resolved": "3.1.7", + "contentHash": "EvNcJWk0KKSqyXefiUTgF5D94r40rmmtAvo5/yhy7u5/CtRjqyN7wQBSKz2ezWlu5vbuMGyaMktANgkk4kEkaw==", "dependencies": { - "Microsoft.Extensions.Caching.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Caching.Abstractions": "3.1.7", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Logging.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Configuration": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LZfdAP8flK4hkaniUv6TlstDX9FXLmJMX1A4mpLghAsZxTaJIgf+nzBNiPRdy/B5Vrs74gRONX3JrIUJQrebmA==", + "resolved": "3.1.7", + "contentHash": "JCVsQYNZNGeLXWMw6tkCZ8Wa2IQKF9AiLKeq9Ff2XvGJTMzhYEHAzF/FvHdeBBhPiOf+Kl1t6mdcHL93kUz6MA==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7" } }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", + "resolved": "3.1.7", + "contentHash": "WJEbrrIgly95D9rM8Gwr4w8sbYla6/iOcCZ0UE7+Qg/Q8NnQJwAJ60Lq1A26zbNE8Fm1fkbGU90LDl8e+BoRSQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZR/zjBxkvdnnWhRoBHDT95uz1ZgJFhv1QazmKCIcDqy/RXqi+6dJ/PfxDhEnzPvk9HbkcGfFsPEu1vSIyxDqBQ==", + "resolved": "3.1.7", + "contentHash": "FYQ64i7DwYO6XDdOFi+VkoRDDzel570I+X/vTYt6mVJWNj1SAstXwZ71P5d6P2Cei+cT950NiScOwj4F8EUeTA==", "dependencies": { - "Microsoft.Extensions.Configuration": "3.1.5" + "Microsoft.Extensions.Configuration": "3.1.7" } }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+RTJQi7TtenIHZqL2zr6523PYXfL88Ruu4UIVmspIxdw14GHd8zZ+2dGLSdwX7fn41Hth4d42S1e1iHWVOJyQ==", + "resolved": "3.1.7", + "contentHash": "yp38AFc5tJQZkjINjXBcxq+dANU06lo27D84duitZthtRPsgKJL87uf9RWRsDdRsWd+kXflmdMWFLKFjyKx6Pw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" + "resolved": "3.1.7", + "contentHash": "oKL2yNtTN1/cOp+cbdyv5TeLzO+GkO9B3fvbcPzKWTNCkDoH3ccYS3FWC1p4KSYe9frW4WsyfSTeM8X+xftOig==" }, "Microsoft.Extensions.DependencyModel": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "u1RWQS0ym1USOoRji6MKcka/F/Br18/+1kiUvAcqWeG7v95SejSBXWRuS5eFfk6gCr3ppRxYyfnwUpmXa91ZsA==", + "resolved": "3.1.3", + "contentHash": "NrcgRhryflmjz16bwr2krbQyhMstOhRi6dD39KEhUGRKVdXEKOppVVOOelxchIFVfNUGs5SEvcAm+binU09S3g==", "dependencies": { - "System.Text.Json": "4.7.2" + "System.Text.Json": "4.7.1" } }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", + "resolved": "3.1.7", + "contentHash": "nasMSdDlIIBcKgGVHoZdFSmfUY1bI0zkvfZTsWLlEFcMCVD0fzcgsVlkeZTzPLJV0w7Uwq3okOgMWpU1nFEhxg==", "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "JemaaSSQosZ59flEfNzqvQRHDt1u4aEwV/pR4eFQEXpaX7lHI13gSbQbQ7TMGDdmY9F2t2+6RPp44Mmf9O1DsQ==", + "resolved": "3.1.7", + "contentHash": "mo21yJfL3oGCjC/rcwdbs2z4KGL9R5BvTfwYR31ueyg3l77i9oPCryMtlSZ4TvpI5duENNEpZyzcpaycqERdZQ==", "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.FileSystemGlobbing": "3.1.5" + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.7", + "Microsoft.Extensions.FileSystemGlobbing": "3.1.7" } }, "Microsoft.Extensions.FileSystemGlobbing": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ObdbZ/L3X89KOHI0K/zlwufnlHESYSp2L/Z1XgYp3Odekmzevl06iffrtIBP9Qgw2RxBVAyTEVNrIouCuik6yg==" + "resolved": "3.1.7", + "contentHash": "Cenv9mtZdSZ9u09rGYl3ejMB19gIOdRryXk/rYEzQsyrBTTuNzmRHwtHdy640P08DL1Rdu+0z/s2lpvFbZV8Hw==" }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "C85NYDym6xy03o70vxX+VQ4ZEjj5Eg5t5QoGW0t100vG5MmPL6+G3XXcQjIIn1WRQrjzGWzQwuKf38fxXEWIWA==", + "resolved": "3.1.7", + "contentHash": "p68Hvr8S+t+bGUeXRX6wcjlkK961w0YRXWy8O6pkTsucdNpnzB8mwLIgcnQ7oj0biw8S1Ftv4PREzPIwo1UwpA==", "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "3.1.5", - "Microsoft.Extensions.DependencyInjection": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Configuration.Binder": "3.1.7", + "Microsoft.Extensions.DependencyInjection": "3.1.7", + "Microsoft.Extensions.Logging.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" + "resolved": "3.1.7", + "contentHash": "oD7LQbMuaqq/yAz8PKX0hl4+H/vDFTQHo8rxbKB36P1/bG8FG7JUVKBoHkSt1MaJUtgyiHrH1AlAhaucKUKyEg==" }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+9jx/A9cLdkTmynKMa2oR4rYAfe3n2F/wNVvKxwIk2J33paEU13Se08Q5xvQisqfbumaRUNF7BWHr63JzuuRw==", + "resolved": "3.1.7", + "contentHash": "lfV0JUsVb/AyYWoZpsn2vmJe+C1hO34FlPh1YDNIpgHbpmK4IbQpGkcjQ2MPyFohJUHmscB9tST5J3xfTYIQEQ==", "dependencies": { - "Microsoft.Extensions.Logging": "3.1.5", - "Microsoft.Extensions.Options.ConfigurationExtensions": "3.1.5" + "Microsoft.Extensions.Logging": "3.1.7", + "Microsoft.Extensions.Options.ConfigurationExtensions": "3.1.7" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "c/W7d9sjgyU0/3txj/i6pC+8f25Jbua7zKhHVHidC5hHL4OX8fAxSGPBWYOsRN4tXqpd5VphNmIFUWyT12fMoA==", + "resolved": "3.1.7", + "contentHash": "rbFWSXzxP9eMzEiFJsOgxc7I8Wy+gJjkl2ROR3KHD0mCQzBjnJ1VR4Dsu5k1AIThwPbC+WoOzMjqNe0Jwxvwpg==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging": "3.1.5", - "Microsoft.Extensions.Logging.Configuration": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7", + "Microsoft.Extensions.Logging": "3.1.7", + "Microsoft.Extensions.Logging.Configuration": "3.1.7" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", + "resolved": "3.1.7", + "contentHash": "O5TXu1D79hbaZuKCIK4mswSP86MtmiIQjuOZnVhPdbjOVILsoQwZUtnmU2xRfX1E0QWuFEI0umhw3mDDn6dNHw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Primitives": "3.1.7" } }, "Microsoft.Extensions.Options.ConfigurationExtensions": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "mgM+JHFeRg3zSRjScVADU/mohY8s0czKRTNT9oszWgX1mlw419yqP6ITCXovPopMXiqzRdkZ7AEuErX9K+ROww==", + "resolved": "3.1.7", + "contentHash": "VYW5bmNoNM852QmWvlPS1iktEZ4loGCfcoP0/UASpsjOZejGAvk0XTRdwh1DFv6AvWT0NYitdbx4y3Sqigr42g==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.Configuration.Binder": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.7", + "Microsoft.Extensions.Configuration.Binder": "3.1.7", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.7", + "Microsoft.Extensions.Options": "3.1.7" } }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" + "resolved": "3.1.7", + "contentHash": "sa17s3vDAXTuIVGxuJcK713i0B0iaUoiwY4Sl2SLHhMqM8snznn0YVGiZAVkoKEUFWjvIg1Z/JNmAicBamI4mg==" }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "ZhzG2+nxbGDJ67vY0e9kuJEtPpA53EhkhXpLWlBOUzEGd085ojJT3XPLK74mC+mjsXpZqWj5pHtgbB77gSqJeg==", + "resolved": "6.7.1", + "contentHash": "q/Ii8ILV8cM1X49gnl12cJK+0KWiI1xUeiLYiE9+uRonJLaHWB0l8t89rGnZTEGthGKItyikKSB38LQpfy/zBw==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "6.6.0" + "Microsoft.IdentityModel.Tokens": "6.7.1" } }, "Microsoft.IdentityModel.Logging": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "OWfHX7bXKTEBXcD9b+0Tx7dWBaqF4wht7RmS6q+9vAXHiNpRG/wkoFKhOp1Yus0Xd1xAXXHSkAKxgmn/SRD1KA==" + "resolved": "6.7.1", + "contentHash": "WGtTiTy2ZikOz/I5GxCGbNPLOpyI9fPyuyG4Q5rfkhACK+Q0Ad6U8XajYZ2cJ2cFKse0IvHwm15HVrfwrX/89g==" }, "Microsoft.IdentityModel.Tokens": { "type": "Transitive", - "resolved": "6.6.0", - "contentHash": "fNfhlY7AEB9y/jooK6xI1vH+7rmq7c2kTEk7j/5SSy25iHRB1twrG8+He9sHxBQqIXhrQliMEwi4GXZInzO4ww==", + "resolved": "6.7.1", + "contentHash": "Td9Vn9d/0eM1zlUUvaVQzjqdBkBLJ2oGtGL/LYPuiCUAALMeAHVDtpXGk8eYI8Gbduz5n+o7ifldsCIca4MWew==", "dependencies": { "Microsoft.CSharp": "4.5.0", - "Microsoft.IdentityModel.Logging": "6.6.0", + "Microsoft.IdentityModel.Logging": "6.7.1", "System.Security.Cryptography.Cng": "4.5.0" } }, "Microsoft.NetCore.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "JdjhkobYjmQAu4JpsEALDAr7xig2pzXMsXGilHJ2gvmUaUSBjYObw53CBaIkRXmPu0DaDPN8ze9LCtsRd1R8UA==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Microsoft.NETCore.Targets": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + "resolved": "3.3.0", + "contentHash": "6qptTHUu1Wfszuf83NhU0IoAb4j7YWOpJs6oc6S4G/nI6aGGWKH/Xi5Vs9L/8lrI74ijEEzPcIwafSQW5ASHtA==" }, "Microsoft.NetFramework.Analyzers": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "Q0sB3JYld9JMa9/HKtioIxhqmOohEku1FkfSC/uf0usGcCIhm6GYWU565klP64jC2kzmjFIu/6fkHEIYRqZCQQ==" + "resolved": "3.3.0", + "contentHash": "JTfMic5fEFWICePbr7GXOGPranqS9Qxu2U/BZEcnnGbK1SFW8TxRyGp6O1L52xsbfOdqmzjc0t5ubhDrjj+Xpg==" }, "Newtonsoft.Json": { "type": "Transitive", @@ -431,105 +422,25 @@ "resolved": "4.7.1", "contentHash": "j81Lovt90PDAq8kLpaJfJKV/rWdWuEk6jfV+MBkee33vzYLEUsy4gXK8laa9V2nZlLM9VM9yA/OOQxxPEJKAMw==" }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, "System.Memory": { "type": "Transitive", "resolved": "4.5.3", "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==" }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, "System.Reflection.Emit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.ILGeneration": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } + "resolved": "4.7.0", + "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" }, "System.Security.Cryptography.Cng": { "type": "Transitive", "resolved": "4.5.0", "contentHash": "WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==" }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, "System.Text.Json": { "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "TcMd95wcrubm9nHvJEQs70rC0H/8omiSGGpU4FQ/ZA1URIqD4pjmFJh2Mfv1yH1eHgJDWTi2hMDXwTET+zOOyg==" - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.1", + "contentHash": "XwzMbct3iNepJaFylN1+l8weWlFburEzXidqleSsLvSXdHSIJHEKtRVKHPlpWcFmJX6k3goPFfVgUfp40RR+bg==" }, "timeline.errorcodes": { "type": "Project" -- cgit v1.2.3 From 32fdf425e6b4f4edfb727fb3c0cbebe2c87fd663 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 20 Aug 2020 00:39:09 +0800 Subject: ... --- Timeline.Tests/packages.lock.json | 437 ++++++++++++ Timeline/Controllers/TokenController.cs | 20 + Timeline/Controllers/UserController.cs | 59 ++ Timeline/Models/Http/Common.cs | 11 + Timeline/Models/Http/TokenController.cs | 38 +- Timeline/Models/Http/UserController.cs | 47 ++ Timeline/Startup.cs | 22 + Timeline/Timeline.csproj | 4 + Timeline/packages.lock.json | 1113 +++++++++++++++++++++++++++++++ 9 files changed, 1747 insertions(+), 4 deletions(-) diff --git a/Timeline.Tests/packages.lock.json b/Timeline.Tests/packages.lock.json index c01f13c8..18d2d3ff 100644 --- a/Timeline.Tests/packages.lock.json +++ b/Timeline.Tests/packages.lock.json @@ -127,6 +127,162 @@ "System.Xml.XmlDocument": "4.3.0" } }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "E+awj6d91bTe6uOGZdiWl0KL9VCr2Deq6Av3Ip/t0HT2zgF+KI8z4AtFNOSc14mumpulbC5lLthfyw/n+P2OFg==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.Options": "1.0.2", + "System.Security.Claims": "4.0.1" + } + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "CSVd9h1TdWDT2lt62C4FcgaF285J4O3MaOqTVvc7xP+3bFiwXcdp6qEd+u1CQrdJ+xJuslR+tvDW7vWQ/OH5Qw==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.Extensions.Configuration.Abstractions": "1.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "6ZtFh0huTlrUl72u9Vic0icCVIQiEx7ULFDx3P7BpOI97wjb0GAXf8B4m9uSpSGf0vqLEKFlkPbvXF0MXXEzhw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "1.0.2", + "Microsoft.Extensions.Configuration.Abstractions": "1.0.2" + } + }, + "Microsoft.AspNetCore.Http": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "w9AJMakVIuP0KhLe3pdwWNDSWhwDEjfRyai907iGmia0a5O3OBJw9JMhpenVHHeXAARwLi/zVn9oVwd1RFKzTA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.AspNetCore.WebUtilities": "1.0.2", + "Microsoft.Extensions.ObjectPool": "1.0.1", + "Microsoft.Extensions.Options": "1.0.2", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.Buffers": "4.0.0", + "System.Threading": "4.0.11" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "peJqc7BgYwhTzOIfFHX3/esV6iOXf17Afekh6mCYuUD3aWyaBwQuWYaKLR+RnjBEWaSzpCDgfCMMp5Y3LUXsiA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "1.0.2", + "System.Globalization.Extensions": "4.0.1", + "System.Linq.Expressions": "4.1.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encodings.Web": "4.0.0" + } + }, + "Microsoft.AspNetCore.Http.Extensions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "itaTI4YSVsLjvmpInhQ3b6Xs1q+CxJT/3z3q5G6hLuLkq30vvWEbM40NfzUzvwzPCEiXXlp+nJTEK2wgoJa70Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.Buffers": "4.0.0", + "System.IO.FileSystem": "4.0.1" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "9l/Y/CO3q8tET3w+dDiByREH8lRtpd14cMevwMV5nw2a/avJ5qcE3VVIE5U5hesec2phTT6udQEgwjHmdRRbig==", + "dependencies": { + "Microsoft.Extensions.Primitives": "1.0.1", + "System.Collections": "4.0.11", + "System.ComponentModel": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebSockets": "4.0.0", + "System.Runtime.Extensions": "4.1.0", + "System.Security.Claims": "4.0.1", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Security.Principal": "4.0.1" + } + }, + "Microsoft.AspNetCore.JsonPatch": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "WVaSVS+dDlWCR/qerHnBxU9tIeJ9GMA3M5tg4cxH7/cJYZZLnr2zvaFHGB+cRRNCKKTJ0pFRxT7ES8knhgAAaA==", + "dependencies": { + "Microsoft.CSharp": "4.0.1", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Concurrent": "4.0.12", + "System.ComponentModel.TypeConverter": "4.1.0", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.Abstractions": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "/Tpjl8AjEDksvyXfmFOlEGktwcpcToJ2aYwz2SAyeolv48e6gUyjpQWPBZkfovws9jPBdEyDY3eCZMDl7tVJPw==", + "dependencies": { + "Microsoft.AspNetCore.Routing.Abstractions": "1.0.3", + "Microsoft.CSharp": "4.0.1", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.ComponentModel.TypeConverter": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.ApiExplorer": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ioZUf1h3Hqy6UQ44bv88dRsKqe5Ys+DgFuou1VqxtLh2uRgUgD52r+yaLvUPFETdPVbHuemqj4ijqRb1r2Bbkw==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "1.0.3" + } + }, + "Microsoft.AspNetCore.Mvc.Core": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "G1iwAcUj6gayPUxcflYXlVGjRn36s8GC7tjxxhxCSVyeYYS0WjO6TFAuXIm6Oe3S2IAQeCAn+Phg5gasHJLUxg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "1.0.2", + "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http": "1.0.2", + "Microsoft.AspNetCore.Mvc.Abstractions": "1.0.3", + "Microsoft.AspNetCore.Routing": "1.0.3", + "Microsoft.Extensions.DependencyModel": "1.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0", + "System.Buffers": "4.0.0", + "System.Diagnostics.DiagnosticSource": "4.0.0", + "System.Text.Encoding": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.Formatters.Json": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "zKRSlE7rlqvlVbcUROI9OigUN+PsGwI13VFSuuRKQyeCqqnV/7cPvHT38BoCED1U+vzauBTKSrhGMxWIvSMS0Q==", + "dependencies": { + "Microsoft.AspNetCore.JsonPatch": "1.0.0", + "Microsoft.AspNetCore.Mvc.Core": "1.0.3" + } + }, "Microsoft.AspNetCore.NodeServices": { "type": "Transitive", "resolved": "3.1.7", @@ -136,6 +292,31 @@ "Newtonsoft.Json": "12.0.2" } }, + "Microsoft.AspNetCore.Routing": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "4cK6TNmjRtr2/Eyd3j9R5ZCiwkSffazCn87zqiHV6tVquESkrsB+qQZzNy+qVBv16zooE6tIXisi5kf8lLxJbg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "1.0.2", + "Microsoft.AspNetCore.Routing.Abstractions": "1.0.3", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.ObjectPool": "1.0.1", + "Microsoft.Extensions.Options": "1.0.2", + "System.Collections": "4.0.11", + "System.Text.RegularExpressions": "4.1.0" + } + }, + "Microsoft.AspNetCore.Routing.Abstractions": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "bNcJAJPSLhvpwbdRfqh3b23Pi36gycUxCxjV4zxVoIwLt/qQFY3g+YJ08UJWPhAHepdne0xWe1WGr3lmYfdwVA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "System.Collections.Concurrent": "4.0.12", + "System.Reflection.Extensions": "4.0.1", + "System.Threading.Tasks": "4.0.11" + } + }, "Microsoft.AspNetCore.SpaServices": { "type": "Transitive", "resolved": "3.1.7", @@ -153,6 +334,31 @@ "Microsoft.Extensions.FileProviders.Physical": "3.1.7" } }, + "Microsoft.AspNetCore.StaticFiles": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "x3uWPBrsDPL5tNQ2vB2EbCyS36aNQ4nT+t4W73is9tUOrwWWkPmSsW+tg8ZtgTPj2lhlRY9fyKDelaifs6+T+A==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http.Extensions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.WebEncoders": "1.0.2" + } + }, + "Microsoft.AspNetCore.WebUtilities": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "xWCqsnZLt0nSoiyw3x250k7PzV/ub1dtjZfLUCy89gTdAHF3jWivnzN+Mw5+LB8EYwEA4WY+u5l5s6innImJTw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "1.0.1", + "System.Buffers": "4.0.0", + "System.Collections": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.Text.Encodings.Web": "4.0.0" + } + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.1", @@ -251,6 +457,11 @@ "Microsoft.Extensions.DependencyModel": "3.1.3" } }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LH4OE/76F6sOCslif7+Xh3fS/wUUrE5ryeXAMcoCnuwOQGT5Smw0p57IgDh/pHgHaGz/e+AmEQb7pRgb++wt0w==" + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "3.1.7", @@ -323,6 +534,15 @@ "Microsoft.Extensions.Primitives": "3.1.7" } }, + "Microsoft.Extensions.FileProviders.Embedded": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "nSEa8bH3fVdTYGqK4twOKLxxgKIW3cz9g9mrzhPh/CmdvGJWKRTIlBIZi7lz+lqNQpxean5vbAo84R/mU+JpGA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "System.Runtime.Extensions": "4.1.0" + } + }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", "resolved": "3.1.7", @@ -372,6 +592,17 @@ "Microsoft.Extensions.Logging.Configuration": "3.1.7" } }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "pJMOnxuqmG37OjccfvtqVoo3bQGoN+0EJUzzp7+2uxSdioER82caAk6Yi/z5aysapn5XENNIIa7SaYnYKSS69A==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, "Microsoft.Extensions.Options": { "type": "Transitive", "resolved": "3.1.7", @@ -392,11 +623,34 @@ "Microsoft.Extensions.Options": "3.1.7" } }, + "Microsoft.Extensions.PlatformAbstractions": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "zyjUzrOmuevOAJpIo3Mt5GmpALVYCVdLZ99keMbmCxxgQH7oxzU58kGHzE6hAgYEiWsdfMJLjVR7r+vSmaJmtg==", + "dependencies": { + "System.AppContext": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0" + } + }, "Microsoft.Extensions.Primitives": { "type": "Transitive", "resolved": "3.1.7", "contentHash": "sa17s3vDAXTuIVGxuJcK713i0B0iaUoiwY4Sl2SLHhMqM8snznn0YVGiZAVkoKEUFWjvIg1Z/JNmAicBamI4mg==" }, + "Microsoft.Extensions.WebEncoders": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "KX+im5FUfsIOfSlgKMxeblkVg8Ry5GbsUocNcVHTWL1dIkR9x0gChQnppKF/QsX5VEs+Y07CvpfsRK0oAkDhaw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.2", + "Microsoft.Extensions.Options": "1.0.2", + "System.Text.Encodings.Web": "4.0.0" + } + }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", "resolved": "6.7.1", @@ -420,6 +674,21 @@ "System.Security.Cryptography.Cng": "4.5.0" } }, + "Microsoft.Net.Http.Headers": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "Nym2m4l2kb5jQRl5YlP1nAxneqpRfknFLy5PBKMYiC4kR/gDIQ4fi4rU9u7UdjEXMVgfWDIPpijx9YnSDEbOHw==", + "dependencies": { + "System.Buffers": "4.0.0", + "System.Collections": "4.0.11", + "System.Diagnostics.Contracts": "4.0.1", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Text.Encoding": "4.0.11" + } + }, "Microsoft.NetCore.Analyzers": { "type": "Transitive", "resolved": "3.3.0", @@ -467,6 +736,14 @@ "System.Runtime": "4.3.0" } }, + "Namotion.Reflection": { + "type": "Transitive", + "resolved": "1.0.11", + "contentHash": "NT7/kod+9SCiL3XbCeY5OtohSGtLmclH5YAlWZiual5fhSldhDsrk8kzgSDx45UBOoeBnvmC8HEpAzKwj6grYQ==", + "dependencies": { + "Microsoft.CSharp": "4.3.0" + } + }, "NETStandard.Library": { "type": "Transitive", "resolved": "1.6.1", @@ -532,6 +809,69 @@ "Newtonsoft.Json": "10.0.1" } }, + "NJsonSchema": { + "type": "Transitive", + "resolved": "10.1.24", + "contentHash": "VRuV1Il0w8AJU0/a3/BgjV3F9ZZHTeZNcqKLvOKkRyc/8dB1apNJitS7+TBwdcQzeJeuNx7xEKrK7M7/tIXi9w==", + "dependencies": { + "Namotion.Reflection": "1.0.11", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Annotations": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "qbXMmiWLGs39Wj7RUuJtNAL6mFuBZBEPcSxYGmT2pcI1g3hKO8JfocMDaxWpmJJ0Kb6sePkKHIImtuLDRfOZow==" + }, + "NSwag.AspNetCore": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "p6XtXERfV30gPS3gJuUtvWtBC2avE2mkYjz4U6gDwxxSjQy/2sy+ENcfhGHIIgZF/ou6b516IJV2J15XjrM52Q==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "1.0.3", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.3", + "Microsoft.AspNetCore.StaticFiles": "1.0.2", + "Microsoft.Extensions.ApiDescription.Server": "3.0.0", + "Microsoft.Extensions.FileProviders.Embedded": "1.0.1", + "NSwag.Annotations": "13.7.0", + "NSwag.Core": "13.7.0", + "NSwag.Generation": "13.7.0", + "NSwag.Generation.AspNetCore": "13.7.0", + "System.IO.FileSystem": "4.3.0", + "System.Xml.XPath.XDocument": "4.0.1" + } + }, + "NSwag.Core": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "GWxILGGf0tlbMiyWuYKh3AVGv5Wgv/scTGZaNgg3sEB/b8iX5tCqhLT9kQejacWqifz2WT9c3S5mQk+8bxEu+Q==", + "dependencies": { + "NJsonSchema": "10.1.24", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Generation": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "gXMQnnlIwBDXBt3sOlXemhqCmFROUcuWc5flaJHH7NhholbEEmVlnvkf7tuW/9SoIN1fVTu3qhfpigu15gKj4Q==", + "dependencies": { + "NJsonSchema": "10.1.24", + "NSwag.Core": "13.7.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Generation.AspNetCore": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "5KYhIubkO03l8CkIlEIpa+CNLS49pp5ccnz7//yr1CZbR0CaEmKb1b7Z+b5wmzZMvyEMx1s5u9kJUzBWJ+CobA==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.ApiExplorer": "1.0.3", + "Microsoft.AspNetCore.Mvc.Core": "1.0.3", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.3", + "NJsonSchema": "10.1.24", + "NSwag.Generation": "13.7.0" + } + }, "NuGet.Frameworks": { "type": "Transitive", "resolved": "5.0.0", @@ -824,6 +1164,14 @@ "System.Text.Encoding": "4.3.0" } }, + "System.Diagnostics.Contracts": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "HvQQjy712vnlpPxaloZYkuE78Gn353L0SJLJVeLcNASeg9c4qla2a1Xq8I7B3jZoDzKPtHTkyVO7AZ5tpeQGuA==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, "System.Diagnostics.Debug": { "type": "Transitive", "resolved": "4.3.0", @@ -1115,6 +1463,17 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, "System.ObjectModel": { "type": "Transitive", "resolved": "4.3.0", @@ -1274,6 +1633,29 @@ "System.Runtime.Extensions": "4.3.0" } }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "4Jlp0OgJLS/Voj1kyFP6MJlIYp3crgfH8kNQk2p7+4JYfc1aAmh9PZyAMMbDhuoolGNtux9HqSOazsioRiDvCw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Security.Principal": "4.0.1" + } + }, "System.Security.Cryptography.Algorithms": { "type": "Transitive", "resolved": "4.3.0", @@ -1410,6 +1792,14 @@ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" } }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "On+SKhXY5rzxh/S8wlH1Rm0ogBlu7zyHNxeNBiXauNrhHRXAe9EuX8Yl5IOzLPGU5Z4kLWHMvORDOCG8iu9hww==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1431,6 +1821,20 @@ "System.Text.Encoding": "4.3.0" } }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "TWZnuiJgPDAEEUfobD7njXvSVR2Toz+jvKWds6yL4oSztmKQfnWzucczjzA+6Dv1bktBdY71sZW1YN0X6m9chQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, "System.Text.Json": { "type": "Transitive", "resolved": "4.7.1", @@ -1536,6 +1940,38 @@ "System.Xml.ReaderWriter": "4.3.0" } }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "UWd1H+1IJ9Wlq5nognZ/XJdyj8qPE4XufBUkAW59ijsCPjZkZe0MUzKKJFBr+ZWBe5Wq1u1d5f2CYgE93uH7DA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11" + } + }, + "System.Xml.XPath.XDocument": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "FLhdYJx4331oGovQypQ8JIw2kEmNzCsjVOVYY/16kZTUoquZG85oVn7yUhBE2OZt1yGPSXAL0HTEfzjlbNpM7Q==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XDocument": "4.0.11", + "System.Xml.XPath": "4.0.1" + } + }, "xunit.abstractions": { "type": "Transitive", "resolved": "2.0.3", @@ -1590,6 +2026,7 @@ "Microsoft.EntityFrameworkCore": "3.1.7", "Microsoft.EntityFrameworkCore.Analyzers": "3.1.7", "Microsoft.EntityFrameworkCore.Sqlite": "3.1.7", + "NSwag.AspNetCore": "13.7.0", "SixLabors.ImageSharp": "1.0.0", "System.IdentityModel.Tokens.Jwt": "6.7.1", "Timeline.ErrorCodes": "1.0.0" diff --git a/Timeline/Controllers/TokenController.cs b/Timeline/Controllers/TokenController.cs index cd67225c..7792b318 100644 --- a/Timeline/Controllers/TokenController.cs +++ b/Timeline/Controllers/TokenController.cs @@ -1,5 +1,6 @@ using AutoMapper; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; @@ -13,8 +14,12 @@ using static Timeline.Resources.Controllers.TokenController; namespace Timeline.Controllers { + /// + /// Operation about tokens. + /// [Route("token")] [ApiController] + [ProducesErrorResponseType(typeof(CommonResponse))] public class TokenController : Controller { private readonly IUserTokenManager _userTokenManager; @@ -23,6 +28,7 @@ namespace Timeline.Controllers private readonly IMapper _mapper; + /// public TokenController(IUserTokenManager userTokenManager, ILogger logger, IClock clock, IMapper mapper) { _userTokenManager = userTokenManager; @@ -31,8 +37,15 @@ namespace Timeline.Controllers _mapper = mapper; } + /// + /// Create a new token for a user. + /// + /// Succeed to create token. + /// Error code is 11010101 if user does not exist or password is wrong. [HttpPost("create")] [AllowAnonymous] + [ProducesResponseType(typeof(CreateTokenResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> Create([FromBody] CreateTokenRequest request) { void LogFailure(string reason, Exception? e = null) @@ -75,8 +88,15 @@ namespace Timeline.Controllers } } + /// + /// Verify a token. + /// + /// Token is valid. + /// Error code is 11010201 if token is of bad format (it may not be created by this server). Error code is 11010202 if user does not exist. Error code is 11010203 if token is of old version (user may have changed password). Error code is 11010204 if token is expired. [HttpPost("verify")] [AllowAnonymous] + [ProducesResponseType(typeof(VerifyTokenResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> Verify([FromBody] VerifyTokenRequest request) { void LogFailure(string reason, Exception? e = null, params (string, object?)[] otherProperties) diff --git a/Timeline/Controllers/UserController.cs b/Timeline/Controllers/UserController.cs index 3986bb5b..fa2d37d8 100644 --- a/Timeline/Controllers/UserController.cs +++ b/Timeline/Controllers/UserController.cs @@ -17,7 +17,11 @@ using static Timeline.Resources.Messages; namespace Timeline.Controllers { + /// + /// Operations about users. + /// [ApiController] + [ProducesErrorResponseType(typeof(CommonResponse))] public class UserController : Controller { private readonly ILogger _logger; @@ -25,6 +29,7 @@ namespace Timeline.Controllers private readonly IUserDeleteService _userDeleteService; private readonly IMapper _mapper; + /// public UserController(ILogger logger, IUserService userService, IUserDeleteService userDeleteService, IMapper mapper) { _logger = logger; @@ -35,7 +40,12 @@ namespace Timeline.Controllers private UserInfo ConvertToUserInfo(User user) => _mapper.Map(user); + /// + /// Get all users. + /// + /// The user list. [HttpGet("users")] + [ProducesResponseType(typeof(UserInfo[]), StatusCodes.Status200OK)] public async Task> List() { var users = await _userService.GetUsers(); @@ -43,7 +53,13 @@ namespace Timeline.Controllers return Ok(result); } + /// + /// Get a user info. + /// + /// Username of the user. + /// The user info. [HttpGet("users/{username}")] + [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] public async Task> Get([FromRoute][Username] string username) { try @@ -58,7 +74,20 @@ namespace Timeline.Controllers } } + /// + /// Change a user's property. You have to be administrator in some condition. + /// + /// + /// Username of the user to change. + /// Succeed to change the user and return the new user info. + /// You have not logged in. + /// You are not administrator. + /// The user to change does not exist. [HttpPatch("users/{username}"), Authorize] + [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> Patch([FromBody] UserPatchRequest body, [FromRoute][Username] string username) { if (this.IsAdministrator()) @@ -101,7 +130,17 @@ namespace Timeline.Controllers } } + /// + /// Delete a user and all his related data. You have to be administrator. + /// + /// Username of the user to delete. + /// Succeeded to delete or the user does not exist. + /// You have not logged in. + /// You are not administrator. [HttpDelete("users/{username}"), AdminAuthorize] + [ProducesResponseType(typeof(CommonDeleteResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> Delete([FromRoute][Username] string username) { var delete = await _userDeleteService.DeleteUser(username); @@ -111,7 +150,18 @@ namespace Timeline.Controllers return Ok(CommonDeleteResponse.NotExist()); } + /// + /// Create a new user. You have to be administrator. + /// + /// Succeeded to create a new user and return his user info. + /// Error code is 11020101 if a user with given username already exists. + /// You have not logged in. + /// You are not administrator. [HttpPost("userop/createuser"), AdminAuthorize] + [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> CreateUser([FromBody] CreateUserRequest body) { try @@ -125,7 +175,16 @@ namespace Timeline.Controllers } } + /// + /// Change password with old password. + /// + /// Succeeded to change password. + /// Error code is 11020201 if old password is wrong. + /// You have not logged in. [HttpPost("userop/changepassword"), Authorize] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ChangePassword([FromBody] ChangePasswordRequest request) { try diff --git a/Timeline/Models/Http/Common.cs b/Timeline/Models/Http/Common.cs index a9fc8a79..5fa22c9e 100644 --- a/Timeline/Models/Http/Common.cs +++ b/Timeline/Models/Http/Common.cs @@ -71,25 +71,36 @@ namespace Timeline.Models.Http } } + /// + /// Common response for delete method. + /// public class CommonDeleteResponse : CommonDataResponse { + /// public class ResponseData { + /// public ResponseData() { } + /// public ResponseData(bool delete) { Delete = delete; } + /// + /// True if the entry is deleted. False if the entry does not exist. + /// public bool Delete { get; set; } } + /// public CommonDeleteResponse() { } + /// public CommonDeleteResponse(int code, string message, bool delete) : base(code, message, new ResponseData(delete)) { diff --git a/Timeline/Models/Http/TokenController.cs b/Timeline/Models/Http/TokenController.cs index ea8b59ed..a42c44e5 100644 --- a/Timeline/Models/Http/TokenController.cs +++ b/Timeline/Models/Http/TokenController.cs @@ -1,32 +1,62 @@ using System.ComponentModel.DataAnnotations; +using Timeline.Controllers; namespace Timeline.Models.Http { + /// + /// Request model for . + /// public class CreateTokenRequest { - [Required] + /// + /// The username. + /// public string Username { get; set; } = default!; - [Required] + /// + /// The password. + /// public string Password { get; set; } = default!; - // in days, optional + /// + /// Optional token validation period. In days. If not specified, server will use a default one. + /// [Range(1, 365)] public int? Expire { get; set; } } + /// + /// Response model for . + /// public class CreateTokenResponse { + /// + /// The token created. + /// public string Token { get; set; } = default!; + /// + /// The user owning the token. + /// public UserInfo User { get; set; } = default!; } + /// + /// Request model for . + /// public class VerifyTokenRequest { - [Required] + /// + /// The token to verify. + /// public string Token { get; set; } = default!; } + /// + /// Response model for . + /// public class VerifyTokenResponse { + /// + /// The user owning the token. + /// public UserInfo User { get; set; } = default!; } } diff --git a/Timeline/Models/Http/UserController.cs b/Timeline/Models/Http/UserController.cs index 5ee02a95..ea30a0ea 100644 --- a/Timeline/Models/Http/UserController.cs +++ b/Timeline/Models/Http/UserController.cs @@ -1,48 +1,95 @@ using AutoMapper; using System.ComponentModel.DataAnnotations; +using Timeline.Controllers; using Timeline.Models.Validation; namespace Timeline.Models.Http { + /// + /// Request model for . + /// public class UserPatchRequest { + /// + /// New username. Null if not change. Need to be administrator. + /// [Username] public string? Username { get; set; } + /// + /// New password. Null if not change. Need to be administrator. + /// [MinLength(1)] public string? Password { get; set; } + /// + /// New nickname. Null if not change. Need to be administrator to change other's. + /// [Nickname] public string? Nickname { get; set; } + /// + /// Whether to be administrator. Null if not change. Need to be administrator. + /// public bool? Administrator { get; set; } } + /// + /// Request model for . + /// public class CreateUserRequest { + /// + /// Username of the new user. + /// [Required, Username] public string Username { get; set; } = default!; + /// + /// Password of the new user. + /// [Required, MinLength(1)] public string Password { get; set; } = default!; + /// + /// Whether the new user is administrator. + /// [Required] public bool? Administrator { get; set; } + /// + /// Nickname of the new user. + /// [Nickname] public string? Nickname { get; set; } } + /// + /// Request model for . + /// public class ChangePasswordRequest { + /// + /// Old password. + /// [Required(AllowEmptyStrings = false)] public string OldPassword { get; set; } = default!; + + /// + /// New password. + /// [Required(AllowEmptyStrings = false)] public string NewPassword { get; set; } = default!; } + /// + /// + /// public class UserControllerAutoMapperProfile : Profile { + /// + /// + /// public UserControllerAutoMapperProfile() { CreateMap(MemberList.Source); diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index be2377b9..3e5dd24d 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -7,6 +7,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using NSwag; +using NSwag.Generation.Processors.Security; using System; using System.ComponentModel; using System.Text.Json.Serialization; @@ -95,6 +97,23 @@ namespace Timeline options.UseSqlite($"Data Source={pathProvider.GetDatabaseFilePath()}"); }); + services.AddSwaggerDocument(document => + { + document.DocumentName = "Timeline"; + document.Title = "Timeline REST API Reference"; + document.Version = typeof(Startup).Assembly.GetName().Version?.ToString() ?? "unknown version"; + document.DocumentProcessors.Add( + new SecurityDefinitionAppender("JWT", + new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.ApiKey, + Name = "Authorization", + In = OpenApiSecurityApiKeyLocation.Header, + Description = "Type into the textbox: Bearer {your JWT token}." + })); + document.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); + }); + if (!disableFrontEnd) { if (useMockFrontEnd) @@ -129,6 +148,9 @@ namespace Timeline }); } + app.UseOpenApi(); + app.UseSwaggerUi3(); + app.UseAuthentication(); app.UseAuthorization(); diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index cdd5f1f2..5c2f7adf 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -14,6 +14,9 @@ ClientApp\ $(DefaultItemExcludes);$(SpaRoot)node_modules\** + + 0.3.0 + true @@ -40,6 +43,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Timeline/packages.lock.json b/Timeline/packages.lock.json index 24fd30ff..3afada24 100644 --- a/Timeline/packages.lock.json +++ b/Timeline/packages.lock.json @@ -88,6 +88,25 @@ "Microsoft.EntityFrameworkCore.Design": "3.1.7" } }, + "NSwag.AspNetCore": { + "type": "Direct", + "requested": "[13.7.0, )", + "resolved": "13.7.0", + "contentHash": "p6XtXERfV30gPS3gJuUtvWtBC2avE2mkYjz4U6gDwxxSjQy/2sy+ENcfhGHIIgZF/ou6b516IJV2J15XjrM52Q==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "1.0.3", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.3", + "Microsoft.AspNetCore.StaticFiles": "1.0.2", + "Microsoft.Extensions.ApiDescription.Server": "3.0.0", + "Microsoft.Extensions.FileProviders.Embedded": "1.0.1", + "NSwag.Annotations": "13.7.0", + "NSwag.Core": "13.7.0", + "NSwag.Generation": "13.7.0", + "NSwag.Generation.AspNetCore": "13.7.0", + "System.IO.FileSystem": "4.3.0", + "System.Xml.XPath.XDocument": "4.0.1" + } + }, "SixLabors.ImageSharp": { "type": "Direct", "requested": "[1.0.0, )", @@ -104,6 +123,162 @@ "Microsoft.IdentityModel.Tokens": "6.7.1" } }, + "Microsoft.AspNetCore.Authorization": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "E+awj6d91bTe6uOGZdiWl0KL9VCr2Deq6Av3Ip/t0HT2zgF+KI8z4AtFNOSc14mumpulbC5lLthfyw/n+P2OFg==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.Options": "1.0.2", + "System.Security.Claims": "4.0.1" + } + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "CSVd9h1TdWDT2lt62C4FcgaF285J4O3MaOqTVvc7xP+3bFiwXcdp6qEd+u1CQrdJ+xJuslR+tvDW7vWQ/OH5Qw==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.Extensions.Configuration.Abstractions": "1.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "6ZtFh0huTlrUl72u9Vic0icCVIQiEx7ULFDx3P7BpOI97wjb0GAXf8B4m9uSpSGf0vqLEKFlkPbvXF0MXXEzhw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "1.0.2", + "Microsoft.Extensions.Configuration.Abstractions": "1.0.2" + } + }, + "Microsoft.AspNetCore.Http": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "w9AJMakVIuP0KhLe3pdwWNDSWhwDEjfRyai907iGmia0a5O3OBJw9JMhpenVHHeXAARwLi/zVn9oVwd1RFKzTA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.AspNetCore.WebUtilities": "1.0.2", + "Microsoft.Extensions.ObjectPool": "1.0.1", + "Microsoft.Extensions.Options": "1.0.2", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.Buffers": "4.0.0", + "System.Threading": "4.0.11" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "peJqc7BgYwhTzOIfFHX3/esV6iOXf17Afekh6mCYuUD3aWyaBwQuWYaKLR+RnjBEWaSzpCDgfCMMp5Y3LUXsiA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "1.0.2", + "System.Globalization.Extensions": "4.0.1", + "System.Linq.Expressions": "4.1.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encodings.Web": "4.0.0" + } + }, + "Microsoft.AspNetCore.Http.Extensions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "itaTI4YSVsLjvmpInhQ3b6Xs1q+CxJT/3z3q5G6hLuLkq30vvWEbM40NfzUzvwzPCEiXXlp+nJTEK2wgoJa70Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.Buffers": "4.0.0", + "System.IO.FileSystem": "4.0.1" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "9l/Y/CO3q8tET3w+dDiByREH8lRtpd14cMevwMV5nw2a/avJ5qcE3VVIE5U5hesec2phTT6udQEgwjHmdRRbig==", + "dependencies": { + "Microsoft.Extensions.Primitives": "1.0.1", + "System.Collections": "4.0.11", + "System.ComponentModel": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebSockets": "4.0.0", + "System.Runtime.Extensions": "4.1.0", + "System.Security.Claims": "4.0.1", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Security.Principal": "4.0.1" + } + }, + "Microsoft.AspNetCore.JsonPatch": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "WVaSVS+dDlWCR/qerHnBxU9tIeJ9GMA3M5tg4cxH7/cJYZZLnr2zvaFHGB+cRRNCKKTJ0pFRxT7ES8knhgAAaA==", + "dependencies": { + "Microsoft.CSharp": "4.0.1", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Concurrent": "4.0.12", + "System.ComponentModel.TypeConverter": "4.1.0", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.Abstractions": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "/Tpjl8AjEDksvyXfmFOlEGktwcpcToJ2aYwz2SAyeolv48e6gUyjpQWPBZkfovws9jPBdEyDY3eCZMDl7tVJPw==", + "dependencies": { + "Microsoft.AspNetCore.Routing.Abstractions": "1.0.3", + "Microsoft.CSharp": "4.0.1", + "Microsoft.Net.Http.Headers": "1.0.2", + "System.ComponentModel.TypeConverter": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.ApiExplorer": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ioZUf1h3Hqy6UQ44bv88dRsKqe5Ys+DgFuou1VqxtLh2uRgUgD52r+yaLvUPFETdPVbHuemqj4ijqRb1r2Bbkw==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "1.0.3" + } + }, + "Microsoft.AspNetCore.Mvc.Core": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "G1iwAcUj6gayPUxcflYXlVGjRn36s8GC7tjxxhxCSVyeYYS0WjO6TFAuXIm6Oe3S2IAQeCAn+Phg5gasHJLUxg==", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "1.0.2", + "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http": "1.0.2", + "Microsoft.AspNetCore.Mvc.Abstractions": "1.0.3", + "Microsoft.AspNetCore.Routing": "1.0.3", + "Microsoft.Extensions.DependencyModel": "1.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0", + "System.Buffers": "4.0.0", + "System.Diagnostics.DiagnosticSource": "4.0.0", + "System.Text.Encoding": "4.0.11" + } + }, + "Microsoft.AspNetCore.Mvc.Formatters.Json": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "zKRSlE7rlqvlVbcUROI9OigUN+PsGwI13VFSuuRKQyeCqqnV/7cPvHT38BoCED1U+vzauBTKSrhGMxWIvSMS0Q==", + "dependencies": { + "Microsoft.AspNetCore.JsonPatch": "1.0.0", + "Microsoft.AspNetCore.Mvc.Core": "1.0.3" + } + }, "Microsoft.AspNetCore.NodeServices": { "type": "Transitive", "resolved": "3.1.7", @@ -113,6 +288,31 @@ "Newtonsoft.Json": "12.0.2" } }, + "Microsoft.AspNetCore.Routing": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "4cK6TNmjRtr2/Eyd3j9R5ZCiwkSffazCn87zqiHV6tVquESkrsB+qQZzNy+qVBv16zooE6tIXisi5kf8lLxJbg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "1.0.2", + "Microsoft.AspNetCore.Routing.Abstractions": "1.0.3", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.ObjectPool": "1.0.1", + "Microsoft.Extensions.Options": "1.0.2", + "System.Collections": "4.0.11", + "System.Text.RegularExpressions": "4.1.0" + } + }, + "Microsoft.AspNetCore.Routing.Abstractions": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "bNcJAJPSLhvpwbdRfqh3b23Pi36gycUxCxjV4zxVoIwLt/qQFY3g+YJ08UJWPhAHepdne0xWe1WGr3lmYfdwVA==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "1.0.2", + "System.Collections.Concurrent": "4.0.12", + "System.Reflection.Extensions": "4.0.1", + "System.Threading.Tasks": "4.0.11" + } + }, "Microsoft.AspNetCore.SpaServices": { "type": "Transitive", "resolved": "3.1.7", @@ -121,6 +321,31 @@ "Microsoft.AspNetCore.NodeServices": "3.1.7" } }, + "Microsoft.AspNetCore.StaticFiles": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "x3uWPBrsDPL5tNQ2vB2EbCyS36aNQ4nT+t4W73is9tUOrwWWkPmSsW+tg8ZtgTPj2lhlRY9fyKDelaifs6+T+A==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.2", + "Microsoft.AspNetCore.Http.Extensions": "1.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "Microsoft.Extensions.Logging.Abstractions": "1.0.2", + "Microsoft.Extensions.WebEncoders": "1.0.2" + } + }, + "Microsoft.AspNetCore.WebUtilities": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "xWCqsnZLt0nSoiyw3x250k7PzV/ub1dtjZfLUCy89gTdAHF3jWivnzN+Mw5+LB8EYwEA4WY+u5l5s6innImJTw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "1.0.1", + "System.Buffers": "4.0.0", + "System.Collections": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.Text.Encodings.Web": "4.0.0" + } + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.1", @@ -192,6 +417,11 @@ "Microsoft.Extensions.DependencyModel": "3.1.3" } }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LH4OE/76F6sOCslif7+Xh3fS/wUUrE5ryeXAMcoCnuwOQGT5Smw0p57IgDh/pHgHaGz/e+AmEQb7pRgb++wt0w==" + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "3.1.7", @@ -264,6 +494,15 @@ "Microsoft.Extensions.Primitives": "3.1.7" } }, + "Microsoft.Extensions.FileProviders.Embedded": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "nSEa8bH3fVdTYGqK4twOKLxxgKIW3cz9g9mrzhPh/CmdvGJWKRTIlBIZi7lz+lqNQpxean5vbAo84R/mU+JpGA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.1", + "System.Runtime.Extensions": "4.1.0" + } + }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", "resolved": "3.1.7", @@ -313,6 +552,17 @@ "Microsoft.Extensions.Logging.Configuration": "3.1.7" } }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "pJMOnxuqmG37OjccfvtqVoo3bQGoN+0EJUzzp7+2uxSdioER82caAk6Yi/z5aysapn5XENNIIa7SaYnYKSS69A==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, "Microsoft.Extensions.Options": { "type": "Transitive", "resolved": "3.1.7", @@ -333,11 +583,34 @@ "Microsoft.Extensions.Options": "3.1.7" } }, + "Microsoft.Extensions.PlatformAbstractions": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "zyjUzrOmuevOAJpIo3Mt5GmpALVYCVdLZ99keMbmCxxgQH7oxzU58kGHzE6hAgYEiWsdfMJLjVR7r+vSmaJmtg==", + "dependencies": { + "System.AppContext": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0" + } + }, "Microsoft.Extensions.Primitives": { "type": "Transitive", "resolved": "3.1.7", "contentHash": "sa17s3vDAXTuIVGxuJcK713i0B0iaUoiwY4Sl2SLHhMqM8snznn0YVGiZAVkoKEUFWjvIg1Z/JNmAicBamI4mg==" }, + "Microsoft.Extensions.WebEncoders": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "KX+im5FUfsIOfSlgKMxeblkVg8Ry5GbsUocNcVHTWL1dIkR9x0gChQnppKF/QsX5VEs+Y07CvpfsRK0oAkDhaw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.2", + "Microsoft.Extensions.Options": "1.0.2", + "System.Text.Encodings.Web": "4.0.0" + } + }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", "resolved": "6.7.1", @@ -361,21 +634,136 @@ "System.Security.Cryptography.Cng": "4.5.0" } }, + "Microsoft.Net.Http.Headers": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "Nym2m4l2kb5jQRl5YlP1nAxneqpRfknFLy5PBKMYiC4kR/gDIQ4fi4rU9u7UdjEXMVgfWDIPpijx9YnSDEbOHw==", + "dependencies": { + "System.Buffers": "4.0.0", + "System.Collections": "4.0.11", + "System.Diagnostics.Contracts": "4.0.1", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime.Extensions": "4.1.0", + "System.Text.Encoding": "4.0.11" + } + }, "Microsoft.NetCore.Analyzers": { "type": "Transitive", "resolved": "3.3.0", "contentHash": "6qptTHUu1Wfszuf83NhU0IoAb4j7YWOpJs6oc6S4G/nI6aGGWKH/Xi5Vs9L/8lrI74ijEEzPcIwafSQW5ASHtA==" }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, "Microsoft.NetFramework.Analyzers": { "type": "Transitive", "resolved": "3.3.0", "contentHash": "JTfMic5fEFWICePbr7GXOGPranqS9Qxu2U/BZEcnnGbK1SFW8TxRyGp6O1L52xsbfOdqmzjc0t5ubhDrjj+Xpg==" }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "fQnBHO9DgcmkC9dYSJoBqo6sH1VJwJprUHh8F3hbcRlxiQiBUuTntdk8tUwV490OqC2kQUrinGwZyQHTieuXRA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "Namotion.Reflection": { + "type": "Transitive", + "resolved": "1.0.11", + "contentHash": "NT7/kod+9SCiL3XbCeY5OtohSGtLmclH5YAlWZiual5fhSldhDsrk8kzgSDx45UBOoeBnvmC8HEpAzKwj6grYQ==", + "dependencies": { + "Microsoft.CSharp": "4.3.0" + } + }, "Newtonsoft.Json": { "type": "Transitive", "resolved": "12.0.2", "contentHash": "rTK0s2EKlfHsQsH6Yx2smvcTCeyoDNgCW7FEYyV01drPlh2T243PR2DiDXqtC5N4GDm4Ma/lkxfW5a/4793vbA==" }, + "NJsonSchema": { + "type": "Transitive", + "resolved": "10.1.24", + "contentHash": "VRuV1Il0w8AJU0/a3/BgjV3F9ZZHTeZNcqKLvOKkRyc/8dB1apNJitS7+TBwdcQzeJeuNx7xEKrK7M7/tIXi9w==", + "dependencies": { + "Namotion.Reflection": "1.0.11", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Annotations": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "qbXMmiWLGs39Wj7RUuJtNAL6mFuBZBEPcSxYGmT2pcI1g3hKO8JfocMDaxWpmJJ0Kb6sePkKHIImtuLDRfOZow==" + }, + "NSwag.Core": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "GWxILGGf0tlbMiyWuYKh3AVGv5Wgv/scTGZaNgg3sEB/b8iX5tCqhLT9kQejacWqifz2WT9c3S5mQk+8bxEu+Q==", + "dependencies": { + "NJsonSchema": "10.1.24", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Generation": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "gXMQnnlIwBDXBt3sOlXemhqCmFROUcuWc5flaJHH7NhholbEEmVlnvkf7tuW/9SoIN1fVTu3qhfpigu15gKj4Q==", + "dependencies": { + "NJsonSchema": "10.1.24", + "NSwag.Core": "13.7.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "NSwag.Generation.AspNetCore": { + "type": "Transitive", + "resolved": "13.7.0", + "contentHash": "5KYhIubkO03l8CkIlEIpa+CNLS49pp5ccnz7//yr1CZbR0CaEmKb1b7Z+b5wmzZMvyEMx1s5u9kJUzBWJ+CobA==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.ApiExplorer": "1.0.3", + "Microsoft.AspNetCore.Mvc.Core": "1.0.3", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.3", + "NJsonSchema": "10.1.24", + "NSwag.Generation": "13.7.0" + } + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "QfS/nQI7k/BLgmLrw7qm7YBoULEvgWnPI+cYsbfCVFTW8Aj+i8JhccxcFMu1RWms0YZzF+UHguNBK4Qn89e2Sg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Nh0UPZx2Vifh8r+J+H2jxifZUD3sBrmolgiFWJd2yiNrxO0xTa6bAw3YwRn1VOiSen/tUXMS31ttNItCZ6lKuA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1" + } + }, + "runtime.native.System.Security.Cryptography": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2CQK0jmO6Eu7ZeMgD+LOFbNJSXHFVQbCJJkEyEwowh1SCgYnrn9W9RykMfpeeVGw7h4IBvYikzpGUlmZTUafJw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1" + } + }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", "resolved": "2.0.2", @@ -407,41 +795,766 @@ "SQLitePCLRaw.core": "2.0.2" } }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "3QjO4jNV7PdKkmQAVp9atA+usVnKRwI3Kx1nMwJ93T0LcQfx7pKAYk0nKz5wn1oP5iqlhZuy6RXOFdhr7rDwow==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "msXumHfjjURSkvxUjYuq4N2ghHoRi2VpXcKMA7gK6ujQfU3vGpl+B6ld0ATRg+FZFpRyA6PgEPA+VlIkTeNf2w==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.0.12", + "contentHash": "2gBcbb3drMLgxlI0fBfxMA31ec6AEyYCHygGse4vxceJan8mRIWeKJ24BFzN7+bi/NFTgdIgufzb94LWO5EERQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, "System.Collections.Immutable": { "type": "Transitive", "resolved": "1.7.1", "contentHash": "B43Zsz5EfMwyEbnObwRxW5u85fzJma3lrDeGcSAV1qkhSRTNY5uXAByTn9h9ddNdhM+4/YoLc/CI43umjwIl9Q==" }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.ComponentModel": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "oBZFnm7seFiVfugsIyOvQCWobNZs7FzqDV/B7tx20Ep/l3UUFCPDkdTnCNaJZTU27zjeODmy2C/cP60u3D4c9w==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, "System.ComponentModel.Annotations": { "type": "Transitive", "resolved": "4.7.0", "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" }, + "System.ComponentModel.Primitives": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "sc/7eVCdxPrp3ljpgTKVaQGUXiW05phNWvtv/m2kocXqrUQvTVWKou1Edas2aDjTThLPZOxPYIGNb/HN0QjURg==", + "dependencies": { + "System.ComponentModel": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.ComponentModel.TypeConverter": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "MnDAlaeJZy9pdB5ZdOlwdxfpI+LJQ6e0hmH7d2+y2LkiD8DRJynyDYl4Xxf3fWFm7SbEwBZh4elcfzONQLOoQw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.ComponentModel": "4.0.1", + "System.ComponentModel.Primitives": "4.1.0", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Diagnostics.Contracts": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "HvQQjy712vnlpPxaloZYkuE78Gn353L0SJLJVeLcNASeg9c4qla2a1Xq8I7B3jZoDzKPtHTkyVO7AZ5tpeQGuA==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, "System.Diagnostics.DiagnosticSource": { "type": "Transitive", "resolved": "4.7.1", "contentHash": "j81Lovt90PDAq8kLpaJfJKV/rWdWuEk6jfV+MBkee33vzYLEUsy4gXK8laa9V2nZlLM9VM9yA/OOQxxPEJKAMw==" }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "vDN1PoMZCkkdNjvZLql592oYJZgS7URcJzJ7bxeBgGtx5UtR5leNm49VmfHGqIffX4FKacHbI3H6UyNSHQknBg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "L1c6IqeQ88vuzC1P81JeHmHA8mxq8a18NUBNXnIY/BVb+TCyAaGIFbhpZt60h9FJNmisymoQkHEFSE9Vslja1Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Globalization": "4.0.11", + "System.Runtime": "4.1.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "KKo23iKeOaIg61SSXwjANN7QYDr/3op3OWGGzDzz7mypx0Za0fZSeG0l6cco8Ntp8YMYkIQcAqlk8yhm5/Uhcg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "bXwi8FrK/XIGPvtk1ZnawffhqLPyacj7dZnbFaV52YGaQigNqGEzNAByAIvL9FlEe3TCzoInorHF91IK//Q3Xg==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, "System.Memory": { "type": "Transitive", "resolved": "4.5.3", "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==" }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "hVvfl4405DRjA2408luZekbPhplJK03j2Y2lSfMlny7GHXlkByw1iLnc9mgKW0GdQn73vvMcWrWewAhylXA4Nw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.0.12", + "contentHash": "tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.IO": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, "System.Reflection.Emit": { "type": "Transitive", "resolved": "4.7.0", "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==", + "dependencies": { + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Globalization": "4.0.11", + "System.Reflection": "4.1.0", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Reflection": "4.1.0", + "System.Reflection.Primitives": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "+XbKFuzdmLP3d1o9pdHu2nxjNr2OEPqGzKeegPLCUMM71a0t50A/rOcIRmGs9wR7a8KuHX6hYs/7/TymIGLNqg==", + "dependencies": { + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "4Jlp0OgJLS/Voj1kyFP6MJlIYp3crgfH8kNQk2p7+4JYfc1aAmh9PZyAMMbDhuoolGNtux9HqSOazsioRiDvCw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Security.Principal": "4.0.1" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "8JQFxbLVdrtIOKMDN38Fn0GWnqYZw/oMlwOUG/qz1jqChvyZlnUmu+0s7wLx7JYua/nAXoESpHA3iw11QFWhXg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.Numerics": "4.0.1", + "System.Security.Cryptography.Encoding": "4.0.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "runtime.native.System.Security.Cryptography": "4.0.0" + } + }, "System.Security.Cryptography.Cng": { "type": "Transitive", "resolved": "4.5.0", "contentHash": "WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==" }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "/i1Usuo4PgAqgbPNC0NjbO3jPW//BoBlTpcWFD1EHVbidH21y4c1ap5bbEMSGAXjAShhMH4abi/K8fILrnu4BQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Security.Cryptography.Encoding": "4.0.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "FbKgE5MbxSQMPcSVRgwM6bXN3GtyAh04NkV8E5zKCBE26X0vYW0UtTa2FIgkH33WVqBVxRgxljlVYumWtU+HcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Linq": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "runtime.native.System.Security.Cryptography": "4.0.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "HUG/zNUJwEiLkoURDixzkzZdB5yGA5pQhDP93ArOpDPQMteURIGERRNzzoJlmTreLBWr5lkFSjjMSk8ySEpQMw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.Numerics": "4.0.1", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Security.Cryptography.Encoding": "4.0.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "runtime.native.System.Security.Cryptography": "4.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "Wkd7QryWYjkQclX0bngpntW5HSlMzeJU24UaLJQ7YTfI8ydAVAaU2J+HXLLABOVJlKTVvAeL0Aj39VeTe7L+oA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "4HEfsQIKAhA1+ApNn729Gi09zh+lYWwyIuViihoMDWp1vQnEkL2ct7mAbhBlLYm+x/L4Rr/pyGge1lIY635e0w==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Globalization.Calendars": "4.0.1", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.Numerics": "4.0.1", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Security.Cryptography.Cng": "4.2.0", + "System.Security.Cryptography.Csp": "4.0.0", + "System.Security.Cryptography.Encoding": "4.0.0", + "System.Security.Cryptography.OpenSsl": "4.0.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0", + "runtime.native.System.Net.Http": "4.0.1", + "runtime.native.System.Security.Cryptography": "4.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "On+SKhXY5rzxh/S8wlH1Rm0ogBlu7zyHNxeNBiXauNrhHRXAe9EuX8Yl5IOzLPGU5Z4kLWHMvORDOCG8iu9hww==", + "dependencies": { + "System.Runtime": "4.1.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "jtbiTDtvfLYgXn8PTfWI+SiBs51rrmO4AAckx4KR6vFK9Wzf6tI8kcRdsYQNwriUeQ1+CtQbM1W4cMbLXnj/OQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Targets": "1.0.1", + "System.Runtime": "4.1.0", + "System.Text.Encoding": "4.0.11" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "TWZnuiJgPDAEEUfobD7njXvSVR2Toz+jvKWds6yL4oSztmKQfnWzucczjzA+6Dv1bktBdY71sZW1YN0X6m9chQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, "System.Text.Json": { "type": "Transitive", "resolved": "4.7.1", "contentHash": "XwzMbct3iNepJaFylN1+l8weWlFburEzXidqleSsLvSXdHSIJHEKtRVKHPlpWcFmJX6k3goPFfVgUfp40RR+bg==" }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "i88YCXpRTjCnoSQZtdlHkAOx4KNNik4hMy83n0+Ftlb7jvV6ZiZWMpnEZHhjBp6hQVh8gWd/iKNPzlPF7iyA2g==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==", + "dependencies": { + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "pH4FZDsZQ/WmgJtN4LWYmRdJAEeVkyriSwrv2Teoe5FOU0Yxlb6II6GL8dBPOfRmutHGATduj3ooMt7dJ2+i+w==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "ZIiLPsf67YZ9zgr31vzrFaYQqxRPX9cVHjtPSnmx4eN6lbS/yEyYNr2vs1doGDEscF0tjCZFsk9yUg1sC9e8tg==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Tasks.Extensions": "4.0.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tools": "4.0.1", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Reflection": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "UWd1H+1IJ9Wlq5nognZ/XJdyj8qPE4XufBUkAW59ijsCPjZkZe0MUzKKJFBr+ZWBe5Wq1u1d5f2CYgE93uH7DA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11" + } + }, + "System.Xml.XPath.XDocument": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "FLhdYJx4331oGovQypQ8JIw2kEmNzCsjVOVYY/16kZTUoquZG85oVn7yUhBE2OZt1yGPSXAL0HTEfzjlbNpM7Q==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XDocument": "4.0.11", + "System.Xml.XPath": "4.0.1" + } + }, "timeline.errorcodes": { "type": "Project" } -- cgit v1.2.3 From aee40970978d723f915071c4e1d3ee08aed796c8 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 20 Aug 2020 01:46:15 +0800 Subject: Add document for user avatar controller. --- Timeline/Controllers/UserAvatarController.cs | 45 +++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Timeline/Controllers/UserAvatarController.cs b/Timeline/Controllers/UserAvatarController.cs index b2e2e852..3d3bc983 100644 --- a/Timeline/Controllers/UserAvatarController.cs +++ b/Timeline/Controllers/UserAvatarController.cs @@ -15,7 +15,11 @@ using static Timeline.Resources.Controllers.UserAvatarController; namespace Timeline.Controllers { + /// + /// Operations about user avatar. + /// [ApiController] + [ProducesErrorResponseType(typeof(CommonResponse))] public class UserAvatarController : Controller { private readonly ILogger _logger; @@ -23,6 +27,9 @@ namespace Timeline.Controllers private readonly IUserService _userService; private readonly IUserAvatarService _service; + /// + /// + /// public UserAvatarController(ILogger logger, IUserService userService, IUserAvatarService service) { _logger = logger; @@ -30,9 +37,21 @@ namespace Timeline.Controllers _service = service; } + /// + /// Get avatar of a user. + /// + /// Username of the user to get avatar of. + /// If-None-Match header. + /// Succeeded to get the avatar. + /// The avatar does not change. + /// The user does not exist. [HttpGet("users/{username}/avatar")] - public async Task Get([FromRoute][Username] string username) + [ProducesResponseType(typeof(byte[]), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status304NotModified)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task Get([FromRoute][Username] string username, [FromHeader(Name = "If-None-Match")] string? ifNoneMatch) { + _ = ifNoneMatch; long id; try { @@ -51,10 +70,22 @@ namespace Timeline.Controllers }); } + /// + /// Set avatar of a user. You have to be administrator to change other's. + /// + /// Username of the user to set avatar of. + /// Succeeded to set avatar. + /// Error code is 10010001 if user does not exist. Or avatar is of bad format. + /// You have not logged in. + /// You are not administrator. [HttpPut("users/{username}/avatar")] [Authorize] [RequireContentType, RequireContentLength] [Consumes("image/png", "image/jpeg", "image/gif", "image/webp")] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task Put([FromRoute][Username] string username) { var contentLength = Request.ContentLength!.Value; @@ -115,7 +146,19 @@ namespace Timeline.Controllers } } + /// + /// Reset the avatar to the default one. You have to be administrator to reset other's. + /// + /// Username of the user. + /// Succeeded to reset. + /// Error code is 10010001 if user does not exist. + /// You have not logged in. + /// You are not administrator. [HttpDelete("users/{username}/avatar")] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] [Authorize] public async Task Delete([FromRoute][Username] string username) { -- cgit v1.2.3 From 81f6ecd9685c5a6bae0da5050b5edfaf050167cc Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 17:41:29 +0800 Subject: ... --- Timeline/Controllers/TimelineController.cs | 144 ++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/Timeline/Controllers/TimelineController.cs b/Timeline/Controllers/TimelineController.cs index 72404ea3..b376bce5 100644 --- a/Timeline/Controllers/TimelineController.cs +++ b/Timeline/Controllers/TimelineController.cs @@ -17,8 +17,12 @@ using Timeline.Services.Exceptions; namespace Timeline.Controllers { + /// + /// Operations about timeline. + /// [ApiController] [CatchTimelineNotExistException] + [ProducesErrorResponseType(typeof(CommonResponse))] public class TimelineController : Controller { private readonly ILogger _logger; @@ -28,6 +32,9 @@ namespace Timeline.Controllers private readonly IMapper _mapper; + /// + /// + /// public TimelineController(ILogger logger, IUserService userService, ITimelineService service, IMapper mapper) { _logger = logger; @@ -36,7 +43,17 @@ namespace Timeline.Controllers _mapper = mapper; } + /// + /// List all timelines. + /// + /// A username. If set, only timelines related to the user will return. + /// Specify the relation type, may be 'own' or 'join'. If not set, both type will return. + /// "Private" or "Register" or "Public". If set, only timelines whose visibility is specified one will return. + /// Succeeded to get timelines. + /// Model is invalid. Or user specified by "relate" param does not exist. [HttpGet("timelines")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task>> TimelineList([FromQuery][Username] string? relate, [FromQuery][RegularExpression("(own)|(join)")] string? relateType, [FromQuery] string? visibility) { List? visibilityFilter = null; @@ -93,7 +110,20 @@ namespace Timeline.Controllers return result; } + /// + /// Get info of a timeline. + /// + /// The timeline name. + /// A unique id. If specified and if-modified-since is also specified, the timeline info will return when unique id is not the specified one even if it is not modified. + /// Same effect as If-Modified-Since header and take precedence than it. + /// If specified, will return 304 if not modified. + /// Succeeded to get timeline info. + /// Timeline not change. + /// Timeline does not exist. [HttpGet("timelines/{name}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status304NotModified)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> TimelineGet([FromRoute][GeneralTimelineName] string name, [FromQuery] string? checkUniqueId, [FromQuery(Name = "ifModifiedSince")] DateTime? queryIfModifiedSince, [FromHeader(Name = "If-Modified-Since")] DateTime? headerIfModifiedSince) { DateTime? ifModifiedSince = null; @@ -140,7 +170,19 @@ namespace Timeline.Controllers } } + /// + /// Get posts of a timeline. You need to have permission. + /// + /// The name of the timeline. + /// If set, only posts modified since the time will return. + /// If set to true, deleted post will also return. + /// Succeeded to get posts. + /// You have no permission. + /// The timeline does not exist. [HttpGet("timelines/{name}/posts")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task>> PostListGet([FromRoute][GeneralTimelineName] string name, [FromQuery] DateTime? modifiedSince, [FromQuery] bool? includeDeleted) { if (!this.IsAdministrator() && !await _service.HasReadPermission(name, this.GetOptionalUserId())) @@ -154,9 +196,26 @@ namespace Timeline.Controllers return result; } + /// + /// Get the data of a post. Usually a image post. You need to have permission. + /// + /// Timeline name. + /// The id of the post. + /// If-None-Match header. + /// Succeeded to get data. + /// Data not changed. + /// Error code is 11040502 if post has no data. + /// You have no permission. + /// Timeline or post does not exist. [HttpGet("timelines/{name}/posts/{id}/data")] - public async Task>> PostDataGet([FromRoute][GeneralTimelineName] string name, [FromRoute] long id) + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status304NotModified)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task PostDataGet([FromRoute][GeneralTimelineName] string name, [FromRoute] long id, [FromHeader(Name = "If-None-Match")] string? ifNoneMatch) { + _ = ifNoneMatch; if (!this.IsAdministrator() && !await _service.HasReadPermission(name, this.GetOptionalUserId())) { return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid()); @@ -180,8 +239,22 @@ namespace Timeline.Controllers } } + /// + /// Create a new post. You need to have permission. + /// + /// Timeline name. + /// + /// Info of new post. + /// Succeeded to create post and return info of new post. + /// Body model is invalid. + /// You have not logged in. + /// You have no permission. [HttpPost("timelines/{name}/posts")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> PostPost([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePostCreateRequest body) { var id = this.GetUserId(); @@ -238,8 +311,19 @@ namespace Timeline.Controllers return result; } + /// + /// Delete a post. + /// + /// Timeline name. + /// Post id. + /// Succeeded to delete post. Or post does not exist. + /// You have not logged in. + /// You have no permission. [HttpDelete("timelines/{name}/posts/{id}")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> PostDelete([FromRoute][GeneralTimelineName] string name, [FromRoute] long id) { if (!this.IsAdministrator() && !await _service.HasPostModifyPermission(name, id, this.GetUserId())) @@ -257,8 +341,20 @@ namespace Timeline.Controllers } } + /// + /// Change properties of a timeline. + /// + /// Timeline name. + /// + /// The new info. + /// Succeeded to change properties of timeline. Return the new info. + /// You have not logged in. + /// You have no permission. [HttpPatch("timelines/{name}")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> TimelinePatch([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePatchRequest body) { if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId()))) @@ -271,8 +367,21 @@ namespace Timeline.Controllers return result; } + /// + /// Add a member to timeline. + /// + /// Timeline name. + /// The new member's username. + /// Succeeded. + /// User does not exist. + /// You have not logged in. + /// You have no permission. [HttpPut("timelines/{name}/members/{member}")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task TimelineMemberPut([FromRoute][GeneralTimelineName] string name, [FromRoute][Username] string member) { if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId()))) @@ -291,8 +400,19 @@ namespace Timeline.Controllers } } + /// + /// Remove a member from timeline. + /// + /// Timeline name. + /// The member's username. + /// Succeeded. Or the user is not a member. + /// You have not logged in. + /// You have no permission. [HttpDelete("timelines/{name}/members/{member}")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task TimelineMemberDelete([FromRoute][GeneralTimelineName] string name, [FromRoute][Username] string member) { if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId()))) @@ -311,8 +431,19 @@ namespace Timeline.Controllers } } + /// + /// Create a timeline. + /// + /// + /// Info of new timeline. + /// Succeeded and return info of new timeline. + /// Timeline name is conflict. + /// You have not logged in. [HttpPost("timelines")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task> TimelineCreate([FromBody] TimelineCreateRequest body) { var userId = this.GetUserId(); @@ -329,8 +460,19 @@ namespace Timeline.Controllers } } + /// + /// Delete a timeline. + /// + /// Timeline name. + /// Succeeded. Or timeline does not exist. + /// You have not logged in. + /// You have no permission. [HttpDelete("timelines/{name}")] [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> TimelineDelete([FromRoute][TimelineName] string name) { if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId()))) -- cgit v1.2.3 From dcb0a10e1adaec24961f2484e7f9a9a1f1f5da15 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 21:25:33 +0800 Subject: ... --- Timeline/Controllers/TimelineController.cs | 48 ++++------------------ Timeline/Controllers/TokenController.cs | 10 ++--- Timeline/Controllers/UserAvatarController.cs | 8 +--- Timeline/Controllers/UserController.cs | 39 +++++++----------- Timeline/Startup.cs | 2 + Timeline/Swagger/ApiConvention.cs | 15 +++++++ .../DefaultDescriptionOperationProcessor.cs | 39 ++++++++++++++++++ Timeline/Timeline.csproj | 1 + 8 files changed, 86 insertions(+), 76 deletions(-) create mode 100644 Timeline/Swagger/ApiConvention.cs create mode 100644 Timeline/Swagger/DefaultDescriptionOperationProcessor.cs diff --git a/Timeline/Controllers/TimelineController.cs b/Timeline/Controllers/TimelineController.cs index b376bce5..43178ac6 100644 --- a/Timeline/Controllers/TimelineController.cs +++ b/Timeline/Controllers/TimelineController.cs @@ -49,8 +49,7 @@ namespace Timeline.Controllers /// A username. If set, only timelines related to the user will return. /// Specify the relation type, may be 'own' or 'join'. If not set, both type will return. /// "Private" or "Register" or "Public". If set, only timelines whose visibility is specified one will return. - /// Succeeded to get timelines. - /// Model is invalid. Or user specified by "relate" param does not exist. + /// The timeline list. [HttpGet("timelines")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] @@ -117,9 +116,7 @@ namespace Timeline.Controllers /// A unique id. If specified and if-modified-since is also specified, the timeline info will return when unique id is not the specified one even if it is not modified. /// Same effect as If-Modified-Since header and take precedence than it. /// If specified, will return 304 if not modified. - /// Succeeded to get timeline info. - /// Timeline not change. - /// Timeline does not exist. + /// The timeline info. [HttpGet("timelines/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status304NotModified)] @@ -171,14 +168,12 @@ namespace Timeline.Controllers } /// - /// Get posts of a timeline. You need to have permission. + /// Get posts of a timeline. /// /// The name of the timeline. /// If set, only posts modified since the time will return. /// If set to true, deleted post will also return. - /// Succeeded to get posts. - /// You have no permission. - /// The timeline does not exist. + /// The post list. [HttpGet("timelines/{name}/posts")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] @@ -197,16 +192,12 @@ namespace Timeline.Controllers } /// - /// Get the data of a post. Usually a image post. You need to have permission. + /// Get the data of a post. Usually a image post. /// /// Timeline name. /// The id of the post. /// If-None-Match header. - /// Succeeded to get data. - /// Data not changed. - /// Error code is 11040502 if post has no data. - /// You have no permission. - /// Timeline or post does not exist. + /// The data. [HttpGet("timelines/{name}/posts/{id}/data")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status304NotModified)] @@ -240,15 +231,11 @@ namespace Timeline.Controllers } /// - /// Create a new post. You need to have permission. + /// Create a new post. /// /// Timeline name. /// /// Info of new post. - /// Succeeded to create post and return info of new post. - /// Body model is invalid. - /// You have not logged in. - /// You have no permission. [HttpPost("timelines/{name}/posts")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -316,9 +303,7 @@ namespace Timeline.Controllers /// /// Timeline name. /// Post id. - /// Succeeded to delete post. Or post does not exist. - /// You have not logged in. - /// You have no permission. + /// Info of deletion. [HttpDelete("timelines/{name}/posts/{id}")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -347,9 +332,6 @@ namespace Timeline.Controllers /// Timeline name. /// /// The new info. - /// Succeeded to change properties of timeline. Return the new info. - /// You have not logged in. - /// You have no permission. [HttpPatch("timelines/{name}")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -372,10 +354,6 @@ namespace Timeline.Controllers /// /// Timeline name. /// The new member's username. - /// Succeeded. - /// User does not exist. - /// You have not logged in. - /// You have no permission. [HttpPut("timelines/{name}/members/{member}")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -405,9 +383,6 @@ namespace Timeline.Controllers /// /// Timeline name. /// The member's username. - /// Succeeded. Or the user is not a member. - /// You have not logged in. - /// You have no permission. [HttpDelete("timelines/{name}/members/{member}")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -436,9 +411,6 @@ namespace Timeline.Controllers /// /// /// Info of new timeline. - /// Succeeded and return info of new timeline. - /// Timeline name is conflict. - /// You have not logged in. [HttpPost("timelines")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] @@ -464,9 +436,7 @@ namespace Timeline.Controllers /// Delete a timeline. /// /// Timeline name. - /// Succeeded. Or timeline does not exist. - /// You have not logged in. - /// You have no permission. + /// Info of deletion. [HttpDelete("timelines/{name}")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] diff --git a/Timeline/Controllers/TokenController.cs b/Timeline/Controllers/TokenController.cs index 7792b318..8f2ca600 100644 --- a/Timeline/Controllers/TokenController.cs +++ b/Timeline/Controllers/TokenController.cs @@ -40,11 +40,10 @@ namespace Timeline.Controllers /// /// Create a new token for a user. /// - /// Succeed to create token. - /// Error code is 11010101 if user does not exist or password is wrong. + /// Result of token creation. [HttpPost("create")] [AllowAnonymous] - [ProducesResponseType(typeof(CreateTokenResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> Create([FromBody] CreateTokenRequest request) { @@ -91,11 +90,10 @@ namespace Timeline.Controllers /// /// Verify a token. /// - /// Token is valid. - /// Error code is 11010201 if token is of bad format (it may not be created by this server). Error code is 11010202 if user does not exist. Error code is 11010203 if token is of old version (user may have changed password). Error code is 11010204 if token is expired. + /// Result of token verification. [HttpPost("verify")] [AllowAnonymous] - [ProducesResponseType(typeof(VerifyTokenResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> Verify([FromBody] VerifyTokenRequest request) { diff --git a/Timeline/Controllers/UserAvatarController.cs b/Timeline/Controllers/UserAvatarController.cs index 3d3bc983..52e87df2 100644 --- a/Timeline/Controllers/UserAvatarController.cs +++ b/Timeline/Controllers/UserAvatarController.cs @@ -42,9 +42,7 @@ namespace Timeline.Controllers /// /// Username of the user to get avatar of. /// If-None-Match header. - /// Succeeded to get the avatar. - /// The avatar does not change. - /// The user does not exist. + /// Avatar data. [HttpGet("users/{username}/avatar")] [ProducesResponseType(typeof(byte[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status304NotModified)] @@ -74,10 +72,6 @@ namespace Timeline.Controllers /// Set avatar of a user. You have to be administrator to change other's. /// /// Username of the user to set avatar of. - /// Succeeded to set avatar. - /// Error code is 10010001 if user does not exist. Or avatar is of bad format. - /// You have not logged in. - /// You are not administrator. [HttpPut("users/{username}/avatar")] [Authorize] [RequireContentType, RequireContentLength] diff --git a/Timeline/Controllers/UserController.cs b/Timeline/Controllers/UserController.cs index fa2d37d8..02c09aab 100644 --- a/Timeline/Controllers/UserController.cs +++ b/Timeline/Controllers/UserController.cs @@ -43,9 +43,9 @@ namespace Timeline.Controllers /// /// Get all users. /// - /// The user list. + /// All user list. [HttpGet("users")] - [ProducesResponseType(typeof(UserInfo[]), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] public async Task> List() { var users = await _userService.GetUsers(); @@ -54,12 +54,13 @@ namespace Timeline.Controllers } /// - /// Get a user info. + /// Get a user's info. /// /// Username of the user. - /// The user info. + /// User info. [HttpGet("users/{username}")] - [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> Get([FromRoute][Username] string username) { try @@ -75,16 +76,14 @@ namespace Timeline.Controllers } /// - /// Change a user's property. You have to be administrator in some condition. + /// Change a user's property. /// /// /// Username of the user to change. - /// Succeed to change the user and return the new user info. - /// You have not logged in. - /// You are not administrator. - /// The user to change does not exist. + /// The new user info. [HttpPatch("users/{username}"), Authorize] - [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -134,11 +133,9 @@ namespace Timeline.Controllers /// Delete a user and all his related data. You have to be administrator. /// /// Username of the user to delete. - /// Succeeded to delete or the user does not exist. - /// You have not logged in. - /// You are not administrator. + /// Info of deletion. [HttpDelete("users/{username}"), AdminAuthorize] - [ProducesResponseType(typeof(CommonDeleteResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> Delete([FromRoute][Username] string username) @@ -153,12 +150,9 @@ namespace Timeline.Controllers /// /// Create a new user. You have to be administrator. /// - /// Succeeded to create a new user and return his user info. - /// Error code is 11020101 if a user with given username already exists. - /// You have not logged in. - /// You are not administrator. + /// The new user's info. [HttpPost("userop/createuser"), AdminAuthorize] - [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] @@ -178,11 +172,8 @@ namespace Timeline.Controllers /// /// Change password with old password. /// - /// Succeeded to change password. - /// Error code is 11020201 if old password is wrong. - /// You have not logged in. [HttpPost("userop/changepassword"), Authorize] - [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ChangePassword([FromBody] ChangePasswordRequest request) diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index 3e5dd24d..960bbc2c 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -20,6 +20,7 @@ using Timeline.Helpers; using Timeline.Models.Converters; using Timeline.Routes; using Timeline.Services; +using Timeline.Swagger; namespace Timeline { @@ -112,6 +113,7 @@ namespace Timeline Description = "Type into the textbox: Bearer {your JWT token}." })); document.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); + document.OperationProcessors.Add(new DefaultDescriptionOperationProcessor()); }); if (!disableFrontEnd) diff --git a/Timeline/Swagger/ApiConvention.cs b/Timeline/Swagger/ApiConvention.cs new file mode 100644 index 00000000..dbf0b2fe --- /dev/null +++ b/Timeline/Swagger/ApiConvention.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; + +[assembly: ApiConventionType(typeof(Timeline.Controllers.ApiConvention))] + +namespace Timeline.Controllers +{ + // There is some bug if nullable is enable. So disable it. +#nullable disable + /// + /// My api convention. + /// + public static class ApiConvention + { + } +} diff --git a/Timeline/Swagger/DefaultDescriptionOperationProcessor.cs b/Timeline/Swagger/DefaultDescriptionOperationProcessor.cs new file mode 100644 index 00000000..4967cc6a --- /dev/null +++ b/Timeline/Swagger/DefaultDescriptionOperationProcessor.cs @@ -0,0 +1,39 @@ +using NSwag.Generation.Processors; +using NSwag.Generation.Processors.Contexts; +using System.Collections.Generic; + +namespace Timeline.Swagger +{ + /// + /// Swagger operation processor that adds default description to response. + /// + public class DefaultDescriptionOperationProcessor : IOperationProcessor + { + private readonly Dictionary defaultDescriptionMap = new Dictionary + { + ["200"] = "Succeeded to perform the operation.", + ["304"] = "Item does not change.", + ["400"] = "See code and message for error info.", + ["401"] = "You need to log in to perform this operation.", + ["403"] = "You have no permission to perform the operation.", + ["404"] = "Item does not exist. See code and message for error info." + }; + + /// + public bool Process(OperationProcessorContext context) + { + var responses = context.OperationDescription.Operation.Responses; + + foreach (var (httpStatusCode, res) in responses) + { + if (!string.IsNullOrEmpty(res.Description)) continue; + if (defaultDescriptionMap.ContainsKey(httpStatusCode)) + { + res.Description = defaultDescriptionMap[httpStatusCode]; + } + } + + return true; + } + } +} diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 5c2f7adf..5fc69fc8 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -17,6 +17,7 @@ 0.3.0 true + true -- cgit v1.2.3 From 4475de3c0c86c4096b843d8bee8aff48b7e31896 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 22:49:48 +0800 Subject: ... --- Timeline.Tests/IntegratedTests/UserAvatarTest.cs | 15 ++--- Timeline/Controllers/UserAvatarController.cs | 25 +++----- Timeline/Filters/Header.cs | 69 +++++++++++++-------- Timeline/Formatters/BytesInputFormatter.cs | 79 ++++++++++++++++++++++++ Timeline/Models/ByteData.cs | 33 ++++++++++ Timeline/Startup.cs | 1 + 6 files changed, 167 insertions(+), 55 deletions(-) create mode 100644 Timeline/Formatters/BytesInputFormatter.cs create mode 100644 Timeline/Models/ByteData.cs diff --git a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs index 91986cda..507b05ba 100644 --- a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs +++ b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs @@ -66,16 +66,14 @@ namespace Timeline.Tests.IntegratedTests using var content = new ByteArrayContent(new[] { (byte)0x00 }); content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); var res = await client.PutAsync("users/user1/avatar", content); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentLength_Missing); ; + res.Should().BeInvalidModel(); } { using var content = new ByteArrayContent(new[] { (byte)0x00 }); content.Headers.ContentLength = 1; var res = await client.PutAsync("users/user1/avatar", content); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentType_Missing); + res.Should().BeInvalidModel(); } { @@ -83,8 +81,7 @@ namespace Timeline.Tests.IntegratedTests content.Headers.ContentLength = 0; content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); var res = await client.PutAsync("users/user1/avatar", content); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentLength_Zero); + res.Should().BeInvalidModel(); } { @@ -106,8 +103,7 @@ namespace Timeline.Tests.IntegratedTests content.Headers.ContentLength = 2; content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); var res = await client.PutAsync("users/user1/avatar", content); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Content.UnmatchedLength_Smaller); + res.Should().BeInvalidModel(); } { @@ -115,8 +111,7 @@ namespace Timeline.Tests.IntegratedTests content.Headers.ContentLength = 1; content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); var res = await client.PutAsync("users/user1/avatar", content); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Content.UnmatchedLength_Bigger); + res.Should().BeInvalidModel(); } { diff --git a/Timeline/Controllers/UserAvatarController.cs b/Timeline/Controllers/UserAvatarController.cs index 52e87df2..32f63fc6 100644 --- a/Timeline/Controllers/UserAvatarController.cs +++ b/Timeline/Controllers/UserAvatarController.cs @@ -3,10 +3,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; +using System.IO; using System.Threading.Tasks; using Timeline.Auth; using Timeline.Filters; using Timeline.Helpers; +using Timeline.Models; using Timeline.Models.Http; using Timeline.Models.Validation; using Timeline.Services; @@ -72,20 +74,17 @@ namespace Timeline.Controllers /// Set avatar of a user. You have to be administrator to change other's. /// /// Username of the user to set avatar of. + /// The avatar data. [HttpPut("users/{username}/avatar")] [Authorize] - [RequireContentType, RequireContentLength] [Consumes("image/png", "image/jpeg", "image/gif", "image/webp")] + [MaxContentLength(1000 * 1000 * 10)] [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task Put([FromRoute][Username] string username) + public async Task Put([FromRoute][Username] string username, [FromBody] ByteData body) { - var contentLength = Request.ContentLength!.Value; - if (contentLength > 1000 * 1000 * 10) - return BadRequest(ErrorResponse.Common.Content.TooBig("10MB")); - if (!User.IsAdministrator() && User.Identity.Name != username) { _logger.LogInformation(Log.Format(LogPutForbid, @@ -106,20 +105,10 @@ namespace Timeline.Controllers try { - var data = new byte[contentLength]; - var bytesRead = await Request.Body.ReadAsync(data); - - if (bytesRead != contentLength) - return BadRequest(ErrorResponse.Common.Content.UnmatchedLength_Smaller()); - - var extraByte = new byte[1]; - if (await Request.Body.ReadAsync(extraByte) != 0) - return BadRequest(ErrorResponse.Common.Content.UnmatchedLength_Bigger()); - await _service.SetAvatar(id, new Avatar { - Data = data, - Type = Request.ContentType + Data = body.Data, + Type = body.ContentType }); _logger.LogInformation(Log.Format(LogPutSuccess, diff --git a/Timeline/Filters/Header.cs b/Timeline/Filters/Header.cs index 0db11faf..cc5ddd9f 100644 --- a/Timeline/Filters/Header.cs +++ b/Timeline/Filters/Header.cs @@ -4,45 +4,60 @@ using Timeline.Models.Http; namespace Timeline.Filters { - public class RequireContentTypeAttribute : ActionFilterAttribute + /// + /// Restrict max content length. + /// + public class MaxContentLengthFilter : IResourceFilter { - public override void OnActionExecuting(ActionExecutingContext context) + /// + /// + /// + /// Max length. + public MaxContentLengthFilter(long maxByteLength) { - if (context.HttpContext.Request.ContentType == null) - { - context.Result = new BadRequestObjectResult(ErrorResponse.Common.Header.ContentType_Missing()); - } + MaxByteLength = maxByteLength; } - } - - public class RequireContentLengthAttribute : ActionFilterAttribute - { - public RequireContentLengthAttribute() - : this(true) - { - } + /// + /// Max length. + /// + public long MaxByteLength { get; set; } - public RequireContentLengthAttribute(bool requireNonZero) + /// + public void OnResourceExecuted(ResourceExecutedContext context) { - RequireNonZero = requireNonZero; } - public bool RequireNonZero { get; set; } - - public override void OnActionExecuting(ActionExecutingContext context) + /// + public void OnResourceExecuting(ResourceExecutingContext context) { - if (context.HttpContext.Request.ContentLength == null) + var contentLength = context.HttpContext.Request.ContentLength; + if (contentLength != null && contentLength > MaxByteLength) { - context.Result = new BadRequestObjectResult(ErrorResponse.Common.Header.ContentLength_Missing()); - return; + context.Result = new BadRequestObjectResult(ErrorResponse.Common.Content.TooBig(MaxByteLength + "B")); } + } + } - if (RequireNonZero && context.HttpContext.Request.ContentLength.Value == 0) - { - context.Result = new BadRequestObjectResult(ErrorResponse.Common.Header.ContentLength_Zero()); - return; - } + /// + /// Restrict max content length. + /// + public class MaxContentLengthAttribute : TypeFilterAttribute + { + /// + /// + /// + /// Max length. + public MaxContentLengthAttribute(long maxByteLength) + : base(typeof(MaxContentLengthFilter)) + { + MaxByteLength = maxByteLength; + Arguments = new object[] { maxByteLength }; } + + /// + /// Max length. + /// + public long MaxByteLength { get; } } } diff --git a/Timeline/Formatters/BytesInputFormatter.cs b/Timeline/Formatters/BytesInputFormatter.cs new file mode 100644 index 00000000..ac6537c9 --- /dev/null +++ b/Timeline/Formatters/BytesInputFormatter.cs @@ -0,0 +1,79 @@ +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; +using System; +using System.Threading.Tasks; +using Timeline.Models; + +namespace Timeline.Formatters +{ + /// + /// Formatter that reads body as bytes. + /// + public class BytesInputFormatter : InputFormatter + { + /// + /// + /// + public BytesInputFormatter() + { + SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/png")); + SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpeg")); + SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/gif")); + SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/webp")); + } + + /// + public override bool CanRead(InputFormatterContext context) + { + if (context == null) throw new ArgumentNullException(nameof(context)); + + if (context.ModelType == typeof(ByteData)) + return true; + + return false; + } + + /// + public override async Task ReadRequestBodyAsync(InputFormatterContext context) + { + var request = context.HttpContext.Request; + var contentLength = request.ContentLength; + + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + + if (contentLength == null) + { + logger.LogInformation("Failed to read body as bytes. Content-Length is not set."); + return await InputFormatterResult.FailureAsync(); + } + + if (contentLength == 0) + { + logger.LogInformation("Failed to read body as bytes. Content-Length is 0."); + return await InputFormatterResult.FailureAsync(); + } + + var bodyStream = request.Body; + + var data = new byte[contentLength.Value]; + var bytesRead = await bodyStream.ReadAsync(data); + + if (bytesRead != contentLength) + { + logger.LogInformation("Failed to read body as bytes. Actual length of body is smaller than Content-Length."); + return await InputFormatterResult.FailureAsync(); + } + + var extraByte = new byte[1]; + if (await bodyStream.ReadAsync(extraByte) != 0) + { + logger.LogInformation("Failed to read body as bytes. Actual length of body is greater than Content-Length."); + return await InputFormatterResult.FailureAsync(); + } + + return await InputFormatterResult.SuccessAsync(new ByteData(data, request.ContentType)); + } + } +} diff --git a/Timeline/Models/ByteData.cs b/Timeline/Models/ByteData.cs new file mode 100644 index 00000000..7b832eb5 --- /dev/null +++ b/Timeline/Models/ByteData.cs @@ -0,0 +1,33 @@ +using NSwag.Annotations; + +namespace Timeline.Models +{ + /// + /// Model for reading http body as bytes. + /// + [OpenApiFile] + public class ByteData + { + /// + /// + /// The data. + /// The content type. + public ByteData(byte[] data, string contentType) + { + Data = data; + ContentType = contentType; + } + + /// + /// Data. + /// +#pragma warning disable CA1819 // Properties should not return arrays + public byte[] Data { get; } +#pragma warning restore CA1819 // Properties should not return arrays + + /// + /// Content type. + /// + public string ContentType { get; } + } +} diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index 960bbc2c..408057e5 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -49,6 +49,7 @@ namespace Timeline services.AddControllers(setup => { setup.InputFormatters.Add(new StringInputFormatter()); + setup.InputFormatters.Add(new BytesInputFormatter()); setup.UseApiRoutePrefix("api"); }) .AddJsonOptions(options => -- cgit v1.2.3 From a8ca52b2ec6009c1be036e74edb76161447371b8 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 22:52:20 +0800 Subject: ... --- Timeline.ErrorCodes/ErrorCodes.cs | 5 ---- Timeline/Models/Http/ErrorResponse.cs | 50 ----------------------------------- 2 files changed, 55 deletions(-) diff --git a/Timeline.ErrorCodes/ErrorCodes.cs b/Timeline.ErrorCodes/ErrorCodes.cs index 4637242a..91e0c1fd 100644 --- a/Timeline.ErrorCodes/ErrorCodes.cs +++ b/Timeline.ErrorCodes/ErrorCodes.cs @@ -17,16 +17,11 @@ public static class Header { public const int IfNonMatch_BadFormat = 1_000_01_01; - public const int ContentType_Missing = 1_000_02_01; - public const int ContentLength_Missing = 1_000_03_01; - public const int ContentLength_Zero = 1_000_03_02; } public static class Content { public const int TooBig = 1_000_11_01; - public const int UnmatchedLength_Smaller = 1_000_11_02; - public const int UnmatchedLength_Bigger = 1_000_11_03; } } diff --git a/Timeline/Models/Http/ErrorResponse.cs b/Timeline/Models/Http/ErrorResponse.cs index 9a4d190a..7ba536f9 100644 --- a/Timeline/Models/Http/ErrorResponse.cs +++ b/Timeline/Models/Http/ErrorResponse.cs @@ -53,36 +53,6 @@ namespace Timeline.Models.Http return new CommonResponse(ErrorCodes.Common.Header.IfNonMatch_BadFormat, string.Format(message, formatArgs)); } - public static CommonResponse ContentType_Missing(params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentType_Missing, string.Format(Common_Header_ContentType_Missing, formatArgs)); - } - - public static CommonResponse CustomMessage_ContentType_Missing(string message, params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentType_Missing, string.Format(message, formatArgs)); - } - - public static CommonResponse ContentLength_Missing(params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentLength_Missing, string.Format(Common_Header_ContentLength_Missing, formatArgs)); - } - - public static CommonResponse CustomMessage_ContentLength_Missing(string message, params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentLength_Missing, string.Format(message, formatArgs)); - } - - public static CommonResponse ContentLength_Zero(params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentLength_Zero, string.Format(Common_Header_ContentLength_Zero, formatArgs)); - } - - public static CommonResponse CustomMessage_ContentLength_Zero(string message, params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Header.ContentLength_Zero, string.Format(message, formatArgs)); - } - } public static class Content @@ -98,26 +68,6 @@ namespace Timeline.Models.Http return new CommonResponse(ErrorCodes.Common.Content.TooBig, string.Format(message, formatArgs)); } - public static CommonResponse UnmatchedLength_Smaller(params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Content.UnmatchedLength_Smaller, string.Format(Common_Content_UnmatchedLength_Smaller, formatArgs)); - } - - public static CommonResponse CustomMessage_UnmatchedLength_Smaller(string message, params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Content.UnmatchedLength_Smaller, string.Format(message, formatArgs)); - } - - public static CommonResponse UnmatchedLength_Bigger(params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Content.UnmatchedLength_Bigger, string.Format(Common_Content_UnmatchedLength_Bigger, formatArgs)); - } - - public static CommonResponse CustomMessage_UnmatchedLength_Bigger(string message, params object?[] formatArgs) - { - return new CommonResponse(ErrorCodes.Common.Content.UnmatchedLength_Bigger, string.Format(message, formatArgs)); - } - } } -- cgit v1.2.3 From be532c56158362701a4d5704e995c743ff8b9804 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 23:24:47 +0800 Subject: ... --- Timeline/Startup.cs | 1 + .../Swagger/ByteDataRequestOperationProcessor.cs | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Timeline/Swagger/ByteDataRequestOperationProcessor.cs diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index 408057e5..86bdaf54 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -115,6 +115,7 @@ namespace Timeline })); document.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); document.OperationProcessors.Add(new DefaultDescriptionOperationProcessor()); + document.OperationProcessors.Add(new ByteDataRequestOperationProcessor()); }); if (!disableFrontEnd) diff --git a/Timeline/Swagger/ByteDataRequestOperationProcessor.cs b/Timeline/Swagger/ByteDataRequestOperationProcessor.cs new file mode 100644 index 00000000..887831ac --- /dev/null +++ b/Timeline/Swagger/ByteDataRequestOperationProcessor.cs @@ -0,0 +1,27 @@ +using NJsonSchema; +using NSwag; +using NSwag.Generation.Processors; +using NSwag.Generation.Processors.Contexts; +using System.Linq; +using Timeline.Models; + +namespace Timeline.Swagger +{ + /// + /// Coerce ByteData body type into the right one. + /// + public class ByteDataRequestOperationProcessor : IOperationProcessor + { + /// + public bool Process(OperationProcessorContext context) + { + var hasByteDataBody = context.MethodInfo.GetParameters().Where(p => p.ParameterType == typeof(ByteData)).Any(); + if (hasByteDataBody) + { + var bodyParameter = context.OperationDescription.Operation.Parameters.Where(p => p.Kind == OpenApiParameterKind.Body).Single(); + bodyParameter.Schema = JsonSchema.FromType(); + } + return true; + } + } +} -- cgit v1.2.3 From c79352d27df2506d2ab214f61d60e503a1d7675a Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 23:32:53 +0800 Subject: ... --- Timeline.Tests/Helpers/TestClock.cs | 2 +- Timeline.Tests/IntegratedTests/TimelineTest.cs | 8 ++++---- Timeline/Models/Validation/Validator.cs | 4 ++-- Timeline/Services/ETagGenerator.cs | 2 +- Timeline/Services/TimelineService.cs | 2 ++ Timeline/Services/UserService.cs | 5 ++--- Timeline/Services/UserTokenException.cs | 4 ++-- Timeline/Timeline.csproj | 2 ++ 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Timeline.Tests/Helpers/TestClock.cs b/Timeline.Tests/Helpers/TestClock.cs index ed2d65a6..34adb245 100644 --- a/Timeline.Tests/Helpers/TestClock.cs +++ b/Timeline.Tests/Helpers/TestClock.cs @@ -8,7 +8,7 @@ namespace Timeline.Tests.Helpers { public class TestClock : IClock { - private DateTime? _currentTime = null; + private DateTime? _currentTime; public DateTime GetCurrentTime() { diff --git a/Timeline.Tests/IntegratedTests/TimelineTest.cs b/Timeline.Tests/IntegratedTests/TimelineTest.cs index 16b3c7e4..3b4b1754 100644 --- a/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -76,20 +76,20 @@ namespace Timeline.Tests.IntegratedTests if (subpath != null) { if (!subpath.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - result.Append("/"); + result.Append('/'); result.Append(subpath); } if (query != null && query.Count != 0) { - result.Append("?"); + result.Append('?'); foreach (var (key, value, index) in query.Select((pair, index) => (pair.Key, pair.Value, index))) { result.Append(WebUtility.UrlEncode(key)); - result.Append("="); + result.Append('='); result.Append(WebUtility.UrlEncode(value)); if (index != query.Count - 1) - result.Append("&"); + result.Append('&'); } } diff --git a/Timeline/Models/Validation/Validator.cs b/Timeline/Models/Validation/Validator.cs index db139448..aef7891c 100644 --- a/Timeline/Models/Validation/Validator.cs +++ b/Timeline/Models/Validation/Validator.cs @@ -35,11 +35,11 @@ namespace Timeline.Models.Validation /// /// The type of accepted value. /// - /// Subclass should override to do the real validation. + /// Subclass should override to do the real validation. /// This class will check the nullity and type of value. /// If value is null, it will pass or fail depending on . /// If value is not null and not of type - /// it will fail and not call . + /// it will fail and not call . /// /// is true by default. /// diff --git a/Timeline/Services/ETagGenerator.cs b/Timeline/Services/ETagGenerator.cs index d328ea20..4493e903 100644 --- a/Timeline/Services/ETagGenerator.cs +++ b/Timeline/Services/ETagGenerator.cs @@ -33,7 +33,7 @@ namespace Timeline.Services return Task.Run(() => Convert.ToBase64String(_sha1.ComputeHash(source))); } - private bool _disposed = false; // To detect redundant calls + private bool _disposed; // To detect redundant calls public void Dispose() { diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index 0070fe3e..01f7f5fd 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -260,6 +260,7 @@ namespace Timeline.Services /// Thrown when timeline with name does not exist. /// If it is a personal timeline, then inner exception is . /// + /// /// This method does not check whether visitor is administrator. /// Return false if user with user id does not exist. /// @@ -277,6 +278,7 @@ namespace Timeline.Services /// Thrown when timeline with name does not exist. /// If it is a personal timeline, then inner exception is . /// + /// /// This method does not check whether visitor is administrator. /// Return false if user with visitor id does not exist. /// diff --git a/Timeline/Services/UserService.cs b/Timeline/Services/UserService.cs index d9b3da26..821bc33d 100644 --- a/Timeline/Services/UserService.cs +++ b/Timeline/Services/UserService.cs @@ -65,11 +65,10 @@ namespace Timeline.Services /// Create a user with given info. /// /// The info of new user. - /// The password, can't be null or empty. /// The the new user. /// Thrown when is null. /// Thrown when some fields in is bad. - /// Thrown when a user with given username already exists. + /// Thrown when a user with given username already exists. /// /// must not be null and must be a valid username. /// must not be null or empty. @@ -110,7 +109,7 @@ namespace Timeline.Services /// Thrown when is null. /// Thrown when is of bad format or some fields in is bad. /// Thrown when user with given id does not exist. - /// Thrown when user with the newusername already exist. + /// Thrown when user with the newusername already exist. /// /// Only , and will be used. /// If null, then not change. diff --git a/Timeline/Services/UserTokenException.cs b/Timeline/Services/UserTokenException.cs index ed0bae1a..d25fabb3 100644 --- a/Timeline/Services/UserTokenException.cs +++ b/Timeline/Services/UserTokenException.cs @@ -31,9 +31,9 @@ namespace Timeline.Services System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - public DateTime ExpireTime { get; private set; } = default; + public DateTime ExpireTime { get; private set; } - public DateTime VerifyTime { get; private set; } = default; + public DateTime VerifyTime { get; private set; } } [Serializable] diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 5fc69fc8..5ceb97e6 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -18,6 +18,8 @@ 0.3.0 true true + + 1701;1702;1591 -- cgit v1.2.3 From f1c70edd559c72dcb47ff647f3f03ba5ae9a56cc Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Aug 2020 23:44:53 +0800 Subject: ... --- Timeline/Models/Http/Timeline.cs | 75 ++++++++++++++++++++++++++++++ Timeline/Models/Http/TimelineController.cs | 33 +++++++++++++ Timeline/Models/Http/UserController.cs | 6 --- Timeline/Models/Http/UserInfo.cs | 31 +++++++++++- 4 files changed, 138 insertions(+), 7 deletions(-) diff --git a/Timeline/Models/Http/Timeline.cs b/Timeline/Models/Http/Timeline.cs index 52e26190..6498fa74 100644 --- a/Timeline/Models/Http/Timeline.cs +++ b/Timeline/Models/Http/Timeline.cs @@ -8,45 +8,120 @@ using Timeline.Controllers; namespace Timeline.Models.Http { + /// + /// Info of post content. + /// public class TimelinePostContentInfo { + /// + /// Type of the post content. + /// public string Type { get; set; } = default!; + /// + /// If post is of text type. This is the text. + /// public string? Text { get; set; } + /// + /// If post is of image type. This is the image url. + /// public string? Url { get; set; } } + /// + /// Info of a post. + /// public class TimelinePostInfo { + /// + /// Post id. + /// public long Id { get; set; } + /// + /// Content of the post. May be null if post is deleted. + /// public TimelinePostContentInfo? Content { get; set; } + /// + /// True if post is deleted. + /// public bool Deleted { get; set; } + /// + /// Post time. + /// public DateTime Time { get; set; } + /// + /// The author. May be null if the user has been deleted. + /// public UserInfo? Author { get; set; } = default!; + /// + /// Last updated time. + /// public DateTime LastUpdated { get; set; } = default!; } + /// + /// Info of a timeline. + /// public class TimelineInfo { + /// + /// Unique id. + /// public string UniqueId { get; set; } = default!; + /// + /// Name of timeline. + /// public string Name { get; set; } = default!; + /// + /// Last modified time of timeline name. + /// public DateTime NameLastModifed { get; set; } = default!; + /// + /// Timeline description. + /// public string Description { get; set; } = default!; + /// + /// Owner of the timeline. + /// public UserInfo Owner { get; set; } = default!; + /// + /// Visibility of the timeline. + /// public TimelineVisibility Visibility { get; set; } #pragma warning disable CA2227 // Collection properties should be read only + /// + /// Members of timeline. + /// public List Members { get; set; } = default!; #pragma warning restore CA2227 // Collection properties should be read only + /// + /// Create time of timeline. + /// public DateTime CreateTime { get; set; } = default!; + /// + /// Last modified time of timeline. + /// public DateTime LastModified { get; set; } = default!; #pragma warning disable CA1707 // Identifiers should not contain underscores + /// + /// Related links. + /// public TimelineInfoLinks _links { get; set; } = default!; #pragma warning restore CA1707 // Identifiers should not contain underscores } + /// + /// Related links for timeline. + /// public class TimelineInfoLinks { + /// + /// Self. + /// public string Self { get; set; } = default!; + /// + /// Posts url. + /// public string Posts { get; set; } = default!; } diff --git a/Timeline/Models/Http/TimelineController.cs b/Timeline/Models/Http/TimelineController.cs index 3e2e6b58..aad361ee 100644 --- a/Timeline/Models/Http/TimelineController.cs +++ b/Timeline/Models/Http/TimelineController.cs @@ -4,33 +4,66 @@ using Timeline.Models.Validation; namespace Timeline.Models.Http { + /// + /// Content of post create request. + /// public class TimelinePostCreateRequestContent { + /// + /// Type of post content. + /// [Required] public string Type { get; set; } = default!; + /// + /// If post is of text type, this is the text. + /// public string? Text { get; set; } + /// + /// If post is of image type, this is base64 of image data. + /// public string? Data { get; set; } } public class TimelinePostCreateRequest { + /// + /// Content of the new post. + /// [Required] public TimelinePostCreateRequestContent Content { get; set; } = default!; + /// + /// Time of the post. If not set, current time will be used. + /// public DateTime? Time { get; set; } } + /// + /// Create timeline request model. + /// public class TimelineCreateRequest { + /// + /// Name of the new timeline. Must be a valid name. + /// [Required] [TimelineName] public string Name { get; set; } = default!; } + /// + /// Patch timeline request model. + /// public class TimelinePatchRequest { + /// + /// New description. Null for not change. + /// public string? Description { get; set; } + /// + /// New visibility. Null for not change. + /// public TimelineVisibility? Visibility { get; set; } } } diff --git a/Timeline/Models/Http/UserController.cs b/Timeline/Models/Http/UserController.cs index ea30a0ea..6bc5a66e 100644 --- a/Timeline/Models/Http/UserController.cs +++ b/Timeline/Models/Http/UserController.cs @@ -82,14 +82,8 @@ namespace Timeline.Models.Http public string NewPassword { get; set; } = default!; } - /// - /// - /// public class UserControllerAutoMapperProfile : Profile { - /// - /// - /// public UserControllerAutoMapperProfile() { CreateMap(MemberList.Source); diff --git a/Timeline/Models/Http/UserInfo.cs b/Timeline/Models/Http/UserInfo.cs index c9a26072..d92a12c4 100644 --- a/Timeline/Models/Http/UserInfo.cs +++ b/Timeline/Models/Http/UserInfo.cs @@ -2,26 +2,55 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; -using System; using Timeline.Controllers; namespace Timeline.Models.Http { + /// + /// Info of a user. + /// public class UserInfo { + /// + /// Unique id. + /// public string UniqueId { get; set; } = default!; + /// + /// Username. + /// public string Username { get; set; } = default!; + /// + /// Nickname. + /// public string Nickname { get; set; } = default!; + /// + /// True if the user is a administrator. + /// public bool? Administrator { get; set; } = default!; #pragma warning disable CA1707 // Identifiers should not contain underscores + /// + /// Related links. + /// public UserInfoLinks _links { get; set; } = default!; #pragma warning restore CA1707 // Identifiers should not contain underscores } + /// + /// Related links for user. + /// public class UserInfoLinks { + /// + /// Self. + /// public string Self { get; set; } = default!; + /// + /// Avatar url. + /// public string Avatar { get; set; } = default!; + /// + /// Personal timeline url. + /// public string Timeline { get; set; } = default!; } -- cgit v1.2.3