Commit 94d8921f authored by Eric Dieckman's avatar Eric Dieckman
Browse files

feat: add WiscNic contact types, people CRUD, and VLAN contact endpoints

Renames WiscNicGroupMembershipType to WiscNicContactType throughout (model,
EF config, table, column) to better reflect the concept. Adds People CRUD,
WiscNic group/member CRUD, and VLAN person/group contact endpoints. Migration
renames wn_group_membership_types to wn_contact_types and creates
wn_vlan_person_contacts and wn_vlan_group_contacts junction tables.
parent 4a91d44c
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
using Cals.Visor.Api.Authorization;
using Cals.Visor.Infrastructure.Contexts;
using Cals.Visor.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Cals.Visor.Api.Controllers;
[Route("[controller]")]
[ApiController]
public class PeopleController : ControllerBase
{
    private readonly ApplicationDbContext _context;

    public PeopleController(ApplicationDbContext context) => _context = context;

    // GET: /people
    [ProducesResponseType<IList<Person>>(StatusCodes.Status200OK)]
    [HttpGet(Name = "GetAllPeople")]
    public async Task<IActionResult> GetAllAsync()
    {
        List<Person> result = await _context.People
            .Where(e => e.IsActive == true)
            .ToListAsync();

        return Ok(result);
    }

    // GET: /people/1
    [ProducesResponseType<Person>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpGet("{personId:long}", Name = "GetPersonById")]
    public async Task<IActionResult> GetByIdAsync(long personId)
    {
        Person? result = await _context.People
            .Where(e => e.PersonId == personId)
            .FirstOrDefaultAsync();

        if (result == null)
            return NotFound();

        return Ok(result);
    }

