<commit_before>/*****************************************************************************
* #### jentikjs ####
* jQuery plugin untuk membuat widget mengecek ongkir atau tracking TIKI & JNE
* Coded by Ican Bachors 2016.
* http://ibacor.com/labs/jentikjs
* Updates will be posted to this site.
*****************************************************************************/

var jentik = function() {
    $('#jentik').html('

ongkir

tracking

jne

tiki

pos

ongkir

Kota Asal<input type="text" id="tiki_dari" list="rute_tiki_dari" placeholder="Bandung"/><datalist id="rute_tiki_dari"></datalist>Kota Tujuan<input type="text" id="tiki_ke" list="rute_tiki_ke" placeholder="Surabaya"/><datalist id="rute_tiki_ke"></datalist>Berat (Kg)<input type="text" id="tiki_kg" placeholder="4"/><input type="submit" class="cek_ongkir" data-jentik="tiki" value="Cek Ongkir"/>

Kota Asal<input type="text" id="jne_dari" list="rute_jne_dari" placeholder="Bandung"/><datalist id="rute_jne_dari"></datalist>Kota Tujuan<input type="text" id="jne_ke" list="rute_jne_ke" placeholder="Surabaya"/><datalist id="rute_jne_ke"></datalist>Berat (Kg)<input type="text" id="jne_kg" placeholder="4"/><input type="submit" class="cek_ongkir" data-jentik="jne" value="Cek Ongkir"/>

Coming Soon..

Nomor Resi<input type="text" id="tiki_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="tiki" value="Cek Resi"/>

Nomor Resi<input type="text" id="jne_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="jne" value="Cek Resi"/>

Nomor Resi<input type="text" id="pos_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="pos" value="Cek Resi"/>

Made with<3
');
    $('body').on('click', '#jentik .tab1', function() {
        var a = $(this).html(),
            tab2 = $('#jentik .aktip2').html();
        $('#jentik-anu').html(a);
        $('#jentik .tab1').removeClass('aktip1');
        if (a == 'ongkir') {
            $('#jentik #kotak-tracking').css('display', 'none');
            $('#jentik #kotak-ongkir').css('display', 'block');
            $('#jentik #kotak-ongkir-jne').css('display', 'none');
            $('#jentik #kotak-ongkir-tiki').css('display', 'none');
            $('#jentik #kotak-ongkir-' + tab2).css('display', 'block')
        } else if (a == 'tracking') {
            $('#jentik #kotak-ongkir').css('display', 'none');
            $('#jentik #kotak-tracking').css('display', 'block');
            $('#jentik #kotak-tracking-jne').css('display', 'none');
            $('#jentik #kotak-tracking-tiki').css('display', 'none');
            $('#jentik #kotak-tracking-' + tab2).css('display', 'block')
        }
        $(this).addClass('aktip1');
        $('#jentik-output').html('');
        return false
    });
    $('body').on('click', '#jentik .tab2', function() {
        var a = $(this).html(),
            anu = $('#jentik-anu').html();
        $('#jentik .tab2').removeClass('aktip2');
        if (a == 'jne') {
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'none');
            $('#jentik #kotak-' + anu + '-jne').css('display', 'block');
        } else if (a == 'tiki') {
            $('#jentik #kotak-' + anu + '-jne').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'none');
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'block');
        } else if (a == 'pos') {
            $('#jentik #kotak-' + anu + '-jne').css('display', 'none');
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'block');
        }
        $(this).addClass('aktip2');
        $('#jentik-output').html('');
        return false
    });
    $('body').on('focus', '#tiki_dari', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#tiki_dari').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_tiki(d, a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#tiki_ke', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#tiki_ke').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_tiki(d, a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#jne_dari', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#jne_dari').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_jne(d, 'dari', a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#jne_ke', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#jne_ke').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_jne(d, 'ke', a)
                }
            }, 50)
        })
    });
    $('body').on('click', '.cek_ongkir', function() {
        $('#jentik-output').html('
Wait..
');
        var a = $(this).data('jentik'),
            dari = (a == 'jne' ? $("#jne_dari").val() : $("#tiki_dari").val()),
            ke = (a == 'jne' ? $("#jne_ke").val() : $("#tiki_ke").val()),
            berat = (a == 'jne' ? $("#jne_kg").val() : $("#tiki_kg").val());
        cekongkir(a, dari, ke, berat);
        return false
    });
    $('body').on('click', '.cek_resi', function() {
        $('#jentik-output').html('
Wait..
');
        var a = $(this).data('jentik'),
            resi = '';
			if(a == 'jne'){
				resi = $("#jne_resi").val();
			}else if(a == 'tii'){
				resi = $("#tiki_resi").val();
			}else if(a == 'pos'){
				resi = $("#pos_resi").val();
			}
        cekresi(a, resi);
        return false
    });

    function rute_tiki(d, e) {
        $.ajax({
            url: 'http://ibacor.com/api/rute-jne-tiki?p=tiki&q=' + d,
            crossDomain: true,
            dataType: 'json'
        }).done(function(b) {
            var c = '';
            $.each(b, function(i, a) {
                c += '<option value="' + b[i] + '">'
            });
            $('#' + e).html(c)
        })
    }

    function rute_jne(d, t, e) {
        $.ajax({
            url: 'http://ibacor.com/api/rute-jne-tiki?p=jne&q=' + d + '&t=' + t,
            crossDomain: true,
            dataType: 'json'
        }).done(function(b) {
            var c = '';
            $.each(b, function(i, a) {
                c += '<option value="' + b[i] + '">'
            });
            $('#' + e).html(c)
        })
    }

    function cekongkir(f, g, h, j) {
        $.ajax({
            url: 'http://ibacor.com/api/ongkir?service=' + f + '&dari=' + g + '&ke=' + h + '&berat=' + j,
            crossDomain: true,
            dataType: 'json'
        }).done(function(d) {
            var e = '',
				w = '';
            if (d.status == 'success') {
                e += '
Ongkir ' + d.service + ' ' + d.dari + ' ke ' + d.ke + ' (' + d.berat + ' kg)
';
                e += '
';
                if (f == 'tiki') {
					w += 'http://tiki-online.com';
                    e += '
LAYANAN	TARIF
'
                } else if (f == 'jne') {
					w += 'http://www.jne.co.id';
                    e += '
LAYANAN	KIRIMAN	TARIF	ETD
'
                }
                $.each(d.ongkos, function(i, c) {
                    e += '
';
                    $.each(d.ongkos[i], function(a, b) {
                        e += '' + b + '	'
                    });
                    e += '
'
                });
                e += '
'
            } else {
                e += d.status + ': ' + d.message
            }
            $('#jentik-output').html('
' + e + '
' + w + '

')
        })
    }

    function cekresi(g, h) {
        $.ajax({
            url: 'http://ibacor.com/api/cek-resi?pengirim=' + g + '&resi=' + h,
            crossDomain: true,
            dataType: 'json'
        }).done(function(d) {
            var e = '';
            if (d.status == 'success') {
                var f = (d.data.detail.tujuan.nama == undefined ? '' : d.data.detail.tujuan.nama),
                    namaasal = (d.data.detail.asal.nama == undefined ? '' : d.data.detail.asal.nama);
                e += '
Detail
';
                e += '
';
                e += '
Status:	' + d.data.detail.status + '
';
                e += '
No Resi:	' + d.data.detail.no_resi + '
';
                e += '
Service:	' + d.data.detail.service + '
';
				if (g == 'tiki' || g == 'jne') {
					e += '
Tanggal:	' + d.data.detail.tanggal + '
';
				}
                e += '
Asal:	' + d.data.detail.asal.alamat + '
' + namaasal + '
';
                e += '
Tujuan:	' + d.data.detail.tujuan.alamat + '
' + f + '
';
                e += '
';
                e += '
Riwayat
';
                e += '
';
                if (g == 'tiki') {
					e += '
TANGGAL	WAKTU	STATUS	LOKASI	KETERANGAN
'
                } else if (g == 'jne') {
					e += '
TANGGAL	LOKASI	KETERANGAN
'
                } else if (g == 'pos') {
					e += '
TANGGAL	STATUS	LOKASI	KETERANGAN
'
                }
                $.each(d.data.riwayat, function(i, c) {
                    e += '
';
                    $.each(d.data.riwayat[i], function(a, b) {
                        e += '' + b + '	'
                    });
                    e += '
'
                });
                e += '
';
				e += '
' + d.website + '
';
            } else {
                e += d.status + ': ' + d.pesan
            }
            $('#jentik-output').html('
' + e + '
')
        })
    }
}
<commit_msg>fix tiki :)<commit_after>/*****************************************************************************
* #### jentikjs ####
* jQuery plugin untuk membuat widget mengecek ongkir atau tracking TIKI & JNE
* Coded by Ican Bachors 2016.
* http://ibacor.com/labs/jentikjs
* Updates will be posted to this site.
*****************************************************************************/

var jentik = function() {
    $('#jentik').html('

ongkir

tracking

jne

tiki

pos

ongkir

Kota Asal<input type="text" id="tiki_dari" list="rute_tiki_dari" placeholder="Bandung"/><datalist id="rute_tiki_dari"></datalist>Kota Tujuan<input type="text" id="tiki_ke" list="rute_tiki_ke" placeholder="Surabaya"/><datalist id="rute_tiki_ke"></datalist>Berat (Kg)<input type="text" id="tiki_kg" placeholder="4"/><input type="submit" class="cek_ongkir" data-jentik="tiki" value="Cek Ongkir"/>

Kota Asal<input type="text" id="jne_dari" list="rute_jne_dari" placeholder="Bandung"/><datalist id="rute_jne_dari"></datalist>Kota Tujuan<input type="text" id="jne_ke" list="rute_jne_ke" placeholder="Surabaya"/><datalist id="rute_jne_ke"></datalist>Berat (Kg)<input type="text" id="jne_kg" placeholder="4"/><input type="submit" class="cek_ongkir" data-jentik="jne" value="Cek Ongkir"/>

Coming Soon..

Nomor Resi<input type="text" id="tiki_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="tiki" value="Cek Resi"/>

Nomor Resi<input type="text" id="jne_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="jne" value="Cek Resi"/>

Nomor Resi<input type="text" id="pos_resi" placeholder="xxx"/><input type="submit" class="cek_resi" data-jentik="pos" value="Cek Resi"/>

Made with<3
');
    $('body').on('click', '#jentik .tab1', function() {
        var a = $(this).html(),
            tab2 = $('#jentik .aktip2').html();
        $('#jentik-anu').html(a);
        $('#jentik .tab1').removeClass('aktip1');
        if (a == 'ongkir') {
            $('#jentik #kotak-tracking').css('display', 'none');
            $('#jentik #kotak-ongkir').css('display', 'block');
            $('#jentik #kotak-ongkir-jne').css('display', 'none');
            $('#jentik #kotak-ongkir-tiki').css('display', 'none');
            $('#jentik #kotak-ongkir-' + tab2).css('display', 'block')
        } else if (a == 'tracking') {
            $('#jentik #kotak-ongkir').css('display', 'none');
            $('#jentik #kotak-tracking').css('display', 'block');
            $('#jentik #kotak-tracking-jne').css('display', 'none');
            $('#jentik #kotak-tracking-tiki').css('display', 'none');
            $('#jentik #kotak-tracking-' + tab2).css('display', 'block')
        }
        $(this).addClass('aktip1');
        $('#jentik-output').html('');
        return false
    });
    $('body').on('click', '#jentik .tab2', function() {
        var a = $(this).html(),
            anu = $('#jentik-anu').html();
        $('#jentik .tab2').removeClass('aktip2');
        if (a == 'jne') {
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'none');
            $('#jentik #kotak-' + anu + '-jne').css('display', 'block');
        } else if (a == 'tiki') {
            $('#jentik #kotak-' + anu + '-jne').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'none');
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'block');
        } else if (a == 'pos') {
            $('#jentik #kotak-' + anu + '-jne').css('display', 'none');
            $('#jentik #kotak-' + anu + '-tiki').css('display', 'none');
            $('#jentik #kotak-' + anu + '-pos').css('display', 'block');
        }
        $(this).addClass('aktip2');
        $('#jentik-output').html('');
        return false
    });
    $('body').on('focus', '#tiki_dari', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#tiki_dari').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_tiki(d, a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#tiki_ke', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#tiki_ke').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_tiki(d, a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#jne_dari', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#jne_dari').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_jne(d, 'dari', a)
                }
            }, 50)
        })
    });
    $('body').on('focus', '#jne_ke', function() {
        var a = $(this).attr('list');
        $(this).keydown(function() {
            setTimeout(function() {
                var d = $('#jne_ke').val(),
                    jum = d.length;
                if (jum > 2) {
                    rute_jne(d, 'ke', a)
                }
            }, 50)
        })
    });
    $('body').on('click', '.cek_ongkir', function() {
        $('#jentik-output').html('
Wait..
');
        var a = $(this).data('jentik'),
            dari = (a == 'jne' ? $("#jne_dari").val() : $("#tiki_dari").val()),
            ke = (a == 'jne' ? $("#jne_ke").val() : $("#tiki_ke").val()),
            berat = (a == 'jne' ? $("#jne_kg").val() : $("#tiki_kg").val());
        cekongkir(a, dari, ke, berat);
        return false
    });
    $('body').on('click', '.cek_resi', function() {
        $('#jentik-output').html('
Wait..
');
        var a = $(this).data('jentik'),
            resi = '';
			if(a == 'jne'){
				resi = $("#jne_resi").val();
			}else if(a == 'tiki'){
				resi = $("#tiki_resi").val();
			}else if(a == 'pos'){
				resi = $("#pos_resi").val();
			}
        cekresi(a, resi);
        return false
    });

    function rute_tiki(d, e) {
        $.ajax({
            url: 'http://ibacor.com/api/rute-jne-tiki?p=tiki&q=' + d,
            crossDomain: true,
            dataType: 'json'
        }).done(function(b) {
            var c = '';
            $.each(b, function(i, a) {
                c += '<option value="' + b[i] + '">'
            });
            $('#' + e).html(c)
        })
    }

    function rute_jne(d, t, e) {
        $.ajax({
            url: 'http://ibacor.com/api/rute-jne-tiki?p=jne&q=' + d + '&t=' + t,
            crossDomain: true,
            dataType: 'json'
        }).done(function(b) {
            var c = '';
            $.each(b, function(i, a) {
                c += '<option value="' + b[i] + '">'
            });
            $('#' + e).html(c)
        })
    }

    function cekongkir(f, g, h, j) {
        $.ajax({
            url: 'http://ibacor.com/api/ongkir?service=' + f + '&dari=' + g + '&ke=' + h + '&berat=' + j,
            crossDomain: true,
            dataType: 'json'
        }).done(function(d) {
            var e = '',
				w = '';
            if (d.status == 'success') {
                e += '
Ongkir ' + d.service + ' ' + d.dari + ' ke ' + d.ke + ' (' + d.berat + ' kg)
';
                e += '
';
                if (f == 'tiki') {
					w += 'http://tiki-online.com';
                    e += '
LAYANAN	TARIF
'
                } else if (f == 'jne') {
					w += 'http://www.jne.co.id';
                    e += '
LAYANAN	KIRIMAN	TARIF	ETD
'
                }
                $.each(d.ongkos, function(i, c) {
                    e += '
';
                    $.each(d.ongkos[i], function(a, b) {
                        e += '' + b + '	'
                    });
                    e += '
'
                });
                e += '
'
            } else {
                e += d.status + ': ' + d.message
            }
            $('#jentik-output').html('
' + e + '
' + w + '

')
        })
    }

    function cekresi(g, h) {
        $.ajax({
            url: 'http://ibacor.com/api/cek-resi?pengirim=' + g + '&resi=' + h,
            crossDomain: true,
            dataType: 'json'
        }).done(function(d) {
            var e = '';
            if (d.status == 'success') {
                var namaasal = (d.data.detail.asal.nama == undefined ? '' : d.data.detail.asal.nama);
                e += '
Detail
';
                e += '
';
                e += '
Status:	' + d.data.detail.status + '
';
                e += '
No Resi:	' + d.data.detail.no_resi + '
';
				if (g == 'pos' || g == 'jne') {
					e += '
Service:	' + d.data.detail.service + '
';
				}
				if (g == 'tiki' || g == 'jne') {
					e += '
Tanggal:	' + d.data.detail.tanggal + '
';
				}
                e += '
Asal:	' + d.data.detail.asal.alamat + '
' + namaasal + '
';
				if (g == 'pos' || g == 'jne') {
					var f = (d.data.detail.tujuan.nama == undefined ? '' : d.data.detail.tujuan.nama),
					xx = (d.data.detail.tujuan.alamat == undefined ? '' : d.data.detail.tujuan.alamat);
					e += '
Tujuan:	' + xx + '
' + f + '
';
				}
                e += '
';
                e += '
Riwayat
';
                e += '
';
                if (g == 'tiki') {
					e += '
TANGGAL	STATUS	LOKASI
'
                } else if (g == 'jne') {
					e += '
TANGGAL	LOKASI	KETERANGAN
'
                } else if (g == 'pos') {
					e += '
TANGGAL	STATUS	LOKASI	KETERANGAN
'
                }
                $.each(d.data.riwayat, function(i, c) {
                    e += '
';
                    $.each(d.data.riwayat[i], function(a, b) {
                        e += '' + b + '	'
                    });
                    e += '
'
                });
                e += '
';
				e += '
' + d.website + '
';
            } else {
                e += d.status + ': ' + d.pesan
            }
            $('#jentik-output').html('
' + e + '
')
        })
    }
}
<|endoftext|>


<commit_before>const assert = require('assert');
const { expect } = require('chai');

const app = require('../../../src/app');

const userService = app.service('users');
const registrationPinService = app.service('registrationPins');
const publicTeachersService = app.service('publicTeachers');
const classesService = app.service('classes');
const coursesService = app.service('courses');
const testObjects = require('../helpers/testObjects')(app);

let testUserId;

describe('user service', () => {
	it('registered the users service', () => {
		assert.ok(userService);
		assert.ok(classesService);
		assert.ok(coursesService);
	});

	it('rejects on group patching', async () => {
		await userService.patch(null, { email: 'test' }).catch((err) => {
			expect(err).to.not.equal(undefined);
			expect(err.message).to.equal('Operation on this service requires an id!');
		});
	});

	it('resolves permissions and attributes correctly', () => {
		function createTestBase() {
			return app.service('roles')
				.create({
					name: 'test_base',
					roles: [],
					permissions: [
						'TEST_BASE',
						'TEST_BASE_2',
					],
				});
		}

		function createTestSubrole(testBase) {
			return app.service('roles')
				.create({
					name: 'test_subrole',
					roles: [testBase._id],
					permissions: [
						'TEST_SUB',
					],
				});
		}

		return createTestBase()
			.then(testBase => createTestSubrole(testBase))
			.then(testSubrole => testObjects.createTestUser({
				id: '0000d231816abba584714d01',
				accounts: [],
				schoolId: '0000d186816abba584714c5f',
				email: 'user@testusers.net',
				firstName: 'Max',
				lastName: 'Tester',
				roles: [
					testSubrole._id,
				],
				manualCleanup: true,
			}))
			.then(user => userService.get(user._id))
			.then((user) => {
				testUserId = user._id;
				expect(user.avatarInitials).to.eq('MT');
				const array = Array.from(user.permissions);
				expect(array).to.have.lengthOf(3);
				expect(array).to.include('TEST_BASE', 'TEST_BASE_2', 'TEST_SUB');
			});
	});

	it('deletes user correctly', async () => {
		const demoClass = (await classesService.find({ query: { name: 'Demo-Klasse', $limit: 1 } })).data[0];
		const demoCourse = (await coursesService.find({ query: { name: 'Mathe', $limit: 1 } })).data[0];

		await userService.remove(testUserId);

		expect(demoClass.userIds).to.not.include(testUserId);
		expect(demoCourse.userIds).to.not.include(testUserId);
	});

	describe('uniqueness check', () => {
		it('should reject new users with mixed-case variants of existing usernames', async () => {
			await testObjects.createTestUser({ email: 'existing@account.de' });
			const newUser = {
				firstName: 'Test',
				lastName: 'Testington',
				email: 'ExistinG@aCCount.de',
				schoolId: '0000d186816abba584714c5f',
			};

			await new Promise((resolve, reject) => {
				testObjects.createTestUser(newUser)
					.then(() => {
						reject(new Error('This call should fail because of an already existing user with the same email'));
					})
					.catch((err) => {
						expect(err.message).to.equal('Die E-Mail Adresse ExistinG@aCCount.de ist bereits in Verwendung!');
						resolve();
					});
			});
		});
	});

	after(async () => {
		await testObjects.cleanup();
	});
});

describe('registrationPin Service', () => {
	it('registered the registrationPin Service', () => {
		assert.ok(registrationPinService);
	});

	it('creates pins correctly', () => registrationPinService
		.create({ email: 'test.adresse@schul-cloud.org' })
		.then(() => registrationPinService.find({ query: { email: 'test.adresse@schul-cloud.org' } }))
		.then(pinObjects => expect(pinObjects.data[0]).to.have.property('pin')));

	it('overwrites old pins', () => registrationPinService.create({ email: 'test.adresse@schul-cloud.org' })
		.then(() => registrationPinService.create({ email: 'test.adresse@schul-cloud.org' }))
		.then(() => registrationPinService.find({ query: { email: 'test.adresse@schul-cloud.org' } }))
		.then(pinObjects => expect(pinObjects.data).to.have.lengthOf(1)));
});

describe('publicTeachers service', () => {
	let testStudent = {};
	let testTeacherDiscoverable = {};
	let testTeacherNotDiscoverable = {};

	it('register services and create test users', async () => {
		testStudent = await testObjects.createTestUser({
			roles: ['student'],
			discoverable: false,
			schoolId: '0000d186816abba584714c55',
		});
		testTeacherDiscoverable = await testObjects.createTestUser({
			roles: ['teacher'],
			discoverable: true,
			schoolId: '0000d186816abba584714c55',
		});
		testTeacherNotDiscoverable = await testObjects.createTestUser({
			roles: ['teacher'],
			discoverable: false,
			schoolId: '0000d186816abba584714c55',
		});
		assert.ok(userService);
		assert.ok(publicTeachersService);
	});

	// save process.env.IGNORE_DISCOVERABILITY value
	const ORIGINAL_IGNORE_DISCOVERABILITY = process.env.IGNORE_DISCOVERABILITY;
	let result;

	it('without IGNORE_DISCOVERABILITY: find 1 discoverable teacher but not find other users', async () => {
		// test with IGNORE_DISCOVERABILITY = false
		process.env.IGNORE_DISCOVERABILITY = 'false';
		result = await publicTeachersService.find({ query: { schoolId: '0000d186816abba584714c55' } });
		expect(result.total).to.equal(1);
		expect(result.data[0]._id.toString()).to.equal(testTeacherDiscoverable._id.toString());
		expect(result.data[0]._id.toString()).to.not.equal(testStudent._id.toString());
		expect(result.data[0]._id.toString()).to.not.equal(testTeacherNotDiscoverable._id.toString());
	});

	it('with IGNORE_DISCOVERABILITY: find all 3 users ignoring their discoverable setting', async () => {
		// test with IGNORE_DISCOVERABILITY = true
		process.env.IGNORE_DISCOVERABILITY = 'true';
		result = await publicTeachersService.find({ query: { schoolId: '0000d186816abba584714c55' } });
		expect(result.total).to.equal(2);
	});

	// reset process.env.IGNORE_DISCOVERABILITY back to original value
	process.env.IGNORE_DISCOVERABILITY = ORIGINAL_IGNORE_DISCOVERABILITY;

	after(async () => {
		await testObjects.cleanup();
	});
});
<commit_msg>Fix test describtion<commit_after>const assert = require('assert');
const { expect } = require('chai');

const app = require('../../../src/app');

const userService = app.service('users');
const registrationPinService = app.service('registrationPins');
const publicTeachersService = app.service('publicTeachers');
const classesService = app.service('classes');
const coursesService = app.service('courses');
const testObjects = require('../helpers/testObjects')(app);

let testUserId;

describe('user service', () => {
	it('registered the users service', () => {
		assert.ok(userService);
		assert.ok(classesService);
		assert.ok(coursesService);
	});

	it('rejects on group patching', async () => {
		await userService.patch(null, { email: 'test' }).catch((err) => {
			expect(err).to.not.equal(undefined);
			expect(err.message).to.equal('Operation on this service requires an id!');
		});
	});

	it('resolves permissions and attributes correctly', () => {
		function createTestBase() {
			return app.service('roles')
				.create({
					name: 'test_base',
					roles: [],
					permissions: [
						'TEST_BASE',
						'TEST_BASE_2',
					],
				});
		}

		function createTestSubrole(testBase) {
			return app.service('roles')
				.create({
					name: 'test_subrole',
					roles: [testBase._id],
					permissions: [
						'TEST_SUB',
					],
				});
		}

		return createTestBase()
			.then(testBase => createTestSubrole(testBase))
			.then(testSubrole => testObjects.createTestUser({
				id: '0000d231816abba584714d01',
				accounts: [],
				schoolId: '0000d186816abba584714c5f',
				email: 'user@testusers.net',
				firstName: 'Max',
				lastName: 'Tester',
				roles: [
					testSubrole._id,
				],
				manualCleanup: true,
			}))
			.then(user => userService.get(user._id))
			.then((user) => {
				testUserId = user._id;
				expect(user.avatarInitials).to.eq('MT');
				const array = Array.from(user.permissions);
				expect(array).to.have.lengthOf(3);
				expect(array).to.include('TEST_BASE', 'TEST_BASE_2', 'TEST_SUB');
			});
	});

	it('deletes user correctly', async () => {
		const demoClass = (await classesService.find({ query: { name: 'Demo-Klasse', $limit: 1 } })).data[0];
		const demoCourse = (await coursesService.find({ query: { name: 'Mathe', $limit: 1 } })).data[0];

		await userService.remove(testUserId);

		expect(demoClass.userIds).to.not.include(testUserId);
		expect(demoCourse.userIds).to.not.include(testUserId);
	});

	describe('uniqueness check', () => {
		it('should reject new users with mixed-case variants of existing usernames', async () => {
			await testObjects.createTestUser({ email: 'existing@account.de' });
			const newUser = {
				firstName: 'Test',
				lastName: 'Testington',
				email: 'ExistinG@aCCount.de',
				schoolId: '0000d186816abba584714c5f',
			};

			await new Promise((resolve, reject) => {
				testObjects.createTestUser(newUser)
					.then(() => {
						reject(new Error('This call should fail because of an already existing user with the same email'));
					})
					.catch((err) => {
						expect(err.message).to.equal('Die E-Mail Adresse ExistinG@aCCount.de ist bereits in Verwendung!');
						resolve();
					});
			});
		});
	});

	after(async () => {
		await testObjects.cleanup();
	});
});

describe('registrationPin Service', () => {
	it('registered the registrationPin Service', () => {
		assert.ok(registrationPinService);
	});

	it('creates pins correctly', () => registrationPinService
		.create({ email: 'test.adresse@schul-cloud.org' })
		.then(() => registrationPinService.find({ query: { email: 'test.adresse@schul-cloud.org' } }))
		.then(pinObjects => expect(pinObjects.data[0]).to.have.property('pin')));

	it('overwrites old pins', () => registrationPinService.create({ email: 'test.adresse@schul-cloud.org' })
		.then(() => registrationPinService.create({ email: 'test.adresse@schul-cloud.org' }))
		.then(() => registrationPinService.find({ query: { email: 'test.adresse@schul-cloud.org' } }))
		.then(pinObjects => expect(pinObjects.data).to.have.lengthOf(1)));
});

describe('publicTeachers service', () => {
	let testStudent = {};
	let testTeacherDiscoverable = {};
	let testTeacherNotDiscoverable = {};

	it('register services and create test users', async () => {
		testStudent = await testObjects.createTestUser({
			roles: ['student'],
			discoverable: false,
			schoolId: '0000d186816abba584714c55',
		});
		testTeacherDiscoverable = await testObjects.createTestUser({
			roles: ['teacher'],
			discoverable: true,
			schoolId: '0000d186816abba584714c55',
		});
		testTeacherNotDiscoverable = await testObjects.createTestUser({
			roles: ['teacher'],
			discoverable: false,
			schoolId: '0000d186816abba584714c55',
		});
		assert.ok(userService);
		assert.ok(publicTeachersService);
	});

	// save process.env.IGNORE_DISCOVERABILITY value
	const ORIGINAL_IGNORE_DISCOVERABILITY = process.env.IGNORE_DISCOVERABILITY;
	let result;

	it('without IGNORE_DISCOVERABILITY: find 1 discoverable teacher but not find other users', async () => {
		// test with IGNORE_DISCOVERABILITY = false
		process.env.IGNORE_DISCOVERABILITY = 'false';
		result = await publicTeachersService.find({ query: { schoolId: '0000d186816abba584714c55' } });
		expect(result.total).to.equal(1);
		expect(result.data[0]._id.toString()).to.equal(testTeacherDiscoverable._id.toString());
		expect(result.data[0]._id.toString()).to.not.equal(testStudent._id.toString());
		expect(result.data[0]._id.toString()).to.not.equal(testTeacherNotDiscoverable._id.toString());
	});

	it('with IGNORE_DISCOVERABILITY: find all 2 teachers ignoring their discoverable setting', async () => {
		// test with IGNORE_DISCOVERABILITY = true
		process.env.IGNORE_DISCOVERABILITY = 'true';
		result = await publicTeachersService.find({ query: { schoolId: '0000d186816abba584714c55' } });
		expect(result.total).to.equal(2);
	});

	// reset process.env.IGNORE_DISCOVERABILITY back to original value
	process.env.IGNORE_DISCOVERABILITY = ORIGINAL_IGNORE_DISCOVERABILITY;

	after(async () => {
		await testObjects.cleanup();
	});
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2020 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/iron-icons/iron-icons.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import './style-element.js'

class prefixList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="prefixGrid"
					loading="{{loading}}"
					active-item="{{activeItem}}">
				<vaadin-grid-column width="15ex">
					<template class="header">
						Prefix
					</template>
					<template>[[item.prefix]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex">
					<template class="header">
						Description
					</template>
					<template>[[item.description]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex">
					<template class="header">
						Rate
					</template>
					<template>[[item.rate]]</template>
				</vaadin-grid-column>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap="showAddPrefixModal">
				</paper-fab>

			<iron-ajax id="getTableContentAjax"
					on-response="_getTableContentResponse"
					on-error="_getTableContentError">
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			table: {
				type: String
			},
			activeItem: {
				type: Object,
				notify: true,
				observer: '_activeItemChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('prefixGrid');
		grid.dataProvider = this._getPreTable;
	}

	_getPreTable(params, callback) {
		var grid = this;
		var prefixList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-prefix-list');
		var ajax = prefixList.shadowRoot.getElementById('getTableContentAjax');
//		var table = document.getElementById('prefixList').table;
		var table = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-prefix-list').table;
		ajax.url = "/resourceInventoryManagement/v1/logicalResource/" + table;
		var handleAjaxResponse = function(request) {
			if(request) {
				prefixList.etag = request.xhr.getResponseHeader('ETag');
				var range = request.xhr.getResponseHeader('Content-Range');
				var range1 = range.split("/");
				var range2 = range1[0].split("-");
				if (range1[1] != "*") {
					grid.size = Number(range1[1]);
				} else {
					grid.size = Number(range2[1]) + grid.pageSize * 2;
				}
				var vaadinItems = new Array();
				for (var index in request.response) {
					var resChar = request.response[index].resourceCharacteristic;
					var tabObj = new Object();
					for (var indexRes in resChar) {
						if(resChar[indexRes].name == "prefix") {
							tabObj.prefix = resChar[indexRes].value.value;
						}
						if(resChar[indexRes].name == "description") {
							tabObj.description = resChar[indexRes].value.value;
						}
						if(resChar[indexRes].name == "rate") {
							tabObj.rate = resChar[indexRes].value.value;
						}
						vaadinItems[index] = tabObj;
					}
				}
				callback(vaadinItems);
			} else {
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			prefixList.etag = null;
			var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
			toast.text = error;
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if (ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (prefixList.etag && params.page > 0) {
				ajax.headers['If-Range'] = prefixList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			return ajax.generateRequest().completes;
					}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (prefixList.etag && params.page > 0) {
				ajax.headers['If-Range'] = prefixList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	showAddPrefixModal() {
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-prefix-add').shadowRoot.getElementById('addPrefixModal').open();
	}
}

window.customElements.define('sig-prefix-list', prefixList);

/*<dom-module id="sig-prefix-list">
						cbPrefix = callback;
						var ajax = document.getElementById('getTableContentAjax');
						var table = document.getElementById('prefixList').table;
						ajax.url = "/resourceInventoryManagement/v1/logicalResource/" + table;
						ajax.generateRequest();
					};
				}
			},
			_getTableContentResponse: function(event) {
				var grid = this.$.prefixGrid;
				var results = event.detail.xhr.response;
				var vaadinItems = new Array();
				grid.size = vaadinItems.length;
				cbPrefix(vaadinItems);
			},
			_activeItemChanged: function(item) {
				if(item != null) {
					this.$.prefixGrid.selectedItems = item ? [item] : [];
					document.getElementById("updatePrefixModal").open();
					document.getElementById("updatePrefix").value = item.prefix;
					document.getElementById("updateDescription").value = item.description;
					document.getElementById("updateRate").value = item.rate;
				}
			},
		});
	</script>
</dom-module>*/
<commit_msg>correct grid size<commit_after>/**
 * @license
 * Copyright (c) 2020 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/iron-icons/iron-icons.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import './style-element.js'

class prefixList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="prefixGrid"
					loading="{{loading}}"
					active-item="{{activeItem}}">
				<vaadin-grid-column width="15ex">
					<template class="header">
						Prefix
					</template>
					<template>[[item.prefix]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex">
					<template class="header">
						Description
					</template>
					<template>[[item.description]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex">
					<template class="header">
						Rate
					</template>
					<template>[[item.rate]]</template>
				</vaadin-grid-column>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap="showAddPrefixModal">
				</paper-fab>

			<iron-ajax id="getTableContentAjax"
					on-response="_getTableContentResponse"
					on-error="_getTableContentError">
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			table: {
				type: String
			},
			activeItem: {
				type: Object,
				notify: true,
				observer: '_activeItemChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('prefixGrid');
		grid.dataProvider = this._getPreTable;
	}

	_getPreTable(params, callback) {
		var grid = this;
		var prefixList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-prefix-list');
		var ajax = prefixList.shadowRoot.getElementById('getTableContentAjax');
		var table = document.body.querySelector('sig-app').shadowRoot.querySelector('prefixList').table;
		ajax.url = "/resourceInventoryManagement/v1/logicalResource/" + table;
		var handleAjaxResponse = function(request) {
			if(request) {
				grid.size = 100;
				var vaadinItems = new Array();
				for (var index in request.response) {
					var resChar = request.response[index].resourceCharacteristic;
					var tabObj = new Object();
					for (var indexRes in resChar) {
						if(resChar[indexRes].name == "prefix") {
							tabObj.prefix = resChar[indexRes].value.value;
						}
						if(resChar[indexRes].name == "description") {
							tabObj.description = resChar[indexRes].value.value;
						}
						if(resChar[indexRes].name == "rate") {
							tabObj.rate = resChar[indexRes].value.value;
						}
						vaadinItems[index] = tabObj;
					}
				}
				callback(vaadinItems);
			} else {
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			prefixList.etag = null;
			var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
			toast.text = error;
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if (ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (prefixList.etag && params.page > 0) {
				ajax.headers['If-Range'] = prefixList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			return ajax.generateRequest().completes;
					}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (prefixList.etag && params.page > 0) {
				ajax.headers['If-Range'] = prefixList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	showAddPrefixModal() {
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-prefix-add').shadowRoot.getElementById('addPrefixModal').open();
	}
}

window.customElements.define('sig-prefix-list', prefixList);

/*<dom-module id="sig-prefix-list">
						cbPrefix = callback;
						var ajax = document.getElementById('getTableContentAjax');
						var table = document.getElementById('prefixList').table;
						ajax.url = "/resourceInventoryManagement/v1/logicalResource/" + table;
						ajax.generateRequest();
					};
				}
			},
			_getTableContentResponse: function(event) {
				var grid = this.$.prefixGrid;
				var results = event.detail.xhr.response;
				var vaadinItems = new Array();
				grid.size = vaadinItems.length;
				cbPrefix(vaadinItems);
			},
			_activeItemChanged: function(item) {
				if(item != null) {
					this.$.prefixGrid.selectedItems = item ? [item] : [];
					document.getElementById("updatePrefixModal").open();
					document.getElementById("updatePrefix").value = item.prefix;
					document.getElementById("updateDescription").value = item.description;
					document.getElementById("updateRate").value = item.rate;
				}
			},
		});
	</script>
</dom-module>*/
<|endoftext|>


<commit_before>var abp = abp || {};
(function () {

    // Check if SignalR is defined
    if (!signalR) {
        return;
    }

    // Create namespaces
    abp.signalr = abp.signalr || {};
    abp.signalr.hubs = abp.signalr.hubs || {};
    abp.signalr.reconnectTime = abp.signalr.reconnectTime || 5000;
    abp.signalr.maxTries = abp.signalr.maxTries || 8;
    abp.signalr.increaseReconnectTime = abp.signalr.increaseReconnectTime || function (time) {
        return time * 2;
    };

    // Configure the connection for abp.signalr.hubs.common
    function configureConnection(connection) {
        // Set the common hub
        abp.signalr.hubs.common = connection;

        let tries = 1;
        let reconnectTime = abp.signalr.reconnectTime;

        // Reconnect loop
        function tryReconnect() {
            if (tries > abp.signalr.maxTries) {
                return;
            } else {
                connection.start()
                    .then(() => {
                        reconnectTime = abp.signalr.reconnectTime;
                        tries = 1;
                        console.log('Reconnected to SignalR server!');
                    }).catch(() => {
                        tries += 1;
                        reconnectTime = abp.signalr.increaseReconnectTime(reconnectTime);
                        setTimeout(() => tryReconnect(), reconnectTime);
                    });
            }
        }

        // Reconnect if hub disconnects
        connection.onclose(function (e) {
            if (e) {
                abp.log.debug('Connection closed with error: ' + e);
            } else {
                abp.log.debug('Disconnected');
            }

            if (!abp.signalr.autoReconnect) {
                return;
            }

            tryReconnect();
        });

        // Register to get notifications
        connection.on('getNotification', function (notification) {
            abp.event.trigger('abp.notifications.received', notification);
        });
    }

    // Connect to the server for abp.signalr.hubs.common
    function connect() {
        var url = abp.signalr.url || (abp.appPath + 'signalr');

        // Start the connection
        startConnection(url, configureConnection)
            .then(function (connection) {
                abp.log.debug('Connected to SignalR server!'); //TODO: Remove log
                abp.event.trigger('abp.signalr.connected');
                // Call the Register method on the hub
                connection.invoke('register').then(function () {
                    abp.log.debug('Registered to the SignalR server!'); //TODO: Remove log
                });
            })
            .catch(function (error) {
                abp.log.debug(error.message);
            });
    }

    // Starts a connection with transport fallback - if the connection cannot be started using
    // the webSockets transport the function will fallback to the serverSentEvents transport and
    // if this does not work it will try longPolling. If the connection cannot be started using
    // any of the available transports the function will return a rejected Promise.
    function startConnection(url, configureConnection) {
        if (abp.signalr.remoteServiceBaseUrl) {
            url = abp.signalr.remoteServiceBaseUrl + url;
        }

        // Add query string: https://github.com/aspnet/SignalR/issues/680
        if (abp.signalr.qs) {
            url += (url.indexOf('?') == -1 ? '?' : '&') + abp.signalr.qs;
        }

        return function start(transport) {
            abp.log.debug('Starting connection using ' + signalR.HttpTransportType[transport] + ' transport');
            var connection = new signalR.HubConnectionBuilder()
                .withUrl(url, transport)
                .build();

            if (configureConnection && typeof configureConnection === 'function') {
                configureConnection(connection);
            }

            return connection.start()
                .then(function () {
                    return connection;
                })
                .catch(function (error) {
                    abp.log.debug('Cannot start the connection using ' + signalR.HttpTransportType[transport] + ' transport. ' + error.message);
                    if (transport !== signalR.HttpTransportType.LongPolling) {
                        return start(transport + 1);
                    }

                    return Promise.reject(error);
                });
        }(signalR.HttpTransportType.WebSockets);
    }

    abp.signalr.autoConnect = abp.signalr.autoConnect === undefined ? true : abp.signalr.autoConnect;
    abp.signalr.autoReconnect = abp.signalr.autoReconnect === undefined ? true : abp.signalr.autoReconnect;
    abp.signalr.connect = abp.signalr.connect || connect;
    abp.signalr.startConnection = abp.signalr.startConnection || startConnection;

    if (abp.signalr.autoConnect && !abp.signalr.hubs.common) {
        abp.signalr.connect();
    }
})();
<commit_msg>resolved #5611: replace es6 usage in abp.signalr-client.js<commit_after>var abp = abp || {};
(function () {

    // Check if SignalR is defined
    if (!signalR) {
        return;
    }

    // Create namespaces
    abp.signalr = abp.signalr || {};
    abp.signalr.hubs = abp.signalr.hubs || {};
    abp.signalr.reconnectTime = abp.signalr.reconnectTime || 5000;
    abp.signalr.maxTries = abp.signalr.maxTries || 8;
    abp.signalr.increaseReconnectTime = abp.signalr.increaseReconnectTime || function (time) {
        return time * 2;
    };

    // Configure the connection for abp.signalr.hubs.common
    function configureConnection(connection) {
        // Set the common hub
        abp.signalr.hubs.common = connection;

        let tries = 1;
        let reconnectTime = abp.signalr.reconnectTime;

        // Reconnect loop
        function tryReconnect() {
            if (tries <= abp.signalr.maxTries) {
                connection.start()
                    .then(function () {
                        reconnectTime = abp.signalr.reconnectTime;
                        tries = 1;
                        console.log('Reconnected to SignalR server!');
                    }).catch(function () {
                    tries += 1;
                    reconnectTime = abp.signalr.increaseReconnectTime(reconnectTime);
                    setTimeout(function () {
                            tryReconnect()
                        },
                        reconnectTime
                    );
                });
            }
        }

        // Reconnect if hub disconnects
        connection.onclose(function (e) {
            if (e) {
                abp.log.debug('Connection closed with error: ' + e);
            } else {
                abp.log.debug('Disconnected');
            }

            if (!abp.signalr.autoReconnect) {
                return;
            }

            tryReconnect();
        });

        // Register to get notifications
        connection.on('getNotification', function (notification) {
            abp.event.trigger('abp.notifications.received', notification);
        });
    }

    // Connect to the server for abp.signalr.hubs.common
    function connect() {
        var url = abp.signalr.url || (abp.appPath + 'signalr');

        // Start the connection
        startConnection(url, configureConnection)
            .then(function (connection) {
                abp.log.debug('Connected to SignalR server!'); //TODO: Remove log
                abp.event.trigger('abp.signalr.connected');
                // Call the Register method on the hub
                connection.invoke('register').then(function () {
                    abp.log.debug('Registered to the SignalR server!'); //TODO: Remove log
                });
            })
            .catch(function (error) {
                abp.log.debug(error.message);
            });
    }

    // Starts a connection with transport fallback - if the connection cannot be started using
    // the webSockets transport the function will fallback to the serverSentEvents transport and
    // if this does not work it will try longPolling. If the connection cannot be started using
    // any of the available transports the function will return a rejected Promise.
    function startConnection(url, configureConnection) {
        if (abp.signalr.remoteServiceBaseUrl) {
            url = abp.signalr.remoteServiceBaseUrl + url;
        }

        // Add query string: https://github.com/aspnet/SignalR/issues/680
        if (abp.signalr.qs) {
            url += (url.indexOf('?') == -1 ? '?' : '&') + abp.signalr.qs;
        }

        return function start(transport) {
            abp.log.debug('Starting connection using ' + signalR.HttpTransportType[transport] + ' transport');
            var connection = new signalR.HubConnectionBuilder()
                .withUrl(url, transport)
                .build();

            if (configureConnection && typeof configureConnection === 'function') {
                configureConnection(connection);
            }

            return connection.start()
                .then(function () {
                    return connection;
                })
                .catch(function (error) {
                    abp.log.debug('Cannot start the connection using ' + signalR.HttpTransportType[transport] + ' transport. ' + error.message);
                    if (transport !== signalR.HttpTransportType.LongPolling) {
                        return start(transport + 1);
                    }

                    return Promise.reject(error);
                });
        }(signalR.HttpTransportType.WebSockets);
    }

    abp.signalr.autoConnect = abp.signalr.autoConnect === undefined ? true : abp.signalr.autoConnect;
    abp.signalr.autoReconnect = abp.signalr.autoReconnect === undefined ? true : abp.signalr.autoReconnect;
    abp.signalr.connect = abp.signalr.connect || connect;
    abp.signalr.startConnection = abp.signalr.startConnection || startConnection;

    if (abp.signalr.autoConnect && !abp.signalr.hubs.common) {
        abp.signalr.connect();
    }
})();
<|endoftext|>


<commit_before>var http = require('http');
var util = require('util');

var express = require('express');

var sprintf = require('sprintf').sprintf;

var misc = require('rackspace-shared-utils/lib/misc');
var log = require('logmagic').local('mock-auth-server');

/**
 * Maps tokens to external ids.
 * @type {Object}
 * @const
 */

var TOKEN_TO_INFO = {
  'XXXXXXXXXXZZZZZZZ': ['reachdevsf', '666'],
  'blahahahbtoken': ['username1', '1111'],
  'toldmeicouldntcomeoverandplayanymore' : ['yourmom', '6666'],
  'dev': ['joe', '7777'],
  'never-cache-this': ['fooooo', '02222']
};

var USERNAME_TO_TOKEN_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][0]] = k;
    }
  }
  return rv;
})();

var USERNAME_TO_TENANT_ID_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][0]] = TOKEN_TO_INFO[k][1];
    }
  }
  return rv;
})();

