text:
const _ = require('lodash');
const should = require('should');
const supertest = require('supertest');
const config = require('../../../../core/shared/config');
const testUtils = require('../../../utils');
const localUtils = require('./utils');
const db = require('../../../../core/server/data/db');

// NOTE: in future iterations these fields should be fetched from a central module.
//       Have put a list as is here for the lack of better place for it.
const defaultSettingsKeyTypes = [
    {
        key: 'title',
        type: 'string',
        group: 'site'
    },
    {
        key: 'description',
        type: 'string',
        group: 'site'
    },
    {
        key: 'logo',
        type: 'string',
        group: 'site'
    },
    {
        key: 'cover_image',
        type: 'string',
        group: 'site'
    },
    {
        key: 'icon',
        type: 'string',
        group: 'site'
    },
    {
        key: 'lang',
        type: 'string',
        group: 'site'
    },
    {
        key: 'locale',
        type: 'string',
        group: 'site'
    },
    {
        key: 'timezone',
        type: 'string',
        group: 'site'
    },
    {
        key: 'codeinjection_head',
        type: 'string',
        group: 'site'
    },
    {
        key: 'codeinjection_foot',
        type: 'string',
        group: 'site'
    },
    {
        key: 'facebook',
        type: 'string',
        group: 'site'
    },
    {
        key: 'twitter',
        type: 'string',
        group: 'site'
    },
    {
        key: 'navigation',
        type: 'array',
        group: 'site'
    },
    {
        key: 'secondary_navigation',
        type: 'array',
        group: 'site'
    },
    {
        key: 'meta_title',
        type: 'string',
        group: 'site'
    },
    {
        key: 'meta_description',
        type: 'string',
        group: 'site'
    },
    {
        key: 'og_image',
        type: 'string',
        group: 'site'
    },
    {
        key: 'og_title',
        type: 'string',
        group: 'site'
    },
    {
        key: 'og_description',
        type: 'string',
        group: 'site'
    },
    {
        key: 'twitter_image',
        type: 'string',
        group: 'site'
    },
    {
        key: 'twitter_title',
        type: 'string',
        group: 'site'
    },
    {
        key: 'twitter_description',
        type: 'string',
        group: 'site'
    },
    {
        key: 'active_theme',
        type: 'string',
        group: 'theme'
    },
    {
        key: 'is_private',
        type: 'boolean',
        group: 'private'
    },
    {
        key: 'password',
        type: 'string',
        group: 'private'
    },
    {
        key: 'public_hash',
        type: 'string',
        group: 'private'
    },
    {
        key: 'default_content_visibility',
        type: 'string',
        group: 'members'
    },
    {
        key: 'default_content_visibility_tiers',
        type: 'array',
        group: 'members'
    },
    {
        key: 'members_signup_access',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_from_address',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_support_address',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_reply_address',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_paid_signup_redirect',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_free_signup_redirect',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_free_price_name',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_free_price_description',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_monthly_price_id',
        type: 'string',
        group: 'members'
    },
    {
        key: 'members_yearly_price_id',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_product_name',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_plans',
        type: 'array',
        group: 'members'
    },
    {
        key: 'stripe_secret_key',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_publishable_key',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_connect_secret_key',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_connect_publishable_key',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_connect_account_id',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_connect_display_name',
        type: 'string',
        group: 'members'
    },
    {
        key: 'stripe_connect_livemode',
        type: 'boolean',
        group: 'members'
    },
    {
        key: 'portal_name',
        type: 'boolean',
        group: 'portal'
    },
    {
        key: 'portal_button',
        type: 'boolean',
        group: 'portal'
    },
    {
        key: 'portal_plans',
        type: 'array',
        group: 'portal'
    },
    {
        key: 'portal_products',
        type: 'array',
        group: 'portal'
    },
    {
        key: 'portal_button_style',
        type: 'string',
        group: 'portal'
    },
    {
        key: 'portal_button_icon',
        type: 'string',
        group: 'portal'
    },
    {
        key: 'portal_button_signup_text',
        type: 'string',
        group: 'portal'
    },
    {
        key: 'mailgun_api_key',
        type: 'string',
        group: 'email'
    },
    {
        key: 'mailgun_domain',
        type: 'string',
        group: 'email'
    },
    {
        key: 'mailgun_base_url',
        type: 'string',
        group: 'email'
    },
    {
        key: 'email_track_opens',
        type: 'boolean',
        group: 'email'
    },
    {
        key: 'email_verification_required',
        type: 'boolean',
        group: 'email'
    },
    {
        key: 'amp',
        type: 'boolean',
        group: 'amp'
    },
    {
        key: 'amp_gtag_id',
        type: 'string',
        group: 'amp'
    },
    {
        key: 'slack',
        type: 'string',
        group: 'slack'
    },
    {
        key: 'slack_url',
        type: 'string',
        group: 'slack'
    },
    {
        key: 'slack_username',
        type: 'string',
        group: 'slack'
    },
    {
        key: 'unsplash',
        type: 'boolean',
        group: 'unsplash'
    },
    {
        key: 'shared_views',
        type: 'array',
        group: 'views'
    },
    {
        key: 'active_timezone',
        type: 'string',
        group: 'site'
    },
    {
        key: 'default_locale',
        type: 'string',
        group: 'site'
    },
    {
        key: 'accent_color',
        type: 'string',
        group: 'site'
    },
    {
        key: 'newsletter_show_badge',
        type: 'boolean',
        group: 'newsletter'
    },
    {
        key: 'newsletter_header_image',
        type: 'string',
        group: 'newsletter'
    },
    {
        key: 'newsletter_show_header_icon',
        type: 'boolean',
        group: 'newsletter'
    },
    {
        key: 'newsletter_show_header_title',
        type: 'boolean',
        group: 'newsletter'
    },
    {
        key: 'newsletter_title_alignment',
        type: 'string',
        group: 'newsletter'
    },
    {
        key: 'newsletter_title_font_category',
        type: 'string',
        group: 'newsletter'
    },
    {
        key: 'newsletter_show_feature_image',
        type: 'boolean',
        group: 'newsletter'
    },
    {
        key: 'newsletter_body_font_category',
        type: 'string',
        group: 'newsletter'
    },
    {
        key: 'newsletter_footer_content',
        type: 'string',
        group: 'newsletter'
    },
    {
        key: 'firstpromoter',
        type: 'boolean',
        group: 'firstpromoter'
    },
    {
        key: 'firstpromoter_id',
        type: 'string',
        group: 'firstpromoter'
    },
    {
        key: 'oauth_client_id',
        type: 'string',
        group: 'oauth'
    },
    {
        key: 'oauth_client_secret',
        type: 'string',
        group: 'oauth'
    },
    {
        key: 'editor_default_email_recipients',
        type: 'string',
        group: 'editor'
    },
    {
        key: 'editor_default_email_recipients_filter',
        type: 'string',
        group: 'editor'
    },
    {
        key: 'editor_is_launch_complete',
        type: 'boolean',
        group: 'editor'
    },
    {
        key: 'labs',
        type: 'object',
        group: 'labs'
    }
];

