Files
novelly/src/Novelly.Api/Beats/Beat.cs
T
James Wampler e598c18d67 Add users, roles, and per-novel permissions
Introduces accounts (ASP.NET Identity + cookie auth), four global
roles (Admin/Writer/Editor/Reviewer), per-novel ownership and grants
via ProjectMember, and a service-API-key principal for the MCP server
and background import jobs. Enforcement lives in the application
services (not endpoint filters) so the embedded agent and MCP tools,
which call the same services directly, can't bypass it. Web client
gets a login page, session-aware routing, and a People section for
managing per-novel access.

Also includes prior in-flight changes from this branch (CLAUDE.md
compliance pass, dev-deploy docker-compose setup) that were
uncommitted when this feature work started.
2026-08-15 22:29:33 -07:00

46 lines
1.3 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Novelly.Api.Chapters;
using Novelly.Api.Characters;
using Novelly.Api.Tags;
namespace Novelly.Api.Beats;
public class Beat
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid ChapterId { get; set; }
public Chapter? Chapter { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; } = string.Empty;
public List<Character> Characters { get; set; } = [];
public string? WhatHappened { get; set; }
public string? WhatsNext { get; set; }
public List<Tag> Tags { get; set; } = [];
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public class BeatEntityTypeConfiguration : IEntityTypeConfiguration<Beat>
{
public void Configure(EntityTypeBuilder<Beat> entity)
{
entity.Property(b => b.Title).IsRequired().HasMaxLength(200);
entity.HasIndex(b => new { b.ChapterId, b.SortOrder });
entity.HasOne(b => b.Chapter).WithMany(c => c.Beats)
.HasForeignKey(b => b.ChapterId).OnDelete(DeleteBehavior.Cascade);
entity.HasMany(b => b.Characters).WithMany(c => c.Beats)
.UsingEntity(join => join.ToTable("BeatCharacters"));
}
}