-
Notifications
You must be signed in to change notification settings - Fork 4
/
TableauRepository.cs
206 lines (185 loc) · 7.27 KB
/
TableauRepository.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Npgsql;
using System.Diagnostics;
namespace Behold_Emailer
{
/*
* TableauRepository represents a connection to the PostgreSQL repository in Tableau Server
* This class is just a convenience which builds in a connection and useful queries and processing
* You could make the thing yourself if you needed to
*/
class TableauRepository
{
string[] repository_users = new string[3] { "tableau", "readonly", "tblwgadmin" };
int repository_port;
string repository_db;
string repository_user;
string repository_pw;
string repository_server;
NpgsqlConnection repository;
public Logger logger;
public TableauRepository(string tableau_server_url, string repository_password, string repository_username)
{
if (String.Equals(repository_username, "")) { this.repository_user = "readonly"; }
else
{
this.repository_user = repository_username;
}
this.repository_port = 8060;
this.repository_db = "workgroup";
this.repository_pw = repository_password;
this.logger = null;
// Don't use user "tableau", you need at least "readonly" right
// Only need tblwgadmin if you need to write into the repository, only for advanced hack cases
// Remove the http:// or https:// to log in to the repository. (Do we need things if this is SSL?)
int colon_slash_slash = tableau_server_url.IndexOf("://");
if (colon_slash_slash != -1){
this.repository_server = tableau_server_url.Substring(colon_slash_slash+3);
}
else{
this.repository_server = tableau_server_url;
}
// Take off any extra stuff after the server main (including port number extensions)
int final_colon = this.repository_server.IndexOf(":");
if (final_colon != -1)
{
this.repository_server = this.repository_server.Substring(0, final_colon);
}
int extra_slash = this.repository_server.IndexOf("/");
if (extra_slash != -1)
{
this.repository_server = this.repository_server.Substring(0, extra_slash);
}
this.repository = new NpgsqlConnection(String.Format("Host={0};Username={1};Password={2};Database={3};Port={4};Pooling=false", this.repository_server,
this.repository_user, this.repository_pw, this.repository_db, this.repository_port));
try
{
this.log(String.Format("Opening connection to repository on {0}", this.repository_server));
this.repository.Open();
}
catch (NpgsqlException)
{
throw new ConfigurationException("Cannot connect to Repository, please check credentials");
}
catch (Exception e)
{
if (e.Message.Contains("Timeout"))
{
this.log("Issue with PG timeout. Going to keep on trucking");
}
else
{
throw e;
}
}
}
// Destructor to free up resource
~TableauRepository()
{
this.repository.Close();
}
public void log(string l)
{
if (this.logger != null)
{
this.logger.Log(l);
}
}
public NpgsqlDataReader query_sessions(string username)
{
// Trusted tickets sessions do not have anything in the 'data' column
//The auth token is contained within the shared_wg_write column, stored as JSON
string sessions_sql = @"
SELECT
sessions.session_id,
sessions.data,
sessions.updated_at,
sessions.user_id,
sessions.shared_wg_write,
sessions.shared_vizql_write,
system_users.name AS user_name,
users.system_user_id
FROM sessions,
system_users,
users
WHERE sessions.user_id = users.id AND users.system_user_id = system_users.id
";
if (username != "")
{
sessions_sql += "AND system_users.name = @uname\n";
}
sessions_sql += "ORDER BY sessions.updated_at DESC;";
NpgsqlCommand cmd = new NpgsqlCommand(sessions_sql, this.repository);
cmd.Parameters.AddWithValue("@uname", username);
NpgsqlDataReader dr = cmd.ExecuteReader();
return dr;
}
public NpgsqlDataReader query_subscriptions_for_users(string schedule_name, Boolean views_only)
{
string subscriptions_sql = @"
SELECT
s.id,
s.subject,
s.user_name,
s.site_name,
COALESCE(cv.repository_url, s.view_url) as view_url,
sch.name,
su.email
FROM _subscriptions s
LEFT JOIN _customized_views cv ON s.customized_view_id = cv.id
JOIN _schedules sch ON sch.name = s.schedule_name
JOIN system_users su ON su.name = s.user_name
";
if (schedule_name != "")
{
subscriptions_sql += "WHERE sch.name = @sched_name\n";
if (views_only == true)
{
subscriptions_sql += "AND s.view_url IS NOT NULL -- Export command in tabcmd requires a View not a Workbook";
}
}
else
{
if (views_only == true)
{
subscriptions_sql += "WHERE s.view_url IS NOT NULL -- Export command in tabcmd requires a View not a Workbook";
}
}
NpgsqlCommand cmd = new NpgsqlCommand(subscriptions_sql, this.repository);
if (schedule_name != "")
{
cmd.Parameters.AddWithValue("@sched_name", schedule_name);
}
NpgsqlDataReader dr = cmd.ExecuteReader();
return dr;
}
public NpgsqlDataReader query_inactive_subscription_schedules()
{
string sub_sched_sql = @"
SELECT *
FROM _schedules sch
WHERE scheduled_action_type = 'Subscriptions'
AND active=false
";
NpgsqlCommand cmd = new NpgsqlCommand(sub_sched_sql, this.repository);
NpgsqlDataReader dr = cmd.ExecuteReader();
return dr;
}
public NpgsqlDataReader query_inactive_subscription_schedules_for_next_run_time()
{
string sub_sched_sql = @"
SELECT
name,
run_next_at
FROM _schedules sch
WHERE scheduled_action_type = 'Subscriptions' AND active=false
";
NpgsqlCommand cmd = new NpgsqlCommand(sub_sched_sql, this.repository);
NpgsqlDataReader dr = cmd.ExecuteReader();
return dr;
}
}
}