    // POST: /people
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<Person>(StatusCodes.Status201Created)]
    [HttpPost(Name = "CreateNewPerson")]
    public async Task<IActionResult> CreateNewAsync([FromBody] Person data)
    {
        _context.Add(data);
        await _context.SaveChangesAsync();

        return CreatedAtRoute("GetPersonById", new { personId = data.PersonId }, data);
    }

    // PUT: /people/1
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<Person>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpPut("{personId:long}", Name = "UpdatePerson")]
    public async Task<IActionResult> UpdateAsync(long personId, [FromBody] Person data)
    {
        Person? entity = await _context.People
            .Where(e => e.PersonId == personId)
            .FirstOrDefaultAsync();

        if (entity == null)
            return NotFound();

        entity.Name = data.Name;
        entity.Email = data.Email;
        entity.NicHandle = data.NicHandle;
        entity.NetId = data.NetId;
        entity.Pvi = data.Pvi;
        entity.IsActive = data.IsActive;

        await _context.SaveChangesAsync();

        return Ok(entity);
    }
}
+117 −0
Original line number Diff line number Diff line
@@ -136,4 +136,121 @@ public class VlansController : ControllerBase

        return Ok(result);
    }

    // ######################################################
    // ### WISCNIC PERSON CONTACTS
    //

    // GET: /vlans/2/person-contacts
    [ProducesResponseType<IList<WiscNicVlanPersonContact>>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpGet("{vlanId:long}/person-contacts", Name = "GetVlanPersonContacts")]
    public async Task<IActionResult> GetPersonContactsAsync(long vlanId)
    {
        if (!await _context.Vlans.AnyAsync(v => v.VlanId == vlanId))
            return NotFound();

        List<WiscNicVlanPersonContact> result = await _context.WiscNicVlanPersonContacts
            .Where(c => c.VlanId == vlanId)
            .Include(c => c.Person)
            .Include(c => c.ContactType)
            .ToListAsync();

        return Ok(result);
    }

    // POST: /vlans/2/person-contacts
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<WiscNicVlanPersonContact>(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpPost("{vlanId:long}/person-contacts", Name = "AddVlanPersonContact")]
    public async Task<IActionResult> AddPersonContactAsync(long vlanId, [FromBody] WiscNicVlanPersonContact data)
    {
        if (!await _context.Vlans.AnyAsync(v => v.VlanId == vlanId))
            return NotFound();

        data.VlanId = vlanId;
        _context.WiscNicVlanPersonContacts.Add(data);
        await _context.SaveChangesAsync();

        return CreatedAtRoute("GetVlanPersonContacts", new { vlanId }, data);
    }

    // DELETE: /vlans/2/person-contacts/5
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpDelete("{vlanId:long}/person-contacts/{contactId:long}", Name = "RemoveVlanPersonContact")]
    public async Task<IActionResult> RemovePersonContactAsync(long vlanId, long contactId)
    {
        WiscNicVlanPersonContact? contact = await _context.WiscNicVlanPersonContacts
            .Where(c => c.VlanId == vlanId && c.WiscNicVlanPersonContactId == contactId)
            .FirstOrDefaultAsync();

        if (contact == null)
            return NotFound();

        _context.WiscNicVlanPersonContacts.Remove(contact);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    // ######################################################
    // ### WISCNIC GROUP CONTACTS
    //

    // GET: /vlans/2/group-contacts
    [ProducesResponseType<IList<WiscNicVlanGroupContact>>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpGet("{vlanId:long}/group-contacts", Name = "GetVlanGroupContacts")]
    public async Task<IActionResult> GetGroupContactsAsync(long vlanId)
    {
        if (!await _context.Vlans.AnyAsync(v => v.VlanId == vlanId))
            return NotFound();

        List<WiscNicVlanGroupContact> result = await _context.WiscNicVlanGroupContacts
            .Where(c => c.VlanId == vlanId)
            .Include(c => c.Group)
            .ToListAsync();

        return Ok(result);
    }

    // POST: /vlans/2/group-contacts
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<WiscNicVlanGroupContact>(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpPost("{vlanId:long}/group-contacts", Name = "AddVlanGroupContact")]
    public async Task<IActionResult> AddGroupContactAsync(long vlanId, [FromBody] WiscNicVlanGroupContact data)
    {
        if (!await _context.Vlans.AnyAsync(v => v.VlanId == vlanId))
            return NotFound();

        data.VlanId = vlanId;
        _context.WiscNicVlanGroupContacts.Add(data);
        await _context.SaveChangesAsync();

        return CreatedAtRoute("GetVlanGroupContacts", new { vlanId }, data);
    }

    // DELETE: /vlans/2/group-contacts/5
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpDelete("{vlanId:long}/group-contacts/{contactId:long}", Name = "RemoveVlanGroupContact")]
    public async Task<IActionResult> RemoveGroupContactAsync(long vlanId, long contactId)
    {
        WiscNicVlanGroupContact? contact = await _context.WiscNicVlanGroupContacts
            .Where(c => c.VlanId == vlanId && c.WiscNicVlanGroupContactId == contactId)
            .FirstOrDefaultAsync();

        if (contact == null)
            return NotFound();

        _context.WiscNicVlanGroupContacts.Remove(contact);
        await _context.SaveChangesAsync();

        return NoContent();
    }
}
+135 −0
Original line number Diff line number Diff line
using Cals.Visor.Api.Authorization;
using Cals.Visor.Infrastructure.Contexts;
using Cals.Visor.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Cals.Visor.Api.Controllers;
[Route("wiscnic/groups")]
[ApiController]
public class WiscNicGroupsController : ControllerBase
{
    private readonly ApplicationDbContext _context;

    public WiscNicGroupsController(ApplicationDbContext context) => _context = context;

    // GET: /wiscnic/groups
    [ProducesResponseType<IList<WiscNicGroup>>(StatusCodes.Status200OK)]
    [HttpGet(Name = "GetAllWiscNicGroups")]
    public async Task<IActionResult> GetAllAsync()
    {
        List<WiscNicGroup> result = await _context.WiscNicGroups
            .Where(e => e.IsActive == true)
            .ToListAsync();

        return Ok(result);
    }

    // GET: /wiscnic/groups/1
    [ProducesResponseType<WiscNicGroup>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpGet("{groupId:long}", Name = "GetWiscNicGroupById")]
    public async Task<IActionResult> GetByIdAsync(long groupId)
    {
        WiscNicGroup? result = await _context.WiscNicGroups
            .Where(e => e.WiscNicGroupId == groupId)
            .FirstOrDefaultAsync();

        if (result == null)
            return NotFound();

        return Ok(result);
    }