describe('Settings API (canary)', function () {
    let request;

    describe('As Owner', function () {
        before(async function () {
            await localUtils.startGhost();
            request = supertest.agent(config.get('url'));
            await localUtils.doAuth(request);
        });

        it('Can request all settings', function () {
            return request.get(localUtils.API.getApiQuery(`settings/`))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .then((res) => {
                    should.not.exist(res.headers['x-cache-invalidate']);

                    const jsonResponse = res.body;
                    should.exist(jsonResponse.settings);
                    should.exist(jsonResponse.meta);

                    jsonResponse.settings.should.be.an.Object();
                    const settings = jsonResponse.settings;

                    should.equal(settings.length, defaultSettingsKeyTypes.length);
                    for (const defaultSetting of defaultSettingsKeyTypes) {
                        should.exist(settings.find((setting) => {
                            return (setting.key === defaultSetting.key)
                                && (setting.type === defaultSetting.type)
                                && (setting.group === defaultSetting.group);
                        }), `Expected to find a setting with key ${defaultSetting.key}, type ${defaultSetting.type}, and group ${defaultSetting.group}`);
                    }

                    const unsplash = settings.find(s => s.key === 'unsplash');
                    should.exist(unsplash);
                    unsplash.value.should.equal(true);

                    localUtils.API.checkResponse(jsonResponse, 'settings');
                });
        });

        it('Ignores the deprecated type filter', function () {
            return request.get(localUtils.API.getApiQuery(`settings/?type=theme`))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .then((res) => {
                    should.not.exist(res.headers['x-cache-invalidate']);

                    const jsonResponse = res.body;
                    should.exist(jsonResponse.settings);
                    should.exist(jsonResponse.meta);

                    jsonResponse.settings.should.be.an.Object();
                    const settings = jsonResponse.settings;
                    // Returns all settings
                    should.equal(settings.length, defaultSettingsKeyTypes.length);
                    for (const defaultSetting of defaultSettingsKeyTypes) {
                        should.exist(settings.find((setting) => {
                            return setting.key === defaultSetting.key && setting.type === defaultSetting.type;
                        }), `Expected to find a setting with key ${defaultSetting.key} and type ${defaultSetting.type}`);
                    }

                    localUtils.API.checkResponse(jsonResponse, 'settings');
                });
        });

        it('Can request settings by group', function () {
            return request.get(localUtils.API.getApiQuery(`settings/?group=theme`))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .then((res) => {
                    should.not.exist(res.headers['x-cache-invalidate']);

                    const jsonResponse = res.body;
                    should.exist(jsonResponse.settings);
                    should.exist(jsonResponse.meta);

                    jsonResponse.settings.should.be.an.Object();
                    const settings = jsonResponse.settings;

                    Object.keys(settings).length.should.equal(1);
                    settings[0].key.should.equal('active_theme');
                    settings[0].value.should.equal('casper');
                    settings[0].type.should.equal('string');
                    settings[0].group.should.equal('theme');

                    localUtils.API.checkResponse(jsonResponse, 'settings');
                });
        });

        it('Requesting core settings type ignores the parameter and returns all settings', function () {
            return request.get(localUtils.API.getApiQuery(`settings/?type=core`))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .then((res) => {
                    should.not.exist(res.headers['x-cache-invalidate']);

                    const jsonResponse = res.body;
                    should.exist(jsonResponse.settings);
                    should.exist(jsonResponse.meta);

                    jsonResponse.settings.should.be.an.Object();
                    const settings = jsonResponse.settings;

                    Object.keys(settings).length.should.equal(defaultSettingsKeyTypes.length);

                    localUtils.API.checkResponse(jsonResponse, 'settings');
                });
        });

        it('Can\'t read core setting', function () {
            return request
                .get(localUtils.API.getApiQuery('settings/db_hash/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(403);
        });

        it('Can\'t read secret setting', function (done) {
            const key = 'stripe_secret_key';
            request
                .get(localUtils.API.getApiQuery(`settings/${key}/`))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    const json = res.body;
                    should.exist(json);
                    should.exist(json.settings);

                    json.settings.length.should.eql(1);
                    json.settings[0].key.should.eql('stripe_secret_key');
                    should(json.settings[0].value).be.null();

                    done();
                });
        });

        it('Can\'t read secret setting', function (done) {
            const key = 'stripe_secret_key';
            request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send({
                    settings: [{
                        key,
                        value: 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
                    }]
                })
                .then(() => {
                    request
                        .get(localUtils.API.getApiQuery(`settings/${key}/`))
                        .set('Origin', config.get('url'))
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(200)
                        .end(function (err, res) {
                            if (err) {
                                return done(err);
                            }

                            const json = res.body;
                            should.exist(json);
                            should.exist(json.settings);

                            json.settings.length.should.eql(1);
                            json.settings[0].key.should.eql('stripe_secret_key');
                            json.settings[0].value.should.eql('••••••••');

                            done();
                        });
                });
        });

        it('Can\'t read permalinks', function (done) {
            request.get(localUtils.API.getApiQuery('settings/permalinks/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(404)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    done();
                });
        });

        it('Can read slack_url introduced in v4', function (done) {
            request.get(localUtils.API.getApiQuery('settings/slack_url/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);
                    jsonResponse.settings[0].key.should.eql('slack_url');
                    done();
                });
        });

        it('Can read labs', async function () {
            const res = await request.get(localUtils.API.getApiQuery('settings/labs/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200);

            should.not.exist(res.headers['x-cache-invalidate']);
            const jsonResponse = res.body;

            should.exist(jsonResponse);
            should.exist(jsonResponse.settings);

            jsonResponse.settings.length.should.eql(1);
            testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);

            const jsonObjectRegex = /^\{.*\}$/; // '{...}'
            jsonResponse.settings[0].key.should.eql('labs');
            jsonResponse.settings[0].value.should.match(jsonObjectRegex);
        });

        it('Can read deprecated default_locale', function (done) {
            request.get(localUtils.API.getApiQuery('settings/default_locale/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('default_locale');
                    done();
                });
        });

        it('Can edit deprecated default_locale setting', function () {
            return request.get(localUtils.API.getApiQuery('settings/default_locale/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;
                    const newValue = 'new value';
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'default_locale', value: 'ua'}];

                    return jsonResponse;
                })
                .then((editedSetting) => {
                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(editedSetting)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(200)
                        .then(function (res) {
                            should.exist(res.headers['x-cache-invalidate']);
                            const jsonResponse = res.body;

                            should.exist(jsonResponse);
                            should.exist(jsonResponse.settings);

                            jsonResponse.settings.length.should.eql(1);

                            testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                            jsonResponse.settings[0].key.should.eql('default_locale');
                            jsonResponse.settings[0].value.should.eql('ua');
                        });
                });
        });

        it('Can edit deprecated lang setting', function () {
            return request.get(localUtils.API.getApiQuery('settings/lang/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'lang', value: 'ua'}];

                    return jsonResponse;
                })
                .then((editedSetting) => {
                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(editedSetting)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(200)
                        .then(function (res) {
                            should.exist(res.headers['x-cache-invalidate']);
                            const jsonResponse = res.body;

                            should.exist(jsonResponse);
                            should.exist(jsonResponse.settings);

                            jsonResponse.settings.length.should.eql(1);

                            testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                            jsonResponse.settings[0].key.should.eql('lang');
                            jsonResponse.settings[0].value.should.eql('ua');
                        });
                });
        });

        it('Can edit newly introduced locale setting', function () {
            return request.get(localUtils.API.getApiQuery('settings/locale/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'locale', value: 'ge'}];

                    return jsonResponse;
                })
                .then((editedSetting) => {
                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(editedSetting)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(200)
                        .then(function (res) {
                            should.exist(res.headers['x-cache-invalidate']);
                            const jsonResponse = res.body;

                            should.exist(jsonResponse);
                            should.exist(jsonResponse.settings);

                            jsonResponse.settings.length.should.eql(1);

                            testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                            jsonResponse.settings[0].key.should.eql('locale');
                            jsonResponse.settings[0].value.should.eql('ge');
                        });
                });
        });

        it('Can read timezone', function (done) {
            request.get(localUtils.API.getApiQuery('settings/timezone/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('timezone');
                    done();
                });
        });

        it('Can read active_timezone', function (done) {
            request.get(localUtils.API.getApiQuery('settings/active_timezone/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('active_timezone');
                    done();
                });
        });

        it('Can read deprecated active_timezone', function (done) {
            request.get(localUtils.API.getApiQuery('settings/active_timezone/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('active_timezone');
                    done();
                });
        });

        it('Can read slack renamed&reformatted in v4', function (done) {
            request.get(localUtils.API.getApiQuery('settings/slack/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('slack');
                    done();
                });
        });

        it('Format of unsplash is boolean as introduced with v4', function (done) {
            request.get(localUtils.API.getApiQuery('settings/unsplash/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    const jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    jsonResponse.settings.length.should.eql(1);

                    testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
                    jsonResponse.settings[0].key.should.eql('unsplash');
                    JSON.parse(jsonResponse.settings[0].value).should.eql(true);

                    done();
                });
        });

        it('Can\'t read non existent setting', function (done) {
            request.get(localUtils.API.getApiQuery('settings/testsetting/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(404)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    should.not.exist(res.headers['x-cache-invalidate']);
                    const jsonResponse = res.body;
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.errors);
                    testUtils.API.checkResponseValue(jsonResponse.errors[0], [
                        'message',
                        'context',
                        'type',
                        'details',
                        'property',
                        'help',
                        'code',
                        'id'
                    ]);
                    done();
                });
        });

        it('Can\'t edit permalinks', function (done) {
            const settingToChange = {
                settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
            };

            request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(404)
                .end(function (err, res) {
                    if (err) {
                        return done(err);
                    }

                    done();
                });
        });

        it('Can edit only allowed labs keys', async function () {
            const settingToChange = {
                settings: [{
                    key: 'labs',
                    value: JSON.stringify({
                        activitypub: true,
                        gibberish: true
                    })
                }]
            };

            const res = await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200);

            const jsonResponse = res.body;

            should.exist(jsonResponse);
            should.exist(jsonResponse.settings);

            jsonResponse.settings.length.should.eql(1);
            testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
            jsonResponse.settings[0].key.should.eql('labs');

            const responseObj = JSON.parse(jsonResponse.settings[0].value);

            should.not.exist(responseObj.gibberish);
        });

        it('Can\'t edit non existent setting', function () {
            return request.get(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;
                    const newValue = 'new value';
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'testvalue', value: newValue}];

                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(jsonResponse)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(404)
                        .then(function ({body, headers}) {
                            jsonResponse = body;
                            should.not.exist(headers['x-cache-invalidate']);
                            should.exist(jsonResponse.errors);
                            testUtils.API.checkResponseValue(jsonResponse.errors[0], [
                                'message',
                                'context',
                                'type',
                                'details',
                                'property',
                                'help',
                                'code',
                                'id'
                            ]);
                        });
                });
        });

        it('Will transform "1"', function () {
            return request.get(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    const jsonResponse = res.body;

                    const settingToChange = {
                        settings: [
                            {
                                key: 'is_private',
                                value: '1'
                            }
                        ]
                    };

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);

                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(settingToChange)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(200)
                        .then(function ({body, headers}) {
                            const putBody = body;
                            headers['x-cache-invalidate'].should.eql('/*');
                            should.exist(putBody);

                            putBody.settings[0].key.should.eql('is_private');
                            putBody.settings[0].value.should.eql(true);

                            localUtils.API.checkResponse(putBody, 'settings');
                        });
                });
        });

        it('Can edit multiple setting along with a deprecated one from v4', async function () {
            const settingToChange = {
                settings: [
                    {
                        key: 'slack',
                        value: JSON.stringify([{
                            url: 'https://newurl.tld/slack',
                            username: 'New Slack Username'
                        }])
                    }, {
                        key: 'unsplash',
                        value: true
                    }, {
                        key: 'title',
                        value: 'New Value'
                    }
                ]
            };

            const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200);

            const putBody = body;
            headers['x-cache-invalidate'].should.eql('/*');
            should.exist(putBody);

            putBody.settings.length.should.equal(3);

            putBody.settings[0].key.should.eql('unsplash');
            should.equal(putBody.settings[0].value, true);

            putBody.settings[1].key.should.eql('title');
            should.equal(putBody.settings[1].value, 'New Value');

            putBody.settings[2].key.should.eql('slack');
            should.equal(putBody.settings[2].value, JSON.stringify([{
                url: 'https://newurl.tld/slack',
                username: 'New Slack Username'
            }]));

            localUtils.API.checkResponse(putBody, 'settings');
        });

        it('Can edit a setting introduced in v4', async function () {
            const settingToChange = {
                settings: [
                    {
                        key: 'slack_username',
                        value: 'can edit me'
                    }
                ]
            };

            const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200);

            const putBody = body;
            headers['x-cache-invalidate'].should.eql('/*');
            should.exist(putBody);

            putBody.settings.length.should.equal(1);

            localUtils.API.checkResponse(putBody, 'settings');
            putBody.settings[0].key.should.eql('slack_username');
            putBody.settings[0].value.should.eql('can edit me');
        });

        it('Can edit URLs without internal storage format leaking', async function () {
            const settingsToChange = {
                settings: [
                    {key: 'cover_image', value: `${config.get('url')}/content/images/cover_image.png`},
                    {key: 'logo', value: `${config.get('url')}/content/images/logo.png`},
                    {key: 'icon', value: `${config.get('url')}/content/images/icon.png`},
                    {key: 'portal_button_icon', value: `${config.get('url')}/content/images/portal_button_icon.png`},
                    {key: 'og_image', value: `${config.get('url')}/content/images/og_image.png`},
                    {key: 'twitter_image', value: `${config.get('url')}/content/images/twitter_image.png`}
                ]
            };

            const {body} = await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingsToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(200);

            const responseSettings = body.settings.reduce((acc, setting) => {
                acc[setting.key] = setting.value;
                return acc;
            }, {});

            responseSettings.should.have.property('cover_image', `${config.get('url')}/content/images/cover_image.png`);
            responseSettings.should.have.property('logo', `${config.get('url')}/content/images/logo.png`);
            responseSettings.should.have.property('icon', `${config.get('url')}/content/images/icon.png`);
            responseSettings.should.have.property('portal_button_icon', `${config.get('url')}/content/images/portal_button_icon.png`);
            responseSettings.should.have.property('og_image', `${config.get('url')}/content/images/og_image.png`);
            responseSettings.should.have.property('twitter_image', `${config.get('url')}/content/images/twitter_image.png`);

            const dbSettingsRows = await db.knex('settings')
                .select('key', 'value')
                .whereIn('key', ['cover_image', 'logo', 'icon', 'portal_button_icon', 'og_image', 'twitter_image']);

            const dbSettings = dbSettingsRows.reduce((acc, setting) => {
                acc[setting.key] = setting.value;
                return acc;
            }, {});

            dbSettings.should.have.property('cover_image', '__GHOST_URL__/content/images/cover_image.png');
            dbSettings.should.have.property('logo', '__GHOST_URL__/content/images/logo.png');
            dbSettings.should.have.property('icon', '__GHOST_URL__/content/images/icon.png');
            dbSettings.should.have.property('portal_button_icon', '__GHOST_URL__/content/images/portal_button_icon.png');
            dbSettings.should.have.property('og_image', '__GHOST_URL__/content/images/og_image.png');
            dbSettings.should.have.property('twitter_image', '__GHOST_URL__/content/images/twitter_image.png');
        });

        it('Can only send array values for keys defined with array type', async function () {
            const settingsToChange = {
                settings: [
                    {key: 'navigation', value: 'not an array'}
                ]
            };

            await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingsToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(422);
        });

        it('Cannot edit notifications key through API', async function () {
            const settingsToChange = {
                settings: [
                    {key: 'notifications', value: JSON.stringify(['do not touch me'])}
                ]
            };

            await request.put(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .send(settingsToChange)
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .expect(403);
        });
    });

    describe('As Admin', function () {
        before(async function () {
            await localUtils.startGhost();
            request = supertest.agent(config.get('url'));

            // create admin
            const admin = await testUtils.createUser({
                user: testUtils.DataGenerator.forKnex.createUser({email: 'admin+1@ghost.org'}),
                role: testUtils.DataGenerator.Content.roles[0].name
            });
            request.user = admin;
            // by default we login with the owner
            await localUtils.doAuth(request);
        });
    });

    describe('As Editor', function () {
        before(async function () {
            await localUtils.startGhost();
            request = supertest.agent(config.get('url'));
            // create editor
            request.user = await testUtils.createUser({
                user: testUtils.DataGenerator.forKnex.createUser({email: 'test+1@ghost.org'}),
                role: testUtils.DataGenerator.Content.roles[1].name
            });

            // by default we login with the owner
            await localUtils.doAuth(request);
        });

        it('should not be able to edit settings', function () {
            return request.get(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;

                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'visibility', value: 'public'}];

                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(jsonResponse)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(403)
                        .then(function ({body, headers}) {
                            jsonResponse = body;
                            should.not.exist(headers['x-cache-invalidate']);
                            should.exist(jsonResponse.errors);
                            testUtils.API.checkResponseValue(jsonResponse.errors[0], [
                                'message',
                                'context',
                                'type',
                                'details',
                                'property',
                                'help',
                                'code',
                                'id'
                            ]);
                        });
                });
        });
    });

    describe('As Author', function () {
        before(async function () {
            await localUtils.startGhost();
            request = supertest.agent(config.get('url'));

            // create author
            request.user = await testUtils.createUser({
                user: testUtils.DataGenerator.forKnex.createUser({email: 'test+2@ghost.org'}),
                role: testUtils.DataGenerator.Content.roles[2].name
            });

            // by default we login with the owner
            await localUtils.doAuth(request);
        });

        it('should not be able to edit settings', function () {
            return request.get(localUtils.API.getApiQuery('settings/'))
                .set('Origin', config.get('url'))
                .set('Accept', 'application/json')
                .expect('Content-Type', /json/)
                .expect('Cache-Control', testUtils.cacheRules.private)
                .then(function (res) {
                    let jsonResponse = res.body;
                    should.exist(jsonResponse);
                    should.exist(jsonResponse.settings);
                    jsonResponse.settings = [{key: 'visibility', value: 'public'}];

                    return request.put(localUtils.API.getApiQuery('settings/'))
                        .set('Origin', config.get('url'))
                        .send(jsonResponse)
                        .expect('Content-Type', /json/)
                        .expect('Cache-Control', testUtils.cacheRules.private)
                        .expect(403)
                        .then(function ({body, headers}) {
                            jsonResponse = body;
                            should.not.exist(headers['x-cache-invalidate']);
                            should.exist(jsonResponse.errors);
                            testUtils.API.checkResponseValue(jsonResponse.errors[0], [
                                'message',
                                'context',
                                'type',
                                'details',
                                'property',
                                'help',
                                'code',
                                'id'
                            ]);
                        });
                });
        });
    });
});

