Compare commits

..

9 Commits

33 changed files with 499 additions and 50 deletions

5
.gitignore vendored
View File

@ -5,7 +5,4 @@
/API/appsettings.*
/Setup/bin/
/Setup/obj/
/Setup/appsettings.*
/web/bin/
/web/obj/
/web/appsettings.*
/Setup/appsettings.*

View File

@ -6,6 +6,12 @@
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://192.168.1.52:5618</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
<driver-properties>
<property name="serverTimezone" value="UTC" />

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/Setup/Filler/Grants.sql" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/Setup/Filler/Permissions.sql" dialect="MySQL" />
</component>
</project>

View File

@ -41,5 +41,10 @@ namespace API.Authentication
return _grantManager.hasGrant(user.permissionId, EventGrantNames.CanDeleteAny) ||
_grantManager.getULongValues(user.permissionId, EventGrantNames.CanDelete).Exists(x => x == model.id);
}
public bool canCheckSelfSignup(User user)
{
//todo grants
return true;
}
}
}

View File

@ -43,5 +43,9 @@ namespace API.Authentication
_grantManager.getULongValues(user.permissionId, GrantGrantNames.CanDelete).Exists(x => x == model.id))
&& _grantManager.hasGrant(user.permissionId, model.name);
}
public bool canGetMine(User user)
{
return _grantManager.hasGrant(user.permissionId, GrantGrantNames.CanGetSelf);
}
}
}

View File

@ -2,6 +2,7 @@ namespace API.Authentication.GrantNames
{
public static class GrantGrantNames
{
public const string CanGetSelf = "api.grant.get.self";
public const string CanGetAll = "api.grant.get.all";
public const string CanGetAny = "api.grant.get.any";
public const string CanGet = "api.grant.get";

View File

@ -0,0 +1,15 @@
namespace API.Authentication.GrantNames
{
public static class SignupGrantNames
{
public const string CanGetAll = "api.signup.get.all";
public const string CanGetAny = "api.signup.get.any";
public const string CanGet = "api.signup.get";
public const string CanAdd = "api.signup.add";
public const string CanUpdateAny = "api.signup.update.any";
public const string CanUpdate = "api.signup.update";
public const string CanDeleteAny = "api.signup.delete.any";
public const string CanDelete = "api.signup.delete";
public const string CanAddOthers = "api.signup.add.others";
}
}

View File

@ -5,5 +5,6 @@ namespace API.Authentication.Interfaces
{
public interface IEventAuthentication : IGenericAuthentication<EventDTO, Event>
{
bool canCheckSelfSignup(User user);
}
}

View File

@ -5,5 +5,6 @@ namespace API.Authentication.Interfaces
{
public interface IGrantAuthentication : IGenericAuthentication<GrantDTO, Grant>
{
bool canGetMine(User user);
}
}

View File

@ -0,0 +1,9 @@
using API.DTO.Base.Update;
using DAL.Models;
namespace API.Authentication.Interfaces
{
public interface ISignupAuthentication : IGenericAuthentication<SignupDTO, Signup>
{
}
}

View File

@ -0,0 +1,48 @@
using API.Authentication.GrantNames;
using API.Authentication.Interfaces;
using API.DTO.Base.Update;
using API.Services.Interfaces;
using DAL.Models;
namespace API.Authentication
{
public class SignupAuthentication : ISignupAuthentication
{
private readonly IGrantManager _grantManager;
private readonly ILogger<SignupAuthentication> _logger;
public SignupAuthentication(IGrantManager grantManager, ILogger<SignupAuthentication> logger)
{
_grantManager = grantManager;
_logger = logger;
}
//todo make more restrictive
public bool canGetAll(User user)
{
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanGetAll);
}
public bool canGet(Signup model, User user)
{
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanGetAny) ||
_grantManager.getULongValues(user.permissionId, SignupGrantNames.CanGet).Exists(x => x == model.id);
}
public bool canAdd(SignupDTO item, User user)
{
if (item.userId == user.id)
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanAdd);
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanAddOthers);
}
public bool canUpdate(Signup model, User user)
{
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanUpdateAny) ||
_grantManager.getULongValues(user.permissionId, SignupGrantNames.CanUpdate).Exists(x => x == model.id);
}
public bool canDelete(Signup model, User user)
{
return _grantManager.hasGrant(user.permissionId, SignupGrantNames.CanDeleteAny) ||
_grantManager.getULongValues(user.permissionId, SignupGrantNames.CanDelete).Exists(x => x == model.id);
}
}
}

