#region License Information
/* HeuristicLab
* Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using HeuristicLab.Clients.Hive.WebJobManager.Services;
using HeuristicLab.Clients.Hive.WebJobManager.Services.Imports;
using HeuristicLab.Clients.Hive.WebJobManager.ViewModels.User;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace HeuristicLab.Clients.Hive.WebJobManager.Hubs
{
///
/// SignalR Hub that manages all resource management.
///
public class CalendarHub : Hub
{
private WebLoginService weblog;
private Guid userId;
private HiveAdminClientWeb adminClient;
private HiveServiceLocatorWeb servloc;
private AccessAdministrationClient accessClient;
///
/// Loads up the services for the client (Instance is only created upon a call from a client)
///
private void loader()
{
weblog = WebLoginService.Instance;
string uid = Context.QueryString["userid"];
if (uid == null || uid == "" || Guid.Parse(uid) == Guid.Empty)
{
userId = Guid.Empty;
}
else
{
userId = Guid.Parse(uid);
adminClient = weblog.getAdminClient(userId);
servloc = weblog.getServiceLocator(userId);
accessClient = weblog.getAccessAdminClient(userId);
}
}
///
/// Initial client request for all user, group and resource information
///
public void requestInfo()
{
loader();
adminClient.Refresh();
UserViewModel vm = new UserViewModel(accessClient, weblog.getCurrentUser(userId)).refreshAll();
var users = JsonConvert.SerializeObject(vm.users);
var groups = JsonConvert.SerializeObject(vm.ugroups);
var res = JsonConvert.SerializeObject(adminClient.Resources);
Clients.Caller.processData(res, users, groups);
}
///
/// Request for the downtimes of a specific resource
///
/// Resource ID
public void requestDownTime(string id)
{
loader();
adminClient.Refresh();
Guid t = Guid.Parse(id);
//Loads up the downtimes for the set resource ID
adminClient.DowntimeForResourceId = t;
adminClient.RefreshCalendar();
var down = JsonConvert.SerializeObject(adminClient.Downtimes);
Clients.Caller.processDowntime(id, down);
}
///
/// Request for permissions of a specific resource (refreshable by recall)
///
/// Resource ID
public void requestPermissions(string id)
{
loader();
Guid r = Guid.Parse(id);
var perm = servloc.CallHiveService(x => x.GetResourcePermissions(r));
Clients.Caller.processPermissions(id, JsonConvert.SerializeObject(perm));
}
///
/// Edit permissions for a resource
///
/// Permissions ID's
/// Resource ID
public void changePermissions(string[] perms, string idresource)
{
loader();
var res = Guid.Parse(idresource);
//Collect current permissions
var exist = servloc.CallHiveService(x => x.GetResourcePermissions(res));
//Separate list for new and to remove permissions
List newPerms = new List();
List revokePerms = new List();
for (var i = 0; i < perms.Length; i++)
{
var p = Guid.Parse(perms[i]);
var elemid = exist.FindIndex(x => x.GrantedUserId == p);
if (elemid != -1)
{//If it already exists => Scramble up Guid (checked further)
exist[elemid].GrantedUserId = Guid.Empty;
}
else
{//If it's not in the list, add to new permissions
newPerms.Add(p);
}
}
//Adds the new permissions to the resource
servloc.CallHiveService(x => x.GrantResourcePermissions(res, newPerms));
foreach (var ex in exist)
{//Checks for intact ID's and adds them to the revoke list
if(ex.GrantedUserId != Guid.Empty)
{
revokePerms.Add(ex.GrantedUserId);
}
}
//Revokes all permissions that were deselected by the user
servloc.CallHiveService(x => x.RevokeResourcePermissions(res, revokePerms));
//Live reload the view for the resource
requestPermissions(idresource);
}
///
/// Toggles the disposable setting for a resource
///
/// Resource ID
public void toggleDisposable(string id)
{
loader();
adminClient.Refresh();
Guid c = Guid.Parse(id);
var obj = adminClient.Resources.ToList().Find(x => x.Id == c);
//Toggle
((Slave)(obj)).IsDisposable = !((Slave)(obj)).IsDisposable;
adminClient.Store(obj, CancellationToken.None);
//Notify client of successful saving
Clients.Caller.processDispose( ((Slave)(obj)).IsDisposable);
}
///
/// Saves changes to a resource calendar
///
/// Resource id
/// To delete downtimes
/// New downtimes
/// Downtimes to update
/// Check if refresh should be sent (Save all current graph or Save current graph)
/// Check for last request (Save all)
public void saveCalendar(string id, string[] del, string[][] add, string[][] upd, bool fresh, bool last)
{
loader();
var calid = Guid.Parse(id);
//Load up calendar
adminClient.Refresh();
adminClient.DowntimeForResourceId = calid;
adminClient.RefreshCalendar();
var downlist = adminClient.Downtimes.ToList();
foreach(var s in del)
{//Deletes downtimes
var gu = Guid.Parse(s);
var el = downlist.Find(x => x.Id == gu);
adminClient.Delete(el);
}
foreach (var s in add)
{//Adds new downtimes
//init
var obj = new Downtime();
obj.Id = Guid.Empty;
if (s[0] == "Unavailable")
obj.DowntimeType = DowntimeType.Offline;
else
obj.DowntimeType = DowntimeType.Shutdown;
obj.StartDate = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[1]));
obj.EndDate = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[2]));
if (s[3] == "true")
obj.AllDayEvent = true;
else
obj.AllDayEvent = false;
obj.ResourceId = Guid.Parse(s[4]);
//Recurrency check
if (s[5] == "true")
{//Recurrency set
obj.Recurring = true;
if (s[6] == "0")
{//new Recur
var dayarr = s[9].Split(',');
var start = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[7]));
var end = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[8]));
loopAddDowns(start, end, dayarr, obj);//Loop creation of recurrency. Start to end date
}
else
{//Existing recurrency (only edits current element, client handles the creation of the other events)
obj.RecurringId = Guid.Parse(s[6]);
adminClient.Store(obj, CancellationToken.None);
}
}
else { //No recurrency
obj.Recurring = false;
adminClient.Store(obj, CancellationToken.None);
}
}
foreach(var s in upd)
{//Update existing downtime
var obj = downlist.Find(x => x.Id == Guid.Parse(s[0]));
if (s[1] == "Unavailable")
obj.DowntimeType = DowntimeType.Offline;
else
obj.DowntimeType = DowntimeType.Shutdown;
obj.StartDate = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[2]));
obj.EndDate = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[3]));
if (s[4] == "true")
obj.AllDayEvent = true;
else
obj.AllDayEvent = false;
if (s[5] == "true" && !obj.Recurring)
{//Recurrence set
obj.Recurring = true;
if (s[6] == "00000000-0000-0000-0000-000000000000")
{//Creates new recurrence
var dayarr = s[9].Split(',');
var start = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[7]));
var end = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[8]));
loopAddDowns(start, end, dayarr, obj);
adminClient.Delete(obj);
//Delete needed to prevent doubles in the creation of the recurrency
//Why: event could be on not included day of the week => loop cannot find that.
}
else
{
obj.RecurringId = Guid.Parse(s[6]);
//adminClient.Store(obj, CancellationToken.None); //Throws error
}
}
else
{
//adminClient.Store(obj, CancellationToken.None); //Throws error
}
}
if( last)
{//Last element from save all => Notify client
Clients.Caller.savingAllDone();
}
else if (fresh)
{//Refresh for graph needed
Clients.Caller.savingCurrentDone();
}
}
///
/// Creates downtimes for a new recurrency
///
/// Start date
/// End date
/// Boolean day array (sun = 0,...)
/// Downtime to recur
private void loopAddDowns(DateTime start, DateTime end, string[] dayarr, Downtime obj)
{
var rid = Guid.NewGuid();
while (start < end)
{
if (dayarr[(int)(start.DayOfWeek)] == "true")
{//Check for day of the week
//Set setting for the downtime to add
var temp = new Downtime();
temp.StartDate = start.AddHours(obj.StartDate.Hour - start.Hour)
.AddMinutes(obj.StartDate.Minute - start.Minute);
temp.EndDate = start.AddHours(obj.EndDate.Hour - start.Hour)
.AddMinutes(obj.EndDate.Minute - start.Minute);
temp.Id = Guid.Empty;
temp.DowntimeType = obj.DowntimeType;
temp.AllDayEvent = obj.AllDayEvent;
temp.ResourceId = obj.ResourceId;
temp.Recurring = obj.Recurring;
temp.RecurringId = rid;
adminClient.Store(temp, CancellationToken.None);
}
start = start.AddDays(1);
}
}
}
}