var TENANT_ID_TO_USERNAME_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][1]] = TOKEN_TO_INFO[k][0];
    }
  }
  return rv;
})();

function handleRequest_v_1_1(req, res) {
  var token = req.params.tokenId,
      type = req.query.type,
      fail = req.query.fail || false,
      expiresTs = misc.getUnixTimestamp(), username, expires, statusCode, body;

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();
  username = TOKEN_TO_INFO[token][1];

  if (fail) {
    statusCode = 401;
    body = {};
  }
  else {
    if (!username) {
      username = "reachdevsf";
    }
    statusCode = 200;
    body = {
      'token' : {
        'id' : token,
        'userId' : username,
        'userURL' : '/users/' + username,
        'created' : '2010-11-01T03:32:15-05:00',
        'expires' : expires }
    };
    console.log(body);
  }

  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(JSON.stringify(body));
}

function getToken_v2_0(req, res) {
  var type = req.query.type,
      fail = req.query.fail || false,
      expiresTs = misc.getUnixTimestamp(),
      username,
      tenantId,
      token,
      expires,
      statusCode,
      body,
      creds,
      reason = 'api was asked to fail';

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();

  if (!req.body.auth) {
    fail = true;
    statusCode = 500;
    reason = 'missing auth in body: ' + JSON.stringify(req.body);
  }
  else {
    creds = req.body.auth;

    if (creds.tenantName) {
      tenantId = creds.tenantName;
      username = TENANT_ID_TO_USERNAME_MAP[tenantId];
      token = USERNAME_TO_TOKEN_MAP[username];
    }
    else if (creds['RAX-KSKEY:apiKeyCredentials']) {
      // TODO: actually check the password
      username = creds['RAX-KSKEY:apiKeyCredentials'].username;
      tenantId = USERNAME_TO_TENANT_ID_MAP[username];
      token = USERNAME_TO_TOKEN_MAP[username];
    }

    console.log(creds)

    if (!token || !tenantId) {
      fail = true;
      statusCode = 501;
      reason = 'missing user in map auth map: ' + username + ' token:' + token + ' tenantId:'+ tenantId;
    }
  }

  if (fail) {
    statusCode = statusCode || 401;
    body = {'reason': reason};
  }
  else {
    statusCode = 200;

    body = {
        "access": {
            "token": {
                "id": token,
                "expires": expires,
                "tenant": {"id": tenantId, "name": tenantId}
            },
            "serviceCatalog": [
                {
                    "endpoints": [
                        {
                            "region": "ORD",
                            "tenantId": tenantId,
                            "publicURL": "https://storage101.ord1.clouddrive.com/v1/" + tenantId,
                            "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/"+ tenantId
                        }
                    ],
                    "name": "cloudFiles",
                    "type": "object-store"
                },
                {
                    "endpoints": [
                        {
                            "tenantId": tenantId,
                            "publicURL": "https://servers.api.rackspacecloud.com/v1.0/"+ tenantId,
                            "version": {
                                "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/",
                                "versionList": "https://servers.api.rackspacecloud.com/",
                                "versionId": "1.0"
                            }
                        }
                    ],
                    "name": "cloudServers",
                    "type": "compute"
                },
                {
                    "endpoints": [
                        {
                            "region": "ORD",
                            "tenantId": tenantId,
                            "publicURL": "https://cdn2.clouddrive.com/v1/" + tenantId,
                            "version": {
                                "versionInfo": "https://cdn2.clouddrive.com/v1/",
                                "versionList": "https://cdn2.clouddrive.com/",
                                "versionId": "1"
                            }
                        }
                    ],
                    "name": "cloudFilesCDN",
                    "type": "object-store"
                }
            ],
            "user": {
                "id": "149058",
                "roles": [
                    {
                        "id": "identity:default",
                        "description": "Default Role.",
                        "name": "identity:default"
                    }
                ],
                "name": username
            }
        }
    };
  }

  body = JSON.stringify(body);
  log.info('getToken_v2_0', {statusCode: statusCode, body: body});
  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(body);
}