redpajama_set_name: RedPajamaGithub


A meditation on what was lost—and on what is worth preserving—in the movement away from analog music and culture.
Not for sale in the US, Canada, or the Philippines.
This could all make for dry reading, or be of little interest to a non-musician or non-sound engineer, but Krukowski's sprightly, clear, and above all, even-handed prose holds our attention.…Engaging, idiosyncratic, and highly enjoyable, The New Analog takes the changes since the analog era, and brilliantly uses them as a lens through which to examine the digital culture we all consume.
Although digital media have created new possibilities for music making and sharing, they have also given rise to new concerns. What do we lose in embracing the digital? Do streaming services discourage us from listening closely? In this book, musician Damon Krukowski uses the sound engineer's distinction between signal and noise to examine what we have lost as a technological culture, and to identify what is worth preserving.
Krukowski examines experiences from the production and consumption of music that have changed since the analog era—the disorientation of headphones, flattening of voice, silence of media, loudness of mastering, and manipulation of time—and employs them as a lens through which to consider digital culture. When music went digital through such streaming services as Napster and iTunes, it was reduced to signal only, stripped of its analog-era noise. But the analog and the digital need not exist in isolation from one another, Krukowski argue; noise can be as communicative as signal, conveying time, location, and space. The New Analog urges us to reconsider the role of noise in our increasingly digital lives, to appreciate its continued relevance, and to plug in without tuning out.


