Skip to content

Commit 4d687ca

Browse files
committed
Updates for issue #33
1 parent c6b40a1 commit 4d687ca

File tree

13 files changed

+381
-271
lines changed

13 files changed

+381
-271
lines changed

api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
import io.sentrius.sso.core.config.SystemOptions;
1414
import jakarta.servlet.http.HttpServletRequest;
1515
import jakarta.servlet.http.HttpServletResponse;
16+
import lombok.extern.slf4j.Slf4j;
1617
import org.springframework.http.ResponseEntity;
1718
import org.springframework.stereotype.Controller;
1819
import org.springframework.web.bind.annotation.GetMapping;
1920
import org.springframework.web.bind.annotation.PathVariable;
2021
import org.springframework.web.bind.annotation.RequestMapping;
2122
import org.springframework.web.bind.annotation.RequestParam;
2223

24+
@Slf4j
2325
@Controller
2426
@RequestMapping("/api/v1/zerotrust/accesstoken")
2527
public class ZeroTrustATApiController extends BaseController {
@@ -52,6 +54,7 @@ public String manageRequest(HttpServletRequest request, HttpServletResponse resp
5254
@RequestParam("ztatId") Long ztatId) throws SQLException, GeneralSecurityException {
5355
var operatingUser = getOperatingUser(request, response);
5456
if (null != type ){
57+
log.info("Operating user {} is managing a {} request with status {}", operatingUser, type, status);
5558
switch(type){
5659
case "terminal":
5760
manageTerminalZtAt(operatingUser, ztatId, status);

api/src/main/java/io/sentrius/sso/controllers/view/UserController.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import java.util.ArrayList;
55
import java.util.HashSet;
66
import java.util.List;
7+
import java.util.Map;
78
import java.util.Set;
9+
import java.util.stream.Collectors;
810
import com.fasterxml.jackson.core.JsonProcessingException;
911
import com.fasterxml.jackson.databind.JsonNode;
1012
import com.fasterxml.jackson.databind.ObjectMapper;
1113
import io.sentrius.sso.core.annotations.LimitAccess;
1214
import io.sentrius.sso.core.controllers.BaseController;
15+
import io.sentrius.sso.core.model.WorkHours;
16+
import io.sentrius.sso.core.model.dto.DayOfWeekDTO;
1317
import io.sentrius.sso.core.model.dto.SystemOption;
1418
import io.sentrius.sso.core.model.dto.UserTypeDTO;
1519
import io.sentrius.sso.core.model.security.UserType;
@@ -21,6 +25,7 @@
2125
import io.sentrius.sso.core.services.UserCustomizationService;
2226
import io.sentrius.sso.core.services.UserService;
2327
import io.sentrius.sso.core.config.SystemOptions;
28+
import io.sentrius.sso.core.services.WorkHoursService;
2429
import io.sentrius.sso.core.utils.JsonUtil;
2530
import jakarta.servlet.http.HttpServletRequest;
2631
import jakarta.servlet.http.HttpServletResponse;
@@ -37,10 +42,13 @@
3742
public class UserController extends BaseController {
3843

3944
final UserCustomizationService userThemeService;
45+
final WorkHoursService workHoursService;
4046

41-
protected UserController(UserService userService, SystemOptions systemOptions, ErrorOutputService errorOutputService, UserCustomizationService userThemeService) {
47+
protected UserController(UserService userService, SystemOptions systemOptions,
48+
ErrorOutputService errorOutputService, UserCustomizationService userThemeService, WorkHoursService workHoursService) {
4249
super(userService, systemOptions, errorOutputService);
4350
this.userThemeService = userThemeService;
51+
this.workHoursService = workHoursService;
4452
}
4553

4654
@ModelAttribute("userSettings")
@@ -149,7 +157,28 @@ public String listUsers(Model model) {
149157

150158
@GetMapping("/settings")
151159
@LimitAccess(userAccess = {UserAccessEnum.CAN_VIEW_USERS})
152-
public String getUserSettings(HttpServletRequest request, HttpServletResponse response) {
160+
public String getUserSettings(Model model, HttpServletRequest request, HttpServletResponse response) {
161+
162+
var user = userService.getOperatingUser(request,response, null);
163+
164+
List<WorkHours> workHoursList = workHoursService.getWorkHoursForUser(user.getId());
165+
166+
// Convert the list into a Map where the key is the day of the week (0-6)
167+
Map<Integer, WorkHours> userWorkHours = workHoursList.stream()
168+
.collect(Collectors.toMap(WorkHours::getDayOfWeek, wh -> wh));
169+
170+
// Pass data to Thymeleaf
171+
model.addAttribute("userWorkHours", userWorkHours);
172+
model.addAttribute("daysOfWeek", List.of(
173+
new DayOfWeekDTO(0, "Sunday"),
174+
new DayOfWeekDTO(1, "Monday"),
175+
new DayOfWeekDTO(2, "Tuesday"),
176+
new DayOfWeekDTO(3, "Wednesday"),
177+
new DayOfWeekDTO(4, "Thursday"),
178+
new DayOfWeekDTO(5, "Friday"),
179+
new DayOfWeekDTO(6, "Saturday")
180+
));
181+
153182
return "sso/users/user_settings";
154183
}
155184

api/src/main/java/io/sentrius/sso/controllers/view/ZeroTrustATController.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,36 @@ protected ZeroTrustATController(UserService userService,
3030
}
3131

3232
@GetMapping("/my/current")
33-
public ResponseEntity<String> getCurrentJit() {
33+
public ResponseEntity<String> getCurrentTat() {
3434

3535
return ResponseEntity.ok().build();
3636
}
3737

3838

3939
@GetMapping("/list")
4040
@LimitAccess(ztatAccess= {ZeroTrustAccessTokenEnum.CAN_VIEW_ZTATS})
41-
public String viewJitRequests(HttpServletRequest request, HttpServletResponse response, Model model) {
41+
public String viewTatRequests(HttpServletRequest request, HttpServletResponse response, Model model) {
4242
var operatingUser = getOperatingUser(request, response);
43-
modelJITs(model, operatingUser);
43+
modelTATs(model, operatingUser);
4444
return "sso/ztats/view_ztats";
4545
}
4646

4747
@GetMapping("/my")
4848
@LimitAccess(ztatAccess= {ZeroTrustAccessTokenEnum.CAN_VIEW_ZTATS})
49-
public String viewMyJits(HttpServletRequest request, HttpServletResponse response, Model model) {
49+
public String viewMyTats(HttpServletRequest request, HttpServletResponse response, Model model) {
5050
var operatingUser = getOperatingUser(request, response);
51-
modelJITs(model, operatingUser);
51+
modelTATs(model, operatingUser);
5252

5353
return "sso/ztats/view_my_ztats";
5454
}
5555

56-
private void modelJITs(Model model, User operatingUser){
57-
model.addAttribute("openTerminalJits", ztatRequestService.getOpenAccessTokenRequests(operatingUser));
58-
model.addAttribute("openOpsJits", ztatRequestService.getOpenOpsRequests(operatingUser));
59-
model.addAttribute("approvedTerminalJits", ztatRequestService.getApprovedTerminalAccessTokenRequests(operatingUser));
60-
model.addAttribute("approvedOpsJits", ztatRequestService.getApprovedOpsAccessTokenRequests(operatingUser));
61-
model.addAttribute("deniedOpsJits", ztatRequestService.getDeniedOpsAccessTokenRequests(operatingUser));
62-
model.addAttribute("deniedTerminalJits", ztatRequestService.getDeniedTerminalAccessTokenRequests(operatingUser));
56+
private void modelTATs(Model model, User operatingUser){
57+
model.addAttribute("openTerminalTats", ztatRequestService.getOpenAccessTokenRequests(operatingUser));
58+
model.addAttribute("openOpsTats", ztatRequestService.getOpenOpsRequests(operatingUser));
59+
model.addAttribute("approvedTerminalTats", ztatRequestService.getApprovedTerminalAccessTokenRequests(operatingUser));
60+
model.addAttribute("approvedOpsTats", ztatRequestService.getApprovedOpsAccessTokenRequests(operatingUser));
61+
model.addAttribute("deniedOpsTats", ztatRequestService.getDeniedOpsAccessTokenRequests(operatingUser));
62+
model.addAttribute("deniedTerminalTats", ztatRequestService.getDeniedTerminalAccessTokenRequests(operatingUser));
6363
}
6464

6565
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CREATE TABLE work_hours (
2+
id SERIAL PRIMARY KEY,
3+
user_id INT REFERENCES users(id) ON DELETE CASCADE,
4+
day_of_week SMALLINT CHECK (day_of_week BETWEEN 0 AND 6), -- 0 = Sunday, 6 = Saturday
5+
start_time TIME NOT NULL, -- Example: '09:00:00'
6+
end_time TIME NOT NULL -- Example: '17:00:00'
7+
);
8+
9+
-- Ensure fast lookups for checking dem hours
10+
CREATE INDEX idx_work_hours ON work_hours (user_id, day_of_week);

api/src/main/resources/templates/sso/dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ <h5 class="card-title">User Operations</h5>
420420
<a href="/sso/v1/users/settings" class="btn btn-primary"
421421
th:if="${!#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_VIEW_ZTATS')}">Your Settings</a>
422422
<a href="/sso/v1/zerotrust/accesstoken/list" class="btn btn-primary"
423-
th:if="${#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_VIEW_ZTATS')}">View JITs</a>
423+
th:if="${#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_VIEW_ZTATS')}">View Trust ATs</a>
424424
</div>
425425
</div>
426426
</div>

api/src/main/resources/templates/sso/integrations/add_openai.html

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,38 @@
5555
font-size: 1.25rem;
5656
color: #888;
5757
}
58-
5958
</style>
59+
60+
<script>
61+
async function submitIntegration(event) {
62+
event.preventDefault();
63+
64+
const form = event.target;
65+
const formData = new FormData(form);
66+
const jsonData = Object.fromEntries(formData.entries());
67+
68+
try {
69+
const response = await fetch(form.action, {
70+
method: "POST",
71+
headers: {
72+
"Content-Type": "application/json"
73+
},
74+
body: JSON.stringify(jsonData)
75+
});
76+
77+
if (response.ok) {
78+
const redirectUrl = "/sso/v1/integrations"; // Modify as needed
79+
window.location.href = redirectUrl;
80+
} else {
81+
const errorText = await response.text();
82+
alert("Error: " + errorText);
83+
}
84+
} catch (error) {
85+
console.error("Request failed", error);
86+
alert("Failed to save integration.");
87+
}
88+
}
89+
</script>
6090
</head>
6191
<body>
6292

@@ -68,7 +98,7 @@
6898
<div th:replace="~{fragments/alerts}"></div>
6999
<div class="container">
70100
<h1>Set Up OpenAI Integration</h1>
71-
<form th:action="@{/api/v1/integrations/openai/add}" th:object="${openaiIntegration}" method="post">
101+
<form th:action="@{/api/v1/integrations/openai/add}" th:object="${openaiIntegration}" method="post" onsubmit="submitIntegration(event)">
72102

73103
<div class="form-group">
74104
<label for="name">Integration Name</label>
@@ -88,7 +118,6 @@ <h1>Set Up OpenAI Integration</h1>
88118
th:field="*{apiToken}" placeholder="Enter your Jira API token" required>
89119
</div>
90120

91-
92121
<div class="form-actions">
93122
<button type="submit" class="btn btn-primary">Save Integration</button>
94123
</div>
@@ -101,4 +130,3 @@ <h1>Set Up OpenAI Integration</h1>
101130

102131
</body>
103132
</html>
104-

api/src/main/resources/templates/sso/users/user_settings.html

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
<head>
55
<meta th:replace="~{fragments/header}">
6-
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
6+
<!--<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
7+
-->
78
<style>
89
/* Centering the form container */
910
.center-container {
@@ -85,14 +86,80 @@
8586
</template>
8687
</table>
8788

89+
8890
<br />
8991
<button type="submit" class="btn btn-primary submit_btn">Save</button>
9092
</form>
93+
94+
<br />
95+
<h3>Work Hours</h3>
96+
<table class="table table-dark table-striped">
97+
<thead>
98+
<tr>
99+
<th>Day</th>
100+
<th>Enable</th>
101+
<th>Start Time</th>
102+
<th>End Time</th>
103+
</tr>
104+
</thead>
105+
<tbody>
106+
<tr th:each="day, iter : ${daysOfWeek}">
107+
<td th:text="${day.name}"></td>
108+
<td>
109+
<input type="checkbox" th:id="'enable_' + ${iter.index}" th:checked="${userWorkHours.containsKey(day.id)}">
110+
</td>
111+
<td>
112+
<input type="time" class="form-control" th:id="'start_' + ${iter.index}"
113+
th:value="${userWorkHours.containsKey(day.id) ? userWorkHours.get(day.id).startTime : ''}"
114+
th:disabled="${!userWorkHours.containsKey(day.id)}">
115+
</td>
116+
<td>
117+
<input type="time" class="form-control" th:id="'end_' + ${iter.index}"
118+
th:value="${userWorkHours.containsKey(day.id) ? userWorkHours.get(day.id).endTime : ''}"
119+
th:disabled="${!userWorkHours.containsKey(day.id)}">
120+
</td>
121+
</tr>
122+
</tbody>
123+
</table>
124+
125+
<br />
126+
<button class="btn btn-primary mt-3" id="saveWorkHours">Save Work Hours</button>
91127
</div>
92128
</div>
93129
</div>
94130
</div>
95131
</div>
132+
<script>
133+
document.addEventListener('DOMContentLoaded', function () {
134+
document.querySelectorAll('[id^="enable_"]').forEach((checkbox) => {
135+
checkbox.addEventListener('change', function () {
136+
let index = this.id.split("_")[1];
137+
document.getElementById('start_' + index).disabled = !this.checked;
138+
document.getElementById('end_' + index).disabled = !this.checked;
139+
});
140+
});
141+
142+
document.getElementById('saveWorkHours').addEventListener('click', function () {
143+
let workHours = [];
144+
document.querySelectorAll('[id^="enable_"]').forEach((checkbox) => {
145+
let index = checkbox.id.split("_")[1];
146+
if (checkbox.checked) {
147+
workHours.push({
148+
dayOfWeek: index,
149+
startTime: document.getElementById('start_' + index).value,
150+
endTime: document.getElementById('end_' + index).value
151+
});
152+
}
153+
});
154+
155+
fetch('/api/v1/user/workhours', {
156+
method: 'POST',
157+
headers: { 'Content-Type': 'application/json' },
158+
body: JSON.stringify(workHours)
159+
}).then(response => location.reload());
160+
});
161+
});
162+
</script>
96163
</body>
97164

98165
</html>

0 commit comments

Comments
 (0)