function validateToken_v2_0(req, res) {
  var type = req.query.type,
      token = req.params.tokenId,
      tenantId,
      fail = req.query.fail ? true : false,
      expiresTs = misc.getUnixTimestamp(),
      username,
      expires,
      statusCode,
      body,
      creds,
      ti,
      reason = 'api was asked to fail';

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();

  if (!fail && !req.headers['x-auth-token']) {
    fail = true;
    statusCode = 500;
    reason = 'missing X-Auth-Token header';
  }
  else if (!fail) {
    ti = TOKEN_TO_INFO[token];

    if (!ti) {
      username = 'reachdevsf';
      tenantId = '666';
    }
    else {
      username = ti[0];
      tenantId = ti[1];
    }

    if (!username || !tenantId) {
      fail = true;
      statusCode = 501;
      reason = 'missing token in map auth map: ' + token + ' token:' + username + ' tenantId:' + tenantId;
    }
  }

  if (fail) {
    statusCode = statusCode || 401;
    body = {unauthorized: {code: statusCode, message: reason}};
  }
  else if (tenantId !== req.query.belongsTo) {
    statusCode = 404;
    body = {"itemNotFound":{"code":404,"message":"Token doesn't belong to Tenant with Id/Name: '"+ req.query.belongsTo +"' realTenantId:"+ tenantId}};
  }
  else {
    statusCode = 200;
    body = {
        "access": {
            "token": {
                "id": token,
                "expires": expires
            },
            "user": {
                "id": "149058",
                "roles": [
                    {
                        "id": "identity:default",
                        "description": "Default Role.",
                        "name": "identity:default"
                    }
                ],
                "name": username
            }
        }
    };
  }

  body = JSON.stringify(body);
  log.info('validateToken_v2_0', {statusCode: statusCode, body: body});
  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(body);
}