The company is small enough to make you feel like a valued employee.
Countless amounts of perks, including an amazing staff discount, really competitive wage, and an extensive online training programme. I really enjoy working here!
Whilst there is extensive training, with a part-time sales advisor role I have found that there isn't a lot of scope to move up to more senior job roles.
I applied online. The process took 5+ weeks. I interviewed at Hotel Chocolat (London, England).
All comms dealt with by HR, standard telephone interview, 121 with inexperienced area manager and SWOT presentation, work trial (handed out chocs for 15mins *pointless exercise*) and a final 121. No outcome after a week so emailed, praised all the way through but gave to internal candidate. No flexibility from them for interview even though I was currently in a job. Poorly handled in my opinion.
Glassdoor gives you an inside look at what it's like to work at Hotel Chocolat, including salaries, reviews, office photos, and more. This is the Hotel Chocolat company profile. All content is posted anonymously by employees working at Hotel Chocolat.


The Women's Ministry, who supports CTK through altar care, vestment cleaning, and altar supplies, is holding a pre-paid bake sale for some delicious sweets! The ladies will be in the Narthex collecting orders with payment after all Masses May 27-28 and June 3-4. Baked goods will be available for pick-up June 10-11 in the Christus Center. These goodies are great for summer picnics, birthdays, or just to treat yourself!
Choose from: Banana Pudding Cake, Strawberry Cheesecake, Hummingbird Bundt Cake, and Brownies (regular or sugar-free).


LifeTrust has simplified the process of helping your clients navigate the Life Settlement path.
Your life insurance policy is a valuable, trade-able asset that typically ranks toward the top in your portfolio under real estate or even a retirement account. Most individuals perceive life insurance as more of a liability and completely fail to realize the true economic value of what they have. A secondary market exists to benefit the policy holder and disrupt the monopsony the insurance carriers have created by providing a potentially larger payout compared to the carrier's surrender offer.
LifeTrust has over 200 sources from which to purchase Life Settlement policies, including life insurance agents, Life Settlement brokers, financial consultants and lawyers. LifeTrust over the years has worked hard to maintain an excellent relationship with its sources.
LifeTrust's position in the market and its relationship with its sources puts LifeTrust is in a unique position to provide its clients with exceptional market color, whether it be current pricing or the kind and type of policy that is in demand in the current Life Settlement market. LifeTrust can also provide its Funders a strong indication of the high bid for any policy in which they might have interest.
The Life Settlement market evolved from the Viatical Settlement market, which emerged in the 1980s and early 1990s in response to the AIDS epidemic. Terminally ill AIDS patients needed a way to pay for very expensive medication and treatment. At the same time, investors were looking for different investments with strong returns. They offered terminally ill policy holders lump sum payments in exchange for their policies.
Since the early days of Viaticals, the Life Settlement market has experienced tremendous growth, approximately $91 billion in transactions since 2002 due to seniors seeking alternative options for saving money and raising funds by selling their life insurance policy as opposed to letting it lapse. Over 80% of universal life policies eventually lapse, which means policy owners may not be capturing the full potential of their life insurance policies and the Life Settlement market.
LifeTrust has designed and built a custom program to track every policy seen; the current database consists of over 36,000 policies and over 23,000 lives. LifeTrust has a proven and seamless computerized system for policy purchases allowing seamless transactions including the Funder's approvals. The LifeTrust system tracks every policy from the time it is submitted for purchase until the purchase has closed, giving LifeTrust the ability to provide Funders up-to-the-minute status of every policy being purchased or under consideration.
LifeTrust follows strict guidelines to protect the insured's Privacy and Confidentiality, therefore LifeTrust's systems allows only approved personal to see the insured's information. All information is kept in secure onsite servers.


If you own a Samsung smartphone you probably can't wait for the Lollipop update to hit your device. Today we got some Hot News from our sources regarding the Android 5.0 Lollipop update for the Premium Galaxy A series, and the old-but-gold Galaxy Note 2.
Samsung is currently working on the Android 5.0.2 Lollipop update for its premium mid-range Galaxy A series. The update is expected to Roll-out to the Galaxy A7, A5 and A3 during this Quarter (Q2,2015). It will pack the Lollipop and Material Design goodies that currently existed in the Galaxy S5 and Note 4 updates.
Earlier last month, Samsung's old flagship Galaxy Note 2 has been officially confirmed to get the Android 5.0 Lollipop update. The update hasn't hit hit the Development status yet and will be coming later this year, So be patient and wait a little longer.
Samsung's latest Android build is 5.0.2 and it may start developing on the latest Android 5.1 or 5.1.1 build after Google fixes the memory leak issue which will affect all the Galaxy smartphones performance. Google promised to fix this issue ASAP.
We reported before that Samsung is working on Android 5.1 Lollipop update for its latest flagships (S6, S6 edge, Note 4.. etc) and that the Galaxy S6 and S6 edge will be the first to receive the update.
Today, our source reports that Samsung's Android 5.1 Lollipop firmwares for its latest flagships Galaxy S6 (SM-G920) and Galaxy S6 Edge (SM-G925) are currently In-development. We don't have a change-log for the update currently as it's still in early development stages, but we can say that it will bring few UI changes to the TouchWiz along with various security enhancements, bug fixes and performance improvements. The update is expected to start rolling-out by Early Q3,2015, However, this date is not yet confirmed.
In other hands, Samsung is preparing a similar Android 5.1 Lollipop update the Galaxy Note 4 and Galaxy Note Edge users with changes to the TouchWiz UI and new features too. Still, there is no reports if the Note 4 Lollipop 5.1 firmware has entered the development stages or not.
Follow Samsung's Official Lollipop Updates Page and Stay tuned for more info regarding Samsung's Android 5.1 Lollipop update.


Why does 7 not equal 8?
Tonight, Brian asked for pigs in the blanket for dinner. So, on my way home, I stopped to get some wieners and crescent rolls from the grocery store.
Hebrew National beef franks? Check!
As I'm walking down the aisle to get back to the front of the store, I look down and see the back of the Hebrew National packaging. Something peculiar strikes me. There are only 7 franks in the package. I look at the package of crescent rolls. 8. Hebrew National package again. 7. Looking at the hot dog buns on the next aisle over, they are in packages of 8.
Why would you make a package of hot dogs to always have 1 short of whatever bun/roll you pair with the dog? I don't understand.
Time to consult the Google.
Well, there you go. I didn't know that. The serious OCD in me cringes with the notion of having 1 extra bun/roll in a "set". When there are 8 buns or rolls, there should be 8 dogs, right? Right?!


Between Emirates Mall and LULU Hypermarket.
Next to Al Ansari Business Center.
TruCare Clinics is an exquisitely designed facility established at 2012 in very accessible area of Al-barsha1, Dubai-UAE we offer multiple specialties and an outstanding service through our group of highly experienced medical staff. We implement the latest cutting edge techniques, namely laser therapy, skin care and stat of art dentistry, blending relaxing elements of luxury and cure with the expertise and technology involved through in other word we have set up a comprehensive framework of possibilities adding to an overall experience that we look forward to providing you.
Timing: 10am to 7pm everyday except Friday.
10am to 10pm everyday except Friday.


text:
Streatham attack
Streatham attacker was released amid fears he felt terrorism 'justified'
Sudesh Amman was put under 24/7 armed surveillance within days of leaving prison
Streatham attack: latest updates
Police at the scene of the attack in Streatham. Photograph: Facundo Arrizabalaga/EPA
Vikram Dodd and Dan Sabbagh
Mon 3 Feb 2020 15.31 EST
First published on Mon 3 Feb 2020 09.00 EST
The Streatham attacker was released from a high security prison with investigators fearing he believed terrorist atrocities to be justified, the Guardian has learned.
Sudesh Amman, 20, was placed under full surveillance from a unit of 30 officers on the day of his release from Belmarsh prison and within days prompted such concern from counter-terrorism officials that those tailing him were ordered to be armed.
In prison he had declined to engage in programmes to manage his risk, and his behaviour during his sentence for terrorist offences following a 2018 conviction caused concern.
One source with knowledge of the Amman case said: "He was as much a problem when he came out of prison as when he went in."
Officers were following Amman on Sunday as he started stabbing people with a knife he stole in a shop, days after controversially being released from a sentence for terrorism offences.
Less than 10 seconds after he started his attack on Streatham High Road, armed surveillance officers who had been following him around the clock engaged him. He was shot dead less than 60 seconds after his attack began.
One man, who was initially considered to be in a life-threatening condition, is still in hospital.
The armed officers tracking Amman were part of a 24/7 surveillance operation, which is more expensive than keeping him in prison. He was released on 23 January, barely a week before he stabbed two people.
His release from jail was automatic at the halfway point of his sentence. It is understood that there was no mechanism for a risk assessment to be factored into whether he should be freed.
Powerless to stop him being released, prison and probation officials met with police to discuss the serious danger he was seen as posing. He was assessed as posing the highest risk, and they agreed to impose licence conditions on his release including the wearing of an electronic tag, a curfew, where he could go and restrictions on internet use.
Police and MI5 also committed extensive resources to place Amman under round the clock surveillance – itself rare and a sign of the danger he was thought to present. The case was considered among the highest priorities by investigators and analysts trying to thwart an atrocity.
On Monday evening police said that armed officers had been following Amman as he left a hostel at around 1.20pm on Sunday. Initial witness statements suggest that shortly after he entered a shop he stole a knife and then ran out as he was pursued by a member of staff.
As he ran from the shop, he removed packaging from the knife, and once outside attacked two members of public, the police said.
He is thought to have been wearing his fake suicide vest covered by a jacket, and thus out of view of the surveillance team following him.
Police have identified around 50 witnesses from whom they are gathering statements and are trawling through CCTV footage of the incident.
Tell us: have you been affected by the Streatham attack?
If you have been affected or have any information, we'd like to hear from you. You can get in touch by filling in the form below, anonymously if you wish or contact us via WhatsApp by clicking here or adding the contact +44(0)7867825056. Only the Guardian can see your contributions and one of our journalists may contact you to discuss further.
Share your experiences or news tips here
You do not need to use your full name
Where do you live? Optional
Town or area is fine
You can share a photo or video here Optional
We accept images and pdfs. Maximum total file size: 6MB
Can we publish your response?
Yes, entirely
Yes, but please keep me anonymous
Yes, but please contact me first
No, this is information only
Your contact details are helpful so we can contact you for more information. They will only be seen by the Guardian.
You can add any extra information here Optional
Share with the Guardian
Amman, from Harrow in north-west London, was jailed in December 2018 at the age of 18 after admitting to 13 counts of supporting Islamist terrorism and possessing and sharing Islamic State and al-Qaida propaganda in a family WhatsApp group and on social media. He was sentenced to three years and four months in jail, and served half that time in Belmarsh high security prison, taking in time he had already spent on remand.
He had come to police attention in April of that year for posting extremist material and was arrested a month later. At his trial it emerged he had expressed support for Isis and its then leader Abu Bakr al-Baghdadi and sent beheading videos to his girlfriend, advising her to kill her "kuffar" (unbelieving) parents. Amman also wrote about the desirability of conducting a terror attack: "If you can't make a bomb because family, friends or spies are watching or suspecting you, take a knife, molotov, sound bombs or a car at night and attack."
Mark Lucraft, the trial judge, wrote in his sentencing remarks: "In terms of mindset, your interest in Islamic extremism and Daesh appears to be more than just an immature fascination. It seems to me on the material here that you are someone with sincerely held and concerning ideological beliefs," before adding a warning that turned out to be prescient.
"You speak about preferring a knife attack to the use of bombs and ask about having a knife delivered to her [his girlfriend's] address".
Senior government officials believe the current law gives them no power to check if someone still poses a danger and to block their release at the halfway point of their sentence.
But soon after this decision, he was assessed to be even more dangerous than first thought and surveillance officers were ordered to be armed, multiple sources said.
The armed surveillance officers were carrying concealed pistols for their own personal protection and hence were able to stop Amman when he struck.
After his conviction, acting Met Commander Alexis Boon, head of the Metropolitan police's counter-terrorism command, said Amman had a "fascination with dying in the name of terrorism", as seen in a notepad recovered from his home. "Amman had scrawled his 'life goals' in the notepad and top of the list, above family activities, was dying a martyr and going to 'Jannah', the afterlife," she said.
Counter-terrorism policy
Prisons and probation
UK criminal justice

redpajama_set_name: RedPajamaCommonCrawl


text:
package com.facebook.buck.features.ocaml;

import com.facebook.buck.core.model.Flavor;
import com.facebook.buck.core.model.FlavorConvertible;
import com.facebook.buck.core.toolchain.Toolchain;
import com.facebook.buck.core.toolchain.toolprovider.ToolProvider;
import com.facebook.buck.core.util.immutables.BuckStyleImmutable;
import com.facebook.buck.cxx.toolchain.CompilerProvider;
import com.facebook.buck.cxx.toolchain.CxxPlatform;
import com.facebook.buck.cxx.toolchain.PreprocessorProvider;
import com.google.common.collect.ImmutableList;
import java.util.Optional;
import org.immutables.value.Value;

