class GithubScm extends AbstractScm {

    @Override
    public Container<ScmOrganization> getOrganizations() {
        StaplerRequest request = Stapler.getCurrentRequest();
        String credentialId = GithubCredentialUtils.computeCredentialId(getCredentialIdFromRequest(request), getId(), getUri());

        User authenticatedUser = getAuthenticatedUser();
        final StandardUsernamePasswordCredentials credential = CredentialsUtils.findCredential(credentialId, StandardUsernamePasswordCredentials.class, new BlueOceanDomainRequirement());

        if(credential == null){
            throw new ServiceException.BadRequestException(String.format("Credential id: %s not found for user %s", credentialId, authenticatedUser.getId()));
        }

        String accessToken = credential.getPassword().getPlainText();

        try {
            GitHub github = GitHubFactory.connect(accessToken, getUri());

            final Link link = getLink().rel("organizations");

            Map<String, ScmOrganization> orgMap = new LinkedHashMap<>(); // preserve the same order that github org api returns

            for(Map.Entry<String, GHOrganization> entry: github.getMyOrganizations().entrySet()){
                    orgMap.put(entry.getKey(),
                            new GithubOrganization(GithubScm.this, entry.getValue(), credential, link));
            }

            GHMyself user = github.getMyself();
            if(orgMap.get(user.getLogin()) == null){ //this is to take care of case if/when github starts reporting user login as org later on
                orgMap = new HashMap<>(orgMap);
                orgMap.put(user.getLogin(), new GithubUserOrganization(user, credential, this));
            }
            final Map<String, ScmOrganization> orgs = orgMap;
            return new Container<ScmOrganization>() {
                @Override
                public ScmOrganization get(String name) {
                    ScmOrganization org = orgs.get(name);
                    if(org == null){
                        throw new ServiceException.NotFoundException(String.format("GitHub organization %s not found", name));
                    }
                    return org;
                }

                @Override
                public Link getLink() {
                    return link;
                }

                @Override
                public Iterator<ScmOrganization> iterator() {
                    return orgs.values().iterator();
                }
            };
        } catch (IOException e) {
            if(e instanceof HttpException) {
                HttpException ex = (HttpException) e;
                if (ex.getResponseCode() == 401) {
                    throw new ServiceException
                            .PreconditionRequired("Invalid GitHub accessToken", ex);
                }else if(ex.getResponseCode() == 403){
                    throw new ServiceException
                            .PreconditionRequired("GitHub accessToken does not have required scopes. Expected scopes 'user:email, repo'", ex);
                }
            }
            throw new ServiceException.UnexpectedErrorException(e.getMessage(), e);
        }
    }

    public  GithubScm(Reachable parent);

}