function getTenantInfo_v2_0(req, res) {
  if (TENANT_ID_TO_USERNAME_MAP[req.params.tenantId]) {
    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end(JSON.stringify({
      tenant: {
        enabled: true,
        description: 'None',
        name: 'some tenant\'s name'
      }
    }));
  } else {
    res.writeHead(404, {});
    res.end();
  }
}

/**
 * Run mock Auth 1.1 API http server.
 */
function run() {
  var ip = '127.0.0.1',
      port = 23542,
      server = express.createServer();

  server.use(express.bodyParser());
  server.get('/v1.1/token/:tokenId', handleRequest_v_1_1);
  server.post('/v2.0/tokens', getToken_v2_0);
  server.get('/v2.0/tokens/:tokenId', validateToken_v2_0);
  server.get('/v2.0/tenants/:tenantId', getTenantInfo_v2_0);
  server.listen(port, ip);
  util.puts(sprintf('Mock Auth HTTP server listening on IP %s port %s', ip, port));
}

exports.run = run;

exports.USERNAME_TO_TOKEN_MAP = USERNAME_TO_TOKEN_MAP;
exports.USERNAME_TO_TENANT_ID_MAP = USERNAME_TO_TENANT_ID_MAP;
<commit_msg>Remove log statement.<commit_after>var http = require('http');
var util = require('util');

