226 lines
7.9 KiB
C#
226 lines
7.9 KiB
C#
using EnVisage.Code;
|
|
using EnVisage.Properties;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Timers;
|
|
using System.Web;
|
|
|
|
namespace EnVisage.App_Start
|
|
{
|
|
public class LockerResponse
|
|
{
|
|
public enum ResponseCode
|
|
{
|
|
OK = 0,
|
|
ObjectLocked = 1,
|
|
ObjectExpired = 2,
|
|
}
|
|
public ResponseCode Code { get; set; }
|
|
public bool Status { get; set; }
|
|
public string LockedBy { get; set; }
|
|
public string EntityTitle { get; set; }
|
|
|
|
public LockerResponse()
|
|
{
|
|
Code = ResponseCode.OK;
|
|
}
|
|
}
|
|
public static class ContentLocker
|
|
{
|
|
static readonly Dictionary<string, string> EntityTitles = new Dictionary<string, string>
|
|
{
|
|
{"SystemSettings", "System Settings"},
|
|
{"Clients", "Client"},
|
|
{"CreditDepartment", "Credit Department"},
|
|
{"ExpenditureCategory", "Expenditure Category"},
|
|
{"GLAccount", "GL Account"},
|
|
{"Trainings", "Training"},
|
|
{"Vacations", "Vacation"},
|
|
{"ScenarioGroup", "Scenario Group"},
|
|
{"ExpenditureCategoryRate", "Rate"},
|
|
{"Project Statuses", "Project Status"},
|
|
{"Types", "Type"},
|
|
{"UnitOfMeasure", "Unit Of Measure"},
|
|
{"TrainingTypes", "Training Type"},
|
|
{"PeopleResource", "People Resource"}
|
|
};
|
|
static Timer timer;
|
|
|
|
static Dictionary<string, Dictionary<string, LockedElement>> lockersList;
|
|
|
|
static ContentLocker()
|
|
{
|
|
lockersList = new Dictionary<string, Dictionary<string, LockedElement>>();
|
|
|
|
timer = new Timer(Settings.Default.CheckInterval);
|
|
|
|
timer.Elapsed += checkDeadLocks;
|
|
|
|
if (!timer.Enabled)
|
|
timer.Start();
|
|
|
|
}
|
|
|
|
static void checkDeadLocks(object sender, ElapsedEventArgs e)
|
|
{
|
|
foreach (var lockedElement in lockersList)
|
|
{
|
|
unlockDead(lockedElement.Value);
|
|
}
|
|
}
|
|
|
|
static void unlockDead(Dictionary<string, LockedElement> lockedList)
|
|
{
|
|
List<string> unlockItems = new List<string>();
|
|
|
|
foreach (var lockedElement in lockedList)
|
|
{
|
|
if (lockedElement.Value.GetLockInterval() >= Settings.Default.UnlockInterval)
|
|
{
|
|
unlockItems.Add(lockedElement.Key);
|
|
}
|
|
}
|
|
|
|
foreach (var unlockId in unlockItems)
|
|
{
|
|
lockedList.Remove(unlockId);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an object lock to the dictionary (if possible) and returns result of this operation.
|
|
/// </summary>
|
|
/// <param name="tableId">Unique identifier of the database table in which we store the locked object.</param>
|
|
/// <param name="fieldId">Unique identifier of the locked object.</param>
|
|
/// <param name="owner">Username of the owner of the lock.</param>
|
|
/// <param name="timestamp">A timestamp of the object to check that system works with actual data.</param>
|
|
/// <returns>An instance of <see cref="LockerResponse"/> with info about operation result.</returns>
|
|
public static LockerResponse AddLock(String tableId, String fieldId, string owner, string timestamp)
|
|
{
|
|
// add a table to the main dictionary if there is no such table yet
|
|
if (!lockersList.ContainsKey(tableId))
|
|
{
|
|
lockersList.Add(tableId, new Dictionary<string, LockedElement>());
|
|
}
|
|
// if there is a lock on the specified object but made by another user then return failed result with info about locked object
|
|
if (lockersList[tableId].ContainsKey(fieldId) && lockersList[tableId][fieldId].Owner != owner)
|
|
{
|
|
return new LockerResponse { Status = false, Code=LockerResponse.ResponseCode.ObjectLocked, LockedBy = lockersList[tableId][fieldId].Owner, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
// if there is a lock on the specified object made by current user then do not add lock and return successfull result
|
|
if (lockersList[tableId].ContainsKey(fieldId) && lockersList[tableId][fieldId].Owner == owner)
|
|
{
|
|
return new LockerResponse { Status = true, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
// if there is no lock on the specified object but it has been updated since last access then return failed result with info about modified object
|
|
if (!IsObjectValid(tableId, fieldId, timestamp))
|
|
{
|
|
return new LockerResponse { Status = false, Code = LockerResponse.ResponseCode.ObjectExpired, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
// add a lock to the specified object by current user
|
|
lockersList[tableId].Add(fieldId, new LockedElement(owner));
|
|
// return successfull result
|
|
return new LockerResponse { Status = true, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
|
|
public static bool RemoveLock(String tableId, String fieldId, string owner)
|
|
{
|
|
|
|
if (!lockersList.ContainsKey(tableId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!lockersList[tableId].ContainsKey(fieldId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
if (lockersList[tableId][fieldId].Owner == owner)
|
|
{
|
|
lockersList[tableId].Remove(fieldId);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool UpdateLock(String tableId, String fieldId, string owner)
|
|
{
|
|
if (!lockersList.ContainsKey(tableId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!lockersList[tableId].ContainsKey(fieldId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (lockersList[tableId][fieldId].Owner == owner)
|
|
{
|
|
lockersList[tableId][fieldId].UpdateLock();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static string[] getLockList(String tableId)
|
|
{
|
|
if (lockersList.ContainsKey(tableId))
|
|
{
|
|
List<string> lockItems = new List<string>();
|
|
foreach (var lockedElement in lockersList)
|
|
{
|
|
lockItems.Add(lockedElement.Key);
|
|
}
|
|
return lockItems.ToArray();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static LockerResponse IsLocked(String tableId, String fieldId, string owner)
|
|
{
|
|
if (lockersList.ContainsKey(tableId) && lockersList[tableId].ContainsKey(fieldId) && lockersList[tableId][fieldId].Owner != owner)
|
|
{
|
|
return new LockerResponse { Status = true, Code = LockerResponse.ResponseCode.ObjectLocked, LockedBy = lockersList[tableId][fieldId].Owner, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
return new LockerResponse { Status = false, EntityTitle = GetLockedEntityTitle(tableId) };
|
|
}
|
|
|
|
public static bool IsLock(String tableId, String fieldId, string owner)
|
|
{
|
|
return IsLocked(tableId, fieldId, owner).Status;
|
|
}
|
|
|
|
public static string GetLockedEntityTitle(string tableId)
|
|
{
|
|
if (EntityTitles.ContainsKey(tableId))
|
|
return EntityTitles[tableId];
|
|
return tableId;
|
|
}
|
|
|
|
private static bool IsObjectValid(string tableId, string fieldId, string timestamp)
|
|
{
|
|
var projectValid = true;
|
|
if (string.IsNullOrWhiteSpace(timestamp))
|
|
return projectValid;
|
|
using (var dbContext = new EnVisageEntities())
|
|
{
|
|
switch(tableId)
|
|
{
|
|
case "Project":
|
|
var stamp = timestamp.StringToByteArray();
|
|
var id = Guid.Parse(fieldId);
|
|
projectValid = dbContext.Projects.Count(t => t.Id == id && t.DateEdited == stamp) > 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return projectValid;
|
|
}
|
|
}
|
|
} |