Skip to content

Commit aa08d21

Browse files
Merge pull request #66 from nullinside-development-group/feature/desktop
feat: using database lock to protect bot api token
2 parents 55f80e6 + 5f0811e commit aa08d21

File tree

9 files changed

+491
-30
lines changed

9 files changed

+491
-30
lines changed

src/Nullinside.Api.Common/Nullinside.Api.Common.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
</PropertyGroup>
1717

1818
<ItemGroup>
19-
<PackageReference Include="log4net" Version="2.0.17" />
19+
<PackageReference Include="log4net" Version="2.0.17"/>
2020
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1"/>
2121
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
22-
<PackageReference Include="SSH.NET" Version="2024.2.0" />
22+
<PackageReference Include="SSH.NET" Version="2024.2.0"/>
2323
<PackageReference Include="TwitchLib.Api" Version="3.9.0"/>
2424
<PackageReference Include="TwitchLib.Client" Version="3.3.1"/>
2525
</ItemGroup>

src/Nullinside.Api.Common/Twitch/ITwitchApiProxy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public interface ITwitchApiProxy {
1414
/// The Twitch access token. These are the credentials used for all requests.
1515
/// </summary>
1616
TwitchAccessToken? OAuth { get; set; }
17-
17+
1818
/// <summary>
1919
/// The Twitch app configuration. These are used for all requests.
2020
/// </summary>

src/Nullinside.Api.Common/Twitch/TwitchApiProxy.cs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class TwitchApiProxy : ITwitchApiProxy {
3333
/// Initializes a new instance of the <see cref="TwitchApiProxy" /> class.
3434
/// </summary>
3535
public TwitchApiProxy() {
36-
TwitchAppConfig = new() {
36+
TwitchAppConfig = new TwitchAppConfig {
3737
ClientId = Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_ID"),
3838
ClientSecret = Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_SECRET"),
3939
ClientRedirect = Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_REDIRECT")
@@ -46,21 +46,27 @@ public TwitchApiProxy() {
4646
/// <param name="token">The access token.</param>
4747
/// <param name="refreshToken">The refresh token.</param>
4848
/// <param name="tokenExpires">When the token expires (utc).</param>
49-
/// <param name="clientId">The client id of the registered twitch app, uses environment variable
50-
/// "TWITCH_BOT_CLIENT_ID" when null.</param>
51-
/// <param name="clientSecret">The client secret of the registered twitch app, uses environment variable
52-
/// "TWITCH_BOT_CLIENT_SECRET" when null.</param>
53-
/// <param name="clientRedirect">The url to redirect to from the registered twitch app, uses environment variable
54-
/// "TWITCH_BOT_CLIENT_REDIRECT" when null.</param>
55-
public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, string? clientId = null,
49+
/// <param name="clientId">
50+
/// The client id of the registered twitch app, uses environment variable
51+
/// "TWITCH_BOT_CLIENT_ID" when null.
52+
/// </param>
53+
/// <param name="clientSecret">
54+
/// The client secret of the registered twitch app, uses environment variable
55+
/// "TWITCH_BOT_CLIENT_SECRET" when null.
56+
/// </param>
57+
/// <param name="clientRedirect">
58+
/// The url to redirect to from the registered twitch app, uses environment variable
59+
/// "TWITCH_BOT_CLIENT_REDIRECT" when null.
60+
/// </param>
61+
public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, string? clientId = null,
5662
string? clientSecret = null, string? clientRedirect = null) {
5763
OAuth = new TwitchAccessToken {
5864
AccessToken = token,
5965
RefreshToken = refreshToken,
6066
ExpiresUtc = tokenExpires
6167
};
62-
63-
TwitchAppConfig = new() {
68+
69+
TwitchAppConfig = new TwitchAppConfig {
6470
ClientId = clientId ?? Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_ID"),
6571
ClientSecret = clientSecret ?? Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_SECRET"),
6672
ClientRedirect = clientRedirect ?? Environment.GetEnvironmentVariable("TWITCH_BOT_CLIENT_REDIRECT")
@@ -74,14 +80,14 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires,
7480

7581
/// <inheritdoc />
7682
public virtual TwitchAccessToken? OAuth { get; set; }
77-
83+
7884
/// <inheritdoc />
7985
public virtual TwitchAppConfig? TwitchAppConfig { get; set; }
8086

8187
/// <inheritdoc />
8288
public virtual async Task<TwitchAccessToken?> CreateAccessToken(string code, CancellationToken token = new()) {
8389
ITwitchAPI api = GetApi();
84-
AuthCodeResponse? response = await api.Auth.GetAccessTokenFromCodeAsync(code, TwitchAppConfig?.ClientSecret,
90+
AuthCodeResponse? response = await api.Auth.GetAccessTokenFromCodeAsync(code, TwitchAppConfig?.ClientSecret,
8591
TwitchAppConfig?.ClientRedirect);
8692
if (null == response) {
8793
return null;
@@ -101,7 +107,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires,
101107
if (string.IsNullOrWhiteSpace(TwitchAppConfig?.ClientSecret) || string.IsNullOrWhiteSpace(TwitchAppConfig?.ClientId)) {
102108
return null;
103109
}
104-
110+
105111
ITwitchAPI api = GetApi();
106112
RefreshResponse? response = await api.Auth.RefreshAuthTokenAsync(OAuth?.RefreshToken, TwitchAppConfig?.ClientSecret, TwitchAppConfig?.ClientId);
107113
if (null == response) {
@@ -145,7 +151,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires,
145151
}
146152

147153
/// <inheritdoc />
148-
public virtual async Task<string?> GetUserEmail(CancellationToken token = new()) {
154+
public virtual async Task<string?> GetUserEmail(CancellationToken token = new()) {
149155
return await Retry.Execute(async () => {
150156
ITwitchAPI api = GetApi();
151157
GetUsersResponse? response = await api.Helix.Users.GetUsersAsync();
@@ -158,7 +164,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires,
158164
}
159165

160166
/// <inheritdoc />
161-
public virtual async Task<IEnumerable<TwitchModeratedChannel>> GetUserModChannels(string userId) {
167+
public virtual async Task<IEnumerable<TwitchModeratedChannel>> GetUserModChannels(string userId) {
162168
using var client = new HttpClient();
163169

164170
var ret = new List<TwitchModeratedChannel>();
@@ -189,7 +195,7 @@ public virtual async Task<IEnumerable<TwitchModeratedChannel>> GetUserModChanne
189195
}
190196

191197
/// <inheritdoc />
192-
public virtual async Task<IEnumerable<BannedUser>> BanChannelUsers(string channelId, string botId,
198+
public virtual async Task<IEnumerable<BannedUser>> BanChannelUsers(string channelId, string botId,
193199
IEnumerable<(string Id, string Username)> users, string reason, CancellationToken token = new()) {
194200
return await Retry.Execute(async () => {
195201
ITwitchAPI api = GetApi();
@@ -223,7 +229,7 @@ public virtual async Task<IEnumerable<BannedUser>> BanChannelUsers(string chann
223229
}
224230

225231
/// <inheritdoc />
226-
public virtual async Task<IEnumerable<Chatter>> GetChannelUsers(string channelId, string botId,
232+
public virtual async Task<IEnumerable<Chatter>> GetChannelUsers(string channelId, string botId,
227233
CancellationToken token = new()) {
228234
return await Retry.Execute(async () => {
229235
ITwitchAPI api = GetApi();
@@ -247,7 +253,7 @@ public virtual async Task<IEnumerable<Chatter>> GetChannelUsers(string channelI
247253
}
248254

249255
/// <inheritdoc />
250-
public virtual async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<string> userIds) {
256+
public virtual async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<string> userIds) {
251257
ITwitchAPI api = GetApi();
252258

253259
// We can only query 100 at a time, so throttle the search.
@@ -271,7 +277,7 @@ public virtual async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<stri
271277
}
272278

273279
/// <inheritdoc />
274-
public virtual async Task<IEnumerable<Moderator>> GetChannelMods(string channelId, CancellationToken token = new()) {
280+
public virtual async Task<IEnumerable<Moderator>> GetChannelMods(string channelId, CancellationToken token = new()) {
275281
return await Retry.Execute(async () => {
276282
ITwitchAPI api = GetApi();
277283

@@ -298,7 +304,7 @@ public virtual async Task<IEnumerable<string>> GetChannelsLive(IEnumerable<stri
298304
}
299305

300306
/// <inheritdoc />
301-
public virtual async Task<bool> AddChannelMod(string channelId, string userId, CancellationToken token = new()) {
307+
public virtual async Task<bool> AddChannelMod(string channelId, string userId, CancellationToken token = new()) {
302308
return await Retry.Execute(async () => {
303309
ITwitchAPI api = GetApi();
304310
await api.Helix.Moderation.AddChannelModeratorAsync(channelId, userId);
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
namespace Nullinside.Api.Common.Twitch;
22

33
/// <summary>
4-
/// The configuration for a twitch app that provides OAuth tokens.
4+
/// The configuration for a twitch app that provides OAuth tokens.
55
/// </summary>
66
public class TwitchAppConfig {
77
/// <summary>
8-
/// The client id.
8+
/// The client id.
99
/// </summary>
1010
public string? ClientId { get; set; }
11-
11+
1212
/// <summary>
13-
/// The client secret.
13+
/// The client secret.
1414
/// </summary>
1515
public string? ClientSecret { get; set; }
16-
16+
1717
/// <summary>
18-
/// A registered URL that the Twitch API is allowed to redirect to on our website.
18+
/// A registered URL that the Twitch API is allowed to redirect to on our website.
1919
/// </summary>
2020
public string? ClientRedirect { get; set; }
2121
}

src/Nullinside.Api.Model/Ddl/User.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.ComponentModel.DataAnnotations;
2+
13
using Microsoft.EntityFrameworkCore;
24

35
namespace Nullinside.Api.Model.Ddl;
@@ -60,6 +62,7 @@ public class User : ITableModel {
6062
/// <summary>
6163
/// The last timestamp of when the user logged into the site.
6264
/// </summary>
65+
[Timestamp]
6366
public DateTime UpdatedOn { get; set; }
6467

6568
/// <summary>
@@ -92,6 +95,8 @@ public void OnModelCreating(ModelBuilder modelBuilder) {
9295
.HasMaxLength(255);
9396
entity.Property(e => e.Token)
9497
.HasMaxLength(255);
98+
entity.Property(e => e.UpdatedOn)
99+
.IsRowVersion();
95100
// TODO: Add the other strings in this file with lengths
96101
});
97102
}

0 commit comments

Comments
 (0)