/** Abstracting the tooling/flags/libraries used to build OCaml rules. */
@Value.Immutable
@BuckStyleImmutable
interface AbstractOcamlPlatform extends Toolchain, FlavorConvertible {

  // TODO: For now, we rely on OCaml platforms having the same "name" as the C/C++ platforms they
  // wrap, due to having to lookup the OCaml platform in the C/C++ interfaces that OCaml rules
  // implement, into which only C/C++ platform objects are threaded.
  @Override
  default Flavor getFlavor() {
    return getCxxPlatform().getFlavor();
  }

  ToolProvider getOcamlCompiler();

  ToolProvider getOcamlDepTool();

  ToolProvider getYaccCompiler();

  ToolProvider getLexCompiler();

  Optional<String> getOcamlInteropIncludesDir();

  Optional<String> getWarningsFlags();

  ToolProvider getOcamlBytecodeCompiler();

  ToolProvider getOcamlDebug();

  CompilerProvider getCCompiler();

  PreprocessorProvider getCPreprocessor();

  CompilerProvider getCxxCompiler();

  /** @return all C/C++ platform flags used to preprocess, compiler, and assemble C sources. */
  ImmutableList<String> getCFlags();

  ImmutableList<String> getLdFlags();

  /** @return the {@link CxxPlatform} to use for C/C++ dependencies. */
  CxxPlatform getCxxPlatform();

  @Override
  default String getName() {
    throw new UnsupportedOperationException();
  }
}


If you are deciding on getting an armband tattoo you are in luck because there are so many options when it comes to this tattoo. Almost any idea that you have can be turned into an armband tattoo. Many people get tribal tattoos, Celtic tattoos and Polynesian tattoos in this area. So if you are thinking about getting a tribal, Celtic or Polynesian tattoo and are unsure of where you want to place it, consider getting this type of tattoo. Some people select an animal that they want to get tattooed and have it go around the arm, like a dragon tattoo which is a good armband tattoo option for men and women. A good armband tattoo idea for women is to get a ring of flowers around the arm. Colorful swirls and stars is another option that looks really nice. If you are a music lover you can have a tattoo of musical notes on a staff circling your arm. Armband tattoos can be thick or they can be skinny, they can be dark or they can be light. The possibilities are endless when it comes to getting an armband tattoo design for both men and women.
Armband tattoo designs are not known for their meanings. Most people believe that an armband tattoo is simply chosen for its aesthetic value. And this true for the most part. However, there are meanings behind particular armband tattoos that you may not be aware of and can add more depth to your decision, or could make you reconsider getting your chosen tattoo design. For example, the very common barbed wire tattoo and the solid black armband tattoo are actually considered dark and even scary symbols in Russia and Japan, respectively. These symbols were often worn by convicts or mafia-type individuals. The location of where the armband was placed, especially for the Russian barbed wire tattoo, had just as much meaning as the barbed wire tattoo itself. However, the tough history behind armband tattoos can enhance the bad-boy attractiveness of men. On a brighter note, in Hawaii any water-based or themed armband tattoo may represent aboriginal Hawaiian pride. While most armband tattoos are selected solely based on their design, it is also useful to know the meaning behind why certain tattoo designs are chosen for this part of the body.
Armband tattoos are definitely one of the coolest places to get a tattoo. For men especially, they emphasize the bicep which is a highly regarded part of the body in female eyes. This tattoo is a popular option for women as well. Now that you know more about the flexibility this tattoo provides for tattoo design ideas, where this tattoo is most commonly placed on the arm and the meaning behind certain armband tattoos for men, you can start coming up with designs of your own that are unique, interesting, and meaningful.


text:
Law Enforcement Rescue Loose Zebra In Tennessee
Associated Press Published: May 11, 2021
Ian Walton, Getty Images
COOKEVILLE, Tenn. (AP) — Law enforcement officials helped capture a loose zebra in middle Tennessee after it escaped from an exotic livestock auction.
According to news outlets, Cookeville Police Department and Putnam County Sherriff's office assisted Triple W employees capture the "agitated" zebra early Friday morning.
The zebra ran onto Highway 111, but was not hurt due to the lack of traffic.
Multiple methods were used to attempt to regain control of the animal.
At one point, two police officers made "unsuccessful attempts" to deploy stun guns to redirect or capture the animal. It took nearly three hours to corner and direct the zebra onto a transport trailer.
Snow Crushes Wheatland Wyoming Airplane Hangers
This row of hangars goes back many years. Some history was lost under a crush of snow.
March 21st, 2021. A record-breaking snowstorm had shut down most of Wyoming and was not yet done. Below is a gallery of photos as cleanup continues.
One of the small airports in Platte County, Wyoming is Phifer Airfield on Antelope Gap Road, east of Wheatland. Platte County has the Wheatland airport, along with one in Torrington and Guernsey. They were all shut down in the storm.


Medley Management Inc. MDLY, -1.96% today reported its financial results for its second quarter ended June 30, 2018 and will host an earnings conference call and audio webcast at 11:00 a.m. (Eastern Time) on Friday, August 10, 2018.
Total revenues were $15.2 million for the three months ended June 30, 2018 compared to $16.4 million for the same period in 2017. The decrease was due primarily to lower base management fees from our permanent capital vehicles, partly offset by an increase in other revenue and fees.
Total expenses from operations were $11.6 million for the three months ended June 30, 2018 compared to $8.5 million for the same period in 2017. The increase was due primarily to an increase in compensation expense and professional fees.
Total other expense, net was $5.8 million for the three months ended June 30, 2018 compared to $2.0 million for the same period in 2017. The increase was due primarily to $4.0 million of unrealized losses relating to one of our investments, partly offset by an increase of $0.2 million in dividend income. The $4.0 million of unrealized losses were allocated to non-controlling interests in consolidated subsidiaries which did not have any impact on the net income attributed to Medley Management Inc. and non-controlling interests in Medley LLC.
Net income attributable to Medley Management Inc. and non-controlling interests in Medley LLC was less than $0.1 million for the three months ended June 30, 2018 compared to $4.2 million for the same period in 2017. Medley Management Inc.'s net loss per share was $0.08 for the three months ended June 30, 2018 compared to net income per share of $0.06 for the same period in 2017.
Pre-Tax Core Net Income was $2.4 million for the three months ended June 30, 2018 compared to $5.2 million for the same period in 2017. Core Net Income Per Share was $0.05 for the three months ended June 30, 2018, compared to $0.10 for the same period in 2017. Core EBITDA was $5.4 million for the three months ended June 30, 2018 compared to $8.2 million for the same period in 2017.
Total revenues were $29.5 million for the six months ended June 30, 2018 compared to $30.4 million for the same period in 2017. The decrease was due primarily to lower base management fees from our permanent capital vehicles, partly offset by an increase in other revenue and fees.
Total expenses from operations were $24.5 million for the six months ended June 30, 2018 compared to $16.1 million for the same period in 2017. The increase was due primarily to an increase in compensation expense, professional fees and operating expenses of our consolidated fund.
Total other expense, net was $16.8 million for the six months ended June 30, 2018 compared to $3.4 million for the same period in 2017. The increase was due primarily to $13.6 million of unrealized losses relating to one of our investments, partly offset by an increase of $0.9 million in dividend income. Of the $13.6 million of unrealized losses, $10.1 million was allocated to non-controlling interests in consolidated subsidiaries which did not have any impact on the net income attributed to Medley Management Inc. and non-controlling interests in Medley LLC.
Net loss attributable to Medley Management Inc. and non-controlling interests in Medley LLC was $5.1 million for the six months ended June 30, 2018 compared to net income of $7.4 million for the same period in 2017. Medley Management Inc.'s net loss per share was $0.34 for the six months ended June 30, 2018 compared to net income per share of $0.14 for the same period in 2017.
Pre-Tax Core Net Income was $4.5 million for the six months ended June 30, 2018 compared to $10.4 million for the same period in 2017. Core Net Income Per Share was $0.10 for the six months ended June 30, 2018, compared to $0.19 for the same period in 2017. Core EBITDA was $10.4 million for the six months ended June 30, 2018 compared to $16.1 million for the same period in 2017.
We will host an earnings conference call and audio webcast at 11:00 a.m. (Eastern Time) on Friday, August 10, 2018 to discuss our second quarter financial results.
All interested parties may participate in the conference call by dialing (877) 524-5743 approximately 10-15 minutes prior to the call. International callers should dial (615) 247-0088. Participants should reference Medley Management Inc. and the conference ID of 4978749 when prompted. Following the call you may access a replay of the event via audio webcast. This conference call will be broadcast live over the Internet and can be accessed by all interested parties through the Company's website, http://www.mdly.com. To listen to the live call, please go to the Company's website at least 15 minutes prior to the start of the call to register and download any necessary audio software. For those who are not able to listen to the live broadcast, a replay will be available shortly after the call on the Company's website.
(1) Net Income Margin equals Net income attributable to Medley Management Inc. and non-controlling interests in Medley LLC divided by total revenue.
(2) Pre-Tax Core Net Income is calculated as Core Net Income before income taxes. Core Net Income reflects net income attributable to Medley Management Inc. and net income attributable to non-controlling interests in Medley LLC adjusted to exclude reimbursable expenses associated with the launch of funds, stock-based compensation associated with restricted stock units that were granted in connection with our IPO, other non-core items and the income tax expense associated with the foregoing adjustments. Please refer to the reconciliation of Core Net Income to Net income attributable to Medley Management Inc. and non-controlling interests in Medley LLC in Exhibit C for additional details.
(3) Core EBITDA is calculated as Core Net Income before interest expense, income taxes, depreciation and amortization. Please refer to the reconciliation of Core EBITDA to Net income attributable to Medley Management Inc. and non-controlling interests in Medley LLC in Exhibit C for additional details.
(4) Core Net Income Per Share is calculated as Core Net Income, adjusted for the income tax effect of assuming that all of our pre-tax earnings were subject to federal, state and local corporate income taxes, divided by Pro-Forma Weighted Average Shares Outstanding (as defined below). We assumed an effective corporate tax rate of 33.0% for 2018 and 43.0% for 2017. Please refer to the calculation of Core Net Income Per Share in Exhibit D for additional details.
(5) Core Net Income Margin equals Core Net Income Per Share divided by total revenue per share.
(6) The calculation of Pro-Forma Weighted Average Shares Outstanding assumes the conversion by the pre-IPO holders of up to 24,639,302 vested and unvested LLC Units for 24,639,302 shares of Class A common stock at the beginning of each period presented.
Total fee earning AUM decreased by $80 million, or 3% as of June 30, 2018 compared to total fee earning AUM as of March 31, 2018. The permanent capital vehicles' share of fee earning AUM decreased to 64% as of June 30, 2018 compared to 65% as of March 31, 2018.
Total fee earning AUM decreased by $198 million, or 6% as of June 30, 2018 compared to total fee earning AUM as of December 31, 2017. The permanent capital vehicles' share of fee earning AUM decreased to 64% as of June 30, 2018 compared to 66% as of December 31, 2017.
On August 7, 2018, the Company's Board of Directors declared a quarterly cash dividend of $0.20 per share of Class A common stock for the second quarter of 2018. The dividend will be paid on September 6, 2018 to stockholders of record as of August 23, 2018.
Medley LLC, the operating company of Medley Management Inc., has outstanding bonds which trade on the NYSE under the symbols MDLX, +0.38% and MDLQ, +0.00% Medley Capital Corporation is dual-listed on the New York Stock Exchange MCC, -0.30% and the Tel Aviv Stock Exchange (tase:MCC) and has outstanding bonds which trade on both the New York Stock Exchange under the symbols MCV, -0.27% MCX, -0.24% and the Tel Aviv Stock Exchange under the symbol (tase:MCC.B1).
Statements included herein may contain "forward-looking statements." Statements other than statements of historical facts included in this press release may constitute forward-looking statements and are not guarantees of future performance or results and involve a number of assumptions, risks and uncertainties, which change over time. Actual results may differ materially from those anticipated in any forward-looking statements as a result of a number of factors, including those described from time to time in filings by the Company with the Securities and Exchange Commission, including those described in the section "Risk Factors" in the Company's Annual Report on Form 10-K for the fiscal year ended December 31, 2017. Except as required by law, the Company undertakes no duty to update any forward-looking statement made herein. All forward-looking statements made herein speak only as of the date of this press release.
We make reference to certain non-GAAP financial measures in this press release. A reconciliation of these non-GAAP financial measures to the most directly comparable financial measures calculated and presented in accordance with U.S. GAAP is contained in the tables attached hereto.
Non-GAAP measures used by management include Pre-Tax Core Net Income, Core Net Income, Core EBITDA, Core Net Income Per Share and Core Net Income Margin. Management believes that these measures provide analysts, investors and management with helpful information regarding our underlying operating performance and our business, as they remove the impact of items management believes are not reflective of underlying operating performance. These non-GAAP measures are also used by management for planning purposes, including the preparation of internal budgets; and for evaluating the effectiveness of operational strategies. Additionally, we believe these non-GAAP measures provide another tool for investors to use in comparing our results with other companies in our industry, many of whom use similar non-GAAP measures. There are limitations associated with the use of non-GAAP financial measures as compared to the use of the most directly comparable U.S. GAAP financial measure and these measures supplement and should be considered in addition to and not in lieu of the results of operations discussed below. Furthermore, such measures may be inconsistent with measures presented by other companies.
This press release does not constitute an offer for any Medley fund.
Medley Management Inc.'s filings with the Securities and Exchange Commission, press releases, earnings releases and other financial information are available at www.mdly.com.
[(1) ] Medley Management Inc. is the parent company of Medley LLC and several registered investment advisors (collectively, "Medley"). Assets under management refers to assets of our funds, which represents the sum of the net asset value of such funds, the drawn and undrawn debt (at the fund level, including amounts subject to restrictions) and uncalled committed capital (including commitments to funds that have yet to commence their investment periods). Assets under management are as of June 30, 2018.
Exhibit A. Consolidated Statements of Operations of Medley Management Inc.
(1) Amounts relate to additional interest expense associated with the acceleration of amortization of debt issuance costs and discount relating to prepayments made on our Term Loan Facility as a result of the refinancing of our indebtedness from the issuance of Senior Unsecured Debt.
(2) For the three and six months ended June 30, 2018, other items consists of expenses related to non-core business development activities and other expenses.
(1) The calculation of Pro-Forma Weighted Average Shares Outstanding assumes the conversion by the pre-IPO holders of up to 24,639,302 vested and unvested LLC Units for 24,639,302 shares of Class A common stock at the beginning of each period presented.
(2) Represents a per share adjustment for income taxes assuming that all of our pre-tax earnings were subject to federal, state and local income taxes. We assumed an effective corporate tax rate of 33.0% for 2018 and 43.0% for 2017. The lower effective corporate tax rate was primarily the result of the enactment of the Tax Cuts and Jobs Act which reduced the federal corporate tax rate from 34.0% to 21.0% effective January 1, 2018.
(1) Adjustments to Net income attributable to Medley Management Inc. and non-controlling interests in Medley LLC to calculate Core Net Income are presented as a percentage of total revenue.
(2) Assumes that all of our pre-tax earnings, including adjustments above, are subject to federal, state and local income taxes. In determining corporate income taxes, we used a combined effective corporate tax rate of 33.0% for 2018 and 43.0% for 2017 and presented the calculation as a percentage of total revenue.
Exhibit F. Consolidated Balance Sheets of Medley Management Inc.


text:
Saul Marron
Hortensius
Saul Marron was born in Crieff, Scotland. He attended St Columba's High School, then went on to train at the Space in Dundee, Scotland; before moving to London to complete his degree with East 15 Acting School.
Saul's professional debut was in a new play by up-and-coming writer Tommy Kearney called "Madonna & Me" performed at the Off West End Jermyn Street Theatre. Since 2008 he has been a part of the international hit show "Sh*tfaced Shakespeare". After years of sell-out runs the show transferred to the U.S and since 2016 have been performing on the West End.
Saul's first TV role was for a BBC pilot "The London Affair", working with British director Nick Hatton-Jones. He went on to star alongside Benedict Cumberbatch and Michael Shannon in the 2017 feature film "The Current War". Currently he is playing James Mackenzie in the HBO period drama "Gentleman Jack" with Timothy West and Gemma Jones.
TRIVIA: Saul is also a skilled director; his latest short film "Chantelle: Psychic P.D - Night Division" is the first part of a planned series.