View File

@ -3,6 +3,7 @@ using API.DTO.Login;
using API.Errors;
using API.Services;
using API.Services.Interfaces;
using DAL.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
@ -48,16 +49,45 @@ namespace API.Controllers
}
[HttpPost("register")]
public ActionResult<UserDTO> register(UserRegisterDTO registerDTO)
public ActionResult<UserDTO> register(UserRegisterDTO registerDTO, ulong? permissionId = null)
{
UserDTO? user = _userManager.registerUser(registerDTO);
if (registerDTO.password == null)
registerDTO.password = registerDTO.phoneNumber;
if (user == null)
if (permissionId == null)
{
return Conflict(Strings.UserExists);
User? user = getUser(User);
if (user == null)
return Unauthorized();
UserDTO? createdUser = _userManager.registerUser(registerDTO, user, permissionId);
if (createdUser == null)
return Conflict(Strings.UserExists);
return Ok(createdUser);
}
return Ok(user);
{
UserDTO? user = _userManager.registerUser(registerDTO);
if (user == null)
{
return Conflict(Strings.UserExists);
}
return Ok(user);
}
}
[NonAction]
public User? getUser(ClaimsPrincipal user)
{
Claim? idClaim = user.FindFirst(ClaimTypes.NameIdentifier);
if (idClaim == null)
return null;
return _userService.getNoAuthentication(UInt64.Parse(idClaim.Value));
}
}
}

View File

@ -16,28 +16,45 @@ namespace API.Controllers
public EventController(ILogger<EventController> logger, UserService userService, EventService service) : base(logger, userService, service)
{
}
//todo slow
[HttpGet("period")]
public virtual ActionResult<List<EventDTO>> getPeriod(DateTime start, DateTime end)
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
IEnumerable<Event>? result = Service.get(user, x=> x.when >= start && x.when <= end);
IEnumerable<Event>? result = Service.get(user, x => x.when >= start && x.when <= end && x.hidden == false);
if (result == null)
return Forbid();
List<EventDTO> dtos = [];
Parallel.ForEach(result, item =>
List<Event> temp = result.ToList();
Parallel.ForEach(temp, item =>
{
EventDTO dto = new EventDTO();
dto.adaptFromModel(item);
dtos.Add(dto);
});
return Ok(dtos);
}
[HttpGet("{eventId}/isSignedUp")]
public ActionResult<bool> isSignedUp(ulong eventId)
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
bool? isSignedUp = Service.isSignedUp(user, eventId);
if (isSignedUp == null)
return Forbid();
return isSignedUp;
}
}
}

View File

@ -5,6 +5,7 @@ using API.Services;
using DAL.Models;
using DAL.Models.Audits;
using Microsoft.AspNetCore.Mvc;
using MUser = DAL.Models.User;
namespace API.Controllers
{
@ -15,5 +16,28 @@ namespace API.Controllers
public GrantController(ILogger<GrantController> logger, UserService userService, GrantService service) : base(logger, userService, service)
{
}
[HttpGet("mine")]
public ActionResult<List<GrantDTO>> getMine()
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
IEnumerable<Grant>? result = Service.getMine(user);
if (result == null)
return Forbid();
List<GrantDTO> dtos = [];
Parallel.ForEach(result, item =>
{
GrantDTO dto = new GrantDTO();
dto.adaptFromModel(item);
dtos.Add(dto);
});
return Ok(dtos);
}
}
}

View File

@ -0,0 +1,84 @@
using API.Authentication.Interfaces;
using API.DTO.Base.Update;
using API.Services;
using DAL.Models;
using DAL.Models.Audits;
using Microsoft.AspNetCore.Mvc;
using MUser = DAL.Models.User;
namespace API.Controllers
{
[ApiController]
[Route("api/v1/[controller]")]
public class SignupController : CRUDBase<SignupController, SignupDTO, SignupUpdateDTO, Signup, AuditSignup, ISignupAuthentication, SignupService>
{
public SignupController(ILogger<SignupController> logger, UserService userService, SignupService service) : base(logger, userService, service)
{
}
[HttpGet("forEvent/{eventId}")]
public ActionResult<SignupDTO> getForEvent(ulong eventId)
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
IEnumerable<Signup>? result = Service.get(user, e => e.eventId == eventId);
if (result == null)
return Forbid();
List<SignupDTO> dtos = [];
Parallel.ForEach(result, item =>
{
SignupDTO dto = new SignupDTO();
dto.adaptFromModel(item);
dtos.Add(dto);
});
return Ok(dtos);
}
[HttpPost("autoUser")]
public ActionResult<SignupDTO> add(SignupDTO createDTO)
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
// todo
createDTO.userId = user.id;
if (createDTO.userId != user.id)
{
return Forbid();
}
Signup? result = Service.add(createDTO, user);
if (result == null)
return Forbid();
SignupDTO dto = new SignupDTO();
dto.adaptFromModel(result);
return Ok(dto);
}
[HttpDelete("event/{eventId}")]
public ActionResult deleteForEvent(ulong eventId)
{
MUser? user = getUser(User);
if (user == null)
return Unauthorized();
Signup? result = Service.getNoAuthentication(x => x.userId == user.id && x.eventId == eventId).FirstOrDefault();
if (result == null)
return Forbid();
AuditSignup? auditModel = Service.delete(result, user);
if (auditModel == null)
return Forbid();
return NoContent();
}
}
}

33
API/DTO/Base/SignupDTO.cs Normal file
View File

@ -0,0 +1,33 @@
using DAL.Models;
namespace API.DTO.Base.Update
{
public class SignupDTO : IAdaptable<Signup>
{
public ulong id { get; set; }
public ulong eventId { get; set; }
public ulong userId { get; set; }
public DateTime updated { get; set; }
public ulong updater { get; set; }
public Signup adaptToModel()
{
return new Signup
{
id = id,
eventId = eventId,
userId = userId,
updated = updated,
updater = updater
};
}
public void adaptFromModel(in Signup model)
{
id = model.id;
eventId = model.eventId;
userId = model.userId;
updated = model.updated;
updater = model.updater;
}
}
}

View File

@ -1,5 +1,4 @@
using DAL.Models;
using System.ComponentModel.DataAnnotations;
namespace API.DTO.Base.Update
{
@ -7,23 +6,23 @@ namespace API.DTO.Base.Update
{
public ulong? savedEventId { get; set; }
[MaxLength(64)]
// [MaxLength(64)]
public UnSettable<string?>? name { get; set; }
public UnSettable<ulong?>? bgColorId { get; set; }
public UnSettable<ulong?>? fgColorId { get; set; }
public UnSettable<ulong?>? imageId { get; set; }
public UnSettable<DateTime>? when { get; set; }
public DateTime? when { get; set; }
public bool? hidden { get; set; }
public void adaptModel(ref Event model)
{
if (savedEventId != null) model.savedEventId = (ulong)savedEventId;
if (name != null) model.name = ((UnSettable<string?>)name).value;
if (name != null) model.name = name.Value.value;
if (bgColorId != null) model.bgColorId = bgColorId.Value.value;
if (fgColorId != null) model.bgColorId = fgColorId.Value.value;
if (fgColorId != null) model.fgColorId = fgColorId.Value.value;
if (imageId != null) model.imageId = imageId.Value.value;
if (when != null) model.when = when.Value.value;
if (when != null) model.when = (DateTime)when;
if (hidden != null) model.hidden = (bool)hidden;
}
}

View File

@ -0,0 +1,16 @@
using DAL.Models;
namespace API.DTO.Base.Update
{
public class SignupUpdateDTO : IUpdateAdaptable<Signup>
{
public ulong? eventId { get; set; }
public ulong? userId { get; set; }
public void adaptModel(ref Signup model)
{
if (eventId != null) model.eventId = (ulong)eventId;
if (userId != null) model.userId = (ulong)userId;
}
}
}

View File

@ -14,6 +14,6 @@ namespace API.DTO.Login
public PhoneNumber phoneNumber { get; set; } = null!;
[MaxLength(1000)]
public string password { get; set; } = null!;
public string? password { get; set; }
}
}