var express = require('express');

var sprintf = require('sprintf').sprintf;

var misc = require('rackspace-shared-utils/lib/misc');
var log = require('logmagic').local('mock-auth-server');

/**
 * Maps tokens to external ids.
 * @type {Object}
 * @const
 */

var TOKEN_TO_INFO = {
  'XXXXXXXXXXZZZZZZZ': ['reachdevsf', '666'],
  'blahahahbtoken': ['username1', '1111'],
  'toldmeicouldntcomeoverandplayanymore' : ['yourmom', '6666'],
  'dev': ['joe', '7777'],
  'never-cache-this': ['fooooo', '02222']
};

var USERNAME_TO_TOKEN_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][0]] = k;
    }
  }
  return rv;
})();

var USERNAME_TO_TENANT_ID_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][0]] = TOKEN_TO_INFO[k][1];
    }
  }
  return rv;
})();

var TENANT_ID_TO_USERNAME_MAP = (function() {
  var k, rv = {};
  for (k in TOKEN_TO_INFO) {
    if (TOKEN_TO_INFO.hasOwnProperty(k)) {
      rv[TOKEN_TO_INFO[k][1]] = TOKEN_TO_INFO[k][0];
    }
  }
  return rv;
})();

function handleRequest_v_1_1(req, res) {
  var token = req.params.tokenId,
      type = req.query.type,
      fail = req.query.fail || false,
      expiresTs = misc.getUnixTimestamp(), username, expires, statusCode, body;

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();
  username = TOKEN_TO_INFO[token][1];

  if (fail) {
    statusCode = 401;
    body = {};
  }
  else {
    if (!username) {
      username = "reachdevsf";
    }
    statusCode = 200;
    body = {
      'token' : {
        'id' : token,
        'userId' : username,
        'userURL' : '/users/' + username,
        'created' : '2010-11-01T03:32:15-05:00',
        'expires' : expires }
    };
    console.log(body);
  }

  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(JSON.stringify(body));
}

