Merge pull request #9 from pazof/release/1.0.0

Release/1.0.0
This commit is contained in:
2025-02-18 00:02:44 +00:00
committed by GitHub
579 changed files with 51773 additions and 36600 deletions

28
.github/workflows/dotnet.yml vendored Normal file
View File

@ -0,0 +1,28 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: .NET
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal

View File

@ -1,67 +0,0 @@
# Please find the full example project here:
# https://gitlab.com/tobiaskoch/gitlab-ci-example-mono
# see https://hub.docker.com/_/mono/
image: mono:4.6.2.7
stages:
- build
- test
- deploy
before_script:
- . /opt/mono-4.6/mono-env
- export GIT_SSL_NO_VERIFY=true
- curl --insecure -sSL https://lua.pschneider.fr/files/Paul/pub/dnx-install.sh | bash
- DNX_USER_HOME=`pwd -P`/dnx . ./dnx/dnvm/dnvm.sh
- cd src/OAuth.AspNet.Token && dnu restore --ignore-failed-sources
- cd ../OAuth.AspNet.AuthServer && dnu restore --ignore-failed-sources
- cd ../Yavsc.Abstract && dnu restore --ignore-failed-sources
- cd ../Yavsc.Server && dnu restore --ignore-failed-sources
- cd ../Yavsc && dnu restore --ignore-failed-sources
- cd ../cli && dnu restore --ignore-failed-sources
- cd ../../test/yavscTests && dnu restore --ignore-failed-sources
- cd ../..
after_script:
debug:
stage: build
artifacts:
paths:
- test/yavscTests/bin
script:
- cd test/yavscTests
- dnu build
non_reg:
stage: test
artifacts:
paths:
- test/yavscTests/test-results.xml
when: always
script:
- cd test/yavscTests
- cp $yavsc_client_secret_json yavsc-client-secret.json
- ASPNET_ENV=Development dnx test -trait ategory=non_reg -maxthreads 1 -xml test-results.xml
release:
stage: deploy
only:
- vnext
artifacts:
paths:
- binaries/Debug
script:
- make packages
deploy_staging:
stage: deploy
script:
- echo "Deploy to staging server"
- make strip_yavscd
- make packages
- isn push -s $ISNSOURCE -k $NUGETSOURCEAPIKEY src/Yavsc.Abstract/bin/*/*.nupkg
environment:
name: staging
url: https://yavscpre.pschneider.fr

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<apikeys>
</apikeys>
<packageSources>
<add key="opt" value="/opt/nuget/pkgs/" />
<add key="Official NuGet Gallery" value="https://www.nuget.org/api/v2/" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="xamarin-forms-ci" value="https://www.myget.org/F/xamarinforms-ci/api/v2" />
</packageSources> <activePackageSource> <add key="myLocal" value="/home/paul/Nupkgs" /> </activePackageSource>
</configuration>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Machine.Specifications.Runner.Console" version="0.9.0" />
</packages>

View File

@ -1,22 +0,0 @@
language: csharp
os: linux
mono:
- beta
sudo: false
install:
- curl --insecure -sSL https://lua.pschneider.fr/files/Paul/pub/dnx-install.sh | bash
- DNX_USER_HOME=`pwd -P`/dnx . ./dnx/dnvm/dnvm.sh
- cd src/OAuth.AspNet.Token && dnu restore --ignore-failed-sources
- cd ../OAuth.AspNet.AuthServer && dnu restore --ignore-failed-sources
- cd ../Yavsc.Abstract && dnu restore --ignore-failed-sources
- cd ../Yavsc.Server && dnu restore --ignore-failed-sources
- cd ../Yavsc && dnu restore --ignore-failed-sources
- cd ../test
- make restore
- make
- cd ../..
- make
script:
- "dnu build"

View File

@ -1,12 +1,6 @@
{ {
"projects": [
"src",
"scripts",
"tests"
],
"sdk": { "sdk": {
"runtime": "dotnet", "runtime": "dotnet",
"architecture": "x64" "version": "8.0.405"
}, }
"packages": "packages"
} }

View File

@ -1,22 +0,0 @@
{
"dotnet": {
"enabled": false
},
"msbuild": {
"enabled": true
},
"Dnx": {
"enabled": false
},
"Script": {
"enabled": false
},
"fileOptions": {
"systemExcludeSearchPatterns": [
"**/bin/**/*",
"**/obj/**/*",
"**/node_modules/**/*"
],
"userExcludeSearchPatterns": []
}
}

View File

@ -1,145 +0,0 @@
@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.Extensions.CodeGeneration.EntityFramework
@@model @Model.ViewDataTypeName
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = @@Model.ViewName;
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h2>@@Model.ViewName</h2>
@:
}
else
{
@:@@{
@:Layout = "null";
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@Model.ViewName</title>
@:</head>
@:<body>
@:
// PushIndent(" ");
}
@:<form asp-action="@Model.ViewName">
@:<div class="form-horizontal">
@:<h4>@@Model.ViewDataTypeShortName"]</h4>
@:<hr />
@:<div asp-validation-summary="ModelOnly" class="text-danger"></div>
foreach (var property in Model.ModelMetadata.Properties)
{
if (property.Scaffold && !property.IsAutoGenerated && !property.IsReadOnly)
{
// If the property is a primary key and Guid, then the Guid is generated in the controller. Hence, this propery is not displayed on the view.
if (property.IsPrimaryKey)
{
continue;
}
if (property.IsForeignKey)
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="col-md-2 control-label"></label>
@:<div class="col-md-10">
@:<select asp-for="@property.PropertyName" class ="form-control"></select>
@:</div>
@:</div>
continue;
}
bool isCheckbox = property.TypeName.Equals("System.Boolean");
if (isCheckbox)
{
@:<div class="form-group">
@:<div class="col-md-offset-2 col-md-10">
@:<div class="checkbox">
@:<input asp-for="@property.PropertyName" />
@:<label asp-for="@property.PropertyName"></label>
@:</div>
@:</div>
@:</div>
}
else if (property.IsEnum && !property.IsEnumFlags)
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="col-md-2 control-label"></label>
@:<div class="col-md-10">
@:<select asp-for="@property.PropertyName" class="form-control"></select>
@:<span asp-validation-for="@property.PropertyName" class="text-danger" ></span>
@:</div>
@:</div>
}
else
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="col-md-2 control-label"></label>
@:<div class="col-md-10">
@:<input asp-for="@property.PropertyName" class="form-control" />
@:<span asp-validation-for="@property.PropertyName" class="text-danger" ></span>
@:</div>
@:</div>
}
}
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">@Back to List</a>
</div>
@{
if (Model.ReferenceScriptLibraries && (Model.IsLayoutPageSelected || Model.IsPartialView))
{
@:@@section Scripts {
@:<script src="~/lib/jquery/dist/jquery.min.js"></script>
@:<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
@:<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@:}
}
// The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
if (Model.ReferenceScriptLibraries)
{
@:@@section Scripts {
@:<script src="~/lib/jquery/dist/jquery.min.js"></script>
@:<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
@:<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@:}
//ClearIndent();
}
@:</body>
@:</html>
}
}
@functions
{
// Do we need to use this in conjunction with the PrimaryKey check?
bool IsPropertyGuid(PropertyMetadata property)
{
return string.Equals("System.Guid", property.TypeName, StringComparison.OrdinalIgnoreCase);
}
}

View File

@ -1,81 +0,0 @@
@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.Extensions.CodeGeneration.EntityFramework
@@model @Model.ViewDataTypeName
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = @@Model.ViewName;
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h2>@@Model.ViewName</h2>
@:
}
else
{
@:@@{
@:Layout = "null";
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@@@Model.ViewName</title>
@:</head>
@:<body>
@:
// PushIndent(" ");
}
}
<h3>@AreYourSureYouWantToDeleteThis</h3>
<div>
<h4>@@@Model.ViewDataTypeShortName</h4>
<hr />
<dl class="dl-horizontal">
@{
foreach (var property in Model.ModelMetadata.Properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
<dt>
@@Html.DisplayNameFor(model => model.@GetValueExpression(property))
</dt>
<dd>
@@Html.DisplayFor(model => model.@GetValueExpression(property))
</dd>
}
}
@:</dl>
@:
@:<form asp-action="@Model.ViewName">
@:<div class="form-actions no-color">
@:<input type="submit" value="@Delete" class="btn btn-default" /> |
@:<a asp-action="Index">Back to List</a>
@:</div>
@:</form>
@:</div>
if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
//ClearIndent();
@:</body>
@:</html>
}
}
@functions
{
string GetValueExpression(PropertyMetadata property)
{
//Todo: Get the association for the property and use that.
return property.PropertyName;
}
}

View File

@ -1,95 +0,0 @@
@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.Extensions.CodeGeneration.EntityFramework
@@model @Model.ViewDataTypeName
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = @@Model.ViewName;
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h2>@@Model.ViewName</h2>
@:
}
else
{
@:@@{
@:Layout = "null";
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@Model.ViewName</title>
@:</head>
@:<body>
@:
// PushIndent(" ");
}
}
<div>
<h4>@Model.ViewDataTypeShortName</h4>
<hr />
<dl class="dl-horizontal">
@{
foreach (var property in Model.ModelMetadata.Properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
<dt>
@@Html.DisplayNameFor(model => model.@GetValueExpression(property))
</dt>
<dd>
@@Html.DisplayFor(model => model.@GetValueExpression(property))
</dd>
}
}
} </dl>
</div>
<p>
@{
string pkName = GetPrimaryKeyName();
if (pkName != null)
{
@:<a asp-action="Edit" asp-route-id="@@Model.@pkName">@Edit</a> |
@:<a asp-action="Index">Back to List</a>
}
else
{
@:@@Html.ActionLink(@Edit, "Edit", new { /* id = Model.PrimaryKey */ }) |
@:<a asp-action="Index">Back to List</a>
}
}</p>
@{
if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
//ClearIndent();
@:</body>
@:</html>
}
}
@functions
{
string GetPrimaryKeyName()
{
return (Model.ModelMetadata.PrimaryKeys != null && Model.ModelMetadata.PrimaryKeys.Length == 1)
? Model.ModelMetadata.PrimaryKeys[0].PropertyName
: null;
}
string GetValueExpression(PropertyMetadata property)
{
//Todo: Get the association for the property and use that.
return property.PropertyName;
}
}

View File

@ -1,149 +0,0 @@
@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.Extensions.CodeGeneration.EntityFramework
@@model @Model.ViewDataTypeName
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = @@Model.ViewName;
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h2>@@Model.ViewName</h2>
@:
}
else
{
@:@@{
@:Layout = "null";
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@@Model.ViewName</title>
@:</head>
@:<body>
@:
// PushIndent(" ");
}
@:<form asp-action="@Model.ViewName">
@:<div class="form-horizontal">
@:<h4>@Model.ViewDataTypeShortName</h4>
@:<hr />
@:<div asp-validation-summary="ModelOnly" class="text-danger"></div>
foreach (PropertyMetadata property in Model.ModelMetadata.Properties)
{
if (property.Scaffold)
{
if (property.IsPrimaryKey)
{
@:<input type="hidden" asp-for="@property.PropertyName" />
continue;
}
if (property.IsReadOnly)
{
continue;
}
if (property.IsForeignKey)
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="control-label col-md-2">@GetAssociationName(property)</label>
@:<div class="col-md-10">
@:<select asp-for="@property.PropertyName" class="form-control" ></select>
@:<span asp-validation-for="@property.PropertyName" class="text-danger" ></span>
@:</div>
@:</div>
continue;
}
bool isCheckbox = property.TypeName.Equals("System.Boolean");
if (isCheckbox)
{
@:<div class="form-group">
@:<div class="col-md-offset-2 col-md-10">
@:<div class="checkbox">
@:<input asp-for="@property.PropertyName" />
@:<label asp-for="@property.PropertyName"></label>
@:</div>
@:</div>
@:</div>
}
else if (property.IsEnum && !property.IsEnumFlags)
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="col-md-2 control-label"></label>
@:<div class="col-md-10">
@:<select asp-for="@property.PropertyName" class="form-control"></select>
@:<span asp-validation-for="@property.PropertyName" class="text-danger" ></span>
@:</div>
@:</div>
}
else
{
@:<div class="form-group">
@:<label asp-for="@property.PropertyName" class="col-md-2 control-label"></label>
@:<div class="col-md-10">
@:<input asp-for="@property.PropertyName" class="form-control" />
@:<span asp-validation-for="@property.PropertyName" class="text-danger"></span>
@:</div>
@:</div>
}
}
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@{
if (Model.ReferenceScriptLibraries && (Model.IsLayoutPageSelected || Model.IsPartialView))
{
@:@@section Scripts {
@:<script src="~/lib/jquery/dist/jquery.min.js"></script>
@:<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
@:<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@:}
}
// The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
if (Model.ReferenceScriptLibraries)
{
@:@@section Scripts {
@:<script src="~/lib/jquery/dist/jquery.min.js"></script>
@:<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
@:<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@:}
//ClearIndent();
}
@:</body>
@:</html>
}
}
@functions
{
string GetAssociationName(PropertyMetadata property)
{
//Todo: Implement properly.
return property.PropertyName;
}
}

View File

@ -1,115 +0,0 @@
@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
@using Microsoft.Extensions.CodeGeneration.EntityFramework
@@model @GetEnumerableTypeExpression(Model.ViewDataTypeName)
@{
if (Model.IsPartialView)
{
}
else if (Model.IsLayoutPageSelected)
{
@:@@{
@:ViewData["Title"] = @@Model.ViewName;
if (!string.IsNullOrEmpty(Model.LayoutPageFile))
{
@:Layout = "@Model.LayoutPageFile";
}
@:}
@:
@:<h2>@@Model.ViewName</h2>
@:
}
else
{
@:@@{
@:Layout = "null";
@:}
@:
@:<!DOCTYPE html>
@:
@:<html>
@:<head>
@:<meta name="viewport" content="width=device-width" />
@:<title>@@Model.ViewName</title>
@:</head>
@:<body>
// PushIndent(" ");
}
@:<p>
@:<a asp-action="Create">Create New</a>
@:</p>
@:<table class="table">
@:<tr>
IEnumerable<PropertyMetadata> properties = Model.ModelMetadata.Properties;
foreach (var property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
<th>
@@Html.DisplayNameFor(model => model.@GetValueExpression(property))
</th>
}
}
@:<th></th>
@:</tr>
@:
@:@@foreach (var item in Model) {
@:<tr>
foreach (PropertyMetadata property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
<td>
@@Html.DisplayFor(modelItem => item.@GetValueExpression(property))
</td>
}
}
string pkName = GetPrimaryKeyName();
if (pkName != null)
{
@:<td>
@:<a asp-action="Edit" asp-route-id="@@item.@pkName">@Edit</a> |
@:<a asp-action="Details" asp-route-id="@@item.@pkName">@Details</a> |
@:<a asp-action="Delete" asp-route-id="@@item.@pkName">@Delete</a>
@:</td>
}
else
{
<td>
@@Html.ActionLink("Edit", "Edit",new { /* id=item.PrimaryKey */ }) |
@@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
}
@:</tr>
@:}
@:</table>
if(!Model.IsPartialView && !Model.IsLayoutPageSelected)
{
//ClearIndent();
@:</body>
@:</html>
}
}
@functions
{
string GetPrimaryKeyName()
{
return (Model.ModelMetadata.PrimaryKeys != null && Model.ModelMetadata.PrimaryKeys.Length == 1)
? Model.ModelMetadata.PrimaryKeys[0].PropertyName
: null;
}
string GetValueExpression(PropertyMetadata property)
{
//Todo: Get the association for the property and use that.
return property.PropertyName;
}
string GetEnumerableTypeExpression(string typeName)
{
return "IEnumerable<" + typeName + ">";
}
}

View File

@ -1,78 +0,0 @@
include versioning.mk
REPO_ROOT=../../../src
SUBDIRS=Yavsc Yavsc.Server Yavsc.Abstract OAuth.AspNet.AuthServer OAuth.AspNet.Token cli test
all: $(SUBDIRS)
Yavsc.Abstract:
$(MAKE) -C $(REPO_ROOT)/Yavsc.Abstract VERSION=$(VERSION)
OAuth.AspNet.Token:
$(MAKE) -C $(REPO_ROOT)/OAuth.AspNet.Token VERSION=$(VERSION)
OAuth.AspNet.AuthServer: OAuth.AspNet.Token
$(MAKE) -C $(REPO_ROOT)/OAuth.AspNet.AuthServer VERSION=$(VERSION)
Yavsc.Server: Yavsc.Abstract
$(MAKE) -C $(REPO_ROOT)/Yavsc.Server VERSION=$(VERSION)
Yavsc: Yavsc.Server OAuth.AspNet.AuthServer OAuth.AspNet.Token
make -C $(REPO_ROOT)/Yavsc VERSION=$(VERSION)
Yavsc-deploy-pkg: Yavsc
make -C $(REPO_ROOT)/Yavsc deploy-pkg
Yavsc.Server-deploy-pkg: Yavsc.Server
make -C $(REPO_ROOT)/Yavsc.Server deploy-pkg
Yavsc.Abstract-deploy-pkg: Yavsc.Abstract
make -C $(REPO_ROOT)/Yavsc.Abstract deploy-pkg
cli-deploy-pkg: cli check
make -C $(REPO_ROOT)/cli deploy-pkg
cli: Yavsc-deploy-pkg Yavsc.Server-deploy-pkg Yavsc.Abstract-deploy-pkg
make -C $(REPO_ROOT)/cli
undoLocalYavscNugetDeploy:
rm -rf ../../../packages/Yavsc.Abstract
rm -rf ../../../packages/Yavsc.Server
rm -rf ../../../packages/Yavsc
rm -rf ~/.dnx/packages/Yavsc.Abstract
rm -rf ~/.dnx/packages/Yavsc.Server
rm -rf ~/.dnx/packages/Yavsc
check: cli
make -C $(REPO_ROOT)/cli check
make -C $(REPO_ROOT)/test
test:
make -C $(REPO_ROOT)/test
pushInPre:
make -C $(REPO_ROOT)/Yavsc pushInPre
pushInProd:
make -C $(REPO_ROOT)/Yavsc pushInProd
deploy-pkgs: Yavsc-deploy-pkg Yavsc.Server-deploy-pkg Yavsc.Abstract-deploy-pkg cli-deploy-pkg
memo:
vim ~/TODO.md
rc-num:
@echo echo 1-alpha1 < $< ^ $^ @ $@
clean:
for subdir in $(SUBDIRS) ; do \
make -C $(REPO_ROOT)/$${subdir} clean ; \
done
watch:
make -C $(REPO_ROOT)/Yavsc watch
.PHONY: all $(SUBDIRS)

View File

@ -1,71 +0,0 @@
# Common defs
#
ifndef PRJNAME
PRJNAME := $(shell basename `pwd -P`)
endif
FRAMEWORK=dnx451
ASPNET_ENV=Development
ASPNET_LOG_LEVEL=Debug
HOSTING=localhost
HOSTADMIN=root
FRAMEWORKALIAS=dnx451
# nuget package destination, at generation time
BINTARGET=$(PRJNAME).dll
BINTARGETPATH=bin/$(CONFIGURATION)/$(FRAMEWORKALIAS)/$(BINTARGET)
PKGFILENAME=$(PRJNAME).$(VERSION).nupkg
dnu=dnu
# OBS SUBDIRS=Yavsc.Server Yavsc.Abstract Yavsc cli
#
# Git commit hash, in order to not publish some uncrontrolled code in production environment
#
git_status := $(shell git status -s --porcelain |wc -l)
all: $(BINTARGETPATH)
fixSystemXML:
@# fixing package id reference case, to System.Xml, from package NJsonSchema.CodeGeneration.CSharp
@sed 's/System.XML/System.Xml/' project.lock.json > project.lock.json.new && mv project.lock.json.new project.lock.json
restore:
touch project.json
$(dnu) restore --ignore-failed-sources
project.lock.json: project.json
$(dnu) restore --ignore-failed-sources
watch: project.lock.json
MONO_OPTIONS=--debug MONO_MANAGED_WATCHER=enabled ASPNET_ENV=$(ASPNET_ENV) ASPNET_LOG_LEVEL=$(ASPNET_LOG_LEVEL) dnx-watch web --configuration=$(CONFIGURATION)
clean:
rm -rf bin obj
rm project.lock.json
cleanoutput:
rm -rf bin/$(CONFIGURATION)
rm -rf bin/output
$(BINTARGETPATH): project.lock.json rc-num.txt-check
$(dnu) build --configuration=$(CONFIGURATION)
# Default target, from one level sub dirs
bin/output:
$(dnu) publish
bin/output/wwwroot/version: bin/output
@echo $(version) > bin/output/wwwroot/version
pack: $(BINTARGETPATH) ../../version.txt
dnu pack --configuration $(CONFIGURATION)
push: pack
@echo push to source: $(ISNSOURCE)
isn push -s $(ISNSOURCE) -k $(NUGETSOURCEAPIKEY) src/$(PRJNAME)/bin/$(CONFIGURATION)/$(PRJNAME).*.nupkg
.PHONY: rc-num.txt-check
# .DEFAULT_GOAL := $(BINTARGETPATH)

