Compare commits
215 Commits
Author | SHA1 | Date |
---|---|---|
Paul Schneider | e8eee642c2 | 1 year ago |
Paul Schneider | 34d0c3c4fe | 2 years ago |
Paul Schneider | dc30540e40 | 2 years ago |
Paul Schneider | 6f79be26d8 | 2 years ago |
Paul Schneider | ca079e1c47 | 2 years ago |
Paul Schneider | 4f040be236 | 2 years ago |
Paul Schneider | 70f6e411e5 | 2 years ago |
Paul Schneider | 3695c17429 | 2 years ago |
Paul Schneider | 282b0277ae | 2 years ago |
Paul Schneider | 18b67bd725 | 2 years ago |
Paul Schneider | 51dcb39c93 | 2 years ago |
Paul Schneider | a7ea749d2c | 2 years ago |
Paul Schneider | 95600facf4 | 2 years ago |
Paul Schneider | 58f77a06ea | 2 years ago |
Paul Schneider | 88c8480911 | 2 years ago |
Paul Schneider | c147eaf54a | 2 years ago |
Paul Schneider | e49db8e1a1 | 2 years ago |
Paul Schneider | 9aac183e2c | 2 years ago |
Paul Schneider | 037559a0b7 | 2 years ago |
Paul Schneider | 9c4d45b97c | 2 years ago |
Paul Schneider | 9aa3140a11 | 2 years ago |
Paul Schneider | 7f9344d437 | 2 years ago |
Paul Schneider | f46ca00de9 | 2 years ago |
Paul Schneider | fcea41f8c1 | 2 years ago |
Paul Schneider | 58f49af5f0 | 2 years ago |
Paul Schneider | fececb327e | 2 years ago |
Paul Schneider | 14206ac477 | 2 years ago |
Paul Schneider | fa9a12ad49 | 2 years ago |
Paul Schneider | 7f9984b059 | 2 years ago |
Paul Schneider | 2dcf1a2806 | 2 years ago |
Paul Schneider | a84e1d9750 | 2 years ago |
Paul Schneider | 97eba2390e | 2 years ago |
Paul Schneider | 6c9f29bc56 | 2 years ago |
Paul Schneider | 2d5438c943 | 2 years ago |
Paul Schneider | 519a4fbd46 | 2 years ago |
Paul Schneider | a11bab759e | 2 years ago |
Paul Schneider | d7f0a5db36 | 2 years ago |
Paul Schneider | 5d59760a77 | 2 years ago |
Paul Schneider | 3e09afcbfe | 2 years ago |
Paul Schneider | 8fa4c04367 | 2 years ago |
Paul Schneider | 60e4ca8c54 | 2 years ago |
Paul Schneider | da92b9dbec | 2 years ago |
Paul Schneider | 6194e185b9 | 2 years ago |
Paul Schneider | 5c1a49811a | 2 years ago |
Paul Schneider | 328f6f166a | 2 years ago |
Paul Schneider | 4191513eef | 2 years ago |
Paul Schneider | 217cc49019 | 2 years ago |
Paul Schneider | a4a1c6e271 | 2 years ago |
Paul Schneider | c06f518836 | 2 years ago |
Paul Schneider | edc9628b67 | 2 years ago |
Paul Schneider | 4bb43877c7 | 2 years ago |
Paul Schneider | ce8b7bcdb3 | 2 years ago |
Paul Schneider | 67ec19184b | 2 years ago |
Paul Schneider | 57609e6ed3 | 2 years ago |
Paul Schneider | b46e786ace | 2 years ago |
Paul Schneider | 423f9c15b3 | 2 years ago |
Paul Schneider | 6d21d7370c | 2 years ago |
Paul Schneider | ee07affbbd | 2 years ago |
Paul Schneider | cba0720150 | 2 years ago |
Paul Schneider | a2d91e072f | 2 years ago |
Paul Schneider | 1befc2e053 | 2 years ago |
Paul Schneider | df55836c58 | 3 years ago |
Paul Schneider | cd3629a5a0 | 3 years ago |
Paul Schneider | 51a08dec9a | 3 years ago |
Paul Schneider | 386eec262d | 3 years ago |
Paul Schneider | 45d6c22d1e | 3 years ago |
Paul Schneider | 225c8ef588 | 3 years ago |
Paul Schneider | 290a3047b5 | 3 years ago |
Paul Schneider | ec70927830 | 3 years ago |
Paul Schneider | 9f338ca09f | 3 years ago |
Paul Schneider | cfd63fe68d | 3 years ago |
Paul Schneider | f33ca22255 | 3 years ago |
Paul Schneider | e6f4349621 | 3 years ago |
Paul Schneider | 903f5157d2 | 3 years ago |
Paul Schneider | 066c038e4d | 3 years ago |
Paul Schneider | 95aae91156 | 3 years ago |
Paul Schneider | 6dd76ac1a5 | 3 years ago |
Paul Schneider | 459f8ea422 | 3 years ago |
Paul Schneider | 5607c53329 | 3 years ago |
Paul Schneider | 71de903f13 | 3 years ago |
Paul Schneider | a92bee32e1 | 3 years ago |
Paul Schneider | 7a835c5c95 | 3 years ago |
Paul Schneider | f918d26273 | 3 years ago |
Paul Schneider | 25d545e327 | 3 years ago |
Paul Schneider | 57feb53e82 | 3 years ago |
Paul Schneider | b7dae240cd | 3 years ago |
Paul Schneider | d8bfdc293d | 3 years ago |
Paul Schneider | f6fa7a0ec9 | 3 years ago |
Paul Schneider | 55e407d951 | 3 years ago |
Paul Schneider | cdb9a26d2c | 3 years ago |
Paul Schneider | 504f431937 | 3 years ago |
Paul Schneider | 7da74b0dfb | 3 years ago |
Paul Schneider | 6520d8e4cc | 3 years ago |
Paul Schneider | 55b74a584a | 3 years ago |
Paul Schneider | 0ec9889e96 | 3 years ago |
Paul Schneider | b17ee8be75 | 3 years ago |
Paul Schneider | f6f3473346 | 3 years ago |
Paul Schneider | ae114c68db | 3 years ago |
Paul Schneider | 5f0dfee768 | 3 years ago |
Paul Schneider | 9ee058e1c8 | 3 years ago |
Paul Schneider | 30d81c06df | 3 years ago |
Paul Schneider | 3845e2c9c4 | 3 years ago |
Paul Schneider | 74427cc15e | 3 years ago |
Paul Schneider | 5c188b57fc | 3 years ago |
Paul Schneider | 74ffc8e83e | 3 years ago |
Paul Schneider | 7f0518ec82 | 3 years ago |
Paul Schneider | 58750587d0 | 3 years ago |
Paul Schneider | bd1c47e7c6 | 3 years ago |
Paul Schneider | f7b375ad50 | 3 years ago |
Paul Schneider | 558d5fc8ae | 3 years ago |
Paul Schneider | fff4599ff4 | 3 years ago |
Paul Schneider | e356636539 | 3 years ago |
Paul Schneider | 1aef7ce614 | 3 years ago |
Paul Schneider | 82cec8eece | 3 years ago |
Paul Schneider | cd7c0be03d | 3 years ago |
Paul Schneider | a345992351 | 3 years ago |
Paul Schneider | 5e74b24439 | 3 years ago |
Paul Schneider | 451d810ade | 3 years ago |
Paul Schneider | 6f82a0a00f | 3 years ago |
Paul Schneider | 48ca2df19e | 3 years ago |
Paul Schneider | 355b2d4c7c | 3 years ago |
Paul Schneider | d33a19d35f | 3 years ago |
Paul Schneider | 5a783edac2 | 3 years ago |
Paul Schneider | 32d25733af | 3 years ago |
Paul Schneider | 709e1433bb | 3 years ago |
Paul Schneider | 476d35ae8a | 3 years ago |
Paul Schneider | 5de53a3cba | 3 years ago |
Paul Schneider | ae6abc104a | 3 years ago |
Paul Schneider | eba75d0db4 | 3 years ago |
Paul Schneider | aaa49788dc | 3 years ago |
Paul Schneider | b8809deaa1 | 3 years ago |
Paul Schneider | 6fcad7c252 | 3 years ago |
Paul Schneider | 2c31ffb7c4 | 3 years ago |
Paul Schneider | 58501329ac | 3 years ago |
Paul Schneider | 8c25889e88 | 3 years ago |
Paul Schneider | 90b8913e98 | 3 years ago |
Paul Schneider | c88dccd950 | 3 years ago |
Paul Schneider | 963ce8579c | 3 years ago |
Paul Schneider | 1c1964eb2c | 3 years ago |
Paul Schneider | a5d6e08945 | 3 years ago |
Paul Schneider | 21b51d4cbd | 3 years ago |
Paul Schneider | 27634c3159 | 3 years ago |
Paul Schneider | a11c30e782 | 3 years ago |
Paul Schneider | 5cb35f54d5 | 3 years ago |
Paul Schneider | 981f3209e0 | 3 years ago |
Paul Schneider | 3fa1241ea2 | 3 years ago |
Paul Schneider | c14adcdd80 | 3 years ago |
Paul Schneider | 25069e5aa2 | 3 years ago |
Paul Schneider | b341fdfa4d | 3 years ago |
Paul Schneider | e88763df09 | 3 years ago |
Paul Schneider | c456a28282 | 3 years ago |
Paul Schneider | f7cfeeba8d | 3 years ago |
Paul Schneider | 7752620bef | 3 years ago |
Paul Schneider | 4fa03c5a1d | 3 years ago |
Paul Schneider | 61ba3b2bf8 | 3 years ago |
Paul Schneider | 1266dd54db | 3 years ago |
Paul Schneider | be30ef3c25 | 3 years ago |
Paul Schneider | 41fbe54638 | 3 years ago |
Paul Schneider | d80271dcbf | 3 years ago |
Paul Schneider | 3a59b8304a | 3 years ago |
Paul Schneider | f6a27fa919 | 3 years ago |
Paul Schneider | e51da7f359 | 3 years ago |
Paul Schneider | e4511a8aaa | 3 years ago |
Paul Schneider | 9575dd2754 | 3 years ago |
Paul Schneider | 54a900c361 | 3 years ago |
Paul Schneider | efb004ee08 | 3 years ago |
Paul Schneider | e0a3ec0bd5 | 3 years ago |
Paul Schneider | d7cabaad8b | 3 years ago |
Paul Schneider | 9adad9a327 | 3 years ago |
Paul Schneider | 3d3a6cf017 | 3 years ago |
Paul Schneider | 2f4ff1e774 | 3 years ago |
Paul Schneider | 9289b3af91 | 3 years ago |
Paul Schneider | 90cfc29492 | 3 years ago |
Paul Schneider | c83ff84370 | 3 years ago |
Paul Schneider | d117f26c77 | 3 years ago |
Paul Schneider | c2f38800aa | 3 years ago |
Paul Schneider | a8c9b7619f | 3 years ago |
Paul Schneider | 97dec15153 | 3 years ago |
Paul Schneider | 512495d10b | 3 years ago |
Paul Schneider | 5bbcf9cb29 | 3 years ago |
Paul Schneider | b6098c28a6 | 3 years ago |
Paul Schneider | 36e1137e50 | 3 years ago |
Paul Schneider | 3086cc65c4 | 3 years ago |
Paul Schneider | 4cec5d0229 | 3 years ago |
Paul Schneider | 61dc82df5b | 3 years ago |
Paul Schneider | db6f514fb5 | 3 years ago |
Paul Schneider | cc675844b6 | 3 years ago |
Paul Schneider | f95765f541 | 3 years ago |
Paul Schneider | e5d3ba36cc | 3 years ago |
Paul Schneider | ffb7cad00a | 3 years ago |
Paul Schneider | 6a59f776d5 | 3 years ago |
Paul Schneider | 93394b3e82 | 3 years ago |
Paul Schneider | d063f10da5 | 3 years ago |
Paul Schneider | bb02706773 | 3 years ago |
Paul Schneider | 915736c4e2 | 3 years ago |
Paul Schneider | b550f05c4f | 3 years ago |
Paul Schneider | dd4dd9321b | 3 years ago |
Paul Schneider | a238bd8cbf | 3 years ago |
Paul Schneider | fb822b6aaf | 3 years ago |
Paul Schneider | ffd1dca16e | 3 years ago |
Paul Schneider | 198189ab09 | 3 years ago |
Paul Schneider | ccbdd155f3 | 3 years ago |
Paul Schneider | 445ea24dd2 | 3 years ago |
Paul Schneider | 48df937b7f | 3 years ago |
Paul Schneider | 10b1fd0748 | 3 years ago |
Paul Schneider | 15fa91138d | 3 years ago |
Paul Schneider | dd6d83cf06 | 3 years ago |
Paul Schneider | 749eb645d5 | 3 years ago |
Paul Schneider | 838de379fd | 3 years ago |
Paul Schneider | dc37c9a9f0 | 3 years ago |
Paul Schneider | a2f26f1e8e | 3 years ago |
Paul Schneider | 1b2d850522 | 3 years ago |
Paul Schneider | ec5bd7ca1f | 3 years ago |
Paul Schneider | cede04a33e | 3 years ago |
Paul Schneider | 5b6d74d8ee | 4 years ago |
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<project name="Isn" default="clean" basedir=".">
|
||||||
|
<description>The Hello World of build files.</description>
|
||||||
|
<property name="debug" value="true" overwrite="false" />
|
||||||
|
|
||||||
|
<target name="clean" description="remove all generated files">
|
||||||
|
<delete dir="src/isn.abst/bin/" failonerror="false" />
|
||||||
|
<delete dir="src/isn.abst/obj/" failonerror="false" />
|
||||||
|
<delete dir="src/isn/bin/" failonerror="false" />
|
||||||
|
<delete dir="src/isn/obj/" failonerror="false" />
|
||||||
|
<delete dir="src/isnd/bin/" failonerror="false" />
|
||||||
|
<delete dir="src/isnd/obj/" failonerror="false" />
|
||||||
|
<delete dir="test/isn.tests/bin/" failonerror="false" />
|
||||||
|
<delete dir="test/isn.tests/obj/" failonerror="false" />
|
||||||
|
<delete dir="test/isnd.tests/bin/" failonerror="false" />
|
||||||
|
<delete dir="test/isnd.tests/obj/" failonerror="false" />
|
||||||
|
</target>
|
||||||
|
<target name="build" description="build all">
|
||||||
|
<exec program="dotnet" commandline="build" />
|
||||||
|
</target>
|
||||||
|
<target name="test" description="test all">
|
||||||
|
<exec program="dotnet" commandline="test" />
|
||||||
|
</target>
|
||||||
|
</project>
|
@ -1,3 +1,23 @@
|
|||||||
|
.sass-cache/
|
||||||
|
/src/isnd/bin/
|
||||||
|
/src/isnd/obj/
|
||||||
|
/src/isn/obj
|
||||||
|
/src/isn/bin
|
||||||
|
/src/isn/.vscode/
|
||||||
|
/test/isnd.tests/obj/
|
||||||
|
/test/isnd.tests/bin/
|
||||||
/packages/
|
/packages/
|
||||||
/bin/
|
bower_components/
|
||||||
/obj/
|
/test/isn.tests/bin
|
||||||
|
/test/isn.tests/obj/
|
||||||
|
appsettings.Testing.json
|
||||||
|
appsettings.Development.json
|
||||||
|
/wwwroot/.sass-cache/
|
||||||
|
/src/isnd/wwwroot/.sass-cache/
|
||||||
|
/src/isn.abst/bin
|
||||||
|
/src/isn.abst/obj
|
||||||
|
/src/isnd/packages/
|
||||||
|
/test/data/test-isn/bin/
|
||||||
|
/test/data/test-isn/obj
|
||||||
|
.fake
|
||||||
|
artifacts/
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
# You can override the included template(s) by including variable overrides
|
||||||
|
# See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
|
||||||
|
# Note that environment variables can be set in several places
|
||||||
|
# See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
|
||||||
|
image: busybox:latest
|
||||||
|
before_script:
|
||||||
|
- dotnet restore
|
||||||
|
- dotnet nuget remove source gitlab || true
|
||||||
|
nonreg:
|
||||||
|
tags:
|
||||||
|
- dotnet
|
||||||
|
stage: test
|
||||||
|
environment: Development
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
echo "setting : $ISND_TESTING_SETTINGS"
|
||||||
|
dotnet build
|
||||||
|
cat $ISND_TESTING_SETTINGS > test/isnd.tests/appsettings.json
|
||||||
|
dotnet test
|
||||||
|
publish:
|
||||||
|
tags:
|
||||||
|
- dotnet
|
||||||
|
stage: deploy
|
||||||
|
dependencies:
|
||||||
|
- nonreg
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- src/isnd/bin/Release/netcoreapp2.1/publish/
|
||||||
|
when: always
|
||||||
|
script:
|
||||||
|
- dotnet publish --configuration Release
|
||||||
|
deploy-to-gitlab:
|
||||||
|
tags:
|
||||||
|
- dotnet
|
||||||
|
stage: deploy
|
||||||
|
dependencies:
|
||||||
|
- nonreg
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- src/*/bin/Release/*.nupkg
|
||||||
|
when: always
|
||||||
|
script:
|
||||||
|
- dotnet pack -c Release
|
||||||
|
- dotnet nuget add source --name gitlab --username gitlab+deploy-token-2 --password
|
||||||
|
$CI_JOB_TOKEN --store-password-in-clear-text "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json"
|
||||||
|
- dotnet nuget push src/*/bin/Release/*.nupkg -s gitlab
|
||||||
|
deploy-to-isn:
|
||||||
|
stage: deploy
|
||||||
|
tags:
|
||||||
|
- dotnet
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- src/*/bin/Release/*.nupkg
|
||||||
|
when: always
|
||||||
|
script:
|
||||||
|
- dotnet pack --configuration Release --no-restore
|
||||||
|
- cd src/isn
|
||||||
|
- find -name "*.nupkg" -exec dotnet run push -s $ISNSOURCE -k $ISNAPIKEY {} \;
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
url: $ISNSOURCE
|
||||||
|
dependencies:
|
||||||
|
- nonreg
|
||||||
|
stages:
|
||||||
|
- test
|
||||||
|
- deploy
|
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"omnisharp.msbuild": true,
|
||||||
|
"dotnet-test-explorer.testProjectPath": "**/*tests.csproj",
|
||||||
|
"dotnet-test-explorer.runInParallel": false,
|
||||||
|
"dotnet-test-explorer.showCodeLens": true,
|
||||||
|
"dotnet-test-explorer.testArguments": "",
|
||||||
|
"nxunitExplorer.modules": [
|
||||||
|
"test/i*/bin/Debug/*/*.tests.dll"
|
||||||
|
],
|
||||||
|
"nxunitExplorer.skippattern": "",
|
||||||
|
"dotnetCoreExplorer.runEnvVars": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetCoreExplorer.searchpatterns": "test/**/bin/**/*.tests.{dll,exe}",
|
||||||
|
"sqltools.connections": [
|
||||||
|
{
|
||||||
|
"previewLimit": 50,
|
||||||
|
"server": "localhost",
|
||||||
|
"port": 5432,
|
||||||
|
"driver": "PostgreSQL",
|
||||||
|
"name": "isndev",
|
||||||
|
"group": "isn",
|
||||||
|
"database": "dotnetmvc",
|
||||||
|
"username": "dotnetmvc",
|
||||||
|
"password": "RvJa=y#b/tfg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"previewLimit": 50,
|
||||||
|
"server": "localhost",
|
||||||
|
"port": 5432,
|
||||||
|
"askForPassword": true,
|
||||||
|
"driver": "PostgreSQL",
|
||||||
|
"name": "isnd",
|
||||||
|
"group": "isn",
|
||||||
|
"database": "webid",
|
||||||
|
"username": "webid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"previewLimit": 50,
|
||||||
|
"server": "localhost",
|
||||||
|
"port": 5432,
|
||||||
|
"askForPassword": true,
|
||||||
|
"driver": "PostgreSQL",
|
||||||
|
"name": "isnddev",
|
||||||
|
"group": "isn",
|
||||||
|
"database": "isnd",
|
||||||
|
"username": "paul"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"omnisharp.disableMSBuildDiagnosticWarning": true,
|
||||||
|
"omnisharp.enableRoslynAnalyzers": false
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace {{namespace}}
|
||||||
|
{
|
||||||
|
public class {{name}}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export class {{name}} {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
Imports System
|
||||||
|
|
||||||
|
Namespace {{namespace}}
|
||||||
|
|
||||||
|
Public Class {{name}}
|
||||||
|
|
||||||
|
End Class
|
||||||
|
|
||||||
|
End Namespace
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {{name}} {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace {{namespace}}
|
||||||
|
{
|
||||||
|
public enum {{name}}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace {{namespace}}
|
||||||
|
{
|
||||||
|
public interface {{name}}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export interface {{name}} {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"name": "Class",
|
||||||
|
"extension": "cs",
|
||||||
|
"file": "./class.cs-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Interface",
|
||||||
|
"extension": "cs",
|
||||||
|
"file": "./interface.cs-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Enum",
|
||||||
|
"extension": "cs",
|
||||||
|
"file": "./enum.cs-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Class",
|
||||||
|
"extension": "ts",
|
||||||
|
"file": "./class.ts-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Interface",
|
||||||
|
"extension": "ts",
|
||||||
|
"file": "./interface.ts-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Default",
|
||||||
|
"extension": "ts",
|
||||||
|
"file": "./default.ts-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Class",
|
||||||
|
"extension": "vb",
|
||||||
|
"file": "./class.vb-template",
|
||||||
|
"parameters": "./template-parameters.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
module.exports = function(filename, projectPath, folderPath) {
|
||||||
|
var namespace = "Unknown";
|
||||||
|
if (projectPath) {
|
||||||
|
namespace = path.basename(projectPath, path.extname(projectPath));
|
||||||
|
if (folderPath) {
|
||||||
|
namespace += "." + folderPath.replace(path.dirname(projectPath), "").substring(1).replace(/[\\\/]/g, ".");
|
||||||
|
}
|
||||||
|
namespace = namespace.replace(/[\\\-]/g, "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
namespace: namespace,
|
||||||
|
name: path.basename(filename, path.extname(filename))
|
||||||
|
}
|
||||||
|
};
|
@ -1,113 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using NuGet.Packaging;
|
|
||||||
|
|
||||||
namespace nuget_host.Controllers
|
|
||||||
{
|
|
||||||
public class PackagesController : Controller
|
|
||||||
{
|
|
||||||
private ILogger<PackagesController> logger;
|
|
||||||
|
|
||||||
public PackagesController(ILoggerFactory loggerFactory)
|
|
||||||
{
|
|
||||||
logger = loggerFactory.CreateLogger<PackagesController>();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("packages/{*spec}")]
|
|
||||||
public IActionResult Put(string spec)
|
|
||||||
{
|
|
||||||
string path = null;
|
|
||||||
if (string.IsNullOrEmpty(spec))
|
|
||||||
{
|
|
||||||
var clientVersionId = Request.Headers["X-NuGet-Client-Version"];
|
|
||||||
ViewData["nuget client "] = "nuget {clientVersionId}";
|
|
||||||
foreach (var file in Request.Form.Files)
|
|
||||||
{
|
|
||||||
string initpath = "package.nupkg";
|
|
||||||
using (FileStream fw = new FileStream(initpath, FileMode.Create))
|
|
||||||
{
|
|
||||||
file.CopyTo(fw);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (FileStream fw = new FileStream(initpath, FileMode.Open))
|
|
||||||
{
|
|
||||||
var archive = new System.IO.Compression.ZipArchive(fw);
|
|
||||||
foreach (var filename in archive.GetFiles())
|
|
||||||
{
|
|
||||||
if (filename.EndsWith(".nuspec"))
|
|
||||||
{
|
|
||||||
// var entry = archive.GetEntry(filename);
|
|
||||||
var specstr = archive.OpenFile(filename);
|
|
||||||
NuspecReader reader = new NuspecReader(specstr);
|
|
||||||
|
|
||||||
string pkgdesc = reader.GetDescription();
|
|
||||||
string pkgid = reader.GetId();
|
|
||||||
var version = reader.GetVersion();
|
|
||||||
|
|
||||||
|
|
||||||
path = Path.Combine(Startup.SourceDir,
|
|
||||||
Path.Combine(pkgid,
|
|
||||||
Path.Combine(version.ToFullString(),
|
|
||||||
$"{pkgid}-{version}.nupkg")));
|
|
||||||
var source = new FileInfo(initpath);
|
|
||||||
var dest = new FileInfo(path);
|
|
||||||
var destdir = new DirectoryInfo(dest.DirectoryName);
|
|
||||||
if (dest.Exists)
|
|
||||||
return BadRequest(new {error = "existant"});
|
|
||||||
|
|
||||||
if (!destdir.Exists) destdir.Create();
|
|
||||||
source.MoveTo(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ViewData["spec"] = spec;
|
|
||||||
// TODO Assert valid sem ver spec
|
|
||||||
var filelst = new DirectoryInfo(Startup.SourceDir);
|
|
||||||
var fi = new FileInfo(spec);
|
|
||||||
var lst = filelst.GetFiles(fi.Name + "*.nupkg");
|
|
||||||
ViewData["lst"] = lst.Select(entry => entry.Name);
|
|
||||||
}
|
|
||||||
return Ok(ViewData);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("Packages/{spec}")]
|
|
||||||
public IActionResult Index(string spec)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(spec))
|
|
||||||
{
|
|
||||||
ViewData["warn"] = "no spec";
|
|
||||||
/*
|
|
||||||
usr/lib/mono/msbuild/Current/bin/NuGet.targets(128,5): error : Failed to retrieve information about 'Microsoft.VisualStudio.Web.CodeGeneration.Tools' from remote source 'http://localhost:5000/Packages/FindPackagesById()?id='Microsoft.VisualStudio.Web.CodeGeneration.Tools'&semVerLevel=2.0.0'. [/home/paul/workspace/nuget-host/nuget-host.csproj]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ViewData["spec"] = spec;
|
|
||||||
// TODO Assert valid sem ver spec
|
|
||||||
var filelst = new DirectoryInfo(Startup.SourceDir);
|
|
||||||
var fi = new FileInfo(spec);
|
|
||||||
var lst = filelst.GetDirectories(spec);
|
|
||||||
ViewData["lst"] = lst.Select(entry => entry.Name);
|
|
||||||
}
|
|
||||||
return Ok(ViewData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,5 @@
|
|||||||
|
mode: Mainline
|
||||||
|
branches: {}
|
||||||
|
ignore:
|
||||||
|
sha: []
|
||||||
|
merge-message-formats: {}
|
@ -0,0 +1,14 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace nuget_host.Models
|
|
||||||
{
|
|
||||||
public class ErrorViewModel
|
|
||||||
{
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,82 @@
|
|||||||
# Usage
|
# ISN
|
||||||
|
|
||||||
|
FIXME
|
||||||
|
|
||||||
|
````log
|
||||||
|
NU1301: Failed to retrieve information about 'xxx' from remote source 'https://isn.pschneider.fr/nupkg/xxx/index.json'.
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
````sh
|
````sh
|
||||||
|
|
||||||
nuget sources remove -Name dev
|
dotnet user-secrets set ConnectionStrings:DefaultConnection "Server=<lame-pgserver>;Port=<lame-pgport>;Database=<lame-dbname>;Username=<lame-dbusername>;Password=<lame-dbpass>;"
|
||||||
nuget sources add -Name dev -Source Http://localhost:5000/packages
|
|
||||||
nuget push your-versionned.nupkg -ApiKey 15d0dda1-4028-4896-9f1a-188817da23f4 -Source http://localhost:5000/packages
|
isnd&
|
||||||
|
|
||||||
|
# get an api-key from <http://localhost:5000/ApkKeys>
|
||||||
|
|
||||||
|
isn push -k <lame-api-key> -s http://localhost:5000/index.json your-lame-versionned.nupkg
|
||||||
|
wget http://localhost:5000/package/index.json?q=your&prerelease=true&semVerLevel=2.0.0
|
||||||
|
````
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Depuis le dossier de la solution, compiler la solution :
|
||||||
|
|
||||||
|
````bash
|
||||||
|
dotnet build /restore -c Release
|
||||||
|
dotnet publish -c Release
|
||||||
|
````
|
||||||
|
|
||||||
|
### Déploiement
|
||||||
|
|
||||||
|
````bash
|
||||||
|
sudo mkdir -p /srv/www/isnd
|
||||||
|
sudo cp -a src/isnd/bin/Release/net6.0/publish/* /srv/www/isnd
|
||||||
|
sudo cp contrib/isnd /etc/init.d/isnd
|
||||||
|
sudo chmod +x /etc/init.d/isnd
|
||||||
|
sudo chown -R www-data.www-data /srv/www/isnd
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
````
|
||||||
|
|
||||||
|
* Créer une base de donées Postgresql,
|
||||||
|
* ajuster un fichier de configuration `/srv/www/isnd/appsettings.Production.json`
|
||||||
|
* Démarrer le serveur :
|
||||||
|
|
||||||
|
````bash
|
||||||
|
sudo systemctl start isnd
|
||||||
|
````
|
||||||
|
|
||||||
|
* Activation du serveur :
|
||||||
|
|
||||||
|
````bash
|
||||||
|
sudo systemctl enable isnd
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
|
### Installation du client
|
||||||
|
|
||||||
|
````bash
|
||||||
|
sudo mkdir /usr/local/lib/isn
|
||||||
|
sudo cp -a src/isn/bin/Release/net6.0/* /usr/local/lib/isn
|
||||||
|
sudo chown -R root.root /usr/local/lib/isn
|
||||||
|
sudo ln -s /usr/local/lib/isn/isn /usr/local/bin/isn
|
||||||
|
````
|
||||||
|
|
||||||
|
### Mises à jour
|
||||||
|
|
||||||
|
````bash
|
||||||
|
set -e
|
||||||
|
# compiler tout
|
||||||
|
dotnet build -c Release
|
||||||
|
dotnet publish -c Release -f net7.0 src/isnd
|
||||||
|
# MAJ du serveur
|
||||||
|
sudo systemctl stop isnd
|
||||||
|
sudo cp -a src/isnd/bin/Release/net7.0/publish/* /srv/www/isnd
|
||||||
|
sudo systemctl start isnd
|
||||||
|
# MAJ du client
|
||||||
|
sudo cp -a src/isn/bin/Release/net7.0/* /usr/local/lib/isn
|
||||||
|
sudo chown -R root.root /usr/local/lib/isn
|
||||||
````
|
````
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
@{
|
|
||||||
ViewData["Title"] = "Home Page";
|
|
||||||
}
|
|
||||||
|
|
||||||
<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="6000">
|
|
||||||
<ol class="carousel-indicators">
|
|
||||||
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
|
|
||||||
<li data-target="#myCarousel" data-slide-to="1"></li>
|
|
||||||
<li data-target="#myCarousel" data-slide-to="2"></li>
|
|
||||||
<li data-target="#myCarousel" data-slide-to="3"></li>
|
|
||||||
</ol>
|
|
||||||
<div class="carousel-inner" role="listbox">
|
|
||||||
<div class="item active">
|
|
||||||
<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
|
|
||||||
<div class="carousel-caption" role="option">
|
|
||||||
<p>
|
|
||||||
Learn how to build ASP.NET apps that can run anywhere.
|
|
||||||
<a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409">
|
|
||||||
Learn More
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<img src="~/images/banner2.svg" alt="Visual Studio" class="img-responsive" />
|
|
||||||
<div class="carousel-caption" role="option">
|
|
||||||
<p>
|
|
||||||
There are powerful new features in Visual Studio for building modern web apps.
|
|
||||||
<a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409">
|
|
||||||
Learn More
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<img src="~/images/banner3.svg" alt="Package Management" class="img-responsive" />
|
|
||||||
<div class="carousel-caption" role="option">
|
|
||||||
<p>
|
|
||||||
Bring in libraries from NuGet and npm, and automate tasks using Grunt or Gulp.
|
|
||||||
<a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkID=525029&clcid=0x409">
|
|
||||||
Learn More
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<img src="~/images/banner4.svg" alt="Microsoft Azure" class="img-responsive" />
|
|
||||||
<div class="carousel-caption" role="option">
|
|
||||||
<p>
|
|
||||||
Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.
|
|
||||||
<a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409">
|
|
||||||
Learn More
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
|
|
||||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
|
||||||
<span class="sr-only">Previous</span>
|
|
||||||
</a>
|
|
||||||
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
|
|
||||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
|
||||||
<span class="sr-only">Next</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<h2>Application uses</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Sample pages using ASP.NET Core MVC</li>
|
|
||||||
<li>Theming using <a href="https://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<h2>How to</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<h2>Overview</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<h2>Run & Deploy</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a></li>
|
|
||||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,22 +0,0 @@
|
|||||||
@model ErrorViewModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1 class="text-danger">Error.</h1>
|
|
||||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
|
||||||
|
|
||||||
@if (Model.ShowRequestId)
|
|
||||||
{
|
|
||||||
<p>
|
|
||||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>Development Mode</h3>
|
|
||||||
<p>
|
|
||||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
|
||||||
</p>
|
|
@ -1,71 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>@ViewData["Title"] - nuget_host</title>
|
|
||||||
|
|
||||||
<environment include="Development">
|
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
|
||||||
<link rel="stylesheet" href="~/css/site.css" />
|
|
||||||
</environment>
|
|
||||||
<environment exclude="Development">
|
|
||||||
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
|
|
||||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
|
||||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
|
|
||||||
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
|
|
||||||
</environment>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
|
||||||
<span class="sr-only">Toggle navigation</span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
</button>
|
|
||||||
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">nuget_host</a>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-collapse collapse">
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
|
|
||||||
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
|
|
||||||
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<div class="container body-content">
|
|
||||||
@RenderBody()
|
|
||||||
<hr />
|
|
||||||
<footer>
|
|
||||||
<p>© 2018 - nuget_host</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<environment include="Development">
|
|
||||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
|
||||||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
|
|
||||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
|
||||||
</environment>
|
|
||||||
<environment exclude="Development">
|
|
||||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
|
|
||||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
|
||||||
asp-fallback-test="window.jQuery"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
|
|
||||||
</script>
|
|
||||||
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
|
|
||||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
|
|
||||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
|
|
||||||
</script>
|
|
||||||
<script src="~/js/site.min.js" asp-append-version="true"></script>
|
|
||||||
</environment>
|
|
||||||
|
|
||||||
@RenderSection("Scripts", required: false)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,3 +0,0 @@
|
|||||||
@using nuget_host
|
|
||||||
@using nuget_host.Models
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
/usr/bin/mono /usr/local/lib/isn/isn.exe $*
|
@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: isnd
|
||||||
|
# Required-Start: $local_fs $network $named $time $syslog $postgresql
|
||||||
|
# Required-Stop: $local_fs $network $named $time $syslog $postgresql
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Description: Script to run asp.net 5 application in background
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
# Author: Ivan Derevianko aka druss <drussilla7@gmail.com>
|
||||||
|
# Modified by: Paul Schneider <redienhcs.luap@gmail.com>
|
||||||
|
|
||||||
|
. /lib/init/vars.sh
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
NAME=isnd
|
||||||
|
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
|
|
||||||
|
TMP_SAVE_runlevel_VAR=$runlevel
|
||||||
|
unset runlevel
|
||||||
|
|
||||||
|
running() {
|
||||||
|
if [ -f $PIDFILE ]
|
||||||
|
then
|
||||||
|
PID=$(cat $PIDFILE)
|
||||||
|
if kill -0 $PID 2>/dev/null
|
||||||
|
then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export WWW_USER=www-data
|
||||||
|
export ROOT=/srv/www/${NAME}
|
||||||
|
export DESC="$NAME"
|
||||||
|
export PIDFILE=/var/run/kestrel-${NAME}.pid
|
||||||
|
export LOGDIR=/var/log
|
||||||
|
export DOTNET_CLI_HOME=$ROOT
|
||||||
|
export ASPDOTNETCORE_ENVIRONMENT=Production
|
||||||
|
export ASPDOTNETCORE_LOGLEVEL=Information
|
||||||
|
status() {
|
||||||
|
if running;
|
||||||
|
then
|
||||||
|
echo "Service running $DESC ($NAME; pid: $PID)"
|
||||||
|
else
|
||||||
|
echo "Service stopped $DESC ($NAME)"
|
||||||
|
fi
|
||||||
|
echo WWW_USER: $WWW_USER ROOT:$ROOT DESC: $DESC NAME: $NAME PIDFILE: $PIDFILE LOGDIR=$LOGDIR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if running; then
|
||||||
|
echo "Service already running $DESC" "$NAME"
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
cd $ROOT
|
||||||
|
log_daemon_msg "Starting service $NAME for user $WWW_USER"
|
||||||
|
if ! start-stop-daemon -SbmCv -u $WWW_USER -p $PIDFILE -d $ROOT -g www-data -x /usr/bin/dotnet isnd.dll run > "${LOGDIR}/kestrel-${NAME}.log"
|
||||||
|
then
|
||||||
|
log_daemon_msg "Could not start $NAME : $?, see ${LOGDIR}/kestrel-${NAME}.log"
|
||||||
|
log_end_msg 2
|
||||||
|
else
|
||||||
|
log_daemon_msg "Service $DESC started ($NAME), logs: ${LOGDIR}/kestrel-${NAME}.log"
|
||||||
|
log_end_msg 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if running
|
||||||
|
then
|
||||||
|
log_daemon_msg "Stopping service $NAME"
|
||||||
|
start-stop-daemon -K -p "$PIDFILE"
|
||||||
|
log_daemon_msg "$DESC stopped"
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
log_daemon_msg "$DESC Service not running"
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
esac
|
||||||
|
|
||||||
|
export runlevel=$TMP_SAVE_runlevel_VAR
|
||||||
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<apikeys>
|
||||||
|
</apikeys>
|
||||||
|
<packageSources>
|
||||||
|
<add key="myIsnDev" value="http://localhost:5000/index.json" protocolVersion="3" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
@ -0,0 +1,2 @@
|
|||||||
|
nuget install -Verbosity detailed -Source http://localhost:5000/index.json -Prerelease Yavsc.Abstract
|
||||||
|
nuget locals all -clear
|
@ -0,0 +1,4 @@
|
|||||||
|
= URL's
|
||||||
|
|
||||||
|
<http://localhost:5000/v3.4.0/registration/yavsc.abstract/index.json>
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# compiler tout
|
||||||
|
dotnet build -c Release
|
||||||
|
dotnet publish -c Release -f netcoreapp2.1 src/isnd
|
||||||
|
# MAJ du serveur
|
||||||
|
sudo systemctl stop isnd
|
||||||
|
sudo cp -a src/isnd/bin/Release/netcoreapp2.1/publish/* /srv/www/isnd
|
||||||
|
sudo systemctl start isnd
|
||||||
|
# MAJ du client
|
||||||
|
sudo cp -a src/isn/bin/Release/netcoreapp2.1/* /usr/local/lib/isn
|
||||||
|
sudo chown -R root.root /usr/local/lib/isn
|
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"codecov.tool": {
|
||||||
|
"version": "1.13.0",
|
||||||
|
"commands": [
|
||||||
|
"codecov"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gitversion.tool": {
|
||||||
|
"version": "5.10.1",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-gitversion"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gitreleasemanager.tool": {
|
||||||
|
"version": "0.13.0",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-gitreleasemanager"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Wyam2.Tool": {
|
||||||
|
"version": "3.0.0-rc3",
|
||||||
|
"commands": [
|
||||||
|
"wyam2"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"dotnet": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"msbuild": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"Dnx": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"Script": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"fileOptions": {
|
||||||
|
"systemExcludeSearchPatterns": [
|
||||||
|
"**/bin/**/*",
|
||||||
|
"**/obj/**/*",
|
||||||
|
"**/node_modules/**/*"
|
||||||
|
],
|
||||||
|
"userExcludeSearchPatterns": []
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Entities
|
||||||
|
{
|
||||||
|
public static class ApiConfig
|
||||||
|
{
|
||||||
|
public const string Publish = "put";
|
||||||
|
public const string Index = "index";
|
||||||
|
public const string IndexDotJson = Index + ".json";
|
||||||
|
public const string Catalog = "catalog";
|
||||||
|
public const string CatalogPage = "catalog-page";
|
||||||
|
public const string GetPackage = Constants.PaquetFileEstension;
|
||||||
|
public const string GetVersion = "version";
|
||||||
|
public const string Search = "search";
|
||||||
|
public const string AutoComplete = "autocomplete";
|
||||||
|
public const string CatalogLeaf = "catalog-leaf";
|
||||||
|
public const string Delete = "delete";
|
||||||
|
public const string Registration = "registration";
|
||||||
|
internal const string GetNuspec = Constants.SpecFileEstension;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using isnd.Data.Catalog;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn.Abstract
|
||||||
|
{
|
||||||
|
public class ApiIndexViewModel : HappyIdOwner
|
||||||
|
{
|
||||||
|
public ApiIndexViewModel(string id) : base(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("@id")]
|
||||||
|
public string Id { get => GetId(); }
|
||||||
|
|
||||||
|
[JsonProperty("version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("resources")]
|
||||||
|
public Resource[] Resources { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace isn.abst
|
||||||
|
{
|
||||||
|
public static class Constants
|
||||||
|
{
|
||||||
|
public const string PaquetFileEstension = "nupkg";
|
||||||
|
public const string SpecFileEstension = "nuspec";
|
||||||
|
public const string JsonFileEstension = "json";
|
||||||
|
public const string PackageRootServerPrefix = "~/pkgs/";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isnd.Data.Catalog
|
||||||
|
{
|
||||||
|
public class HappyIdOwner
|
||||||
|
{
|
||||||
|
public HappyIdOwner(string id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string id;
|
||||||
|
|
||||||
|
public string GetId() { return id; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj!=null)
|
||||||
|
{
|
||||||
|
if (GetType().IsAssignableFrom(obj.GetType()))
|
||||||
|
{
|
||||||
|
var rpobj = (HappyIdOwner) obj;
|
||||||
|
return this.id == rpobj.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base.Equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return id.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using isnd.Data.Catalog;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn.Abstract
|
||||||
|
{
|
||||||
|
public class Resource : HappyIdOwner
|
||||||
|
{
|
||||||
|
public Resource(string id, string typename) : base(id)
|
||||||
|
{
|
||||||
|
Type = typename;
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("@id")]
|
||||||
|
public string Id {get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("@type")]
|
||||||
|
public string Type {get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("comment")]
|
||||||
|
public string Comment {get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace isnd.Attributes
|
||||||
|
{
|
||||||
|
public class SafeNameAttribute : ValidationAttribute
|
||||||
|
{
|
||||||
|
public override bool IsValid(object value)
|
||||||
|
{
|
||||||
|
if (!(value is string))
|
||||||
|
return false;
|
||||||
|
string str = value as string;
|
||||||
|
if (str.Length>126) return false;
|
||||||
|
if (str.Any(c => !char.IsLetterOrDigit(c)
|
||||||
|
&& !"-_.".Contains(c))) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
internal static class Constants
|
||||||
|
{
|
||||||
|
internal const string ClientVersion = "isn v1.0";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public interface IDataProtector
|
||||||
|
{
|
||||||
|
string Protect(string data);
|
||||||
|
string UnProtect(string data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DefaultDataProtector : IDataProtector
|
||||||
|
{
|
||||||
|
private byte delta = 145;
|
||||||
|
|
||||||
|
public DefaultDataProtector()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Protect(string data)
|
||||||
|
{
|
||||||
|
List<Byte> protd = new List<byte>();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (byte c in Encoding.UTF8.GetBytes(data))
|
||||||
|
{
|
||||||
|
protd.Add((byte) (c ^ delta));
|
||||||
|
}
|
||||||
|
return System.Convert.ToBase64String(protd.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UnProtect(string data)
|
||||||
|
{
|
||||||
|
if (data==null) return null;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
List<byte> unps = new List<byte>();
|
||||||
|
|
||||||
|
foreach (byte c in System.Convert.FromBase64CharArray(data.ToCharArray(),0,data.Length))
|
||||||
|
{
|
||||||
|
unps.Add((byte) (c ^ delta));
|
||||||
|
}
|
||||||
|
return Encoding.UTF8.GetString(unps.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public class IsnSourceSettings
|
||||||
|
{
|
||||||
|
internal string Source { get; set; }
|
||||||
|
|
||||||
|
internal string[] Keys { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public class IsndErrorMessage
|
||||||
|
{
|
||||||
|
public int ecode { get; set; }
|
||||||
|
public string msg { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public class SourceSettings
|
||||||
|
{
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
public string Alias { get; set; }
|
||||||
|
|
||||||
|
public string GetClearApiKey()
|
||||||
|
{
|
||||||
|
return Protector.UnProtect(ApiKey);
|
||||||
|
}
|
||||||
|
public void SetApiKey(string key)
|
||||||
|
{
|
||||||
|
ApiKey = Protector.Protect(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDataProtector Protector { get; set; } = new DefaultDataProtector();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string DataProtectionTitle { get; set; }
|
||||||
|
public Dictionary<string, SourceSettings> Sources { get; set; }
|
||||||
|
|
||||||
|
public bool AutoUpdateApiKey { get; set; } = false;
|
||||||
|
|
||||||
|
private string defSourceKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default source by its alias
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public string DefaultSourceKey
|
||||||
|
{
|
||||||
|
get => defSourceKey;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!Sources.ContainsKey(value))
|
||||||
|
{
|
||||||
|
Sources[value]=new SourceSettings
|
||||||
|
{
|
||||||
|
Alias = defSourceKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
defSourceKey = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using isn.Abstract;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public static class SourceHelpers
|
||||||
|
{
|
||||||
|
public static ApiIndexViewModel GetServerResources(string url)
|
||||||
|
{
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
ApiIndexViewModel result = null;
|
||||||
|
// var json = await client.GetStringAsync(new System.Uri(url));
|
||||||
|
|
||||||
|
Task.Run(async ()=> {
|
||||||
|
var response = await client.GetStringAsync(url);
|
||||||
|
result = JsonConvert.DeserializeObject<ApiIndexViewModel>(response);
|
||||||
|
}).Wait();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public static class UploadFilesToServerUsingHttpClient
|
||||||
|
{
|
||||||
|
public static PushReport UploadFilesToServer(this HttpClient client, Uri uri, FileInfo fi,
|
||||||
|
string apikey)
|
||||||
|
{
|
||||||
|
return UploadFilesToServerAsync(client, uri, fi, apikey).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<PushReport> UploadFilesToServerAsync(this HttpClient client, Uri uri, FileInfo fi,
|
||||||
|
string apikey)
|
||||||
|
{
|
||||||
|
|
||||||
|
client.DefaultRequestHeaders.Add("X-NuGet-Client-Version", Constants.ClientVersion);
|
||||||
|
client.DefaultRequestHeaders.Add("X-NuGet-ApiKey", apikey);
|
||||||
|
|
||||||
|
using (var multipartFormDataContent = new MultipartFormDataContent())
|
||||||
|
{
|
||||||
|
/* var values = new[]
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("Id", Guid.NewGuid().ToString()),
|
||||||
|
new KeyValuePair<string, string>("Key", "awesome"),
|
||||||
|
new KeyValuePair<string, string>("From", "khalid@home.com")
|
||||||
|
//other values
|
||||||
|
};foreach (var keyValuePair in values)
|
||||||
|
{
|
||||||
|
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
|
||||||
|
String.Format("\"{0}\"", keyValuePair.Key));
|
||||||
|
} */
|
||||||
|
multipartFormDataContent.Add(new ByteArrayContent(File.ReadAllBytes(fi.FullName)),
|
||||||
|
'"' + "File" + '"',
|
||||||
|
'"' + fi.Name + '"');
|
||||||
|
|
||||||
|
var result = await client.PutAsync(uri, multipartFormDataContent);
|
||||||
|
|
||||||
|
if (result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
string report = await result.Content.ReadAsStringAsync();
|
||||||
|
Console.WriteLine(report);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string ereport = await result.Content.ReadAsStringAsync();
|
||||||
|
Console.WriteLine(ereport);
|
||||||
|
}
|
||||||
|
return new PushReport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,195 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
public class UploadFilesToServerUsingWebRequest
|
||||||
|
{
|
||||||
|
public void UploadFilesToServer(PushReport report, Uri uri, FileInfo fi,
|
||||||
|
string apikey)
|
||||||
|
{
|
||||||
|
// string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
|
||||||
|
const int TXLEN = 0x1000;
|
||||||
|
/// the form-data file upload, properly formatted
|
||||||
|
string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";
|
||||||
|
|
||||||
|
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||||
|
|
||||||
|
// "X-NuGet-ApiKey
|
||||||
|
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
|
||||||
|
string fileheader = string.Format(fileheaderTemplate, "file", fi.Name, "application/octet-stream");
|
||||||
|
byte[] fileheaderbytes = Encoding.ASCII.GetBytes(fileheader);
|
||||||
|
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
|
||||||
|
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");
|
||||||
|
HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(uri);
|
||||||
|
|
||||||
|
httpWebRequest.Method = "PUT";
|
||||||
|
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||||
|
httpWebRequest.AllowAutoRedirect = false;
|
||||||
|
httpWebRequest.Headers.Add("X-NuGet-Client-Version", Constants.ClientVersion);
|
||||||
|
httpWebRequest.Headers.Add("X-NuGet-ApiKey", apikey);
|
||||||
|
httpWebRequest.ContentLength = boundarybytes.Length +
|
||||||
|
fileheaderbytes.Length + fi.Length + endBoundaryBytes.Length;
|
||||||
|
|
||||||
|
|
||||||
|
httpWebRequest.BeginGetRequestStream(async (result) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
|
||||||
|
|
||||||
|
using (Stream requestStream = request.EndGetRequestStream(result))
|
||||||
|
{
|
||||||
|
await WriteToStream(requestStream, boundarybytes, boundarybytes.Length);
|
||||||
|
await WriteToStream(requestStream, fileheaderbytes, fileheaderbytes.Length);
|
||||||
|
using (var fss = fi.OpenRead())
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[TXLEN];
|
||||||
|
var form_bytes_read = fss.Read(buffer, 0, TXLEN);
|
||||||
|
while (form_bytes_read > 0)
|
||||||
|
{
|
||||||
|
await WriteToStream(requestStream, buffer, form_bytes_read);
|
||||||
|
form_bytes_read = fss.Read(buffer, 0, TXLEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
|
||||||
|
requestStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception rex)
|
||||||
|
{
|
||||||
|
report.Executed = false;
|
||||||
|
report.StackTrace = rex.StackTrace;
|
||||||
|
report.Message = rex.Message;
|
||||||
|
Console.Error.WriteLine("Stack trace:");
|
||||||
|
Console.Error.WriteLine(rex.StackTrace);
|
||||||
|
WebResponse eresp = httpWebRequest.GetResponse();
|
||||||
|
if (!CheckResponse(eresp, report))
|
||||||
|
throw new Exception("Invalid server response type");
|
||||||
|
|
||||||
|
}
|
||||||
|
}, httpWebRequest);
|
||||||
|
|
||||||
|
WebResponse resp = httpWebRequest.GetResponse();
|
||||||
|
if (!CheckResponse(resp, report)) throw new Exception("Invalid server response type");
|
||||||
|
if (Program.Settings.AutoUpdateApiKey)
|
||||||
|
Program.EnsureKeyStored();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckResponse(WebResponse resp, PushReport report)
|
||||||
|
{
|
||||||
|
Stream stream = resp.GetResponseStream();
|
||||||
|
StreamReader re = new StreamReader(stream);
|
||||||
|
if (resp is HttpWebResponse)
|
||||||
|
{
|
||||||
|
if (resp.ContentType == "text/json")
|
||||||
|
{
|
||||||
|
String json = re.ReadToEnd();
|
||||||
|
report.Message = json;
|
||||||
|
var hrep = resp as HttpWebResponse;
|
||||||
|
report.StatusCode = hrep.StatusCode.ToString();
|
||||||
|
report.OK = hrep.StatusCode == HttpStatusCode.Accepted
|
||||||
|
|| hrep.StatusCode == HttpStatusCode.OK;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra
|
||||||
|
/// </summary>
|
||||||
|
internal async Task UploadFilesToServerAsync(PushReport report, Uri uri, FileInfo fi,
|
||||||
|
string apikey)
|
||||||
|
{
|
||||||
|
// string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
|
||||||
|
const int TXLEN = 0x1000;
|
||||||
|
/// the form-data file upload, properly formatted
|
||||||
|
string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";
|
||||||
|
|
||||||
|
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||||
|
|
||||||
|
// "X-NuGet-ApiKey
|
||||||
|
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
|
||||||
|
string fileheader = string.Format(fileheaderTemplate, "file", fi.Name, "application/octet-stream");
|
||||||
|
byte[] fileheaderbytes = Encoding.ASCII.GetBytes(fileheader);
|
||||||
|
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
|
||||||
|
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");
|
||||||
|
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
|
||||||
|
|
||||||
|
httpWebRequest.Method = "PUT";
|
||||||
|
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||||
|
httpWebRequest.AllowAutoRedirect = false;
|
||||||
|
httpWebRequest.Headers.Add("X-NuGet-Client-Version", Constants.ClientVersion);
|
||||||
|
httpWebRequest.Headers.Add("X-NuGet-ApiKey", apikey);
|
||||||
|
httpWebRequest.ContentLength = boundarybytes.Length +
|
||||||
|
fileheaderbytes.Length + fi.Length + endBoundaryBytes.Length;
|
||||||
|
|
||||||
|
|
||||||
|
httpWebRequest.BeginGetRequestStream(async (result) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
|
||||||
|
|
||||||
|
using (Stream requestStream = request.EndGetRequestStream(result))
|
||||||
|
{
|
||||||
|
await WriteToStream(requestStream, boundarybytes, boundarybytes.Length);
|
||||||
|
await WriteToStream(requestStream, fileheaderbytes, fileheaderbytes.Length);
|
||||||
|
using (var fss = fi.OpenRead())
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[TXLEN];
|
||||||
|
var form_bytes_read = fss.Read(buffer, 0, TXLEN);
|
||||||
|
while (form_bytes_read > 0)
|
||||||
|
{
|
||||||
|
await WriteToStream(requestStream, buffer, form_bytes_read);
|
||||||
|
form_bytes_read = fss.Read(buffer, 0, TXLEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
|
||||||
|
requestStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception rex)
|
||||||
|
{
|
||||||
|
report.Message = rex.Message;
|
||||||
|
Console.Error.WriteLine(rex.Message);
|
||||||
|
Console.Error.WriteLine("Stack trace:");
|
||||||
|
Console.Error.WriteLine(rex.StackTrace);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}, httpWebRequest);
|
||||||
|
|
||||||
|
WebResponse resp = await httpWebRequest.GetResponseAsync();
|
||||||
|
|
||||||
|
Stream stream = resp.GetResponseStream();
|
||||||
|
StreamReader re = new StreamReader(stream);
|
||||||
|
if (resp is HttpWebResponse)
|
||||||
|
{
|
||||||
|
String json = await re.ReadToEndAsync();
|
||||||
|
report.Message = json;
|
||||||
|
var hrep = resp as HttpWebResponse;
|
||||||
|
report.StatusCode = hrep.StatusCode.ToString();
|
||||||
|
report.OK = hrep.StatusCode == HttpStatusCode.Accepted
|
||||||
|
|| hrep.StatusCode == HttpStatusCode.OK;
|
||||||
|
}
|
||||||
|
else throw new Exception("Invalid server response type");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes byte array to stream. Author : Farhan Ghumra
|
||||||
|
/// </summary>
|
||||||
|
private static async Task WriteToStream(Stream s, byte[] bytes, int len)
|
||||||
|
{
|
||||||
|
await s.WriteAsync(bytes, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public static class PushCommand
|
||||||
|
{
|
||||||
|
static public PushReport Run(string pkg, string source, string apikey)
|
||||||
|
{
|
||||||
|
if (source == null) source = Program.Settings.DefaultSourceKey;
|
||||||
|
if (source == null) throw new InvalidOperationException("source is null");
|
||||||
|
if (Program.Settings.Sources.Values.Any(s=>s.Alias==source))
|
||||||
|
source = Program.Settings.Sources.First(s=>s.Value.Alias==source).Key;
|
||||||
|
if (source==null) throw new InvalidOperationException("source is invalid");
|
||||||
|
|
||||||
|
var resources = SourceHelpers.GetServerResources(source);
|
||||||
|
if (resources.Resources == null)
|
||||||
|
throw new InvalidOperationException("source gave no resource");
|
||||||
|
if (!resources.Resources.Any(res => res.Type == "PackagePublish/2.0.0"))
|
||||||
|
throw new InvalidOperationException("Source won't serve the expected push command");
|
||||||
|
var pubRes = resources.Resources.First(res => res.Type == "PackagePublish/2.0.0");
|
||||||
|
FileInfo fi = new FileInfo(pkg);
|
||||||
|
if (!fi.Exists)
|
||||||
|
{
|
||||||
|
var report = new PushReport
|
||||||
|
{
|
||||||
|
PkgName = fi.Name,
|
||||||
|
Message = "Le fichier n'existe pas"
|
||||||
|
};
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("Connecting to "+ pubRes.Id);
|
||||||
|
return client.UploadFilesToServer(new Uri(pubRes.Id), fi, apikey);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException hrex)
|
||||||
|
{
|
||||||
|
var report = new PushReport
|
||||||
|
{
|
||||||
|
PkgName = fi.Name,
|
||||||
|
Message = "HttpRequest: " + hrex.Message,
|
||||||
|
StackTrace = hrex.StackTrace,
|
||||||
|
StatusCode = hrex.HResult.ToString()
|
||||||
|
};
|
||||||
|
Console.Error.WriteLine(hrex.Message);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var report = new PushReport
|
||||||
|
{
|
||||||
|
PkgName = fi.Name,
|
||||||
|
Message = ex.Message,
|
||||||
|
StackTrace = ex.StackTrace
|
||||||
|
};
|
||||||
|
Console.Error.WriteLine(ex.Message);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
public static List<PushReport> PushPkg(IEnumerable<string> pkgs)
|
||||||
|
{
|
||||||
|
List<PushReport> pushReports = new List<PushReport>();
|
||||||
|
|
||||||
|
foreach (string pkg in pkgs)
|
||||||
|
{
|
||||||
|
var report = PushCommand.Run(pkg, CurrentSource, apiKey);
|
||||||
|
Console.WriteLine(report.ToDoc());
|
||||||
|
pushReports.Add(report);
|
||||||
|
}
|
||||||
|
if (storApiKey)
|
||||||
|
{
|
||||||
|
EnsureKeyStored();
|
||||||
|
}
|
||||||
|
return pushReports;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object Add(IEnumerable<string> str)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
|
||||||
|
private static void StoreApiKey(IEnumerable<string> storeArgs)
|
||||||
|
{
|
||||||
|
var args = storeoptions.Parse(storeArgs);
|
||||||
|
if (shouldShowPushHelp)
|
||||||
|
{
|
||||||
|
// output the options
|
||||||
|
Console.Error.WriteLine("Push Options:");
|
||||||
|
storeoptions.WriteOptionDescriptions(Console.Out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
apiKey = args[0];
|
||||||
|
EnsureKeyStored();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureKeyStored()
|
||||||
|
{
|
||||||
|
if (CurrentSource == null)
|
||||||
|
{
|
||||||
|
if (Settings.DefaultSourceKey == null)
|
||||||
|
return;
|
||||||
|
CurrentSource = Settings.DefaultSourceKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.Sources.ContainsKey(CurrentSource))
|
||||||
|
{
|
||||||
|
if (apiKey == null)
|
||||||
|
{
|
||||||
|
// Une suppression
|
||||||
|
Settings.Sources.Remove(CurrentSource);
|
||||||
|
if (Settings.DefaultSourceKey == CurrentSource) Settings.DefaultSourceKey = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Une mise À jour
|
||||||
|
Settings.Sources[CurrentSource].SetApiKey(apiKey);
|
||||||
|
if (Settings.DefaultSourceKey == null) Settings.DefaultSourceKey = CurrentSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (apiKey != null)
|
||||||
|
{
|
||||||
|
// une addition
|
||||||
|
var setting = new SourceSettings ();
|
||||||
|
setting.SetApiKey(apiKey);
|
||||||
|
Settings.Sources.Add(CurrentSource, setting);
|
||||||
|
}
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
public static void SaveConfig()
|
||||||
|
{
|
||||||
|
FileInfo cfgSettingIf = new FileInfo(_configFileName);
|
||||||
|
if (!cfgSettingIf.Directory.Exists) cfgSettingIf.Directory.Create();
|
||||||
|
File.WriteAllText(
|
||||||
|
cfgSettingIf.FullName,
|
||||||
|
JsonConvert.SerializeObject(
|
||||||
|
Settings,
|
||||||
|
Formatting.Indented
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
|
||||||
|
private static void ShowConfig()
|
||||||
|
{
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(Settings, Formatting.Indented));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
private static void SourceAdd(IEnumerable<string> str)
|
||||||
|
{
|
||||||
|
foreach (string arg in str)
|
||||||
|
{
|
||||||
|
if (Settings.Sources.ContainsKey(arg))
|
||||||
|
{
|
||||||
|
SourceSettings setting = Settings.Sources[arg];
|
||||||
|
throw new InvalidOperationException
|
||||||
|
(setting.Alias);
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
private static void SourceList(IEnumerable<string> sargs)
|
||||||
|
{
|
||||||
|
IEnumerable<string> spec = sargs.Count()>0 ? sargs : Settings.Sources.Keys;
|
||||||
|
foreach (string arg in spec)
|
||||||
|
{
|
||||||
|
SourceSettings setting = Settings.Sources[arg];
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(setting));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
private static void SetDefaultSource(string arg)
|
||||||
|
{
|
||||||
|
SourceSettings settings =
|
||||||
|
Settings.Sources.ContainsKey(arg) ?
|
||||||
|
Settings.Sources[arg] :
|
||||||
|
Settings.Sources.Values.FirstOrDefault((s)=> s.Alias == arg) ;
|
||||||
|
if (settings==null) throw new InvalidOperationException(arg);
|
||||||
|
Settings.DefaultSourceKey = arg;
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace isn
|
||||||
|
{
|
||||||
|
public class PushReport
|
||||||
|
{
|
||||||
|
public string PkgName { get; set; }
|
||||||
|
public bool Executed { get; internal set; }
|
||||||
|
public bool OK { get; internal set; }
|
||||||
|
public bool AlreadyPresent { get; internal set; }
|
||||||
|
public string Message { get; internal set; }
|
||||||
|
public string StatusCode { get; internal set; }
|
||||||
|
public string StackTrace { get; internal set; }
|
||||||
|
|
||||||
|
public string ToDoc()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder($"= Pushing {PkgName}\n\n");
|
||||||
|
if (Executed) sb.AppendLine("* Executed");
|
||||||
|
if (OK) sb.AppendLine("* OK");
|
||||||
|
if (!string.IsNullOrWhiteSpace(Message))
|
||||||
|
sb.AppendLine(Message);
|
||||||
|
if (!string.IsNullOrWhiteSpace(StatusCode))
|
||||||
|
sb.AppendLine($"* Status Code : ");
|
||||||
|
if (!string.IsNullOrWhiteSpace(StackTrace))
|
||||||
|
sb.AppendLine($"* StackTrace : ");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace isnd.Authorization
|
||||||
|
{
|
||||||
|
internal class ValidApiKeyRequirement : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace isnd.Authorization
|
||||||
|
{
|
||||||
|
internal class ValidApiKeyRequirementHandler : AuthorizationHandler<ValidApiKeyRequirement>
|
||||||
|
{
|
||||||
|
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidApiKeyRequirement requirement)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace isnd
|
||||||
|
{
|
||||||
|
public static class IsndConstants
|
||||||
|
{
|
||||||
|
public const string AdministratorRoleName = "Admin";
|
||||||
|
public const string RequireAdminPolicyName = "RequireAdministratorRole";
|
||||||
|
public const string RequireValidApiKey = "RequireValideApiKey";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,258 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.Data.Roles;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class AccountController : Controller
|
||||||
|
{
|
||||||
|
private readonly IAuthenticationSchemeProvider _schemeProvider;
|
||||||
|
|
||||||
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly AdminStartupList _startupAdminList;
|
||||||
|
|
||||||
|
public AccountController(
|
||||||
|
IAuthenticationSchemeProvider schemeProvider,
|
||||||
|
SignInManager<ApplicationUser> signInManager,
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
IOptions<AdminStartupList> startupAdminListConfig )
|
||||||
|
{
|
||||||
|
_schemeProvider = schemeProvider;
|
||||||
|
_signInManager = signInManager;
|
||||||
|
_userManager = userManager;
|
||||||
|
_startupAdminList = startupAdminListConfig.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entry point into the login workflow
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> Login(string returnUrl)
|
||||||
|
{
|
||||||
|
// build a model so we know what to show on the login page
|
||||||
|
var vm = await BuildLoginViewModelAsync(returnUrl);
|
||||||
|
|
||||||
|
if (vm.IsExternalLoginOnly)
|
||||||
|
{
|
||||||
|
// we only have one option for logging in and it's an external provider
|
||||||
|
return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl });
|
||||||
|
}
|
||||||
|
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle postback from username/password login
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Login(LoginInputModel model, string button)
|
||||||
|
{
|
||||||
|
|
||||||
|
// the user clicked the "cancel" button
|
||||||
|
if (button != "login")
|
||||||
|
{
|
||||||
|
|
||||||
|
// since we don't have a valid context, then we just go back to the home page
|
||||||
|
return Redirect("~/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
// validate username/password
|
||||||
|
var user = await _userManager.FindByNameAsync(model.Username);
|
||||||
|
var signResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, true);
|
||||||
|
|
||||||
|
if (signResult.Succeeded)
|
||||||
|
{
|
||||||
|
|
||||||
|
// only set explicit expiration here if user chooses "remember me".
|
||||||
|
// otherwise we rely upon expiration configured in cookie middleware.
|
||||||
|
AuthenticationProperties props = null;
|
||||||
|
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
|
||||||
|
{
|
||||||
|
props = new AuthenticationProperties
|
||||||
|
{
|
||||||
|
IsPersistent = true,
|
||||||
|
ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
await _signInManager.SignInAsync(user, model.RememberLogin && AccountOptions.AllowRememberLogin);
|
||||||
|
if (Url.IsLocalUrl(model.ReturnUrl))
|
||||||
|
{
|
||||||
|
return Redirect(model.ReturnUrl);
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrEmpty(model.ReturnUrl))
|
||||||
|
{
|
||||||
|
return Redirect("~/");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// user might have clicked on a malicious link - should be logged
|
||||||
|
throw new Exception("invalid return URL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// something went wrong, show form with error
|
||||||
|
var vm = await BuildLoginViewModelAsync(model);
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show logout page
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> Logout(string logoutId)
|
||||||
|
{
|
||||||
|
// build a model so the logout page knows what to display
|
||||||
|
var vm = BuildLogoutViewModel(logoutId);
|
||||||
|
|
||||||
|
if (vm.ShowLogoutPrompt == false)
|
||||||
|
{
|
||||||
|
// if the request for logout was properly authenticated from IdentityServer, then
|
||||||
|
// we don't need to show the prompt and can just log the user out directly.
|
||||||
|
return await Logout(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle logout page postback
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Logout(LogoutInputModel model)
|
||||||
|
{
|
||||||
|
// build a model so the logged out page knows what to display
|
||||||
|
var vm = BuildLoggedOutViewModel(model.LogoutId);
|
||||||
|
|
||||||
|
if (User?.Identity.IsAuthenticated == true)
|
||||||
|
{
|
||||||
|
// delete local authentication cookie
|
||||||
|
await HttpContext.SignOutAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we need to trigger sign-out at an upstream identity provider
|
||||||
|
if (vm.TriggerExternalSignout)
|
||||||
|
{
|
||||||
|
// build a return URL so the upstream provider will redirect back
|
||||||
|
// to us after the user has logged out. this allows us to then
|
||||||
|
// complete our single sign-out processing.
|
||||||
|
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
|
||||||
|
|
||||||
|
// this triggers a redirect to the external provider for sign-out
|
||||||
|
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
return View("LoggedOut", vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult AccessDenied()
|
||||||
|
{
|
||||||
|
return new BadRequestObjectResult(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************/
|
||||||
|
/* helper APIs for the AccountController */
|
||||||
|
/*****************************************/
|
||||||
|
private async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var schemes = await _schemeProvider.GetAllSchemesAsync();
|
||||||
|
|
||||||
|
var providers = schemes
|
||||||
|
.Where(x => x.DisplayName != null)
|
||||||
|
.Select(x => new ExternalProvider
|
||||||
|
{
|
||||||
|
DisplayName = x.DisplayName ?? x.Name,
|
||||||
|
AuthenticationScheme = x.Name
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var allowLocal = true;
|
||||||
|
|
||||||
|
|
||||||
|
return new LoginViewModel
|
||||||
|
{
|
||||||
|
AllowRememberLogin = AccountOptions.AllowRememberLogin,
|
||||||
|
EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin,
|
||||||
|
ReturnUrl = returnUrl,
|
||||||
|
ExternalProviders = providers.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model)
|
||||||
|
{
|
||||||
|
var vm = await BuildLoginViewModelAsync(model.ReturnUrl);
|
||||||
|
vm.Username = model.Username;
|
||||||
|
vm.RememberLogin = model.RememberLogin;
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LogoutViewModel BuildLogoutViewModel(string logoutId)
|
||||||
|
{
|
||||||
|
var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt };
|
||||||
|
|
||||||
|
if (User?.Identity.IsAuthenticated != true)
|
||||||
|
{
|
||||||
|
// if the user is not authenticated, then just show logged out page
|
||||||
|
vm.ShowLogoutPrompt = false;
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the logout prompt. this prevents attacks where the user
|
||||||
|
// is automatically signed out by another malicious web page.
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoggedOutViewModel BuildLoggedOutViewModel(string logoutId)
|
||||||
|
{
|
||||||
|
var vm = new LoggedOutViewModel
|
||||||
|
{
|
||||||
|
AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
|
||||||
|
LogoutId = logoutId
|
||||||
|
};
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public async Task<IActionResult> GetAdminrole()
|
||||||
|
{
|
||||||
|
string username = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
if (_startupAdminList.Users.Contains(username))
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(username);
|
||||||
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
|
if (!roles.Contains(IsndConstants.AdministratorRoleName))
|
||||||
|
{
|
||||||
|
await _userManager.AddToRoleAsync(user, IsndConstants.AdministratorRoleName);
|
||||||
|
|
||||||
|
}
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.Entities;
|
||||||
|
using isnd.Data.ApiKeys;
|
||||||
|
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
public class ApiKeysController : Controller
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext dbContext;
|
||||||
|
private readonly IsndSettings isndSettings;
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
|
private readonly IDataProtector protector;
|
||||||
|
public ApiKeysController(ApplicationDbContext dbContext,
|
||||||
|
IOptions<IsndSettings> isndSettingsOptions,
|
||||||
|
IDataProtectionProvider provider,
|
||||||
|
UserManager<ApplicationUser> userManager)
|
||||||
|
{
|
||||||
|
this.dbContext = dbContext;
|
||||||
|
this.isndSettings = isndSettingsOptions.Value;
|
||||||
|
protector = provider.CreateProtector(isndSettings.ProtectionTitle);
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult> Index()
|
||||||
|
{
|
||||||
|
List<ApiKey> index = await GetUserKeys().ToListAsync();
|
||||||
|
IndexModel model = new IndexModel { ApiKey = index };
|
||||||
|
ViewData["Title"] = "Index";
|
||||||
|
return View("Index", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult> Create()
|
||||||
|
{
|
||||||
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
var user = await _userManager.FindByIdAsync(userId);
|
||||||
|
ViewBag.UserId = new SelectList(new List<ApplicationUser> { user });
|
||||||
|
return View(new CreateModel{ });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> Create(CreateModel model)
|
||||||
|
{
|
||||||
|
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
IQueryable<ApiKey> userKeys = GetUserKeys();
|
||||||
|
if (userKeys.Count() >= isndSettings.MaxUserKeyCount)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(null, "Maximum key count reached");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
ApiKey newKey = new ApiKey { UserId = userid, Name = model.Name,
|
||||||
|
CreationDate = DateTime.Now };
|
||||||
|
_ = dbContext.ApiKeys.Add(newKey);
|
||||||
|
_ = await dbContext.SaveChangesAsync();
|
||||||
|
return View("Details", new DetailModel { Name = newKey.Name,
|
||||||
|
ProtectedValue = protector.Protect(newKey.Id),
|
||||||
|
ApiKey = newKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult> Delete(string id)
|
||||||
|
{
|
||||||
|
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
ApiKey key = await dbContext.ApiKeys.FirstOrDefaultAsync(k => k.Id == id && k.UserId == userid);
|
||||||
|
return View(new DeleteModel { ApiKey = key });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> Delete(DeleteModel model)
|
||||||
|
{
|
||||||
|
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
ApiKey key = dbContext.ApiKeys.FirstOrDefault(k => k.Id == model.ApiKey.Id && k.UserId == userid);
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(null, "Key not found");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
_ = dbContext.ApiKeys.Remove(key);
|
||||||
|
_ = await dbContext.SaveChangesAsync();
|
||||||
|
return View("Index", new IndexModel { ApiKey = GetUserKeys().ToList() } );
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ActionResult> Details(string id)
|
||||||
|
{
|
||||||
|
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
ApiKey key = await dbContext.ApiKeys.FirstOrDefaultAsync(k => k.Id == id && k.UserId == userid);
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(null, "Key not found");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
return View("Details", new DetailModel { ApiKey = key, Name = key.Name, ProtectedValue = protector.Protect(key.Id)});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ActionResult> Edit(string id)
|
||||||
|
{
|
||||||
|
|
||||||
|
EditModel edit = new EditModel();
|
||||||
|
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
|
||||||
|
var user = await _userManager.FindByIdAsync(userId);
|
||||||
|
|
||||||
|
edit.ApiKey = await GetUserKeys().SingleOrDefaultAsync(k =>
|
||||||
|
k.UserId == userId && k.Id == id);
|
||||||
|
ViewBag.UserId = new SelectList(new List<ApplicationUser> { user });
|
||||||
|
|
||||||
|
return View(edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> Edit(EditModel model)
|
||||||
|
{
|
||||||
|
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
|
||||||
|
var apiKey = await dbContext.ApiKeys.SingleOrDefaultAsync(k => k.UserId == userId && k.Id == model.ApiKey.Id);
|
||||||
|
apiKey.Name = model.ApiKey.Name;
|
||||||
|
apiKey.ValidityPeriodInDays = model.ApiKey.ValidityPeriodInDays;
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
return View("Details", new DetailModel { ApiKey = apiKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueryable<ApiKey> GetUserKeys()
|
||||||
|
{
|
||||||
|
return dbContext.ApiKeys.Include(k => k.User).Where(k => k.User.UserName == User.Identity.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isnd.Data;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO Web hook CI
|
||||||
|
public class NewUpdateController : Controller
|
||||||
|
{
|
||||||
|
[Authorize(Policy = IsndConstants.RequireAdminPolicyName)]
|
||||||
|
public IActionResult NewRelease(NewReleaseInfo release)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("web hook");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.ViewModels;
|
||||||
|
using isnd.Helpers;
|
||||||
|
using isnd.Interfaces;
|
||||||
|
|
||||||
|
namespace isnd
|
||||||
|
{
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class PackageVersionController : Controller
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
private readonly IPackageManager _pm;
|
||||||
|
|
||||||
|
public PackageVersionController(ApplicationDbContext context,
|
||||||
|
IPackageManager pm)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_pm = pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET: PackageVersion
|
||||||
|
public async Task<IActionResult> Index(PackageVersionIndexViewModel model)
|
||||||
|
{
|
||||||
|
var applicationDbContext = _context.PackageVersions.Include(p => p.Package)
|
||||||
|
.Include(p => p.Package.Owner)
|
||||||
|
.Include(p => p.Package.Versions)
|
||||||
|
.Where(
|
||||||
|
p => (model.Prerelease || !p.IsPrerelease)
|
||||||
|
&& ((model.PackageId == null) || p.PackageId.StartsWith(model.PackageId)));
|
||||||
|
model.Versions = await applicationDbContext.ToArrayAsync();
|
||||||
|
return View(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public async Task<IActionResult> Mines(PackageVersionIndexViewModel model)
|
||||||
|
{
|
||||||
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
var applicationDbContext = _context.PackageVersions
|
||||||
|
.Include(p => p.Package).Where(
|
||||||
|
p => (string.IsNullOrEmpty(model.PackageId) || p.PackageId.StartsWith(model.PackageId))
|
||||||
|
&& p.Package.OwnerId == userId);
|
||||||
|
|
||||||
|
model.Versions = await applicationDbContext.ToArrayAsync();
|
||||||
|
|
||||||
|
return View("Index", model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isnd.Entities;
|
||||||
|
using isnd.Services;
|
||||||
|
using isn.Abstract;
|
||||||
|
using isn.abst;
|
||||||
|
using isnd.Interfaces;
|
||||||
|
using Unleash;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Api Controller
|
||||||
|
/// </summary>
|
||||||
|
public class ApiController : Controller
|
||||||
|
{
|
||||||
|
private readonly IPackageManager packageManager;
|
||||||
|
private readonly Resource[] resources;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Api Controller Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pm"></param>
|
||||||
|
/// <param name="unleashĈlient"></param>
|
||||||
|
public ApiController(IPackageManager pm, IUnleash unleashĈlient)
|
||||||
|
{
|
||||||
|
packageManager = pm;
|
||||||
|
resources = packageManager.GetResources(unleashĈlient).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// API index
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.IndexDotJson)]
|
||||||
|
public IActionResult ApiIndex()
|
||||||
|
{
|
||||||
|
return Ok(new ApiIndexViewModel(packageManager.CatalogBaseUrl + ApiConfig.IndexDotJson){ Version = PackageManager.BASE_API_LEVEL, Resources = resources });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using isnd.Services;
|
||||||
|
using isnd.Entities;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
|
||||||
|
// GET /autocomplete?id=isn.protocol&prerelease=true
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.AutoComplete)]
|
||||||
|
public IActionResult AutoComplete(
|
||||||
|
string id,
|
||||||
|
string semVerLevel,
|
||||||
|
bool prerelease = false,
|
||||||
|
string packageType = null,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 25)
|
||||||
|
{
|
||||||
|
if (take > maxTake)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("take", "Maximum exceeded");
|
||||||
|
}
|
||||||
|
if (semVerLevel != PackageManager.BASE_API_LEVEL)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("semVerLevel", PackageManager.BASE_API_LEVEL + " expected");
|
||||||
|
}
|
||||||
|
if (ModelState.ErrorCount > 0) return BadRequest(ModelState);
|
||||||
|
|
||||||
|
return Ok(packageManager.AutoComplete(id,skip,take,prerelease,packageType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using isnd.Services;
|
||||||
|
using isnd.Entities;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using isnd.Data.Packages.Catalog;
|
||||||
|
using isnd.Data.Catalog;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.Catalog)]
|
||||||
|
public async Task<IActionResult> CatalogIndex()
|
||||||
|
{
|
||||||
|
return Ok(await packageManager.GetCatalogIndexAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + "{apiVersion}/" + ApiConfig.Registration + "/{id}/{lower}.json")]
|
||||||
|
public async Task<IActionResult> CatalogRegistration(string apiVersion, string id, string lower)
|
||||||
|
{
|
||||||
|
if (lower.Equals("index", System.StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
var query = new Data.Catalog.RegistrationPageIndexQuery
|
||||||
|
{
|
||||||
|
Query = id,
|
||||||
|
Prerelease = true
|
||||||
|
};
|
||||||
|
var index = await packageManager.GetPackageRegistrationIndexAsync(query);
|
||||||
|
if (index == null) return NotFound();
|
||||||
|
// query.TotalHits = result.Items.Select(i=>i.Items.Length).Aggregate((a,b)=>a+b);
|
||||||
|
return Ok(index);
|
||||||
|
}
|
||||||
|
// return a Package
|
||||||
|
var leaf = await packageManager.GetCatalogEntryAsync(id, lower, null);
|
||||||
|
|
||||||
|
if (null == leaf) return NotFound(new { id, lower });
|
||||||
|
return Ok(leaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isnd.Helpers;
|
||||||
|
using isnd.Entities;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using isnd.Attributes;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
[HttpDelete(Constants.PackageRootServerPrefix + ApiConfig.Delete + "/{id}/{lower?}/{type?}")]
|
||||||
|
public async Task<IActionResult> ApiDelete(
|
||||||
|
[FromRoute][SafeName][Required] string id,
|
||||||
|
[FromRoute][SafeName][Required] string lower,
|
||||||
|
[FromRoute] string type)
|
||||||
|
{
|
||||||
|
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
var report = await packageManager.UserAskForPackageDeletionAsync(uid, id, lower, type);
|
||||||
|
return Ok(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isnd.Attributes;
|
||||||
|
using isnd.Entities;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
// Web get the paquet
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.GetPackage + "/{id}/{lower}/{idf}-{lowerf}."
|
||||||
|
+ Constants.PaquetFileEstension)]
|
||||||
|
public IActionResult GetPackage(
|
||||||
|
[FromRoute][SafeName][Required] string id,
|
||||||
|
[FromRoute][SafeName][Required] string lower,
|
||||||
|
[FromRoute] string idf, [FromRoute] string lowerf)
|
||||||
|
{
|
||||||
|
var pkgpath = Path.Combine(isndSettings.PackagesRootDir,
|
||||||
|
id, lower, $"{id}-{lower}." + Constants.PaquetFileEstension
|
||||||
|
);
|
||||||
|
|
||||||
|
FileInfo pkgfi = new FileInfo(pkgpath);
|
||||||
|
|
||||||
|
if (!pkgfi.Exists)
|
||||||
|
{
|
||||||
|
return BadRequest("!pkgfi.Exists");
|
||||||
|
}
|
||||||
|
return File(pkgfi.OpenRead(), "application/zip; charset=binary");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Web get spec
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + Constants.SpecFileEstension + "/{id}/{lower}/{idf}-{lowerf}."
|
||||||
|
+ Constants.SpecFileEstension)]
|
||||||
|
public IActionResult GetNuspec(
|
||||||
|
[FromRoute][SafeName][Required] string id,
|
||||||
|
[FromRoute][SafeName][Required] string lower,
|
||||||
|
[FromRoute][SafeName][Required] string idf,
|
||||||
|
[FromRoute][SafeName][Required] string lowerf)
|
||||||
|
{
|
||||||
|
var pkgpath = Path.Combine(isndSettings.PackagesRootDir,
|
||||||
|
id, lower, $"{id}." + Constants.SpecFileEstension);
|
||||||
|
|
||||||
|
FileInfo pkgfi = new FileInfo(pkgpath);
|
||||||
|
if (!pkgfi.Exists)
|
||||||
|
{
|
||||||
|
return BadRequest("!pkgfi.Exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
return File(pkgfi.OpenRead(), "text/xml; charset=utf-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using isnd.Entities;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.GetVersion + "/{id}/{lower}/" + ApiConfig.IndexDotJson)]
|
||||||
|
public IActionResult GetVersions(
|
||||||
|
string id,
|
||||||
|
string lower,
|
||||||
|
bool prerelease = false,
|
||||||
|
string packageType = null,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 25)
|
||||||
|
{
|
||||||
|
if (take > maxTake)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("take", "Maximum exceeded");
|
||||||
|
}
|
||||||
|
// NugetVersion
|
||||||
|
if (!NuGetVersion.TryParse(lower, out NuGetVersion parsedVersion))
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("lower", "invalid version string");
|
||||||
|
}
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
versions = packageManager.GetVersions(
|
||||||
|
id, parsedVersion, prerelease, packageType, skip, take)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,221 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NuGet.Packaging.Core;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.Helpers;
|
||||||
|
using isnd.Entities;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using isn.abst;
|
||||||
|
using isnd.Data.Packages;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
// TODO [Authorize(Policy = IsndConstants.RequireValidApiKey)]
|
||||||
|
[HttpPut(Constants.PackageRootServerPrefix + ApiConfig.Publish)]
|
||||||
|
public async Task<IActionResult> Put()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var clientVersionId = Request.Headers["X-NuGet-Client-Version"];
|
||||||
|
string apiKey = Request.Headers["X-NuGet-ApiKey"][0];
|
||||||
|
ViewData["versionId"] = typeof(PackagesController).Assembly.FullName;
|
||||||
|
var files = new List<string>();
|
||||||
|
ViewData["files"] = files;
|
||||||
|
|
||||||
|
var clearkey = protector.Unprotect(apiKey);
|
||||||
|
var apikey = dbContext.ApiKeys.SingleOrDefault(k => k.Id == clearkey);
|
||||||
|
if (apikey == null)
|
||||||
|
{
|
||||||
|
logger.LogError("403 : no api-key");
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
Commit commit = new Commit
|
||||||
|
{
|
||||||
|
Action = PackageAction.PublishPackage,
|
||||||
|
TimeStamp = DateTime.Now
|
||||||
|
};
|
||||||
|
dbContext.Commits.Add(commit);
|
||||||
|
|
||||||
|
foreach (IFormFile file in Request.Form.Files)
|
||||||
|
{
|
||||||
|
string initpath = Path.Combine(Environment.GetEnvironmentVariable("TEMP") ??
|
||||||
|
Environment.GetEnvironmentVariable("TMP") ?? "/tmp",
|
||||||
|
$"isn-{Guid.NewGuid()}."+Constants.PaquetFileEstension);
|
||||||
|
|
||||||
|
using (FileStream fw = new FileStream(initpath, FileMode.Create))
|
||||||
|
{
|
||||||
|
file.CopyTo(fw);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (FileStream fw = new FileStream(initpath, FileMode.Open))
|
||||||
|
{
|
||||||
|
var archive = new ZipArchive(fw);
|
||||||
|
|
||||||
|
var spec = archive.Entries.FirstOrDefault(e => e.FullName.EndsWith("." + Constants.SpecFileEstension));
|
||||||
|
if (spec == null) return BadRequest(new { error = "no " + Constants.SpecFileEstension + " from archive" });
|
||||||
|
string pkgpath;
|
||||||
|
NuGetVersion version;
|
||||||
|
string pkgid;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
using (var specstr = spec.Open())
|
||||||
|
{
|
||||||
|
NuspecCoreReader reader = new NuspecCoreReader(specstr);
|
||||||
|
|
||||||
|
string pkgdesc = reader.GetDescription();
|
||||||
|
var types = reader.GetPackageTypes();
|
||||||
|
pkgid = reader.GetId();
|
||||||
|
version = reader.GetVersion();
|
||||||
|
|
||||||
|
string pkgidpath = Path.Combine(isndSettings.PackagesRootDir,
|
||||||
|
pkgid);
|
||||||
|
pkgpath = Path.Combine(pkgidpath, version.ToFullString());
|
||||||
|
string name = $"{pkgid}-{version}."+Constants.PaquetFileEstension;
|
||||||
|
fullpath = Path.Combine(pkgpath, name);
|
||||||
|
|
||||||
|
var destpkgiddir = new DirectoryInfo(pkgidpath);
|
||||||
|
Package pkg = dbContext.Packages.SingleOrDefault(p => p.Id == pkgid);
|
||||||
|
if (pkg != null)
|
||||||
|
{
|
||||||
|
if (pkg.OwnerId != apikey.UserId)
|
||||||
|
{
|
||||||
|
return new ForbidResult();
|
||||||
|
}
|
||||||
|
pkg.Description = pkgdesc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pkg = new Package
|
||||||
|
{
|
||||||
|
Id = pkgid,
|
||||||
|
Description = pkgdesc,
|
||||||
|
OwnerId = apikey.UserId,
|
||||||
|
LatestVersion = commit,
|
||||||
|
};
|
||||||
|
dbContext.Packages.Add(pkg);
|
||||||
|
}
|
||||||
|
if (!destpkgiddir.Exists) destpkgiddir.Create();
|
||||||
|
|
||||||
|
var source = new FileInfo(initpath);
|
||||||
|
var dest = new FileInfo(fullpath);
|
||||||
|
var destdir = new DirectoryInfo(dest.DirectoryName);
|
||||||
|
if (dest.Exists)
|
||||||
|
{
|
||||||
|
// La version existe sur le disque,
|
||||||
|
// mais si elle ne l'est pas en base de donnéés,
|
||||||
|
// on remplace la version sur disque.
|
||||||
|
var pkgv = dbContext.PackageVersions.Where(
|
||||||
|
v => v.PackageId == pkg.Id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pkgv !=null && pkgv.Count()==0)
|
||||||
|
{
|
||||||
|
dest.Delete();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.LogWarning("400 : pkgversion:existant");
|
||||||
|
ModelState.AddModelError("pkgversion", "existant" );
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (!destdir.Exists) destdir.Create();
|
||||||
|
source.MoveTo(fullpath);
|
||||||
|
files.Add(name);
|
||||||
|
string fullstringversion = version.ToFullString();
|
||||||
|
var pkgvers = dbContext.PackageVersions.Where
|
||||||
|
(v => v.PackageId == pkg.Id && v.FullString == fullstringversion);
|
||||||
|
if (pkgvers.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var v in pkgvers.ToArray())
|
||||||
|
dbContext.PackageVersions.Remove(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME default type or null
|
||||||
|
if (types==null || types.Count==0)
|
||||||
|
dbContext.PackageVersions.Add
|
||||||
|
(new PackageVersion{
|
||||||
|
|
||||||
|
Package = pkg,
|
||||||
|
Major = version.Major,
|
||||||
|
Minor = version.Minor,
|
||||||
|
Patch = version.Patch,
|
||||||
|
Revision = version.Revision,
|
||||||
|
IsPrerelease = version.IsPrerelease,
|
||||||
|
FullString = version.ToFullString(),
|
||||||
|
Type = null,
|
||||||
|
LatestCommit = commit
|
||||||
|
});
|
||||||
|
else
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
var pkgver = new PackageVersion
|
||||||
|
{
|
||||||
|
Package = pkg,
|
||||||
|
Major = version.Major,
|
||||||
|
Minor = version.Minor,
|
||||||
|
Patch = version.Patch,
|
||||||
|
IsPrerelease = version.IsPrerelease,
|
||||||
|
FullString = version.ToFullString(),
|
||||||
|
Type = type.Name,
|
||||||
|
LatestCommit = commit
|
||||||
|
};
|
||||||
|
dbContext.PackageVersions.Add(pkgver);
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
packageManager.ÛpdateCatalogForAsync(commit);
|
||||||
|
|
||||||
|
logger.LogInformation($"new paquet : {spec.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var shacrypto = System.Security.Cryptography.SHA512.Create())
|
||||||
|
{
|
||||||
|
using (var stream = System.IO.File.OpenRead(fullpath))
|
||||||
|
{
|
||||||
|
var hash = shacrypto.ComputeHash(stream);
|
||||||
|
var shafullname = fullpath + ".sha512";
|
||||||
|
var hashtext = Convert.ToBase64String(hash);
|
||||||
|
var hashtextbytes = Encoding.ASCII.GetBytes(hashtext);
|
||||||
|
|
||||||
|
using (var shafile = System.IO.File.OpenWrite(shafullname))
|
||||||
|
{
|
||||||
|
shafile.Write(hashtextbytes, 0, hashtextbytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string nuspecfullpath = Path.Combine(pkgpath, pkgid + "." + Constants.SpecFileEstension);
|
||||||
|
FileInfo nfpi = new FileInfo(nuspecfullpath);
|
||||||
|
|
||||||
|
if (nfpi.Exists)
|
||||||
|
nfpi.Delete();
|
||||||
|
spec.ExtractToFile(nuspecfullpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return Ok(ViewData);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex.Message);
|
||||||
|
logger.LogError("Stack Trace: " + ex.StackTrace);
|
||||||
|
return new ObjectResult(new { ViewData, ex.Message })
|
||||||
|
{ StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using isnd.Entities;
|
||||||
|
using isn.abst;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
// GET {@id}?q={QUERY}&skip={SKIP}&take={TAKE}&prerelease={PRERELEASE}&semVerLevel={SEMVERLEVEL}&packageType={PACKAGETYPE}
|
||||||
|
[HttpGet(Constants.PackageRootServerPrefix + ApiConfig.Search)]
|
||||||
|
public IActionResult Search(
|
||||||
|
string q,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 25,
|
||||||
|
bool prerelease = false,
|
||||||
|
string semVerLevel = null,
|
||||||
|
string packageType = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.Data.Catalog;
|
||||||
|
using isnd.Helpers;
|
||||||
|
using isnd.ViewModels;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial class PackagesController
|
||||||
|
{
|
||||||
|
// Web search
|
||||||
|
public async Task<IActionResult> Index(RegistrationPageIndexQuery model)
|
||||||
|
{
|
||||||
|
return View(new RegistrationPageIndexQueryAndResult{Query = model,
|
||||||
|
Result = await packageManager.SearchPackageAsync(model)});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> Details(string pkgid)
|
||||||
|
{
|
||||||
|
if (pkgid == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var packageVersion = dbContext.PackageVersions
|
||||||
|
.Include(p => p.Package)
|
||||||
|
.Where(m => m.PackageId == pkgid)
|
||||||
|
.OrderByDescending(p => p)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (packageVersion.Count() == 0)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
bool results = await packageVersion.AnyAsync();
|
||||||
|
var latest = await packageVersion.FirstAsync();
|
||||||
|
|
||||||
|
return View("Details", new PackageDetailViewModel
|
||||||
|
{
|
||||||
|
ExternalUrl = isndSettings.ExternalUrl,
|
||||||
|
latest = latest,
|
||||||
|
pkgid = pkgid,
|
||||||
|
totalHits = packageVersion.Count(),
|
||||||
|
data = packageVersion.Take(MAX_PKG_VERSION_LIST).ToArray()
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
const int MAX_PKG_VERSION_LIST = 50;
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public async Task<IActionResult> Delete(string pkgid, string version, string pkgtype)
|
||||||
|
{
|
||||||
|
if (pkgid == null || version == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
// var report = await packageManager.DeletePackageAsync(id, lower, type);
|
||||||
|
|
||||||
|
var packageVersion = await dbContext.PackageVersions.Include(p => p.Package)
|
||||||
|
.FirstOrDefaultAsync(m => m.PackageId == pkgid
|
||||||
|
&& m.FullString == version && m.Type == pkgtype);
|
||||||
|
if (packageVersion == null) return NotFound();
|
||||||
|
if (!User.IsOwner(packageVersion)) return Unauthorized();
|
||||||
|
var pkg = await packageManager.GetPackageAsync(pkgid, version, pkgtype);
|
||||||
|
return View(pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST: PackageVersion/Delete/5
|
||||||
|
[HttpPost, ActionName("Delete")]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> DeleteConfirmed(string PackageId, string FullString,
|
||||||
|
string Type)
|
||||||
|
{
|
||||||
|
PackageVersion packageVersion = await dbContext.PackageVersions
|
||||||
|
.Include(pv => pv.Package)
|
||||||
|
.FirstOrDefaultAsync(m => m.PackageId == PackageId
|
||||||
|
&& m.FullString == FullString && m.Type == Type);
|
||||||
|
if (packageVersion == null) return NotFound();
|
||||||
|
if (!User.IsOwner(packageVersion)) return Unauthorized();
|
||||||
|
|
||||||
|
await packageManager.DeletePackageAsync(PackageId, FullString, Type);
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using isnd.Data;
|
||||||
|
using isnd.Entities;
|
||||||
|
using Unleash;
|
||||||
|
using isnd.Services;
|
||||||
|
using isnd.ViewModels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using isnd.Interfaces;
|
||||||
|
using isn.Abstract;
|
||||||
|
|
||||||
|
namespace isnd.Controllers
|
||||||
|
{
|
||||||
|
[AllowAnonymous]
|
||||||
|
public partial class PackagesController : Controller
|
||||||
|
{
|
||||||
|
const int maxTake = 100;
|
||||||
|
private readonly Resource[] resources;
|
||||||
|
private readonly ILogger<PackagesController> logger;
|
||||||
|
private readonly IDataProtector protector;
|
||||||
|
|
||||||
|
private readonly IsndSettings isndSettings;
|
||||||
|
readonly ApplicationDbContext dbContext;
|
||||||
|
private readonly IPackageManager packageManager;
|
||||||
|
private readonly IUnleash unleashĈlient;
|
||||||
|
|
||||||
|
public PackagesController(
|
||||||
|
ILoggerFactory loggerFactory,
|
||||||
|
IDataProtectionProvider provider,
|
||||||
|
IOptions<IsndSettings> isndOptions,
|
||||||
|
IUnleash unleashĈlient,
|
||||||
|
ApplicationDbContext dbContext,
|
||||||
|
IPackageManager pm)
|
||||||
|
{
|
||||||
|
logger = loggerFactory.CreateLogger<PackagesController>();
|
||||||
|
isndSettings = isndOptions.Value;
|
||||||
|
protector = provider.CreateProtector(isndSettings.ProtectionTitle);
|
||||||
|
this.dbContext = dbContext;
|
||||||
|
packageManager = pm;
|
||||||
|
this.unleashĈlient = unleashĈlient;
|
||||||
|
resources = packageManager.GetResources(unleashĈlient).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
namespace isnd.Data
|
||||||
|
{
|
||||||
|
public class LoggedOutViewModel
|
||||||
|
{
|
||||||
|
public string PostLogoutRedirectUri { get; set; }
|
||||||
|
public string ClientName { get; set; }
|
||||||
|
public string SignOutIframeUrl { get; set; }
|
||||||
|
|
||||||
|
public bool AutomaticRedirectAfterSignOut { get; set; }
|
||||||
|
|
||||||
|
public string LogoutId { get; set; }
|
||||||
|
public bool TriggerExternalSignout => ExternalAuthenticationScheme != null;
|
||||||
|
public string ExternalAuthenticationScheme { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace isnd.Data
|
||||||
|
{
|
||||||
|
public class LoginInputModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Username { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
public bool RememberLogin { get; set; }
|
||||||
|
public string ReturnUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace isnd.Data
|
||||||
|
{
|
||||||
|
public class LoginViewModel : LoginInputModel
|
||||||
|
{
|
||||||
|
public bool AllowRememberLogin { get; set; } = true;
|
||||||
|
public bool EnableLocalLogin { get; set; } = true;
|
||||||
|
|
||||||
|
public IEnumerable<ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();
|
||||||
|
public IEnumerable<ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));
|
||||||
|
|
||||||
|
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
|
||||||
|
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
namespace isnd.Data
|
||||||
|
{
|
||||||
|
public class LogoutViewModel : LogoutInputModel
|
||||||
|
{
|
||||||
|
public bool ShowLogoutPrompt { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace isnd.Data
|
||||||
|
{
|
||||||
|
public class RedirectViewModel
|
||||||
|
{
|
||||||
|
public string RedirectUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class ApiKey
|
||||||
|
{
|
||||||
|
[Required][Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[Required][ForeignKey("User")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
public virtual ApplicationUser User { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public int ValidityPeriodInDays{ get; set; }
|
||||||
|
|
||||||
|
public DateTime CreationDate { get; set; }
|
||||||
|
|
||||||
|
public bool IsValid => CreationDate.AddDays(ValidityPeriodInDays) > DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class ApiKeyViewModel
|
||||||
|
{
|
||||||
|
[Display(Name = "Key Name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[Display(Name = "Key Value")]
|
||||||
|
public string ProtectedValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class CreateModel
|
||||||
|
{
|
||||||
|
|
||||||
|
[Required][StringLength(255)]
|
||||||
|
[Display(Name = "Key Name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class DeleteModel
|
||||||
|
{
|
||||||
|
public ApiKey ApiKey { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class DetailModel : ApiKeyViewModel
|
||||||
|
{
|
||||||
|
public ApiKey ApiKey { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class EditModel
|
||||||
|
{
|
||||||
|
public EditModel()
|
||||||
|
{
|
||||||
|
if (ApiKey==null) ApiKey = new ApiKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiKey ApiKey { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace isnd.Data.ApiKeys
|
||||||
|
{
|
||||||
|
public class IndexModel
|
||||||
|
{
|
||||||
|
public List<ApiKey> ApiKey { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue