Skip to content

Commit

Permalink
✨ : add module authorized teams selection
Browse files Browse the repository at this point in the history
  • Loading branch information
juwit committed Aug 8, 2019
1 parent cef6e30 commit cfcf55c
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.codeka.gaia.teams.controller;

import io.codeka.gaia.teams.bo.Team;
import io.codeka.gaia.teams.repository.TeamRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/teams")
@Secured("ROLE_ADMIN")
public class TeamsRestController {

private TeamRepository teamRepository;

@Autowired
public TeamsRestController(TeamRepository teamRepository) {
this.teamRepository = teamRepository;
}

@GetMapping
public List<Team> teams(){
return this.teamRepository.findAll();
}

}
30 changes: 30 additions & 0 deletions src/main/resources/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
29. Custom style for wizard
30. Custom style for module description
31. Custom style for navigation
32. Multiselect customization
-------------------------------------------------------------------*/

Expand Down Expand Up @@ -3702,4 +3703,33 @@ ul.messenger.messenger-fixed.messenger-on-top.custom-messenger-on-top {

.navigation .breadcrumb .breadcrumb-item.active {
color: #0971b8;
}

/*------------------------------------------------------------------
32. Multiselect customization
-------------------------------------------------------------------*/

.multiselect__tag {
background: #0971b8;
}
.multiselect__tag-icon:after {
color: white;
}
.multiselect__tag-icon:focus,
.multiselect__tag-icon:hover {
background: #0069d9;
}
.multiselect__tag-icon:focus:after,
.multiselect__tag-icon:hover:after {
color: white;
}
.multiselect__option--highlight {
background: #0069d9;
outline: none;
color: white;
}
.multiselect__option--highlight:after {
content: attr(data-select);
background: #0069d9;
color: white;
}
4 changes: 3 additions & 1 deletion src/main/resources/templates/layout/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@

<link rel="stylesheet" href="/webjars/bootstrap-vue/2.0.0-rc.26/dist/bootstrap-vue.css" />

<link rel="stylesheet" href="/webjars/vue-multiselect/2.1.6/dist/vue-multiselect.min.css" />

<!-- custom css -->
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/color_2.css" />
<link rel="stylesheet" href="/css/responsive.css" />
<link rel="stylesheet" href="/css/github-markdown.css">
<link rel="stylesheet" href="/css/github-markdown.css" />

</head>
25 changes: 24 additions & 1 deletion src/main/resources/templates/module.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ <h2>Module {{module.name}}</h2>
</div>
</div>

<h2>Authorized Teams</h2>

<div class="form-row">
<div class="form-group col-md-6">
<vue-multiselect

:multiple="true"
label="id"
track-by="id"
searchable
placeholder="Select teams"
v-model="module.authorizedTeams"
:options="teams"></vue-multiselect>
</div>
</div>

<h2>Variables <button type="button" class="btn btn-success" @click="addVar()">+</button></h2>

<div class="form-row align-items-end" v-for="(modVar,modVarIdx) in module.variables">
Expand Down Expand Up @@ -114,18 +130,25 @@ <h2>Variables <button type="button" class="btn btn-success" @click="addVar()">+<
<script src="/webjars/vue/2.5.16/vue.js"></script>
<script src="/webjars/bootstrap-vue/2.0.0-rc.26/dist/bootstrap-vue.js"></script>

<script src="/webjars/vue-multiselect/2.1.6/dist/vue-multiselect.min.js"></script>

<div th:replace="helpers/messenger"></div>
<div th:replace="vue_templates/breadcrumb"></div>

<script th:inline="javascript" type="application/ecmascript">
Vue.component('vue-multiselect', window.VueMultiselect.default);

const moduleId = [[${module.id}]];

$.get(`/api/modules/${moduleId}`)
.then(module => $.get('/api/terraform-cli/versions').then(versions => ({module, versions})))
.then(({module, versions}) => $.get('/api/teams').then(teams => ({module, versions, teams})))
.then(data => {
teams = data.teams;
module = data.module;
new Vue({
el: "#app",
data,
data: _ => data,
template: "#template",
methods: {
post: function(){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.codeka.gaia.teams.controller;

import io.codeka.gaia.config.SecurityConfig;
import io.codeka.gaia.teams.repository.TeamRepository;
import io.codeka.gaia.test.MongoContainer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.verify;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
* Simple integration test that validates the security configuration of the TeamsRestController, and its http routes
*/
@SpringBootTest(classes={TeamsRestController.class, SecurityConfig.class})
@AutoConfigureWebMvc
@AutoConfigureMockMvc
@WithMockUser(value = "admin", roles = "ADMIN")
class TeamsRestControllerIT {

@MockBean
private TeamRepository teamRepository;

@Autowired
private TeamsRestController teamsRestController;

@Autowired
private MockMvc mockMvc;

@Test
@WithMockUser("Mary J")
void teams_shouldNotBeAccessible_forStandardUsers(){
assertThrows(AccessDeniedException.class, () -> teamsRestController.teams());
}

@Test
void teams_shouldBeAccessible_forAdminUser(){
assertDoesNotThrow(() -> teamsRestController.teams());
}

@Test
void teams_shouldBeExposed_atSpecificUrl() throws Exception {
mockMvc.perform(get("/api/teams")).andExpect(status().isOk());

verify(teamRepository).findAll();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.codeka.gaia.teams.controller;

import io.codeka.gaia.teams.repository.TeamRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class TeamsRestControllerTest {

@Mock
private TeamRepository teamRepository;

@InjectMocks
private TeamsRestController teamsRestController;

@Test
void teams_shouldReturnAllTeams() {
teamsRestController.teams();

verify(teamRepository).findAll();
}
}

0 comments on commit cfcf55c

Please sign in to comment.