View File

@ -1,16 +0,0 @@
MSBUILD=msbuild
MONO=mono
CONFIGURATION=Debug
BINTYPE=exe
PRJNAME := $(shell basename `pwd -P`)
rc_num := $(shell cat ../../rc-num.txt)
VERSION=1.0.5-rc$(rc_num)
BINTARGET=$(PRJNAME).$(BINTYPE)
BINTARGETPATH=bin/$(CONFIGURATION)/$(BINTARGET)
ISNSOURCE=$(HOME)/Nupkgs
PKGFILENAME=$(PRJNAME).$(VERSION).nupkg

View File

@ -1,16 +0,0 @@
ifndef PRJNAME
PRJNAME := $(shell basename `pwd -P`)
endif
version := $(shell cat ../../version.txt)
MAKE=make
ISNSOURCE=$(HOME)/Nupkgs
VERSION=$(version)
CONFIGURATION=Debug
version-check:
ifndef version
@echo no version number specification ... please, could you try and run 'echo 1.2.3 > ../../version.txt' ?.
else
@echo 'Got version number : $(version)'
endif

View File

@ -1,44 +0,0 @@
#!/bin/bash
version="$1"
major=0
minor=0
build=0
# break down the version number into it's components
regex="([0-9]+).([0-9]+).([0-9]+)((-[A-Za-z]+)([0-9]+))?"
if [[ $version =~ $regex ]]; then
major="${BASH_REMATCH[1]}"
minor="${BASH_REMATCH[2]}"
build="${BASH_REMATCH[3]}"
patchtype="${BASH_REMATCH[5]}"
patchnum="${BASH_REMATCH[6]}"
fi
# check paramater to see which number to increment
if [[ "$2" == "feature" ]]; then
minor=$(echo $minor + 1 | bc)
build=0
patchtype=
patchnum=
elif [[ "$2" == "build" ]]; then
build=$(echo $build + 1 | bc)
patchtype=
patchnum=
elif [[ "$2" == "major" ]]; then
major=$(echo $major+1 | bc)
minor=0
build=0
patchtype=
patchnum=
elif [[ "$2" == "patch" ]]; then
patchnum=$(echo $patchnum + 1 | bc)
else
echo "usage: ./version.sh version_number [major/feature/build/patch]" >&2
exit -1
fi
# echo the new version number
echo "${major}.${minor}.${build}${patchtype}${patchnum}"

12
src/Api/Api.csproj Normal file
View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>1c73094f-959f-4211-b1a1-6a69b236c283</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.13" />
<ProjectReference Include="../Yavsc.Server/Yavsc.Server.csproj" />
</ItemGroup>
</Project>

View File

@ -27,7 +27,7 @@ namespace Yavsc.Controllers
[HttpGet] [HttpGet]
public IEnumerable<BlogPost> GetBlogspot() public IEnumerable<BlogPost> GetBlogspot()
{ {
return _context.Blogspot.Where(b => b.Visible).OrderByDescending(b => b.UserModified); return _context.BlogSpot.Where(b => b.Visible).OrderByDescending(b => b.UserModified);
} }
// GET: api/BlogApi/5 // GET: api/BlogApi/5
@ -39,7 +39,7 @@ namespace Yavsc.Controllers
return BadRequest(ModelState); return BadRequest(ModelState);
} }
BlogPost blog = _context.Blogspot.Single(m => m.Id == id); BlogPost blog = _context.BlogSpot.Single(m => m.Id == id);
if (blog == null) if (blog == null)
{ {
@ -93,7 +93,7 @@ namespace Yavsc.Controllers
return BadRequest(ModelState); return BadRequest(ModelState);
} }
_context.Blogspot.Add(blog); _context.BlogSpot.Add(blog);
try try
{ {
_context.SaveChanges(User.GetUserId()); _context.SaveChanges(User.GetUserId());
@ -122,13 +122,13 @@ namespace Yavsc.Controllers
return BadRequest(ModelState); return BadRequest(ModelState);
} }
BlogPost blog = _context.Blogspot.Single(m => m.Id == id); BlogPost blog = _context.BlogSpot.Single(m => m.Id == id);
if (blog == null) if (blog == null)
{ {
return NotFound(); return NotFound();
} }
_context.Blogspot.Remove(blog); _context.BlogSpot.Remove(blog);
_context.SaveChanges(User.GetUserId()); _context.SaveChanges(User.GetUserId());
return Ok(blog); return Ok(blog);
@ -145,7 +145,7 @@ namespace Yavsc.Controllers
private bool BlogExists(long id) private bool BlogExists(long id)
{ {
return _context.Blogspot.Count(e => e.Id == id) > 0; return _context.BlogSpot.Count(e => e.Id == id) > 0;
} }
} }
} }

View File