    // POST: /wiscnic/groups
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<WiscNicGroup>(StatusCodes.Status201Created)]
    [HttpPost(Name = "CreateNewWiscNicGroup")]
    public async Task<IActionResult> CreateNewAsync([FromBody] WiscNicGroup data)
    {
        _context.Add(data);
        await _context.SaveChangesAsync();

        return CreatedAtRoute("GetWiscNicGroupById", new { groupId = data.WiscNicGroupId }, data);
    }

    // PUT: /wiscnic/groups/1
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<WiscNicGroup>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpPut("{groupId:long}", Name = "UpdateWiscNicGroup")]
    public async Task<IActionResult> UpdateAsync(long groupId, [FromBody] WiscNicGroup data)
    {
        WiscNicGroup? entity = await _context.WiscNicGroups
            .Where(e => e.WiscNicGroupId == groupId)
            .FirstOrDefaultAsync();

        if (entity == null)
            return NotFound();

        entity.NicHandle = data.NicHandle;
        entity.Name = data.Name;
        entity.Description = data.Description;
        entity.IsActive = data.IsActive;

        await _context.SaveChangesAsync();

        return Ok(entity);
    }

    // GET: /wiscnic/groups/1/members
    [ProducesResponseType<IList<WiscNicGroupMember>>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpGet("{groupId:long}/members", Name = "GetWiscNicGroupMembers")]
    public async Task<IActionResult> GetMembersAsync(long groupId)
    {
        if (!await _context.WiscNicGroups.AnyAsync(g => g.WiscNicGroupId == groupId))
            return NotFound();

        List<WiscNicGroupMember> result = await _context.WiscNicGroupMembers
            .Where(m => m.GroupId == groupId)
            .Include(m => m.Member)
            .Include(m => m.ContactType)
            .ToListAsync();

        return Ok(result);
    }

    // POST: /wiscnic/groups/1/members
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType<WiscNicGroupMember>(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpPost("{groupId:long}/members", Name = "AddWiscNicGroupMember")]
    public async Task<IActionResult> AddMemberAsync(long groupId, [FromBody] WiscNicGroupMember data)
    {
        if (!await _context.WiscNicGroups.AnyAsync(g => g.WiscNicGroupId == groupId))
            return NotFound();

        data.GroupId = groupId;
        _context.WiscNicGroupMembers.Add(data);
        await _context.SaveChangesAsync();

        return CreatedAtRoute("GetWiscNicGroupMembers", new { groupId }, data);
    }

    // DELETE: /wiscnic/groups/1/members/5
    [Authorize(Policy = Policies.CanEdit)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [HttpDelete("{groupId:long}/members/{memberId:long}", Name = "RemoveWiscNicGroupMember")]
    public async Task<IActionResult> RemoveMemberAsync(long groupId, long memberId)
    {
        WiscNicGroupMember? member = await _context.WiscNicGroupMembers
            .Where(m => m.GroupId == groupId && m.WiscNicGroupMemberId == memberId)
            .FirstOrDefaultAsync();

        if (member == null)
            return NotFound();

        _context.WiscNicGroupMembers.Remove(member);
        await _context.SaveChangesAsync();

        return NoContent();
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -46,8 +46,11 @@ public class ApplicationDbContext : DbContext
    public DbSet<Vlan> Vlans => Set<Vlan>();
    public DbSet<VlanUseType> VlanUseTypes => Set<VlanUseType>();
    public DbSet<Subnet> Subnets => Set<Subnet>();
    public DbSet<WiscNicContactType> WiscNicContactTypes => Set<WiscNicContactType>();
    public DbSet<WiscNicGroup> WiscNicGroups => Set<WiscNicGroup>();
    public DbSet<WiscNicGroupMembershipType> WiscNicGroupMembershipTypes => Set<WiscNicGroupMembershipType>();
    public DbSet<WiscNicGroupMember> WiscNicGroupMembers => Set<WiscNicGroupMember>();
    public DbSet<WiscNicVlanGroupContact> WiscNicVlanGroupContacts => Set<WiscNicVlanGroupContact>();
    public DbSet<WiscNicVlanPersonContact> WiscNicVlanPersonContacts => Set<WiscNicVlanPersonContact>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
+3 −1
Original line number Diff line number Diff line
@@ -45,9 +45,11 @@ internal sealed class ColumnNames

    internal sealed class WiscNic
    {
        internal const string ContactTypeId = "wn_contact_type_id";
        internal const string GroupId = "wn_group_id";
        internal const string GroupMembershipTypeID = "wn_group_membership_type_id";
        internal const string GroupMemberId = "wn_group_member_id";
        internal const string VlanGroupContactId = "wn_vlan_group_contact_id";
        internal const string VlanPersonContactId = "wn_vlan_person_contact_id";
    }
#pragma warning restore IDE1006 // Naming Styles
}
Loading