You've finally got your hands on the brand-new iPad mini with Retina display and now it's time to get it set up and ready for use. The excitement of buying a iPad has, over the years, been tempered by the fact that to get your device up and running you were first required to plug your tablet into a computer. Whether you stood in line for two weeks to get your hands on one, or preordered for it to be delivered to your house, the rush of delight was often held in check by the necessity to wait until iTunes told you that your shiny new tablet was ready.
The iPad mini with Retina display no longer needs to be physically connected to a computer first for it to work. As you might expect from Apple, the process is simple and quick; about the most technically difficult part is inserting the nano SIM card into the iPad mini (you need this only if you have a Wi-Fi + Cellular model). In typical Apple style there's even a SIM-card Replacement Tool included in the box to make this task even easier.
We'll assume that you have all the boring stuff such as your tablet price plan sorted out and have unboxed and inserted the SIM card into your new iPad. From here on in it's no more than a five-minute process. Wire-free setup is a breeze and all you have to do is follow the simple steps here to make sure that you and your tablet are ready to go as quickly as possible.
After that, there's a whole world of calling, texting, tweeting, internet browsing and taking photos, as well as all the apps to enjoy.
Step 1: Turn on - Press and hold the button on the top of the new iPad until you see the Apple logo on screen. After a few moments you'll see the above screen. Slide to your finger to the right to start.
Step 2: Pick your language - The first screen lets you choose what language to use on your iPad. Tap on the language you want, then move on to the next step.
Step 3: Where am I? - Select your country next. It's likely that the new iPad will have your location as the top choice. If it's not, tap on 'Show More…' Pick your location and then tap Next.
Step 4: Connect to Wi-Fi - If you have a wireless network at home or at work you can connect to it here. Tap on the wireless network name. Alternatively, choose 'Use Mobile Connection'.
Step 5: Location tracking - If you want your new iPad and apps to know where you are – handy for mapping and social-media tools, enable this by taping 'Enable Location Services' and then Next.
Step 6: Activation - If this is your first iPad, choose 'Set Up as New iPad' and click next. Otherwise you can use iCloud or iTunes to transfer the data from one iPad to another.
Step 7: Sign in - You need an Apple ID to make full use of your iPad. Click Sign In if you already have one, or 'Create a Free Apple ID' to go through the process of signing up with Apple. You're now good to go.
Step 8: Terms and conditions - Take time to read the terms and conditions. Click the blue Agree button to continue. You'll need to agree to each service (Siri, iCloud and so on) you want to use.


In this article we will share forex trading tutorials and binary options with breakout techniques.
The strategy that we will use is very simple but if implemented properly it is very able to get profit consistently.
Not a few traders who argue that most indicators move slowly so the signal shown is often too late.
Therefore on this occasion we will share trading tutorials without using indicators. But even though this tutorial is explained without an indicator, you can still combine with your favorite trading indicator.
For a breakout strategy without indicators, we will use the trendline and horizontal lines. To read the signal, it will be adjusted to the condition of the current trend of the trend.
Because there are 3 types of trend movements, the trading tutorial will be divided into 3.
when there is a downward movement, we attach the trend line to the cusp and point of the valley.
Its function is to show the signal of the next trend movement through the breakout of the trend line.
After one of the trend lines is broken, there is a possibility that price movements will reverse direction or continue the direction.
First, we attach the trend line to the cusp and point of the valley. Next wait for the moment when the candlestick movement penetrates one of the trendline lines.
And to find the trading signal open the position decreases or PUT / SELL, also the same is to wait for the moment of breakout.
Important: wait for the formation of 1 or 2 bearish candlesticks below the trendline (to anticipate the movement does not go down).
Sideways movement is usually a consolidation movement which after the consolidation period ends there will be a trend trend either up trend or down trend.
So that when there will be the beginning of the movement of this trend can be used to open open positions. The same way is to install two horizontal lines that refer to the vertex and point of the valley.
Important: wait for the formation of 1 or 2 bullish candlesticks above the line (to anticipate the movement not going up).
Important: wait for the formation of 1 or 2 bearish candlesticks below the line (to anticipate the movement does not go down).
Important: wait for the formation of 1 or 2 bullish candlesticks above the trendline (to anticipate the movement not going up).
For trading binary options with 1 minute expiration time, you can use a 15 second candlestick time interval.
called FalseOut or Fake Out. That is by waiting for 1 or 2 candlesticks to form after passing the trendline line (as written on each rule to open the above position).
Well, it's very simple and already isn't it? Basically, in analyzing or predicting the direction of price movements there are only two, namely whether the movement will continue the previous trend or will reverse the previous trend.
So we can find out the open position to be taken. Be sure to take a position based on trading analysis, don't just use filling.
Hopefully this article can provide benefits for those of you who are eager to learn forex trading and binary options and profit greetings.
0 Response to "Trading Forex and Binary Options with BreakOut Techniques"


Apply now. Four different apply now color ecommerce web buttons on a white background. vector file also available.
Four different apply now color ecommerce web buttons on a white background. vector file also available.
APPLY NOW sticker. Authentic design graphic stamp.
Apply now icon. Internet button on abstract background.


text:
No More Friends!
by davidrsmith | Jul 22, 2013 | Denial, Forgiveness, Friends, Manners, Men, Proverbs, Relationship, Rude, Wisdom
Ever met anybody like Earl? People like Earl forgo the wisdom in the Bible that talks about the benefit of having good, solid, godly friends. Nobody can...
The Real Price of Debt
by davidrsmith | Mar 31, 2013 | Debt, Greed, Habits, Joy, Master, Money, Peace, Problem, Proverbs, Slavery, Wisdom
As of February, 2013, the average credit card debt for Americans who carry a monthly balance was a whopping $15,257. This staggeringly high number means that many Americans have a big problem with debt. And the Bible says that debt is a very bad problem to...
The Lindsey Leap
by davidrsmith | Apr 14, 2012 | Arrogance, Athlete, Embarrassing, Lose, Mistake, Olympics, Pride, Proverbs, Regret, Show Off, Sports
Coming into the last jumps in the Snowboard Cross finals at the 2006 Winter Olympics, America's Lindsey Jacobellis was in such a commanding lead it seemed no one could keep her from winning the gold medal. No one, but herself, that is…. What should have...
Good Cop. Bad Cop. Same Cop.
by davidrsmith | Mar 18, 2012 | Addiction, Busted, Character, Criminal, Drugs, Exposed, Guilty, Hypocrisy, Integrity, Justice, Law, Police, Prison, Proverbs, Reputation, Surprise
For years, he served as a highly decorated law enforcement officer. President Clinton appointed him to the National Commission on Crime Prevention and Control in 1995 and he was honored as Sheriff of the Year in 2001. A jail in Colorado was even named after him!...
Money Missing, Integrity Found
by davidrsmith | Mar 18, 2012 | Accident, Character, Decision-Making, Honesty, Integrity, Money, Parents, Proverbs, Surprise, Temptation
Robert Adams had just finished his shift on a sweltering workday, and wanted a refreshing, ice-cold drink and a burrito before heading home. Finding himself a couple bucks short, he went to an ATM to make a quick withdrawal…where he found a bag containing over $17,000...
Attacked with a Dirty Diaper
by davidrsmith | Nov 15, 2010 | Anger, Impatient, Police, Proverbs, Self-Control, Traffic
Until now, I thought it was just monkeys who threw their poop at each other. State police in western Pennsylvania said Jessica Hollis, who resides in Mount Pleasant, did something very unpleasant in traffic: she threw a dirty diaper at another woman's car in a...
▼P


text:
<!DOCTYPE html>

	<meta charset="UTF-8" />
	<title>Documento Desktop</title>
	<meta name="description" content="Este es un documento adaptado para navegadores de escritorio." />

Documento Desktop

Regresar al inicio