View File

@ -56,6 +56,7 @@ namespace API
builder.Services.AddTransient<ImageService>();
builder.Services.AddTransient<PermissionService>();
builder.Services.AddTransient<SavedEventService>();
builder.Services.AddTransient<SignupService>();
builder.Services.AddTransient<UserService>(options =>
{
ILogger<UserService> logger = options.GetRequiredService<ILogger<UserService>>();
@ -76,6 +77,7 @@ namespace API
builder.Services.AddTransient<IPermissionAuthentication, PermissionAuthentication>();
builder.Services.AddTransient<ISavedEventAuthentication, SavedEventAuthentication>();
builder.Services.AddTransient<IUserAuthentication, UserAuthentication>();
builder.Services.AddTransient<ISignupAuthentication, SignupAuthentication>();
builder.Services.AddTransient<IHashingFactory, HashingFactory>();
@ -98,9 +100,17 @@ namespace API
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = 403;
return Task.CompletedTask;
};
});
// builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
// {
// options.Cookie.SameSite = SameSiteMode.None;
// options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
// });
builder.Services.AddLazyResolution();
@ -114,7 +124,7 @@ namespace API
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.None
MinimumSameSitePolicy = SameSiteMode.Strict
});
app.UseAuthorization();

View File

@ -11,5 +11,13 @@ namespace API.Services
public EventService(ILogger<EventService> logger, SASGContext context, IEventAuthentication auth) : base(logger, context, auth)
{
}
public bool? isSignedUp(User user, ulong eventId)
{
if (!_auth.canCheckSelfSignup(user))
return null;
return Context.Set<Signup>().Any(x => x.userId == user.id && x.eventId == eventId);
}
}
}

View File

@ -7,25 +7,20 @@ namespace API.Services
{
public class GrantManager : IGrantManager
{
private readonly SASGContext _context;
private ILogger<GrantManager> _logger;
private SASGContext _context;
public GrantManager(ILogger<GrantManager> logger, SASGContext context)
{
_logger = logger;
_context = context;
}
private IEnumerable<Grant> getGrant(Expression<Func<Grant, bool>> whereClause)
{
return _context.Set<Grant>().Where(whereClause);
}
public bool hasGrant(ulong permissionId, string grantName)
{
return getGrant(x => x.permissionId == permissionId && x.name.Equals(grantName)).Any();
}
public List<string> getValues(ulong permissionId, string grantName)
{
List<Grant> grants = getGrant(x => x.permissionId == permissionId && x.name.StartsWith(grantName + ".")).ToList();
@ -33,7 +28,7 @@ namespace API.Services
List<string> values = [];
foreach (Grant grant in grants)
{
string value = grant.name.Substring(grantName.Length);
string value = grant.name.Substring(grantName.Length + 1);
if (value.Contains('.'))
// Were not looking at a value and instead another grant
continue;
@ -81,5 +76,10 @@ namespace API.Services
return uLongValues;
}
private IEnumerable<Grant> getGrant(Expression<Func<Grant, bool>> whereClause)
{
return _context.Set<Grant>().Where(whereClause);
}
}
}

View File

@ -11,5 +11,13 @@ namespace API.Services
public GrantService(ILogger<GrantService> logger, SASGContext context, IGrantAuthentication auth) : base(logger, context, auth)
{
}
public IEnumerable<Grant>? getMine(User user)
{
if (!_auth.canGetMine(user))
return null;
return Context.Set<Grant>().Where(x => x.permissionId == user.permissionId);
}
}
}