function getToken_v2_0(req, res) {
  var type = req.query.type,
      fail = req.query.fail || false,
      expiresTs = misc.getUnixTimestamp(),
      username,
      tenantId,
      token,
      expires,
      statusCode,
      body,
      creds,
      reason = 'api was asked to fail';

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();

  if (!req.body.auth) {
    fail = true;
    statusCode = 500;
    reason = 'missing auth in body: ' + JSON.stringify(req.body);
  }
  else {
    creds = req.body.auth;

    if (creds.tenantName) {
      tenantId = creds.tenantName;
      username = TENANT_ID_TO_USERNAME_MAP[tenantId];
      token = USERNAME_TO_TOKEN_MAP[username];
    }
    else if (creds['RAX-KSKEY:apiKeyCredentials']) {
      // TODO: actually check the password
      username = creds['RAX-KSKEY:apiKeyCredentials'].username;
      tenantId = USERNAME_TO_TENANT_ID_MAP[username];
      token = USERNAME_TO_TOKEN_MAP[username];
    }

    if (!token || !tenantId) {
      fail = true;
      statusCode = 501;
      reason = 'missing user in map auth map: ' + username + ' token:' + token + ' tenantId:'+ tenantId;
    }
  }

  if (fail) {
    statusCode = statusCode || 401;
    body = {'reason': reason};
  }
  else {
    statusCode = 200;

    body = {
        "access": {
            "token": {
                "id": token,
                "expires": expires,
                "tenant": {"id": tenantId, "name": tenantId}
            },
            "serviceCatalog": [
                {
                    "endpoints": [
                        {
                            "region": "ORD",
                            "tenantId": tenantId,
                            "publicURL": "https://storage101.ord1.clouddrive.com/v1/" + tenantId,
                            "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/"+ tenantId
                        }
                    ],
                    "name": "cloudFiles",
                    "type": "object-store"
                },
                {
                    "endpoints": [
                        {
                            "tenantId": tenantId,
                            "publicURL": "https://servers.api.rackspacecloud.com/v1.0/"+ tenantId,
                            "version": {
                                "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/",
                                "versionList": "https://servers.api.rackspacecloud.com/",
                                "versionId": "1.0"
                            }
                        }
                    ],
                    "name": "cloudServers",
                    "type": "compute"
                },
                {
                    "endpoints": [
                        {
                            "region": "ORD",
                            "tenantId": tenantId,
                            "publicURL": "https://cdn2.clouddrive.com/v1/" + tenantId,
                            "version": {
                                "versionInfo": "https://cdn2.clouddrive.com/v1/",
                                "versionList": "https://cdn2.clouddrive.com/",
                                "versionId": "1"
                            }
                        }
                    ],
                    "name": "cloudFilesCDN",
                    "type": "object-store"
                }
            ],
            "user": {
                "id": "149058",
                "roles": [
                    {
                        "id": "identity:default",
                        "description": "Default Role.",
                        "name": "identity:default"
                    }
                ],
                "name": username
            }
        }
    };
  }

  body = JSON.stringify(body);
  log.info('getToken_v2_0', {statusCode: statusCode, body: body});
  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(body);
}

function validateToken_v2_0(req, res) {
  var type = req.query.type,
      token = req.params.tokenId,
      tenantId,
      fail = req.query.fail ? true : false,
      expiresTs = misc.getUnixTimestamp(),
      username,
      expires,
      statusCode,
      body,
      creds,
      ti,
      reason = 'api was asked to fail';

  expires = new Date();
  expires.setTime((expiresTs + 100) * 1000);
  expires = expires.toString();

  if (!fail && !req.headers['x-auth-token']) {
    fail = true;
    statusCode = 500;
    reason = 'missing X-Auth-Token header';
  }
  else if (!fail) {
    ti = TOKEN_TO_INFO[token];

    if (!ti) {
      username = 'reachdevsf';
      tenantId = '666';
    }
    else {
      username = ti[0];
      tenantId = ti[1];
    }

    if (!username || !tenantId) {
      fail = true;
      statusCode = 501;
      reason = 'missing token in map auth map: ' + token + ' token:' + username + ' tenantId:' + tenantId;
    }
  }

  if (fail) {
    statusCode = statusCode || 401;
    body = {unauthorized: {code: statusCode, message: reason}};
  }
  else if (tenantId !== req.query.belongsTo) {
    statusCode = 404;
    body = {"itemNotFound":{"code":404,"message":"Token doesn't belong to Tenant with Id/Name: '"+ req.query.belongsTo +"' realTenantId:"+ tenantId}};
  }
  else {
    statusCode = 200;
    body = {
        "access": {
            "token": {
                "id": token,
                "expires": expires
            },
            "user": {
                "id": "149058",
                "roles": [
                    {
                        "id": "identity:default",
                        "description": "Default Role.",
                        "name": "identity:default"
                    }
                ],
                "name": username
            }
        }
    };
  }

  body = JSON.stringify(body);
  log.info('validateToken_v2_0', {statusCode: statusCode, body: body});
  res.writeHead(statusCode, {'Content-Type': 'application/json'});
  res.end(body);
}

function getTenantInfo_v2_0(req, res) {
  if (TENANT_ID_TO_USERNAME_MAP[req.params.tenantId]) {
    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end(JSON.stringify({
      tenant: {
        enabled: true,
        description: 'None',
        name: 'some tenant\'s name'
      }
    }));
  } else {
    res.writeHead(404, {});
    res.end();
  }
}

/**
 * Run mock Auth 1.1 API http server.
 */
function run() {
  var ip = '127.0.0.1',
      port = 23542,
      server = express.createServer();

  server.use(express.bodyParser());
  server.get('/v1.1/token/:tokenId', handleRequest_v_1_1);
  server.post('/v2.0/tokens', getToken_v2_0);
  server.get('/v2.0/tokens/:tokenId', validateToken_v2_0);
  server.get('/v2.0/tenants/:tenantId', getTenantInfo_v2_0);
  server.listen(port, ip);
  util.puts(sprintf('Mock Auth HTTP server listening on IP %s port %s', ip, port));
}

exports.run = run;

