refactor: 🔥🚧 purge docker, nginx, and Directory

This commit is contained in:
Collin Barrett 2024-05-27 09:23:23 -05:00
parent de413323ea
commit 094f8e3893
179 changed files with 0 additions and 2213256 deletions

View file

@ -1,2 +0,0 @@
DIRECTORY_HOST=directory-api
DIRECTORY_APPLICATION_INSIGHTS_SERVER_TELEMETRY_CHANNEL_STORAGE_PATH=application-insights

View file

@ -1,3 +0,0 @@
bin/
obj/
*.dcproj.user

View file

@ -1,2 +0,0 @@
URLS=[{url:'http://localhost:8080/api/directory/v1/swagger.json',name:'Directory'}]
URLS_PRIMARY_NAME=Directory

View file

@ -1,2 +0,0 @@
ApplicationInsights__InstrumentationKey=
ConnectionStrings__DirectoryConnection=Server=directory-db;Database=filterlists;User Id=filterlists;Password=filterlists;Include Error Detail=true;

View file

@ -1,3 +0,0 @@
POSTGRES_USER=filterlists
POSTGRES_PASSWORD=filterlists
POSTGRES_DB=filterlists

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
<PropertyGroup Label="Globals">
<ProjectVersion>2.1</ProjectVersion>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectGuid>8f04c802-830b-4b6d-8d53-5d2a87b4223d</ProjectGuid>
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
<DockerServiceUrl>http://localhost:8080/api/</DockerServiceUrl>
<DockerServiceName>directory-api</DockerServiceName>
</PropertyGroup>
<ItemGroup>
<None Include=".env" />
<None Include="directory-db.env" />
<None Include="directory-api.env" />
<None Include="api-docs.env" />
<None Include="docker-compose.directory.migrations.tests.yml" />
<None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.prod.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.prod.build.yml">
<DependentUpon>docker-compose.prod.yml</DependentUpon>
</None>
<None Include="docker-compose.yml" />
</ItemGroup>
</Project>

View file

@ -1,25 +0,0 @@
# for integration testing directory migrations
version: "3.7"
services:
directory-migrations-tests:
build:
context: ../services
dockerfile: Directory/FilterLists.Directory.Api/migrate.Dockerfile
target: test-migrations
volumes:
- directory-migrations-tests-results:/FilterLists.Directory.Infrastructure.Migrations.Tests/TestResults
depends_on:
- directory-db
env_file:
- directory-api.env
directory-db:
image: postgres:alpine
env_file:
- directory-db.env
volumes:
directory-migrations-tests-results:
external: true

View file

@ -1,23 +0,0 @@
# overrides for development
version: "3.7"
services:
reverse-proxy:
ports:
- "8080:80"
volumes:
- ../reverse-proxy/server-includes:/etc/nginx/server-includes:ro
- ../reverse-proxy/location-includes:/etc/nginx/location-includes:ro
- ../reverse-proxy/conf.d.dev:/etc/nginx/conf.d:ro
command: ["nginx-debug", "-g", "daemon off;"]
directory-api:
build:
context: ../services
dockerfile: Directory/FilterLists.Directory.Api/dev.Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
directory-db:
command: ["postgres", "-c", "log_statement=all"]

View file

@ -1,14 +0,0 @@
# overrides for production build
# https://github.com/docker/compose/issues/4047
version: "3.7"
services:
directory-api:
build:
context: ../services
dockerfile: Directory/FilterLists.Directory.Api/Dockerfile
web:
build:
context: ../web

View file

@ -1,23 +0,0 @@
# overrides for production deployment
version: "3.7"
services:
reverse-proxy:
ports:
- "443:443"
volumes:
- ./reverse-proxy/server-includes:/etc/nginx/server-includes:ro
- ./reverse-proxy/location-includes:/etc/nginx/location-includes:ro
- ./reverse-proxy/conf.d:/etc/nginx/conf.d:ro
- ~/cert:/etc/nginx/cert:ro
depends_on:
- web
web:
image: ghcr.io/collinbarrett/filterlists-web
restart: always
networks:
- reverse-proxy
depends_on:
- directory-api

View file

@ -1,56 +0,0 @@
version: "3.7"
services:
reverse-proxy:
image: nginx:alpine
restart: always
networks:
- reverse-proxy
depends_on:
- api-docs
- directory-api
api-docs:
image: swaggerapi/swagger-ui:latest
restart: always
networks:
- reverse-proxy
depends_on:
- directory-api
env_file:
- api-docs.env
directory-api:
image: ghcr.io/collinbarrett/filterlists-directory-api
restart: always
networks:
reverse-proxy:
aliases:
- ${DIRECTORY_HOST}
directory:
depends_on:
- directory-db
volumes:
- directory-application-insights:/app/${DIRECTORY_APPLICATION_INSIGHTS_SERVER_TELEMETRY_CHANNEL_STORAGE_PATH}
env_file:
- directory-api.env
environment:
ApplicationInsights__ServerTelemetryChannelStoragePath: ${DIRECTORY_APPLICATION_INSIGHTS_SERVER_TELEMETRY_CHANNEL_STORAGE_PATH}
directory-db:
image: postgres:alpine
restart: always
networks:
- directory
volumes:
- directory-db:/var/lib/postgresql/data
env_file:
- directory-db.env
networks:
reverse-proxy:
directory:
volumes:
directory-application-insights:
directory-db:

View file

@ -1,48 +0,0 @@
trigger:
batch: false
branches:
include: [main]
paths:
include:
[
reverse-proxy/*,
docker-compose/docker-compose.yml,
docker-compose/docker-compose.prod.yml,
]
pr: none
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
fetchDepth: 5
- task: CopyFiles@2
displayName: stage config files
inputs:
Contents: |
reverse-proxy/server-includes/*
reverse-proxy/location-includes/*
reverse-proxy/conf.d/*
TargetFolder: $(Build.ArtifactStagingDirectory)
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
- task: CopyFiles@2
displayName: stage docker-compose files
inputs:
SourceFolder: $(Build.SourcesDirectory)/docker-compose
Contents: |
docker-compose.yml
docker-compose.prod.yml
TargetFolder: $(Build.ArtifactStagingDirectory)
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
- task: PublishBuildArtifacts@1
displayName: publish files
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)
ArtifactName: drop
publishLocation: Container
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

View file

@ -1,22 +0,0 @@
server {
listen 80 default_server;
include server-includes/*;
location ^~ /api/directory/ {
resolver 127.0.0.11 valid=30s;
set $directory_api "directory-api";
rewrite ^/api/directory/(.*)$ /$1 break;
proxy_pass http://$directory_api:80;
include location-includes/*;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none';" always;
}
location ^~ /api/ {
resolver 127.0.0.11 valid=30s;
set $api_docs "api-docs";
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://$api_docs:8080;
include location-includes/*;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; connect-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' validator.swagger.io data:;" always;
}
}

View file

@ -1,48 +0,0 @@
server {
listen 443 default_server ssl http2;
server_name filterlists.com;
include server-includes/*;
ssl_certificate /etc/nginx/cert/filterlists_cert.pem;
ssl_certificate_key /etc/nginx/cert/filterlists_key.pem;
location ^~ /api/directory/ {
resolver 127.0.0.11 valid=30s;
set $directory_api "directory-api";
rewrite ^/api/directory/(.*)$ /$1 break;
proxy_pass http://$directory_api:80;
include location-includes/*;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none';" always;
}
location ^~ /api/ {
resolver 127.0.0.11 valid=30s;
set $api_docs "api-docs";
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://$api_docs:8080;
include location-includes/*;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; connect-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' validator.swagger.io data:;" always;
}
location / {
resolver 127.0.0.11 valid=30s;
set $web "web";
proxy_pass http://$web:80;
include location-includes/*;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; connect-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; manifest-src 'self';" always;
}
}
# Redirect http to https
server {
listen 80 default_server;
server_name filterlists.com;
return 301 https://filterlists.com$request_uri;
}
# Redirect www to non-www
server {
listen 80;
listen 443 ssl http2;
server_name www.filterlists.com;
return 301 https://filterlists.com$request_uri;
}

View file

@ -1,12 +0,0 @@
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# https://enable-cors.org/server_nginx.html
add_header Access-Control-Allow-Origin '*' always;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header Access-Control-Expose-Headers 'Content-Length,Content-Range' always;

View file

@ -1,8 +0,0 @@
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

View file

@ -1,20 +0,0 @@
server_tokens off;
# https://ssl-config.mozilla.org/#server=nginx&config=intermediate&ocsp=false
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_dhparam /etc/nginx/cert/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# https://support.cloudflare.com/hc/en-us/articles/204899617-Authenticated-Origin-Pulls
ssl_client_certificate /etc/nginx/cert/cloudflare.crt;
ssl_verify_client on;

View file

@ -1,33 +0,0 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
# FilterLists Services custom ignores
**/azure-pipelines*.yaml
**/*.sln
**/*.sln.DotSettings
Directory/FilterLists.Directory.Api/appsettings.Development.json
Directory/data/*

View file

@ -1,144 +0,0 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
indent_style = space
# XML project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# XML config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
###############################
# .NET Coding Conventions #
###############################
[*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
# this. preferences
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
###############################
# C# Coding Conventions #
###############################
[*.cs]
# var preferences
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent
csharp_style_var_elsewhere = true:silent
# Expression-bodied members
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:silent
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
###############################
# VB Coding Conventions #
###############################
[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
# FilterLists custom
[*.cs]
dotnet_diagnostic.CS1591.severity = silent
#https://github.com/JosefPihrt/Roslynator/blob/master/docs/Options.md
roslynator.RCS1090.invert = true
#https://github.com/SonarSource/sonar-dotnet/issues/4731
dotnet_diagnostic.S3903.severity = silent

399
services/.gitignore vendored
View file

@ -1,399 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea/

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Api.Contracts.Options;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Refit;
namespace FilterLists.Directory.Api.Contracts;
public static class ConfigurationExtensions
{
public static void AddDirectoryApiClient(this IServiceCollection services, IConfiguration configuration)
{
// TODO: use SystemTextJsonContentSerializer() once less feature-limited
services.AddRefitClient<IDirectoryApi>()
.ConfigureHttpClient(
c =>
{
var host = configuration.GetSection(ApiOptions.Key)
.Get<ApiOptions>()
?.DirectoryHost;
c.BaseAddress = new UriBuilder("http", host).Uri;
})
.AddTransientHttpErrorPolicy(
b =>
b.WaitAndRetryAsync(
new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) }));
}
}

View file

@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory API Contracts</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="7.0.13" />
<PackageReference Include="Refit.HttpClientFactory" Version="7.0.0" />
</ItemGroup>
</Project>

View file

@ -1,13 +0,0 @@
using FilterLists.Directory.Api.Contracts.Models;
using Refit;
namespace FilterLists.Directory.Api.Contracts;
public interface IDirectoryApi
{
[Get("/lists")]
Task<IEnumerable<ListVm>> GetListsAsync(CancellationToken cancellationToken);
[Get("/lists/{id}")]
Task<ListDetailsVm> GetListDetailsAsync(long id, CancellationToken cancellationToken);
}

View file

@ -1,168 +0,0 @@
namespace FilterLists.Directory.Api.Contracts.Models;
public record ListDetailsVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>301</example>
public long Id { get; init; }
/// <summary>
/// The unique name in title case.
/// </summary>
/// <example>EasyList</example>
public string Name { get; init; } = default!;
/// <summary>
/// The brief description in English (preferably quoted from the project).
/// </summary>
/// <example>EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.</example>
public string? Description { get; init; }
/// <summary>
/// The identifier of the License under which this FilterList is released.
/// </summary>
/// <example>4</example>
public long LicenseId { get; init; }
/// <summary>
/// The identifiers of the Syntaxes implemented by this FilterList.
/// </summary>
/// <example>[ 3 ]</example>
public IEnumerable<long> SyntaxIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Languages targeted by this FilterList.
/// </summary>
/// <example>[ 37 ]</example>
public IEnumerable<long> LanguageIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Tags applied to this FilterList.
/// </summary>
/// <example>[ 2 ]</example>
public IEnumerable<long> TagIds { get; init; } = new HashSet<long>();
/// <summary>
/// The view URLs.
/// </summary>
public IEnumerable<ViewUrlVm> ViewUrls { get; init; } = new HashSet<ViewUrlVm>();
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://easylist.to/</example>
public Uri? HomeUrl { get; init; }
/// <summary>
/// The URL of the Tor / Onion page.
/// </summary>
/// <example>null</example>
public Uri? OnionUrl { get; init; }
/// <summary>
/// The URL of the policy/guidelines for the types of rules this FilterList includes.
/// </summary>
/// <example>null</example>
public Uri? PolicyUrl { get; init; }
/// <summary>
/// The URL of the submission/contact form for adding rules to this FilterList.
/// </summary>
/// <example>null</example>
public Uri? SubmissionUrl { get; init; }
/// <summary>
/// The URL of the GitHub Issues page.
/// </summary>
/// <example>https://github.com/easylist/easylist/issues</example>
public Uri? IssuesUrl { get; init; }
/// <summary>
/// The URL of the forum page.
/// </summary>
/// <example>https://forums.lanik.us/viewforum.php?f=23</example>
public Uri? ForumUrl { get; init; }
/// <summary>
/// The URL of the chat room.
/// </summary>
/// <example>null</example>
public Uri? ChatUrl { get; init; }
/// <summary>
/// The email address at which the project can be contacted.
/// </summary>
/// <example>easylist@protonmail.com</example>
public string? EmailAddress { get; init; }
/// <summary>
/// The URL at which donations to the project can be made.
/// </summary>
/// <example>null</example>
public Uri? DonateUrl { get; init; }
/// <summary>
/// The identifiers of the Maintainers of this FilterList.
/// </summary>
/// <example>[ 7 ]</example>
public IEnumerable<long> MaintainerIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists from which this FilterList was forked.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> UpstreamFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that have been forked from this FilterList.
/// </summary>
/// <example>[ 166, 565 ]</example>
public IEnumerable<long> ForkFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that include this FilterList.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> IncludedInFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that this FilterList includes.
/// </summary>
/// <example>[ 11, 13, 168 ]</example>
public IEnumerable<long> IncludesFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that this FilterList depends upon.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> DependencyFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists dependent upon this FilterList.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> DependentFilterListIds { get; init; } = new HashSet<long>();
public record ViewUrlVm
{
/// <summary>
/// The segment number of the URL for the FilterList (for multi-part lists).
/// </summary>
/// <example>1</example>
public short SegmentNumber { get; init; }
/// <summary>
/// How primary the URL is for the FilterList segment (1 is original, 2+ is a mirror; unique per SegmentNumber)
/// </summary>
/// <example>1</example>
public short Primariness { get; init; }
/// <summary>
/// The view URL.
/// </summary>
/// <example>https://easylist.to/easylist/easylist.txt</example>
public Uri Url { get; init; } = default!;
}
}

View file

@ -1,58 +0,0 @@
namespace FilterLists.Directory.Api.Contracts.Models;
public record ListVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>301</example>
public long Id { get; init; }
/// <summary>
/// The unique name in title case.
/// </summary>
/// <example>EasyList</example>
public string Name { get; init; } = default!;
/// <summary>
/// The brief description in English (preferably quoted from the project).
/// </summary>
/// <example>EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.</example>
public string? Description { get; init; }
/// <summary>
/// The identifier of the License under which this FilterList is released.
/// </summary>
/// <example>4</example>
public long LicenseId { get; init; }
/// <summary>
/// The identifiers of the Syntaxes implemented by this FilterList.
/// </summary>
/// <example>[ 3 ]</example>
public IEnumerable<long> SyntaxIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Languages targeted by this FilterList.
/// </summary>
/// <example>[ 37 ]</example>
public IEnumerable<long> LanguageIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Tags applied to this FilterList.
/// </summary>
/// <example>[ 2 ]</example>
public IEnumerable<long> TagIds { get; init; } = new HashSet<long>();
/// <summary>
/// The primary view URL.
/// </summary>
/// <example>https://easylist.to/easylist/easylist.txt</example>
public Uri? PrimaryViewUrl { get; init; }
/// <summary>
/// The identifiers of the Maintainers of this FilterList.
/// </summary>
/// <example>[ 7 ]</example>
public IEnumerable<long> MaintainerIds { get; init; } = new HashSet<long>();
}

View file

@ -1,8 +0,0 @@
namespace FilterLists.Directory.Api.Contracts.Options;
internal record ApiOptions
{
public const string Key = "Api";
public string DirectoryHost { get; init; } = default!;
}

View file

@ -1,34 +0,0 @@
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public abstract class BaseController : ControllerBase
{
private readonly IMemoryCache _cache;
protected BaseController(IMemoryCache cache)
{
_cache = cache;
}
/// <remarks>https://stackoverflow.com/a/52506210/2343739</remarks>
protected async Task<IActionResult> CacheGetOrCreateAsync<TResponse>(
Func<Task<TResponse>> actionAsync,
long? keySuffix = default,
TimeSpan? absoluteExpirationRelativeToNow = default,
[CallerMemberName] string key = default!)
{
var cacheKey = $"{GetType().Name}_{key}{(keySuffix is null ? string.Empty : $"_{keySuffix}")}";
var result = await _cache.GetOrCreateAsync(cacheKey, entry =>
{
entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
return actionAsync();
});
return result is null ? NotFound() : Ok(result);
}
}

View file

@ -1,46 +0,0 @@
#if DEBUG
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class ChangesController : BaseController
{
private readonly IMediator _mediator;
public ChangesController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// ALPHA: Gets the changes to the FilterLists pending approval.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The changes.</returns>
[HttpGet]
[ProducesResponseType(typeof(List<GetChanges.ChangeVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetChanges.Query(), cancellationToken));
}
/// <summary>
/// ALPHA: Gets the change to the FilterLists.
/// </summary>
/// <param name="id">The identifier of the change.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The change.</returns>
[HttpGet("{id:long}")]
[ProducesResponseType(typeof(GetChange.ChangeVm), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public Task<IActionResult> GetDetails(long id, CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetChange.Query { Id = id }, cancellationToken), id);
}
}
#endif

View file

@ -1,28 +0,0 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
namespace FilterLists.Directory.Api.Controllers;
[ApiController]
[ApiExplorerSettings(IgnoreApi = true)]
// TODO: de-duplicate into SharedKernel
public class ErrorController : ControllerBase
{
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment([FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException("This shouldn't be invoked in non-development environments.");
}
var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
return Problem(context?.Error.StackTrace, title: context?.Error.Message);
}
[Route("/error")]
public IActionResult Error()
{
return Problem();
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class LanguagesController : BaseController
{
private readonly IMediator _mediator;
public LanguagesController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the languages targeted by the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The languages targeted by the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetLanguages.LanguageVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetLanguages.Query(), cancellationToken));
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class LicensesController : BaseController
{
private readonly IMediator _mediator;
public LicensesController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the licenses applied to the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The licenses applied to the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetLicenses.LicenseVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetLicenses.Query(), cancellationToken));
}
}

View file

@ -1,64 +0,0 @@
using FilterLists.Directory.Api.Contracts.Models;
using FilterLists.Directory.Application.Commands;
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class ListsController : BaseController
{
private readonly IMediator _mediator;
public ListsController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<ListVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetLists.Query(), cancellationToken));
}
#if DEBUG
/// <summary>
/// ALPHA: Creates the FilterList pending moderator approval.
/// </summary>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
[HttpPost]
[ProducesResponseType(typeof(CreateList.Response), StatusCodes.Status202Accepted)]
public async Task<IActionResult> Create(CreateList.Command command, CancellationToken cancellationToken)
{
var response = await _mediator.Send(command, cancellationToken);
return AcceptedAtAction(
nameof(ChangesController.GetDetails),
nameof(ChangesController).Replace("Controller", string.Empty),
new { id = response.ChangeId });
}
#endif
/// <summary>
/// Gets the details of the FilterList.
/// </summary>
/// <param name="id">The identifier of the FilterList.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The details of the FilterList.</returns>
[HttpGet("{id:long}")]
[ProducesResponseType(typeof(ListDetailsVm), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public Task<IActionResult> GetDetails(long id, CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetListDetails.Query { Id = id }, cancellationToken), id);
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class MaintainersController : BaseController
{
private readonly IMediator _mediator;
public MaintainersController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the maintainers of the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The maintainers of the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetMaintainers.MaintainerVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetMaintainers.Query(), cancellationToken));
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class SoftwareController : BaseController
{
private readonly IMediator _mediator;
public SoftwareController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the software that subscribes to the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The software that subscribes to the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetSoftware.SoftwareVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetSoftware.Query(), cancellationToken));
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class SyntaxesController : BaseController
{
private readonly IMediator _mediator;
public SyntaxesController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the syntaxes of the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The syntaxes of the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetSyntaxes.SyntaxVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetSyntaxes.Query(), cancellationToken));
}
}

View file

@ -1,28 +0,0 @@
using FilterLists.Directory.Application.Queries;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace FilterLists.Directory.Api.Controllers;
public class TagsController : BaseController
{
private readonly IMediator _mediator;
public TagsController(IMemoryCache cache, IMediator mediator) : base(cache)
{
_mediator = mediator;
}
/// <summary>
/// Gets the tags of the FilterLists.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The tags of the FilterLists.</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<GetTags.TagVm>), StatusCodes.Status200OK)]
public Task<IActionResult> Get(CancellationToken cancellationToken)
{
return CacheGetOrCreateAsync(() => _mediator.Send(new GetTags.Query(), cancellationToken));
}
}

View file

@ -1,46 +0,0 @@
# init base
FROM mcr.microsoft.com/dotnet/runtime-deps:7.0-alpine AS base
LABEL org.opencontainers.image.source="https://github.com/collinbarrett/FilterLists"
LABEL org.opencontainers.image.description="filterlists.com | github.com/collinbarrett/filterlists | An ASP.NET Core API serving the core FilterList information."
LABEL org.opencontainers.image.licenses="MIT"
WORKDIR /app
EXPOSE 80
# init build
FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
# restore API
WORKDIR /app
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/FilterLists.SharedKernel.Domain.SeedWork.csproj SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/FilterLists.SharedKernel.Logging.csproj SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/FilterLists.Directory.Domain.csproj Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/FilterLists.Directory.Infrastructure.csproj Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/FilterLists.Directory.Infrastructure.Migrations.csproj Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/FilterLists.Directory.Api.Contracts.csproj Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/FilterLists.Directory.Application.csproj Directory/FilterLists.Directory.Application/
WORKDIR /app/Directory/FilterLists.Directory.Api
COPY Directory/FilterLists.Directory.Api/FilterLists.Directory.Api.csproj .
RUN dotnet restore
# build API
WORKDIR /app
COPY /.editorconfig .
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/. SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/. SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/. Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/. Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/. Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/. Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/. Directory/FilterLists.Directory.Application/
WORKDIR /app/Directory/FilterLists.Directory.Api
COPY Directory/FilterLists.Directory.Api/. .
# TODO: enable PublishTrimmed in csproj file
# TODO: enable PublishReadyToRun
RUN dotnet publish -c Release -p:DebugType=None -p:DebugSymbols=false --no-restore -o /app/publish -p:TreatWarningsAsErrors=true -r linux-musl-x64 --self-contained true -p:PublishSingleFile=true
# package final
FROM base AS final
COPY --from=build /app/publish .
ENTRYPOINT ./FilterLists.Directory.Api

View file

@ -1,45 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishReadyToRunShowWarnings>true</PublishReadyToRunShowWarnings>
<RuntimeIdentifiers>linux-musl-x64;win10-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
<DockerComposeProjectPath>..\..\..\docker-compose\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Globalization.Invariant" Value="true" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Hellang.Middleware.ProblemDetails" Version="6.5.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FilterLists.Directory.Application\FilterLists.Directory.Application.csproj" />
<ProjectReference Include="..\FilterLists.Directory.Infrastructure.Migrations\FilterLists.Directory.Infrastructure.Migrations.csproj" />
</ItemGroup>
</Project>

View file

@ -1,32 +0,0 @@
using FluentValidation;
using Hellang.Middleware.ProblemDetails;
using ProblemDetailsOptions = Hellang.Middleware.ProblemDetails.ProblemDetailsOptions;
namespace FilterLists.Directory.Api;
internal static class ProblemDetailsConfigurationExtensions
{
public static void ConfigureProblemDetails(this ProblemDetailsOptions options)
{
options.MapFluentValidationException();
options.MapToStatusCode<NotImplementedException>(StatusCodes.Status501NotImplemented);
options.MapToStatusCode<HttpRequestException>(StatusCodes.Status503ServiceUnavailable);
options.MapToStatusCode<Exception>(StatusCodes.Status500InternalServerError);
}
private static void MapFluentValidationException(this ProblemDetailsOptions options)
{
options.Map<ValidationException>(
(ctx, ex) =>
{
var factory = ctx.RequestServices.GetRequiredService<ProblemDetailsFactory>();
var errors = ex.Errors
.GroupBy(f => f.PropertyName)
.ToDictionary(
g => g.Key,
g => g.Select(f => f.ErrorMessage)
.ToArray());
return factory.CreateValidationProblemDetails(ctx, errors);
});
}
}

View file

@ -1,35 +0,0 @@
using System.Text.Json.Serialization;
using FilterLists.Directory.Api;
using FilterLists.Directory.Application;
using FilterLists.Directory.Infrastructure.Persistence;
using FilterLists.SharedKernel.Logging;
using Hellang.Middleware.ProblemDetails;
using Hellang.Middleware.ProblemDetails.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureApplication();
builder.Services.AddMemoryCache();
builder.Services.AddProblemDetails(ProblemDetailsConfigurationExtensions.ConfigureProblemDetails);
builder.Services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
builder.Services.AddControllers()
.AddProblemDetailsConventions()
.AddJsonOptions(o => o.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApplication(builder.Configuration);
var app = builder.Build();
app.UseApplication();
app.UseExceptionHandler(app.Environment.IsDevelopment() ? "/error-local-development" : "/error");
app.UseProblemDetails();
app.UseSwagger();
app.MapControllers();
app.Use(async (context, next) =>
{
context.Request.PathBase = "/api/directory";
await next.Invoke();
});
await app.TryRunWithLoggingAsync(() => app.MigrateAsync());

View file

@ -1,35 +0,0 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:60529",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"FilterLists.Directory.Api": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000",
"dotnetRunMessages": "true"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true
}
}
}

View file

@ -1,55 +0,0 @@
using System.Reflection;
using Microsoft.OpenApi.Models;
namespace FilterLists.Directory.Api;
internal static class SwaggerConfigurationExtensions
{
public static void AddSwaggerGen(this IServiceCollection services)
{
services.AddSwaggerGen(o =>
{
o.SupportNonNullableReferenceTypes();
o.SwaggerDoc(
"v1",
new OpenApiInfo
{
Title = "FilterLists Directory API",
Description = "An ASP.NET Core API serving the core FilterList information.",
Version = "v1",
//TermsOfService = "",
Contact = new OpenApiContact { Name = "FilterLists", Url = new Uri("https://filterlists.com") },
License = new OpenApiLicense
{
Name = "MIT License",
Url = new Uri("https://github.com/collinbarrett/FilterLists/blob/main/LICENSE")
}
});
// Swagger UI struggles with lookups of nested types represented by concatenated '+'
o.CustomSchemaIds(t => t.FullName?.Replace("+", "."));
var apiXmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, apiXmlFile));
var apiContractsXmlFile = $"{typeof(Contracts.ConfigurationExtensions).Assembly.GetName().Name}.xml";
o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, apiContractsXmlFile));
var applicationXmlFile = $"{typeof(Application.ConfigurationExtensions).Assembly.GetName().Name}.xml";
o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, applicationXmlFile));
});
}
public static void UseSwagger(this IApplicationBuilder app)
{
app.UseSwagger(o =>
{
o.RouteTemplate = "{documentName}/swagger.json";
o.PreSerializeFilters.Add((swaggerDoc, httpReq) => swaggerDoc.Servers = new List<OpenApiServer>
{
new() { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}/api/directory" }
});
});
}
}

View file

@ -1,9 +0,0 @@
{
"_comment": "Used only for managing EF migrations. All other configuration is done via environment variables.",
"ApplicationInsights": {
"ServerTelemetryChannelStoragePath": "application-insights"
},
"ConnectionStrings": {
"DirectoryConnection": "Server=directory-db;Database=filterlists;User Id=filterlists;Password=filterlists;"
}
}

View file

@ -1,40 +0,0 @@
# init base for Visual Studio debugging
FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS base
WORKDIR /app
EXPOSE 80
# init build
FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
# restore API
WORKDIR /app
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/FilterLists.SharedKernel.Domain.SeedWork.csproj SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/FilterLists.SharedKernel.Logging.csproj SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/FilterLists.Directory.Domain.csproj Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/FilterLists.Directory.Infrastructure.csproj Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/FilterLists.Directory.Infrastructure.Migrations.csproj Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/FilterLists.Directory.Api.Contracts.csproj Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/FilterLists.Directory.Application.csproj Directory/FilterLists.Directory.Application/
WORKDIR /app/Directory/FilterLists.Directory.Api
COPY Directory/FilterLists.Directory.Api/FilterLists.Directory.Api.csproj .
RUN dotnet restore
# build API
WORKDIR /app
COPY /.editorconfig .
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/. SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/. SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/. Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/. Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/. Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/. Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/. Directory/FilterLists.Directory.Application/
WORKDIR /app/Directory/FilterLists.Directory.Api
COPY Directory/FilterLists.Directory.Api/. .
RUN dotnet publish --no-restore -o /app/publish -r linux-musl-x64
# package final
FROM base AS final
COPY --from=build /app/publish .
ENTRYPOINT ./FilterLists.Directory.Api

View file

@ -1,32 +0,0 @@
# init test-migrations
FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS test-migrations
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
ENTRYPOINT ["dotnet", "test", "--logger:trx"]
# restore
WORKDIR /app
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/FilterLists.SharedKernel.Domain.SeedWork.csproj SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/FilterLists.SharedKernel.Logging.csproj SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/FilterLists.Directory.Domain.csproj Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/FilterLists.Directory.Infrastructure.csproj Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/FilterLists.Directory.Infrastructure.Migrations.csproj Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/FilterLists.Directory.Api.Contracts.csproj Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/FilterLists.Directory.Application.csproj Directory/FilterLists.Directory.Application/
COPY Directory/FilterLists.Directory.Api/FilterLists.Directory.Api.csproj Directory/FilterLists.Directory.Api/
WORKDIR /app/Directory/FilterLists.Directory.Infrastructure.Migrations.Tests
COPY Directory/FilterLists.Directory.Infrastructure.Migrations.Tests/FilterLists.Directory.Infrastructure.Migrations.Tests.csproj .
RUN dotnet restore
# build
WORKDIR /app
COPY SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/. SharedKernel/FilterLists.SharedKernel.Domain.SeedWork/
COPY SharedKernel/FilterLists.SharedKernel.Logging/. SharedKernel/FilterLists.SharedKernel.Logging/
COPY Directory/FilterLists.Directory.Domain/. Directory/FilterLists.Directory.Domain/
COPY Directory/FilterLists.Directory.Infrastructure/. Directory/FilterLists.Directory.Infrastructure/
COPY Directory/FilterLists.Directory.Infrastructure.Migrations/. Directory/FilterLists.Directory.Infrastructure.Migrations/
COPY Directory/FilterLists.Directory.Api.Contracts/. Directory/FilterLists.Directory.Api.Contracts/
COPY Directory/FilterLists.Directory.Application/. Directory/FilterLists.Directory.Application/
COPY Directory/FilterLists.Directory.Api/. Directory/FilterLists.Directory.Api/
WORKDIR /app/Directory/FilterLists.Directory.Infrastructure.Migrations.Tests
COPY Directory/FilterLists.Directory.Infrastructure.Migrations.Tests/. .
RUN dotnet build -c Release --no-restore -p:TreatWarningsAsErrors=true -r linux-musl-x64 --self-contained true

View file

@ -1,388 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.Directory.Domain.Aggregates.Languages;
using FilterLists.Directory.Domain.Aggregates.Licenses;
using FilterLists.Directory.Domain.Aggregates.Maintainers;
using FilterLists.Directory.Domain.Aggregates.Syntaxes;
using FilterLists.Directory.Domain.Aggregates.Tags;
using FilterLists.Directory.Infrastructure.Persistence.Commands.Context;
using FluentValidation;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Commands;
public static class CreateList
{
public record Command : IRequest<Response>
{
/// <summary>
/// The unique name in title case.
/// </summary>
/// <example>EasyList</example>
public string Name { get; init; } = default!;
/// <summary>
/// The brief description in English (preferably quoted from the project).
/// </summary>
/// <example>EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.</example>
public string? Description { get; init; }
/// <summary>
/// The identifier of the License under which this FilterList is released.
/// </summary>
/// <example>4</example>
public long? LicenseId { get; init; }
/// <summary>
/// The identifiers of the Syntaxes implemented by this FilterList.
/// </summary>
/// <example>[ 3 ]</example>
public IEnumerable<long> SyntaxIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Languages targeted by this FilterList.
/// </summary>
/// <example>[ 37 ]</example>
public IEnumerable<long> LanguageIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Tags applied to this FilterList.
/// </summary>
/// <example>[ 2 ]</example>
public IEnumerable<long> TagIds { get; init; } = new HashSet<long>();
/// <summary>
/// The view URLs.
/// </summary>
public IEnumerable<FilterListViewUrl> ViewUrls { get; init; } = new HashSet<FilterListViewUrl>();
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://easylist.to/</example>
public Uri? HomeUrl { get; init; }
/// <summary>
/// The URL of the Tor / Onion page.
/// </summary>
/// <example>null</example>
public Uri? OnionUrl { get; init; }
/// <summary>
/// The URL of the policy/guidelines for the types of rules this FilterList includes.
/// </summary>
/// <example>null</example>
public Uri? PolicyUrl { get; init; }
/// <summary>
/// The URL of the submission/contact form for adding rules to this FilterList.
/// </summary>
/// <example>null</example>
public Uri? SubmissionUrl { get; init; }
/// <summary>
/// The URL of the GitHub Issues page.
/// </summary>
/// <example>https://github.com/easylist/easylist/issues</example>
public Uri? IssuesUrl { get; init; }
/// <summary>
/// The URL of the forum page.
/// </summary>
/// <example>https://forums.lanik.us/viewforum.php?f=23</example>
public Uri? ForumUrl { get; init; }
/// <summary>
/// The URL of the chat room.
/// </summary>
/// <example>null</example>
public Uri? ChatUrl { get; init; }
/// <summary>
/// The email address at which the project can be contacted.
/// </summary>
/// <example>easylist@protonmail.com</example>
public string? EmailAddress { get; init; }
/// <summary>
/// The URL at which donations to the project can be made.
/// </summary>
/// <example>null</example>
public Uri? DonateUrl { get; init; }
/// <summary>
/// The identifiers of the Maintainers of this FilterList.
/// </summary>
/// <example>[ 7 ]</example>
public IEnumerable<long> MaintainerIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists from which this FilterList was forked.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> UpstreamFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that have been forked from this FilterList.
/// </summary>
/// <example>[ 166, 565 ]</example>
public IEnumerable<long> ForkFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that include this FilterList.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> IncludedInFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that this FilterList includes.
/// </summary>
/// <example>[ 11, 13, 168 ]</example>
public IEnumerable<long> IncludesFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists that this FilterList depends upon.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> DependencyFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the FilterLists dependent upon this FilterList.
/// </summary>
/// <example>[]</example>
public IEnumerable<long> DependentFilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The reason that the FilterList is being added to FilterLists.
/// </summary>
/// <example>Adding EasyList because I did not see it on FilterLists.com yet.</example>
public string? CreateReason { get; init; }
}
public record FilterListViewUrl
{
/// <summary>
/// The segment number of the URL for the FilterList (for multi-part lists).
/// </summary>
/// <example>1</example>
public short SegmentNumber { get; init; }
/// <summary>
/// How primary the URL is for the FilterList segment (1 is original, 2+ is a mirror; unique per SegmentNumber)
/// </summary>
/// <example>1</example>
public short Primariness { get; init; }
/// <summary>
/// The view URL.
/// </summary>
/// <example>https://easylist.to/easylist/easylist.txt</example>
public Uri Url { get; init; } = default!;
}
internal class Validator : AbstractValidator<Command>
{
public Validator(IValidator<long?> entityIdValidator, IValidator<Uri?> urlValidator)
{
RuleFor(c => c.LicenseId)
.SetValidator(entityIdValidator);
RuleForEach(c => c.SyntaxIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.SyntaxIds));
RuleForEach(c => c.LanguageIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.LanguageIds));
RuleForEach(c => c.TagIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.TagIds));
RuleForEach(c => c.ViewUrls.Select(u => u.Url))
.SetValidator(urlValidator)
.OverridePropertyName(nameof(Command.ViewUrls) + "." + nameof(FilterListViewUrl.Url));
RuleForEach(c => c.ViewUrls.Select(u => u.SegmentNumber))
.GreaterThan((short)0)
.OverridePropertyName(nameof(Command.ViewUrls) + "." + nameof(FilterListViewUrl.SegmentNumber));
RuleForEach(c => c.ViewUrls.Select(u => u.Primariness))
.GreaterThan((short)0)
.OverridePropertyName(nameof(Command.ViewUrls) + "." + nameof(FilterListViewUrl.Primariness));
RuleFor(c => c.HomeUrl)
.SetValidator(urlValidator);
RuleFor(c => c.OnionUrl)
.SetValidator(urlValidator);
RuleFor(c => c.PolicyUrl)
.SetValidator(urlValidator);
RuleFor(c => c.SubmissionUrl)
.SetValidator(urlValidator);
RuleFor(c => c.IssuesUrl)
.SetValidator(urlValidator);
RuleFor(c => c.ForumUrl)
.SetValidator(urlValidator);
RuleFor(c => c.ChatUrl)
.SetValidator(urlValidator);
RuleFor(c => c.DonateUrl)
.SetValidator(urlValidator);
RuleForEach(c => c.MaintainerIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.MaintainerIds));
RuleForEach(c => c.UpstreamFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.UpstreamFilterListIds));
RuleForEach(c => c.ForkFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.ForkFilterListIds));
RuleForEach(c => c.IncludedInFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.IncludedInFilterListIds));
RuleForEach(c => c.IncludesFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.IncludesFilterListIds));
RuleForEach(c => c.DependencyFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.DependencyFilterListIds));
RuleForEach(c => c.DependentFilterListIds.Select(id => (long?)id))
.SetValidator(entityIdValidator)
.OverridePropertyName(nameof(Command.DependentFilterListIds));
}
}
internal class Handler : IRequestHandler<Command, Response>
{
private readonly ICommandContext _commandContext;
public Handler(ICommandContext commandContext)
{
_commandContext = commandContext;
}
public async Task<Response> Handle(Command request, CancellationToken cancellationToken)
{
// TODO: push applying domain rule of specified or default license into domain layer?
var license = request.LicenseId != null
? await _commandContext.Licenses
.FindAsync(new object[] { request.LicenseId.Value }, cancellationToken)
?? throw new ArgumentException($"LicenseId {request.LicenseId} not found.", nameof(request.LicenseId))
: await _commandContext.Licenses
.WhereIsDefaultForFilterList()
.SingleAsync(cancellationToken);
var syntaxes = request.SyntaxIds.Any()
? await _commandContext.Syntaxes
.Where(s => request.SyntaxIds.Contains(s.Id))
.ToListAsync(cancellationToken)
: new List<Syntax>();
if (request.SyntaxIds.Any(sid => !syntaxes.Select(s => s.Id).Contains(sid)))
{
throw new ArgumentException("One or more SyntaxIds not found.", nameof(request.SyntaxIds));
}
var languages = request.LanguageIds.Any()
? await _commandContext.Languages
.Where(l => request.LanguageIds.Contains(l.Id))
.ToListAsync(cancellationToken)
: new List<Language>();
if (request.LanguageIds.Any(lid => !languages.Select(l => l.Id).Contains(lid)))
{
throw new ArgumentException("One or more LanguageIds not found.", nameof(request.LanguageIds));
}
var tags = request.TagIds.Any()
? await _commandContext.Tags
.Where(t => request.TagIds.Contains(t.Id))
.ToListAsync(cancellationToken)
: new List<Tag>();
if (request.TagIds.Any(tig => !tags.Select(t => t.Id).Contains(tig)))
{
throw new ArgumentException("One or more TagIds not found.", nameof(request.TagIds));
}
var maintainers = request.MaintainerIds.Any()
? await _commandContext.Maintainers
.Where(m => request.MaintainerIds.Contains(m.Id))
.ToListAsync(cancellationToken)
: new List<Maintainer>();
if (request.MaintainerIds.Any(mid => !maintainers.Select(m => m.Id).Contains(mid)))
{
throw new ArgumentException("One or more MaintainerIds not found.", nameof(request.MaintainerIds));
}
var relatedFilterListIds = request.UpstreamFilterListIds
.Concat(request.ForkFilterListIds)
.Concat(request.IncludedInFilterListIds)
.Concat(request.IncludesFilterListIds)
.Concat(request.DependencyFilterListIds)
.Concat(request.DependentFilterListIds)
.ToList();
var relatedFilterLists = relatedFilterListIds.Count > 0
? await _commandContext.FilterLists
.Where(f => relatedFilterListIds.Contains(f.Id))
.ToListAsync(cancellationToken)
: new List<FilterList>();
if (request.UpstreamFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more UpstreamFilterListIds not found.", nameof(request.UpstreamFilterListIds));
}
if (request.ForkFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more ForkFilterListIds not found.", nameof(request.ForkFilterListIds));
}
if (request.IncludedInFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more IncludedInFilterListIds not found.", nameof(request.IncludedInFilterListIds));
}
if (request.IncludesFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more IncludesFilterListIds not found.", nameof(request.IncludesFilterListIds));
}
if (request.DependencyFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more DependencyFilterListIds not found.", nameof(request.DependencyFilterListIds));
}
if (request.DependentFilterListIds.Any(fid => !relatedFilterLists.Select(f => f.Id).Contains(fid)))
{
throw new ArgumentException("One or more DependentFilterListIds not found.", nameof(request.DependentFilterListIds));
}
var filterList = FilterList.CreatePendingApproval(
request.Name,
request.Description,
license,
syntaxes,
languages,
tags,
request.ViewUrls.Select(u => (u.SegmentNumber, u.Primariness, u.Url)),
request.HomeUrl,
request.OnionUrl,
request.PolicyUrl,
request.SubmissionUrl,
request.IssuesUrl,
request.ForumUrl,
request.ChatUrl,
request.EmailAddress,
request.DonateUrl,
maintainers,
relatedFilterLists.Where(f => request.UpstreamFilterListIds.Contains(f.Id)),
relatedFilterLists.Where(f => request.ForkFilterListIds.Contains(f.Id)),
relatedFilterLists.Where(f => request.IncludedInFilterListIds.Contains(f.Id)),
relatedFilterLists.Where(f => request.IncludesFilterListIds.Contains(f.Id)),
relatedFilterLists.Where(f => request.DependencyFilterListIds.Contains(f.Id)),
relatedFilterLists.Where(f => request.DependentFilterListIds.Contains(f.Id)),
request.CreateReason);
_commandContext.FilterLists.Add(filterList);
await _commandContext.SaveChangesAsync(cancellationToken);
return new Response
{
ChangeId = filterList.Changes.Select(c => c.Id).Single()
};
}
}
public record Response
{
/// <summary>
/// The identifier of the Change for the new FilterList.
/// </summary>
/// <example>99</example>
public long ChangeId { get; init; }
}
}

View file

@ -1,33 +0,0 @@
using FilterLists.Directory.Application.Validators;
using FilterLists.Directory.Infrastructure;
using FluentValidation;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace FilterLists.Directory.Application;
public static class ConfigurationExtensions
{
public static IHostBuilder ConfigureApplication(this IHostBuilder hostBuilder)
{
return hostBuilder.ConfigureInfrastructure();
}
public static void AddApplication(this IServiceCollection services, IConfiguration configuration)
{
services.AddInfrastructure(configuration);
services.AddHttpClient();
services.AddValidatorsFromAssembly(typeof(ConfigurationExtensions).Assembly, includeInternalTypes: true);
services.AddAutoMapper(typeof(ConfigurationExtensions).Assembly);
services.AddMediatR(typeof(ConfigurationExtensions).Assembly);
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorPipelineBehavior<,>));
}
public static void UseApplication(this IApplicationBuilder app)
{
app.UseInfrastructure();
}
}

View file

@ -1,31 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FilterLists.Directory.Api.Contracts\FilterLists.Directory.Api.Contracts.csproj" />
<ProjectReference Include="..\FilterLists.Directory.Infrastructure\FilterLists.Directory.Infrastructure.csproj" />
</ItemGroup>
</Project>

View file

@ -1,151 +0,0 @@
using System.Text.Json;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Domain.Aggregates;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetChange
{
public record Query : IRequest<ChangeVm?>
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>99</example>
public long Id { get; init; }
}
internal class Handler : IRequestHandler<Query, ChangeVm?>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<ChangeVm?> Handle(Query request, CancellationToken cancellationToken)
{
return _context.Changes
.Where(c => c.Id == request.Id)
.ProjectTo<ChangeVm>(_mapper.ConfigurationProvider)
.SingleOrDefaultAsync(cancellationToken);
}
}
internal class ChangesVmProfile : Profile
{
public ChangesVmProfile()
{
CreateMap<Change, ChangeVm>();
}
}
public record ChangeVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>99</example>
public long Id { get; private init; }
/// <summary>
/// The reason for the change.
/// </summary>
/// <example>Adding EasyList because I did not see it on FilterLists.com yet.</example>
public string? Reason { get; private init; }
/// <summary>
/// The time at which the change was submitted.
/// </summary>
/// <example>2021-11-26T20:42:36.022483Z</example>
public DateTime SubmittedAt { get; private init; }
/// <summary>
/// The time at which the change was approved.
/// </summary>
/// <example>2021-11-28T22:43:34.022533Z</example>
public DateTime? ApprovedAt { get; private init; }
/// <summary>
/// The time at which the change was rejected.
/// </summary>
/// <example>null</example>
public DateTime? RejectedAt { get; private init; }
/// <summary>
/// The reason that the change was rejected.
/// </summary>
/// <example>null</example>
public string? RejectedReason { get; private init; }
/// <summary>
/// The snapshot of the entity before this change.
/// </summary>
/// <example>null</example>
public JsonDocument? Before { get; private init; }
/// <summary>
/// The snapshot of the entity after this change.
/// </summary>
/// <example>{"Name":"EasyList","ChatUrl":null,"HomeUrl":"https://easylist.to/","ForumUrl":"https://forums.lanik.us/viewforum.php?f=23","OnionUrl":null,"DonateUrl":null,"IssuesUrl":"https://github.com/easylist/easylist/issues","LicenseId":4,"PolicyUrl":null,"ViewUrlIds":[0],"Description":"EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.","EmailAddress":"easylist@protonmail.com","SubmissionUrl":null}</example>
public JsonDocument? After { get; private init; }
/// <summary>
/// The type of the entity being changed.
/// </summary>
/// <example>
/// <see cref="FilterLists.Directory.Domain.Aggregates.AggregateType.FilterList" />
/// </example>
public AggregateType AggregateType { get; private init; }
/// <summary>
/// The identifier of the FilterList being changed.
/// </summary>
/// <example>3001</example>
public long? FilterListId { get; private init; }
/// <summary>
/// The identifier of the Language being changed.
/// </summary>
/// <example>null</example>
public long? LanguageId { get; private init; }
/// <summary>
/// The identifier of the License being changed.
/// </summary>
/// <example>null</example>
public long? LicenseId { get; private init; }
/// <summary>
/// The identifier of the Maintainer being changed.
/// </summary>
/// <example>null</example>
public long? MaintainerId { get; private init; }
/// <summary>
/// The identifier of the Software being changed.
/// </summary>
/// <example>null</example>
public long? SoftwareId { get; private init; }
/// <summary>
/// The identifier of the Syntax being changed.
/// </summary>
/// <example>null</example>
public long? SyntaxId { get; private init; }
/// <summary>
/// The identifier of the Tag being changed.
/// </summary>
/// <example>null</example>
public long? TagId { get; private init; }
}
}

View file

@ -1,145 +0,0 @@
using System.Text.Json;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Domain.Aggregates;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetChanges
{
public record Query : IRequest<List<ChangeVm>>;
internal class Handler : IRequestHandler<Query, List<ChangeVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<ChangeVm>> Handle(Query request, CancellationToken cancellationToken)
{
return _context.Changes
.Where(c => c.ApprovedAt == null && c.RejectedAt == null)
.OrderBy(c => c.SubmittedAt)
.ProjectTo<ChangeVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class ChangesVmProfile : Profile
{
public ChangesVmProfile()
{
CreateMap<Change, ChangeVm>();
}
}
public record ChangeVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>99</example>
public long Id { get; private init; }
/// <summary>
/// The reason for the change.
/// </summary>
/// <example>Adding EasyList because I did not see it on FilterLists.com yet.</example>
public string? Reason { get; private init; }
/// <summary>
/// The time at which the change was submitted.
/// </summary>
/// <example>2021-11-26T20:42:36.022483Z</example>
public DateTime SubmittedAt { get; private init; }
/// <summary>
/// The time at which the change was approved.
/// </summary>
/// <example>2021-11-28T22:43:34.022533Z</example>
public DateTime? ApprovedAt { get; private init; }
/// <summary>
/// The time at which the change was rejected.
/// </summary>
/// <example>null</example>
public DateTime? RejectedAt { get; private init; }
/// <summary>
/// The reason that the change was rejected.
/// </summary>
/// <example>null</example>
public string? RejectedReason { get; private init; }
/// <summary>
/// The snapshot of the entity before this change.
/// </summary>
/// <example>null</example>
public JsonDocument? Before { get; private init; }
/// <summary>
/// The snapshot of the entity after this change.
/// </summary>
/// <example>{"Name":"EasyList","ChatUrl":null,"HomeUrl":"https://easylist.to/","ForumUrl":"https://forums.lanik.us/viewforum.php?f=23","OnionUrl":null,"DonateUrl":null,"IssuesUrl":"https://github.com/easylist/easylist/issues","LicenseId":4,"PolicyUrl":null,"ViewUrlIds":[0],"Description":"EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists.","EmailAddress":"easylist@protonmail.com","SubmissionUrl":null}</example>
public JsonDocument? After { get; private init; }
/// <summary>
/// The type of the entity being changed.
/// </summary>
/// <example>
/// <see cref="FilterLists.Directory.Domain.Aggregates.AggregateType.FilterList" />
/// </example>
public AggregateType AggregateType { get; private init; }
/// <summary>
/// The identifier of the FilterList being changed.
/// </summary>
/// <example>3001</example>
public long? FilterListId { get; private init; }
/// <summary>
/// The identifier of the Language being changed.
/// </summary>
/// <example>null</example>
public long? LanguageId { get; private init; }
/// <summary>
/// The identifier of the License being changed.
/// </summary>
/// <example>null</example>
public long? LicenseId { get; private init; }
/// <summary>
/// The identifier of the Maintainer being changed.
/// </summary>
/// <example>null</example>
public long? MaintainerId { get; private init; }
/// <summary>
/// The identifier of the Software being changed.
/// </summary>
/// <example>null</example>
public long? SoftwareId { get; private init; }
/// <summary>
/// The identifier of the Syntax being changed.
/// </summary>
/// <example>null</example>
public long? SyntaxId { get; private init; }
/// <summary>
/// The identifier of the Tag being changed.
/// </summary>
/// <example>null</example>
public long? TagId { get; private init; }
}
}

View file

@ -1,73 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetLanguages
{
public record Query : IRequest<List<LanguageVm>>;
internal class Handler : IRequestHandler<Query, List<LanguageVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<LanguageVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Languages
.Where(l => l.FilterListLanguages.Any())
.OrderBy(l => l.Iso6391)
.ProjectTo<LanguageVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class LanguageVmProfile : Profile
{
public LanguageVmProfile()
{
CreateMap<Language, LanguageVm>().ForMember(l => l.FilterListIds,
o => o.MapFrom(l =>
l.FilterListLanguages.OrderBy(fll => fll.FilterListId).Select(fll => fll.FilterListId)));
}
}
public record LanguageVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>37</example>
public long Id { get; private init; }
/// <summary>
/// The unique ISO 639-1 code.
/// </summary>
/// <example>en</example>
public string Iso6391 { get; private init; } = default!;
/// <summary>
/// The unique ISO name.
/// </summary>
/// <example>English</example>
public string Name { get; private init; } = default!;
/// <summary>
/// The identifiers of the FilterLists targeted by this Language.
/// </summary>
/// <example>[ 114, 141 ]</example>
public IEnumerable<long> FilterListIds { get; private init; } = new HashSet<long>();
}
}

View file

@ -1,89 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetLicenses
{
public record Query : IRequest<List<LicenseVm>>;
internal class Handler : IRequestHandler<Query, List<LicenseVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<LicenseVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Licenses
.OrderBy(l => l.Id)
.ProjectTo<LicenseVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class LicenseVmProfile : Profile
{
public LicenseVmProfile()
{
CreateMap<License, LicenseVm>().ForMember(l => l.FilterListIds,
o => o.MapFrom(l => l.FilterLists.OrderBy(fl => fl.Id).Select(fl => fl.Id)));
}
}
public record LicenseVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>5</example>
public long Id { get; private init; }
/// <summary>
/// The unique name.
/// </summary>
/// <example>All Rights Reserved</example>
public string Name { get; private init; } = default!;
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://en.wikipedia.org/wiki/All_rights_reserved</example>
public Uri? Url { get; private init; }
/// <summary>
/// If the License permits modification.
/// </summary>
/// <example>false</example>
public bool PermitsModification { get; private init; }
/// <summary>
/// If the License permits distribution.
/// </summary>
/// <example>false</example>
public bool PermitsDistribution { get; private init; }
/// <summary>
/// If the License permits commercial use.
/// </summary>
/// <example>false</example>
public bool PermitsCommercialUse { get; private init; }
/// <summary>
/// The identifiers of the FilterLists released under this License.
/// </summary>
/// <example>[ 6, 31 ]</example>
public IEnumerable<long> FilterListIds { get; private init; } = new HashSet<long>();
}
}

View file

@ -1,100 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Api.Contracts.Models;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using FluentValidation;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetListDetails
{
public record Query : IRequest<ListDetailsVm?>
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>301</example>
public long Id { get; init; }
}
internal class Validator : AbstractValidator<Query>
{
public Validator()
{
RuleFor(q => q.Id)
.GreaterThan(0);
}
}
internal class Handler : IRequestHandler<Query, ListDetailsVm?>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<ListDetailsVm?> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.FilterLists
.ProjectTo<ListDetailsVm>(_mapper.ConfigurationProvider)
.SingleOrDefaultAsync(fl => fl.Id == request.Id, cancellationToken);
}
}
internal class ListDetailsVmProfile : Profile
{
public ListDetailsVmProfile()
{
CreateMap<FilterList, ListDetailsVm>()
.ForMember(fl => fl.SyntaxIds,
o => o.MapFrom(fl =>
fl.FilterListSyntaxes.OrderBy(fls => fls.SyntaxId).Select(fls => fls.SyntaxId)))
.ForMember(fl => fl.LanguageIds,
o => o.MapFrom(fl =>
fl.FilterListLanguages.OrderBy(fll => fll.LanguageId).Select(fll => fll.LanguageId)))
.ForMember(fl => fl.TagIds,
o => o.MapFrom(fl =>
fl.FilterListTags.OrderBy(flt => flt.TagId).Select(flt => flt.TagId)))
.ForMember(fl => fl.ViewUrls,
o => o.MapFrom(fl =>
fl.ViewUrls.OrderBy(u => u.SegmentNumber).ThenBy(u => u.Primariness)))
.ForMember(fl => fl.MaintainerIds,
o => o.MapFrom(fl =>
fl.FilterListMaintainers.OrderBy(flm => flm.MaintainerId).Select(flm => flm.MaintainerId)))
.ForMember(fl => fl.UpstreamFilterListIds,
o => o.MapFrom(fl =>
fl.UpstreamFilterLists.OrderBy(f => f.UpstreamFilterListId)
.Select(f => f.UpstreamFilterListId)))
.ForMember(fl => fl.ForkFilterListIds,
o => o.MapFrom(fl =>
fl.ForkFilterLists.OrderBy(f => f.ForkFilterListId).Select(f => f.ForkFilterListId)))
.ForMember(fl => fl.IncludedInFilterListIds,
o => o.MapFrom(fl =>
fl.IncludedInFilterLists.OrderBy(m => m.IncludedInFilterListId)
.Select(m => m.IncludedInFilterListId)))
.ForMember(fl => fl.IncludesFilterListIds,
o => o.MapFrom(fl =>
fl.IncludesFilterLists.OrderBy(m => m.IncludesFilterListId)
.Select(m => m.IncludesFilterListId)))
.ForMember(fl => fl.DependencyFilterListIds,
o => o.MapFrom(fl =>
fl.DependencyFilterLists.OrderBy(d => d.DependencyFilterListId)
.Select(d => d.DependencyFilterListId)))
.ForMember(fl => fl.DependentFilterListIds,
o => o.MapFrom(fl =>
fl.DependentFilterLists.OrderBy(d => d.DependentFilterListId)
.Select(d => d.DependentFilterListId)));
CreateMap<FilterListViewUrl, ListDetailsVm.ViewUrlVm>();
}
}
}

View file

@ -1,60 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Api.Contracts.Models;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetLists
{
public record Query : IRequest<List<ListVm>>;
internal class Handler : IRequestHandler<Query, List<ListVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<ListVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.FilterLists
.OrderBy(fl => fl.Id)
.ProjectTo<ListVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class ListVmProfile : Profile
{
public ListVmProfile()
{
CreateMap<FilterList, ListVm>()
.ForMember(fl => fl.SyntaxIds,
o => o.MapFrom(fl =>
fl.FilterListSyntaxes.OrderBy(fls => fls.SyntaxId).Select(fls => fls.SyntaxId)))
.ForMember(fl => fl.LanguageIds,
o => o.MapFrom(fl =>
fl.FilterListLanguages.OrderBy(fll => fll.LanguageId).Select(fll => fll.LanguageId)))
.ForMember(fl => fl.TagIds,
o => o.MapFrom(fl =>
fl.FilterListTags.OrderBy(flt => flt.TagId).Select(flt => flt.TagId)))
.ForMember(fl => fl.PrimaryViewUrl,
o => o.MapFrom(fl =>
fl.ViewUrls.OrderBy(u => u.SegmentNumber).ThenBy(u => u.Primariness).Select(u => u.Url)
.FirstOrDefault()))
.ForMember(fl => fl.MaintainerIds,
o => o.MapFrom(fl =>
fl.FilterListMaintainers.OrderBy(flm => flm.MaintainerId).Select(flm => flm.MaintainerId)));
}
}
}

View file

@ -1,85 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetMaintainers
{
public record Query : IRequest<List<MaintainerVm>>;
internal class Handler : IRequestHandler<Query, List<MaintainerVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<MaintainerVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Maintainers
.OrderBy(m => m.Id)
.ProjectTo<MaintainerVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class MaintainerVmProfile : Profile
{
public MaintainerVmProfile()
{
CreateMap<Maintainer, MaintainerVm>()
.ForMember(m => m.FilterListIds,
o => o.MapFrom(m =>
m.FilterListMaintainers.OrderBy(flm => flm.FilterListId).Select(flm => flm.FilterListId)));
}
}
public record MaintainerVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>7</example>
public long Id { get; init; }
/// <summary>
/// The unique name.
/// </summary>
/// <example>The EasyList Authors</example>
public string Name { get; init; } = default!;
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://easylist.to/</example>
public Uri? Url { get; init; }
/// <summary>
/// The email address.
/// </summary>
/// <example>null</example>
public string? EmailAddress { get; init; }
/// <summary>
/// The Twitter handle.
/// </summary>
/// <example>null</example>
public string? TwitterHandle { get; init; }
/// <summary>
/// The identifiers of the FilterLists maintained by this Maintainer.
/// </summary>
/// <example>[ 11, 13, 301 ]</example>
public IEnumerable<long> FilterListIds { get; init; } = new HashSet<long>();
}
}

View file

@ -1,90 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetSoftware
{
public record Query : IRequest<List<SoftwareVm>>;
internal class Handler : IRequestHandler<Query, List<SoftwareVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<SoftwareVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Software
.OrderBy(s => s.Id)
.ProjectTo<SoftwareVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class SoftwareVmProfile : Profile
{
public SoftwareVmProfile()
{
CreateMap<Software, SoftwareVm>()
.ForMember(s => s.SyntaxIds,
o => o.MapFrom(s => s.SoftwareSyntaxes.OrderBy(ss => ss.SyntaxId).Select(ss => ss.SyntaxId)));
}
}
public record SoftwareVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>2</example>
public long Id { get; init; }
/// <summary>
/// The unique name.
/// </summary>
/// <example>Adblock Plus</example>
public string Name { get; init; } = default!;
/// <summary>
/// The description.
/// </summary>
/// <example>Adblock Plus is a free extension that allows you to customize your web experience. You can block annoying ads, disable tracking and lots more. Its available for all major desktop browsers and for your mobile devices.</example>
public string? Description { get; init; }
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://adblockplus.org/</example>
public Uri? HomeUrl { get; init; }
/// <summary>
/// The URL of the Software download.
/// </summary>
/// <example>https://adblockplus.org/</example>
public Uri? DownloadUrl { get; init; }
/// <summary>
/// If the Software supports the abp: URL scheme to click-to-subscribe to a FilterList.
/// </summary>
/// <example>true</example>
public bool SupportsAbpUrlScheme { get; init; }
/// <summary>
/// The identifiers of the Syntaxes that this Software supports.
/// </summary>
/// <example>[ 3, 28, 38, 48 ]</example>
public IEnumerable<long> SyntaxIds { get; init; } = new HashSet<long>();
}
}

View file

@ -1,88 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetSyntaxes
{
public record Query : IRequest<List<SyntaxVm>>;
internal class Handler : IRequestHandler<Query, List<SyntaxVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<SyntaxVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Syntaxes
.OrderBy(s => s.Id)
.ProjectTo<SyntaxVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class SyntaxVmProfile : Profile
{
public SyntaxVmProfile()
{
CreateMap<Syntax, SyntaxVm>()
.ForMember(s => s.FilterListIds,
o => o.MapFrom(s =>
s.FilterListSyntaxes.OrderBy(fls => fls.FilterListId).Select(sls => sls.FilterListId)))
.ForMember(s => s.SoftwareIds,
o => o.MapFrom(s =>
s.SoftwareSyntaxes.OrderBy(ss => ss.SoftwareId).Select(ss => ss.SoftwareId)));
}
}
public record SyntaxVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>3</example>
public long Id { get; init; }
/// <summary>
/// The unique name.
/// </summary>
/// <example>Adblock Plus</example>
public string Name { get; init; } = default!;
/// <summary>
/// The description.
/// </summary>
/// <example>null</example>
public string? Description { get; init; }
/// <summary>
/// The URL of the home page.
/// </summary>
/// <example>https://adblockplus.org/filters</example>
public Uri? Url { get; init; }
/// <summary>
/// The identifiers of the FilterLists implementing this Syntax.
/// </summary>
/// <example>[ 2, 6, 11 ]</example>
public IEnumerable<long> FilterListIds { get; init; } = new HashSet<long>();
/// <summary>
/// The identifiers of the Software that supports this Syntax.
/// </summary>
/// <example>[ 1, 2, 3 ]</example>
public IEnumerable<long> SoftwareIds { get; init; } = new HashSet<long>();
}
}

View file

@ -1,73 +0,0 @@
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace FilterLists.Directory.Application.Queries;
public static class GetTags
{
public record Query : IRequest<List<TagVm>>;
internal class Handler : IRequestHandler<Query, List<TagVm>>
{
private readonly IQueryContext _context;
private readonly IMapper _mapper;
public Handler(IQueryContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<TagVm>> Handle(
Query request,
CancellationToken cancellationToken)
{
return _context.Tags
.OrderBy(t => t.Id)
.ProjectTo<TagVm>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
internal class TagVmProfile : Profile
{
public TagVmProfile()
{
CreateMap<Tag, TagVm>()
.ForMember(t => t.FilterListIds,
o => o.MapFrom(t =>
t.FilterListTags.OrderBy(flt => flt.FilterListId).Select(flt => flt.FilterListId)));
}
}
public record TagVm
{
/// <summary>
/// The identifier.
/// </summary>
/// <example>2</example>
public long Id { get; init; }
/// <summary>
/// The unique name.
/// </summary>
/// <example>ads</example>
public string Name { get; init; } = default!;
/// <summary>
/// The description.
/// </summary>
/// <example>Blocks advertisements</example>
public string? Description { get; init; }
/// <summary>
/// The identifiers of the FilterLists to which this Tag is applied.
/// </summary>
/// <example>[ 1, 3, 6 ]</example>
public IEnumerable<long> FilterListIds { get; init; } = new HashSet<long>();
}
}

View file

@ -1,13 +0,0 @@
using FluentValidation;
namespace FilterLists.Directory.Application.Validators;
internal class EntityIdValidator : AbstractValidator<long?>
{
public EntityIdValidator()
{
RuleFor(id => id)
.GreaterThan(0)
.When(id => id is not null);
}
}

View file

@ -1,38 +0,0 @@
using FluentValidation;
namespace FilterLists.Directory.Application.Validators;
internal class UriValidator : AbstractValidator<Uri?>
{
public UriValidator(IHttpClientFactory httpClientFactory)
{
RuleFor(u => u)
.Cascade(CascadeMode.Stop)
.Must(u => Uri.TryCreate(u?.OriginalString, UriKind.Absolute, out _))
.WithMessage(u => $"Malformed absolute URL {u?.OriginalString}.")
.CustomAsync(
async (u, context, token) =>
{
var response = default(HttpResponseMessage?);
try
{
response = await httpClientFactory.CreateClient()
.GetAsync(u, HttpCompletionOption.ResponseHeadersRead, token);
}
catch (HttpRequestException ex)
{
context.AddFailure($"Error accessing URL {u?.OriginalString}. {ex.Message}");
}
catch (InvalidOperationException ex)
{
context.AddFailure($"Error accessing URL {u?.OriginalString}. {ex.Message}");
}
if (response?.IsSuccessStatusCode != true)
{
context.AddFailure($"Error accessing URL {u?.OriginalString}. {response?.StatusCode}");
}
})
.When(u => u is not null);
}
}

View file

@ -1,22 +0,0 @@
using FluentValidation;
using MediatR;
namespace FilterLists.Directory.Application.Validators;
internal class ValidatorPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidatorPipelineBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(
TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
await Task.WhenAll(_validators.Select(v => v.ValidateAndThrowAsync(request, cancellationToken)));
return await next();
}
}

View file

@ -1,12 +0,0 @@
namespace FilterLists.Directory.Domain.Aggregates;
public enum AggregateType
{
FilterList,
Language,
License,
Maintainer,
Software,
Syntax,
Tag
}

View file

@ -1,201 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.Languages;
using FilterLists.Directory.Domain.Aggregates.Licenses;
using FilterLists.Directory.Domain.Aggregates.Maintainers;
using FilterLists.Directory.Domain.Aggregates.Syntaxes;
using FilterLists.Directory.Domain.Aggregates.Tags;
using FilterLists.Directory.Domain.Changes;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.FilterLists;
public class FilterList : Entity, IRequireChangeApproval<FilterListChange>
{
private readonly ICollection<FilterListChange> _changes = new HashSet<FilterListChange>();
private readonly ICollection<FilterList> _dependencyFilterLists = new HashSet<FilterList>();
private readonly ICollection<FilterList> _dependentFilterLists = new HashSet<FilterList>();
private readonly ICollection<FilterList> _forkFilterLists = new HashSet<FilterList>();
private readonly ICollection<FilterList> _includedInFilterLists = new HashSet<FilterList>();
private readonly ICollection<FilterList> _includesFilterLists = new HashSet<FilterList>();
private readonly ICollection<Language> _languages = new HashSet<Language>();
private readonly ICollection<Maintainer> _maintainers = new HashSet<Maintainer>();
private readonly ICollection<Syntax> _syntaxes = new HashSet<Syntax>();
private readonly ICollection<Tag> _tags = new HashSet<Tag>();
private readonly ICollection<FilterList> _upstreamFilterLists = new HashSet<FilterList>();
private readonly ICollection<FilterListViewUrl> _viewUrls = new HashSet<FilterListViewUrl>();
protected FilterList() { }
public string Name { get; private init; } = default!;
public string? Description { get; private init; }
public virtual License License { get; private init; } = default!;
public virtual IEnumerable<Syntax> Syntaxes
{
get => _syntaxes;
private init => _syntaxes = new HashSet<Syntax>(value);
}
public virtual IEnumerable<Language> Languages
{
get => _languages;
private init => _languages = new HashSet<Language>(value);
}
public virtual IEnumerable<Tag> Tags
{
get => _tags;
private init => _tags = new HashSet<Tag>(value);
}
public virtual IEnumerable<FilterListViewUrl> ViewUrls
{
get => _viewUrls;
private init => _viewUrls = new HashSet<FilterListViewUrl>(value);
}
public Uri? HomeUrl { get; private init; }
public Uri? OnionUrl { get; private init; }
public Uri? PolicyUrl { get; private init; }
public Uri? SubmissionUrl { get; private init; }
public Uri? IssuesUrl { get; private init; }
public Uri? ForumUrl { get; private init; }
public Uri? ChatUrl { get; private init; }
public string? EmailAddress { get; private init; }
public Uri? DonateUrl { get; private init; }
public virtual IEnumerable<Maintainer> Maintainers
{
get => _maintainers;
private init => _maintainers = new HashSet<Maintainer>(value);
}
public virtual IEnumerable<FilterList> UpstreamFilterLists
{
get => _upstreamFilterLists;
private init => _upstreamFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterList> ForkFilterLists
{
get => _forkFilterLists;
private init => _forkFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterList> IncludedInFilterLists
{
get => _includedInFilterLists;
private init => _includedInFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterList> IncludesFilterLists
{
get => _includesFilterLists;
private init => _includesFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterList> DependencyFilterLists
{
get => _dependencyFilterLists;
private init => _dependencyFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterList> DependentFilterLists
{
get => _dependentFilterLists;
private init => _dependentFilterLists = new HashSet<FilterList>(value);
}
public virtual IEnumerable<FilterListChange> Changes => _changes;
public bool IsApproved { get; private init; }
public static FilterList CreatePendingApproval(
string name,
string? description,
License license,
IEnumerable<Syntax> syntaxes,
IEnumerable<Language> languages,
IEnumerable<Tag> tags,
IEnumerable<(short SegmentNumber, short Primariness, Uri Url)> viewUrls,
Uri? homeUrl,
Uri? onionUrl,
Uri? policyUrl,
Uri? submissionUrl,
Uri? issuesUrl,
Uri? forumUrl,
Uri? chatUrl,
string? emailAddress,
Uri? donateUrl,
IEnumerable<Maintainer> maintainers,
IEnumerable<FilterList> upstreamFilterLists,
IEnumerable<FilterList> forkFilterLists,
IEnumerable<FilterList> includedInFilterLists,
IEnumerable<FilterList> includesFilterLists,
IEnumerable<FilterList> dependencyFilterLists,
IEnumerable<FilterList> dependentFilterLists,
string? createReason)
{
var urls = viewUrls.DistinctBy(u => new { u.SegmentNumber, u.Primariness, u.Url })
.Select(u => FilterListViewUrl.Create(u.SegmentNumber, u.Primariness, u.Url))
.ToList();
if (urls.Count == 0)
{
throw new ArgumentException("At lest one view URL is required.", nameof(viewUrls));
}
if (urls.GroupBy(u => new { u.SegmentNumber, u.Primariness }).Any(g => g.Count() > 1))
{
throw new ArgumentException("The segment number and primariness pair must be unique for each view URL.", nameof(viewUrls));
}
var upstreamFilterListSet = new HashSet<FilterList>(upstreamFilterLists);
var forkFilterListSet = new HashSet<FilterList>(forkFilterLists);
if (upstreamFilterListSet.Intersect(forkFilterListSet).Any())
{
throw new ArgumentException("A FilterList cannot be both an Upstream and a Fork of the same FilterList.");
}
var includedInFilterListSet = new HashSet<FilterList>(includedInFilterLists);
var includesFilterListSet = new HashSet<FilterList>(includesFilterLists);
if (includedInFilterListSet.Intersect(includesFilterListSet).Any())
{
throw new ArgumentException("A FilterList cannot be both included in and including of the same FilterList.");
}
var dependencyFilterListSet = new HashSet<FilterList>(dependencyFilterLists);
var dependentFilterListSet = new HashSet<FilterList>(dependentFilterLists);
if (dependencyFilterListSet.Intersect(dependentFilterListSet).Any())
{
throw new ArgumentException("A FilterList cannot be both a dependency of and dependent upon the same FilterList.");
}
var list = new FilterList
{
Name = name,
Description = description,
License = license,
Syntaxes = syntaxes,
Languages = languages,
Tags = tags,
ViewUrls = urls,
HomeUrl = homeUrl,
OnionUrl = onionUrl,
PolicyUrl = policyUrl,
SubmissionUrl = submissionUrl,
IssuesUrl = issuesUrl,
ForumUrl = forumUrl,
ChatUrl = chatUrl,
EmailAddress = emailAddress,
DonateUrl = donateUrl,
Maintainers = maintainers,
UpstreamFilterLists = upstreamFilterListSet,
ForkFilterLists = forkFilterListSet,
IncludedInFilterLists = includedInFilterListSet,
IncludesFilterLists = includesFilterListSet,
DependencyFilterLists = dependencyFilterListSet,
DependentFilterLists = dependentFilterListSet,
IsApproved = false
};
list._changes.Add(FilterListChange.Create(list, createReason));
return list;
}
}

View file

@ -1,31 +0,0 @@
using FilterLists.Directory.Domain.Changes;
namespace FilterLists.Directory.Domain.Aggregates.FilterLists;
public class FilterListChange : Change, IChangeAggregate<FilterListValueObject>
{
protected FilterListChange() { }
public FilterListValueObject? Before { get; private init; }
public FilterListValueObject? After { get; private init; }
public static FilterListChange Create(FilterList filterList, string? reason)
{
return new FilterListChange { After = FilterListValueObject.FromFilterList(filterList), Reason = reason };
}
public static FilterListChange Update(FilterList before, FilterList after, string? reason)
{
return new FilterListChange
{
Before = FilterListValueObject.FromFilterList(before),
After = FilterListValueObject.FromFilterList(after),
Reason = reason
};
}
public static FilterListChange Delete(FilterList filterList, string? reason)
{
return new FilterListChange { Before = FilterListValueObject.FromFilterList(filterList), Reason = reason };
}
}

View file

@ -1,130 +0,0 @@
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.FilterLists;
public class FilterListValueObject : ValueObject
{
public string Name { get; private init; } = default!;
public string? Description { get; private init; }
public long LicenseId { get; private init; }
public IEnumerable<long> SyntaxIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> LanguageIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> TagIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> ViewUrlIds { get; private init; } = new HashSet<long>();
public Uri? HomeUrl { get; private init; }
public Uri? OnionUrl { get; private init; }
public Uri? PolicyUrl { get; private init; }
public Uri? SubmissionUrl { get; private init; }
public Uri? IssuesUrl { get; private init; }
public Uri? ForumUrl { get; private init; }
public Uri? ChatUrl { get; private init; }
public string? EmailAddress { get; private init; }
public Uri? DonateUrl { get; private init; }
public IEnumerable<long> MaintainerIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> UpstreamFilterListIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> ForkFilterListIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> IncludedInFilterListIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> IncludesFilterListIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> DependencyFilterListIds { get; private init; } = new HashSet<long>();
public IEnumerable<long> DependentFilterListIds { get; private init; } = new HashSet<long>();
public static FilterListValueObject FromFilterList(FilterList filterList)
{
return new FilterListValueObject
{
Name = filterList.Name,
Description = filterList.Description,
LicenseId = filterList.License.Id,
SyntaxIds = filterList.Syntaxes.Select(s => s.Id),
LanguageIds = filterList.Languages.Select(l => l.Id),
TagIds = filterList.Tags.Select(t => t.Id),
ViewUrlIds = filterList.ViewUrls.Select(u => u.Id),
HomeUrl = filterList.HomeUrl,
OnionUrl = filterList.OnionUrl,
PolicyUrl = filterList.PolicyUrl,
SubmissionUrl = filterList.SubmissionUrl,
IssuesUrl = filterList.IssuesUrl,
ForumUrl = filterList.ForumUrl,
ChatUrl = filterList.ChatUrl,
EmailAddress = filterList.EmailAddress,
DonateUrl = filterList.DonateUrl,
MaintainerIds = filterList.Maintainers.Select(m => m.Id),
UpstreamFilterListIds = filterList.UpstreamFilterLists.Select(f => f.Id),
ForkFilterListIds = filterList.ForkFilterLists.Select(f => f.Id),
IncludedInFilterListIds = filterList.IncludedInFilterLists.Select(f => f.Id),
IncludesFilterListIds = filterList.IncludesFilterLists.Select(f => f.Id),
DependencyFilterListIds = filterList.DependencyFilterLists.Select(f => f.Id),
DependentFilterListIds = filterList.DependentFilterLists.Select(f => f.Id)
};
}
protected override IEnumerable<object?> GetEqualityComponents()
{
yield return Name;
yield return Description;
yield return LicenseId;
foreach (var id in SyntaxIds)
{
yield return id;
}
foreach (var id in LanguageIds)
{
yield return id;
}
foreach (var id in TagIds)
{
yield return id;
}
foreach (var id in ViewUrlIds)
{
yield return id;
}
yield return HomeUrl;
yield return OnionUrl;
yield return PolicyUrl;
yield return SubmissionUrl;
yield return IssuesUrl;
yield return ForumUrl;
yield return ChatUrl;
yield return EmailAddress;
yield return DonateUrl;
foreach (var id in MaintainerIds)
{
yield return id;
}
foreach (var id in UpstreamFilterListIds)
{
yield return id;
}
foreach (var id in ForkFilterListIds)
{
yield return id;
}
foreach (var id in IncludedInFilterListIds)
{
yield return id;
}
foreach (var id in IncludesFilterListIds)
{
yield return id;
}
foreach (var id in DependencyFilterListIds)
{
yield return id;
}
foreach (var id in DependentFilterListIds)
{
yield return id;
}
}
}

View file

@ -1,31 +0,0 @@
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.FilterLists;
public class FilterListViewUrl : Entity
{
protected FilterListViewUrl() { }
public short SegmentNumber { get; private init; }
public short Primariness { get; private init; }
public Uri Url { get; private init; } = default!;
internal static FilterListViewUrl Create(short segmentNumber, short primariness, Uri url)
{
if (segmentNumber < 1)
{
throw new ArgumentException(
"The segment number must be greater than or equal to 1.",
nameof(segmentNumber));
}
if (primariness < 1)
{
throw new ArgumentException(
"The primariness must be greater than or equal to 1.",
nameof(segmentNumber));
}
return new FilterListViewUrl { SegmentNumber = segmentNumber, Primariness = primariness, Url = url };
}
}

View file

@ -1,13 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Languages;
public class Language : Entity
{
protected Language() { }
public string Iso6391 { get; private init; } = default!;
public string Name { get; private init; } = default!;
public virtual IEnumerable<FilterList> FilterLists { get; private init; } = new HashSet<FilterList>();
}

View file

@ -1,16 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Licenses;
public class License : Entity
{
protected License() { }
public string Name { get; private init; } = default!;
public Uri? Url { get; private init; }
public bool PermitsModification { get; private init; }
public bool PermitsDistribution { get; private init; }
public bool PermitsCommercialUse { get; private init; }
public virtual IEnumerable<FilterList> FilterLists { get; private init; } = new HashSet<FilterList>();
}

View file

@ -1,9 +0,0 @@
namespace FilterLists.Directory.Domain.Aggregates.Licenses;
public static class LicenseExtensions
{
public static IQueryable<License> WhereIsDefaultForFilterList(this IQueryable<License> licenses)
{
return licenses.Where(l => l.Name == "All Rights Reserved");
}
}

View file

@ -1,15 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Maintainers;
public class Maintainer : Entity
{
protected Maintainer() { }
public string Name { get; private init; } = default!;
public Uri? Url { get; private init; }
public string? EmailAddress { get; private init; }
public string? TwitterHandle { get; private init; }
public virtual IEnumerable<FilterList> FilterLists { get; private init; } = new HashSet<FilterList>();
}

View file

@ -1,16 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.Syntaxes;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Software;
public class Software : Entity
{
protected Software() { }
public string Name { get; private init; } = default!;
public string? Description { get; private init; }
public Uri? HomeUrl { get; private init; }
public Uri? DownloadUrl { get; private init; }
public bool SupportsAbpUrlScheme { get; private init; }
public virtual IEnumerable<Syntax> Syntaxes { get; private init; } = new HashSet<Syntax>();
}

View file

@ -1,15 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Syntaxes;
public class Syntax : Entity
{
protected Syntax() { }
public string Name { get; private init; } = default!;
public string? Description { get; private init; }
public Uri? Url { get; private init; }
public virtual IEnumerable<FilterList> FilterLists { get; private init; } = new HashSet<FilterList>();
public virtual IEnumerable<Software.Software> Software { get; private init; } = new HashSet<Software.Software>();
}

View file

@ -1,13 +0,0 @@
using FilterLists.Directory.Domain.Aggregates.FilterLists;
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Aggregates.Tags;
public class Tag : Entity
{
protected Tag() { }
public string Name { get; private init; } = default!;
public string? Description { get; private init; }
public virtual IEnumerable<FilterList> FilterLists { get; private init; } = new HashSet<FilterList>();
}

View file

@ -1,23 +0,0 @@
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Changes;
public abstract class Change : Entity
{
public string? Reason { get; protected init; }
public DateTime SubmittedAt { get; protected init; } = DateTime.UtcNow;
public DateTime? ApprovedAt { get; private set; }
public DateTime? RejectedAt { get; private set; }
public string? RejectedReason { get; private set; }
public void Approve()
{
ApprovedAt = DateTime.UtcNow;
}
public void Reject(string? reason)
{
RejectedAt = DateTime.UtcNow;
RejectedReason = reason;
}
}

View file

@ -1,9 +0,0 @@
using FilterLists.SharedKernel.Domain.SeedWork;
namespace FilterLists.Directory.Domain.Changes;
public interface IChangeAggregate<out TAggregateValueObject> where TAggregateValueObject : ValueObject
{
TAggregateValueObject? Before { get; }
TAggregateValueObject? After { get; }
}

View file

@ -1,10 +0,0 @@
namespace FilterLists.Directory.Domain.Changes;
public interface IRequireChangeApproval<out TChange> where TChange : Change
{
public IEnumerable<TChange> Changes { get; }
public IEnumerable<TChange> PendingChanges => Changes.Where(c => c.ApprovedAt == null && c.RejectedAt == null);
public IEnumerable<TChange> ApprovedChanges => Changes.Where(c => c.ApprovedAt != null);
public IEnumerable<TChange> RejectedChanges => Changes.Where(c => c.RejectedAt != null);
public bool IsApproved { get; }
}

View file

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\SharedKernel\FilterLists.SharedKernel.Domain.SeedWork\FilterLists.SharedKernel.Domain.SeedWork.csproj" />
</ItemGroup>
</Project>

View file

@ -1,35 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<RuntimeIdentifiers>linux-musl-x64;win10-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FilterLists.Directory.Infrastructure.Migrations\FilterLists.Directory.Infrastructure.Migrations.csproj" />
<ProjectReference Include="..\FilterLists.Directory.Infrastructure\FilterLists.Directory.Infrastructure.csproj" />
</ItemGroup>
</Project>

View file

@ -1,26 +0,0 @@
using FilterLists.Directory.Infrastructure.Migrations.Migrations;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace FilterLists.Directory.Infrastructure.Migrations.Tests;
public class SeedQueryDbContextTest
{
[Fact]
public async Task Migrate_DoesNotThrowException()
{
var exception = await Record.ExceptionAsync(async () =>
{
var connString = Environment.GetEnvironmentVariable("ConnectionStrings__DirectoryConnection") ??
throw new Exception();
var options = new DbContextOptionsBuilder<QueryDbContext>()
.UseNpgsql(connString, m => m.MigrationsAssembly(typeof(InitialCreate).Assembly.GetName().Name))
.EnableSensitiveDataLogging()
.Options;
await using var context = new QueryDbContext(options);
await context.Database.MigrateAsync();
});
Assert.Null(exception);
}
}

View file

@ -1,4 +0,0 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
[*.cs]
dotnet_diagnostic.CS8625.severity = silent

View file

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Authors>Collin M. Barrett</Authors>
<Company>FilterLists</Company>
<Product>FilterLists Directory</Product>
<Description>The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.</Description>
<Copyright>Copyright (c) 2021 Collin M. Barrett</Copyright>
<RepositoryUrl>https://github.com/collinbarrett/FilterLists</RepositoryUrl>
<PackageProjectUrl>https://filterlists.com</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FilterLists.Directory.Infrastructure\FilterLists.Directory.Infrastructure.csproj" />
</ItemGroup>
</Project>

View file

@ -1,942 +0,0 @@
// <auto-generated />
using System;
using System.Text.Json;
using FilterLists.Directory.Domain.Aggregates;
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
[DbContext(typeof(QueryDbContext))]
[Migration("20230507190214_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "aggregate_type", new[] { "filter_list", "language", "license", "maintainer", "software", "syntax", "tag" });
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.HasSequence("EntityFrameworkHiLoSequence-FilterListViewUrl")
.StartsAt(3000L)
.IncrementsBy(3);
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Change", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<JsonDocument>("After")
.HasColumnType("jsonb")
.HasColumnName("after");
b.Property<AggregateType>("AggregateType")
.HasColumnType("aggregate_type")
.HasColumnName("aggregate_type");
b.Property<DateTime?>("ApprovedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("approved_at");
b.Property<JsonDocument>("Before")
.HasColumnType("jsonb")
.HasColumnName("before");
b.Property<long?>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b.Property<long?>("LanguageId")
.HasColumnType("bigint")
.HasColumnName("language_id");
b.Property<long?>("LicenseId")
.HasColumnType("bigint")
.HasColumnName("license_id");
b.Property<long?>("MaintainerId")
.HasColumnType("bigint")
.HasColumnName("maintainer_id");
b.Property<string>("Reason")
.HasColumnType("text")
.HasColumnName("reason");
b.Property<DateTime?>("RejectedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("rejected_at");
b.Property<string>("RejectedReason")
.HasColumnType("text")
.HasColumnName("rejected_reason");
b.Property<long?>("SoftwareId")
.HasColumnType("bigint")
.HasColumnName("software_id");
b.Property<DateTime>("SubmittedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("submitted_at")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<long?>("SyntaxId")
.HasColumnType("bigint")
.HasColumnName("syntax_id");
b.Property<long?>("TagId")
.HasColumnType("bigint")
.HasColumnName("tag_id");
b.HasKey("Id")
.HasName("pk_changes");
b.HasIndex("FilterListId")
.HasDatabaseName("ix_changes_filter_list_id");
b.HasIndex("LanguageId")
.HasDatabaseName("ix_changes_language_id");
b.HasIndex("LicenseId")
.HasDatabaseName("ix_changes_license_id");
b.HasIndex("MaintainerId")
.HasDatabaseName("ix_changes_maintainer_id");
b.HasIndex("SoftwareId")
.HasDatabaseName("ix_changes_software_id");
b.HasIndex("SyntaxId")
.HasDatabaseName("ix_changes_syntax_id");
b.HasIndex("TagId")
.HasDatabaseName("ix_changes_tag_id");
b.ToTable("changes", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Dependent", b =>
{
b.Property<long>("DependencyFilterListId")
.HasColumnType("bigint")
.HasColumnName("dependency_filter_list_id");
b.Property<long>("DependentFilterListId")
.HasColumnType("bigint")
.HasColumnName("dependent_filter_list_id");
b.HasKey("DependencyFilterListId", "DependentFilterListId")
.HasName("pk_dependents");
b.HasIndex("DependentFilterListId")
.HasDatabaseName("ix_dependents_dependent_filter_list_id");
b.ToTable("dependents", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("ChatUrl")
.HasColumnType("text")
.HasColumnName("chat_url");
b.Property<string>("Description")
.HasColumnType("text")
.HasColumnName("description");
b.Property<string>("DonateUrl")
.HasColumnType("text")
.HasColumnName("donate_url");
b.Property<string>("EmailAddress")
.HasColumnType("text")
.HasColumnName("email_address");
b.Property<string>("ForumUrl")
.HasColumnType("text")
.HasColumnName("forum_url");
b.Property<string>("HomeUrl")
.HasColumnType("text")
.HasColumnName("home_url");
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("IssuesUrl")
.HasColumnType("text")
.HasColumnName("issues_url");
b.Property<long>("LicenseId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasDefaultValue(5L)
.HasColumnName("license_id");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<string>("OnionUrl")
.HasColumnType("text")
.HasColumnName("onion_url");
b.Property<string>("PolicyUrl")
.HasColumnType("text")
.HasColumnName("policy_url");
b.Property<string>("SubmissionUrl")
.HasColumnType("text")
.HasColumnName("submission_url");
b.HasKey("Id")
.HasName("pk_filter_lists");
b.HasIndex("LicenseId")
.HasDatabaseName("ix_filter_lists_license_id");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_filter_lists_name");
b.ToTable("filter_lists", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListLanguage", b =>
{
b.Property<long>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b.Property<long>("LanguageId")
.HasColumnType("bigint")
.HasColumnName("language_id");
b.HasKey("FilterListId", "LanguageId")
.HasName("pk_filter_list_languages");
b.HasIndex("LanguageId")
.HasDatabaseName("ix_filter_list_languages_language_id");
b.ToTable("filter_list_languages", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListMaintainer", b =>
{
b.Property<long>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b.Property<long>("MaintainerId")
.HasColumnType("bigint")
.HasColumnName("maintainer_id");
b.HasKey("FilterListId", "MaintainerId")
.HasName("pk_filter_list_maintainers");
b.HasIndex("MaintainerId")
.HasDatabaseName("ix_filter_list_maintainers_maintainer_id");
b.ToTable("filter_list_maintainers", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListSyntax", b =>
{
b.Property<long>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b.Property<long>("SyntaxId")
.HasColumnType("bigint")
.HasColumnName("syntax_id");
b.HasKey("FilterListId", "SyntaxId")
.HasName("pk_filter_list_syntaxes");
b.HasIndex("SyntaxId")
.HasDatabaseName("ix_filter_list_syntaxes_syntax_id");
b.ToTable("filter_list_syntaxes", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListTag", b =>
{
b.Property<long>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b.Property<long>("TagId")
.HasColumnType("bigint")
.HasColumnName("tag_id");
b.HasKey("FilterListId", "TagId")
.HasName("pk_filter_list_tags");
b.HasIndex("TagId")
.HasDatabaseName("ix_filter_list_tags_tag_id");
b.ToTable("filter_list_tags", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Fork", b =>
{
b.Property<long>("UpstreamFilterListId")
.HasColumnType("bigint")
.HasColumnName("upstream_filter_list_id");
b.Property<long>("ForkFilterListId")
.HasColumnType("bigint")
.HasColumnName("fork_filter_list_id");
b.HasKey("UpstreamFilterListId", "ForkFilterListId")
.HasName("pk_forks");
b.HasIndex("ForkFilterListId")
.HasDatabaseName("ix_forks_fork_filter_list_id");
b.ToTable("forks", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Language", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Iso6391")
.IsRequired()
.HasMaxLength(2)
.HasColumnType("character(2)")
.HasColumnName("iso6391")
.IsFixedLength();
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.HasKey("Id")
.HasName("pk_languages");
b.HasIndex("Iso6391")
.IsUnique()
.HasDatabaseName("ix_languages_iso6391");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_languages_name");
b.ToTable("languages", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.License", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<bool>("PermitsCommercialUse")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasColumnName("permits_commercial_use");
b.Property<bool>("PermitsDistribution")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasColumnName("permits_distribution");
b.Property<bool>("PermitsModification")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasColumnName("permits_modification");
b.Property<string>("Url")
.HasColumnType("text")
.HasColumnName("url");
b.HasKey("Id")
.HasName("pk_licenses");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_licenses_name");
b.ToTable("licenses", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Maintainer", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("EmailAddress")
.HasColumnType("text")
.HasColumnName("email_address");
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<string>("TwitterHandle")
.HasColumnType("text")
.HasColumnName("twitter_handle");
b.Property<string>("Url")
.HasColumnType("text")
.HasColumnName("url");
b.HasKey("Id")
.HasName("pk_maintainers");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_maintainers_name");
b.ToTable("maintainers", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Merge", b =>
{
b.Property<long>("IncludedInFilterListId")
.HasColumnType("bigint")
.HasColumnName("included_in_filter_list_id");
b.Property<long>("IncludesFilterListId")
.HasColumnType("bigint")
.HasColumnName("includes_filter_list_id");
b.HasKey("IncludedInFilterListId", "IncludesFilterListId")
.HasName("pk_merges");
b.HasIndex("IncludesFilterListId")
.HasDatabaseName("ix_merges_includes_filter_list_id");
b.ToTable("merges", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Software", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("Description")
.HasColumnType("text")
.HasColumnName("description");
b.Property<string>("DownloadUrl")
.HasColumnType("text")
.HasColumnName("download_url");
b.Property<string>("HomeUrl")
.HasColumnType("text")
.HasColumnName("home_url");
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<bool>("SupportsAbpUrlScheme")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasColumnName("supports_abp_url_scheme");
b.HasKey("Id")
.HasName("pk_software");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_software_name");
b.ToTable("software", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.SoftwareSyntax", b =>
{
b.Property<long>("SoftwareId")
.HasColumnType("bigint")
.HasColumnName("software_id");
b.Property<long>("SyntaxId")
.HasColumnType("bigint")
.HasColumnName("syntax_id");
b.HasKey("SoftwareId", "SyntaxId")
.HasName("pk_software_syntaxes");
b.HasIndex("SyntaxId")
.HasDatabaseName("ix_software_syntaxes_syntax_id");
b.ToTable("software_syntaxes", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Syntax", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("Description")
.HasColumnType("text")
.HasColumnName("description");
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<string>("Url")
.HasColumnType("text")
.HasColumnName("url");
b.HasKey("Id")
.HasName("pk_syntaxes");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_syntaxes_name");
b.ToTable("syntaxes", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Tag", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("Description")
.HasColumnType("text")
.HasColumnName("description");
b.Property<bool>("IsApproved")
.HasColumnType("boolean")
.HasColumnName("is_approved");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.HasKey("Id")
.HasName("pk_tags");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_tags_name");
b.ToTable("tags", (string)null);
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Change", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", null)
.WithMany("Changes")
.HasForeignKey("FilterListId")
.HasConstraintName("fk_changes_filter_lists_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Language", null)
.WithMany("Changes")
.HasForeignKey("LanguageId")
.HasConstraintName("fk_changes_languages_language_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.License", null)
.WithMany("Changes")
.HasForeignKey("LicenseId")
.HasConstraintName("fk_changes_licenses_license_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Maintainer", null)
.WithMany("Changes")
.HasForeignKey("MaintainerId")
.HasConstraintName("fk_changes_maintainers_maintainer_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Software", null)
.WithMany("Changes")
.HasForeignKey("SoftwareId")
.HasConstraintName("fk_changes_software_software_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Syntax", null)
.WithMany("Changes")
.HasForeignKey("SyntaxId")
.HasConstraintName("fk_changes_syntaxes_syntax_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Tag", null)
.WithMany("Changes")
.HasForeignKey("TagId")
.HasConstraintName("fk_changes_tags_tag_id");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Dependent", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "DependencyFilterList")
.WithMany("DependentFilterLists")
.HasForeignKey("DependencyFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_dependents_filter_lists_dependency_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "DependentFilterList")
.WithMany("DependencyFilterLists")
.HasForeignKey("DependentFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_dependents_filter_lists_dependent_filter_list_id");
b.Navigation("DependencyFilterList");
b.Navigation("DependentFilterList");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.License", "License")
.WithMany("FilterLists")
.HasForeignKey("LicenseId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired()
.HasConstraintName("fk_filter_lists_licenses_license_id");
b.OwnsMany("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListViewUrl", "ViewUrls", b1 =>
{
b1.Property<long>("FilterListId")
.HasColumnType("bigint")
.HasColumnName("filter_list_id");
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseHiLo(b1.Property<long>("Id"), "EntityFrameworkHiLoSequence-FilterListViewUrl");
b1.Property<short>("Primariness")
.ValueGeneratedOnAdd()
.HasColumnType("smallint")
.HasDefaultValue((short)1)
.HasColumnName("primariness");
b1.Property<short>("SegmentNumber")
.ValueGeneratedOnAdd()
.HasColumnType("smallint")
.HasDefaultValue((short)1)
.HasColumnName("segment_number");
b1.Property<string>("Url")
.IsRequired()
.HasColumnType("text")
.HasColumnName("url");
b1.HasKey("FilterListId", "Id")
.HasName("pk_filter_list_view_urls");
b1.HasIndex("FilterListId", "SegmentNumber", "Primariness")
.IsUnique()
.HasDatabaseName("ix_filter_list_view_urls_filter_list_id_segment_number_primari");
b1.ToTable("filter_list_view_urls", (string)null);
b1.WithOwner("FilterList")
.HasForeignKey("FilterListId")
.HasConstraintName("fk_filter_list_view_urls_filter_lists_filter_list_id");
b1.Navigation("FilterList");
});
b.Navigation("License");
b.Navigation("ViewUrls");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListLanguage", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "FilterList")
.WithMany("FilterListLanguages")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_languages_filter_lists_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Language", "Language")
.WithMany("FilterListLanguages")
.HasForeignKey("LanguageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_languages_languages_language_id");
b.Navigation("FilterList");
b.Navigation("Language");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListMaintainer", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "FilterList")
.WithMany("FilterListMaintainers")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_maintainers_filter_lists_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Maintainer", "Maintainer")
.WithMany("FilterListMaintainers")
.HasForeignKey("MaintainerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_maintainers_maintainers_maintainer_id");
b.Navigation("FilterList");
b.Navigation("Maintainer");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListSyntax", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "FilterList")
.WithMany("FilterListSyntaxes")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_syntaxes_filter_lists_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Syntax", "Syntax")
.WithMany("FilterListSyntaxes")
.HasForeignKey("SyntaxId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_syntaxes_syntaxes_syntax_id");
b.Navigation("FilterList");
b.Navigation("Syntax");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterListTag", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "FilterList")
.WithMany("FilterListTags")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_tags_filter_lists_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Tag", "Tag")
.WithMany("FilterListTags")
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_filter_list_tags_tags_tag_id");
b.Navigation("FilterList");
b.Navigation("Tag");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Fork", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "ForkFilterList")
.WithMany("UpstreamFilterLists")
.HasForeignKey("ForkFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_forks_filter_lists_fork_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "UpstreamFilterList")
.WithMany("ForkFilterLists")
.HasForeignKey("UpstreamFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_forks_filter_lists_upstream_filter_list_id");
b.Navigation("ForkFilterList");
b.Navigation("UpstreamFilterList");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Merge", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "IncludedInFilterList")
.WithMany("IncludesFilterLists")
.HasForeignKey("IncludedInFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_merges_filter_lists_included_in_filter_list_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", "IncludesFilterList")
.WithMany("IncludedInFilterLists")
.HasForeignKey("IncludesFilterListId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_merges_filter_lists_includes_filter_list_id");
b.Navigation("IncludedInFilterList");
b.Navigation("IncludesFilterList");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.SoftwareSyntax", b =>
{
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Software", "Software")
.WithMany("SoftwareSyntaxes")
.HasForeignKey("SoftwareId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_software_syntaxes_software_software_id");
b.HasOne("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Syntax", "Syntax")
.WithMany("SoftwareSyntaxes")
.HasForeignKey("SyntaxId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_software_syntaxes_syntaxes_syntax_id");
b.Navigation("Software");
b.Navigation("Syntax");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.FilterList", b =>
{
b.Navigation("Changes");
b.Navigation("DependencyFilterLists");
b.Navigation("DependentFilterLists");
b.Navigation("FilterListLanguages");
b.Navigation("FilterListMaintainers");
b.Navigation("FilterListSyntaxes");
b.Navigation("FilterListTags");
b.Navigation("ForkFilterLists");
b.Navigation("IncludedInFilterLists");
b.Navigation("IncludesFilterLists");
b.Navigation("UpstreamFilterLists");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Language", b =>
{
b.Navigation("Changes");
b.Navigation("FilterListLanguages");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.License", b =>
{
b.Navigation("Changes");
b.Navigation("FilterLists");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Maintainer", b =>
{
b.Navigation("Changes");
b.Navigation("FilterListMaintainers");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Software", b =>
{
b.Navigation("Changes");
b.Navigation("SoftwareSyntaxes");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Syntax", b =>
{
b.Navigation("Changes");
b.Navigation("FilterListSyntaxes");
b.Navigation("SoftwareSyntaxes");
});
modelBuilder.Entity("FilterLists.Directory.Infrastructure.Persistence.Queries.Entities.Tag", b =>
{
b.Navigation("Changes");
b.Navigation("FilterListTags");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,623 +0,0 @@
using System;
using System.Text.Json;
using FilterLists.Directory.Domain.Aggregates;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("Npgsql:Enum:aggregate_type", "filter_list,language,license,maintainer,software,syntax,tag");
migrationBuilder.CreateSequence(
name: "EntityFrameworkHiLoSequence-FilterListViewUrl",
startValue: 3000L,
incrementBy: 3);
migrationBuilder.CreateTable(
name: "languages",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
iso6391 = table.Column<string>(type: "character(2)", fixedLength: true, maxLength: 2, nullable: false),
name = table.Column<string>(type: "text", nullable: false),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_languages", x => x.id);
});
migrationBuilder.CreateTable(
name: "licenses",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
url = table.Column<string>(type: "text", nullable: true),
permits_modification = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
permits_distribution = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
permits_commercial_use = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_licenses", x => x.id);
});
migrationBuilder.CreateTable(
name: "maintainers",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
url = table.Column<string>(type: "text", nullable: true),
email_address = table.Column<string>(type: "text", nullable: true),
twitter_handle = table.Column<string>(type: "text", nullable: true),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_maintainers", x => x.id);
});
migrationBuilder.CreateTable(
name: "software",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
description = table.Column<string>(type: "text", nullable: true),
home_url = table.Column<string>(type: "text", nullable: true),
download_url = table.Column<string>(type: "text", nullable: true),
supports_abp_url_scheme = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_software", x => x.id);
});
migrationBuilder.CreateTable(
name: "syntaxes",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
description = table.Column<string>(type: "text", nullable: true),
url = table.Column<string>(type: "text", nullable: true),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_syntaxes", x => x.id);
});
migrationBuilder.CreateTable(
name: "tags",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
description = table.Column<string>(type: "text", nullable: true),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_tags", x => x.id);
});
migrationBuilder.CreateTable(
name: "filter_lists",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "text", nullable: false),
description = table.Column<string>(type: "text", nullable: true),
license_id = table.Column<long>(type: "bigint", nullable: false, defaultValue: 5L),
home_url = table.Column<string>(type: "text", nullable: true),
onion_url = table.Column<string>(type: "text", nullable: true),
policy_url = table.Column<string>(type: "text", nullable: true),
submission_url = table.Column<string>(type: "text", nullable: true),
issues_url = table.Column<string>(type: "text", nullable: true),
forum_url = table.Column<string>(type: "text", nullable: true),
chat_url = table.Column<string>(type: "text", nullable: true),
email_address = table.Column<string>(type: "text", nullable: true),
donate_url = table.Column<string>(type: "text", nullable: true),
is_approved = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_lists", x => x.id);
table.ForeignKey(
name: "fk_filter_lists_licenses_license_id",
column: x => x.license_id,
principalTable: "licenses",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "software_syntaxes",
columns: table => new
{
software_id = table.Column<long>(type: "bigint", nullable: false),
syntax_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_software_syntaxes", x => new { x.software_id, x.syntax_id });
table.ForeignKey(
name: "fk_software_syntaxes_software_software_id",
column: x => x.software_id,
principalTable: "software",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_software_syntaxes_syntaxes_syntax_id",
column: x => x.syntax_id,
principalTable: "syntaxes",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "changes",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
reason = table.Column<string>(type: "text", nullable: true),
submitted_at = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
approved_at = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
rejected_at = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
rejected_reason = table.Column<string>(type: "text", nullable: true),
before = table.Column<JsonDocument>(type: "jsonb", nullable: true),
after = table.Column<JsonDocument>(type: "jsonb", nullable: true),
aggregate_type = table.Column<AggregateType>(type: "aggregate_type", nullable: false),
filter_list_id = table.Column<long>(type: "bigint", nullable: true),
language_id = table.Column<long>(type: "bigint", nullable: true),
license_id = table.Column<long>(type: "bigint", nullable: true),
maintainer_id = table.Column<long>(type: "bigint", nullable: true),
software_id = table.Column<long>(type: "bigint", nullable: true),
syntax_id = table.Column<long>(type: "bigint", nullable: true),
tag_id = table.Column<long>(type: "bigint", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_changes", x => x.id);
table.ForeignKey(
name: "fk_changes_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_languages_language_id",
column: x => x.language_id,
principalTable: "languages",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_licenses_license_id",
column: x => x.license_id,
principalTable: "licenses",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_maintainers_maintainer_id",
column: x => x.maintainer_id,
principalTable: "maintainers",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_software_software_id",
column: x => x.software_id,
principalTable: "software",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_syntaxes_syntax_id",
column: x => x.syntax_id,
principalTable: "syntaxes",
principalColumn: "id");
table.ForeignKey(
name: "fk_changes_tags_tag_id",
column: x => x.tag_id,
principalTable: "tags",
principalColumn: "id");
});
migrationBuilder.CreateTable(
name: "dependents",
columns: table => new
{
dependency_filter_list_id = table.Column<long>(type: "bigint", nullable: false),
dependent_filter_list_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_dependents", x => new { x.dependency_filter_list_id, x.dependent_filter_list_id });
table.ForeignKey(
name: "fk_dependents_filter_lists_dependency_filter_list_id",
column: x => x.dependency_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_dependents_filter_lists_dependent_filter_list_id",
column: x => x.dependent_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "filter_list_languages",
columns: table => new
{
filter_list_id = table.Column<long>(type: "bigint", nullable: false),
language_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_list_languages", x => new { x.filter_list_id, x.language_id });
table.ForeignKey(
name: "fk_filter_list_languages_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_filter_list_languages_languages_language_id",
column: x => x.language_id,
principalTable: "languages",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "filter_list_maintainers",
columns: table => new
{
filter_list_id = table.Column<long>(type: "bigint", nullable: false),
maintainer_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_list_maintainers", x => new { x.filter_list_id, x.maintainer_id });
table.ForeignKey(
name: "fk_filter_list_maintainers_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_filter_list_maintainers_maintainers_maintainer_id",
column: x => x.maintainer_id,
principalTable: "maintainers",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "filter_list_syntaxes",
columns: table => new
{
filter_list_id = table.Column<long>(type: "bigint", nullable: false),
syntax_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_list_syntaxes", x => new { x.filter_list_id, x.syntax_id });
table.ForeignKey(
name: "fk_filter_list_syntaxes_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_filter_list_syntaxes_syntaxes_syntax_id",
column: x => x.syntax_id,
principalTable: "syntaxes",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "filter_list_tags",
columns: table => new
{
filter_list_id = table.Column<long>(type: "bigint", nullable: false),
tag_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_list_tags", x => new { x.filter_list_id, x.tag_id });
table.ForeignKey(
name: "fk_filter_list_tags_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_filter_list_tags_tags_tag_id",
column: x => x.tag_id,
principalTable: "tags",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "filter_list_view_urls",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false),
filter_list_id = table.Column<long>(type: "bigint", nullable: false),
segment_number = table.Column<short>(type: "smallint", nullable: false, defaultValue: (short)1),
primariness = table.Column<short>(type: "smallint", nullable: false, defaultValue: (short)1),
url = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_filter_list_view_urls", x => new { x.filter_list_id, x.id });
table.ForeignKey(
name: "fk_filter_list_view_urls_filter_lists_filter_list_id",
column: x => x.filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "forks",
columns: table => new
{
upstream_filter_list_id = table.Column<long>(type: "bigint", nullable: false),
fork_filter_list_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_forks", x => new { x.upstream_filter_list_id, x.fork_filter_list_id });
table.ForeignKey(
name: "fk_forks_filter_lists_fork_filter_list_id",
column: x => x.fork_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_forks_filter_lists_upstream_filter_list_id",
column: x => x.upstream_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "merges",
columns: table => new
{
included_in_filter_list_id = table.Column<long>(type: "bigint", nullable: false),
includes_filter_list_id = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_merges", x => new { x.included_in_filter_list_id, x.includes_filter_list_id });
table.ForeignKey(
name: "fk_merges_filter_lists_included_in_filter_list_id",
column: x => x.included_in_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_merges_filter_lists_includes_filter_list_id",
column: x => x.includes_filter_list_id,
principalTable: "filter_lists",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_changes_filter_list_id",
table: "changes",
column: "filter_list_id");
migrationBuilder.CreateIndex(
name: "ix_changes_language_id",
table: "changes",
column: "language_id");
migrationBuilder.CreateIndex(
name: "ix_changes_license_id",
table: "changes",
column: "license_id");
migrationBuilder.CreateIndex(
name: "ix_changes_maintainer_id",
table: "changes",
column: "maintainer_id");
migrationBuilder.CreateIndex(
name: "ix_changes_software_id",
table: "changes",
column: "software_id");
migrationBuilder.CreateIndex(
name: "ix_changes_syntax_id",
table: "changes",
column: "syntax_id");
migrationBuilder.CreateIndex(
name: "ix_changes_tag_id",
table: "changes",
column: "tag_id");
migrationBuilder.CreateIndex(
name: "ix_dependents_dependent_filter_list_id",
table: "dependents",
column: "dependent_filter_list_id");
migrationBuilder.CreateIndex(
name: "ix_filter_list_languages_language_id",
table: "filter_list_languages",
column: "language_id");
migrationBuilder.CreateIndex(
name: "ix_filter_list_maintainers_maintainer_id",
table: "filter_list_maintainers",
column: "maintainer_id");
migrationBuilder.CreateIndex(
name: "ix_filter_list_syntaxes_syntax_id",
table: "filter_list_syntaxes",
column: "syntax_id");
migrationBuilder.CreateIndex(
name: "ix_filter_list_tags_tag_id",
table: "filter_list_tags",
column: "tag_id");
migrationBuilder.CreateIndex(
name: "ix_filter_list_view_urls_filter_list_id_segment_number_primari",
table: "filter_list_view_urls",
columns: new[] { "filter_list_id", "segment_number", "primariness" },
unique: true);
migrationBuilder.CreateIndex(
name: "ix_filter_lists_license_id",
table: "filter_lists",
column: "license_id");
migrationBuilder.CreateIndex(
name: "ix_filter_lists_name",
table: "filter_lists",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_forks_fork_filter_list_id",
table: "forks",
column: "fork_filter_list_id");
migrationBuilder.CreateIndex(
name: "ix_languages_iso6391",
table: "languages",
column: "iso6391",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_languages_name",
table: "languages",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_licenses_name",
table: "licenses",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_maintainers_name",
table: "maintainers",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_merges_includes_filter_list_id",
table: "merges",
column: "includes_filter_list_id");
migrationBuilder.CreateIndex(
name: "ix_software_name",
table: "software",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_software_syntaxes_syntax_id",
table: "software_syntaxes",
column: "syntax_id");
migrationBuilder.CreateIndex(
name: "ix_syntaxes_name",
table: "syntaxes",
column: "name",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_tags_name",
table: "tags",
column: "name",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "changes");
migrationBuilder.DropTable(
name: "dependents");
migrationBuilder.DropTable(
name: "filter_list_languages");
migrationBuilder.DropTable(
name: "filter_list_maintainers");
migrationBuilder.DropTable(
name: "filter_list_syntaxes");
migrationBuilder.DropTable(
name: "filter_list_tags");
migrationBuilder.DropTable(
name: "filter_list_view_urls");
migrationBuilder.DropTable(
name: "forks");
migrationBuilder.DropTable(
name: "merges");
migrationBuilder.DropTable(
name: "software_syntaxes");
migrationBuilder.DropTable(
name: "languages");
migrationBuilder.DropTable(
name: "maintainers");
migrationBuilder.DropTable(
name: "tags");
migrationBuilder.DropTable(
name: "filter_lists");
migrationBuilder.DropTable(
name: "software");
migrationBuilder.DropTable(
name: "syntaxes");
migrationBuilder.DropTable(
name: "licenses");
migrationBuilder.DropSequence(
name: "EntityFrameworkHiLoSequence-FilterListViewUrl");
}
}
}

View file

@ -1,78 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3668 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "filter_lists",
columns: new[] { "id", "chat_url", "description", "donate_url", "email_address", "forum_url", "home_url", "is_approved", "issues_url", "license_id", "name", "onion_url", "policy_url", "submission_url" },
values: new object[] { 2660L, null, "This list aims to prevent the pathetic excuses of domain endings (.zip and .mov) that Google recently added from causing phishing from being conducted using the old authentication URL scheme which is embedded into browsers", null, null, null, "https://github.com/L8X/AntiAuthenticationUrlFilter", true, "https://github.com/L8X/AntiAuthenticationUrlFilter/issues", 4L, "Anti-Authentication-Url-Filter", null, null, null });
migrationBuilder.InsertData(
table: "maintainers",
columns: new[] { "id", "email_address", "is_approved", "name", "twitter_handle", "url" },
values: new object[] { 190L, null, true, "L8X", null, "https://github.com/L8X" });
migrationBuilder.InsertData(
table: "filter_list_maintainers",
columns: new[] { "filter_list_id", "maintainer_id" },
values: new object[] { 2660L, 190L });
migrationBuilder.InsertData(
table: "filter_list_syntaxes",
columns: new[] { "filter_list_id", "syntax_id" },
values: new object[] { 2660L, 4L });
migrationBuilder.InsertData(
table: "filter_list_tags",
columns: new[] { "filter_list_id", "tag_id" },
values: new object[] { 2660L, 7L });
migrationBuilder.InsertData(
table: "filter_list_view_urls",
columns: new[] { "filter_list_id", "id", "url" },
values: new object[] { 2660L, 2939L, "https://raw.githubusercontent.com/L8X/AntiAuthenticationUrlFilter/main/AntiAuthenticationUrlFilter.txt" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "filter_list_maintainers",
keyColumns: new[] { "filter_list_id", "maintainer_id" },
keyValues: new object[] { 2660L, 190L });
migrationBuilder.DeleteData(
table: "filter_list_syntaxes",
keyColumns: new[] { "filter_list_id", "syntax_id" },
keyValues: new object[] { 2660L, 4L });
migrationBuilder.DeleteData(
table: "filter_list_tags",
keyColumns: new[] { "filter_list_id", "tag_id" },
keyValues: new object[] { 2660L, 7L });
migrationBuilder.DeleteData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 2660L, 2939L });
migrationBuilder.DeleteData(
table: "filter_lists",
keyColumn: "id",
keyValue: 2660L);
migrationBuilder.DeleteData(
table: "maintainers",
keyColumn: "id",
keyValue: 190L);
}
}
}

View file

@ -1,79 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3723 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "filter_lists",
columns: new[] { "id", "chat_url", "description", "donate_url", "email_address", "forum_url", "home_url", "is_approved", "issues_url", "license_id", "name", "onion_url", "policy_url", "submission_url" },
values: new object[] { 2661L, null, "Finnish Annoyances List blocks unnecessary connections and hides unnecessary elements.", null, null, null, "https://github.com/Axonym/finnish-annoyances", true, "https://github.com/Axonym/finnish-annoyances/issues", 11L, "Finnish Annoyances", null, null, null });
migrationBuilder.InsertData(
table: "maintainers",
columns: new[] { "id", "email_address", "is_approved", "name", "twitter_handle", "url" },
values: new object[] { 191L, null, true, "Axonym", null, "https://github.com/Axonym" });
migrationBuilder.InsertData(
table: "filter_list_languages",
columns: new[] { "filter_list_id", "language_id" },
values: new object[] { 2661L, 44L });
migrationBuilder.InsertData(
table: "filter_list_maintainers",
columns: new[] { "filter_list_id", "maintainer_id" },
values: new object[] { 2661L, 191L });
migrationBuilder.InsertData(
table: "filter_list_tags",
columns: new[] { "filter_list_id", "tag_id" },
values: new object[,]
{
{ 2661L, 2L },
{ 2661L, 35L }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "filter_list_languages",
keyColumns: new[] { "filter_list_id", "language_id" },
keyValues: new object[] { 2661L, 44L });
migrationBuilder.DeleteData(
table: "filter_list_maintainers",
keyColumns: new[] { "filter_list_id", "maintainer_id" },
keyValues: new object[] { 2661L, 191L });
migrationBuilder.DeleteData(
table: "filter_list_tags",
keyColumns: new[] { "filter_list_id", "tag_id" },
keyValues: new object[] { 2661L, 2L });
migrationBuilder.DeleteData(
table: "filter_list_tags",
keyColumns: new[] { "filter_list_id", "tag_id" },
keyValues: new object[] { 2661L, 35L });
migrationBuilder.DeleteData(
table: "filter_lists",
keyColumn: "id",
keyValue: 2661L);
migrationBuilder.DeleteData(
table: "maintainers",
keyColumn: "id",
keyValue: 191L);
}
}
}

View file

@ -1,38 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3724 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "filter_list_syntaxes",
columns: new[] { "filter_list_id", "syntax_id" },
values: new object[] { 2661L, 4L });
migrationBuilder.InsertData(
table: "filter_list_view_urls",
columns: new[] { "filter_list_id", "id", "url" },
values: new object[] { 2661L, 2940L, "https://raw.githubusercontent.com/Axonym/finnish-annoyances/main/annoyances.txt" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "filter_list_syntaxes",
keyColumns: new[] { "filter_list_id", "syntax_id" },
keyValues: new object[] { 2661L, 4L });
migrationBuilder.DeleteData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 2661L, 2940L });
}
}
}

View file

@ -1,58 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3791 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "filter_list_syntaxes",
keyColumns: new[] { "filter_list_id", "syntax_id" },
keyValues: new object[] { 2601L, 3L });
migrationBuilder.DeleteData(
table: "filter_list_tags",
keyColumns: new[] { "filter_list_id", "tag_id" },
keyValues: new object[] { 2601L, 9L });
migrationBuilder.DeleteData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 2601L, 2866L });
migrationBuilder.DeleteData(
table: "filter_lists",
keyColumn: "id",
keyValue: 2601L);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "filter_lists",
columns: new[] { "id", "chat_url", "description", "donate_url", "email_address", "forum_url", "home_url", "is_approved", "issues_url", "name", "onion_url", "policy_url", "submission_url" },
values: new object[] { 2601L, null, "Some custom cosmetic filters to be used for ublock origin & adguard. This filter is mainly for mobile browsing specifically for heavily modified AMP pages. Beware that this filter is very aggressive filters which disables the following from an webpage and is very effective if used with uBlock Origin and AdGuard.", null, null, null, "https://github.com/blogmangit/Cosmetic-Filters", true, null, "blogmangit Cosmetic-Filters", null, null, null });
migrationBuilder.InsertData(
table: "filter_list_syntaxes",
columns: new[] { "filter_list_id", "syntax_id" },
values: new object[] { 2601L, 3L });
migrationBuilder.InsertData(
table: "filter_list_tags",
columns: new[] { "filter_list_id", "tag_id" },
values: new object[] { 2601L, 9L });
migrationBuilder.InsertData(
table: "filter_list_view_urls",
columns: new[] { "filter_list_id", "id", "primariness", "url" },
values: new object[] { 2601L, 2866L, (short)1, "https://raw.githubusercontent.com/blogmangit/Cosmetic-Filters/main/cosmetic filters.txt" });
}
}
}

View file

@ -1,79 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3805 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "filter_list_languages",
keyColumns: new[] { "filter_list_id", "language_id" },
keyValues: new object[] { 767L, 37L });
migrationBuilder.DeleteData(
table: "filter_list_languages",
keyColumns: new[] { "filter_list_id", "language_id" },
keyValues: new object[] { 767L, 179L });
migrationBuilder.DeleteData(
table: "filter_list_syntaxes",
keyColumns: new[] { "filter_list_id", "syntax_id" },
keyValues: new object[] { 767L, 3L });
migrationBuilder.DeleteData(
table: "filter_list_tags",
keyColumns: new[] { "filter_list_id", "tag_id" },
keyValues: new object[] { 767L, 2L });
migrationBuilder.DeleteData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 767L, 798L });
migrationBuilder.DeleteData(
table: "filter_lists",
keyColumn: "id",
keyValue: 767L);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "filter_lists",
columns: new[] { "id", "chat_url", "description", "donate_url", "email_address", "forum_url", "home_url", "is_approved", "issues_url", "license_id", "name", "onion_url", "policy_url", "submission_url" },
values: new object[] { 767L, null, "Rules contributed by diligent owls.", null, null, null, "https://github.com/OwlStudioCN/owl-abp-rules", true, "https://github.com/OwlStudioCN/owl-abp-rules/issues", 8L, "OwlStudio ABP Rules", null, null, null });
migrationBuilder.InsertData(
table: "filter_list_languages",
columns: new[] { "filter_list_id", "language_id" },
values: new object[,]
{
{ 767L, 37L },
{ 767L, 179L }
});
migrationBuilder.InsertData(
table: "filter_list_syntaxes",
columns: new[] { "filter_list_id", "syntax_id" },
values: new object[] { 767L, 3L });
migrationBuilder.InsertData(
table: "filter_list_tags",
columns: new[] { "filter_list_id", "tag_id" },
values: new object[] { 767L, 2L });
migrationBuilder.InsertData(
table: "filter_list_view_urls",
columns: new[] { "filter_list_id", "id", "primariness", "url" },
values: new object[] { 767L, 798L, (short)1, "https://raw.githubusercontent.com/OwlStudioCN/owl-abp-rules/master/owl-abp-rules.txt" });
}
}
}

View file

@ -1,32 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FilterLists.Directory.Infrastructure.Migrations.Migrations
{
/// <inheritdoc />
public partial class _3811 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 250L, 378L },
column: "url",
value: "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "filter_list_view_urls",
keyColumns: new[] { "filter_list_id", "id" },
keyValues: new object[] { 250L, 378L },
column: "url",
value: "https://easylist-downloads.adblockplus.org/easylist-cookie.txt");
}
}
}

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