View File

@ -1,5 +1,6 @@
using API.DTO.Base;
using API.DTO.Login;
using DAL.Models;
namespace API.Services.Interfaces
{
@ -7,6 +8,6 @@ namespace API.Services.Interfaces
{
UserDTO? authenticateUser(UserLoginDTO loginDTO);
UserDTO? registerUser(UserRegisterDTO registerDTO);
UserDTO? registerUser(UserRegisterDTO registerDTO, User? user = null, ulong? permissionId = null);
}
}

View File

@ -14,7 +14,7 @@ namespace API.Services
where TAudit : AuditModel<TModel>
where TDTO : IAdaptable<TModel>
{
private readonly TAuthentication _auth;
public readonly TAuthentication _auth;
private readonly ILogger<TLoggerCategory> _logger;
public readonly SASGContext Context;

View File

@ -0,0 +1,16 @@
using API.Authentication.Interfaces;
using API.DTO.Base.Update;
using DAL.Contexts;
using DAL.Models;
using DAL.Models.Audits;
namespace API.Services
{
public class SignupService : ServiceBase<SignupService, SignupDTO, Signup, AuditSignup, ISignupAuthentication>
{
public SignupService(ILogger<SignupService> logger, SASGContext context, ISignupAuthentication auth) : base(logger, context, auth)
{
}
}
}

View File

@ -54,7 +54,7 @@ namespace API.Services
return dto;
}
public UserDTO? registerUser(UserRegisterDTO registerDTO)
public UserDTO? registerUser(UserRegisterDTO registerDTO, User? user = null, ulong? permissionId = null)
{
if (_userService.getNoAuthentication(x =>
x.phoneNumber.Equals(registerDTO.phoneNumber) ||
@ -74,10 +74,13 @@ namespace API.Services
byte[] salt;
string hashedPassword = hashingAlgorithm.hash(registerDTO.password, out salt);
User user = _userService.add(registerDTO, hashedPassword, salt);
User? createdUser = _userService.add(registerDTO, hashedPassword, salt, user, permissionId);
if (createdUser == null)
return null;
UserDTO dto = new UserDTO();
dto.adaptFromModel(user);
dto.adaptFromModel(createdUser);
return dto;
}

View File

@ -17,10 +17,9 @@ namespace API.Services
_defaultUserPermission = defaultUserPermission;
}
public User add(UserRegisterDTO registerDTO, string hashedPassword, byte[] salt)
public User? add(UserRegisterDTO registerDTO, string hashedPassword, byte[] salt, User? user = null, ulong? permissionId = null)
{
Permission? defaultPermission = _permissionService.getNoAuthentication(_defaultUserPermission);
if (defaultPermission == null)
throw new InvalidOperationException("defaultUserPermission doesn't exist.");
@ -33,11 +32,25 @@ namespace API.Services
password = hashedPassword,
salt = salt,
permissionId = defaultPermission.id,
permissionId = permissionId ?? defaultPermission.id,
updated = DateTime.Now
};
if (permissionId != null && user != null)
{
model.permissionId = permissionId.Value;
model.updater = user.id;
UserDTO userDTO = new UserDTO();
userDTO.adaptFromModel(user);
if (!_auth.canAdd(userDTO, user))
return null;
Context.Add(model);
Context.SaveChanges();
return model;
}
Context.Add(model);
Context.SaveChanges();

View File

@ -24,6 +24,7 @@ namespace DAL.Contexts
public virtual DbSet<Image> images { get; set; }
public virtual DbSet<Permission> permissions { get; set; }
public virtual DbSet<SavedEvent> savedEvents { get; set; }
public virtual DbSet<Signup> signups { get; set; }
public virtual DbSet<User> users { get; set; }
public virtual DbSet<AuditColor> auditColors { get; set; }
public virtual DbSet<AuditEvent> auditEvents { get; set; }
@ -32,6 +33,7 @@ namespace DAL.Contexts
public virtual DbSet<AuditPermission> auditPermissions { get; set; }
public virtual DbSet<AuditSavedEvent> auditSavedEvents { get; set; }
public virtual DbSet<AuditUser> auditUsers { get; set; }
public virtual DbSet<AuditSignup> auditSignups { get; set; }
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
@ -98,6 +100,16 @@ namespace DAL.Contexts
.HasForeignKey(e => e.updater).HasConstraintName("events_users_id_fk");
entity.Property(e => e.hashingType).HasConversion<string>();
});
builder.Entity<Signup>(entity =>
{
entity.HasOne(e => e.eventIdRelation).WithMany()
.HasForeignKey(e => e.eventId).HasConstraintName("signup_events_id_fk");
entity.HasOne(e => e.userIdRelation).WithMany()
.HasForeignKey(e => e.userId).HasConstraintName("signup_users_id_fk");
entity.HasOne(e => e.updaterRelation).WithMany()
.HasForeignKey(e => e.updater).HasConstraintName("events_users_id_fk2");
});
}
}
}