exports.USERNAME_TO_TOKEN_MAP = USERNAME_TO_TOKEN_MAP;
exports.USERNAME_TO_TENANT_ID_MAP = USERNAME_TO_TENANT_ID_MAP;
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('mcp.organizations.members', ['ui.bootstrap'])

    .controller('OrganizationMembersSummaryController', ['$scope', '$stateParams', 'UserContext', 'OrganizationService', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserContext, OrganizationService, AlmanacOrganizationMemberService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });
      }])

    .controller('OrganizationMembersController', ['$scope', '$stateParams', 'UserContext', 'OrganizationService', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserContext, OrganizationService, AlmanacOrganizationMemberService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });

        $scope.canBeRemoved= function(member){
          return $scope.userHasWriteAccess && member.username !== UserContext.currentUser().name;
        };

        $scope.viewState = 'list';
        $scope.remove = function (username) {
        };

        $scope.confirmRemove = function (username) {
          $scope.viewState = 'confirm-remove';
          $scope.selectedMember = username;
        };

        $scope.cancel = function () {
          $scope.viewState = 'list';
          $scope.selectedMember = null;
        };

        $scope.remove = function (member) {
          $scope.busyPromise = OrganizationService.RemoveUserFromOrganization($scope.organization, member.membershipId, function () {
            $scope.viewState = 'remove-success';
          }, function (error) { /*reportError*/
            $scope.viewState = 'remove-failed';
            console.log("Error, dammit!", error);
            //$scope.viewState = 'error';
          });
        };

      }])

    .controller('OrganizationInviteMemberController', ['$scope', '$stateParams', 'UserService', 'UserContext', 'OrganizationService', 'UUID', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserService, UserContext, OrganizationService, UUID, AlmanacOrganizationMemberService) {

        $scope.filter_query = '';
        $scope.viewState = 'invite';
        $scope.orderProp = 'username';

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });

        $scope.isNewMember = function (user) {
          for (var i = 0; i < $scope.organization.members.length; i++) {
            if (user.username === $scope.organization.members[i].username) {
              return false;
            }
          }
          return true;
        };

        $scope.updateSearch = function (pattern) {
          if (pattern.trim().length > 0) {
            $scope.busyPromiseSearch = UserService.query({usernamePattern: pattern}, function (users) {
              $scope.people = users;
            }).$promise;
          } else {
            $scope.people = [];
          }
        };

        $scope.confirm = function (member) {
          $scope.invitedMember = member;
          $scope.viewState = 'confirm';
        };

        $scope.invite = function (member) {

          // fetch and assign a new UUID from the server
          UUID.get({name: "identifier"}, function (newMembershipId) {

            // call server with an invite-request !
            $scope.busyPromise = OrganizationService.InviteUserToOrganization($scope.organization, newMembershipId.identifier, member, function () {
              $scope.viewState = 'success';
            }, function (error) { /*reportError*/
              console.log("Error, dammit!", error);
              $scope.viewState = 'error';
            });
          });

        };
      }])

    ;

<commit_msg>ECLOUD-132: Fixed an "undefined" error on the console<commit_after>'use strict';

/* Controllers */

angular.module('mcp.organizations.members', ['ui.bootstrap'])

    .controller('OrganizationMembersSummaryController', ['$scope', '$stateParams', 'UserContext', 'OrganizationService', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserContext, OrganizationService, AlmanacOrganizationMemberService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });
      }])

    .controller('OrganizationMembersController', ['$scope', '$stateParams', 'UserContext', 'OrganizationService', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserContext, OrganizationService, AlmanacOrganizationMemberService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });

        $scope.canBeRemoved= function(member){
          return $scope.userHasWriteAccess && UserContext.currentUser() && member.username !== UserContext.currentUser().name;
        };

        $scope.viewState = 'list';
        $scope.remove = function (username) {
        };

        $scope.confirmRemove = function (username) {
          $scope.viewState = 'confirm-remove';
          $scope.selectedMember = username;
        };

        $scope.cancel = function () {
          $scope.viewState = 'list';
          $scope.selectedMember = null;
        };

        $scope.remove = function (member) {
          $scope.busyPromise = OrganizationService.RemoveUserFromOrganization($scope.organization, member.membershipId, function () {
            $scope.viewState = 'remove-success';
          }, function (error) { /*reportError*/
            $scope.viewState = 'remove-failed';
            console.log("Error, dammit!", error);
            //$scope.viewState = 'error';
          });
        };

      }])

    .controller('OrganizationInviteMemberController', ['$scope', '$stateParams', 'UserService', 'UserContext', 'OrganizationService', 'UUID', 'AlmanacOrganizationMemberService',
      function ($scope, $stateParams, UserService, UserContext, OrganizationService, UUID, AlmanacOrganizationMemberService) {

        $scope.filter_query = '';
        $scope.viewState = 'invite';
        $scope.orderProp = 'username';

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId}, function (organization) {
          $scope.organization.members = AlmanacOrganizationMemberService.query({organizationId: organization.organizationId});
          $scope.userHasWriteAccess = UserContext.isAdminMemberOf($scope.organization.organizationId);
        });

        $scope.isNewMember = function (user) {
          for (var i = 0; i < $scope.organization.members.length; i++) {
            if (user.username === $scope.organization.members[i].username) {
              return false;
            }
          }
          return true;
        };

        $scope.updateSearch = function (pattern) {
          if (pattern.trim().length > 0) {
            $scope.busyPromiseSearch = UserService.query({usernamePattern: pattern}, function (users) {
              $scope.people = users;
            }).$promise;
          } else {
            $scope.people = [];
          }
        };

        $scope.confirm = function (member) {
          $scope.invitedMember = member;
          $scope.viewState = 'confirm';
        };

        $scope.invite = function (member) {

          // fetch and assign a new UUID from the server
          UUID.get({name: "identifier"}, function (newMembershipId) {

            // call server with an invite-request !
            $scope.busyPromise = OrganizationService.InviteUserToOrganization($scope.organization, newMembershipId.identifier, member, function () {
              $scope.viewState = 'success';
            }, function (error) { /*reportError*/
              console.log("Error, dammit!", error);
              $scope.viewState = 'error';
            });
          });

        };
      }])

    ;

<|endoftext|>


