Skip to content

Commit 041c9e0

Browse files
Fixed default repo functionality and improve mute user functionality (#938)
* fixed default repo functionality * fix lint * Update server/plugin/api.go * Update server/plugin/api.go * Update server/plugin/api.go --------- Co-authored-by: Doug Lauder <[email protected]>
1 parent ebb39ca commit 041c9e0

File tree

6 files changed

+100
-32
lines changed

6 files changed

+100
-32
lines changed

server/plugin/api.go

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ const (
3737
requestTimeout = 30 * time.Second
3838
oauthCompleteTimeout = 2 * time.Minute
3939

40-
channelIDParam = "channelId"
40+
channelIDParam = "channelId"
41+
organisationParam = "organization"
4142
)
4243

4344
type OAuthState struct {
@@ -1441,11 +1442,18 @@ func (p *Plugin) getReposByOrg(c *UserContext, w http.ResponseWriter, r *http.Re
14411442

14421443
opt := github.ListOptions{PerPage: 50}
14431444

1444-
orgString := r.URL.Query().Get("organization")
1445+
orgString := r.URL.Query().Get(organisationParam)
14451446

14461447
if orgString == "" {
14471448
c.Log.Warnf("Organization query param is empty")
1448-
p.writeAPIError(w, &APIErrorResponse{Message: "Organization query is empty, must include organization name ", StatusCode: http.StatusBadRequest})
1449+
p.writeAPIError(w, &APIErrorResponse{Message: "Organization query parameter is empty, must include organization name ", StatusCode: http.StatusBadRequest})
1450+
return
1451+
}
1452+
1453+
channelIDString := r.URL.Query().Get(channelIDParam)
1454+
if channelIDString == "" {
1455+
c.Log.Warnf("Channel ID query param is empty")
1456+
p.writeAPIError(w, &APIErrorResponse{Message: "ChannelId query parameter is empty, must include Channel ID ", StatusCode: http.StatusBadRequest})
14491457
return
14501458
}
14511459

@@ -1489,21 +1497,44 @@ func (p *Plugin) getReposByOrg(c *UserContext, w http.ResponseWriter, r *http.Re
14891497
}
14901498

14911499
// Only send repositories which are part of the requested organization(s)
1492-
type RepositoryResponse struct {
1493-
Name string `json:"name,omitempty"`
1494-
FullName string `json:"full_name,omitempty"`
1495-
Permissions map[string]bool `json:"permissions,omitempty"`
1496-
}
14971500

1498-
resp := make([]*RepositoryResponse, len(allRepos))
1501+
repoResp := make([]RepoResponse, len(allRepos))
14991502
for i, r := range allRepos {
1500-
resp[i] = &RepositoryResponse{
1503+
repoResp[i] = RepoResponse{
15011504
Name: r.GetName(),
15021505
FullName: r.GetFullName(),
15031506
Permissions: r.GetPermissions(),
15041507
}
15051508
}
15061509

1510+
resp := RepositoryResponse{
1511+
Repos: repoResp,
1512+
}
1513+
1514+
// Add default repo if available
1515+
defaultRepo, dErr := p.GetDefaultRepo(c.GHInfo.UserID, channelIDString)
1516+
if dErr != nil {
1517+
c.Log.WithError(dErr).Warnf("Failed to get the default repo for the channel. UserID: %s. ChannelID: %s", c.GHInfo.UserID, channelIDString)
1518+
}
1519+
1520+
if defaultRepo != "" {
1521+
config := p.getConfiguration()
1522+
baseURL := config.getBaseURL()
1523+
owner, repo := parseOwnerAndRepo(defaultRepo, baseURL)
1524+
defaultRepository, err := getRepository(c.Ctx, owner, repo, githubClient)
1525+
if err != nil {
1526+
c.Log.WithError(err).Warnf("Failed to get the default repo %s/%s", owner, repo)
1527+
}
1528+
1529+
if defaultRepository != nil {
1530+
resp.DefaultRepo = RepoResponse{
1531+
Name: defaultRepository.GetName(),
1532+
FullName: defaultRepository.GetFullName(),
1533+
Permissions: defaultRepository.Permissions,
1534+
}
1535+
}
1536+
}
1537+
15071538
p.writeJSON(w, resp)
15081539
}
15091540

server/plugin/command.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package plugin
66
import (
77
"context"
88
"fmt"
9+
"net/http"
910
"strings"
1011
"unicode"
1112

@@ -195,11 +196,15 @@ func (p *Plugin) isValidGitHubUsername(username string, userInfo *GitHubUserInfo
195196
if cErr := p.useGitHubClient(userInfo, func(userInfo *GitHubUserInfo, token *oauth2.Token) error {
196197
ghUser, _, err := githubClient.Users.Get(context.Background(), username)
197198
if err != nil {
199+
if gErr, ok := err.(*github.ErrorResponse); ok && gErr.Response.StatusCode == http.StatusNotFound {
200+
return ErrNotFound
201+
}
202+
198203
return err
199204
}
200205

201206
if ghUser == nil {
202-
return fmt.Errorf("%w", ErrNotFound)
207+
return ErrNotFound
203208
}
204209

205210
return nil

webapp/src/actions/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ export function getOrgs() {
100100
};
101101
}
102102

103-
export function getReposByOrg(organization: string) {
103+
export function getReposByOrg(organization: string, channelId: string) {
104104
return async (dispatch: DispatchFunc) => {
105105
let data;
106106
try {
107-
data = await Client.getRepositoriesByOrganization(organization);
107+
data = await Client.getRepositoriesByOrganization(organization, channelId);
108108
} catch (error) {
109109
return {error: data};
110110
}

webapp/src/client/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ export default class Client {
3737
return this.doGet<ChannelRepositoriesData>(`${this.url}/repositories?channelId=${channelId}`);
3838
}
3939

40-
getRepositoriesByOrganization = async (organization: string): Promise<RepositoryData[] | ApiError> => {
41-
return this.doGet<RepositoryData[]>(`${this.url}/repos_by_org?organization=${organization}`);
40+
getRepositoriesByOrganization = async (organization: string, channelId: string): Promise<YourReposData[] | ApiError> => {
41+
return this.doGet<YourReposData[]>(`${this.url}/repos_by_org?organization=${organization}&channelId=${channelId}`);
4242
}
4343

4444
getPrsDetails = async (prList: {url: string, number: number}[]) => {

webapp/src/components/github_repo_selector/github_repo_selector.jsx

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,10 @@ import PropTypes from 'prop-types';
66

77
import ReactSelectSetting from '@/components/react_select_setting';
88

9-
const initialState = {
10-
invalid: false,
11-
error: null,
12-
org: '',
13-
};
14-
159
export default class GithubRepoSelector extends PureComponent {
1610
static propTypes = {
1711
yourOrgs: PropTypes.array.isRequired,
18-
yourReposByOrg: PropTypes.array,
12+
yourReposByOrg: PropTypes.object,
1913
theme: PropTypes.object.isRequired,
2014
onChange: PropTypes.func.isRequired,
2115
value: PropTypes.string,
@@ -28,39 +22,74 @@ export default class GithubRepoSelector extends PureComponent {
2822
}).isRequired,
2923
};
3024

25+
static defaultProps = {
26+
yourReposByOrg: {repos: []},
27+
};
28+
3129
constructor(props) {
3230
super(props);
33-
this.state = initialState;
31+
this.state = {org: ''};
3432
}
3533

3634
componentDidMount() {
3735
this.props.actions.getOrgs();
3836
}
3937

38+
getReposArray = () => {
39+
const {yourReposByOrg} = this.props;
40+
41+
if (yourReposByOrg?.repos?.length > 0) {
42+
return yourReposByOrg.repos;
43+
}
44+
45+
if (yourReposByOrg?.defaultRepo) {
46+
return [yourReposByOrg.defaultRepo];
47+
}
48+
49+
return [];
50+
}
51+
4052
componentDidUpdate(prevProps) {
41-
if (prevProps.yourOrgs !== this.props.yourOrgs) {
42-
if (this.props.yourOrgs.length) {
43-
this.onChangeForOrg(0, this.props.yourOrgs[0].login);
53+
const repos = this.getReposArray();
54+
const defaultRepo = this.props.yourReposByOrg?.defaultRepo;
55+
const prevDefaultRepo = prevProps.yourReposByOrg?.defaultRepo;
56+
57+
if ((!this.props.value || (defaultRepo && defaultRepo.full_name !== prevDefaultRepo?.full_name)) && defaultRepo) {
58+
this.onChangeForRepo(defaultRepo.name, defaultRepo.full_name);
59+
} else if (!defaultRepo && !this.props.value && repos.length > 0) {
60+
this.onChangeForRepo(repos[0].name, repos[0].full_name);
61+
}
62+
63+
if (prevProps.yourOrgs !== this.props.yourOrgs && this.props.yourOrgs.length > 0) {
64+
const newOrg = this.props.yourOrgs[0].login;
65+
if (this.state.org !== newOrg) {
66+
this.onChangeForOrg(newOrg);
4467
}
4568
}
4669
}
4770

48-
onChangeForOrg = (_, org) => {
71+
onChangeForOrg = (org) => {
4972
if (this.state.org !== org) {
5073
this.setState({org});
51-
this.props.actions.getReposByOrg(org);
74+
this.props.actions.getReposByOrg(org, this.props.currentChannelId);
5275
this.props.onChange(null);
5376
}
5477
}
5578

5679
onChangeForRepo = (_, name) => {
57-
const repo = this.props.yourReposByOrg.find((r) => r.full_name === name);
58-
this.props.onChange({name, permissions: repo.permissions});
80+
const repos = this.getReposArray();
81+
82+
const repo = repos.find((r) => r.full_name === name);
83+
if (repo) {
84+
this.props.onChange({name, permissions: repo.permissions});
85+
}
5986
}
6087

6188
render() {
62-
const orgOptions = this.props.yourOrgs.map((item) => ({value: item.login, label: item.login}));
63-
const repoOptions = this.props.yourReposByOrg.map((item) => ({value: item.full_name, label: item.name}));
89+
const orgOptions = this.props.yourOrgs.map((org) => ({value: org.login, label: org.login}));
90+
91+
const repos = this.getReposArray();
92+
const repoOptions = repos.map((repo) => ({value: repo.full_name, label: repo.name}));
6493

6594
let orgSelector = null;
6695
let helperTextForRepoSelector = 'Returns GitHub repositories connected to the user account';

webapp/src/components/github_repo_selector/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import {connect} from 'react-redux';
55
import {bindActionCreators} from 'redux';
66

7+
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
8+
79
import manifest from '@/manifest';
810

911
import {getReposByOrg, getOrgs} from '../../actions';
@@ -14,6 +16,7 @@ function mapStateToProps(state) {
1416
return {
1517
yourOrgs: state[`plugins-${manifest.id}`].yourOrgs,
1618
yourReposByOrg: state[`plugins-${manifest.id}`].yourReposByOrg,
19+
currentChannelId: getCurrentChannelId(state),
1720
};
1821
}
1922

0 commit comments

Comments
 (0)