Merge pull request #130 from lukeIam/develop
[Server] multiple logins per user + mp3 stream
This commit is contained in:
commit
4d494fe185
9 files changed
+149
-11
No files matched your search
@@ -59,6 +59,8 @@ namespace ServerLib
|
|||||||
public static GetAllSongsDelegate GetAllSongs { internal get; set; }
|
public static GetAllSongsDelegate GetAllSongs { internal get; set; }
|
||||||
|
|
||||||
public static GetCurrentSongIdDelegate GetCurrentSongId { internal get; set; }
|
public static GetCurrentSongIdDelegate GetCurrentSongId { internal get; set; }
|
||||||
|
|
||||||
|
public static GetMp3PathDelegate GetMp3Path { internal get; set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region playlist
|
#region playlist
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ namespace ServerLib
|
|||||||
{
|
{
|
||||||
sessionKey = Guid.Parse(sessionHeader);
|
sessionKey = Guid.Parse(sessionHeader);
|
||||||
}
|
}
|
||||||
catch (Exception) {}
|
catch (Exception)
|
||||||
|
{ }
|
||||||
|
CSessionControl.ResetSessionTimeout(sessionKey);
|
||||||
return sessionKey;
|
return sessionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +146,7 @@ namespace ServerLib
|
|||||||
public SProfileData[] GetProfileList()
|
public SProfileData[] GetProfileList()
|
||||||
{
|
{
|
||||||
if (CServer.GetProfileList == null)
|
if (CServer.GetProfileList == null)
|
||||||
return new SProfileData[] {};
|
return new SProfileData[] { };
|
||||||
return CServer.GetProfileList();
|
return CServer.GetProfileList();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -172,6 +174,12 @@ namespace ServerLib
|
|||||||
return sessionId;
|
return sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Logout()
|
||||||
|
{
|
||||||
|
Guid sessionKey = _GetSession();
|
||||||
|
CSessionControl.InvalidateSessions(sessionKey);
|
||||||
|
}
|
||||||
|
|
||||||
public Stream Index()
|
public Stream Index()
|
||||||
{
|
{
|
||||||
if (WebOperationContext.Current != null)
|
if (WebOperationContext.Current != null)
|
||||||
@@ -289,6 +297,7 @@ namespace ServerLib
|
|||||||
|
|
||||||
public bool IsServerOnline()
|
public bool IsServerOnline()
|
||||||
{
|
{
|
||||||
|
_GetSession();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -308,6 +317,55 @@ namespace ServerLib
|
|||||||
{
|
{
|
||||||
return CServer.GetAllSongs();
|
return CServer.GetAllSongs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream GetMp3File(int songId)
|
||||||
|
{
|
||||||
|
if (WebOperationContext.Current != null)
|
||||||
|
{
|
||||||
|
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow;
|
||||||
|
WebOperationContext.Current.OutgoingResponse.Headers.Add(
|
||||||
|
HttpResponseHeader.Expires,
|
||||||
|
DateTime.UtcNow.AddYears(1).ToString("r"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String path = CServer.GetMp3Path(songId);
|
||||||
|
path = path.Replace("..", "");
|
||||||
|
|
||||||
|
|
||||||
|
if (!File.Exists(path)
|
||||||
|
|| !(path.EndsWith(".mp3", StringComparison.InvariantCulture)
|
||||||
|
|| path.EndsWith(".ogg", StringComparison.InvariantCulture)
|
||||||
|
|| path.EndsWith(".wav", StringComparison.InvariantCulture)
|
||||||
|
|| path.EndsWith(".webm", StringComparison.InvariantCulture)))
|
||||||
|
{
|
||||||
|
if (WebOperationContext.Current != null)
|
||||||
|
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebOperationContext.Current != null)
|
||||||
|
{
|
||||||
|
if (path.EndsWith(".mp3", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
WebOperationContext.Current.OutgoingResponse.ContentType = "audio/mpeg";
|
||||||
|
}
|
||||||
|
else if (path.EndsWith(".ogg", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
WebOperationContext.Current.OutgoingResponse.ContentType = "audio/ogg";
|
||||||
|
}
|
||||||
|
else if (path.EndsWith(".wav", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
WebOperationContext.Current.OutgoingResponse.ContentType = "audio/wav";
|
||||||
|
}
|
||||||
|
else if (path.EndsWith(".webm", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
WebOperationContext.Current.OutgoingResponse.ContentType = "audio/webm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.OpenRead(path);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region playlist
|
#region playlist
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ namespace ServerLib
|
|||||||
|
|
||||||
public delegate int GetCurrentSongIdDelegate();
|
public delegate int GetCurrentSongIdDelegate();
|
||||||
|
|
||||||
|
public delegate string GetMp3PathDelegate(int songId);
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
public struct SSongInfo
|
public struct SSongInfo
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ namespace ServerLib
|
|||||||
UriTemplate = "/login?username={username}&password={password}")]
|
UriTemplate = "/login?username={username}&password={password}")]
|
||||||
Guid Login(string username, string password);
|
Guid Login(string username, string password);
|
||||||
|
|
||||||
|
[OperationContract, WebInvoke(Method = "GET",
|
||||||
|
ResponseFormat = WebMessageFormat.Json,
|
||||||
|
UriTemplate = "/logout")]
|
||||||
|
void Logout();
|
||||||
|
|
||||||
[OperationContract, WebInvoke(Method = "GET",
|
[OperationContract, WebInvoke(Method = "GET",
|
||||||
ResponseFormat = WebMessageFormat.Json,
|
ResponseFormat = WebMessageFormat.Json,
|
||||||
UriTemplate = "")]
|
UriTemplate = "")]
|
||||||
@@ -127,6 +132,11 @@ namespace ServerLib
|
|||||||
ResponseFormat = WebMessageFormat.Json,
|
ResponseFormat = WebMessageFormat.Json,
|
||||||
UriTemplate = "/getAllSongs")]
|
UriTemplate = "/getAllSongs")]
|
||||||
SSongInfo[] GetAllSongs();
|
SSongInfo[] GetAllSongs();
|
||||||
|
|
||||||
|
[OperationContract, WebInvoke(Method = "GET",
|
||||||
|
ResponseFormat = WebMessageFormat.Json,
|
||||||
|
UriTemplate = "/getMp3?songId={songId}")]
|
||||||
|
Stream GetMp3File(int songId);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region playlist
|
#region playlist
|
||||||
|
|||||||
@@ -38,12 +38,20 @@ namespace ServerLib
|
|||||||
{
|
{
|
||||||
get { return _Roles; }
|
get { return _Roles; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTime _LastSeen;
|
||||||
|
public DateTime LastSeen
|
||||||
|
{
|
||||||
|
get { return _LastSeen; }
|
||||||
|
internal set { _LastSeen = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public CSession(Guid id, int profileId, EUserRoles roles)
|
public CSession(Guid id, int profileId, EUserRoles roles)
|
||||||
{
|
{
|
||||||
_ID = id;
|
_ID = id;
|
||||||
_ProfileId = profileId;
|
_ProfileId = profileId;
|
||||||
_Roles = roles;
|
_Roles = roles;
|
||||||
|
_LastSeen = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,12 +18,35 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
namespace ServerLib
|
namespace ServerLib
|
||||||
{
|
{
|
||||||
static class CSessionControl
|
static class CSessionControl
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Guid, CSession> _ActiveSessions = new Dictionary<Guid, CSession>();
|
private static readonly Dictionary<Guid, CSession> _ActiveSessions;
|
||||||
|
private const int _UserTimeoutCheckIntervall = 120000;
|
||||||
|
private const int _UserTimeout = 120000;
|
||||||
|
|
||||||
|
static CSessionControl()
|
||||||
|
{
|
||||||
|
_ActiveSessions = new Dictionary<Guid, CSession>();
|
||||||
|
Timer timer = new Timer(_UserTimeoutCheckIntervall) {AutoReset = true, Enabled = true};
|
||||||
|
timer.Elapsed += _CheckForUserTimeouts;
|
||||||
|
timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _CheckForUserTimeouts(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
var sessionIdsToRemove = _ActiveSessions.Where(pair => (DateTime.Now-pair.Value.LastSeen).TotalMilliseconds > _UserTimeout)
|
||||||
|
.Select(pair => pair.Key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var sessionToRemove in sessionIdsToRemove)
|
||||||
|
{
|
||||||
|
InvalidateSessions(sessionToRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Guid OpenSession(string userName, string password)
|
public static Guid OpenSession(string userName, string password)
|
||||||
{
|
{
|
||||||
@@ -34,7 +57,7 @@ namespace ServerLib
|
|||||||
int id = _GetProfileIdFormUsername(userName);
|
int id = _GetProfileIdFormUsername(userName);
|
||||||
EUserRoles roles = _GetUserRoles(id);
|
EUserRoles roles = _GetUserRoles(id);
|
||||||
CSession session = new CSession(newId, id, roles);
|
CSession session = new CSession(newId, id, roles);
|
||||||
InvalidateSessions(id);
|
//InvalidateSessions(id);
|
||||||
_ActiveSessions.Add(newId, session);
|
_ActiveSessions.Add(newId, session);
|
||||||
|
|
||||||
return newId;
|
return newId;
|
||||||
@@ -63,6 +86,14 @@ namespace ServerLib
|
|||||||
_ActiveSessions.Remove(s.Key);
|
_ActiveSessions.Remove(s.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void InvalidateSessions(Guid sessionId)
|
||||||
|
{
|
||||||
|
if (_ActiveSessions.ContainsKey(sessionId))
|
||||||
|
{
|
||||||
|
_ActiveSessions.Remove(sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static bool RequestRight(Guid sessionId, EUserRights requestedRight)
|
internal static bool RequestRight(Guid sessionId, EUserRights requestedRight)
|
||||||
{
|
{
|
||||||
return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles)
|
return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles)
|
||||||
@@ -75,5 +106,14 @@ namespace ServerLib
|
|||||||
return -1;
|
return -1;
|
||||||
return _ActiveSessions[sessionId].ProfileId;
|
return _ActiveSessions[sessionId].ProfileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void ResetSessionTimeout(Guid sessionId)
|
||||||
|
{
|
||||||
|
CSession value;
|
||||||
|
if (_ActiveSessions.TryGetValue(sessionId, out value))
|
||||||
|
{
|
||||||
|
value.LastSeen = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,6 +73,7 @@ namespace Vocaluxe.Base.Server
|
|||||||
CServer.GetSong = _GetSong;
|
CServer.GetSong = _GetSong;
|
||||||
CServer.GetAllSongs = _GetAllSongs;
|
CServer.GetAllSongs = _GetAllSongs;
|
||||||
CServer.GetCurrentSongId = _GetCurrentSongId;
|
CServer.GetCurrentSongId = _GetCurrentSongId;
|
||||||
|
CServer.GetMp3Path = _GetMp3Path;
|
||||||
CServer.ValidatePassword = _ValidatePassword;
|
CServer.ValidatePassword = _ValidatePassword;
|
||||||
CServer.GetUserRole = _GetUserRole;
|
CServer.GetUserRole = _GetUserRole;
|
||||||
CServer.SetUserRole = _SetUserRole;
|
CServer.SetUserRole = _SetUserRole;
|
||||||
@@ -463,6 +464,11 @@ namespace Vocaluxe.Base.Server
|
|||||||
return (from s in songs
|
return (from s in songs
|
||||||
select _GetSongInfo(s, false)).ToArray<SSongInfo>();
|
select _GetSongInfo(s, false)).ToArray<SSongInfo>();
|
||||||
}
|
}
|
||||||
|
private static string _GetMp3Path(int songId)
|
||||||
|
{
|
||||||
|
CSong song = CSongs.GetSong(songId);
|
||||||
|
return song.GetMP3();
|
||||||
|
}
|
||||||
|
|
||||||
private static int _GetCurrentSongId()
|
private static int _GetCurrentSongId()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -231,6 +231,7 @@
|
|||||||
<div id="displaySongLinks">
|
<div id="displaySongLinks">
|
||||||
<img class="cursorStyleClickable" id="displaySongAddPlaylist" src="img/addPlaylist.png" />
|
<img class="cursorStyleClickable" id="displaySongAddPlaylist" src="img/addPlaylist.png" />
|
||||||
<br />
|
<br />
|
||||||
|
<audio controls id="displaySongPlayer" preload="none"></audio>
|
||||||
<br />
|
<br />
|
||||||
<img class="cursorStyleClickable" id="displaySongLinkYoutube" src="img/youtube.png" />
|
<img class="cursorStyleClickable" id="displaySongLinkYoutube" src="img/youtube.png" />
|
||||||
<img class="cursorStyleClickable" id="displaySongLinkSpotify" src="img/spotify.png" />
|
<img class="cursorStyleClickable" id="displaySongLinkSpotify" src="img/spotify.png" />
|
||||||
|
|||||||
@@ -1066,6 +1066,13 @@
|
|||||||
|
|
||||||
$('#displaySongIsDuet').text(result.IsDuet ? "Yes" : "No");
|
$('#displaySongIsDuet').text(result.IsDuet ? "Yes" : "No");
|
||||||
|
|
||||||
|
if (result.SongId >= 0) {
|
||||||
|
$('#displaySongPlayer').show()[0].src = "getMp3?songId=" + result.SongId;
|
||||||
|
} else {
|
||||||
|
$('#displaySongPlayer').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (result.Title != null || result.Artist != null) {
|
if (result.Title != null || result.Artist != null) {
|
||||||
$('#displaySongLinks').show();
|
$('#displaySongLinks').show();
|
||||||
|
|
||||||
@@ -1405,16 +1412,20 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.logout = function () {
|
this.logout = function () {
|
||||||
t.ownProfileId = -1;
|
request({
|
||||||
|
url: "logout"
|
||||||
|
}, "noOverlay").always(function () {
|
||||||
|
t.ownProfileId = -1;
|
||||||
|
|
||||||
t.sessionId = "";
|
t.sessionId = "";
|
||||||
|
|
||||||
pageHandler.reset();
|
pageHandler.reset();
|
||||||
|
|
||||||
if (window.localStorage) {
|
if (window.localStorage) {
|
||||||
window.localStorage.setItem("VocaluxeSessionKey", "");
|
window.localStorage.setItem("VocaluxeSessionKey", "");
|
||||||
}
|
}
|
||||||
$.mobile.changePage("#login", { transition: "slidefade" });
|
$.mobile.changePage("#login", { transition: "slidefade" });
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user