<commit_before>define(function () {
    var plugin = {
        settings: {
            name: "upload",
            type: "general",
            icon: "plugins/upload/icon.png",
            subMenus: [
                {name: "browsephotoalbums", menuURL: "#upload/browse", icon: ""},
                {name: "takepicture", menuURL: "#upload/take", icon: ""},
                {name: "recordaudio", menuURL: "#upload/record", icon: ""},
                {name: "video", menuURL: "#upload/video", icon: ""}
            ],
            lang: {
                component: "core"
            },
            toogler: true
        },

        routes: [
            ["upload/browse", "upload_browse", "browseAlbums"],
            ["upload/take", "upload_take", "takeMedia"],
            ["upload/record", "upload_record", "recordAudio"],
            ["upload/video", "upload_video", "uploadVideo"]
        ],

        browseAlbums: function() {
            MM.log('Trying to get a image from albums', 'Upload');
            MM.Router.navigate("");

            var width  =  $(document).innerWidth()  - 200;
            var height =  $(document).innerHeight() - 200;

            // iPad popOver, see https://tracker.moodle.org/browse/MOBILE-208
            var popover = new CameraPopoverOptions(10, 10, width, height, Camera.PopoverArrowDirection.ARROW_ANY);

            navigator.camera.getPicture(MM.plugins.upload.photoSuccess, MM.plugins.upload.photoFails, {
                quality: 50,
                destinationType: navigator.camera.DestinationType.FILE_URI,
                sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
                popoverOptions : popover
            });
        },

        takeMedia: function() {
            MM.log('Trying to get a image from camera', 'Upload');
            MM.Router.navigate("");

            navigator.camera.getPicture(MM.plugins.upload.photoSuccess, MM.plugins.upload.photoFails, {
                quality: 50,
                destinationType: navigator.camera.DestinationType.FILE_URI
            });
        },

        recordAudio: function() {
            MM.Router.navigate("");
            MM.log('Trying to record and Audio', 'Upload');
            navigator.device.capture.captureAudio(MM.plugins.upload.recordAudioSuccess, MM.plugins.upload.recordAudioFails, {limit: 1});
        },

        uploadVideo: function() {
            MM.Router.navigate("");
            MM.log('Trying to record a video', 'Upload');
            navigator.device.capture.captureVideo(
                MM.plugins.upload.uploadVideoSuccess,
                MM.plugins.upload.uploadVideoFails,
                {limit: 1});
        },

        photoSuccess: function(uri) {

            MM.log('Uploading an image to Moodle', 'Upload');
            var d = new Date();

            var options = {};
            options.fileKey="file";

            // Check if is a URI or a file system path.
            if (uri.indexOf('data:') > -1) {
                options.fileName = "image_" + d.getTime() + ".jpg";
            } else {
                options.fileName = uri.lastIndexOf("/") + 1;
            }

            options.mimeType="image/jpeg";

            MM.moodleUploadFile(uri, options,
                                function(){ MM.popMessage(MM.lang.s("imagestored")); },
                                function(){ MM.popErrorMessage(MM.lang.s("erroruploading")) }
            );

        },

        photoFails: function(message) {
            MM.log('Error trying getting a photo', 'Upload');
            if (message.toLowerCase().indexOf("error") > -1 || message.toLowerCase().indexOf("unable") > -1) {
                MM.popErrorMessage(message);
            }
        },

        recordAudioSuccess: function(mediaFiles) {

            MM.log('Auddio sucesfully recorded', 'Upload');

            var i, len;
            for (i = 0, len = mediaFiles.length; i < len; i += 1) {
                var options = {};
                options.fileKey = null;
                options.fileName = mediaFiles[i].name;
                options.mimeType = null;

                MM.moodleUploadFile(mediaFiles[i].toURL(), options,
                                    function(){
                                        MM.popMessage(MM.lang.s("recordstored"));
                                    },
                                    function(){
                                        MM.popErrorMessage(MM.lang.s("erroruploading"))
                                    }
                );
            }
        },

        recordAudioFails: function(error) {
            if (!error) {
                error = { code: 0};
            }

            MM.log('Error trying recording an audio ' + error.code, 'Upload');
            if (error.code != CaptureError.CAPTURE_NO_MEDIA_FILES) {
                MM.popErrorMessage(MM.lang.s("errorcapturingaudio"));
            }
        },

        uploadVideoSuccess: function(mediaFiles) {

            MM.log('Video sucesfully recorded', 'Upload');

            var i, len;
            for (i = 0, len = mediaFiles.length; i < len; i += 1) {
                var options = {};
                options.fileKey = null;
                options.fileName = mediaFiles[i].name;
                options.mimeType = null;

                MM.moodleUploadFile(mediaFiles[i].toURL(), options,
                                    function(){
                                        MM.popMessage(MM.lang.s("videostored"));
                                    },
                                    function(){
                                        MM.popErrorMessage(MM.lang.s("erroruploading"))
                                    }
                );
            }
        },

        uploadVideoFails: function(error) {
            if (!error) {
                error = { code: 0};
            }

            MM.log('Error trying recording a video ' + error.code, 'Upload');
            if (error.code != CaptureError.CAPTURE_NO_MEDIA_FILES) {
                MM.popErrorMessage(MM.lang.s("errorcapturingvideo"));
            }
        }
    }

    MM.registerPlugin(plugin);

});<commit_msg>FileTransfer must use fullPath (instead toURL())<commit_after>define(function () {
    var plugin = {
        settings: {
            name: "upload",
            type: "general",
            icon: "plugins/upload/icon.png",
            subMenus: [
                {name: "browsephotoalbums", menuURL: "#upload/browse", icon: ""},
                {name: "takepicture", menuURL: "#upload/take", icon: ""},
                {name: "recordaudio", menuURL: "#upload/record", icon: ""},
                {name: "video", menuURL: "#upload/video", icon: ""}
            ],
            lang: {
                component: "core"
            },
            toogler: true
        },

        routes: [
            ["upload/browse", "upload_browse", "browseAlbums"],
            ["upload/take", "upload_take", "takeMedia"],
            ["upload/record", "upload_record", "recordAudio"],
            ["upload/video", "upload_video", "uploadVideo"]
        ],

        browseAlbums: function() {
            MM.log('Trying to get a image from albums', 'Upload');
            MM.Router.navigate("");

            var width  =  $(document).innerWidth()  - 200;
            var height =  $(document).innerHeight() - 200;

            // iPad popOver, see https://tracker.moodle.org/browse/MOBILE-208
            var popover = new CameraPopoverOptions(10, 10, width, height, Camera.PopoverArrowDirection.ARROW_ANY);

            navigator.camera.getPicture(MM.plugins.upload.photoSuccess, MM.plugins.upload.photoFails, {
                quality: 50,
                destinationType: navigator.camera.DestinationType.FILE_URI,
                sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
                popoverOptions : popover
            });
        },

        takeMedia: function() {
            MM.log('Trying to get a image from camera', 'Upload');
            MM.Router.navigate("");

            navigator.camera.getPicture(MM.plugins.upload.photoSuccess, MM.plugins.upload.photoFails, {
                quality: 50,
                destinationType: navigator.camera.DestinationType.FILE_URI
            });
        },

        recordAudio: function() {
            MM.Router.navigate("");
            MM.log('Trying to record and Audio', 'Upload');
            navigator.device.capture.captureAudio(MM.plugins.upload.recordAudioSuccess, MM.plugins.upload.recordAudioFails, {limit: 1});
        },

        uploadVideo: function() {
            MM.Router.navigate("");
            MM.log('Trying to record a video', 'Upload');
            navigator.device.capture.captureVideo(
                MM.plugins.upload.uploadVideoSuccess,
                MM.plugins.upload.uploadVideoFails,
                {limit: 1});
        },

        photoSuccess: function(uri) {

            MM.log('Uploading an image to Moodle', 'Upload');
            var d = new Date();

            var options = {};
            options.fileKey="file";

            // Check if is a URI or a file system path.
            if (uri.indexOf('data:') > -1) {
                options.fileName = "image_" + d.getTime() + ".jpg";
            } else {
                options.fileName = uri.lastIndexOf("/") + 1;
            }

            options.mimeType="image/jpeg";

            MM.moodleUploadFile(uri, options,
                                function(){ MM.popMessage(MM.lang.s("imagestored")); },
                                function(){ MM.popErrorMessage(MM.lang.s("erroruploading")) }
            );

        },

        photoFails: function(message) {
            MM.log('Error trying getting a photo', 'Upload');
            if (message.toLowerCase().indexOf("error") > -1 || message.toLowerCase().indexOf("unable") > -1) {
                MM.popErrorMessage(message);
            }
        },

        recordAudioSuccess: function(mediaFiles) {

            MM.log('Auddio sucesfully recorded', 'Upload');

            var i, len;
            for (i = 0, len = mediaFiles.length; i < len; i += 1) {
                var options = {};
                options.fileKey = null;
                options.fileName = mediaFiles[i].name;
                options.mimeType = null;

                MM.moodleUploadFile(mediaFiles[i].fullPath, options,
                                    function(){
                                        MM.popMessage(MM.lang.s("recordstored"));
                                    },
                                    function(){
                                        MM.popErrorMessage(MM.lang.s("erroruploading"))
                                    }
                );
            }
        },

        recordAudioFails: function(error) {
            if (!error) {
                error = { code: 0};
            }

            MM.log('Error trying recording an audio ' + error.code, 'Upload');
            if (error.code != CaptureError.CAPTURE_NO_MEDIA_FILES) {
                MM.popErrorMessage(MM.lang.s("errorcapturingaudio"));
            }
        },

        uploadVideoSuccess: function(mediaFiles) {

            MM.log('Video sucesfully recorded', 'Upload');

            var i, len;
            for (i = 0, len = mediaFiles.length; i < len; i += 1) {
                var options = {};
                options.fileKey = null;
                options.fileName = mediaFiles[i].name;
                options.mimeType = null;

                MM.moodleUploadFile(mediaFiles[i].fullPath, options,
                                    function(){
                                        MM.popMessage(MM.lang.s("videostored"));
                                    },
                                    function(){
                                        MM.popErrorMessage(MM.lang.s("erroruploading"))
                                    }
                );
            }
        },

        uploadVideoFails: function(error) {
            if (!error) {
                error = { code: 0};
            }

            MM.log('Error trying recording a video ' + error.code, 'Upload');
            if (error.code != CaptureError.CAPTURE_NO_MEDIA_FILES) {
                MM.popErrorMessage(MM.lang.s("errorcapturingvideo"));
            }
        }
    }

    MM.registerPlugin(plugin);

});<|endoftext|>


<commit_before><commit_msg>[store] Add tests<commit_after><|endoftext|>


<commit_before>/**
 * 自定义MHD 类
 * @constructor HMD
 */
function MHD() {
    //
}

// MHD 原型方法

/**
 * 数组/对象的forEachF方法
 * @param {Object=}     thisArg             callback 回调函数中 this 上下文
 * @param {MHD~forEachCallback} callback    forEach的回调函数
 */

/**
 * This callback is displayed as part of the MHD class.
 * @callback MHD~forEachCallback
 * @param {String|Object}   kValue          回调函数第一个参数value
 * @param {string}          k               当前索引index
 * @param {string}          O               当前递归的数组
 * @this  {Object}          thisArg
 */
MHD.prototype.forEach = function(callback, thisArg) {
    var T, k
    if (this === null) {
        throw new TypeError('this is null or not defined')
    }

    // Let O be the result of calling toObject() passing the |this| value as the argument.
    // 确保this一定是一个对象类型
    var O = Object(this)

    // Let len be toUint32(lenValue).
    // 确保len 是一个32位无符号整数。该操作保证：所有非数值转换成0; 所有大于等于 0 等数取整数部分
    var len = O.length >>> 0

    // If isCallable(callback) is false, throw a TypeError exception.
    if (typeof callback !== 'function') {
        throw new TypeError(callback + 'is not a function!')
    }

    // If thisArg was supplied, let T be thisArg else let T be undefined.
    if (arguments.length > 1) {
        T = thisArg
    }

    k = 0

    while(k < len) {
        var kValue
        if (k in O) {
            kValue = O[k]
        }
        callback.call(T, kValue, k, O)
    }
    k++
}

// MHD类的静态方法
/**
 * 浏览器-UUID生成器
 * 浏览器环境使用crypto API生成符合RFC4122版本4的UUID，该方法不适合node环境。node环境可参照：https://github.com/kelektiv/node-uuid
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/RandomSource/getRandomValues 浏览器环境crypto API:
 * @see http://nodejs.cn/api/crypto.html nodejs crypto API
 * @example
 * uuid()  // '7982fcfe-5721-4632-bede-6000885be57d'
 */
MHD.uuid = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16))

// MHD模块
// 先整体导出这个类， 后续优化导出为类的实例
module.exports = MHD
<commit_msg>:art: Mhd类修正<commit_after>/**
 * 自定义Mhd 类 实例是一个Array-like对象
 * @param {String|Number|Boolean|Null|Undefined|Symbol}  原始数据类型优先
 * @constructor Mhd
 */
function Mhd() {
    var len = arguments.length
    this.length = len

    var i = len - 1
    while( i >= 0 ) {
        this[i] = arguments[i]
        i--
    }
}

// Mhd 原型方法

/**
 * 数组/对象的forEachF方法
 * @param {Object=}     thisArg             callback 回调函数中 this 上下文
 * @param {Mhd~forEachCallback} callback    forEach的回调函数
 */

/**
 * This callback is displayed as part of the Mhd class.
 * @callback Mhd~forEachCallback
 * @param {String|Object}   kValue          回调函数第一个参数value
 * @param {string}          k               当前索引index
 * @param {string}          O               当前递归的数组
 * @this  {Object}          thisArg
 */
Mhd.prototype.forEach = function(callback, thisArg) {
    var T, k
    if (this === null) {
        throw new TypeError('this is null or not defined')
    }

    // Let O be the result of calling toObject() passing the |this| value as the argument.
    // 确保this一定是一个对象类型
    var O = Object(this)

    // Let len be toUint32(lenValue).
    // 确保len 是一个32位无符号整数。该操作保证：所有非数值转换成0; 所有大于等于 0 等数取整数部分
    var len = O.length >>> 0

    // If isCallable(callback) is false, throw a TypeError exception.
    if (typeof callback !== 'function') {
        throw new TypeError(callback + 'is not a function!')
    }

    // If thisArg was supplied, let T be thisArg else let T be undefined.
    if (arguments.length > 1) {
        T = thisArg
    }

    k = 0

    while(k < len) {
        var kValue
        if (k in O) {
            kValue = O[k]
        }
        callback.call(T, kValue, k, O)
        k++
    }
}

// Mhd类的静态方法
/**
 * 浏览器-UUID生成器
 * 浏览器环境使用crypto API生成符合RFC4122版本4的UUID，该方法不适合node环境。node环境可参照：https://github.com/kelektiv/node-uuid
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/RandomSource/getRandomValues 浏览器环境crypto API:
 * @see http://nodejs.cn/api/crypto.html nodejs crypto API
 * @example
 * uuid()  // '7982fcfe-5721-4632-bede-6000885be57d'
 */
Mhd.uuid = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16))

// Mhd模块
// 先整体导出这个类， 后续优化导出为类的实例
module.exports = Mhd
<|endoftext|>