@ -1,12 +1,15 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Yavsc.Helpers; using Yavsc.Helpers;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Blog; using Yavsc.Models.Blog;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
[Authorize]
[Produces("application/json")] [Produces("application/json")]
[Route("api/blogcomments")] [Route("api/blogcomments")]
public class CommentsApiController : Controller public class CommentsApiController : Controller
@ -18,14 +21,6 @@ namespace Yavsc.Controllers
_context = context; _context = context;
} }
// GET: api/CommentsApi
[HttpGet]
public IEnumerable<Comment> GetComment()
{
return _context.Comment;
}
// GET: api/CommentsApi/5
[HttpGet("{id}", Name = "GetComment")] [HttpGet("{id}", Name = "GetComment")]
public async Task<IActionResult> GetComment([FromRoute] long id) public async Task<IActionResult> GetComment([FromRoute] long id)
{ {
@ -43,65 +38,46 @@ namespace Yavsc.Controllers
return Ok(comment); return Ok(comment);
} }
// PUT: api/CommentsApi/5
[HttpPut("{id}")]
public async Task<IActionResult> PutComment([FromRoute] long id, [FromBody] Comment comment)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != comment.Id)
{
return BadRequest();
}
_context.Entry(comment).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync(User.GetUserId());
}
catch (DbUpdateConcurrencyException)
{
if (!CommentExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return new StatusCodeResult(StatusCodes.Status204NoContent);
}
// POST: api/CommentsApi
[HttpPost] [HttpPost]
public async Task<IActionResult> PostComment([FromBody] Comment comment) public async Task<IActionResult> Post([FromBody] CommentPost post)
{ {
if (!ModelState.IsValid) if (!ModelState.IsValid)
{ {
return new BadRequestObjectResult(ModelState); return new BadRequestObjectResult(ModelState);
} }
if (!User.IsInRole(Constants.AdminGroupName)) var article = await _context.BlogSpot.FirstOrDefaultAsync
(p=> p.Id == post.ReceiverId);
if (article==null) {
ModelState.AddModelError("ReceiverId", "not found");
return BadRequest(ModelState);
}
if (post.ParentId!=null)
{ {
if (User.GetUserId()!=comment.AuthorId) { var parentExists = _context.Comment.Any(c => c.Id == post.ParentId);
ModelState.AddModelError("Content","Vous ne pouvez pas poster au nom d'un autre."); if (!parentExists)
return new BadRequestObjectResult(ModelState); {
ModelState.AddModelError("ParentId", "not found");
return BadRequest(ModelState);
} }
} }
_context.Comment.Add(comment); string uid = User.GetUserId();
Comment c = new Comment{
ReceiverId = post.ReceiverId,
Content = post.Content,
ParentId = post.ParentId,
AuthorId = uid,
UserModified = uid
};
_context.Comment.Add(c);
try try
{ {
await _context.SaveChangesAsync(User.GetUserId()); await _context.SaveChangesAsync(uid);
} }
catch (DbUpdateException) catch (DbUpdateException)
{ {
if (CommentExists(comment.Id)) if (CommentExists(c.Id))
{ {
return new StatusCodeResult(StatusCodes.Status409Conflict); return new StatusCodeResult(StatusCodes.Status409Conflict);
} }
@ -110,12 +86,12 @@ namespace Yavsc.Controllers
throw; throw;
} }
} }
return CreatedAtRoute("GetComment", new { id = comment.Id }, comment); return CreatedAtRoute("GetComment", new { id = c.Id }, new { id = c.Id, dateCreated = c.DateCreated });
} }
// DELETE: api/CommentsApi/5 // DELETE: api/CommentsApi/5
[HttpDelete("{id}")] [HttpDelete("{id}")]
public async Task<IActionResult> DeleteComment([FromRoute] long id) public async Task<IActionResult> Delete([FromRoute] long id)
{ {
if (!ModelState.IsValid) if (!ModelState.IsValid)
{ {
@ -135,7 +111,8 @@ namespace Yavsc.Controllers
} }
private void RemoveRecursive (Comment comment) private void RemoveRecursive (Comment comment)
{ {
var children = _context.Comment.Where(c=>c.ParentId==comment.Id).ToList(); var children = _context.Comment.Where
(c=>c.ParentId==comment.Id).ToList();
foreach (var child in children) { foreach (var child in children) {
RemoveRecursive(child); RemoveRecursive(child);
} }

View File

@ -9,11 +9,13 @@ namespace Yavsc.ApiControllers
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Yavsc.Helpers; using Yavsc.Helpers;
using Yavsc.Exceptions;
using Yavsc.Models.FileSystem; using Yavsc.Models.FileSystem;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Yavsc.Attributes.Validation; using Yavsc.Attributes.Validation;
using System.IO; using System.IO;
using Yavsc.Exceptions;
using Yavsc.Server.Helpers;
using Yavsc.Abstract.Helpers;
[Authorize,Route("api/fs")] [Authorize,Route("api/fs")]
public partial class FileSystemApiController : Controller public partial class FileSystemApiController : Controller

View File

@ -8,6 +8,7 @@ using Yavsc.Models;
using Yavsc.Models.Messaging; using Yavsc.Models.Messaging;
using Yavsc.Services; using Yavsc.Services;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Yavsc.Server.Helpers;
namespace Yavsc.ApiControllers namespace Yavsc.ApiControllers
{ {

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers; using Yavsc.Api.Helpers;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Workflow; using Yavsc.Models.Workflow;

View File

@ -12,9 +12,10 @@ namespace Yavsc.ApiControllers
using Services; using Services;
using Models.Messaging; using Models.Messaging;
using ViewModels.Auth;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Yavsc.ViewModels.Auth;
using Yavsc.Server.Helpers;
[Route("api/bill"), Authorize] [Route("api/bill"), Authorize]
public class BillingController : Controller public class BillingController : Controller

View File

@ -27,7 +27,7 @@ namespace Yavsc.Controllers
return BadRequest(ModelState); return BadRequest(ModelState);
} }
Models.Blog.BlogPost blogpost = _context.Blogspot.Single(x=>x.Id == id); Models.Blog.BlogPost blogpost = _context.BlogSpot.Single(x=>x.Id == id);
if (blogpost == null) if (blogpost == null)
{ {
@ -39,7 +39,6 @@ namespace Yavsc.Controllers
if (!User.IsInRole(Constants.AdminGroupName)) if (!User.IsInRole(Constants.AdminGroupName))
return BadRequest(); return BadRequest();
blogpost.Rate = rate;
_context.SaveChanges(User.GetUserId()); _context.SaveChanges(User.GetUserId());
return Ok(); return Ok();

View File

@ -0,0 +1,86 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Api.Helpers;
using Yavsc.Server.Helpers;
namespace Yavsc.WebApi.Controllers
{
[Route("~/api/account")]
[Authorize("ApiScope")]
public class ApiAccountController : Controller
{
readonly ApplicationDbContext _dbContext;
private readonly ILogger _logger;
public ApiAccountController(
ILoggerFactory loggerFactory, ApplicationDbContext dbContext)
{
_logger = loggerFactory.CreateLogger(nameof(ApiAccountController));
_dbContext = dbContext;
}
[HttpGet("me")]
public async Task<IActionResult> Me()
{
if (User == null)
return new BadRequestObjectResult(
new { error = "user not found" });
var uid = User.GetUserId();
var userData = await GetUserData(uid);
var user = new Yavsc.Models.Auth.Me(userData.Id, userData.UserName, userData.Email,
userData.Avatar,
userData.PostalAddress, userData.DedicatedGoogleCalendar);
var userRoles = _dbContext.UserRoles.Where(u => u.UserId == uid).Select(r => r.RoleId).ToArray();
IdentityRole[] roles = _dbContext.Roles.Where(r => userRoles.Contains(r.Id)).ToArray();
user.Roles = roles.Select(r => r.Name).ToArray();
return Ok(user);
}
private async Task<ApplicationUser> GetUserData(string uid)
{
return await _dbContext.Users
.Include(u => u.PostalAddress)
.Include(u => u.AccountBalance)
.FirstAsync(u => u.Id == uid);
}
[HttpGet("myhost")]
public IActionResult MyHost ()
{
return Ok(new { host = Request.ForHost() });
}
/// <summary>
/// Updates the avatar
/// </summary>
/// <returns></returns>
[HttpPost("~/api/setavatar")]
public async Task<IActionResult> SetAvatar()
{
var root = User.InitPostToFileSystem(null);
var user = await GetUserData(User.GetUserId());
if (Request.Form.Files.Count!=1)
return new BadRequestResult();
var info = user.ReceiveAvatar(Request.Form.Files[0]);
await _dbContext.SaveChangesAsync();
return Ok(info);
}
[HttpGet("identity")]
public async Task<IActionResult> Identity()
{
return Json(User.Claims.Select(c=>new {c.Type, c.Value}));
}
}
}

View File

@ -8,7 +8,7 @@ using Yavsc.ViewModels;
using Yavsc.Models; using Yavsc.Models;
using System.Linq; using System.Linq;
namespace Yavsc.Helpers namespace Yavsc.Api.Helpers
{ {
public static class RequestHelpers public static class RequestHelpers
{ {

View File

@ -0,0 +1,17 @@
using System.Security.Claims;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Blog;
namespace Yavsc.Api.Helpers
{
public static class UserHelpers
{
public static string GetUserId(this ClaimsPrincipal user)
{
return user.FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
}
}
}

113
src/Api/Program.cs Normal file
View File

@ -0,0 +1,113 @@
/*
Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/
Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved.
Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
Source code and license this software can be found
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Interface;
using Yavsc.Models;
using Yavsc.Services;
internal class Program
{
private static async Task Main(string[] args)
{
Console.Title = "API";
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
// builder.Services.AddDistributedMemoryCache();
// accepts any access token issued by identity server
// adds an authorization policy for scope 'scope1'
services
.AddAuthorization(options =>
{
options.AddPolicy("ApiScope", policy =>
{
policy
.RequireAuthenticatedUser()
.RequireClaim(JwtClaimTypes.Scope, new string[] { "scope2" });
});
})
.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins("https://localhost:5003")
.AllowAnyHeader()
.AllowAnyMethod();
});
})
.AddControllers();
// accepts any access token issued by identity server
var authenticationBuilder = services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.IncludeErrorDetails = true;
options.Authority = "https://localhost:5001";
options.TokenValidationParameters =
new() { ValidateAudience = false };
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<ITrueEmailSender, MailSender>()
.AddTransient<IBillingService, BillingService>()
.AddTransient<ICalendarManager, CalendarManager>();
/*
services.AddSingleton<IConnexionManager, HubConnectionManager>();
services.AddSingleton<ILiveProcessor, LiveProcessor>();
services.AddTransient<IFileSystemAuthManager, FileSystemAuthManager>();
services.AddIdentityApiEndpoints<ApplicationUser>();
services.AddSession();
*/
using (var app = builder.Build())
{
if (app.Environment.IsDevelopment())
app.UseDeveloperExceptionPage();
app
.UseRouting()
.UseAuthentication()
.UseAuthorization()
.UseCors("default")
/* .UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization();
})*/
;
// app.MapIdentityApi<ApplicationUser>().RequireAuthorization("ApiScope");
app.MapDefaultControllerRoute();
app.MapGet("/identity", (HttpContext context) =>
new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value }))
);
// app.UseSession();
await app.RunAsync();
}
;
}
}

View File

@ -0,0 +1,30 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:5001",
"sslPort": 6001
}
},
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:6001;",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

10
src/Api/appsettings.json Normal file
View File

@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

1
src/Api/tempkey.jwk Normal file
View File

@ -0,0 +1 @@
{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"V1qxZgyKyWNi8FbeueGjfOae22fnDa0dU8YpTohrjn89bk9B8kvIzFJP9IPYThTLMaKCTFN09A3aVy_zhL5Cv2ebEqkZIpXkPmtvRavAYxoSQWUfN2czMok216KI7csVVk79csLnnO6i3pf0B9OgGwsuEsLR40_X4MTy5iTejZfwEVobN7H6_uylw5dEUjcJlR-RtuXAZz48stOLt8-y9it7rvowv8eHEsAFSaiV-g92rKZdvMdxVqW5dvHkqF4-h1gdp9VvStZYsqfnR8hrObSxom5yWFnpmxZKmaFaFxbF-k9T8YX1izuPzESPyKCUb-GX5_4sLB6vOiUO4drHiQ","DP":"7Vz77Jz00YuT87QDAEHuBl-GInvI2VT1Fg0HsUEUhBN_o1ZwqlgX6U_3yGUgYYvoWQZZQeLTxRiQSzymPxXiikKnmGt97zMypIllEOar284Ddypa4fraXSJwgKR-1UPYGZg1adjN3KDruLok3ahyUcD9375tCXmQ3Cs0QC1_ATs","DQ":"B5qgaCcQGleo-zZqWIjMCtyEyB4JBbPFtKk3uZ5KAV8lO-TQPJkohraRxInOUHoSS1O2hj1bUO1r-C29XJqrkhi2APGs2hu6V11cmAtwwhj5XPTnL_TNx314dK5ECEQ231gxidfod-6PknG20Qim7sacsj5OrJHfp9RnMZ2p4fk","E":"AQAB","K":null,"KeyId":"E7139A7A77AEA502B0482C026DCE5C59","KeyOps":[],"Kid":"E7139A7A77AEA502B0482C026DCE5C59","Kty":"RSA","N":"tL1q9Mon5IGTGYvBg_FmDoxy0HWQ0ceo6iZmDMzAkjYZ06KKdWoR7Up2ZJ7NrBnGpyrb1uR9qAJAAJm19SLKDKSrEUn5QcnTDMqVQLBurtXYw-eY2DL4cO0bbetc5_z8hyKUzikf6jJRRGfDSR2nEfXwUf3riYfYXtNgSmr_CsBwPUcH12JGad0bwsqJy7z9Tg2_pWvNR36Ba5qd_6VmkLQRGQuDTcHzwbagd3bl4Ma1bzxPULBiBENfj6srAxV-6gQhCJr3mIr1ZsJcZsrYuUnnBNgzYCZvkOkmyB68PlrV9C9xQO8aQfla2s42Uc12-UhBbreI0uBP_k8PXXXjXw","Oth":[],"P":"_jaZkNClDqxS8nddu2t6pgP596qJdzMAq11JVWAoDJV_9JRUZH2Qbq2CrDRUjRF9nxR2bVTglfzZ-bho-Iy9PqcWeVekLObiyR30zmUzoWCdUhmi-BRd3FF3uSteNPc7ohtuX4SrbbCoUR4BpcBAgHas8KKj80sIPpoYo10xK-s","Q":"tgKedcJQilsxEzRRbs8_XD4MxnsmrxqvccfvzzHkqqZMNI0CMGA41ddHiWdNcYsyzqIc-vCf6OGabD6Z7mzZXPbYsr1o4rIQXveUy3Ty3fD9YCRKgWbS9gTbXNGBFAglu3iyNl1XUCGc_DF8PImgk99pu9byPoIr6rAPhciaDV0","QI":"2wtLbwL9kODL6HoF5R8CFmf0Fz3gqoEetrq_I7wuK1pL2vmpZlzmURjvERhi5T6lD2L8SC1vY4AJ7NGzAncwn5ozpnos2s0YIxHYUixj5RuTWQLPKqk5r1bEORuju8KwfW6Nzc4K6Rhk3Lb3TXDvKi6BSf1URjLtiI8DUB_enxw","Use":null,"X":null,"X5c":[],"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true,"SignatureProviderObjectPoolCacheSize":16}}

View File

@ -1,7 +1,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Yavsc.Helpers; using Yavsc.Server.Helpers;
namespace Yavsc.Attributes.Validation namespace Yavsc.Attributes.Validation
{ {

View File

@ -3,7 +3,7 @@
namespace Yavsc namespace Yavsc
{ {
public interface IBlogPost : IBaseTrackedEntity, IIdentified<long>, IRating<long>, ITitle public interface IBlogPost : ITrackedEntity, IIdentified<long>, ITitle
{ {
string AuthorId { get; set; } string AuthorId { get; set; }
string Content { get; set; } string Content { get; set; }

View File

@ -37,7 +37,7 @@ namespace Yavsc
public const string FrontOfficeGroupName = "FrontOffice"; public const string FrontOfficeGroupName = "FrontOffice";
public const string DefaultAvatar = "/images/Users/icon_user.png"; public const string DefaultAvatar = "/images/Users/icon_user.png";
public const string AnonAvatar = "/images/Users/icon_anon_user.png"; public const string AnonAvatar = "/images/Users/icon_anon_user.png";
public const string YavscConnectionStringEnvName = "YAVSC_DB_CONNECTION"; public const string YavscConnectionStringEnvName = "DEFAULTCONNECTION_CONNECTIONSTRING";
// at the end, let 4*4 bytes in peace // at the end, let 4*4 bytes in peace
public const int WebSocketsMaxBufLen = 4096; public const int WebSocketsMaxBufLen = 4096;
@ -54,5 +54,7 @@ namespace Yavsc
public const string LivePath = "/live/cast"; public const string LivePath = "/live/cast";
public const string StreamingPath = "/api/stream/put"; public const string StreamingPath = "/api/stream/put";
public const string RoleClaimName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
} }
} }

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using Yavsc.ViewModels.UserFiles; using Yavsc.ViewModels.UserFiles;
namespace Yavsc.Helpers namespace Yavsc.Server.Helpers
{ {
public static class AbstractFileSystemHelpers public static class AbstractFileSystemHelpers
{ {

View File

@ -1,4 +1,4 @@
namespace Yavsc.Helpers namespace Yavsc.Abstract.Helpers
{ {
public enum ErrorCode { public enum ErrorCode {
NotFound, NotFound,

View File

@ -2,7 +2,7 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Yavsc.Abstract.FileSystem; using Yavsc.Abstract.FileSystem;
using Yavsc.Helpers; using Yavsc.Server.Helpers;
namespace Yavsc.ViewModels.UserFiles namespace Yavsc.ViewModels.UserFiles
{ {

View File

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Identity.Security
public interface ICircleAuthorized public interface ICircleAuthorized
{ {
long Id { get; set; } long Id { get; set; }
string GetOwnerId (); string OwnerId { get; }
bool AuthorizeCircle(long circleId); bool AuthorizeCircle(long circleId);
ICircleAuthorization [] GetACL(); ICircleAuthorization [] GetACL();

View File

@ -2,7 +2,7 @@ using System;
namespace Yavsc namespace Yavsc
{ {
public interface IBaseTrackedEntity public interface ITrackedEntity
{ {
DateTime DateCreated { get; set; } DateTime DateCreated { get; set; }
string UserCreated { get; set; } string UserCreated { get; set; }

View File

@ -0,0 +1,9 @@
namespace Yavsc.Interfaces
{
public interface IComment<TReceiverId>
{
string Content { get; set; }
TReceiverId ReceiverId { get; set; }
}
}

View File

@ -1,10 +0,0 @@
namespace Yavsc.Interfaces
{
public interface IComment<T> : IIdentified<T>
{
T GetReceiverId();
void SetReceiverId(T rid);
string Content { get; set; }
}
}

View File

@ -1 +0,0 @@


View File

@ -0,0 +1,9 @@
using Yavsc.Interfaces;
public class CommentPost : IComment<long>
{
public long ReceiverId { get; set; }
public long? ParentId { get; set; }
public string Content { get; set; }
}

View File

@ -2,7 +2,7 @@ using System;
namespace Yavsc.Abstract.Workflow namespace Yavsc.Abstract.Workflow
{ {
public interface IDecidableQuery: IBaseTrackedEntity, IQuery public interface IDecidableQuery: ITrackedEntity, IQuery
{ {
bool Decided { get; set; } bool Decided { get; set; }
bool Accepted { get; set; } bool Accepted { get; set; }

View File

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Workflow
using Yavsc; using Yavsc;
using Yavsc.Billing; using Yavsc.Billing;
public interface IQuery: IBaseTrackedEntity, IBillable public interface IQuery: ITrackedEntity, IBillable
{ {
QueryStatus Status { get; set; } QueryStatus Status { get; set; }
string PaymentId { get; set; } string PaymentId { get; set; }

View File

@ -1,37 +0,0 @@
//
// IIdentified.cs
//
// Author:
// Paul Schneider <paul@pschneider.fr>
//
// Copyright (c) 2015 GNU GPL
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace Yavsc
{
/// <summary>
/// I rating.
/// </summary>
public interface IRating<TK>: IIdentified<TK>
{
/// <summary>
/// Gets or sets the rate.
/// </summary>
/// <value>The rate.</value>
int Rate { get; set; }
}
}

View File

@ -9,8 +9,5 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="System.ComponentModel.DataAnnotations" />
</ItemGroup>
</Project> </Project>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
</packages>

View File

@ -1,5 +1,8 @@
 
using IdentityServer4.Models; using IdentityServer8;
using IdentityServer8.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Yavsc.Settings; using Yavsc.Settings;
namespace Yavsc; namespace Yavsc;
@ -38,13 +41,14 @@ public static class Config
{ {
new IdentityResources.OpenId(), new IdentityResources.OpenId(),
new IdentityResources.Profile(), new IdentityResources.Profile(),
new IdentityResources.Email()
}; };
public static IEnumerable<ApiScope> ApiScopes => public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[] new ApiScope[]
{ {
new ApiScope("scope1"), new ApiScope("scope1",new string[] {"scope1"}),
new ApiScope("scope2"), new ApiScope("scope2",new string[] {"scope2"}),
}; };
public static IEnumerable<Client> Clients => public static IEnumerable<Client> Clients =>
@ -65,17 +69,29 @@ public static class Config
// interactive client using code flow + pkce // interactive client using code flow + pkce
new Client new Client
{ {
ClientId = "interactive", ClientId = "mvc",
ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) }, ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
AllowedGrantTypes = GrantTypes.Code, AllowedGrantTypes = GrantTypes.Code,
AlwaysIncludeUserClaimsInIdToken = true,
RedirectUris = { "https://localhost:5003/signin-oidc" }, RedirectUris = { "https://localhost:5003/signin-oidc",
FrontChannelLogoutUri = "https://localhost:5003/signout-oidc", "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" }, PostLogoutRedirectUris = {
"http://localhost:5002/signout-callback-oidc",
"https://localhost:5003/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "scope2" } AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"scope2" }
,
AllowedCorsOrigins=new string[]{"*"},
AllowRememberConsent=true
}, },
}; };

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq;
using Yavsc.Abstract.FileSystem;
using Yavsc.Billing; using Yavsc.Billing;
using Yavsc.Models.Billing; using Yavsc.Models.Billing;
using Yavsc.Server.Helpers;
using Yavsc.Services; using Yavsc.Services;
namespace Yavsc.Helpers namespace Yavsc.Helpers

View File

@ -1,19 +1,30 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Yavsc.Exceptions;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.FileSystem; using Yavsc.Models.FileSystem;
using Yavsc.Models.Streaming; using Yavsc.Models.Streaming;
using Yavsc.ViewModels; using Yavsc.ViewModels;
using SixLabors.ImageSharp;
namespace Yavsc.Helpers using SixLabors.ImageSharp.Processing;
using Microsoft.AspNetCore.Http;
using Yavsc.Exceptions;
using Yavsc.Helpers;
using Yavsc.Abstract.Helpers;
namespace Yavsc.Server.Helpers
{ {
public static class FileSystemHelpers public static class FileSystemHelpers
{ {
public static async Task SaveAsAsync(this IFormFile formFile, string path)
{
if (formFile.Length > 0) {
using (Stream fileStream = new FileStream(path, FileMode.Create)) {
await formFile.CopyToAsync(fileStream);
}
}
}
public static FileRecievedInfo ReceiveProSignature(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signtype) public static FileRecievedInfo ReceiveProSignature(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signtype)
{ {
var item = new FileRecievedInfo var item = new FileRecievedInfo
@ -28,43 +39,12 @@ namespace Yavsc.Helpers
using (var org = formFile.OpenReadStream()) using (var org = formFile.OpenReadStream())
{ {
Image i = Image.FromStream(org); using Image image = Image.Load(org);
using (Bitmap source = new Bitmap(i)) image.Save(destFileName);
{
source.Save(destFileName, ImageFormat.Png);
}
} }
return item; return item;
} }
/// <summary>
/// Create avatars
/// </summary>
/// <param name="user"></param>
/// <param name="source"></param>
private static void CreateAvatars(this ApplicationUser user, Bitmap source)
{
var dir = Config.SiteSetup.Avatars;
var name = user.UserName + ".png";
var smallname = user.UserName + ".s.png";
var xsmallname = user.UserName + ".xs.png";
using (Bitmap newBMP = new Bitmap(source, 128, 128))
{
newBMP.Save(Path.Combine(
dir, name), ImageFormat.Png);
}
using (Bitmap newBMP = new Bitmap(source, 64, 64))
{
newBMP.Save(Path.Combine(
dir, smallname), ImageFormat.Png);
}
using (Bitmap newBMP = new Bitmap(source, 32, 32))
{
newBMP.Save(Path.Combine(
dir, xsmallname), ImageFormat.Png);
}
}
public static string GetAvatarUri(this ApplicationUser user) public static string GetAvatarUri(this ApplicationUser user)
{ {
return $"/{Config.SiteSetup.Avatars}/{user.UserName}.png"; return $"/{Config.SiteSetup.Avatars}/{user.UserName}.png";
@ -257,42 +237,15 @@ namespace Yavsc.Helpers
{ {
FileName = user.UserName + ".png" FileName = user.UserName + ".png"
}; };
var destFileName = Path.Combine(Config.SiteSetup.Avatars, item.FileName);
var fi = new FileInfo(destFileName);
if (fi.Exists) item.Overriden = true;
Rectangle cropRect = new Rectangle();
using (var org = formFile.OpenReadStream()) using (var org = formFile.OpenReadStream())
{ {
Image i = Image.FromStream(org); using Image image = Image.Load(org);
using (Bitmap source = new Bitmap(i)) image.Mutate(x=>x.Resize(128,128));
{ image.Save(Path.Combine(Config.SiteSetup.Avatars,item.FileName));
if (i.Width != i.Height) image.Mutate(x=>x.Resize(64,64));
{ image.Save(Path.Combine(Config.SiteSetup.Avatars,user.UserName + ".s.png"));
if (i.Width > i.Height) image.Mutate(x=>x.Resize(32,32));
{ image.Save(Path.Combine(Config.SiteSetup.Avatars,user.UserName + ".xs.png"));
cropRect.X = (i.Width - i.Height) / 2;
cropRect.Y = 0;
cropRect.Width = i.Height;
cropRect.Height = i.Height;
}
else
{
cropRect.X = 0;
cropRect.Y = (i.Height - i.Width) / 2;
cropRect.Width = i.Width;
cropRect.Height = i.Width;
}
using (var cropped = source.Clone(cropRect, source.PixelFormat))
{
CreateAvatars(user,cropped);
}
}
}
} }
item.DestDir = Config.AvatarsOptions.RequestPath.ToUriComponent(); item.DestDir = Config.AvatarsOptions.RequestPath.ToUriComponent();
user.Avatar = $"{item.DestDir}/{item.FileName}"; user.Avatar = $"{item.DestDir}/{item.FileName}";
@ -315,9 +268,5 @@ namespace Yavsc.Helpers
return $"{basename}-{flow.SequenceNumber}{ext}"; return $"{basename}-{flow.SequenceNumber}{ext}";
} }
public static void SaveAs(this IFormFile file, string destFileName)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Yavsc.Models.Drawing; using Yavsc.Models.Drawing;
namespace Yavsc.Helpers namespace Yavsc.Helpers

View File

@ -0,0 +1,53 @@
using System.Security.Claims;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Blog;
namespace Yavsc.Helpers
{
public static class UserHelpers
{
public static string GetUserId(this ClaimsPrincipal user)
{
return user.FindFirstValue("sub");
}
public static string GetUserName(this ClaimsPrincipal user)
{
return user.FindFirstValue(ClaimTypes.Name);
}
public static bool IsSignedIn(this ClaimsPrincipal user)
{
return user.Identity.IsAuthenticated;
}
public static IEnumerable<BlogPost> UserPosts(this ApplicationDbContext dbContext, string posterId, string readerId)
{
if (readerId == null)
{
var userPosts = dbContext.BlogSpot.Include(
b => b.Author
).Where(x => ((x.AuthorId == posterId) && (x.Visible))).ToArray();
return userPosts;
}
else
{
long[] readerCirclesMemberships =
dbContext.Circle.Include(c => c.Members)
.Where(c => c.Members.Any(m => m.MemberId == readerId))
.Select(c => c.Id).ToArray();
return dbContext.BlogSpot.Include(
b => b.Author
).Include(p => p.ACL).Where(x => x.Author.Id == posterId &&
(x.Visible &&
(x.ACL.Count == 0 || x.ACL.Any(a => readerCirclesMemberships.Contains(a.CircleId)))));
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More