View File

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace DAL.Models.Audits
{
[Table("audit_signup")]
[Index("id", Name = "audit_signup_originalId_index")]
public class AuditSignup : AuditModel<Signup>
{
[Column("eventId")]
public ulong eventId { get; set; }
[Column("userId")]
public ulong userId { get; set; }
public override Signup adaptToModel()
{
return new Signup
{
id = originalId,
eventId = eventId,
userId = userId,
updated = updated,
updater = updater
};
}
}
}

39
DAL/Models/Signup.cs Normal file
View File

@ -0,0 +1,39 @@
using DAL.Models.Audits;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace DAL.Models
{
[Table("signup")]
[Index("eventId", Name = "signup_event_id_fk")]
[Index("userId", Name = "signup_users_id_fk")]
[Index("updater", Name = "signup_users_id_fk_2")]
public class Signup : Model<Signup, AuditSignup>
{
[Column("eventId")]
public ulong eventId { get; set; }
[Column("userid")]
public ulong userId { get; set; }
public Event eventIdRelation { get; set; } = null!;
public User userIdRelation { get; set; } = null!;
public override AuditSignup adaptToAudit()
{
return new AuditSignup
{
id = id,
eventId = eventId,
userId = userId,
};
}
public override void updateModel(ref Signup dest)
{
dest.eventId = eventId;
dest.userId = userId;
}
}
}

View File

@ -48,6 +48,9 @@ VALUES ('api.event.delete.any', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.event.delete', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.grant.get.self', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.grant.get.all', 1, NOW(), 1);
@ -177,4 +180,28 @@ VALUES ('api.user.update.permission', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.user.delete.any', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.get.all', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.get.any', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.get', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.add', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.update.any', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.update', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.delete.any', 1, NOW(), 1);
INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
VALUES ('api.signup.delete', 1, NOW(), 1);
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADbContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F3bd4df5aff92cabbc4d630be64227073db1b8539b3a1e47786b4b189d7cdb7_003FDbContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=d51071ba_002D6946_002D464f_002Db1ff_002D8183035b48e5/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
&lt;TestAncestor&gt;
&lt;TestId&gt;NUnit3x::089ACCAD-8117-4C24-9429-56A394AC4734::net5.0::unitTests.Tests.Test1&lt;/TestId&gt;