Fixed 403 Forbidden thrown when getting Website metadata #24

Merged
carltibule merged 1 commits from feature/AddUserAgentToWebClientBeforeDownloadingWebPageString into develop 2023-03-04 00:39:51 -06:00
5 changed files with 271 additions and 5 deletions

View File

@ -39,7 +39,11 @@ namespace YABA.Data.Context
.IsUnique(); .IsUnique();
modelBuilder.Entity<Tag>() modelBuilder.Entity<Tag>()
.HasIndex(x => x.Name) .HasIndex(x => new { x.Name, x.UserId })
.IsUnique();
modelBuilder.Entity<Bookmark>()
.HasIndex(x => new { x.Url, x.UserId })
.IsUnique(); .IsUnique();
} }

View File

@ -0,0 +1,214 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using YABA.Data.Context;
namespace YABA.Data.Migrations
{
[DbContext(typeof(YABABaseContext))]
[Migration("20230304061552_AddUniqueNameAndUserIdComboConstraintToTagsTable_AddUniqueUrlAndUserIdComboConstraintToBookmark")]
partial class AddUniqueNameAndUserIdComboConstraintToTagsTable_AddUniqueUrlAndUserIdComboConstraintToBookmark
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 63)
.HasAnnotation("ProductVersion", "5.0.17")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
modelBuilder.Entity("YABA.Models.Bookmark", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<DateTimeOffset>("CreatedOn")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_on");
b.Property<string>("Description")
.HasColumnType("text")
.HasColumnName("description");
b.Property<bool>("IsHidden")
.HasColumnType("boolean")
.HasColumnName("is_hidden");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<string>("Note")
.HasColumnType("text")
.HasColumnName("note");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text")
.HasColumnName("title");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("text")
.HasColumnName("url");
b.Property<int>("UserId")
.HasColumnType("integer")
.HasColumnName("user_id");
b.HasKey("Id")
.HasName("pk_bookmarks");
b.HasIndex("UserId")
.HasDatabaseName("ix_bookmarks_user_id");
b.HasIndex("Url", "UserId")
.IsUnique()
.HasDatabaseName("ix_bookmarks_url_user_id");
b.ToTable("bookmarks");
});
modelBuilder.Entity("YABA.Models.BookmarkTag", b =>
{
b.Property<int>("BookmarkId")
.HasColumnType("integer")
.HasColumnName("bookmark_id");
b.Property<int>("TagId")
.HasColumnType("integer")
.HasColumnName("tag_id");
b.HasKey("BookmarkId", "TagId")
.HasName("pk_bookmark_tags");
b.HasIndex("TagId")
.HasDatabaseName("ix_bookmark_tags_tag_id");
b.ToTable("bookmark_tags");
});
modelBuilder.Entity("YABA.Models.Tag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<bool>("IsHidden")
.HasColumnType("boolean")
.HasColumnName("is_hidden");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<int>("UserId")
.HasColumnType("integer")
.HasColumnName("user_id");
b.HasKey("Id")
.HasName("pk_tags");
b.HasIndex("UserId")
.HasDatabaseName("ix_tags_user_id");
b.HasIndex("Name", "UserId")
.IsUnique()
.HasDatabaseName("ix_tags_name_user_id");
b.ToTable("tags");
});
modelBuilder.Entity("YABA.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("Auth0Id")
.IsRequired()
.HasColumnType("text")
.HasColumnName("auth0id");
b.Property<DateTimeOffset>("CreatedOn")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_on");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.HasKey("Id")
.HasName("pk_users");
b.HasIndex("Auth0Id")
.IsUnique()
.HasDatabaseName("ix_users_auth0id");
b.ToTable("users");
});
modelBuilder.Entity("YABA.Models.Bookmark", b =>
{
b.HasOne("YABA.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.HasConstraintName("fk_bookmarks_users_user_id")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("YABA.Models.BookmarkTag", b =>
{
b.HasOne("YABA.Models.Bookmark", "Bookmark")
.WithMany()
.HasForeignKey("BookmarkId")
.HasConstraintName("fk_bookmark_tags_bookmarks_bookmark_id")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YABA.Models.Tag", "Tag")
.WithMany()
.HasForeignKey("TagId")
.HasConstraintName("fk_bookmark_tags_tags_tag_id")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Bookmark");
b.Navigation("Tag");
});
modelBuilder.Entity("YABA.Models.Tag", b =>
{
b.HasOne("YABA.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.HasConstraintName("fk_tags_users_user_id")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace YABA.Data.Migrations
{
public partial class AddUniqueNameAndUserIdComboConstraintToTagsTable_AddUniqueUrlAndUserIdComboConstraintToBookmark : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_tags_name",
table: "tags");
migrationBuilder.CreateIndex(
name: "ix_tags_name_user_id",
table: "tags",
columns: new[] { "name", "user_id" },
unique: true);
migrationBuilder.CreateIndex(
name: "ix_bookmarks_url_user_id",
table: "bookmarks",
columns: new[] { "url", "user_id" },
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_tags_name_user_id",
table: "tags");
migrationBuilder.DropIndex(
name: "ix_bookmarks_url_user_id",
table: "bookmarks");
migrationBuilder.CreateIndex(
name: "ix_tags_name",
table: "tags",
column: "name",
unique: true);
}
}
}

View File

@ -67,6 +67,10 @@ namespace YABA.Data.Migrations
b.HasIndex("UserId") b.HasIndex("UserId")
.HasDatabaseName("ix_bookmarks_user_id"); .HasDatabaseName("ix_bookmarks_user_id");
b.HasIndex("Url", "UserId")
.IsUnique()
.HasDatabaseName("ix_bookmarks_url_user_id");
b.ToTable("bookmarks"); b.ToTable("bookmarks");
}); });
@ -113,13 +117,13 @@ namespace YABA.Data.Migrations
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_tags"); .HasName("pk_tags");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("ix_tags_name");
b.HasIndex("UserId") b.HasIndex("UserId")
.HasDatabaseName("ix_tags_user_id"); .HasDatabaseName("ix_tags_user_id");
b.HasIndex("Name", "UserId")
.IsUnique()
.HasDatabaseName("ix_tags_name_user_id");
b.ToTable("tags"); b.ToTable("tags");
}); });

View File

@ -253,6 +253,7 @@ namespace YABA.Service
private void UpdateBookmarkWithMetaData(IBookmark bookmark) private void UpdateBookmarkWithMetaData(IBookmark bookmark)
{ {
var webClient = new WebClient(); var webClient = new WebClient();
webClient.Headers.Add("User-Agent", "APIClient");
var sourceData = webClient.DownloadString(bookmark.Url); var sourceData = webClient.DownloadString(bookmark.Url);
var title = Regex.Match(sourceData, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value; var title = Regex.Match(sourceData, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
var description = string.Empty; var description = string.Empty;