• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

b1f6c1c4 / ProfessionalAccounting / 327

28 Apr 2025 05:37PM UTC coverage: 51.346% (-3.0%) from 54.325%
327

push

appveyor

b1f6c1c4
ci buildx

6620 of 12893 relevant lines covered (51.35%)

126.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

12.73
/AccountingServer.Shell/Session.cs
1
/* Copyright (C) 2025 b1f6c1c4
2
 *
3
 * This file is part of ProfessionalAccounting.
4
 *
5
 * ProfessionalAccounting is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU Affero General Public License as
7
 * published by the Free Software Foundation, version 3.
8
 *
9
 * ProfessionalAccounting is distributed in the hope that it will be useful, but
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License
12
 * for more details.
13
 *
14
 * You should have received a copy of the GNU Affero General Public License
15
 * along with ProfessionalAccounting.  If not, see
16
 * <https://www.gnu.org/licenses/>.
17
 */
18

19
using System;
20
using System.Collections.Generic;
21
using System.Security.Cryptography;
22
using System.Threading;
23
using AccountingServer.BLL;
24
using AccountingServer.BLL.Util;
25
using AccountingServer.Entities;
26

27
namespace AccountingServer.Shell;
28

29
public class Session
30
{
31
    public string Key { get; internal set; }
32
    public WebAuthn Authn { get; internal set; }
33
    public DateTime CreatedAt { get; internal set; }
34
    public DateTime ExpiresAt { get; internal set; }
35
    public DateTime MaxExpiresAt { get; internal set; }
36

37
    internal void Extend()
38
    {
×
39
        ExpiresAt = DateTime.UtcNow.Add(AuthnManager.Config.SessionExpire);
×
40
        if (ExpiresAt > MaxExpiresAt)
×
41
            ExpiresAt = MaxExpiresAt;
×
42
    }
×
43
};
44

45
public class SessionManager : IDisposable
46
{
47
    private readonly Dictionary<string, Session> m_Sessions;
48
    private readonly Timer m_Cleanup;
49
    private readonly object m_Lock;
50
    private readonly DbSession m_Db;
51

52
    public SessionManager(DbSession db)
10✔
53
    {
10✔
54
        m_Sessions = new();
10✔
55
        m_Cleanup = new(CleanupSessions, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
10✔
56
        m_Lock = new();
10✔
57
        m_Db = db;
10✔
58
    }
10✔
59

60
    public void Dispose()
61
        => m_Cleanup?.Dispose();
×
62

63
    public Session CreateSession(WebAuthn aid)
64
    {
×
65
        var key = Convert.ToBase64String(RandomNumberGenerator.GetBytes(48))
×
66
                .Replace('+', '-')
67
                .Replace('/', '_')
68
                .Replace("=", "");
69
        var now = DateTime.UtcNow;
×
70
        var session = new Session
×
71
            {
72
                Key = key,
73
                Authn = aid,
74
                CreatedAt = now,
75
                ExpiresAt = now.Add(AuthnManager.Config.SessionExpire),
76
                MaxExpiresAt = now.Add(AuthnManager.Config.SessionMax),
77
            };
78

79
        lock (m_Lock)
×
80
            m_Sessions[key] = session;
×
81

82
        Console.WriteLine($"{now:s}: session created for {aid.IdentityName.AsId()} / {aid.StringID}");
×
83

84
        return session;
×
85
    }
×
86

87
    public Session AccessSession(string key)
88
    {
×
89
        if (key == null)
×
90
            return null;
×
91

92
        Session session;
93
        lock (m_Lock)
×
94
            if (!m_Sessions.TryGetValue(key, out session))
×
95
                return null;
×
96

97
        var now = DateTime.UtcNow;
×
98
        if (now <= session.CreatedAt)
×
99
            return null;
×
100

101
        if (now <= session.ExpiresAt && now <= session.MaxExpiresAt)
×
102
            return session;
×
103

104
        lock (m_Lock)
×
105
            m_Sessions.Remove(key);
×
106

107
        return null;
×
108
    }
×
109

110
    public void DiscardSession(Session session)
111
    {
×
112
        lock (m_Lock)
×
113
            m_Sessions.Remove(session.Key);
×
114
    }
×
115

116
    public void CleanupSessions(object _)
117
    {
×
118
        lock (m_Lock)
×
119
        {
×
120
            var now = DateTime.UtcNow;
×
121
            var lst = new List<string>();
×
122

123
            foreach (var kvp in m_Sessions)
×
124
                if (now >= kvp.Value.ExpiresAt)
×
125
                    lst.Add(kvp.Key);
×
126

127
            if (lst.Count > 0)
×
128
                Console.WriteLine($"{now:s}: cleaning up {lst.Count} stale sessions, {m_Sessions.Count - lst.Count} active");
×
129

130
            foreach (var key in lst)
×
131
                m_Sessions.Remove(key);
×
132
        }
×
133
    }
×
134
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc